* Broadcom B43legacy wireless driver
*
* Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>
- * Copyright (c) 2005 Stefano Brivio <st3@riseup.net>
+ * Copyright (c) 2005-2008 Stefano Brivio <stefano.brivio@polimi.it>
* Copyright (c) 2005, 2006 Michael Buesch <mb@bu3sch.de>
* Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
* Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
MODULE_AUTHOR("Michael Buesch");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID);
+
#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO)
static int modparam_pio;
module_param_named(pio, modparam_pio, int, 0444);
MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames"
" Preemption");
-static int modparam_short_retry = B43legacy_DEFAULT_SHORT_RETRY_LIMIT;
-module_param_named(short_retry, modparam_short_retry, int, 0444);
-MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)");
-
-static int modparam_long_retry = B43legacy_DEFAULT_LONG_RETRY_LIMIT;
-module_param_named(long_retry, modparam_long_retry, int, 0444);
-MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
-
static char modparam_fwpostfix[16];
module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load.");
B43legacy_WARN_ON(offset % 4 != 0);
- status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
- if (status & B43legacy_SBF_XFER_REG_BYTESWAP)
+ status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ if (status & B43legacy_MACCTL_BE)
val = swab32(val);
b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset);
{
u32 status;
- status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
- status |= B43legacy_SBF_TIME_UPDATE;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+ status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ status |= B43legacy_MACCTL_TBTTHOLD;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
mmiowb();
}
{
u32 status;
- status = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
- status &= ~B43legacy_SBF_TIME_UPDATE;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, status);
+ status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ status &= ~B43legacy_MACCTL_TBTTHOLD;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status);
}
static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf)
b43legacy_ram_write(dev, i * 4, buffer[i]);
/* dummy read follows */
- b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+ b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
b43legacy_write16(dev, 0x0568, 0x0000);
b43legacy_write16(dev, 0x07C0, 0x0000);
static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev)
{
b43legacy_jssi_write(dev, 0x7F7F7F7F);
- b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
b43legacy_read32(dev,
- B43legacy_MMIO_STATUS2_BITFIELD)
+ B43legacy_MMIO_MACCMD)
| (1 << 4));
B43legacy_WARN_ON(dev->noisecalc.channel_at_start !=
dev->phy.channel);
{
if (!dev->reg124_set_0x4) /*FIXME rename this variable*/
return;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
- b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD)
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
+ b43legacy_read32(dev, B43legacy_MMIO_MACCMD)
| 0x4);
}
plcp.data = 0;
b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ dev->wl->vif,
size,
B43legacy_RATE_TO_100KBPS(rate));
/* Write PLCP in two parts and timing for packet transfer */
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP);
dur = ieee80211_generic_frame_duration(dev->wl->hw,
- dev->wl->if_id,
+ dev->wl->vif,
*dest_size,
B43legacy_RATE_TO_100KBPS(rate));
hdr->duration_id = dur;
b43legacy_write_probe_resp_template(dev, 0x268, 0x4A,
B43legacy_CCK_RATE_11MB);
- status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+ status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
status |= 0x03;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD, status);
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD, status);
}
static void b43legacy_refresh_templates(struct b43legacy_wldev *dev,
return;
dev->irq_savedstate &= ~B43legacy_IRQ_BEACON;
- status = b43legacy_read32(dev, B43legacy_MMIO_STATUS2_BITFIELD);
+ status = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
if (!dev->cached_beacon || ((status & 0x1) && (status & 0x2))) {
/* ACK beacon IRQ. */
b43legacy_write_beacon_template(dev, 0x68, 0x18,
B43legacy_CCK_RATE_1MB);
status |= 0x1;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
status);
}
if (!(status & 0x2)) {
b43legacy_write_beacon_template(dev, 0x468, 0x1A,
B43legacy_CCK_RATE_1MB);
status |= 0x2;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS2_BITFIELD,
+ b43legacy_write32(dev, B43legacy_MMIO_MACCMD,
status);
}
}
if (unlikely(reason & B43legacy_IRQ_MAC_TXERR))
b43legacyerr(dev->wl, "MAC transmission error\n");
- if (unlikely(reason & B43legacy_IRQ_PHY_TXERR))
+ if (unlikely(reason & B43legacy_IRQ_PHY_TXERR)) {
b43legacyerr(dev->wl, "PHY transmission error\n");
+ rmb();
+ if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) {
+ b43legacyerr(dev->wl, "Too many PHY TX errors, "
+ "restarting the controller\n");
+ b43legacy_controller_restart(dev, "PHY TX errors");
+ }
+ }
if (unlikely(merged_dma_reason & (B43legacy_DMAIRQ_FATALMASK |
B43legacy_DMAIRQ_NONFATALMASK))) {
u16 fwpatch;
u16 fwdate;
u16 fwtime;
- u32 tmp;
+ u32 tmp, macctl;
int err = 0;
+ /* Jump the microcode PSM to offset 0 */
+ macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN);
+ macctl |= B43legacy_MACCTL_PSM_JMP0;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+ /* Zero out all microcode PSM registers and shared memory. */
+ for (i = 0; i < 64; i++)
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0);
+ for (i = 0; i < 4096; i += 2)
+ b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0);
+
/* Upload Microcode. */
data = (__be32 *) (dev->fw.ucode->data + hdr_len);
len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);
b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
B43legacy_IRQ_ALL);
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402);
+
+ /* Start the microcode PSM */
+ macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ macctl &= ~B43legacy_MACCTL_PSM_JMP0;
+ macctl |= B43legacy_MACCTL_PSM_RUN;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
/* Wait for the microcode to load and respond */
i = 0;
b43legacyerr(dev->wl, "Microcode not responding\n");
b43legacy_print_fw_helptext(dev->wl);
err = -ENODEV;
- goto out;
+ goto error;
+ }
+ msleep_interruptible(50);
+ if (signal_pending(current)) {
+ err = -EINTR;
+ goto error;
}
- udelay(10);
}
/* dummy read follows */
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
" is supported. You must change your firmware"
" files.\n");
b43legacy_print_fw_helptext(dev->wl);
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0);
err = -EOPNOTSUPP;
- goto out;
+ goto error;
}
- b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u "
- "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
- (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
- (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);
+ b43legacyinfo(dev->wl, "Loading firmware version 0x%X, patch level %u "
+ "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,
+ (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,
+ (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F,
+ fwtime & 0x1F);
dev->fw.rev = fwrev;
dev->fw.patch = fwpatch;
-out:
+ return 0;
+
+error:
+ macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ macctl &= ~B43legacy_MACCTL_PSM_RUN;
+ macctl |= B43legacy_MACCTL_PSM_JMP0;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
return err;
}
u32 mask;
u32 set;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
b43legacy_read32(dev,
- B43legacy_MMIO_STATUS_BITFIELD)
+ B43legacy_MMIO_MACCTL)
& 0xFFFF3FFF);
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
mask |= 0x0060;
set |= 0x0060;
}
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) {
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
b43legacy_read16(dev,
B43legacy_MMIO_GPIO_MASK)
B43legacy_WARN_ON(dev->mac_suspended < 0);
B43legacy_WARN_ON(irqs_disabled());
if (dev->mac_suspended == 0) {
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
b43legacy_read32(dev,
- B43legacy_MMIO_STATUS_BITFIELD)
- | B43legacy_SBF_MAC_ENABLED);
+ B43legacy_MMIO_MACCTL)
+ | B43legacy_MACCTL_ENABLED);
b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,
B43legacy_IRQ_MAC_SUSPENDED);
/* the next two are dummy reads */
- b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
+ b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
b43legacy_power_saving_ctl_bits(dev, -1, -1);
dev->irq_savedstate = tmp;
b43legacy_power_saving_ctl_bits(dev, -1, 1);
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
b43legacy_read32(dev,
- B43legacy_MMIO_STATUS_BITFIELD)
- & ~B43legacy_SBF_MAC_ENABLED);
+ B43legacy_MMIO_MACCTL)
+ & ~B43legacy_MACCTL_ENABLED);
b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
for (i = 40; i; i--) {
tmp = b43legacy_read32(dev,
static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
{
b43legacy_radio_turn_off(dev, 1);
- b43legacy_leds_exit(dev);
b43legacy_gpio_cleanup(dev);
/* firmware is released later */
}
struct b43legacy_phy *phy = &dev->phy;
int err;
int tmp;
- u32 value32;
+ u32 value32, macctl;
u16 value16;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,
- B43legacy_SBF_CORE_READY
- | B43legacy_SBF_400);
+ /* Initialize the MAC control */
+ macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED;
+ if (dev->phy.gmode)
+ macctl |= B43legacy_MACCTL_GMODE;
+ macctl |= B43legacy_MACCTL_INFRA;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
err = b43legacy_request_firmware(dev);
if (err)
err = b43legacy_gpio_init(dev);
if (err)
goto out; /* firmware is released later */
- b43legacy_leds_init(dev);
err = b43legacy_upload_initvals(dev);
if (err)
- goto err_leds_exit;
+ goto err_gpio_clean;
b43legacy_radio_turn_on(dev);
b43legacy_write16(dev, 0x03E6, 0x0000);
if (dev->dev->id.revision < 5)
b43legacy_write32(dev, 0x010C, 0x01000000);
- value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
- value32 &= ~B43legacy_SBF_MODE_NOTADHOC;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
- value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
- value32 |= B43legacy_SBF_MODE_NOTADHOC;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
+ value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ value32 &= ~B43legacy_MACCTL_INFRA;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
+ value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ value32 |= B43legacy_MACCTL_INFRA;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32);
if (b43legacy_using_pio(dev)) {
b43legacy_write32(dev, 0x0210, 0x00000100);
b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY,
dev->dev->bus->chipco.fast_pwrup_delay);
+ /* PHY TX errors counter. */
+ atomic_set(&phy->txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+
B43legacy_WARN_ON(err != 0);
b43legacydbg(dev->wl, "Chip initialized\n");
out:
err_radio_off:
b43legacy_radio_turn_off(dev, 1);
-err_leds_exit:
- b43legacy_leds_exit(dev);
+err_gpio_clean:
b43legacy_gpio_cleanup(dev);
goto out;
}
static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev)
{
b43legacy_phy_lo_mark_all_unused(dev);
- if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_RSSI) {
+ if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) {
b43legacy_mac_suspend(dev);
b43legacy_calc_nrssi_slope(dev);
b43legacy_mac_enable(dev);
static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev)
{
b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */
+
+ atomic_set(&dev->phy.txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT);
+ wmb();
}
static void do_periodic_work(struct b43legacy_wldev *dev)
return err;
}
-static int b43legacy_tx(struct ieee80211_hw *hw,
- struct sk_buff *skb,
- struct ieee80211_tx_control *ctl)
+static int b43legacy_op_tx(struct ieee80211_hw *hw,
+ struct sk_buff *skb,
+ struct ieee80211_tx_control *ctl)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
return NETDEV_TX_OK;
}
-static int b43legacy_conf_tx(struct ieee80211_hw *hw,
- int queue,
- const struct ieee80211_tx_queue_params *params)
+static int b43legacy_op_conf_tx(struct ieee80211_hw *hw,
+ int queue,
+ const struct ieee80211_tx_queue_params *params)
{
return 0;
}
-static int b43legacy_get_tx_stats(struct ieee80211_hw *hw,
- struct ieee80211_tx_queue_stats *stats)
+static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw,
+ struct ieee80211_tx_queue_stats *stats)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
return err;
}
-static int b43legacy_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
+static int b43legacy_op_get_stats(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
unsigned long flags;
}
}
-static int b43legacy_dev_config(struct ieee80211_hw *hw,
- struct ieee80211_conf *conf)
+static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
+ struct ieee80211_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
b43legacy_short_slot_timing_disable(dev);
}
+ dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP);
+
/* Adjust the desired TX power level. */
if (conf->power_level != 0) {
if (conf->power_level != phy->power_level) {
return err;
}
-static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
- enum set_key_cmd cmd,
- const u8 *local_addr, const u8 *addr,
- struct ieee80211_key_conf *key)
-{
- struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev = wl->current_dev;
- unsigned long flags;
- int err = -EOPNOTSUPP;
- DECLARE_MAC_BUF(mac);
-
- if (!dev)
- return -ENODEV;
- mutex_lock(&wl->mutex);
- spin_lock_irqsave(&wl->irq_lock, flags);
-
- if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
- err = -ENODEV;
- }
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- mutex_unlock(&wl->mutex);
- b43legacydbg(wl, "Using software based encryption for "
- "mac: %s\n", print_mac(mac, addr));
- return err;
-}
-
-static void b43legacy_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed,
- unsigned int *fflags,
- int mc_count,
- struct dev_addr_list *mc_list)
+static void b43legacy_op_configure_filter(struct ieee80211_hw *hw,
+ unsigned int changed,
+ unsigned int *fflags,
+ int mc_count,
+ struct dev_addr_list *mc_list)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
spin_unlock_irqrestore(&wl->irq_lock, flags);
}
-static int b43legacy_config_interface(struct ieee80211_hw *hw,
- int if_id,
- struct ieee80211_if_conf *conf)
+static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_if_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
return -ENODEV;
mutex_lock(&wl->mutex);
spin_lock_irqsave(&wl->irq_lock, flags);
- B43legacy_WARN_ON(wl->if_id != if_id);
+ B43legacy_WARN_ON(wl->vif != vif);
if (conf->bssid)
memcpy(wl->bssid, conf->bssid, ETH_ALEN);
else
memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig));
memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos));
- /* Flags */
- phy->locked = 0;
/* 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;
phy->lofcal = 0xFFFF;
phy->initval = 0xFFFF;
- spin_lock_init(&phy->lock);
phy->interfmode = B43legacy_INTERFMODE_NONE;
phy->channel = 0xFF;
}
#endif /* CONFIG_SSB_DRIVER_PCICORE */
}
+/* Write the short and long frame retry limit values. */
+static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev,
+ unsigned int short_retry,
+ unsigned int long_retry)
+{
+ /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing
+ * the chip-internal counter. */
+ short_retry = min(short_retry, (unsigned int)0xF);
+ long_retry = min(long_retry, (unsigned int)0xF);
+
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry);
+ b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry);
+}
+
/* Shutdown a wireless core */
/* Locking: wl->mutex */
static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev)
{
struct b43legacy_wl *wl = dev->wl;
struct b43legacy_phy *phy = &dev->phy;
+ u32 macctl;
B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED);
if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED)
return;
b43legacy_set_status(dev, B43legacy_STAT_UNINIT);
+ /* Stop the microcode PSM. */
+ macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);
+ macctl &= ~B43legacy_MACCTL_PSM_RUN;
+ macctl |= B43legacy_MACCTL_PSM_JMP0;
+ b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl);
+
mutex_unlock(&wl->mutex);
/* Must unlock as it would otherwise deadlock. No races here.
* Cancel possibly pending workqueues. */
cancel_work_sync(&dev->restart_work);
mutex_lock(&wl->mutex);
- mutex_unlock(&dev->wl->mutex);
- b43legacy_rfkill_exit(dev);
- mutex_lock(&dev->wl->mutex);
-
+ b43legacy_leds_exit(dev);
b43legacy_rng_exit(dev->wl);
b43legacy_pio_free(dev);
b43legacy_dma_free(dev);
/* Flags */
phy->calibrated = 0;
- phy->locked = 0;
if (phy->_lo_pairs)
memset(phy->_lo_pairs, 0,
hf |= B43legacy_HF_SYMW;
if (phy->rev == 1)
hf |= B43legacy_HF_GDCW;
- if (sprom->r1.boardflags_lo & B43legacy_BFL_PACTRL)
+ if (sprom->boardflags_lo & B43legacy_BFL_PACTRL)
hf |= B43legacy_HF_OFDMPABOOST;
} else if (phy->type == B43legacy_PHYTYPE_B) {
hf |= B43legacy_HF_SYMW;
}
b43legacy_hf_write(dev, hf);
- /* Short/Long Retry Limit.
- * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing
- * the chip-internal counter.
- */
- tmp = limit_value(modparam_short_retry, 0, 0xF);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
- 0x0006, tmp);
- tmp = limit_value(modparam_long_retry, 0, 0xF);
- b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS,
- 0x0007, tmp);
+ b43legacy_set_retry_limits(dev,
+ B43legacy_DEFAULT_SHORT_RETRY_LIMIT,
+ B43legacy_DEFAULT_LONG_RETRY_LIMIT);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED,
0x0044, 3);
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
- memset(wl->bssid, 0, ETH_ALEN);
- memset(wl->mac_addr, 0, ETH_ALEN);
b43legacy_upload_card_macaddress(dev);
b43legacy_security_init(dev);
- b43legacy_rfkill_init(dev);
b43legacy_rng_init(wl);
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
+ b43legacy_leds_init(dev);
out:
return err;
return err;
}
-static int b43legacy_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static int b43legacy_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev;
dev = wl->current_dev;
wl->operating = 1;
- wl->if_id = conf->if_id;
+ wl->vif = conf->vif;
wl->if_type = conf->type;
memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
return err;
}
-static void b43legacy_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static void b43legacy_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_if_init_conf *conf)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
mutex_lock(&wl->mutex);
B43legacy_WARN_ON(!wl->operating);
- B43legacy_WARN_ON(wl->if_id != conf->if_id);
+ B43legacy_WARN_ON(wl->vif != conf->vif);
+ wl->vif = NULL;
wl->operating = 0;
mutex_unlock(&wl->mutex);
}
-static int b43legacy_start(struct ieee80211_hw *hw)
+static int b43legacy_op_start(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
int did_init = 0;
int err = 0;
+ bool do_rfkill_exit = 0;
+
+ /* First register RFkill.
+ * LEDs that are registered later depend on it. */
+ b43legacy_rfkill_init(dev);
+
+ /* Kill all old instance specific information to make sure
+ * the card won't use it in the short timeframe between start
+ * and mac80211 reconfiguring it. */
+ memset(wl->bssid, 0, ETH_ALEN);
+ memset(wl->mac_addr, 0, ETH_ALEN);
+ wl->filter_flags = 0;
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
err = b43legacy_wireless_core_init(dev);
- if (err)
+ if (err) {
+ do_rfkill_exit = 1;
goto out_mutex_unlock;
+ }
did_init = 1;
}
if (err) {
if (did_init)
b43legacy_wireless_core_exit(dev);
+ do_rfkill_exit = 1;
goto out_mutex_unlock;
}
}
out_mutex_unlock:
mutex_unlock(&wl->mutex);
+ if (do_rfkill_exit)
+ b43legacy_rfkill_exit(dev);
+
return err;
}
-static void b43legacy_stop(struct ieee80211_hw *hw)
+static void b43legacy_op_stop(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
struct b43legacy_wldev *dev = wl->current_dev;
+ b43legacy_rfkill_exit(dev);
+
mutex_lock(&wl->mutex);
if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
b43legacy_wireless_core_stop(dev);
mutex_unlock(&wl->mutex);
}
+static int b43legacy_op_set_retry_limit(struct ieee80211_hw *hw,
+ u32 short_retry_limit,
+ u32 long_retry_limit)
+{
+ struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
+ struct b43legacy_wldev *dev;
+ int err = 0;
+
+ mutex_lock(&wl->mutex);
+ dev = wl->current_dev;
+ if (unlikely(!dev ||
+ (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED))) {
+ err = -ENODEV;
+ goto out_unlock;
+ }
+ b43legacy_set_retry_limits(dev, short_retry_limit, long_retry_limit);
+out_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
static const struct ieee80211_ops b43legacy_hw_ops = {
- .tx = b43legacy_tx,
- .conf_tx = b43legacy_conf_tx,
- .add_interface = b43legacy_add_interface,
- .remove_interface = b43legacy_remove_interface,
- .config = b43legacy_dev_config,
- .config_interface = b43legacy_config_interface,
- .set_key = b43legacy_dev_set_key,
- .configure_filter = b43legacy_configure_filter,
- .get_stats = b43legacy_get_stats,
- .get_tx_stats = b43legacy_get_tx_stats,
- .start = b43legacy_start,
- .stop = b43legacy_stop,
+ .tx = b43legacy_op_tx,
+ .conf_tx = b43legacy_op_conf_tx,
+ .add_interface = b43legacy_op_add_interface,
+ .remove_interface = b43legacy_op_remove_interface,
+ .config = b43legacy_op_dev_config,
+ .config_interface = b43legacy_op_config_interface,
+ .configure_filter = b43legacy_op_configure_filter,
+ .get_stats = b43legacy_op_get_stats,
+ .get_tx_stats = b43legacy_op_get_tx_stats,
+ .start = b43legacy_op_start,
+ .stop = b43legacy_op_stop,
+ .set_retry_limit = b43legacy_op_set_retry_limit,
};
/* Hard-reset the chip. Do not call this directly.
static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev)
{
- b43legacy_rfkill_free(dev);
/* We release firmware that late to not be required to re-request
* is all the time when we reinit the core. */
b43legacy_release_firmware(dev);
if (!wl->current_dev)
wl->current_dev = dev;
INIT_WORK(&dev->restart_work, b43legacy_chip_reset);
- b43legacy_rfkill_alloc(dev);
b43legacy_radio_turn_off(dev, 1);
b43legacy_switch_analog(dev, 0);
if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
bus->boardinfo.type == 0x4E &&
bus->boardinfo.rev > 0x40)
- bus->sprom.r1.boardflags_lo |= B43legacy_BFL_PACTRL;
-
- /* Convert Antennagain values to Q5.2 */
- if (bus->sprom.r1.antenna_gain_bg == 0xFF)
- bus->sprom.r1.antenna_gain_bg = 2; /* if unset, use 2 dBm */
- bus->sprom.r1.antenna_gain_bg <<= 2;
+ bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL;
}
static void b43legacy_wireless_exit(struct ssb_device *dev,
hw->max_noise = -110;
hw->queues = 1; /* FIXME: hardware has more queues */
SET_IEEE80211_DEV(hw, dev->dev);
- if (is_valid_ether_addr(sprom->r1.et1mac))
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.et1mac);
+ if (is_valid_ether_addr(sprom->et1mac))
+ SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac);
else
- SET_IEEE80211_PERM_ADDR(hw, sprom->r1.il0mac);
+ SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac);
/* Get and initialize struct b43legacy_wl */
wl = hw_to_b43legacy_wl(hw);
.resume = b43legacy_resume,
};
+static void b43legacy_print_driverinfo(void)
+{
+ const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "",
+ *feat_pio = "", *feat_dma = "";
+
+#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT
+ feat_pci = "P";
+#endif
+#ifdef CONFIG_B43LEGACY_LEDS
+ feat_leds = "L";
+#endif
+#ifdef CONFIG_B43LEGACY_RFKILL
+ feat_rfkill = "R";
+#endif
+#ifdef CONFIG_B43LEGACY_PIO
+ feat_pio = "I";
+#endif
+#ifdef CONFIG_B43LEGACY_DMA
+ feat_dma = "D";
+#endif
+ printk(KERN_INFO "Broadcom 43xx driver loaded "
+ "[ Features: %s%s%s%s%s, Firmware-ID: "
+ B43legacy_SUPPORTED_FIRMWARE_ID " ]\n",
+ feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma);
+}
+
static int __init b43legacy_init(void)
{
int err;
if (err)
goto err_dfs_exit;
+ b43legacy_print_driverinfo();
+
return err;
err_dfs_exit: