aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/b43legacy/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43legacy/main.c')
-rw-r--r--drivers/net/wireless/b43legacy/main.c327
1 files changed, 178 insertions, 149 deletions
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 1f11e1670bf..1aec2146a2b 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -4,7 +4,7 @@
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
* Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
- * Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
+ * Copyright (c) 2005, 2006 Michael Buesch <m@bues.ch>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
* Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net>
@@ -31,11 +31,10 @@
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/if_arp.h>
#include <linux/etherdevice.h>
#include <linux/firmware.h>
-#include <linux/wireless.h>
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/skbuff.h>
@@ -61,7 +60,6 @@ MODULE_AUTHOR("Stefano Brivio");
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
MODULE_FIRMWARE("b43legacy/ucode2.fw");
MODULE_FIRMWARE("b43legacy/ucode4.fw");
@@ -724,9 +722,9 @@ void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags)
macctl &= ~B43legacy_MACCTL_GMODE;
if (flags & B43legacy_TMSLOW_GMODE) {
macctl |= B43legacy_MACCTL_GMODE;
- dev->phy.gmode = 1;
+ dev->phy.gmode = true;
} else
- dev->phy.gmode = 0;
+ dev->phy.gmode = false;
macctl |= B43legacy_MACCTL_IHR_ENABLED;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
}
@@ -813,7 +811,7 @@ static void b43legacy_calculate_link_quality(struct b43legacy_wldev *dev)
if (dev->noisecalc.calculation_running)
return;
dev->noisecalc.channel_at_start = dev->phy.channel;
- dev->noisecalc.calculation_running = 1;
+ dev->noisecalc.calculation_running = true;
dev->noisecalc.nr_samples = 0;
b43legacy_generate_noise_sample(dev);
@@ -875,7 +873,7 @@ static void handle_irq_noise(struct b43legacy_wldev *dev)
dev->stats.link_noise = average;
drop_calculation:
- dev->noisecalc.calculation_running = 0;
+ dev->noisecalc.calculation_running = false;
return;
}
generate_new:
@@ -891,7 +889,7 @@ static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev)
b43legacy_power_saving_ctl_bits(dev, -1, -1);
}
if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC))
- dev->dfq_valid = 1;
+ dev->dfq_valid = true;
}
static void handle_irq_atim_end(struct b43legacy_wldev *dev)
@@ -900,7 +898,7 @@ static void handle_irq_atim_end(struct b43legacy_wldev *dev)
b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
| B43legacy_MACCMD_DFQ_VALID);
- dev->dfq_valid = 0;
+ dev->dfq_valid = false;
}
}
@@ -973,14 +971,14 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
unsigned int i, len, variable_len;
const struct ieee80211_mgmt *bcn;
const u8 *ie;
- bool tim_found = 0;
+ bool tim_found = false;
unsigned int rate;
u16 ctl;
int antenna;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon);
bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data);
- len = min((size_t)dev->wl->current_beacon->len,
+ len = min_t(size_t, dev->wl->current_beacon->len,
0x200 - sizeof(struct b43legacy_plcp_hdr6));
rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value;
@@ -1021,7 +1019,7 @@ static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev,
/* A valid TIM is at least 4 bytes long. */
if (ie_len < 4)
break;
- tim_found = 1;
+ tim_found = true;
tim_position = sizeof(struct b43legacy_plcp_hdr6);
tim_position += offsetof(struct ieee80211_mgmt,
@@ -1058,6 +1056,7 @@ static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev,
b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif,
+ IEEE80211_BAND_2GHZ,
size,
rate);
/* Write PLCP in two parts and timing for packet transfer */
@@ -1123,6 +1122,7 @@ static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev,
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
dev->wl->vif,
+ IEEE80211_BAND_2GHZ,
*dest_size,
rate);
hdr->duration_id = dur;
@@ -1155,7 +1155,7 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
b43legacy_write_probe_resp_plcp(dev, 0x350, size,
&b43legacy_b_ratetable[3]);
- size = min((size_t)size,
+ size = min_t(size_t, size,
0x200 - sizeof(struct b43legacy_plcp_hdr6));
b43legacy_write_template_common(dev, probe_resp_data,
size, ram_offset,
@@ -1174,7 +1174,7 @@ static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev)
* but we don't use that feature anyway. */
b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
&__b43legacy_ratetable[3]);
- wl->beacon0_uploaded = 1;
+ wl->beacon0_uploaded = true;
}
static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev)
@@ -1184,7 +1184,7 @@ static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev)
if (wl->beacon1_uploaded)
return;
b43legacy_write_beacon_template(dev, 0x468, 0x1A);
- wl->beacon1_uploaded = 1;
+ wl->beacon1_uploaded = true;
}
static void handle_irq_beacon(struct b43legacy_wldev *dev)
@@ -1214,7 +1214,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
if (unlikely(wl->beacon_templates_virgin)) {
/* We never uploaded a beacon before.
* Upload both templates now, but only mark one valid. */
- wl->beacon_templates_virgin = 0;
+ wl->beacon_templates_virgin = false;
b43legacy_upload_beacon0(dev);
b43legacy_upload_beacon1(dev);
cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
@@ -1277,8 +1277,8 @@ static void b43legacy_update_templates(struct b43legacy_wl *wl)
if (wl->current_beacon)
dev_kfree_skb_any(wl->current_beacon);
wl->current_beacon = beacon;
- wl->beacon0_uploaded = 0;
- wl->beacon1_uploaded = 0;
+ wl->beacon0_uploaded = false;
+ wl->beacon1_uploaded = false;
ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger);
}
@@ -1508,14 +1508,22 @@ static void b43legacy_release_firmware(struct b43legacy_wldev *dev)
static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
{
- b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/"
+ b43legacyerr(wl, "You must go to http://wireless.kernel.org/en/users/"
"Drivers/b43#devicefirmware "
"and download the correct firmware (version 3).\n");
}
+static void b43legacy_fw_cb(const struct firmware *firmware, void *context)
+{
+ struct b43legacy_wldev *dev = context;
+
+ dev->fwp = firmware;
+ complete(&dev->fw_load_complete);
+}
+
static int do_request_fw(struct b43legacy_wldev *dev,
const char *name,
- const struct firmware **fw)
+ const struct firmware **fw, bool async)
{
char path[sizeof(modparam_fwpostfix) + 32];
struct b43legacy_fw_header *hdr;
@@ -1528,7 +1536,24 @@ static int do_request_fw(struct b43legacy_wldev *dev,
snprintf(path, ARRAY_SIZE(path),
"b43legacy%s/%s.fw",
modparam_fwpostfix, name);
- err = request_firmware(fw, path, dev->dev->dev);
+ b43legacyinfo(dev->wl, "Loading firmware %s\n", path);
+ if (async) {
+ init_completion(&dev->fw_load_complete);
+ err = request_firmware_nowait(THIS_MODULE, 1, path,
+ dev->dev->dev, GFP_KERNEL,
+ dev, b43legacy_fw_cb);
+ if (err) {
+ b43legacyerr(dev->wl, "Unable to load firmware\n");
+ return err;
+ }
+ /* stall here until fw ready */
+ wait_for_completion(&dev->fw_load_complete);
+ if (!dev->fwp)
+ err = -EINVAL;
+ *fw = dev->fwp;
+ } else {
+ err = request_firmware(fw, path, dev->dev->dev);
+ }
if (err) {
b43legacyerr(dev->wl, "Firmware file \"%s\" not found "
"or load failed.\n", path);
@@ -1559,15 +1584,20 @@ err_format:
return -EPROTO;
}
-static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
+static int b43legacy_one_core_attach(struct ssb_device *dev,
+ struct b43legacy_wl *wl);
+static void b43legacy_one_core_detach(struct ssb_device *dev);
+
+static void b43legacy_request_firmware(struct work_struct *work)
{
+ struct b43legacy_wl *wl = container_of(work,
+ struct b43legacy_wl, firmware_load);
+ struct b43legacy_wldev *dev = wl->current_dev;
struct b43legacy_firmware *fw = &dev->fw;
const u8 rev = dev->dev->id.revision;
const char *filename;
- u32 tmshigh;
int err;
- tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);
if (!fw->ucode) {
if (rev == 2)
filename = "ucode2";
@@ -1575,7 +1605,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
filename = "ucode4";
else
filename = "ucode5";
- err = do_request_fw(dev, filename, &fw->ucode);
+ err = do_request_fw(dev, filename, &fw->ucode, true);
if (err)
goto err_load;
}
@@ -1584,7 +1614,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
filename = "pcm4";
else
filename = "pcm5";
- err = do_request_fw(dev, filename, &fw->pcm);
+ err = do_request_fw(dev, filename, &fw->pcm, false);
if (err)
goto err_load;
}
@@ -1602,7 +1632,7 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
default:
goto err_no_initvals;
}
- err = do_request_fw(dev, filename, &fw->initvals);
+ err = do_request_fw(dev, filename, &fw->initvals, false);
if (err)
goto err_load;
}
@@ -1622,12 +1652,18 @@ static int b43legacy_request_firmware(struct b43legacy_wldev *dev)
default:
goto err_no_initvals;
}
- err = do_request_fw(dev, filename, &fw->initvals_band);
+ err = do_request_fw(dev, filename, &fw->initvals_band, false);
if (err)
goto err_load;
}
+ err = ieee80211_register_hw(wl->hw);
+ if (err)
+ goto err_one_core_detach;
+ return;
- return 0;
+err_one_core_detach:
+ b43legacy_one_core_detach(dev->dev);
+ goto error;
err_load:
b43legacy_print_fw_helptext(dev->wl);
@@ -1641,7 +1677,7 @@ err_no_initvals:
error:
b43legacy_release_firmware(dev);
- return err;
+ return;
}
static int b43legacy_upload_microcode(struct b43legacy_wldev *dev)
@@ -1909,7 +1945,7 @@ static int b43legacy_gpio_init(struct b43legacy_wldev *dev)
return 0;
ssb_write32(gpiodev, B43legacy_GPIO_CONTROL,
(ssb_read32(gpiodev, B43legacy_GPIO_CONTROL)
- & mask) | set);
+ & ~mask) | set);
return 0;
}
@@ -2155,9 +2191,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
macctl |= B43legacy_MACCTL_INFRA;
b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
- err = b43legacy_request_firmware(dev);
- if (err)
- goto out;
err = b43legacy_upload_microcode(dev);
if (err)
goto out; /* firmware is released later */
@@ -2234,7 +2267,7 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00);
value32 = ssb_read32(dev->dev, SSB_TMSLOW);
- value32 |= 0x00100000;
+ value32 |= B43legacy_TMSLOW_MACPHYCLKEN;
ssb_write32(dev->dev, SSB_TMSLOW, value32);
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
@@ -2442,34 +2475,69 @@ static int b43legacy_rng_init(struct b43legacy_wl *wl)
return err;
}
-static int b43legacy_op_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb)
+static void b43legacy_tx_work(struct work_struct *work)
+{
+ struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl,
+ tx_work);
+ struct b43legacy_wldev *dev;
+ struct sk_buff *skb;
+ int queue_num;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev || b43legacy_status(dev) < B43legacy_STAT_STARTED)) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+
+ for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+ while (skb_queue_len(&wl->tx_queue[queue_num])) {
+ skb = skb_dequeue(&wl->tx_queue[queue_num]);
+ if (b43legacy_using_pio(dev))
+ err = b43legacy_pio_tx(dev, skb);
+ else
+ err = b43legacy_dma_tx(dev, skb);
+ if (err == -ENOSPC) {
+ wl->tx_queue_stopped[queue_num] = 1;
+ ieee80211_stop_queue(wl->hw, queue_num);
+ skb_queue_head(&wl->tx_queue[queue_num], skb);
+ break;
+ }
+ if (unlikely(err))
+ dev_kfree_skb(skb); /* Drop it */
+ err = 0;
+ }
+
+ if (!err)
+ wl->tx_queue_stopped[queue_num] = 0;
+ }
+
+ mutex_unlock(&wl->mutex);
+}
+
+static void b43legacy_op_tx(struct ieee80211_hw *hw,
+ struct ieee80211_tx_control *control,
+ struct sk_buff *skb)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- int err = -ENODEV;
- unsigned long flags;
- if (unlikely(!dev))
- goto out;
- if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
- goto out;
- /* DMA-TX is done without a global lock. */
- if (b43legacy_using_pio(dev)) {
- spin_lock_irqsave(&wl->irq_lock, flags);
- err = b43legacy_pio_tx(dev, skb);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- } else
- err = b43legacy_dma_tx(dev, skb);
-out:
- if (unlikely(err)) {
- /* Drop the packet. */
+ if (unlikely(skb->len < 2 + 2 + 6)) {
+ /* Too short, this can't be a valid frame. */
dev_kfree_skb_any(skb);
+ return;
}
- return NETDEV_TX_OK;
+ B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags);
+
+ skb_queue_tail(&wl->tx_queue[skb->queue_mapping], skb);
+ if (!wl->tx_queue_stopped[skb->queue_mapping])
+ ieee80211_queue_work(wl->hw, &wl->tx_work);
+ else
+ ieee80211_stop_queue(wl->hw, skb->queue_mapping);
}
-static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
return 0;
@@ -2512,7 +2580,7 @@ static int find_wldev_for_phymode(struct b43legacy_wl *wl,
if (d->phy.possible_phymodes & phymode) {
/* Ok, this device supports the PHY-mode.
* Set the gmode bit. */
- *gmode = 1;
+ *gmode = true;
*dev = d;
return 0;
@@ -2548,7 +2616,7 @@ static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
struct b43legacy_wldev *uninitialized_var(up_dev);
struct b43legacy_wldev *down_dev;
int err;
- bool gmode = 0;
+ bool gmode = false;
int prev_status;
err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode);
@@ -2591,7 +2659,7 @@ static int b43legacy_switch_phymode(struct b43legacy_wl *wl,
if (prev_status >= B43legacy_STAT_STARTED) {
err = b43legacy_wireless_core_start(up_dev);
if (err) {
- b43legacyerr(wl, "Fatal: Coult not start device for "
+ b43legacyerr(wl, "Fatal: Could not start device for "
"newly selected %s-PHY mode\n",
phymode_to_string(new_mode));
b43legacy_wireless_core_exit(up_dev);
@@ -2635,11 +2703,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
unsigned long flags;
unsigned int new_phymode = 0xFFFF;
int antenna_tx;
- int antenna_rx;
int err = 0;
antenna_tx = B43legacy_ANTENNA_DEFAULT;
- antenna_rx = B43legacy_ANTENNA_DEFAULT;
mutex_lock(&wl->mutex);
dev = wl->current_dev;
@@ -2654,7 +2720,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
goto out_unlock_mutex;
/* Switch the PHY mode (if necessary). */
- switch (conf->channel->band) {
+ switch (conf->chandef.chan->band) {
case IEEE80211_BAND_2GHZ:
if (phy->type == B43legacy_PHYTYPE_B)
new_phymode = B43legacy_PHYMODE_B;
@@ -2682,8 +2748,9 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
/* Switch to the requested channel.
* The firmware takes care of races with the TX handler. */
- if (conf->channel->hw_value != phy->channel)
- b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0);
+ if (conf->chandef.chan->hw_value != phy->channel)
+ b43legacy_radio_selectchannel(dev, conf->chandef.chan->hw_value,
+ 0);
dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_MONITOR);
@@ -2776,14 +2843,12 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
- struct b43legacy_phy *phy;
unsigned long flags;
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(wl->vif != vif);
dev = wl->current_dev;
- phy = &dev->phy;
/* Disable IRQs while reconfiguring the device.
* This makes it possible to drop the spinlock throughout
@@ -2885,6 +2950,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
{
struct b43legacy_wl *wl = dev->wl;
unsigned long flags;
+ int queue_num;
if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
return;
@@ -2904,11 +2970,16 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
/* Must unlock as it would otherwise deadlock. No races here.
* Cancel the possibly running self-rearming periodic work. */
cancel_delayed_work_sync(&dev->periodic_work);
+ cancel_work_sync(&wl->tx_work);
mutex_lock(&wl->mutex);
- ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
+ /* Drain all TX queues. */
+ for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+ while (skb_queue_len(&wl->tx_queue[queue_num]))
+ dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num]));
+ }
- b43legacy_mac_suspend(dev);
+b43legacy_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43legacydbg(wl, "Wireless interface stopped\n");
}
@@ -2975,7 +3046,7 @@ static int b43legacy_phy_versioning(struct b43legacy_wldev *dev)
break;
default:
unsupported = 1;
- };
+ }
if (unsupported) {
b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY "
"(Analog %u, Type %u, Revision %u)\n",
@@ -3050,12 +3121,12 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
/* Assume the radio is enabled. If it's not enabled, the state will
* immediately get fixed on the first periodic work run. */
- dev->radio_hw_enable = 1;
+ dev->radio_hw_enable = true;
phy->savedpctlreg = 0xFFFF;
- phy->aci_enable = 0;
- phy->aci_wlan_automatic = 0;
- phy->aci_hw_rssi = 0;
+ phy->aci_enable = false;
+ phy->aci_wlan_automatic = false;
+ phy->aci_hw_rssi = false;
lo = phy->_lo_pairs;
if (lo)
@@ -3087,7 +3158,7 @@ static void setup_struct_phy_for_init(struct b43legacy_wldev *dev,
static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
{
/* Flags */
- dev->dfq_valid = 0;
+ dev->dfq_valid = false;
/* Stats */
memset(&dev->stats, 0, sizeof(dev->stats));
@@ -3105,37 +3176,6 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
memset(&dev->noisecalc, 0, sizeof(dev->noisecalc));
}
-static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev)
-{
-#ifdef CONFIG_SSB_DRIVER_PCICORE
- struct ssb_bus *bus = dev->dev->bus;
- u32 tmp;
-
- if (bus->pcicore.dev &&
- bus->pcicore.dev->id.coreid == SSB_DEV_PCI &&
- bus->pcicore.dev->id.revision <= 5) {
- /* IMCFGLO timeouts workaround. */
- tmp = ssb_read32(dev->dev, SSB_IMCFGLO);
- switch (bus->bustype) {
- case SSB_BUSTYPE_PCI:
- case SSB_BUSTYPE_PCMCIA:
- tmp &= ~SSB_IMCFGLO_REQTO;
- tmp &= ~SSB_IMCFGLO_SERTO;
- tmp |= 0x32;
- break;
- case SSB_BUSTYPE_SSB:
- tmp &= ~SSB_IMCFGLO_REQTO;
- tmp &= ~SSB_IMCFGLO_SERTO;
- tmp |= 0x53;
- break;
- default:
- break;
- }
- ssb_write32(dev->dev, SSB_IMCFGLO, tmp);
- }
-#endif /* CONFIG_SSB_DRIVER_PCICORE */
-}
-
static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev,
bool idle) {
u16 pu_delay = 1050;
@@ -3224,9 +3264,9 @@ static void prepare_phy_data_for_init(struct b43legacy_wldev *dev)
phy->lofcal = 0xFFFF;
phy->initval = 0xFFFF;
- phy->aci_enable = 0;
- phy->aci_wlan_automatic = 0;
- phy->aci_hw_rssi = 0;
+ phy->aci_enable = false;
+ phy->aci_wlan_automatic = false;
+ phy->aci_hw_rssi = false;
phy->antenna_diversity = 0xFFFF;
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
@@ -3279,7 +3319,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
/* Enable IRQ routing to this device. */
ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev);
- b43legacy_imcfglo_timeouts_workaround(dev);
prepare_phy_data_for_init(dev);
b43legacy_phy_calibrate(dev);
err = b43legacy_chip_init(dev);
@@ -3393,7 +3432,7 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
b43legacydbg(wl, "Adding Interface type %d\n", vif->type);
dev = wl->current_dev;
- wl->operating = 1;
+ wl->operating = true;
wl->vif = vif;
wl->if_type = vif->type;
memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
@@ -3427,7 +3466,7 @@ static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
B43legacy_WARN_ON(wl->vif != vif);
wl->vif = NULL;
- wl->operating = 0;
+ wl->operating = false;
spin_lock_irqsave(&wl->irq_lock, flags);
b43legacy_adjust_opmode(dev);
@@ -3451,10 +3490,10 @@ static int b43legacy_op_start(struct ieee80211_hw *hw)
memset(wl->bssid, 0, ETH_ALEN);
memset(wl->mac_addr, 0, ETH_ALEN);
wl->filter_flags = 0;
- wl->beacon0_uploaded = 0;
- wl->beacon1_uploaded = 0;
- wl->beacon_templates_virgin = 1;
- wl->radio_enabled = 1;
+ wl->beacon0_uploaded = false;
+ wl->beacon1_uploaded = false;
+ wl->beacon_templates_virgin = true;
+ wl->radio_enabled = true;
mutex_lock(&wl->mutex);
@@ -3493,7 +3532,7 @@ static void b43legacy_op_stop(struct ieee80211_hw *hw)
if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
b43legacy_wireless_core_stop(dev);
b43legacy_wireless_core_exit(dev);
- wl->radio_enabled = 0;
+ wl->radio_enabled = false;
mutex_unlock(&wl->mutex);
}
@@ -3520,7 +3559,7 @@ static int b43legacy_op_get_survey(struct ieee80211_hw *hw, int idx,
if (idx != 0)
return -ENOENT;
- survey->channel = conf->channel;
+ survey->channel = conf->chandef.chan;
survey->filled = SURVEY_INFO_NOISE_DBM;
survey->noise = dev->stats.link_noise;
@@ -3652,7 +3691,7 @@ static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev)
have_bphy = 1;
dev->phy.gmode = (have_gphy || have_bphy);
- dev->phy.radio_on = 1;
+ dev->phy.radio_on = true;
tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
@@ -3729,26 +3768,8 @@ static int b43legacy_one_core_attach(struct ssb_device *dev,
struct b43legacy_wl *wl)
{
struct b43legacy_wldev *wldev;
- struct pci_dev *pdev;
int err = -ENOMEM;
- if (!list_empty(&wl->devlist)) {
- /* We are not the first core on this chip. */
- pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL;
- /* Only special chips support more than one wireless
- * core, although some of the other chips have more than
- * one wireless core as well. Check for this and
- * bail out early.
- */
- if (!pdev ||
- ((pdev->device != 0x4321) &&
- (pdev->device != 0x4313) &&
- (pdev->device != 0x431A))) {
- b43legacydbg(wl, "Ignoring unconnected 802.11 core\n");
- return -ENODEV;
- }
- }
-
wldev = kzalloc(sizeof(*wldev), GFP_KERNEL);
if (!wldev)
goto out;
@@ -3761,7 +3782,7 @@ static int b43legacy_one_core_attach(struct ssb_device *dev,
(void (*)(unsigned long))b43legacy_interrupt_tasklet,
(unsigned long)wldev);
if (modparam_pio)
- wldev->__using_pio = 1;
+ wldev->__using_pio = true;
INIT_LIST_HEAD(&wldev->list);
err = b43legacy_wireless_core_attach(wldev);
@@ -3785,7 +3806,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus)
/* boardflags workarounds */
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
bus->boardinfo.type == 0x4E &&
- bus->boardinfo.rev > 0x40)
+ bus->sprom.board_rev > 0x40)
bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
}
@@ -3804,6 +3825,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
struct ieee80211_hw *hw;
struct b43legacy_wl *wl;
int err = -ENOMEM;
+ int queue_num;
b43legacy_sprom_fixup(dev->bus);
@@ -3838,9 +3860,17 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
mutex_init(&wl->mutex);
INIT_LIST_HEAD(&wl->devlist);
INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
+ INIT_WORK(&wl->tx_work, b43legacy_tx_work);
+
+ /* Initialize queues and flags. */
+ for (queue_num = 0; queue_num < B43legacy_QOS_QUEUE_NUM; queue_num++) {
+ skb_queue_head_init(&wl->tx_queue[queue_num]);
+ wl->tx_queue_stopped[queue_num] = 0;
+ }
ssb_set_devtypedata(dev, wl);
- b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id);
+ b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n",
+ dev->bus->chip_id, dev->id.revision);
err = 0;
out:
return err;
@@ -3867,17 +3897,13 @@ static int b43legacy_probe(struct ssb_device *dev,
if (err)
goto err_wireless_exit;
- if (first) {
- err = ieee80211_register_hw(wl->hw);
- if (err)
- goto err_one_core_detach;
- }
+ /* setup and start work to load firmware */
+ INIT_WORK(&wl->firmware_load, b43legacy_request_firmware);
+ schedule_work(&wl->firmware_load);
out:
return err;
-err_one_core_detach:
- b43legacy_one_core_detach(dev);
err_wireless_exit:
if (first)
b43legacy_wireless_exit(dev, wl);
@@ -3892,8 +3918,12 @@ static void b43legacy_remove(struct ssb_device *dev)
/* We must cancel any work here before unregistering from ieee80211,
* as the ieee80211 unreg will destroy the workqueue. */
cancel_work_sync(&wldev->restart_work);
+ cancel_work_sync(&wl->firmware_load);
+ complete(&wldev->fw_load_complete);
B43legacy_WARN_ON(!wl);
+ if (!wldev->fw.ucode)
+ return; /* NULL if fw never loaded */
if (wl->current_dev == wldev)
ieee80211_unregister_hw(wl->hw);
@@ -4002,8 +4032,7 @@ static void b43legacy_print_driverinfo(void)
feat_dma = "D";
#endif
printk(KERN_INFO "Broadcom 43xx-legacy driver loaded "
- "[ Features: %s%s%s%s, Firmware-ID: "
- B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
+ "[ Features: %s%s%s%s ]\n",
feat_pci, feat_leds, feat_pio, feat_dma);
}