aboutsummaryrefslogtreecommitdiffstats
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];
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.