aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43legacy/main.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-09-17 01:29:23 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:52:57 -0400
commit4150c57212ad134765dd78c654a4b9906252b66d (patch)
treec37ab7a3f75532a623ed00339782d769514422d2 /drivers/net/wireless/b43legacy/main.c
parent070ac3a2651e3c1c4d277c5f1981517427c386a7 (diff)
[PATCH] mac80211: revamp interface and filter configuration
Drivers are currently supposed to keep track of monitor interfaces if they allow so-called "hard" monitor, and they are also supposed to keep track of multicast etc. This patch changes that, replaces the set_multicast_list() callback with a new configure_filter() callback that takes filter flags (FIF_*) instead of interface flags (IFF_*). For a driver, this means it should open the filter as much as necessary to get all frames requested by the filter flags. Accordingly, the filter flags are named "positively", e.g. FIF_ALLMULTI. Multicast filtering is a bit special in that drivers that have no multicast address filters need to allow multicast frames through when either the FIF_ALLMULTI flag is set or when the mc_count value is positive. At the same time, drivers are no longer notified about monitor interfaces at all, this means they now need to implement the start() and stop() callbacks and the new change_filter_flags() callback. Also, the start()/stop() ordering changed, start() is now called *before* any add_interface() as it really should be, and stop() after any remove_interface(). The patch also changes the behaviour of setting the bssid to multicast for scanning when IEEE80211_HW_NO_PROBE_FILTERING is set; the IEEE80211_HW_NO_PROBE_FILTERING flag is removed and the filter flag FIF_BCN_PRBRESP_PROMISC introduced. This is a lot more efficient for hardware like b43 that supports it and other hardware can still set the BSSID to all-ones. Driver modifications by Johannes Berg (b43 & iwlwifi), Michael Wu (rtl8187, adm8211, and p54), Larry Finger (b43legacy), and Ivo van Doorn (rt2x00). Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
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];
91module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); 91module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
92MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load."); 92MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load.");
93 93
94static int modparam_mon_keep_bad;
95module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444);
96MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode");
97
98static int modparam_mon_keep_badplcp;
99module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444);
100MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode");
101
102/* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */ 94/* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */
103static const struct ssb_device_id b43legacy_ssb_tbl[] = { 95static const struct ssb_device_id b43legacy_ssb_tbl[] = {
104 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2), 96 SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2),
@@ -566,12 +558,11 @@ static void b43legacy_write_mac_bssid_templates(struct b43legacy_wldev *dev)
566 } 558 }
567} 559}
568 560
569static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev, 561static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev)
570 const u8 *mac_addr)
571{ 562{
572 dev->wl->mac_addr = mac_addr;
573 b43legacy_write_mac_bssid_templates(dev); 563 b43legacy_write_mac_bssid_templates(dev);
574 b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF, mac_addr); 564 b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF,
565 dev->wl->mac_addr);
575} 566}
576 567
577static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, 568static void b43legacy_set_slot_time(struct b43legacy_wldev *dev,
@@ -1874,34 +1865,25 @@ static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev)
1874 ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP; 1865 ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP;
1875 ctl &= ~B43legacy_MACCTL_KEEP_BAD; 1866 ctl &= ~B43legacy_MACCTL_KEEP_BAD;
1876 ctl &= ~B43legacy_MACCTL_PROMISC; 1867 ctl &= ~B43legacy_MACCTL_PROMISC;
1868 ctl &= ~B43legacy_MACCTL_BEACPROMISC;
1877 ctl |= B43legacy_MACCTL_INFRA; 1869 ctl |= B43legacy_MACCTL_INFRA;
1878 1870
1879 if (wl->operating) { 1871 if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP))
1880 switch (wl->if_type) { 1872 ctl |= B43legacy_MACCTL_AP;
1881 case IEEE80211_IF_TYPE_AP: 1873 else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
1882 ctl |= B43legacy_MACCTL_AP; 1874 ctl &= ~B43legacy_MACCTL_INFRA;
1883 break; 1875
1884 case IEEE80211_IF_TYPE_IBSS: 1876 if (wl->filter_flags & FIF_CONTROL)
1885 ctl &= ~B43legacy_MACCTL_INFRA;
1886 break;
1887 case IEEE80211_IF_TYPE_STA:
1888 case IEEE80211_IF_TYPE_MNTR:
1889 case IEEE80211_IF_TYPE_WDS:
1890 break;
1891 default:
1892 b43legacyerr(wl, "Improper value of %d for"
1893 " wl->if_type\n", wl->if_type);
1894 }
1895 }
1896 if (wl->monitor) {
1897 ctl |= B43legacy_MACCTL_KEEP_CTL; 1877 ctl |= B43legacy_MACCTL_KEEP_CTL;
1898 if (modparam_mon_keep_bad) 1878 if (wl->filter_flags & FIF_FCSFAIL)
1899 ctl |= B43legacy_MACCTL_KEEP_BAD; 1879 ctl |= B43legacy_MACCTL_KEEP_BAD;
1900 if (modparam_mon_keep_badplcp) 1880 if (wl->filter_flags & FIF_PLCPFAIL)
1901 ctl |= B43legacy_MACCTL_KEEP_BADPLCP; 1881 ctl |= B43legacy_MACCTL_KEEP_BADPLCP;
1902 } 1882 if (wl->filter_flags & FIF_PROMISC_IN_BSS)
1903 if (wl->promisc)
1904 ctl |= B43legacy_MACCTL_PROMISC; 1883 ctl |= B43legacy_MACCTL_PROMISC;
1884 if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC)
1885 ctl |= B43legacy_MACCTL_BEACPROMISC;
1886
1905 /* Workaround: On old hardware the HW-MAC-address-filter 1887 /* Workaround: On old hardware the HW-MAC-address-filter
1906 * doesn't work properly, so always run promisc in filter 1888 * doesn't work properly, so always run promisc in filter
1907 * it in software. */ 1889 * it in software. */
@@ -2091,10 +2073,6 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev)
2091 value32 |= B43legacy_SBF_MODE_NOTADHOC; 2073 value32 |= B43legacy_SBF_MODE_NOTADHOC;
2092 b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32); 2074 b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
2093 2075
2094 value32 = b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);
2095 value32 |= 0x100000;
2096 b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, value32);
2097
2098 if (b43legacy_using_pio(dev)) { 2076 if (b43legacy_using_pio(dev)) {
2099 b43legacy_write32(dev, 0x0210, 0x00000100); 2077 b43legacy_write32(dev, 0x0210, 0x00000100);
2100 b43legacy_write32(dev, 0x0230, 0x00000100); 2078 b43legacy_write32(dev, 0x0230, 0x00000100);
@@ -2699,7 +2677,7 @@ out_unlock_mutex:
2699} 2677}
2700 2678
2701static int b43legacy_dev_set_key(struct ieee80211_hw *hw, 2679static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
2702 set_key_cmd cmd, 2680 enum set_key_cmd cmd,
2703 const u8 *local_addr, const u8 *addr, 2681 const u8 *local_addr, const u8 *addr,
2704 struct ieee80211_key_conf *key) 2682 struct ieee80211_key_conf *key)
2705{ 2683{
@@ -2724,22 +2702,42 @@ static int b43legacy_dev_set_key(struct ieee80211_hw *hw,
2724 return err; 2702 return err;
2725} 2703}
2726 2704
2727static void b43legacy_set_multicast_list(struct ieee80211_hw *hw, 2705static void b43legacy_configure_filter(struct ieee80211_hw *hw,
2728 unsigned short netflags, 2706 unsigned int changed,
2729 int mc_count) 2707 unsigned int *fflags,
2708 int mc_count,
2709 struct dev_addr_list *mc_list)
2730{ 2710{
2731 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); 2711 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
2732 struct b43legacy_wldev *dev = wl->current_dev; 2712 struct b43legacy_wldev *dev = wl->current_dev;
2733 unsigned long flags; 2713 unsigned long flags;
2734 2714
2735 if (!dev) 2715 if (!dev) {
2716 *fflags = 0;
2736 return; 2717 return;
2737 spin_lock_irqsave(&wl->irq_lock, flags);
2738 if (wl->promisc != !!(netflags & IFF_PROMISC)) {
2739 wl->promisc = !!(netflags & IFF_PROMISC);
2740 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED)
2741 b43legacy_adjust_opmode(dev);
2742 } 2718 }
2719
2720 spin_lock_irqsave(&wl->irq_lock, flags);
2721 *fflags &= FIF_PROMISC_IN_BSS |
2722 FIF_ALLMULTI |
2723 FIF_FCSFAIL |
2724 FIF_PLCPFAIL |
2725 FIF_CONTROL |
2726 FIF_OTHER_BSS |
2727 FIF_BCN_PRBRESP_PROMISC;
2728
2729 changed &= FIF_PROMISC_IN_BSS |
2730 FIF_ALLMULTI |
2731 FIF_FCSFAIL |
2732 FIF_PLCPFAIL |
2733 FIF_CONTROL |
2734 FIF_OTHER_BSS |
2735 FIF_BCN_PRBRESP_PROMISC;
2736
2737 wl->filter_flags = *fflags;
2738
2739 if (changed && b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED)
2740 b43legacy_adjust_opmode(dev);
2743 spin_unlock_irqrestore(&wl->irq_lock, flags); 2741 spin_unlock_irqrestore(&wl->irq_lock, flags);
2744} 2742}
2745 2743
@@ -2755,21 +2753,19 @@ static int b43legacy_config_interface(struct ieee80211_hw *hw,
2755 return -ENODEV; 2753 return -ENODEV;
2756 mutex_lock(&wl->mutex); 2754 mutex_lock(&wl->mutex);
2757 spin_lock_irqsave(&wl->irq_lock, flags); 2755 spin_lock_irqsave(&wl->irq_lock, flags);
2758 if (conf->type != IEEE80211_IF_TYPE_MNTR) { 2756 B43legacy_WARN_ON(wl->if_id != if_id);
2759 B43legacy_WARN_ON(wl->if_id != if_id); 2757 if (conf->bssid)
2760 wl->bssid = conf->bssid; 2758 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
2761 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { 2759 else
2762 if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) { 2760 memset(wl->bssid, 0, ETH_ALEN);
2763 B43legacy_WARN_ON(conf->type != 2761 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
2764 IEEE80211_IF_TYPE_AP); 2762 if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
2765 b43legacy_set_ssid(dev, conf->ssid, 2763 B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
2766 conf->ssid_len); 2764 b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
2767 if (conf->beacon) 2765 if (conf->beacon)
2768 b43legacy_refresh_templates(dev, 2766 b43legacy_refresh_templates(dev, conf->beacon);
2769 conf->beacon);
2770 }
2771 b43legacy_write_mac_bssid_templates(dev);
2772 } 2767 }
2768 b43legacy_write_mac_bssid_templates(dev);
2773 } 2769 }
2774 spin_unlock_irqrestore(&wl->irq_lock, flags); 2770 spin_unlock_irqrestore(&wl->irq_lock, flags);
2775 mutex_unlock(&wl->mutex); 2771 mutex_unlock(&wl->mutex);
@@ -3216,8 +3212,9 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev)
3216 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4); 3212 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0414, 0x01F4);
3217 3213
3218 ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ 3214 ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
3219 wl->bssid = NULL; 3215 memset(wl->bssid, 0, ETH_ALEN);
3220 b43legacy_upload_card_macaddress(dev, NULL); 3216 memset(wl->mac_addr, 0, ETH_ALEN);
3217 b43legacy_upload_card_macaddress(dev);
3221 b43legacy_security_init(dev); 3218 b43legacy_security_init(dev);
3222 b43legacy_rng_init(wl); 3219 b43legacy_rng_init(wl);
3223 3220
@@ -3246,22 +3243,80 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
3246 struct b43legacy_wldev *dev; 3243 struct b43legacy_wldev *dev;
3247 unsigned long flags; 3244 unsigned long flags;
3248 int err = -EOPNOTSUPP; 3245 int err = -EOPNOTSUPP;
3249 int did_init = 0; 3246
3247 /* TODO: allow WDS/AP devices to coexist */
3248
3249 if (conf->type != IEEE80211_IF_TYPE_AP &&
3250 conf->type != IEEE80211_IF_TYPE_STA &&
3251 conf->type != IEEE80211_IF_TYPE_WDS &&
3252 conf->type != IEEE80211_IF_TYPE_IBSS)
3253 return -EOPNOTSUPP;
3250 3254
3251 mutex_lock(&wl->mutex); 3255 mutex_lock(&wl->mutex);
3252 if ((conf->type != IEEE80211_IF_TYPE_MNTR) && 3256 if (wl->operating)
3253 wl->operating)
3254 goto out_mutex_unlock; 3257 goto out_mutex_unlock;
3255 3258
3256 b43legacydbg(wl, "Adding Interface type %d\n", conf->type); 3259 b43legacydbg(wl, "Adding Interface type %d\n", conf->type);
3257 3260
3258 dev = wl->current_dev; 3261 dev = wl->current_dev;
3262 wl->operating = 1;
3263 wl->if_id = conf->if_id;
3264 wl->if_type = conf->type;
3265 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
3266
3267 spin_lock_irqsave(&wl->irq_lock, flags);
3268 b43legacy_adjust_opmode(dev);
3269 b43legacy_upload_card_macaddress(dev);
3270 spin_unlock_irqrestore(&wl->irq_lock, flags);
3271
3272 err = 0;
3273 out_mutex_unlock:
3274 mutex_unlock(&wl->mutex);
3275
3276 return err;
3277}
3278
3279static void b43legacy_remove_interface(struct ieee80211_hw *hw,
3280 struct ieee80211_if_init_conf *conf)
3281{
3282 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
3283 struct b43legacy_wldev *dev = wl->current_dev;
3284 unsigned long flags;
3285
3286 b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
3287
3288 mutex_lock(&wl->mutex);
3289
3290 B43legacy_WARN_ON(!wl->operating);
3291 B43legacy_WARN_ON(wl->if_id != conf->if_id);
3292
3293 wl->operating = 0;
3294
3295 spin_lock_irqsave(&wl->irq_lock, flags);
3296 b43legacy_adjust_opmode(dev);
3297 memset(wl->mac_addr, 0, ETH_ALEN);
3298 b43legacy_upload_card_macaddress(dev);
3299 spin_unlock_irqrestore(&wl->irq_lock, flags);
3300
3301 mutex_unlock(&wl->mutex);
3302}
3303
3304static int b43legacy_start(struct ieee80211_hw *hw)
3305{
3306 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
3307 struct b43legacy_wldev *dev = wl->current_dev;
3308 int did_init = 0;
3309 int err;
3310
3311 mutex_lock(&wl->mutex);
3312
3259 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { 3313 if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) {
3260 err = b43legacy_wireless_core_init(dev); 3314 err = b43legacy_wireless_core_init(dev);
3261 if (err) 3315 if (err)
3262 goto out_mutex_unlock; 3316 goto out_mutex_unlock;
3263 did_init = 1; 3317 did_init = 1;
3264 } 3318 }
3319
3265 if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { 3320 if (b43legacy_status(dev) < B43legacy_STAT_STARTED) {
3266 err = b43legacy_wireless_core_start(dev); 3321 err = b43legacy_wireless_core_start(dev);
3267 if (err) { 3322 if (err) {
@@ -3271,59 +3326,21 @@ static int b43legacy_add_interface(struct ieee80211_hw *hw,
3271 } 3326 }
3272 } 3327 }
3273 3328
3274 spin_lock_irqsave(&wl->irq_lock, flags);
3275 switch (conf->type) {
3276 case IEEE80211_IF_TYPE_MNTR:
3277 wl->monitor++;
3278 break;
3279 default:
3280 wl->operating = 1;
3281 wl->if_id = conf->if_id;
3282 wl->if_type = conf->type;
3283 b43legacy_upload_card_macaddress(dev, conf->mac_addr);
3284 }
3285 b43legacy_adjust_opmode(dev);
3286 spin_unlock_irqrestore(&wl->irq_lock, flags);
3287
3288 err = 0;
3289out_mutex_unlock: 3329out_mutex_unlock:
3290 mutex_unlock(&wl->mutex); 3330 mutex_unlock(&wl->mutex);
3291 3331
3292 return err; 3332 return err;
3293} 3333}
3294 3334
3295static void b43legacy_remove_interface(struct ieee80211_hw *hw, 3335void b43legacy_stop(struct ieee80211_hw *hw)
3296 struct ieee80211_if_init_conf *conf)
3297{ 3336{
3298 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); 3337 struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
3299 struct b43legacy_wldev *dev; 3338 struct b43legacy_wldev *dev = wl->current_dev;
3300 unsigned long flags;
3301
3302 b43legacydbg(wl, "Removing Interface type %d\n", conf->type);
3303 3339
3304 mutex_lock(&wl->mutex); 3340 mutex_lock(&wl->mutex);
3305 if (conf->type == IEEE80211_IF_TYPE_MNTR) { 3341 if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
3306 wl->monitor--; 3342 b43legacy_wireless_core_stop(dev);
3307 B43legacy_WARN_ON(wl->monitor < 0); 3343 b43legacy_wireless_core_exit(dev);
3308 } else {
3309 B43legacy_WARN_ON(!wl->operating);
3310 wl->operating = 0;
3311 }
3312
3313 dev = wl->current_dev;
3314 if (!wl->operating && wl->monitor == 0) {
3315 /* No interface left. */
3316 if (b43legacy_status(dev) >= B43legacy_STAT_STARTED)
3317 b43legacy_wireless_core_stop(dev);
3318 b43legacy_wireless_core_exit(dev);
3319 } else {
3320 /* Just monitor interfaces left. */
3321 spin_lock_irqsave(&wl->irq_lock, flags);
3322 b43legacy_adjust_opmode(dev);
3323 if (!wl->operating)
3324 b43legacy_upload_card_macaddress(dev, NULL);
3325 spin_unlock_irqrestore(&wl->irq_lock, flags);
3326 }
3327 mutex_unlock(&wl->mutex); 3344 mutex_unlock(&wl->mutex);
3328} 3345}
3329 3346
@@ -3336,9 +3353,11 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
3336 .config = b43legacy_dev_config, 3353 .config = b43legacy_dev_config,
3337 .config_interface = b43legacy_config_interface, 3354 .config_interface = b43legacy_config_interface,
3338 .set_key = b43legacy_dev_set_key, 3355 .set_key = b43legacy_dev_set_key,
3339 .set_multicast_list = b43legacy_set_multicast_list, 3356 .configure_filter = b43legacy_configure_filter,
3340 .get_stats = b43legacy_get_stats, 3357 .get_stats = b43legacy_get_stats,
3341 .get_tx_stats = b43legacy_get_tx_stats, 3358 .get_tx_stats = b43legacy_get_tx_stats,
3359 .start = b43legacy_start,
3360 .stop = b43legacy_stop,
3342}; 3361};
3343 3362
3344/* Hard-reset the chip. Do not call this directly. 3363/* Hard-reset the chip. Do not call this directly.