summaryrefslogtreecommitdiff
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.c245
1 files changed, 132 insertions, 113 deletions
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index a793f183a2c0..f0749510bcd7 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -91,14 +91,6 @@ 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),
@@ -566,12 +558,11 @@ static void b43legacy_write_mac_bssid_templates(struct b43legacy_wldev *dev)
}
}
-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,
@@ -1874,34 +1865,25 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev)
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. */
@@ -2091,10 +2073,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
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);
@@ -2699,7 +2677,7 @@ out_unlock_mutex:
}
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)
{
@@ -2724,22 +2702,42 @@ static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
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);
}
@@ -2755,21 +2753,19 @@ static int b43legacy_config_interface(struct ieee80211_hw *hw,
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);
@@ -3216,8 +3212,9 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
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);
@@ -3246,22 +3243,80 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
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;
+
+ 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) {
@@ -3271,59 +3326,21 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
}
}
- 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)
+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);
}
@@ -3336,9 +3353,11 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
.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.