module_param_named(long_retry, modparam_long_retry, int, 0444);
MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)");
-static int modparam_noleds;
-module_param_named(noleds, modparam_noleds, int, 0444);
-MODULE_PARM_DESC(noleds, "Turn off all LED activity");
-
static char modparam_fwpostfix[16];
module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load.");
-static int modparam_mon_keep_bad;
-module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444);
-MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode");
-
-static int modparam_mon_keep_badplcp;
-module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444);
-MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode");
-
/* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */
static const struct ssb_device_id b43legacy_ssb_tbl[] = {
SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2),
}
}
-static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev,
- const u8 *mac_addr)
+static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev)
{
- dev->wl->mac_addr = mac_addr;
b43legacy_write_mac_bssid_templates(dev);
- b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF, mac_addr);
+ b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF,
+ dev->wl->mac_addr);
}
static void b43legacy_set_slot_time(struct b43legacy_wldev *dev,
u32 dma_reason[ARRAY_SIZE(dev->dma_reason)];
u32 merged_dma_reason = 0;
int i;
- int activity = 0;
unsigned long flags;
spin_lock_irqsave(&dev->wl->irq_lock, flags);
b43legacy_pio_rx(dev->pio.queue0);
else
b43legacy_dma_rx(dev->dma.rx_ring0);
- /* We intentionally don't set "activity" to 1, here. */
}
B43legacy_WARN_ON(dma_reason[1] & B43legacy_DMAIRQ_RX_DONE);
B43legacy_WARN_ON(dma_reason[2] & B43legacy_DMAIRQ_RX_DONE);
b43legacy_pio_rx(dev->pio.queue3);
else
b43legacy_dma_rx(dev->dma.rx_ring3);
- activity = 1;
}
B43legacy_WARN_ON(dma_reason[4] & B43legacy_DMAIRQ_RX_DONE);
B43legacy_WARN_ON(dma_reason[5] & B43legacy_DMAIRQ_RX_DONE);
- if (reason & B43legacy_IRQ_TX_OK) {
+ if (reason & B43legacy_IRQ_TX_OK)
handle_irq_transmit_status(dev);
- activity = 1;
- /* TODO: In AP mode, this also causes sending of powersave
- responses. */
- }
- if (!modparam_noleds)
- b43legacy_leds_update(dev, activity);
b43legacy_interrupt_enable(dev, dev->irq_savedstate);
mmiowb();
spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl)
{
b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/"
- "Drivers/bcm43xx#devicefirmware "
+ "Drivers/b43#devicefirmware "
"and download the correct firmware (version 3).\n");
}
B43legacy_MMIO_STATUS_BITFIELD)
& 0xFFFF3FFF);
- b43legacy_leds_switch_all(dev, 0);
b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,
b43legacy_read16(dev,
B43legacy_MMIO_GPIO_MASK)
ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP;
ctl &= ~B43legacy_MACCTL_KEEP_BAD;
ctl &= ~B43legacy_MACCTL_PROMISC;
+ ctl &= ~B43legacy_MACCTL_BEACPROMISC;
ctl |= B43legacy_MACCTL_INFRA;
- if (wl->operating) {
- switch (wl->if_type) {
- case IEEE80211_IF_TYPE_AP:
- ctl |= B43legacy_MACCTL_AP;
- break;
- case IEEE80211_IF_TYPE_IBSS:
- ctl &= ~B43legacy_MACCTL_INFRA;
- break;
- case IEEE80211_IF_TYPE_STA:
- case IEEE80211_IF_TYPE_MNTR:
- case IEEE80211_IF_TYPE_WDS:
- break;
- default:
- b43legacyerr(wl, "Improper value of %d for"
- " wl->if_type\n", wl->if_type);
- }
- }
- if (wl->monitor) {
+ if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
+ ctl |= B43legacy_MACCTL_AP;
+ else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
+ ctl &= ~B43legacy_MACCTL_INFRA;
+
+ if (wl->filter_flags & FIF_CONTROL)
ctl |= B43legacy_MACCTL_KEEP_CTL;
- if (modparam_mon_keep_bad)
- ctl |= B43legacy_MACCTL_KEEP_BAD;
- if (modparam_mon_keep_badplcp)
- ctl |= B43legacy_MACCTL_KEEP_BADPLCP;
- }
- if (wl->promisc)
+ if (wl->filter_flags & FIF_FCSFAIL)
+ ctl |= B43legacy_MACCTL_KEEP_BAD;
+ if (wl->filter_flags & FIF_PLCPFAIL)
+ ctl |= B43legacy_MACCTL_KEEP_BADPLCP;
+ if (wl->filter_flags & FIF_PROMISC_IN_BSS)
ctl |= B43legacy_MACCTL_PROMISC;
+ if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC)
+ ctl |= B43legacy_MACCTL_BEACPROMISC;
+
/* Workaround: On old hardware the HW-MAC-address-filter
* doesn't work properly, so always run promisc in filter
* it in software. */
static void b43legacy_chip_exit(struct b43legacy_wldev *dev)
{
b43legacy_radio_turn_off(dev);
- if (!modparam_noleds)
- b43legacy_leds_exit(dev);
+ b43legacy_leds_exit(dev);
b43legacy_gpio_cleanup(dev);
/* firmware is released later */
}
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_gpio_cleanup;
+ goto err_leds_exit;
b43legacy_radio_turn_on(dev);
b43legacy_write16(dev, 0x03E6, 0x0000);
value32 |= B43legacy_SBF_MODE_NOTADHOC;
b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
- value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
- value32 |= 0x100000;
- b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
-
if (b43legacy_using_pio(dev)) {
b43legacy_write32(dev, 0x0210, 0x00000100);
b43legacy_write32(dev, 0x0230, 0x00000100);
err_radio_off:
b43legacy_radio_turn_off(dev);
-err_gpio_cleanup:
+err_leds_exit:
+ b43legacy_leds_exit(dev);
b43legacy_gpio_cleanup(dev);
goto out;
}
dev->radio_hw_enable = radio_hw_enable;
b43legacyinfo(dev->wl, "Radio hardware status changed to %s\n",
(radio_hw_enable) ? "enabled" : "disabled");
- b43legacy_leds_update(dev, 0);
}
}
if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST))
delay = msecs_to_jiffies(50);
else
- delay = round_jiffies(HZ);
+ delay = round_jiffies_relative(HZ);
queue_delayed_work(dev->wl->hw->workqueue,
&dev->periodic_work, delay);
out:
}
static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
- set_key_cmd cmd,
+ enum set_key_cmd cmd,
const u8 *local_addr, const u8 *addr,
struct ieee80211_key_conf *key)
{
return err;
}
-static void b43legacy_set_multicast_list(struct ieee80211_hw *hw,
- unsigned short netflags,
- int mc_count)
+static void b43legacy_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;
unsigned long flags;
- if (!dev)
+ if (!dev) {
+ *fflags = 0;
return;
- spin_lock_irqsave(&wl->irq_lock, flags);
- if (wl->promisc != !!(netflags & IFF_PROMISC)) {
- wl->promisc = !!(netflags & IFF_PROMISC);
- if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED)
- b43legacy_adjust_opmode(dev);
}
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ *fflags &= FIF_PROMISC_IN_BSS |
+ FIF_ALLMULTI |
+ FIF_FCSFAIL |
+ FIF_PLCPFAIL |
+ FIF_CONTROL |
+ FIF_OTHER_BSS |
+ FIF_BCN_PRBRESP_PROMISC;
+
+ changed &= FIF_PROMISC_IN_BSS |
+ FIF_ALLMULTI |
+ FIF_FCSFAIL |
+ FIF_PLCPFAIL |
+ FIF_CONTROL |
+ FIF_OTHER_BSS |
+ FIF_BCN_PRBRESP_PROMISC;
+
+ wl->filter_flags = *fflags;
+
+ if (changed && b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED)
+ b43legacy_adjust_opmode(dev);
spin_unlock_irqrestore(&wl->irq_lock, flags);
}
return -ENODEV;
mutex_lock(&wl->mutex);
spin_lock_irqsave(&wl->irq_lock, flags);
- if (conf->type != IEEE80211_IF_TYPE_MNTR) {
- B43legacy_WARN_ON(wl->if_id != if_id);
- wl->bssid = conf->bssid;
- if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
- if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
- B43legacy_WARN_ON(conf->type !=
- IEEE80211_IF_TYPE_AP);
- b43legacy_set_ssid(dev, conf->ssid,
- conf->ssid_len);
- if (conf->beacon)
- b43legacy_refresh_templates(dev,
- conf->beacon);
- }
- b43legacy_write_mac_bssid_templates(dev);
+ B43legacy_WARN_ON(wl->if_id != if_id);
+ if (conf->bssid)
+ memcpy(wl->bssid, conf->bssid, ETH_ALEN);
+ else
+ memset(wl->bssid, 0, ETH_ALEN);
+ if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
+ if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
+ B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+ b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
+ if (conf->beacon)
+ b43legacy_refresh_templates(dev, conf->beacon);
}
+ b43legacy_write_mac_bssid_templates(dev);
}
spin_unlock_irqrestore(&wl->irq_lock, flags);
mutex_unlock(&wl->mutex);
if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
return;
+
+ /* Disable and sync interrupts. We must do this before than
+ * setting the status to INITIALIZED, as the interrupt handler
+ * won't care about IRQs then. */
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ dev->irq_savedstate = b43legacy_interrupt_disable(dev,
+ B43legacy_IRQ_ALL);
+ b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+ b43legacy_synchronize_irq(dev);
+
b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED);
mutex_unlock(&wl->mutex);
ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */
- /* Disable and sync interrupts. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- dev->irq_savedstate = b43legacy_interrupt_disable(dev,
- B43legacy_IRQ_ALL);
- b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- b43legacy_synchronize_irq(dev);
-
b43legacy_mac_suspend(dev);
free_irq(dev->dev->irq, dev);
b43legacydbg(wl, "Wireless interface stopped\n");
b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
- wl->bssid = NULL;
- b43legacy_upload_card_macaddress(dev, NULL);
+ memset(wl->bssid, 0, ETH_ALEN);
+ memset(wl->mac_addr, 0, ETH_ALEN);
+ b43legacy_upload_card_macaddress(dev);
b43legacy_security_init(dev);
b43legacy_rng_init(wl);
struct b43legacy_wldev *dev;
unsigned long flags;
int err = -EOPNOTSUPP;
- int did_init = 0;
+
+ /* TODO: allow WDS/AP devices to coexist */
+
+ if (conf->type != IEEE80211_IF_TYPE_AP &&
+ conf->type != IEEE80211_IF_TYPE_STA &&
+ conf->type != IEEE80211_IF_TYPE_WDS &&
+ conf->type != IEEE80211_IF_TYPE_IBSS)
+ return -EOPNOTSUPP;
mutex_lock(&wl->mutex);
- if ((conf->type != IEEE80211_IF_TYPE_MNTR) &&
- wl->operating)
+ if (wl->operating)
goto out_mutex_unlock;
b43legacydbg(wl, "Adding Interface type %d\n", conf->type);
dev = wl->current_dev;
+ wl->operating = 1;
+ wl->if_id = conf->if_id;
+ wl->if_type = conf->type;
+ memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43legacy_adjust_opmode(dev);
+ b43legacy_upload_card_macaddress(dev);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ err = 0;
+ out_mutex_unlock:
+ mutex_unlock(&wl->mutex);
+
+ return err;
+}
+
+static void b43legacy_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;
+ unsigned long flags;
+
+ b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
+
+ mutex_lock(&wl->mutex);
+
+ B43legacy_WARN_ON(!wl->operating);
+ B43legacy_WARN_ON(wl->if_id != conf->if_id);
+
+ wl->operating = 0;
+
+ spin_lock_irqsave(&wl->irq_lock, flags);
+ b43legacy_adjust_opmode(dev);
+ memset(wl->mac_addr, 0, ETH_ALEN);
+ b43legacy_upload_card_macaddress(dev);
+ spin_unlock_irqrestore(&wl->irq_lock, flags);
+
+ mutex_unlock(&wl->mutex);
+}
+
+static int b43legacy_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;
+
+ mutex_lock(&wl->mutex);
+
if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
err = b43legacy_wireless_core_init(dev);
if (err)
goto out_mutex_unlock;
did_init = 1;
}
+
if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
err = b43legacy_wireless_core_start(dev);
if (err) {
}
}
- spin_lock_irqsave(&wl->irq_lock, flags);
- switch (conf->type) {
- case IEEE80211_IF_TYPE_MNTR:
- wl->monitor++;
- break;
- default:
- wl->operating = 1;
- wl->if_id = conf->if_id;
- wl->if_type = conf->type;
- b43legacy_upload_card_macaddress(dev, conf->mac_addr);
- }
- b43legacy_adjust_opmode(dev);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
-
- err = 0;
out_mutex_unlock:
mutex_unlock(&wl->mutex);
return err;
}
-static void b43legacy_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
+static void b43legacy_stop(struct ieee80211_hw *hw)
{
struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
- struct b43legacy_wldev *dev;
- unsigned long flags;
-
- b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
+ struct b43legacy_wldev *dev = wl->current_dev;
mutex_lock(&wl->mutex);
- if (conf->type == IEEE80211_IF_TYPE_MNTR) {
- wl->monitor--;
- B43legacy_WARN_ON(wl->monitor < 0);
- } else {
- B43legacy_WARN_ON(!wl->operating);
- wl->operating = 0;
- }
-
- dev = wl->current_dev;
- if (!wl->operating && wl->monitor == 0) {
- /* No interface left. */
- if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
- b43legacy_wireless_core_stop(dev);
- b43legacy_wireless_core_exit(dev);
- } else {
- /* Just monitor interfaces left. */
- spin_lock_irqsave(&wl->irq_lock, flags);
- b43legacy_adjust_opmode(dev);
- if (!wl->operating)
- b43legacy_upload_card_macaddress(dev, NULL);
- spin_unlock_irqrestore(&wl->irq_lock, flags);
- }
+ if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
+ b43legacy_wireless_core_stop(dev);
+ b43legacy_wireless_core_exit(dev);
mutex_unlock(&wl->mutex);
}
.config = b43legacy_dev_config,
.config_interface = b43legacy_config_interface,
.set_key = b43legacy_dev_set_key,
- .set_multicast_list = b43legacy_set_multicast_list,
+ .configure_filter = b43legacy_configure_filter,
.get_stats = b43legacy_get_stats,
.get_tx_stats = b43legacy_get_tx_stats,
+ .start = b43legacy_start,
+ .stop = b43legacy_stop,
};
/* Hard-reset the chip. Do not call this directly.
else
have_bphy = 1;
- /* Initialize LEDs structs. */
- err = b43legacy_leds_init(dev);
- if (err)
- goto err_powerdown;
-
dev->phy.gmode = (have_gphy || have_bphy);
tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0;
b43legacy_wireless_core_reset(dev, tmp);
err = b43legacy_phy_versioning(dev);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
/* Check if this device supports multiband. */
if (!pdev ||
(pdev->device != 0x4312 &&
err = b43legacy_validate_chipaccess(dev);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
err = b43legacy_setup_modes(dev, have_bphy, have_gphy);
if (err)
- goto err_leds_exit;
+ goto err_powerdown;
/* Now set some default "current_dev" */
if (!wl->current_dev)
out:
return err;
-err_leds_exit:
- b43legacy_leds_exit(dev);
err_powerdown:
ssb_bus_may_powerdown(bus);
return err;