aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/main.c')
-rw-r--r--drivers/net/wireless/b43/main.c248
1 files changed, 132 insertions, 116 deletions
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index b44c9f928848..72467c86f8d4 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -92,14 +92,6 @@ static char modparam_fwpostfix[16];
92module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); 92module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444);
93MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load."); 93MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load.");
94 94
95static int modparam_mon_keep_bad;
96module_param_named(mon_keep_bad, modparam_mon_keep_bad, int, 0444);
97MODULE_PARM_DESC(mon_keep_bad, "Keep bad frames in monitor mode");
98
99static int modparam_mon_keep_badplcp;
100module_param_named(mon_keep_badplcp, modparam_mon_keep_bad, int, 0444);
101MODULE_PARM_DESC(mon_keep_badplcp, "Keep frames with bad PLCP in monitor mode");
102
103static int modparam_hwpctl; 95static int modparam_hwpctl;
104module_param_named(hwpctl, modparam_hwpctl, int, 0444); 96module_param_named(hwpctl, modparam_hwpctl, int, 0444);
105MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)"); 97MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)");
@@ -561,15 +553,10 @@ static void b43_write_mac_bssid_templates(struct b43_wldev *dev)
561 } 553 }
562} 554}
563 555
564static void b43_upload_card_macaddress(struct b43_wldev *dev, 556static void b43_upload_card_macaddress(struct b43_wldev *dev)
565 const u8 * mac_addr)
566{ 557{
567 if (mac_addr)
568 memcpy(dev->wl->mac_addr, mac_addr, ETH_ALEN);
569 else
570 memset(dev->wl->mac_addr, 0, ETH_ALEN);
571 b43_write_mac_bssid_templates(dev); 558 b43_write_mac_bssid_templates(dev);
572 b43_macfilter_set(dev, B43_MACFILTER_SELF, mac_addr); 559 b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr);
573} 560}
574 561
575static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) 562static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time)
@@ -2052,33 +2039,25 @@ static void b43_adjust_opmode(struct b43_wldev *dev)
2052 ctl &= ~B43_MACCTL_KEEP_BADPLCP; 2039 ctl &= ~B43_MACCTL_KEEP_BADPLCP;
2053 ctl &= ~B43_MACCTL_KEEP_BAD; 2040 ctl &= ~B43_MACCTL_KEEP_BAD;
2054 ctl &= ~B43_MACCTL_PROMISC; 2041 ctl &= ~B43_MACCTL_PROMISC;
2042 ctl &= ~B43_MACCTL_BEACPROMISC;
2055 ctl |= B43_MACCTL_INFRA; 2043 ctl |= B43_MACCTL_INFRA;
2056 2044
2057 if (wl->operating) { 2045 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP))
2058 switch (wl->if_type) { 2046 ctl |= B43_MACCTL_AP;
2059 case IEEE80211_IF_TYPE_AP: 2047 else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS))
2060 ctl |= B43_MACCTL_AP; 2048 ctl &= ~B43_MACCTL_INFRA;
2061 break; 2049
2062 case IEEE80211_IF_TYPE_IBSS: 2050 if (wl->filter_flags & FIF_CONTROL)
2063 ctl &= ~B43_MACCTL_INFRA;
2064 break;
2065 case IEEE80211_IF_TYPE_STA:
2066 case IEEE80211_IF_TYPE_MNTR:
2067 case IEEE80211_IF_TYPE_WDS:
2068 break;
2069 default:
2070 B43_WARN_ON(1);
2071 }
2072 }
2073 if (wl->monitor) {
2074 ctl |= B43_MACCTL_KEEP_CTL; 2051 ctl |= B43_MACCTL_KEEP_CTL;
2075 if (modparam_mon_keep_bad) 2052 if (wl->filter_flags & FIF_FCSFAIL)
2076 ctl |= B43_MACCTL_KEEP_BAD; 2053 ctl |= B43_MACCTL_KEEP_BAD;
2077 if (modparam_mon_keep_badplcp) 2054 if (wl->filter_flags & FIF_PLCPFAIL)
2078 ctl |= B43_MACCTL_KEEP_BADPLCP; 2055 ctl |= B43_MACCTL_KEEP_BADPLCP;
2079 } 2056 if (wl->filter_flags & FIF_PROMISC_IN_BSS)
2080 if (wl->promisc)
2081 ctl |= B43_MACCTL_PROMISC; 2057 ctl |= B43_MACCTL_PROMISC;
2058 if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC)
2059 ctl |= B43_MACCTL_BEACPROMISC;
2060
2082 /* Workaround: On old hardware the HW-MAC-address-filter 2061 /* Workaround: On old hardware the HW-MAC-address-filter
2083 * doesn't work properly, so always run promisc in filter 2062 * doesn't work properly, so always run promisc in filter
2084 * it in software. */ 2063 * it in software. */
@@ -2254,9 +2233,6 @@ static int b43_chip_init(struct b43_wldev *dev)
2254 & ~B43_MACCTL_INFRA); 2233 & ~B43_MACCTL_INFRA);
2255 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) 2234 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
2256 | B43_MACCTL_INFRA); 2235 | B43_MACCTL_INFRA);
2257 /* Let beacons come through */
2258 b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)
2259 | B43_MACCTL_BEACPROMISC);
2260 2236
2261 if (b43_using_pio(dev)) { 2237 if (b43_using_pio(dev)) {
2262 b43_write32(dev, 0x0210, 0x00000100); 2238 b43_write32(dev, 0x0210, 0x00000100);
@@ -2899,9 +2875,9 @@ static int b43_dev_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf)
2899 return err; 2875 return err;
2900} 2876}
2901 2877
2902static int b43_dev_set_key(struct ieee80211_hw *hw, 2878static int b43_dev_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2903 set_key_cmd cmd, const u8 *local_addr, 2879 const u8 *local_addr, const u8 *addr,
2904 const u8 *addr, struct ieee80211_key_conf *key) 2880 struct ieee80211_key_conf *key)
2905{ 2881{
2906 struct b43_wl *wl = hw_to_b43_wl(hw); 2882 struct b43_wl *wl = hw_to_b43_wl(hw);
2907 struct b43_wldev *dev = wl->current_dev; 2883 struct b43_wldev *dev = wl->current_dev;
@@ -3003,21 +2979,40 @@ out:
3003 return err; 2979 return err;
3004} 2980}
3005 2981
3006static void b43_set_multicast_list(struct ieee80211_hw *hw, 2982static void b43_configure_filter(struct ieee80211_hw *hw,
3007 unsigned short netflags, int mc_count) 2983 unsigned int changed, unsigned int *fflags,
2984 int mc_count, struct dev_addr_list *mc_list)
3008{ 2985{
3009 struct b43_wl *wl = hw_to_b43_wl(hw); 2986 struct b43_wl *wl = hw_to_b43_wl(hw);
3010 struct b43_wldev *dev = wl->current_dev; 2987 struct b43_wldev *dev = wl->current_dev;
3011 unsigned long flags; 2988 unsigned long flags;
3012 2989
3013 if (!dev) 2990 if (!dev) {
2991 *fflags = 0;
3014 return; 2992 return;
3015 spin_lock_irqsave(&wl->irq_lock, flags);
3016 if (wl->promisc != !!(netflags & IFF_PROMISC)) {
3017 wl->promisc = !!(netflags & IFF_PROMISC);
3018 if (b43_status(dev) >= B43_STAT_INITIALIZED)
3019 b43_adjust_opmode(dev);
3020 } 2993 }
2994
2995 spin_lock_irqsave(&wl->irq_lock, flags);
2996 *fflags &= FIF_PROMISC_IN_BSS |
2997 FIF_ALLMULTI |
2998 FIF_FCSFAIL |
2999 FIF_PLCPFAIL |
3000 FIF_CONTROL |
3001 FIF_OTHER_BSS |
3002 FIF_BCN_PRBRESP_PROMISC;
3003
3004 changed &= FIF_PROMISC_IN_BSS |
3005 FIF_ALLMULTI |
3006 FIF_FCSFAIL |
3007 FIF_PLCPFAIL |
3008 FIF_CONTROL |
3009 FIF_OTHER_BSS |
3010 FIF_BCN_PRBRESP_PROMISC;
3011
3012 wl->filter_flags = *fflags;
3013
3014 if (changed && b43_status(dev) >= B43_STAT_INITIALIZED)
3015 b43_adjust_opmode(dev);
3021 spin_unlock_irqrestore(&wl->irq_lock, flags); 3016 spin_unlock_irqrestore(&wl->irq_lock, flags);
3022} 3017}
3023 3018
@@ -3032,21 +3027,19 @@ static int b43_config_interface(struct ieee80211_hw *hw,
3032 return -ENODEV; 3027 return -ENODEV;
3033 mutex_lock(&wl->mutex); 3028 mutex_lock(&wl->mutex);
3034 spin_lock_irqsave(&wl->irq_lock, flags); 3029 spin_lock_irqsave(&wl->irq_lock, flags);
3035 if (conf->type != IEEE80211_IF_TYPE_MNTR) { 3030 B43_WARN_ON(wl->if_id != if_id);
3036 B43_WARN_ON(wl->if_id != if_id); 3031 if (conf->bssid)
3037 if (conf->bssid) 3032 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
3038 memcpy(wl->bssid, conf->bssid, ETH_ALEN); 3033 else
3039 else 3034 memset(wl->bssid, 0, ETH_ALEN);
3040 memset(wl->bssid, 0, ETH_ALEN); 3035 if (b43_status(dev) >= B43_STAT_INITIALIZED) {
3041 if (b43_status(dev) >= B43_STAT_INITIALIZED) { 3036 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
3042 if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP)) { 3037 B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
3043 B43_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP); 3038 b43_set_ssid(dev, conf->ssid, conf->ssid_len);
3044 b43_set_ssid(dev, conf->ssid, conf->ssid_len); 3039 if (conf->beacon)
3045 if (conf->beacon) 3040 b43_refresh_templates(dev, conf->beacon);
3046 b43_refresh_templates(dev, conf->beacon);
3047 }
3048 b43_write_mac_bssid_templates(dev);
3049 } 3041 }
3042 b43_write_mac_bssid_templates(dev);
3050 } 3043 }
3051 spin_unlock_irqrestore(&wl->irq_lock, flags); 3044 spin_unlock_irqrestore(&wl->irq_lock, flags);
3052 mutex_unlock(&wl->mutex); 3045 mutex_unlock(&wl->mutex);
@@ -3472,7 +3465,8 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
3472 3465
3473 ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ 3466 ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */
3474 memset(wl->bssid, 0, ETH_ALEN); 3467 memset(wl->bssid, 0, ETH_ALEN);
3475 b43_upload_card_macaddress(dev, NULL); 3468 memset(wl->mac_addr, 0, ETH_ALEN);
3469 b43_upload_card_macaddress(dev);
3476 b43_security_init(dev); 3470 b43_security_init(dev);
3477 b43_rng_init(wl); 3471 b43_rng_init(wl);
3478 3472
@@ -3502,21 +3496,80 @@ static int b43_add_interface(struct ieee80211_hw *hw,
3502 struct b43_wldev *dev; 3496 struct b43_wldev *dev;
3503 unsigned long flags; 3497 unsigned long flags;
3504 int err = -EOPNOTSUPP; 3498 int err = -EOPNOTSUPP;
3505 int did_init = 0; 3499
3500 /* TODO: allow WDS/AP devices to coexist */
3501
3502 if (conf->type != IEEE80211_IF_TYPE_AP &&
3503 conf->type != IEEE80211_IF_TYPE_STA &&
3504 conf->type != IEEE80211_IF_TYPE_WDS &&
3505 conf->type != IEEE80211_IF_TYPE_IBSS)
3506 return -EOPNOTSUPP;
3506 3507
3507 mutex_lock(&wl->mutex); 3508 mutex_lock(&wl->mutex);
3508 if ((conf->type != IEEE80211_IF_TYPE_MNTR) && wl->operating) 3509 if (wl->operating)
3509 goto out_mutex_unlock; 3510 goto out_mutex_unlock;
3510 3511
3511 b43dbg(wl, "Adding Interface type %d\n", conf->type); 3512 b43dbg(wl, "Adding Interface type %d\n", conf->type);
3512 3513
3513 dev = wl->current_dev; 3514 dev = wl->current_dev;
3515 wl->operating = 1;
3516 wl->if_id = conf->if_id;
3517 wl->if_type = conf->type;
3518 memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN);
3519
3520 spin_lock_irqsave(&wl->irq_lock, flags);
3521 b43_adjust_opmode(dev);
3522 b43_upload_card_macaddress(dev);
3523 spin_unlock_irqrestore(&wl->irq_lock, flags);
3524
3525 err = 0;
3526 out_mutex_unlock:
3527 mutex_unlock(&wl->mutex);
3528
3529 return err;
3530}
3531
3532static void b43_remove_interface(struct ieee80211_hw *hw,
3533 struct ieee80211_if_init_conf *conf)
3534{
3535 struct b43_wl *wl = hw_to_b43_wl(hw);
3536 struct b43_wldev *dev = wl->current_dev;
3537 unsigned long flags;
3538
3539 b43dbg(wl, "Removing Interface type %d\n", conf->type);
3540
3541 mutex_lock(&wl->mutex);
3542
3543 B43_WARN_ON(!wl->operating);
3544 B43_WARN_ON(wl->if_id != conf->if_id);
3545
3546 wl->operating = 0;
3547
3548 spin_lock_irqsave(&wl->irq_lock, flags);
3549 b43_adjust_opmode(dev);
3550 memset(wl->mac_addr, 0, ETH_ALEN);
3551 b43_upload_card_macaddress(dev);
3552 spin_unlock_irqrestore(&wl->irq_lock, flags);
3553
3554 mutex_unlock(&wl->mutex);
3555}
3556
3557static int b43_start(struct ieee80211_hw *hw)
3558{
3559 struct b43_wl *wl = hw_to_b43_wl(hw);
3560 struct b43_wldev *dev = wl->current_dev;
3561 int did_init = 0;
3562 int err;
3563
3564 mutex_lock(&wl->mutex);
3565
3514 if (b43_status(dev) < B43_STAT_INITIALIZED) { 3566 if (b43_status(dev) < B43_STAT_INITIALIZED) {
3515 err = b43_wireless_core_init(dev); 3567 err = b43_wireless_core_init(dev);
3516 if (err) 3568 if (err)
3517 goto out_mutex_unlock; 3569 goto out_mutex_unlock;
3518 did_init = 1; 3570 did_init = 1;
3519 } 3571 }
3572
3520 if (b43_status(dev) < B43_STAT_STARTED) { 3573 if (b43_status(dev) < B43_STAT_STARTED) {
3521 err = b43_wireless_core_start(dev); 3574 err = b43_wireless_core_start(dev);
3522 if (err) { 3575 if (err) {
@@ -3526,59 +3579,21 @@ static int b43_add_interface(struct ieee80211_hw *hw,
3526 } 3579 }
3527 } 3580 }
3528 3581
3529 spin_lock_irqsave(&wl->irq_lock, flags); 3582 out_mutex_unlock:
3530 switch (conf->type) {
3531 case IEEE80211_IF_TYPE_MNTR:
3532 wl->monitor++;
3533 break;
3534 default:
3535 wl->operating = 1;
3536 wl->if_id = conf->if_id;
3537 wl->if_type = conf->type;
3538 b43_upload_card_macaddress(dev, conf->mac_addr);
3539 }
3540 b43_adjust_opmode(dev);
3541 spin_unlock_irqrestore(&wl->irq_lock, flags);
3542
3543 err = 0;
3544 out_mutex_unlock:
3545 mutex_unlock(&wl->mutex); 3583 mutex_unlock(&wl->mutex);
3546 3584
3547 return err; 3585 return err;
3548} 3586}
3549 3587
3550static void b43_remove_interface(struct ieee80211_hw *hw, 3588void b43_stop(struct ieee80211_hw *hw)
3551 struct ieee80211_if_init_conf *conf)
3552{ 3589{
3553 struct b43_wl *wl = hw_to_b43_wl(hw); 3590 struct b43_wl *wl = hw_to_b43_wl(hw);
3554 struct b43_wldev *dev; 3591 struct b43_wldev *dev = wl->current_dev;
3555 unsigned long flags;
3556
3557 b43dbg(wl, "Removing Interface type %d\n", conf->type);
3558 3592
3559 mutex_lock(&wl->mutex); 3593 mutex_lock(&wl->mutex);
3560 if (conf->type == IEEE80211_IF_TYPE_MNTR) { 3594 if (b43_status(dev) >= B43_STAT_STARTED)
3561 wl->monitor--; 3595 b43_wireless_core_stop(dev);
3562 B43_WARN_ON(wl->monitor < 0); 3596 b43_wireless_core_exit(dev);
3563 } else {
3564 B43_WARN_ON(!wl->operating);
3565 wl->operating = 0;
3566 }
3567
3568 dev = wl->current_dev;
3569 if (!wl->operating && wl->monitor == 0) {
3570 /* No interface left. */
3571 if (b43_status(dev) >= B43_STAT_STARTED)
3572 b43_wireless_core_stop(dev);
3573 b43_wireless_core_exit(dev);
3574 } else {
3575 /* Just monitor interfaces left. */
3576 spin_lock_irqsave(&wl->irq_lock, flags);
3577 b43_adjust_opmode(dev);
3578 if (!wl->operating)
3579 b43_upload_card_macaddress(dev, NULL);
3580 spin_unlock_irqrestore(&wl->irq_lock, flags);
3581 }
3582 mutex_unlock(&wl->mutex); 3597 mutex_unlock(&wl->mutex);
3583} 3598}
3584 3599
@@ -3589,10 +3604,12 @@ static const struct ieee80211_ops b43_hw_ops = {
3589 .remove_interface = b43_remove_interface, 3604 .remove_interface = b43_remove_interface,
3590 .config = b43_dev_config, 3605 .config = b43_dev_config,
3591 .config_interface = b43_config_interface, 3606 .config_interface = b43_config_interface,
3592 .set_multicast_list = b43_set_multicast_list, 3607 .configure_filter = b43_configure_filter,
3593 .set_key = b43_dev_set_key, 3608 .set_key = b43_dev_set_key,
3594 .get_stats = b43_get_stats, 3609 .get_stats = b43_get_stats,
3595 .get_tx_stats = b43_get_tx_stats, 3610 .get_tx_stats = b43_get_tx_stats,
3611 .start = b43_start,
3612 .stop = b43_stop,
3596}; 3613};
3597 3614
3598/* Hard-reset the chip. Do not call this directly. 3615/* Hard-reset the chip. Do not call this directly.
@@ -3930,8 +3947,7 @@ static int b43_wireless_init(struct ssb_device *dev)
3930 } 3947 }
3931 3948
3932 /* fill hw info */ 3949 /* fill hw info */
3933 hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE | 3950 hw->flags = IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE;
3934 IEEE80211_HW_MONITOR_DURING_OPER;
3935 hw->max_signal = 100; 3951 hw->max_signal = 100;
3936 hw->max_rssi = -110; 3952 hw->max_rssi = -110;
3937 hw->max_noise = -110; 3953 hw->max_noise = -110;