diff options
author | David S. Miller <davem@davemloft.net> | 2009-12-30 16:51:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-12-30 16:51:29 -0500 |
commit | 3a999e6eb5d277cd6a321dcda3fc43c3d9e4e4b8 (patch) | |
tree | b0ad8d03710ee556e97515ba1c949233859391ce | |
parent | 6cd9b49d7328c4656bfc17fcb47fb814955d40d2 (diff) | |
parent | 891dc5e73783eeabd2a704a9425e2a199b39c9f9 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
99 files changed, 4015 insertions, 3119 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 870d190fe617..5b5db085fbf0 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -88,27 +88,6 @@ Who: Luis R. Rodriguez <lrodriguez@atheros.com> | |||
88 | 88 | ||
89 | --------------------------- | 89 | --------------------------- |
90 | 90 | ||
91 | What: CONFIG_WIRELESS_OLD_REGULATORY - old static regulatory information | ||
92 | When: March 2010 / desktop catchup | ||
93 | |||
94 | Why: The old regulatory infrastructure has been replaced with a new one | ||
95 | which does not require statically defined regulatory domains. We do | ||
96 | not want to keep static regulatory domains in the kernel due to the | ||
97 | the dynamic nature of regulatory law and localization. We kept around | ||
98 | the old static definitions for the regulatory domains of: | ||
99 | |||
100 | * US | ||
101 | * JP | ||
102 | * EU | ||
103 | |||
104 | and used by default the US when CONFIG_WIRELESS_OLD_REGULATORY was | ||
105 | set. We will remove this option once the standard Linux desktop catches | ||
106 | up with the new userspace APIs we have implemented. | ||
107 | |||
108 | Who: Luis R. Rodriguez <lrodriguez@atheros.com> | ||
109 | |||
110 | --------------------------- | ||
111 | |||
112 | What: dev->power.power_state | 91 | What: dev->power.power_state |
113 | When: July 2007 | 92 | When: July 2007 |
114 | Why: Broken design for runtime control over driver power states, confusing | 93 | Why: Broken design for runtime control over driver power states, confusing |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 39410016b4ff..e1f04bb437e3 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1400,15 +1400,15 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, | |||
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | static int adm8211_add_interface(struct ieee80211_hw *dev, | 1402 | static int adm8211_add_interface(struct ieee80211_hw *dev, |
1403 | struct ieee80211_if_init_conf *conf) | 1403 | struct ieee80211_vif *vif) |
1404 | { | 1404 | { |
1405 | struct adm8211_priv *priv = dev->priv; | 1405 | struct adm8211_priv *priv = dev->priv; |
1406 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1406 | if (priv->mode != NL80211_IFTYPE_MONITOR) |
1407 | return -EOPNOTSUPP; | 1407 | return -EOPNOTSUPP; |
1408 | 1408 | ||
1409 | switch (conf->type) { | 1409 | switch (vif->type) { |
1410 | case NL80211_IFTYPE_STATION: | 1410 | case NL80211_IFTYPE_STATION: |
1411 | priv->mode = conf->type; | 1411 | priv->mode = vif->type; |
1412 | break; | 1412 | break; |
1413 | default: | 1413 | default: |
1414 | return -EOPNOTSUPP; | 1414 | return -EOPNOTSUPP; |
@@ -1416,8 +1416,8 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, | |||
1416 | 1416 | ||
1417 | ADM8211_IDLE(); | 1417 | ADM8211_IDLE(); |
1418 | 1418 | ||
1419 | ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr)); | 1419 | ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)vif->addr)); |
1420 | ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 1420 | ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
1421 | 1421 | ||
1422 | adm8211_update_mode(dev); | 1422 | adm8211_update_mode(dev); |
1423 | 1423 | ||
@@ -1427,7 +1427,7 @@ static int adm8211_add_interface(struct ieee80211_hw *dev, | |||
1427 | } | 1427 | } |
1428 | 1428 | ||
1429 | static void adm8211_remove_interface(struct ieee80211_hw *dev, | 1429 | static void adm8211_remove_interface(struct ieee80211_hw *dev, |
1430 | struct ieee80211_if_init_conf *conf) | 1430 | struct ieee80211_vif *vif) |
1431 | { | 1431 | { |
1432 | struct adm8211_priv *priv = dev->priv; | 1432 | struct adm8211_priv *priv = dev->priv; |
1433 | priv->mode = NL80211_IFTYPE_MONITOR; | 1433 | priv->mode = NL80211_IFTYPE_MONITOR; |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 2517364d3ebe..0fb419936dff 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -1789,7 +1789,7 @@ static void at76_mac80211_stop(struct ieee80211_hw *hw) | |||
1789 | } | 1789 | } |
1790 | 1790 | ||
1791 | static int at76_add_interface(struct ieee80211_hw *hw, | 1791 | static int at76_add_interface(struct ieee80211_hw *hw, |
1792 | struct ieee80211_if_init_conf *conf) | 1792 | struct ieee80211_vif *vif) |
1793 | { | 1793 | { |
1794 | struct at76_priv *priv = hw->priv; | 1794 | struct at76_priv *priv = hw->priv; |
1795 | int ret = 0; | 1795 | int ret = 0; |
@@ -1798,7 +1798,7 @@ static int at76_add_interface(struct ieee80211_hw *hw, | |||
1798 | 1798 | ||
1799 | mutex_lock(&priv->mtx); | 1799 | mutex_lock(&priv->mtx); |
1800 | 1800 | ||
1801 | switch (conf->type) { | 1801 | switch (vif->type) { |
1802 | case NL80211_IFTYPE_STATION: | 1802 | case NL80211_IFTYPE_STATION: |
1803 | priv->iw_mode = IW_MODE_INFRA; | 1803 | priv->iw_mode = IW_MODE_INFRA; |
1804 | break; | 1804 | break; |
@@ -1814,7 +1814,7 @@ exit: | |||
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | static void at76_remove_interface(struct ieee80211_hw *hw, | 1816 | static void at76_remove_interface(struct ieee80211_hw *hw, |
1817 | struct ieee80211_if_init_conf *conf) | 1817 | struct ieee80211_vif *vif) |
1818 | { | 1818 | { |
1819 | at76_dbg(DBG_MAC80211, "%s()", __func__); | 1819 | at76_dbg(DBG_MAC80211, "%s()", __func__); |
1820 | } | 1820 | } |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 20f04ab2b13e..4d27f7f67c76 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1939,7 +1939,7 @@ err_free: | |||
1939 | } | 1939 | } |
1940 | 1940 | ||
1941 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, | 1941 | static int ar9170_op_add_interface(struct ieee80211_hw *hw, |
1942 | struct ieee80211_if_init_conf *conf) | 1942 | struct ieee80211_vif *vif) |
1943 | { | 1943 | { |
1944 | struct ar9170 *ar = hw->priv; | 1944 | struct ar9170 *ar = hw->priv; |
1945 | struct ath_common *common = &ar->common; | 1945 | struct ath_common *common = &ar->common; |
@@ -1952,8 +1952,8 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1952 | goto unlock; | 1952 | goto unlock; |
1953 | } | 1953 | } |
1954 | 1954 | ||
1955 | ar->vif = conf->vif; | 1955 | ar->vif = vif; |
1956 | memcpy(common->macaddr, conf->mac_addr, ETH_ALEN); | 1956 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
1957 | 1957 | ||
1958 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { | 1958 | if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { |
1959 | ar->rx_software_decryption = true; | 1959 | ar->rx_software_decryption = true; |
@@ -1973,7 +1973,7 @@ unlock: | |||
1973 | } | 1973 | } |
1974 | 1974 | ||
1975 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, | 1975 | static void ar9170_op_remove_interface(struct ieee80211_hw *hw, |
1976 | struct ieee80211_if_init_conf *conf) | 1976 | struct ieee80211_vif *vif) |
1977 | { | 1977 | { |
1978 | struct ar9170 *ar = hw->priv; | 1978 | struct ar9170 *ar = hw->priv; |
1979 | 1979 | ||
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index a4c086f069b1..fdfaf0f618f1 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -225,9 +225,9 @@ static int ath5k_reset_wake(struct ath5k_softc *sc); | |||
225 | static int ath5k_start(struct ieee80211_hw *hw); | 225 | static int ath5k_start(struct ieee80211_hw *hw); |
226 | static void ath5k_stop(struct ieee80211_hw *hw); | 226 | static void ath5k_stop(struct ieee80211_hw *hw); |
227 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 227 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
228 | struct ieee80211_if_init_conf *conf); | 228 | struct ieee80211_vif *vif); |
229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | 229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, |
230 | struct ieee80211_if_init_conf *conf); | 230 | struct ieee80211_vif *vif); |
231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | 232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, |
233 | int mc_count, struct dev_addr_list *mc_list); | 233 | int mc_count, struct dev_addr_list *mc_list); |
@@ -1903,17 +1903,6 @@ accept: | |||
1903 | rxs->noise = sc->ah->ah_noise_floor; | 1903 | rxs->noise = sc->ah->ah_noise_floor; |
1904 | rxs->signal = rxs->noise + rs.rs_rssi; | 1904 | rxs->signal = rxs->noise + rs.rs_rssi; |
1905 | 1905 | ||
1906 | /* An rssi of 35 indicates you should be able use | ||
1907 | * 54 Mbps reliably. A more elaborate scheme can be used | ||
1908 | * here but it requires a map of SNR/throughput for each | ||
1909 | * possible mode used */ | ||
1910 | rxs->qual = rs.rs_rssi * 100 / 35; | ||
1911 | |||
1912 | /* rssi can be more than 35 though, anything above that | ||
1913 | * should be considered at 100% */ | ||
1914 | if (rxs->qual > 100) | ||
1915 | rxs->qual = 100; | ||
1916 | |||
1917 | rxs->antenna = rs.rs_antenna; | 1906 | rxs->antenna = rs.rs_antenna; |
1918 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); | 1907 | rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); |
1919 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); | 1908 | rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); |
@@ -2381,6 +2370,9 @@ ath5k_init(struct ath5k_softc *sc) | |||
2381 | */ | 2370 | */ |
2382 | ath5k_stop_locked(sc); | 2371 | ath5k_stop_locked(sc); |
2383 | 2372 | ||
2373 | /* Set PHY calibration interval */ | ||
2374 | ah->ah_cal_intval = ath5k_calinterval; | ||
2375 | |||
2384 | /* | 2376 | /* |
2385 | * The basic interface to setting the hardware in a good | 2377 | * The basic interface to setting the hardware in a good |
2386 | * state is ``reset''. On return the hardware is known to | 2378 | * state is ``reset''. On return the hardware is known to |
@@ -2408,10 +2400,6 @@ ath5k_init(struct ath5k_softc *sc) | |||
2408 | 2400 | ||
2409 | /* Set ack to be sent at low bit-rates */ | 2401 | /* Set ack to be sent at low bit-rates */ |
2410 | ath5k_hw_set_ack_bitrate_high(ah, false); | 2402 | ath5k_hw_set_ack_bitrate_high(ah, false); |
2411 | |||
2412 | /* Set PHY calibration inteval */ | ||
2413 | ah->ah_cal_intval = ath5k_calinterval; | ||
2414 | |||
2415 | ret = 0; | 2403 | ret = 0; |
2416 | done: | 2404 | done: |
2417 | mmiowb(); | 2405 | mmiowb(); |
@@ -2785,7 +2773,7 @@ static void ath5k_stop(struct ieee80211_hw *hw) | |||
2785 | } | 2773 | } |
2786 | 2774 | ||
2787 | static int ath5k_add_interface(struct ieee80211_hw *hw, | 2775 | static int ath5k_add_interface(struct ieee80211_hw *hw, |
2788 | struct ieee80211_if_init_conf *conf) | 2776 | struct ieee80211_vif *vif) |
2789 | { | 2777 | { |
2790 | struct ath5k_softc *sc = hw->priv; | 2778 | struct ath5k_softc *sc = hw->priv; |
2791 | int ret; | 2779 | int ret; |
@@ -2796,22 +2784,22 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
2796 | goto end; | 2784 | goto end; |
2797 | } | 2785 | } |
2798 | 2786 | ||
2799 | sc->vif = conf->vif; | 2787 | sc->vif = vif; |
2800 | 2788 | ||
2801 | switch (conf->type) { | 2789 | switch (vif->type) { |
2802 | case NL80211_IFTYPE_AP: | 2790 | case NL80211_IFTYPE_AP: |
2803 | case NL80211_IFTYPE_STATION: | 2791 | case NL80211_IFTYPE_STATION: |
2804 | case NL80211_IFTYPE_ADHOC: | 2792 | case NL80211_IFTYPE_ADHOC: |
2805 | case NL80211_IFTYPE_MESH_POINT: | 2793 | case NL80211_IFTYPE_MESH_POINT: |
2806 | case NL80211_IFTYPE_MONITOR: | 2794 | case NL80211_IFTYPE_MONITOR: |
2807 | sc->opmode = conf->type; | 2795 | sc->opmode = vif->type; |
2808 | break; | 2796 | break; |
2809 | default: | 2797 | default: |
2810 | ret = -EOPNOTSUPP; | 2798 | ret = -EOPNOTSUPP; |
2811 | goto end; | 2799 | goto end; |
2812 | } | 2800 | } |
2813 | 2801 | ||
2814 | ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); | 2802 | ath5k_hw_set_lladdr(sc->ah, vif->addr); |
2815 | ath5k_mode_setup(sc); | 2803 | ath5k_mode_setup(sc); |
2816 | 2804 | ||
2817 | ret = 0; | 2805 | ret = 0; |
@@ -2822,13 +2810,13 @@ end: | |||
2822 | 2810 | ||
2823 | static void | 2811 | static void |
2824 | ath5k_remove_interface(struct ieee80211_hw *hw, | 2812 | ath5k_remove_interface(struct ieee80211_hw *hw, |
2825 | struct ieee80211_if_init_conf *conf) | 2813 | struct ieee80211_vif *vif) |
2826 | { | 2814 | { |
2827 | struct ath5k_softc *sc = hw->priv; | 2815 | struct ath5k_softc *sc = hw->priv; |
2828 | u8 mac[ETH_ALEN] = {}; | 2816 | u8 mac[ETH_ALEN] = {}; |
2829 | 2817 | ||
2830 | mutex_lock(&sc->lock); | 2818 | mutex_lock(&sc->lock); |
2831 | if (sc->vif != conf->vif) | 2819 | if (sc->vif != vif) |
2832 | goto end; | 2820 | goto end; |
2833 | 2821 | ||
2834 | ath5k_hw_set_lladdr(sc->ah, mac); | 2822 | ath5k_hw_set_lladdr(sc->ah, mac); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 0c87771383f0..e185479e295e 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h | |||
@@ -77,6 +77,9 @@ | |||
77 | #define ATH9K_TXERR_XTXOP 0x08 | 77 | #define ATH9K_TXERR_XTXOP 0x08 |
78 | #define ATH9K_TXERR_TIMER_EXPIRED 0x10 | 78 | #define ATH9K_TXERR_TIMER_EXPIRED 0x10 |
79 | #define ATH9K_TX_ACKED 0x20 | 79 | #define ATH9K_TX_ACKED 0x20 |
80 | #define ATH9K_TXERR_MASK \ | ||
81 | (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \ | ||
82 | ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED) | ||
80 | 83 | ||
81 | #define ATH9K_TX_BA 0x01 | 84 | #define ATH9K_TX_BA 0x01 |
82 | #define ATH9K_TX_PWRMGMT 0x02 | 85 | #define ATH9K_TX_PWRMGMT 0x02 |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3f5b887d0fcd..79fbbda15493 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2504,6 +2504,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2504 | return; /* another wiphy still in use */ | 2504 | return; /* another wiphy still in use */ |
2505 | } | 2505 | } |
2506 | 2506 | ||
2507 | /* Ensure HW is awake when we try to shut it down. */ | ||
2508 | ath9k_ps_wakeup(sc); | ||
2509 | |||
2507 | if (ah->btcoex_hw.enabled) { | 2510 | if (ah->btcoex_hw.enabled) { |
2508 | ath9k_hw_btcoex_disable(ah); | 2511 | ath9k_hw_btcoex_disable(ah); |
2509 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 2512 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
@@ -2524,6 +2527,9 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2524 | /* disable HAL and put h/w to sleep */ | 2527 | /* disable HAL and put h/w to sleep */ |
2525 | ath9k_hw_disable(ah); | 2528 | ath9k_hw_disable(ah); |
2526 | ath9k_hw_configpcipowersave(ah, 1, 1); | 2529 | ath9k_hw_configpcipowersave(ah, 1, 1); |
2530 | ath9k_ps_restore(sc); | ||
2531 | |||
2532 | /* Finally, put the chip in FULL SLEEP mode */ | ||
2527 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | 2533 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); |
2528 | 2534 | ||
2529 | sc->sc_flags |= SC_OP_INVALID; | 2535 | sc->sc_flags |= SC_OP_INVALID; |
@@ -2534,12 +2540,12 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2534 | } | 2540 | } |
2535 | 2541 | ||
2536 | static int ath9k_add_interface(struct ieee80211_hw *hw, | 2542 | static int ath9k_add_interface(struct ieee80211_hw *hw, |
2537 | struct ieee80211_if_init_conf *conf) | 2543 | struct ieee80211_vif *vif) |
2538 | { | 2544 | { |
2539 | struct ath_wiphy *aphy = hw->priv; | 2545 | struct ath_wiphy *aphy = hw->priv; |
2540 | struct ath_softc *sc = aphy->sc; | 2546 | struct ath_softc *sc = aphy->sc; |
2541 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2547 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2542 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2548 | struct ath_vif *avp = (void *)vif->drv_priv; |
2543 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; | 2549 | enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; |
2544 | int ret = 0; | 2550 | int ret = 0; |
2545 | 2551 | ||
@@ -2551,7 +2557,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2551 | goto out; | 2557 | goto out; |
2552 | } | 2558 | } |
2553 | 2559 | ||
2554 | switch (conf->type) { | 2560 | switch (vif->type) { |
2555 | case NL80211_IFTYPE_STATION: | 2561 | case NL80211_IFTYPE_STATION: |
2556 | ic_opmode = NL80211_IFTYPE_STATION; | 2562 | ic_opmode = NL80211_IFTYPE_STATION; |
2557 | break; | 2563 | break; |
@@ -2562,11 +2568,11 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2562 | ret = -ENOBUFS; | 2568 | ret = -ENOBUFS; |
2563 | goto out; | 2569 | goto out; |
2564 | } | 2570 | } |
2565 | ic_opmode = conf->type; | 2571 | ic_opmode = vif->type; |
2566 | break; | 2572 | break; |
2567 | default: | 2573 | default: |
2568 | ath_print(common, ATH_DBG_FATAL, | 2574 | ath_print(common, ATH_DBG_FATAL, |
2569 | "Interface type %d not yet supported\n", conf->type); | 2575 | "Interface type %d not yet supported\n", vif->type); |
2570 | ret = -EOPNOTSUPP; | 2576 | ret = -EOPNOTSUPP; |
2571 | goto out; | 2577 | goto out; |
2572 | } | 2578 | } |
@@ -2598,18 +2604,18 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
2598 | * Enable MIB interrupts when there are hardware phy counters. | 2604 | * Enable MIB interrupts when there are hardware phy counters. |
2599 | * Note we only do this (at the moment) for station mode. | 2605 | * Note we only do this (at the moment) for station mode. |
2600 | */ | 2606 | */ |
2601 | if ((conf->type == NL80211_IFTYPE_STATION) || | 2607 | if ((vif->type == NL80211_IFTYPE_STATION) || |
2602 | (conf->type == NL80211_IFTYPE_ADHOC) || | 2608 | (vif->type == NL80211_IFTYPE_ADHOC) || |
2603 | (conf->type == NL80211_IFTYPE_MESH_POINT)) { | 2609 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { |
2604 | sc->imask |= ATH9K_INT_MIB; | 2610 | sc->imask |= ATH9K_INT_MIB; |
2605 | sc->imask |= ATH9K_INT_TSFOOR; | 2611 | sc->imask |= ATH9K_INT_TSFOOR; |
2606 | } | 2612 | } |
2607 | 2613 | ||
2608 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); | 2614 | ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); |
2609 | 2615 | ||
2610 | if (conf->type == NL80211_IFTYPE_AP || | 2616 | if (vif->type == NL80211_IFTYPE_AP || |
2611 | conf->type == NL80211_IFTYPE_ADHOC || | 2617 | vif->type == NL80211_IFTYPE_ADHOC || |
2612 | conf->type == NL80211_IFTYPE_MONITOR) | 2618 | vif->type == NL80211_IFTYPE_MONITOR) |
2613 | ath_start_ani(common); | 2619 | ath_start_ani(common); |
2614 | 2620 | ||
2615 | out: | 2621 | out: |
@@ -2618,12 +2624,12 @@ out: | |||
2618 | } | 2624 | } |
2619 | 2625 | ||
2620 | static void ath9k_remove_interface(struct ieee80211_hw *hw, | 2626 | static void ath9k_remove_interface(struct ieee80211_hw *hw, |
2621 | struct ieee80211_if_init_conf *conf) | 2627 | struct ieee80211_vif *vif) |
2622 | { | 2628 | { |
2623 | struct ath_wiphy *aphy = hw->priv; | 2629 | struct ath_wiphy *aphy = hw->priv; |
2624 | struct ath_softc *sc = aphy->sc; | 2630 | struct ath_softc *sc = aphy->sc; |
2625 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2631 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2626 | struct ath_vif *avp = (void *)conf->vif->drv_priv; | 2632 | struct ath_vif *avp = (void *)vif->drv_priv; |
2627 | int i; | 2633 | int i; |
2628 | 2634 | ||
2629 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); | 2635 | ath_print(common, ATH_DBG_CONFIG, "Detach Interface\n"); |
@@ -2637,14 +2643,16 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
2637 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || | 2643 | if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || |
2638 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || | 2644 | (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || |
2639 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { | 2645 | (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { |
2646 | ath9k_ps_wakeup(sc); | ||
2640 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | 2647 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
2641 | ath_beacon_return(sc, avp); | 2648 | ath_beacon_return(sc, avp); |
2649 | ath9k_ps_restore(sc); | ||
2642 | } | 2650 | } |
2643 | 2651 | ||
2644 | sc->sc_flags &= ~SC_OP_BEACONS; | 2652 | sc->sc_flags &= ~SC_OP_BEACONS; |
2645 | 2653 | ||
2646 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { | 2654 | for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { |
2647 | if (sc->beacon.bslot[i] == conf->vif) { | 2655 | if (sc->beacon.bslot[i] == vif) { |
2648 | printk(KERN_DEBUG "%s: vif had allocated beacon " | 2656 | printk(KERN_DEBUG "%s: vif had allocated beacon " |
2649 | "slot\n", __func__); | 2657 | "slot\n", __func__); |
2650 | sc->beacon.bslot[i] = NULL; | 2658 | sc->beacon.bslot[i] = NULL; |
@@ -3087,15 +3095,21 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
3087 | case IEEE80211_AMPDU_RX_STOP: | 3095 | case IEEE80211_AMPDU_RX_STOP: |
3088 | break; | 3096 | break; |
3089 | case IEEE80211_AMPDU_TX_START: | 3097 | case IEEE80211_AMPDU_TX_START: |
3098 | ath9k_ps_wakeup(sc); | ||
3090 | ath_tx_aggr_start(sc, sta, tid, ssn); | 3099 | ath_tx_aggr_start(sc, sta, tid, ssn); |
3091 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 3100 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
3101 | ath9k_ps_restore(sc); | ||
3092 | break; | 3102 | break; |
3093 | case IEEE80211_AMPDU_TX_STOP: | 3103 | case IEEE80211_AMPDU_TX_STOP: |
3104 | ath9k_ps_wakeup(sc); | ||
3094 | ath_tx_aggr_stop(sc, sta, tid); | 3105 | ath_tx_aggr_stop(sc, sta, tid); |
3095 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | 3106 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
3107 | ath9k_ps_restore(sc); | ||
3096 | break; | 3108 | break; |
3097 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3109 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
3110 | ath9k_ps_wakeup(sc); | ||
3098 | ath_tx_aggr_resume(sc, sta, tid); | 3111 | ath_tx_aggr_resume(sc, sta, tid); |
3112 | ath9k_ps_restore(sc); | ||
3099 | break; | 3113 | break; |
3100 | default: | 3114 | default: |
3101 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 3115 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 5321f735e5a0..f7af5ea54753 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -96,7 +96,7 @@ static void ath_pci_bt_coex_prep(struct ath_common *common) | |||
96 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); | 96 | pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); |
97 | } | 97 | } |
98 | 98 | ||
99 | const static struct ath_bus_ops ath_pci_bus_ops = { | 99 | static const struct ath_bus_ops ath_pci_bus_ops = { |
100 | .read_cachesize = ath_pci_read_cachesize, | 100 | .read_cachesize = ath_pci_read_cachesize, |
101 | .cleanup = ath_pci_cleanup, | 101 | .cleanup = ath_pci_cleanup, |
102 | .eeprom_read = ath_pci_eeprom_read, | 102 | .eeprom_read = ath_pci_eeprom_read, |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 1e813bbf474a..fa12b9060b0b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -2072,7 +2072,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2072 | &txq->axq_q, lastbf->list.prev); | 2072 | &txq->axq_q, lastbf->list.prev); |
2073 | 2073 | ||
2074 | txq->axq_depth--; | 2074 | txq->axq_depth--; |
2075 | txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_FILT); | 2075 | txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); |
2076 | txq->axq_tx_inprogress = false; | 2076 | txq->axq_tx_inprogress = false; |
2077 | spin_unlock_bh(&txq->axq_lock); | 2077 | spin_unlock_bh(&txq->axq_lock); |
2078 | 2078 | ||
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 64c12e1bced3..073be566d05e 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -3,6 +3,7 @@ config B43 | |||
3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA | 3 | depends on SSB_POSSIBLE && MAC80211 && HAS_DMA |
4 | select SSB | 4 | select SSB |
5 | select FW_LOADER | 5 | select FW_LOADER |
6 | select SSB_BLOCKIO | ||
6 | ---help--- | 7 | ---help--- |
7 | b43 is a driver for the Broadcom 43xx series wireless devices. | 8 | b43 is a driver for the Broadcom 43xx series wireless devices. |
8 | 9 | ||
@@ -78,14 +79,6 @@ config B43_SDIO | |||
78 | 79 | ||
79 | If unsure, say N. | 80 | If unsure, say N. |
80 | 81 | ||
81 | # Data transfers to the device via PIO | ||
82 | # This is only needed on PCMCIA and SDIO devices. All others can do DMA properly. | ||
83 | config B43_PIO | ||
84 | bool | ||
85 | depends on B43 && (B43_SDIO || B43_PCMCIA || B43_FORCE_PIO) | ||
86 | select SSB_BLOCKIO | ||
87 | default y | ||
88 | |||
89 | config B43_NPHY | 82 | config B43_NPHY |
90 | bool "Pre IEEE 802.11n support (BROKEN)" | 83 | bool "Pre IEEE 802.11n support (BROKEN)" |
91 | depends on B43 && EXPERIMENTAL && BROKEN | 84 | depends on B43 && EXPERIMENTAL && BROKEN |
@@ -137,12 +130,4 @@ config B43_DEBUG | |||
137 | for production use. | 130 | for production use. |
138 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. | 131 | Only say Y, if you are debugging a problem in the b43 driver sourcecode. |
139 | 132 | ||
140 | config B43_FORCE_PIO | ||
141 | bool "Force usage of PIO instead of DMA" | ||
142 | depends on B43 && B43_DEBUG | ||
143 | ---help--- | ||
144 | This will disable DMA and always enable PIO instead. | ||
145 | 133 | ||
146 | Say N! | ||
147 | This is only for debugging the PIO engine code. You do | ||
148 | _NOT_ want to enable this. | ||
diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile index 84772a2542dc..5e83b6f0a3a0 100644 --- a/drivers/net/wireless/b43/Makefile +++ b/drivers/net/wireless/b43/Makefile | |||
@@ -12,7 +12,7 @@ b43-y += xmit.o | |||
12 | b43-y += lo.o | 12 | b43-y += lo.o |
13 | b43-y += wa.o | 13 | b43-y += wa.o |
14 | b43-y += dma.o | 14 | b43-y += dma.o |
15 | b43-$(CONFIG_B43_PIO) += pio.o | 15 | b43-y += pio.o |
16 | b43-y += rfkill.o | 16 | b43-y += rfkill.o |
17 | b43-$(CONFIG_B43_LEDS) += leds.o | 17 | b43-$(CONFIG_B43_LEDS) += leds.o |
18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o | 18 | b43-$(CONFIG_B43_PCMCIA) += pcmcia.o |
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index fe3bf9491997..2f12a750bc98 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -821,11 +821,9 @@ struct b43_wl { | |||
821 | /* The device LEDs. */ | 821 | /* The device LEDs. */ |
822 | struct b43_leds leds; | 822 | struct b43_leds leds; |
823 | 823 | ||
824 | #ifdef CONFIG_B43_PIO | ||
825 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ | 824 | /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ |
826 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); | 825 | u8 pio_scratchspace[110] __attribute__((__aligned__(8))); |
827 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); | 826 | u8 pio_tailspace[4] __attribute__((__aligned__(8))); |
828 | #endif /* CONFIG_B43_PIO */ | ||
829 | }; | 827 | }; |
830 | 828 | ||
831 | static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) | 829 | static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) |
@@ -876,20 +874,9 @@ static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) | |||
876 | 874 | ||
877 | static inline bool b43_using_pio_transfers(struct b43_wldev *dev) | 875 | static inline bool b43_using_pio_transfers(struct b43_wldev *dev) |
878 | { | 876 | { |
879 | #ifdef CONFIG_B43_PIO | ||
880 | return dev->__using_pio_transfers; | 877 | return dev->__using_pio_transfers; |
881 | #else | ||
882 | return 0; | ||
883 | #endif | ||
884 | } | 878 | } |
885 | 879 | ||
886 | #ifdef CONFIG_B43_FORCE_PIO | ||
887 | # define B43_FORCE_PIO 1 | ||
888 | #else | ||
889 | # define B43_FORCE_PIO 0 | ||
890 | #endif | ||
891 | |||
892 | |||
893 | /* Message printing */ | 880 | /* Message printing */ |
894 | void b43info(struct b43_wl *wl, const char *fmt, ...) | 881 | void b43info(struct b43_wl *wl, const char *fmt, ...) |
895 | __attribute__ ((format(printf, 2, 3))); | 882 | __attribute__ ((format(printf, 2, 3))); |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 027be275e035..615af22c49fd 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -383,160 +383,44 @@ static inline | |||
383 | } | 383 | } |
384 | } | 384 | } |
385 | 385 | ||
386 | /* Check if a DMA region fits the device constraints. | ||
387 | * Returns true, if the region is OK for usage with this device. */ | ||
388 | static inline bool b43_dma_address_ok(struct b43_dmaring *ring, | ||
389 | dma_addr_t addr, size_t size) | ||
390 | { | ||
391 | switch (ring->type) { | ||
392 | case B43_DMA_30BIT: | ||
393 | if ((u64)addr + size > (1ULL << 30)) | ||
394 | return 0; | ||
395 | break; | ||
396 | case B43_DMA_32BIT: | ||
397 | if ((u64)addr + size > (1ULL << 32)) | ||
398 | return 0; | ||
399 | break; | ||
400 | case B43_DMA_64BIT: | ||
401 | /* Currently we can't have addresses beyond | ||
402 | * 64bit in the kernel. */ | ||
403 | break; | ||
404 | } | ||
405 | return 1; | ||
406 | } | ||
407 | |||
408 | #define is_4k_aligned(addr) (((u64)(addr) & 0x0FFFull) == 0) | ||
409 | #define is_8k_aligned(addr) (((u64)(addr) & 0x1FFFull) == 0) | ||
410 | |||
411 | static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base, | ||
412 | dma_addr_t dmaaddr, size_t size) | ||
413 | { | ||
414 | ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE); | ||
415 | free_pages((unsigned long)base, get_order(size)); | ||
416 | } | ||
417 | |||
418 | static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring, | ||
419 | dma_addr_t *dmaaddr, size_t size, | ||
420 | gfp_t gfp_flags) | ||
421 | { | ||
422 | void *base; | ||
423 | |||
424 | base = (void *)__get_free_pages(gfp_flags, get_order(size)); | ||
425 | if (!base) | ||
426 | return NULL; | ||
427 | memset(base, 0, size); | ||
428 | *dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size, | ||
429 | DMA_TO_DEVICE); | ||
430 | if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) { | ||
431 | free_pages((unsigned long)base, get_order(size)); | ||
432 | return NULL; | ||
433 | } | ||
434 | |||
435 | return base; | ||
436 | } | ||
437 | |||
438 | static void * b43_get_and_map_ringmem(struct b43_dmaring *ring, | ||
439 | dma_addr_t *dmaaddr, size_t size) | ||
440 | { | ||
441 | void *base; | ||
442 | |||
443 | base = __b43_get_and_map_ringmem(ring, dmaaddr, size, | ||
444 | GFP_KERNEL); | ||
445 | if (!base) { | ||
446 | b43err(ring->dev->wl, "Failed to allocate or map pages " | ||
447 | "for DMA ringmemory\n"); | ||
448 | return NULL; | ||
449 | } | ||
450 | if (!b43_dma_address_ok(ring, *dmaaddr, size)) { | ||
451 | /* The memory does not fit our device constraints. | ||
452 | * Retry with GFP_DMA set to get lower memory. */ | ||
453 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
454 | base = __b43_get_and_map_ringmem(ring, dmaaddr, size, | ||
455 | GFP_KERNEL | GFP_DMA); | ||
456 | if (!base) { | ||
457 | b43err(ring->dev->wl, "Failed to allocate or map pages " | ||
458 | "in the GFP_DMA region for DMA ringmemory\n"); | ||
459 | return NULL; | ||
460 | } | ||
461 | if (!b43_dma_address_ok(ring, *dmaaddr, size)) { | ||
462 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
463 | b43err(ring->dev->wl, "Failed to allocate DMA " | ||
464 | "ringmemory that fits device constraints\n"); | ||
465 | return NULL; | ||
466 | } | ||
467 | } | ||
468 | /* We expect the memory to be 4k aligned, at least. */ | ||
469 | if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) { | ||
470 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
471 | return NULL; | ||
472 | } | ||
473 | |||
474 | return base; | ||
475 | } | ||
476 | |||
477 | static int alloc_ringmemory(struct b43_dmaring *ring) | 386 | static int alloc_ringmemory(struct b43_dmaring *ring) |
478 | { | 387 | { |
479 | unsigned int required; | 388 | gfp_t flags = GFP_KERNEL; |
480 | void *base; | 389 | |
481 | dma_addr_t dmaaddr; | 390 | /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K |
482 | 391 | * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing | |
483 | /* There are several requirements to the descriptor ring memory: | 392 | * has shown that 4K is sufficient for the latter as long as the buffer |
484 | * - The memory region needs to fit the address constraints for the | 393 | * does not cross an 8K boundary. |
485 | * device (same as for frame buffers). | 394 | * |
486 | * - For 30/32bit DMA devices, the descriptor ring must be 4k aligned. | 395 | * For unknown reasons - possibly a hardware error - the BCM4311 rev |
487 | * - For 64bit DMA devices, the descriptor ring must be 8k aligned. | 396 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, |
397 | * which accounts for the GFP_DMA flag below. | ||
398 | * | ||
399 | * The flags here must match the flags in free_ringmemory below! | ||
488 | */ | 400 | */ |
489 | |||
490 | if (ring->type == B43_DMA_64BIT) | 401 | if (ring->type == B43_DMA_64BIT) |
491 | required = ring->nr_slots * sizeof(struct b43_dmadesc64); | 402 | flags |= GFP_DMA; |
492 | else | 403 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, |
493 | required = ring->nr_slots * sizeof(struct b43_dmadesc32); | 404 | B43_DMA_RINGMEMSIZE, |
494 | if (B43_WARN_ON(required > 0x1000)) | 405 | &(ring->dmabase), flags); |
406 | if (!ring->descbase) { | ||
407 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); | ||
495 | return -ENOMEM; | 408 | return -ENOMEM; |
496 | |||
497 | ring->alloc_descsize = 0x1000; | ||
498 | base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); | ||
499 | if (!base) | ||
500 | return -ENOMEM; | ||
501 | ring->alloc_descbase = base; | ||
502 | ring->alloc_dmabase = dmaaddr; | ||
503 | |||
504 | if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) { | ||
505 | /* We're on <=32bit DMA, or we already got 8k aligned memory. | ||
506 | * That's all we need, so we're fine. */ | ||
507 | ring->descbase = base; | ||
508 | ring->dmabase = dmaaddr; | ||
509 | return 0; | ||
510 | } | ||
511 | b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize); | ||
512 | |||
513 | /* Ok, we failed at the 8k alignment requirement. | ||
514 | * Try to force-align the memory region now. */ | ||
515 | ring->alloc_descsize = 0x2000; | ||
516 | base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); | ||
517 | if (!base) | ||
518 | return -ENOMEM; | ||
519 | ring->alloc_descbase = base; | ||
520 | ring->alloc_dmabase = dmaaddr; | ||
521 | |||
522 | if (is_8k_aligned(dmaaddr)) { | ||
523 | /* We're already 8k aligned. That Ok, too. */ | ||
524 | ring->descbase = base; | ||
525 | ring->dmabase = dmaaddr; | ||
526 | return 0; | ||
527 | } | 409 | } |
528 | /* Force-align it to 8k */ | 410 | memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); |
529 | ring->descbase = (void *)((u8 *)base + 0x1000); | ||
530 | ring->dmabase = dmaaddr + 0x1000; | ||
531 | B43_WARN_ON(!is_8k_aligned(ring->dmabase)); | ||
532 | 411 | ||
533 | return 0; | 412 | return 0; |
534 | } | 413 | } |
535 | 414 | ||
536 | static void free_ringmemory(struct b43_dmaring *ring) | 415 | static void free_ringmemory(struct b43_dmaring *ring) |
537 | { | 416 | { |
538 | b43_unmap_and_free_ringmem(ring, ring->alloc_descbase, | 417 | gfp_t flags = GFP_KERNEL; |
539 | ring->alloc_dmabase, ring->alloc_descsize); | 418 | |
419 | if (ring->type == B43_DMA_64BIT) | ||
420 | flags |= GFP_DMA; | ||
421 | |||
422 | ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, | ||
423 | ring->descbase, ring->dmabase, flags); | ||
540 | } | 424 | } |
541 | 425 | ||
542 | /* Reset the RX DMA channel */ | 426 | /* Reset the RX DMA channel */ |
@@ -646,14 +530,29 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, | |||
646 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) | 530 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) |
647 | return 1; | 531 | return 1; |
648 | 532 | ||
649 | if (!b43_dma_address_ok(ring, addr, buffersize)) { | 533 | switch (ring->type) { |
650 | /* We can't support this address. Unmap it again. */ | 534 | case B43_DMA_30BIT: |
651 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); | 535 | if ((u64)addr + buffersize > (1ULL << 30)) |
652 | return 1; | 536 | goto address_error; |
537 | break; | ||
538 | case B43_DMA_32BIT: | ||
539 | if ((u64)addr + buffersize > (1ULL << 32)) | ||
540 | goto address_error; | ||
541 | break; | ||
542 | case B43_DMA_64BIT: | ||
543 | /* Currently we can't have addresses beyond | ||
544 | * 64bit in the kernel. */ | ||
545 | break; | ||
653 | } | 546 | } |
654 | 547 | ||
655 | /* The address is OK. */ | 548 | /* The address is OK. */ |
656 | return 0; | 549 | return 0; |
550 | |||
551 | address_error: | ||
552 | /* We can't support this address. Unmap it again. */ | ||
553 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); | ||
554 | |||
555 | return 1; | ||
657 | } | 556 | } |
658 | 557 | ||
659 | static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) | 558 | static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) |
@@ -715,9 +614,6 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
715 | meta->dmaaddr = dmaaddr; | 614 | meta->dmaaddr = dmaaddr; |
716 | ring->ops->fill_descriptor(ring, desc, dmaaddr, | 615 | ring->ops->fill_descriptor(ring, desc, dmaaddr, |
717 | ring->rx_buffersize, 0, 0, 0); | 616 | ring->rx_buffersize, 0, 0, 0); |
718 | ssb_dma_sync_single_for_device(ring->dev->dev, | ||
719 | ring->alloc_dmabase, | ||
720 | ring->alloc_descsize, DMA_TO_DEVICE); | ||
721 | 617 | ||
722 | return 0; | 618 | return 0; |
723 | } | 619 | } |
@@ -1354,9 +1250,6 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1354 | } | 1250 | } |
1355 | /* Now transfer the whole frame. */ | 1251 | /* Now transfer the whole frame. */ |
1356 | wmb(); | 1252 | wmb(); |
1357 | ssb_dma_sync_single_for_device(ring->dev->dev, | ||
1358 | ring->alloc_dmabase, | ||
1359 | ring->alloc_descsize, DMA_TO_DEVICE); | ||
1360 | ops->poke_tx(ring, next_slot(ring, slot)); | 1253 | ops->poke_tx(ring, next_slot(ring, slot)); |
1361 | return 0; | 1254 | return 0; |
1362 | 1255 | ||
@@ -1760,7 +1653,6 @@ void b43_dma_tx_resume(struct b43_wldev *dev) | |||
1760 | b43_power_saving_ctl_bits(dev, 0); | 1653 | b43_power_saving_ctl_bits(dev, 0); |
1761 | } | 1654 | } |
1762 | 1655 | ||
1763 | #ifdef CONFIG_B43_PIO | ||
1764 | static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, | 1656 | static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, |
1765 | u16 mmio_base, bool enable) | 1657 | u16 mmio_base, bool enable) |
1766 | { | 1658 | { |
@@ -1794,4 +1686,3 @@ void b43_dma_direct_fifo_rx(struct b43_wldev *dev, | |||
1794 | mmio_base = b43_dmacontroller_base(type, engine_index); | 1686 | mmio_base = b43_dmacontroller_base(type, engine_index); |
1795 | direct_fifo_rx(dev, type, mmio_base, enable); | 1687 | direct_fifo_rx(dev, type, mmio_base, enable); |
1796 | } | 1688 | } |
1797 | #endif /* CONFIG_B43_PIO */ | ||
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index e607b392314c..f7ab37c4cdbc 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -157,6 +157,7 @@ struct b43_dmadesc_generic { | |||
157 | } __attribute__ ((__packed__)); | 157 | } __attribute__ ((__packed__)); |
158 | 158 | ||
159 | /* Misc DMA constants */ | 159 | /* Misc DMA constants */ |
160 | #define B43_DMA_RINGMEMSIZE PAGE_SIZE | ||
160 | #define B43_DMA0_RX_FRAMEOFFSET 30 | 161 | #define B43_DMA0_RX_FRAMEOFFSET 30 |
161 | 162 | ||
162 | /* DMA engine tuning knobs */ | 163 | /* DMA engine tuning knobs */ |
@@ -246,12 +247,6 @@ struct b43_dmaring { | |||
246 | /* The QOS priority assigned to this ring. Only used for TX rings. | 247 | /* The QOS priority assigned to this ring. Only used for TX rings. |
247 | * This is the mac80211 "queue" value. */ | 248 | * This is the mac80211 "queue" value. */ |
248 | u8 queue_prio; | 249 | u8 queue_prio; |
249 | /* Pointers and size of the originally allocated and mapped memory | ||
250 | * region for the descriptor ring. */ | ||
251 | void *alloc_descbase; | ||
252 | dma_addr_t alloc_dmabase; | ||
253 | unsigned int alloc_descsize; | ||
254 | /* Pointer to our wireless device. */ | ||
255 | struct b43_wldev *dev; | 250 | struct b43_wldev *dev; |
256 | #ifdef CONFIG_B43_DEBUG | 251 | #ifdef CONFIG_B43_DEBUG |
257 | /* Maximum number of used slots. */ | 252 | /* Maximum number of used slots. */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 4c41cfe44f26..60290c06e950 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -102,6 +102,9 @@ int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; | |||
102 | module_param_named(verbose, b43_modparam_verbose, int, 0644); | 102 | module_param_named(verbose, b43_modparam_verbose, int, 0644); |
103 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); | 103 | MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); |
104 | 104 | ||
105 | static int modparam_pio; | ||
106 | module_param_named(pio, modparam_pio, int, 0444); | ||
107 | MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); | ||
105 | 108 | ||
106 | static const struct ssb_device_id b43_ssb_tbl[] = { | 109 | static const struct ssb_device_id b43_ssb_tbl[] = { |
107 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), | 110 | SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), |
@@ -1786,8 +1789,8 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) | |||
1786 | dma_reason[4], dma_reason[5]); | 1789 | dma_reason[4], dma_reason[5]); |
1787 | b43err(dev->wl, "This device does not support DMA " | 1790 | b43err(dev->wl, "This device does not support DMA " |
1788 | "on your system. Please use PIO instead.\n"); | 1791 | "on your system. Please use PIO instead.\n"); |
1789 | b43err(dev->wl, "CONFIG_B43_FORCE_PIO must be set in " | 1792 | b43err(dev->wl, "Unload the b43 module and reload " |
1790 | "your kernel configuration.\n"); | 1793 | "with 'pio=1'\n"); |
1791 | return; | 1794 | return; |
1792 | } | 1795 | } |
1793 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { | 1796 | if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { |
@@ -4353,7 +4356,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4353 | 4356 | ||
4354 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || | 4357 | if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || |
4355 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || | 4358 | (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || |
4356 | B43_FORCE_PIO) { | 4359 | modparam_pio) { |
4357 | dev->__using_pio_transfers = 1; | 4360 | dev->__using_pio_transfers = 1; |
4358 | err = b43_pio_init(dev); | 4361 | err = b43_pio_init(dev); |
4359 | } else { | 4362 | } else { |
@@ -4388,7 +4391,7 @@ err_busdown: | |||
4388 | } | 4391 | } |
4389 | 4392 | ||
4390 | static int b43_op_add_interface(struct ieee80211_hw *hw, | 4393 | static int b43_op_add_interface(struct ieee80211_hw *hw, |
4391 | struct ieee80211_if_init_conf *conf) | 4394 | struct ieee80211_vif *vif) |
4392 | { | 4395 | { |
4393 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4396 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4394 | struct b43_wldev *dev; | 4397 | struct b43_wldev *dev; |
@@ -4396,24 +4399,24 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4396 | 4399 | ||
4397 | /* TODO: allow WDS/AP devices to coexist */ | 4400 | /* TODO: allow WDS/AP devices to coexist */ |
4398 | 4401 | ||
4399 | if (conf->type != NL80211_IFTYPE_AP && | 4402 | if (vif->type != NL80211_IFTYPE_AP && |
4400 | conf->type != NL80211_IFTYPE_MESH_POINT && | 4403 | vif->type != NL80211_IFTYPE_MESH_POINT && |
4401 | conf->type != NL80211_IFTYPE_STATION && | 4404 | vif->type != NL80211_IFTYPE_STATION && |
4402 | conf->type != NL80211_IFTYPE_WDS && | 4405 | vif->type != NL80211_IFTYPE_WDS && |
4403 | conf->type != NL80211_IFTYPE_ADHOC) | 4406 | vif->type != NL80211_IFTYPE_ADHOC) |
4404 | return -EOPNOTSUPP; | 4407 | return -EOPNOTSUPP; |
4405 | 4408 | ||
4406 | mutex_lock(&wl->mutex); | 4409 | mutex_lock(&wl->mutex); |
4407 | if (wl->operating) | 4410 | if (wl->operating) |
4408 | goto out_mutex_unlock; | 4411 | goto out_mutex_unlock; |
4409 | 4412 | ||
4410 | b43dbg(wl, "Adding Interface type %d\n", conf->type); | 4413 | b43dbg(wl, "Adding Interface type %d\n", vif->type); |
4411 | 4414 | ||
4412 | dev = wl->current_dev; | 4415 | dev = wl->current_dev; |
4413 | wl->operating = 1; | 4416 | wl->operating = 1; |
4414 | wl->vif = conf->vif; | 4417 | wl->vif = vif; |
4415 | wl->if_type = conf->type; | 4418 | wl->if_type = vif->type; |
4416 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 4419 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
4417 | 4420 | ||
4418 | b43_adjust_opmode(dev); | 4421 | b43_adjust_opmode(dev); |
4419 | b43_set_pretbtt(dev); | 4422 | b43_set_pretbtt(dev); |
@@ -4428,17 +4431,17 @@ static int b43_op_add_interface(struct ieee80211_hw *hw, | |||
4428 | } | 4431 | } |
4429 | 4432 | ||
4430 | static void b43_op_remove_interface(struct ieee80211_hw *hw, | 4433 | static void b43_op_remove_interface(struct ieee80211_hw *hw, |
4431 | struct ieee80211_if_init_conf *conf) | 4434 | struct ieee80211_vif *vif) |
4432 | { | 4435 | { |
4433 | struct b43_wl *wl = hw_to_b43_wl(hw); | 4436 | struct b43_wl *wl = hw_to_b43_wl(hw); |
4434 | struct b43_wldev *dev = wl->current_dev; | 4437 | struct b43_wldev *dev = wl->current_dev; |
4435 | 4438 | ||
4436 | b43dbg(wl, "Removing Interface type %d\n", conf->type); | 4439 | b43dbg(wl, "Removing Interface type %d\n", vif->type); |
4437 | 4440 | ||
4438 | mutex_lock(&wl->mutex); | 4441 | mutex_lock(&wl->mutex); |
4439 | 4442 | ||
4440 | B43_WARN_ON(!wl->operating); | 4443 | B43_WARN_ON(!wl->operating); |
4441 | B43_WARN_ON(wl->vif != conf->vif); | 4444 | B43_WARN_ON(wl->vif != vif); |
4442 | wl->vif = NULL; | 4445 | wl->vif = NULL; |
4443 | 4446 | ||
4444 | wl->operating = 0; | 4447 | wl->operating = 0; |
diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h index 7dd649c9ddad..7b3c42f93a16 100644 --- a/drivers/net/wireless/b43/pio.h +++ b/drivers/net/wireless/b43/pio.h | |||
@@ -55,8 +55,6 @@ | |||
55 | #define B43_PIO_MAX_NR_TXPACKETS 32 | 55 | #define B43_PIO_MAX_NR_TXPACKETS 32 |
56 | 56 | ||
57 | 57 | ||
58 | #ifdef CONFIG_B43_PIO | ||
59 | |||
60 | struct b43_pio_txpacket { | 58 | struct b43_pio_txpacket { |
61 | /* Pointer to the TX queue we belong to. */ | 59 | /* Pointer to the TX queue we belong to. */ |
62 | struct b43_pio_txqueue *queue; | 60 | struct b43_pio_txqueue *queue; |
@@ -169,42 +167,4 @@ void b43_pio_rx(struct b43_pio_rxqueue *q); | |||
169 | void b43_pio_tx_suspend(struct b43_wldev *dev); | 167 | void b43_pio_tx_suspend(struct b43_wldev *dev); |
170 | void b43_pio_tx_resume(struct b43_wldev *dev); | 168 | void b43_pio_tx_resume(struct b43_wldev *dev); |
171 | 169 | ||
172 | |||
173 | #else /* CONFIG_B43_PIO */ | ||
174 | |||
175 | |||
176 | static inline int b43_pio_init(struct b43_wldev *dev) | ||
177 | { | ||
178 | return 0; | ||
179 | } | ||
180 | static inline void b43_pio_free(struct b43_wldev *dev) | ||
181 | { | ||
182 | } | ||
183 | static inline void b43_pio_stop(struct b43_wldev *dev) | ||
184 | { | ||
185 | } | ||
186 | static inline int b43_pio_tx(struct b43_wldev *dev, | ||
187 | struct sk_buff *skb) | ||
188 | { | ||
189 | return 0; | ||
190 | } | ||
191 | static inline void b43_pio_handle_txstatus(struct b43_wldev *dev, | ||
192 | const struct b43_txstatus *status) | ||
193 | { | ||
194 | } | ||
195 | static inline void b43_pio_get_tx_stats(struct b43_wldev *dev, | ||
196 | struct ieee80211_tx_queue_stats *stats) | ||
197 | { | ||
198 | } | ||
199 | static inline void b43_pio_rx(struct b43_pio_rxqueue *q) | ||
200 | { | ||
201 | } | ||
202 | static inline void b43_pio_tx_suspend(struct b43_wldev *dev) | ||
203 | { | ||
204 | } | ||
205 | static inline void b43_pio_tx_resume(struct b43_wldev *dev) | ||
206 | { | ||
207 | } | ||
208 | |||
209 | #endif /* CONFIG_B43_PIO */ | ||
210 | #endif /* B43_PIO_H_ */ | 170 | #endif /* B43_PIO_H_ */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 4a905b6a886b..fbae264095cc 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3361,7 +3361,7 @@ err_kfree_lo_control: | |||
3361 | } | 3361 | } |
3362 | 3362 | ||
3363 | static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | 3363 | static int b43legacy_op_add_interface(struct ieee80211_hw *hw, |
3364 | struct ieee80211_if_init_conf *conf) | 3364 | struct ieee80211_vif *vif) |
3365 | { | 3365 | { |
3366 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3366 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3367 | struct b43legacy_wldev *dev; | 3367 | struct b43legacy_wldev *dev; |
@@ -3370,23 +3370,23 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3370 | 3370 | ||
3371 | /* TODO: allow WDS/AP devices to coexist */ | 3371 | /* TODO: allow WDS/AP devices to coexist */ |
3372 | 3372 | ||
3373 | if (conf->type != NL80211_IFTYPE_AP && | 3373 | if (vif->type != NL80211_IFTYPE_AP && |
3374 | conf->type != NL80211_IFTYPE_STATION && | 3374 | vif->type != NL80211_IFTYPE_STATION && |
3375 | conf->type != NL80211_IFTYPE_WDS && | 3375 | vif->type != NL80211_IFTYPE_WDS && |
3376 | conf->type != NL80211_IFTYPE_ADHOC) | 3376 | vif->type != NL80211_IFTYPE_ADHOC) |
3377 | return -EOPNOTSUPP; | 3377 | return -EOPNOTSUPP; |
3378 | 3378 | ||
3379 | mutex_lock(&wl->mutex); | 3379 | mutex_lock(&wl->mutex); |
3380 | if (wl->operating) | 3380 | if (wl->operating) |
3381 | goto out_mutex_unlock; | 3381 | goto out_mutex_unlock; |
3382 | 3382 | ||
3383 | b43legacydbg(wl, "Adding Interface type %d\n", conf->type); | 3383 | b43legacydbg(wl, "Adding Interface type %d\n", vif->type); |
3384 | 3384 | ||
3385 | dev = wl->current_dev; | 3385 | dev = wl->current_dev; |
3386 | wl->operating = 1; | 3386 | wl->operating = 1; |
3387 | wl->vif = conf->vif; | 3387 | wl->vif = vif; |
3388 | wl->if_type = conf->type; | 3388 | wl->if_type = vif->type; |
3389 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 3389 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
3390 | 3390 | ||
3391 | spin_lock_irqsave(&wl->irq_lock, flags); | 3391 | spin_lock_irqsave(&wl->irq_lock, flags); |
3392 | b43legacy_adjust_opmode(dev); | 3392 | b43legacy_adjust_opmode(dev); |
@@ -3403,18 +3403,18 @@ static int b43legacy_op_add_interface(struct ieee80211_hw *hw, | |||
3403 | } | 3403 | } |
3404 | 3404 | ||
3405 | static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, | 3405 | static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, |
3406 | struct ieee80211_if_init_conf *conf) | 3406 | struct ieee80211_vif *vif) |
3407 | { | 3407 | { |
3408 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 3408 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
3409 | struct b43legacy_wldev *dev = wl->current_dev; | 3409 | struct b43legacy_wldev *dev = wl->current_dev; |
3410 | unsigned long flags; | 3410 | unsigned long flags; |
3411 | 3411 | ||
3412 | b43legacydbg(wl, "Removing Interface type %d\n", conf->type); | 3412 | b43legacydbg(wl, "Removing Interface type %d\n", vif->type); |
3413 | 3413 | ||
3414 | mutex_lock(&wl->mutex); | 3414 | mutex_lock(&wl->mutex); |
3415 | 3415 | ||
3416 | B43legacy_WARN_ON(!wl->operating); | 3416 | B43legacy_WARN_ON(!wl->operating); |
3417 | B43legacy_WARN_ON(wl->vif != conf->vif); | 3417 | B43legacy_WARN_ON(wl->vif != vif); |
3418 | wl->vif = NULL; | 3418 | wl->vif = NULL; |
3419 | 3419 | ||
3420 | wl->operating = 0; | 3420 | wl->operating = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d1bab141508a..28ffe4c826d8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -681,19 +681,13 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv, | |||
681 | snr = rx_stats_sig_avg / rx_stats_noise_diff; | 681 | snr = rx_stats_sig_avg / rx_stats_noise_diff; |
682 | rx_status.noise = rx_status.signal - | 682 | rx_status.noise = rx_status.signal - |
683 | iwl3945_calc_db_from_ratio(snr); | 683 | iwl3945_calc_db_from_ratio(snr); |
684 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, | ||
685 | rx_status.noise); | ||
686 | |||
687 | /* If noise info not available, calculate signal quality indicator (%) | ||
688 | * using just the dBm signal level. */ | ||
689 | } else { | 684 | } else { |
690 | rx_status.noise = priv->last_rx_noise; | 685 | rx_status.noise = priv->last_rx_noise; |
691 | rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); | ||
692 | } | 686 | } |
693 | 687 | ||
694 | 688 | ||
695 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", | 689 | IWL_DEBUG_STATS(priv, "Rssi %d noise %d sig_avg %d noise_diff %d\n", |
696 | rx_status.signal, rx_status.noise, rx_status.qual, | 690 | rx_status.signal, rx_status.noise, |
697 | rx_stats_sig_avg, rx_stats_noise_diff); | 691 | rx_stats_sig_avg, rx_stats_noise_diff); |
698 | 692 | ||
699 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); | 693 | header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 28f6eb5f2cba..3ec2fe370b58 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -222,7 +222,6 @@ struct iwl3945_ibss_seq { | |||
222 | * | 222 | * |
223 | *****************************************************************************/ | 223 | *****************************************************************************/ |
224 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); | 224 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); |
225 | extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); | ||
226 | extern void iwl3945_rx_replenish(void *data); | 225 | extern void iwl3945_rx_replenish(void *data); |
227 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 226 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
228 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 227 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index fe511cbf012e..b93e49158196 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -150,7 +150,7 @@ static s32 expected_tpt_mimo3_40MHz[4][IWL_RATE_COUNT] = { | |||
150 | }; | 150 | }; |
151 | 151 | ||
152 | /* mbps, mcs */ | 152 | /* mbps, mcs */ |
153 | const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { | 153 | static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { |
154 | { "1", "BPSK DSSS"}, | 154 | { "1", "BPSK DSSS"}, |
155 | { "2", "QPSK DSSS"}, | 155 | { "2", "QPSK DSSS"}, |
156 | {"5.5", "BPSK CCK"}, | 156 | {"5.5", "BPSK CCK"}, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index e3b96b48b7fe..14f482960d7f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2584,12 +2584,12 @@ int iwl_set_mode(struct iwl_priv *priv, int mode) | |||
2584 | EXPORT_SYMBOL(iwl_set_mode); | 2584 | EXPORT_SYMBOL(iwl_set_mode); |
2585 | 2585 | ||
2586 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 2586 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
2587 | struct ieee80211_if_init_conf *conf) | 2587 | struct ieee80211_vif *vif) |
2588 | { | 2588 | { |
2589 | struct iwl_priv *priv = hw->priv; | 2589 | struct iwl_priv *priv = hw->priv; |
2590 | unsigned long flags; | 2590 | unsigned long flags; |
2591 | 2591 | ||
2592 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); | 2592 | IWL_DEBUG_MAC80211(priv, "enter: type %d\n", vif->type); |
2593 | 2593 | ||
2594 | if (priv->vif) { | 2594 | if (priv->vif) { |
2595 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); | 2595 | IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); |
@@ -2597,19 +2597,19 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2597 | } | 2597 | } |
2598 | 2598 | ||
2599 | spin_lock_irqsave(&priv->lock, flags); | 2599 | spin_lock_irqsave(&priv->lock, flags); |
2600 | priv->vif = conf->vif; | 2600 | priv->vif = vif; |
2601 | priv->iw_mode = conf->type; | 2601 | priv->iw_mode = vif->type; |
2602 | 2602 | ||
2603 | spin_unlock_irqrestore(&priv->lock, flags); | 2603 | spin_unlock_irqrestore(&priv->lock, flags); |
2604 | 2604 | ||
2605 | mutex_lock(&priv->mutex); | 2605 | mutex_lock(&priv->mutex); |
2606 | 2606 | ||
2607 | if (conf->mac_addr) { | 2607 | if (vif->addr) { |
2608 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); | 2608 | IWL_DEBUG_MAC80211(priv, "Set %pM\n", vif->addr); |
2609 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 2609 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
2610 | } | 2610 | } |
2611 | 2611 | ||
2612 | if (iwl_set_mode(priv, conf->type) == -EAGAIN) | 2612 | if (iwl_set_mode(priv, vif->type) == -EAGAIN) |
2613 | /* we are not ready, will run again when ready */ | 2613 | /* we are not ready, will run again when ready */ |
2614 | set_bit(STATUS_MODE_PENDING, &priv->status); | 2614 | set_bit(STATUS_MODE_PENDING, &priv->status); |
2615 | 2615 | ||
@@ -2621,7 +2621,7 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, | |||
2621 | EXPORT_SYMBOL(iwl_mac_add_interface); | 2621 | EXPORT_SYMBOL(iwl_mac_add_interface); |
2622 | 2622 | ||
2623 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 2623 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
2624 | struct ieee80211_if_init_conf *conf) | 2624 | struct ieee80211_vif *vif) |
2625 | { | 2625 | { |
2626 | struct iwl_priv *priv = hw->priv; | 2626 | struct iwl_priv *priv = hw->priv; |
2627 | 2627 | ||
@@ -2634,7 +2634,7 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2634 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2634 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
2635 | iwlcore_commit_rxon(priv); | 2635 | iwlcore_commit_rxon(priv); |
2636 | } | 2636 | } |
2637 | if (priv->vif == conf->vif) { | 2637 | if (priv->vif == vif) { |
2638 | priv->vif = NULL; | 2638 | priv->vif = NULL; |
2639 | memset(priv->bssid, 0, ETH_ALEN); | 2639 | memset(priv->bssid, 0, ETH_ALEN); |
2640 | } | 2640 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 308f679ef81c..3ef86f6c7755 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -332,9 +332,9 @@ int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
332 | int iwl_commit_rxon(struct iwl_priv *priv); | 332 | int iwl_commit_rxon(struct iwl_priv *priv); |
333 | int iwl_set_mode(struct iwl_priv *priv, int mode); | 333 | int iwl_set_mode(struct iwl_priv *priv, int mode); |
334 | int iwl_mac_add_interface(struct ieee80211_hw *hw, | 334 | int iwl_mac_add_interface(struct ieee80211_hw *hw, |
335 | struct ieee80211_if_init_conf *conf); | 335 | struct ieee80211_vif *vif); |
336 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, | 336 | void iwl_mac_remove_interface(struct ieee80211_hw *hw, |
337 | struct ieee80211_if_init_conf *conf); | 337 | struct ieee80211_vif *vif); |
338 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); | 338 | int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); |
339 | void iwl_config_ap(struct iwl_priv *priv); | 339 | void iwl_config_ap(struct iwl_priv *priv); |
340 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, | 340 | int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index f5c87e72660a..6f36b6e79f5e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -650,47 +650,6 @@ void iwl_reply_statistics(struct iwl_priv *priv, | |||
650 | } | 650 | } |
651 | EXPORT_SYMBOL(iwl_reply_statistics); | 651 | EXPORT_SYMBOL(iwl_reply_statistics); |
652 | 652 | ||
653 | #define PERFECT_RSSI (-20) /* dBm */ | ||
654 | #define WORST_RSSI (-95) /* dBm */ | ||
655 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
656 | |||
657 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
658 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
659 | * about formulas used below. */ | ||
660 | static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
661 | { | ||
662 | int sig_qual; | ||
663 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
664 | |||
665 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
666 | * as indicator; formula is (signal dbm - noise dbm). | ||
667 | * SNR at or above 40 is a great signal (100%). | ||
668 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
669 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
670 | if (noise_dbm) { | ||
671 | if (rssi_dbm - noise_dbm >= 40) | ||
672 | return 100; | ||
673 | else if (rssi_dbm < noise_dbm) | ||
674 | return 0; | ||
675 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
676 | |||
677 | /* Else use just the signal level. | ||
678 | * This formula is a least squares fit of data points collected and | ||
679 | * compared with a reference system that had a percentage (%) display | ||
680 | * for signal quality. */ | ||
681 | } else | ||
682 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
683 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
684 | (RSSI_RANGE * RSSI_RANGE); | ||
685 | |||
686 | if (sig_qual > 100) | ||
687 | sig_qual = 100; | ||
688 | else if (sig_qual < 1) | ||
689 | sig_qual = 0; | ||
690 | |||
691 | return sig_qual; | ||
692 | } | ||
693 | |||
694 | /* Calc max signal level (dBm) among 3 possible receivers */ | 653 | /* Calc max signal level (dBm) among 3 possible receivers */ |
695 | static inline int iwl_calc_rssi(struct iwl_priv *priv, | 654 | static inline int iwl_calc_rssi(struct iwl_priv *priv, |
696 | struct iwl_rx_phy_res *rx_resp) | 655 | struct iwl_rx_phy_res *rx_resp) |
@@ -1101,11 +1060,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1101 | if (iwl_is_associated(priv) && | 1060 | if (iwl_is_associated(priv) && |
1102 | !test_bit(STATUS_SCANNING, &priv->status)) { | 1061 | !test_bit(STATUS_SCANNING, &priv->status)) { |
1103 | rx_status.noise = priv->last_rx_noise; | 1062 | rx_status.noise = priv->last_rx_noise; |
1104 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, | ||
1105 | rx_status.noise); | ||
1106 | } else { | 1063 | } else { |
1107 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 1064 | rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
1108 | rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0); | ||
1109 | } | 1065 | } |
1110 | 1066 | ||
1111 | /* Reset beacon noise level if not associated. */ | 1067 | /* Reset beacon noise level if not associated. */ |
@@ -1118,8 +1074,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1118 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); | 1074 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); |
1119 | #endif | 1075 | #endif |
1120 | iwl_dbg_log_rx_data_frame(priv, len, header); | 1076 | iwl_dbg_log_rx_data_frame(priv, len, header); |
1121 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", | 1077 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, TSF %llu\n", |
1122 | rx_status.signal, rx_status.noise, rx_status.qual, | 1078 | rx_status.signal, rx_status.noise, |
1123 | (unsigned long long)rx_status.mactime); | 1079 | (unsigned long long)rx_status.mactime); |
1124 | 1080 | ||
1125 | /* | 1081 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 6533122ed87a..10b0aa8024c4 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1299,47 +1299,6 @@ int iwl3945_calc_db_from_ratio(int sig_ratio) | |||
1299 | return (int)ratio2dB[sig_ratio]; | 1299 | return (int)ratio2dB[sig_ratio]; |
1300 | } | 1300 | } |
1301 | 1301 | ||
1302 | #define PERFECT_RSSI (-20) /* dBm */ | ||
1303 | #define WORST_RSSI (-95) /* dBm */ | ||
1304 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | ||
1305 | |||
1306 | /* Calculate an indication of rx signal quality (a percentage, not dBm!). | ||
1307 | * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info | ||
1308 | * about formulas used below. */ | ||
1309 | int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) | ||
1310 | { | ||
1311 | int sig_qual; | ||
1312 | int degradation = PERFECT_RSSI - rssi_dbm; | ||
1313 | |||
1314 | /* If we get a noise measurement, use signal-to-noise ratio (SNR) | ||
1315 | * as indicator; formula is (signal dbm - noise dbm). | ||
1316 | * SNR at or above 40 is a great signal (100%). | ||
1317 | * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. | ||
1318 | * Weakest usable signal is usually 10 - 15 dB SNR. */ | ||
1319 | if (noise_dbm) { | ||
1320 | if (rssi_dbm - noise_dbm >= 40) | ||
1321 | return 100; | ||
1322 | else if (rssi_dbm < noise_dbm) | ||
1323 | return 0; | ||
1324 | sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; | ||
1325 | |||
1326 | /* Else use just the signal level. | ||
1327 | * This formula is a least squares fit of data points collected and | ||
1328 | * compared with a reference system that had a percentage (%) display | ||
1329 | * for signal quality. */ | ||
1330 | } else | ||
1331 | sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * | ||
1332 | (15 * RSSI_RANGE + 62 * degradation)) / | ||
1333 | (RSSI_RANGE * RSSI_RANGE); | ||
1334 | |||
1335 | if (sig_qual > 100) | ||
1336 | sig_qual = 100; | ||
1337 | else if (sig_qual < 1) | ||
1338 | sig_qual = 0; | ||
1339 | |||
1340 | return sig_qual; | ||
1341 | } | ||
1342 | |||
1343 | /** | 1302 | /** |
1344 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode | 1303 | * iwl3945_rx_handle - Main entry function for receiving responses from uCode |
1345 | * | 1304 | * |
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h index 79ffa3b98d73..842811142bef 100644 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ b/drivers/net/wireless/iwmc3200wifi/iwm.h | |||
@@ -268,7 +268,7 @@ struct iwm_priv { | |||
268 | 268 | ||
269 | struct sk_buff_head rx_list; | 269 | struct sk_buff_head rx_list; |
270 | struct list_head rx_tickets; | 270 | struct list_head rx_tickets; |
271 | struct list_head rx_packets[IWM_RX_ID_HASH]; | 271 | struct list_head rx_packets[IWM_RX_ID_HASH + 1]; |
272 | struct workqueue_struct *rx_wq; | 272 | struct workqueue_struct *rx_wq; |
273 | struct work_struct rx_worker; | 273 | struct work_struct rx_worker; |
274 | 274 | ||
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c index 4a0c3e3cd3b1..220361e69cd3 100644 --- a/drivers/net/wireless/libertas/scan.c +++ b/drivers/net/wireless/libertas/scan.c | |||
@@ -567,11 +567,8 @@ int lbs_scan_networks(struct lbs_private *priv, int full_scan) | |||
567 | chan_count = lbs_scan_create_channel_list(priv, chan_list); | 567 | chan_count = lbs_scan_create_channel_list(priv, chan_list); |
568 | 568 | ||
569 | netif_stop_queue(priv->dev); | 569 | netif_stop_queue(priv->dev); |
570 | netif_carrier_off(priv->dev); | 570 | if (priv->mesh_dev) |
571 | if (priv->mesh_dev) { | ||
572 | netif_stop_queue(priv->mesh_dev); | 571 | netif_stop_queue(priv->mesh_dev); |
573 | netif_carrier_off(priv->mesh_dev); | ||
574 | } | ||
575 | 572 | ||
576 | /* Prepare to continue an interrupted scan */ | 573 | /* Prepare to continue an interrupted scan */ |
577 | lbs_deb_scan("chan_count %d, scan_channel %d\n", | 574 | lbs_deb_scan("chan_count %d, scan_channel %d\n", |
@@ -635,16 +632,13 @@ out2: | |||
635 | priv->scan_channel = 0; | 632 | priv->scan_channel = 0; |
636 | 633 | ||
637 | out: | 634 | out: |
638 | if (priv->connect_status == LBS_CONNECTED) { | 635 | if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) |
639 | netif_carrier_on(priv->dev); | 636 | netif_wake_queue(priv->dev); |
640 | if (!priv->tx_pending_len) | 637 | |
641 | netif_wake_queue(priv->dev); | 638 | if (priv->mesh_dev && lbs_mesh_connected(priv) && |
642 | } | 639 | !priv->tx_pending_len) |
643 | if (priv->mesh_dev && lbs_mesh_connected(priv)) { | 640 | netif_wake_queue(priv->mesh_dev); |
644 | netif_carrier_on(priv->mesh_dev); | 641 | |
645 | if (!priv->tx_pending_len) | ||
646 | netif_wake_queue(priv->mesh_dev); | ||
647 | } | ||
648 | kfree(chan_list); | 642 | kfree(chan_list); |
649 | 643 | ||
650 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); | 644 | lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); |
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 019431d2f8a9..ba3eb0101d55 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -318,14 +318,14 @@ static void lbtf_op_stop(struct ieee80211_hw *hw) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | static int lbtf_op_add_interface(struct ieee80211_hw *hw, | 320 | static int lbtf_op_add_interface(struct ieee80211_hw *hw, |
321 | struct ieee80211_if_init_conf *conf) | 321 | struct ieee80211_vif *vif) |
322 | { | 322 | { |
323 | struct lbtf_private *priv = hw->priv; | 323 | struct lbtf_private *priv = hw->priv; |
324 | if (priv->vif != NULL) | 324 | if (priv->vif != NULL) |
325 | return -EOPNOTSUPP; | 325 | return -EOPNOTSUPP; |
326 | 326 | ||
327 | priv->vif = conf->vif; | 327 | priv->vif = vif; |
328 | switch (conf->type) { | 328 | switch (vif->type) { |
329 | case NL80211_IFTYPE_MESH_POINT: | 329 | case NL80211_IFTYPE_MESH_POINT: |
330 | case NL80211_IFTYPE_AP: | 330 | case NL80211_IFTYPE_AP: |
331 | lbtf_set_mode(priv, LBTF_AP_MODE); | 331 | lbtf_set_mode(priv, LBTF_AP_MODE); |
@@ -337,12 +337,12 @@ static int lbtf_op_add_interface(struct ieee80211_hw *hw, | |||
337 | priv->vif = NULL; | 337 | priv->vif = NULL; |
338 | return -EOPNOTSUPP; | 338 | return -EOPNOTSUPP; |
339 | } | 339 | } |
340 | lbtf_set_mac_address(priv, (u8 *) conf->mac_addr); | 340 | lbtf_set_mac_address(priv, (u8 *) vif->addr); |
341 | return 0; | 341 | return 0; |
342 | } | 342 | } |
343 | 343 | ||
344 | static void lbtf_op_remove_interface(struct ieee80211_hw *hw, | 344 | static void lbtf_op_remove_interface(struct ieee80211_hw *hw, |
345 | struct ieee80211_if_init_conf *conf) | 345 | struct ieee80211_vif *vif) |
346 | { | 346 | { |
347 | struct lbtf_private *priv = hw->priv; | 347 | struct lbtf_private *priv = hw->priv; |
348 | 348 | ||
@@ -495,7 +495,6 @@ int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) | |||
495 | stats.band = IEEE80211_BAND_2GHZ; | 495 | stats.band = IEEE80211_BAND_2GHZ; |
496 | stats.signal = prxpd->snr; | 496 | stats.signal = prxpd->snr; |
497 | stats.noise = prxpd->nf; | 497 | stats.noise = prxpd->nf; |
498 | stats.qual = prxpd->snr - prxpd->nf; | ||
499 | /* Marvell rate index has a hole at value 4 */ | 498 | /* Marvell rate index has a hole at value 4 */ |
500 | if (prxpd->rx_rate > 4) | 499 | if (prxpd->rx_rate > 4) |
501 | --prxpd->rx_rate; | 500 | --prxpd->rx_rate; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 718a5f198c30..84df3fcf37b3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -584,24 +584,24 @@ static void mac80211_hwsim_stop(struct ieee80211_hw *hw) | |||
584 | 584 | ||
585 | 585 | ||
586 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, | 586 | static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, |
587 | struct ieee80211_if_init_conf *conf) | 587 | struct ieee80211_vif *vif) |
588 | { | 588 | { |
589 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", | 589 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", |
590 | wiphy_name(hw->wiphy), __func__, conf->type, | 590 | wiphy_name(hw->wiphy), __func__, vif->type, |
591 | conf->mac_addr); | 591 | vif->addr); |
592 | hwsim_set_magic(conf->vif); | 592 | hwsim_set_magic(vif); |
593 | return 0; | 593 | return 0; |
594 | } | 594 | } |
595 | 595 | ||
596 | 596 | ||
597 | static void mac80211_hwsim_remove_interface( | 597 | static void mac80211_hwsim_remove_interface( |
598 | struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) | 598 | struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
599 | { | 599 | { |
600 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", | 600 | printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", |
601 | wiphy_name(hw->wiphy), __func__, conf->type, | 601 | wiphy_name(hw->wiphy), __func__, vif->type, |
602 | conf->mac_addr); | 602 | vif->addr); |
603 | hwsim_check_magic(conf->vif); | 603 | hwsim_check_magic(vif); |
604 | hwsim_clear_magic(conf->vif); | 604 | hwsim_clear_magic(vif); |
605 | } | 605 | } |
606 | 606 | ||
607 | 607 | ||
@@ -896,6 +896,16 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | |||
896 | return 0; | 896 | return 0; |
897 | } | 897 | } |
898 | 898 | ||
899 | static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) | ||
900 | { | ||
901 | /* | ||
902 | * In this special case, there's nothing we need to | ||
903 | * do because hwsim does transmission synchronously. | ||
904 | * In the future, when it does transmissions via | ||
905 | * userspace, we may need to do something. | ||
906 | */ | ||
907 | } | ||
908 | |||
899 | 909 | ||
900 | static const struct ieee80211_ops mac80211_hwsim_ops = | 910 | static const struct ieee80211_ops mac80211_hwsim_ops = |
901 | { | 911 | { |
@@ -912,6 +922,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = | |||
912 | .conf_tx = mac80211_hwsim_conf_tx, | 922 | .conf_tx = mac80211_hwsim_conf_tx, |
913 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 923 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
914 | .ampdu_action = mac80211_hwsim_ampdu_action, | 924 | .ampdu_action = mac80211_hwsim_ampdu_action, |
925 | .flush = mac80211_hwsim_flush, | ||
915 | }; | 926 | }; |
916 | 927 | ||
917 | 928 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 59d49159cf2a..c1c6ecd0c5b3 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -92,8 +92,7 @@ struct mwl8k_device_info { | |||
92 | char *part_name; | 92 | char *part_name; |
93 | char *helper_image; | 93 | char *helper_image; |
94 | char *fw_image; | 94 | char *fw_image; |
95 | struct rxd_ops *rxd_ops; | 95 | struct rxd_ops *ap_rxd_ops; |
96 | u16 modes; | ||
97 | }; | 96 | }; |
98 | 97 | ||
99 | struct mwl8k_rx_queue { | 98 | struct mwl8k_rx_queue { |
@@ -126,29 +125,23 @@ struct mwl8k_tx_queue { | |||
126 | struct sk_buff **skb; | 125 | struct sk_buff **skb; |
127 | }; | 126 | }; |
128 | 127 | ||
129 | /* Pointers to the firmware data and meta information about it. */ | 128 | struct mwl8k_priv { |
130 | struct mwl8k_firmware { | 129 | struct ieee80211_hw *hw; |
131 | /* Boot helper code */ | 130 | struct pci_dev *pdev; |
132 | struct firmware *helper; | ||
133 | 131 | ||
134 | /* Microcode */ | 132 | struct mwl8k_device_info *device_info; |
135 | struct firmware *ucode; | ||
136 | }; | ||
137 | 133 | ||
138 | struct mwl8k_priv { | ||
139 | void __iomem *sram; | 134 | void __iomem *sram; |
140 | void __iomem *regs; | 135 | void __iomem *regs; |
141 | struct ieee80211_hw *hw; | ||
142 | 136 | ||
143 | struct pci_dev *pdev; | 137 | /* firmware */ |
138 | struct firmware *fw_helper; | ||
139 | struct firmware *fw_ucode; | ||
144 | 140 | ||
145 | struct mwl8k_device_info *device_info; | 141 | /* hardware/firmware parameters */ |
146 | bool ap_fw; | 142 | bool ap_fw; |
147 | struct rxd_ops *rxd_ops; | 143 | struct rxd_ops *rxd_ops; |
148 | 144 | ||
149 | /* firmware files and meta data */ | ||
150 | struct mwl8k_firmware fw; | ||
151 | |||
152 | /* firmware access */ | 145 | /* firmware access */ |
153 | struct mutex fw_mutex; | 146 | struct mutex fw_mutex; |
154 | struct task_struct *fw_mutex_owner; | 147 | struct task_struct *fw_mutex_owner; |
@@ -211,17 +204,13 @@ struct mwl8k_priv { | |||
211 | 204 | ||
212 | /* Per interface specific private data */ | 205 | /* Per interface specific private data */ |
213 | struct mwl8k_vif { | 206 | struct mwl8k_vif { |
214 | /* backpointer to parent config block */ | 207 | /* Local MAC address. */ |
215 | struct mwl8k_priv *priv; | 208 | u8 mac_addr[ETH_ALEN]; |
216 | |||
217 | /* BSS config of AP or IBSS from mac80211*/ | ||
218 | struct ieee80211_bss_conf bss_info; | ||
219 | 209 | ||
220 | /* BSSID of AP or IBSS */ | 210 | /* BSSID of AP. */ |
221 | u8 bssid[ETH_ALEN]; | 211 | u8 bssid[ETH_ALEN]; |
222 | u8 mac_addr[ETH_ALEN]; | ||
223 | 212 | ||
224 | /* Index into station database.Returned by update_sta_db call */ | 213 | /* Index into station database. Returned by UPDATE_STADB. */ |
225 | u8 peer_id; | 214 | u8 peer_id; |
226 | 215 | ||
227 | /* Non AMPDU sequence number assigned by driver */ | 216 | /* Non AMPDU sequence number assigned by driver */ |
@@ -242,6 +231,9 @@ static const struct ieee80211_channel mwl8k_channels[] = { | |||
242 | { .center_freq = 2452, .hw_value = 9, }, | 231 | { .center_freq = 2452, .hw_value = 9, }, |
243 | { .center_freq = 2457, .hw_value = 10, }, | 232 | { .center_freq = 2457, .hw_value = 10, }, |
244 | { .center_freq = 2462, .hw_value = 11, }, | 233 | { .center_freq = 2462, .hw_value = 11, }, |
234 | { .center_freq = 2467, .hw_value = 12, }, | ||
235 | { .center_freq = 2472, .hw_value = 13, }, | ||
236 | { .center_freq = 2484, .hw_value = 14, }, | ||
245 | }; | 237 | }; |
246 | 238 | ||
247 | static const struct ieee80211_rate mwl8k_rates[] = { | 239 | static const struct ieee80211_rate mwl8k_rates[] = { |
@@ -355,8 +347,8 @@ static void mwl8k_release_fw(struct firmware **fw) | |||
355 | 347 | ||
356 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) | 348 | static void mwl8k_release_firmware(struct mwl8k_priv *priv) |
357 | { | 349 | { |
358 | mwl8k_release_fw(&priv->fw.ucode); | 350 | mwl8k_release_fw(&priv->fw_ucode); |
359 | mwl8k_release_fw(&priv->fw.helper); | 351 | mwl8k_release_fw(&priv->fw_helper); |
360 | } | 352 | } |
361 | 353 | ||
362 | /* Request fw image */ | 354 | /* Request fw image */ |
@@ -377,7 +369,7 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) | |||
377 | int rc; | 369 | int rc; |
378 | 370 | ||
379 | if (di->helper_image != NULL) { | 371 | if (di->helper_image != NULL) { |
380 | rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw.helper); | 372 | rc = mwl8k_request_fw(priv, di->helper_image, &priv->fw_helper); |
381 | if (rc) { | 373 | if (rc) { |
382 | printk(KERN_ERR "%s: Error requesting helper " | 374 | printk(KERN_ERR "%s: Error requesting helper " |
383 | "firmware file %s\n", pci_name(priv->pdev), | 375 | "firmware file %s\n", pci_name(priv->pdev), |
@@ -386,11 +378,11 @@ static int mwl8k_request_firmware(struct mwl8k_priv *priv) | |||
386 | } | 378 | } |
387 | } | 379 | } |
388 | 380 | ||
389 | rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw.ucode); | 381 | rc = mwl8k_request_fw(priv, di->fw_image, &priv->fw_ucode); |
390 | if (rc) { | 382 | if (rc) { |
391 | printk(KERN_ERR "%s: Error requesting firmware file %s\n", | 383 | printk(KERN_ERR "%s: Error requesting firmware file %s\n", |
392 | pci_name(priv->pdev), di->fw_image); | 384 | pci_name(priv->pdev), di->fw_image); |
393 | mwl8k_release_fw(&priv->fw.helper); | 385 | mwl8k_release_fw(&priv->fw_helper); |
394 | return rc; | 386 | return rc; |
395 | } | 387 | } |
396 | 388 | ||
@@ -551,13 +543,12 @@ static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, | |||
551 | static int mwl8k_load_firmware(struct ieee80211_hw *hw) | 543 | static int mwl8k_load_firmware(struct ieee80211_hw *hw) |
552 | { | 544 | { |
553 | struct mwl8k_priv *priv = hw->priv; | 545 | struct mwl8k_priv *priv = hw->priv; |
554 | struct firmware *fw = priv->fw.ucode; | 546 | struct firmware *fw = priv->fw_ucode; |
555 | struct mwl8k_device_info *di = priv->device_info; | ||
556 | int rc; | 547 | int rc; |
557 | int loops; | 548 | int loops; |
558 | 549 | ||
559 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { | 550 | if (!memcmp(fw->data, "\x01\x00\x00\x00", 4)) { |
560 | struct firmware *helper = priv->fw.helper; | 551 | struct firmware *helper = priv->fw_helper; |
561 | 552 | ||
562 | if (helper == NULL) { | 553 | if (helper == NULL) { |
563 | printk(KERN_ERR "%s: helper image needed but none " | 554 | printk(KERN_ERR "%s: helper image needed but none " |
@@ -584,10 +575,7 @@ static int mwl8k_load_firmware(struct ieee80211_hw *hw) | |||
584 | return rc; | 575 | return rc; |
585 | } | 576 | } |
586 | 577 | ||
587 | if (di->modes & BIT(NL80211_IFTYPE_AP)) | 578 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); |
588 | iowrite32(MWL8K_MODE_AP, priv->regs + MWL8K_HIU_GEN_PTR); | ||
589 | else | ||
590 | iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); | ||
591 | 579 | ||
592 | loops = 500000; | 580 | loops = 500000; |
593 | do { | 581 | do { |
@@ -658,43 +646,6 @@ struct peer_capability_info { | |||
658 | __le16 amsdu_enabled; | 646 | __le16 amsdu_enabled; |
659 | } __attribute__((packed)); | 647 | } __attribute__((packed)); |
660 | 648 | ||
661 | /* Inline functions to manipulate QoS field in data descriptor. */ | ||
662 | static inline u16 mwl8k_qos_setbit_eosp(u16 qos) | ||
663 | { | ||
664 | u16 val_mask = 1 << 4; | ||
665 | |||
666 | /* End of Service Period Bit 4 */ | ||
667 | return qos | val_mask; | ||
668 | } | ||
669 | |||
670 | static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) | ||
671 | { | ||
672 | u16 val_mask = 0x3; | ||
673 | u8 shift = 5; | ||
674 | u16 qos_mask = ~(val_mask << shift); | ||
675 | |||
676 | /* Ack Policy Bit 5-6 */ | ||
677 | return (qos & qos_mask) | ((ack_policy & val_mask) << shift); | ||
678 | } | ||
679 | |||
680 | static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) | ||
681 | { | ||
682 | u16 val_mask = 1 << 7; | ||
683 | |||
684 | /* AMSDU present Bit 7 */ | ||
685 | return qos | val_mask; | ||
686 | } | ||
687 | |||
688 | static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) | ||
689 | { | ||
690 | u16 val_mask = 0xff; | ||
691 | u8 shift = 8; | ||
692 | u16 qos_mask = ~(val_mask << shift); | ||
693 | |||
694 | /* Queue Length Bits 8-15 */ | ||
695 | return (qos & qos_mask) | ((len & val_mask) << shift); | ||
696 | } | ||
697 | |||
698 | /* DMA header used by firmware and hardware. */ | 649 | /* DMA header used by firmware and hardware. */ |
699 | struct mwl8k_dma_data { | 650 | struct mwl8k_dma_data { |
700 | __le16 fwlen; | 651 | __le16 fwlen; |
@@ -761,9 +712,9 @@ static inline void mwl8k_add_dma_header(struct sk_buff *skb) | |||
761 | 712 | ||
762 | 713 | ||
763 | /* | 714 | /* |
764 | * Packet reception for 88w8366. | 715 | * Packet reception for 88w8366 AP firmware. |
765 | */ | 716 | */ |
766 | struct mwl8k_rxd_8366 { | 717 | struct mwl8k_rxd_8366_ap { |
767 | __le16 pkt_len; | 718 | __le16 pkt_len; |
768 | __u8 sq2; | 719 | __u8 sq2; |
769 | __u8 rate; | 720 | __u8 rate; |
@@ -781,23 +732,23 @@ struct mwl8k_rxd_8366 { | |||
781 | __u8 rx_ctrl; | 732 | __u8 rx_ctrl; |
782 | } __attribute__((packed)); | 733 | } __attribute__((packed)); |
783 | 734 | ||
784 | #define MWL8K_8366_RATE_INFO_MCS_FORMAT 0x80 | 735 | #define MWL8K_8366_AP_RATE_INFO_MCS_FORMAT 0x80 |
785 | #define MWL8K_8366_RATE_INFO_40MHZ 0x40 | 736 | #define MWL8K_8366_AP_RATE_INFO_40MHZ 0x40 |
786 | #define MWL8K_8366_RATE_INFO_RATEID(x) ((x) & 0x3f) | 737 | #define MWL8K_8366_AP_RATE_INFO_RATEID(x) ((x) & 0x3f) |
787 | 738 | ||
788 | #define MWL8K_8366_RX_CTRL_OWNED_BY_HOST 0x80 | 739 | #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST 0x80 |
789 | 740 | ||
790 | static void mwl8k_rxd_8366_init(void *_rxd, dma_addr_t next_dma_addr) | 741 | static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr) |
791 | { | 742 | { |
792 | struct mwl8k_rxd_8366 *rxd = _rxd; | 743 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
793 | 744 | ||
794 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 745 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
795 | rxd->rx_ctrl = MWL8K_8366_RX_CTRL_OWNED_BY_HOST; | 746 | rxd->rx_ctrl = MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST; |
796 | } | 747 | } |
797 | 748 | ||
798 | static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | 749 | static void mwl8k_rxd_8366_ap_refill(void *_rxd, dma_addr_t addr, int len) |
799 | { | 750 | { |
800 | struct mwl8k_rxd_8366 *rxd = _rxd; | 751 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
801 | 752 | ||
802 | rxd->pkt_len = cpu_to_le16(len); | 753 | rxd->pkt_len = cpu_to_le16(len); |
803 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 754 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -806,12 +757,12 @@ static void mwl8k_rxd_8366_refill(void *_rxd, dma_addr_t addr, int len) | |||
806 | } | 757 | } |
807 | 758 | ||
808 | static int | 759 | static int |
809 | mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | 760 | mwl8k_rxd_8366_ap_process(void *_rxd, struct ieee80211_rx_status *status, |
810 | __le16 *qos) | 761 | __le16 *qos) |
811 | { | 762 | { |
812 | struct mwl8k_rxd_8366 *rxd = _rxd; | 763 | struct mwl8k_rxd_8366_ap *rxd = _rxd; |
813 | 764 | ||
814 | if (!(rxd->rx_ctrl & MWL8K_8366_RX_CTRL_OWNED_BY_HOST)) | 765 | if (!(rxd->rx_ctrl & MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST)) |
815 | return -1; | 766 | return -1; |
816 | rmb(); | 767 | rmb(); |
817 | 768 | ||
@@ -820,11 +771,11 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | |||
820 | status->signal = -rxd->rssi; | 771 | status->signal = -rxd->rssi; |
821 | status->noise = -rxd->noise_floor; | 772 | status->noise = -rxd->noise_floor; |
822 | 773 | ||
823 | if (rxd->rate & MWL8K_8366_RATE_INFO_MCS_FORMAT) { | 774 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_MCS_FORMAT) { |
824 | status->flag |= RX_FLAG_HT; | 775 | status->flag |= RX_FLAG_HT; |
825 | if (rxd->rate & MWL8K_8366_RATE_INFO_40MHZ) | 776 | if (rxd->rate & MWL8K_8366_AP_RATE_INFO_40MHZ) |
826 | status->flag |= RX_FLAG_40MHZ; | 777 | status->flag |= RX_FLAG_40MHZ; |
827 | status->rate_idx = MWL8K_8366_RATE_INFO_RATEID(rxd->rate); | 778 | status->rate_idx = MWL8K_8366_AP_RATE_INFO_RATEID(rxd->rate); |
828 | } else { | 779 | } else { |
829 | int i; | 780 | int i; |
830 | 781 | ||
@@ -844,17 +795,17 @@ mwl8k_rxd_8366_process(void *_rxd, struct ieee80211_rx_status *status, | |||
844 | return le16_to_cpu(rxd->pkt_len); | 795 | return le16_to_cpu(rxd->pkt_len); |
845 | } | 796 | } |
846 | 797 | ||
847 | static struct rxd_ops rxd_8366_ops = { | 798 | static struct rxd_ops rxd_8366_ap_ops = { |
848 | .rxd_size = sizeof(struct mwl8k_rxd_8366), | 799 | .rxd_size = sizeof(struct mwl8k_rxd_8366_ap), |
849 | .rxd_init = mwl8k_rxd_8366_init, | 800 | .rxd_init = mwl8k_rxd_8366_ap_init, |
850 | .rxd_refill = mwl8k_rxd_8366_refill, | 801 | .rxd_refill = mwl8k_rxd_8366_ap_refill, |
851 | .rxd_process = mwl8k_rxd_8366_process, | 802 | .rxd_process = mwl8k_rxd_8366_ap_process, |
852 | }; | 803 | }; |
853 | 804 | ||
854 | /* | 805 | /* |
855 | * Packet reception for 88w8687. | 806 | * Packet reception for STA firmware. |
856 | */ | 807 | */ |
857 | struct mwl8k_rxd_8687 { | 808 | struct mwl8k_rxd_sta { |
858 | __le16 pkt_len; | 809 | __le16 pkt_len; |
859 | __u8 link_quality; | 810 | __u8 link_quality; |
860 | __u8 noise_level; | 811 | __u8 noise_level; |
@@ -871,26 +822,26 @@ struct mwl8k_rxd_8687 { | |||
871 | __u8 pad2[2]; | 822 | __u8 pad2[2]; |
872 | } __attribute__((packed)); | 823 | } __attribute__((packed)); |
873 | 824 | ||
874 | #define MWL8K_8687_RATE_INFO_SHORTPRE 0x8000 | 825 | #define MWL8K_STA_RATE_INFO_SHORTPRE 0x8000 |
875 | #define MWL8K_8687_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) | 826 | #define MWL8K_STA_RATE_INFO_ANTSELECT(x) (((x) >> 11) & 0x3) |
876 | #define MWL8K_8687_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) | 827 | #define MWL8K_STA_RATE_INFO_RATEID(x) (((x) >> 3) & 0x3f) |
877 | #define MWL8K_8687_RATE_INFO_40MHZ 0x0004 | 828 | #define MWL8K_STA_RATE_INFO_40MHZ 0x0004 |
878 | #define MWL8K_8687_RATE_INFO_SHORTGI 0x0002 | 829 | #define MWL8K_STA_RATE_INFO_SHORTGI 0x0002 |
879 | #define MWL8K_8687_RATE_INFO_MCS_FORMAT 0x0001 | 830 | #define MWL8K_STA_RATE_INFO_MCS_FORMAT 0x0001 |
880 | 831 | ||
881 | #define MWL8K_8687_RX_CTRL_OWNED_BY_HOST 0x02 | 832 | #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST 0x02 |
882 | 833 | ||
883 | static void mwl8k_rxd_8687_init(void *_rxd, dma_addr_t next_dma_addr) | 834 | static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr) |
884 | { | 835 | { |
885 | struct mwl8k_rxd_8687 *rxd = _rxd; | 836 | struct mwl8k_rxd_sta *rxd = _rxd; |
886 | 837 | ||
887 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); | 838 | rxd->next_rxd_phys_addr = cpu_to_le32(next_dma_addr); |
888 | rxd->rx_ctrl = MWL8K_8687_RX_CTRL_OWNED_BY_HOST; | 839 | rxd->rx_ctrl = MWL8K_STA_RX_CTRL_OWNED_BY_HOST; |
889 | } | 840 | } |
890 | 841 | ||
891 | static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | 842 | static void mwl8k_rxd_sta_refill(void *_rxd, dma_addr_t addr, int len) |
892 | { | 843 | { |
893 | struct mwl8k_rxd_8687 *rxd = _rxd; | 844 | struct mwl8k_rxd_sta *rxd = _rxd; |
894 | 845 | ||
895 | rxd->pkt_len = cpu_to_le16(len); | 846 | rxd->pkt_len = cpu_to_le16(len); |
896 | rxd->pkt_phys_addr = cpu_to_le32(addr); | 847 | rxd->pkt_phys_addr = cpu_to_le32(addr); |
@@ -899,13 +850,13 @@ static void mwl8k_rxd_8687_refill(void *_rxd, dma_addr_t addr, int len) | |||
899 | } | 850 | } |
900 | 851 | ||
901 | static int | 852 | static int |
902 | mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | 853 | mwl8k_rxd_sta_process(void *_rxd, struct ieee80211_rx_status *status, |
903 | __le16 *qos) | 854 | __le16 *qos) |
904 | { | 855 | { |
905 | struct mwl8k_rxd_8687 *rxd = _rxd; | 856 | struct mwl8k_rxd_sta *rxd = _rxd; |
906 | u16 rate_info; | 857 | u16 rate_info; |
907 | 858 | ||
908 | if (!(rxd->rx_ctrl & MWL8K_8687_RX_CTRL_OWNED_BY_HOST)) | 859 | if (!(rxd->rx_ctrl & MWL8K_STA_RX_CTRL_OWNED_BY_HOST)) |
909 | return -1; | 860 | return -1; |
910 | rmb(); | 861 | rmb(); |
911 | 862 | ||
@@ -915,16 +866,16 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | |||
915 | 866 | ||
916 | status->signal = -rxd->rssi; | 867 | status->signal = -rxd->rssi; |
917 | status->noise = -rxd->noise_level; | 868 | status->noise = -rxd->noise_level; |
918 | status->antenna = MWL8K_8687_RATE_INFO_ANTSELECT(rate_info); | 869 | status->antenna = MWL8K_STA_RATE_INFO_ANTSELECT(rate_info); |
919 | status->rate_idx = MWL8K_8687_RATE_INFO_RATEID(rate_info); | 870 | status->rate_idx = MWL8K_STA_RATE_INFO_RATEID(rate_info); |
920 | 871 | ||
921 | if (rate_info & MWL8K_8687_RATE_INFO_SHORTPRE) | 872 | if (rate_info & MWL8K_STA_RATE_INFO_SHORTPRE) |
922 | status->flag |= RX_FLAG_SHORTPRE; | 873 | status->flag |= RX_FLAG_SHORTPRE; |
923 | if (rate_info & MWL8K_8687_RATE_INFO_40MHZ) | 874 | if (rate_info & MWL8K_STA_RATE_INFO_40MHZ) |
924 | status->flag |= RX_FLAG_40MHZ; | 875 | status->flag |= RX_FLAG_40MHZ; |
925 | if (rate_info & MWL8K_8687_RATE_INFO_SHORTGI) | 876 | if (rate_info & MWL8K_STA_RATE_INFO_SHORTGI) |
926 | status->flag |= RX_FLAG_SHORT_GI; | 877 | status->flag |= RX_FLAG_SHORT_GI; |
927 | if (rate_info & MWL8K_8687_RATE_INFO_MCS_FORMAT) | 878 | if (rate_info & MWL8K_STA_RATE_INFO_MCS_FORMAT) |
928 | status->flag |= RX_FLAG_HT; | 879 | status->flag |= RX_FLAG_HT; |
929 | 880 | ||
930 | status->band = IEEE80211_BAND_2GHZ; | 881 | status->band = IEEE80211_BAND_2GHZ; |
@@ -935,11 +886,11 @@ mwl8k_rxd_8687_process(void *_rxd, struct ieee80211_rx_status *status, | |||
935 | return le16_to_cpu(rxd->pkt_len); | 886 | return le16_to_cpu(rxd->pkt_len); |
936 | } | 887 | } |
937 | 888 | ||
938 | static struct rxd_ops rxd_8687_ops = { | 889 | static struct rxd_ops rxd_sta_ops = { |
939 | .rxd_size = sizeof(struct mwl8k_rxd_8687), | 890 | .rxd_size = sizeof(struct mwl8k_rxd_sta), |
940 | .rxd_init = mwl8k_rxd_8687_init, | 891 | .rxd_init = mwl8k_rxd_sta_init, |
941 | .rxd_refill = mwl8k_rxd_8687_refill, | 892 | .rxd_refill = mwl8k_rxd_sta_refill, |
942 | .rxd_process = mwl8k_rxd_8687_process, | 893 | .rxd_process = mwl8k_rxd_sta_process, |
943 | }; | 894 | }; |
944 | 895 | ||
945 | 896 | ||
@@ -1153,16 +1104,18 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1153 | * Packet transmission. | 1104 | * Packet transmission. |
1154 | */ | 1105 | */ |
1155 | 1106 | ||
1156 | /* Transmit packet ACK policy */ | ||
1157 | #define MWL8K_TXD_ACK_POLICY_NORMAL 0 | ||
1158 | #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 | ||
1159 | |||
1160 | #define MWL8K_TXD_STATUS_OK 0x00000001 | 1107 | #define MWL8K_TXD_STATUS_OK 0x00000001 |
1161 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 | 1108 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 |
1162 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 | 1109 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 |
1163 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 | 1110 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 |
1164 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 | 1111 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 |
1165 | 1112 | ||
1113 | #define MWL8K_QOS_QLEN_UNSPEC 0xff00 | ||
1114 | #define MWL8K_QOS_ACK_POLICY_MASK 0x0060 | ||
1115 | #define MWL8K_QOS_ACK_POLICY_NORMAL 0x0000 | ||
1116 | #define MWL8K_QOS_ACK_POLICY_BLOCKACK 0x0060 | ||
1117 | #define MWL8K_QOS_EOSP 0x0010 | ||
1118 | |||
1166 | struct mwl8k_tx_desc { | 1119 | struct mwl8k_tx_desc { |
1167 | __le32 status; | 1120 | __le32 status; |
1168 | __u8 data_rate; | 1121 | __u8 data_rate; |
@@ -1459,24 +1412,17 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1459 | if (ieee80211_is_mgmt(wh->frame_control) || | 1412 | if (ieee80211_is_mgmt(wh->frame_control) || |
1460 | ieee80211_is_ctl(wh->frame_control)) { | 1413 | ieee80211_is_ctl(wh->frame_control)) { |
1461 | txdatarate = 0; | 1414 | txdatarate = 0; |
1462 | qos = mwl8k_qos_setbit_eosp(qos); | 1415 | qos |= MWL8K_QOS_QLEN_UNSPEC | MWL8K_QOS_EOSP; |
1463 | /* Set Queue size to unspecified */ | ||
1464 | qos = mwl8k_qos_setbit_qlen(qos, 0xff); | ||
1465 | } else if (ieee80211_is_data(wh->frame_control)) { | 1416 | } else if (ieee80211_is_data(wh->frame_control)) { |
1466 | txdatarate = 1; | 1417 | txdatarate = 1; |
1467 | if (is_multicast_ether_addr(wh->addr1)) | 1418 | if (is_multicast_ether_addr(wh->addr1)) |
1468 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; | 1419 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; |
1469 | 1420 | ||
1470 | /* Send pkt in an aggregate if AMPDU frame. */ | 1421 | qos &= ~MWL8K_QOS_ACK_POLICY_MASK; |
1471 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | 1422 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) |
1472 | qos = mwl8k_qos_setbit_ack(qos, | 1423 | qos |= MWL8K_QOS_ACK_POLICY_BLOCKACK; |
1473 | MWL8K_TXD_ACK_POLICY_BLOCKACK); | ||
1474 | else | 1424 | else |
1475 | qos = mwl8k_qos_setbit_ack(qos, | 1425 | qos |= MWL8K_QOS_ACK_POLICY_NORMAL; |
1476 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1477 | |||
1478 | if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
1479 | qos = mwl8k_qos_setbit_amsdu(qos); | ||
1480 | } | 1426 | } |
1481 | 1427 | ||
1482 | dma = pci_map_single(priv->pdev, skb->data, | 1428 | dma = pci_map_single(priv->pdev, skb->data, |
@@ -1897,9 +1843,9 @@ __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, int allmulti, | |||
1897 | } | 1843 | } |
1898 | 1844 | ||
1899 | /* | 1845 | /* |
1900 | * CMD_802_11_GET_STAT. | 1846 | * CMD_GET_STAT. |
1901 | */ | 1847 | */ |
1902 | struct mwl8k_cmd_802_11_get_stat { | 1848 | struct mwl8k_cmd_get_stat { |
1903 | struct mwl8k_cmd_pkt header; | 1849 | struct mwl8k_cmd_pkt header; |
1904 | __le32 stats[64]; | 1850 | __le32 stats[64]; |
1905 | } __attribute__((packed)); | 1851 | } __attribute__((packed)); |
@@ -1909,10 +1855,10 @@ struct mwl8k_cmd_802_11_get_stat { | |||
1909 | #define MWL8K_STAT_FCS_ERROR 24 | 1855 | #define MWL8K_STAT_FCS_ERROR 24 |
1910 | #define MWL8K_STAT_RTS_SUCCESS 11 | 1856 | #define MWL8K_STAT_RTS_SUCCESS 11 |
1911 | 1857 | ||
1912 | static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | 1858 | static int mwl8k_cmd_get_stat(struct ieee80211_hw *hw, |
1913 | struct ieee80211_low_level_stats *stats) | 1859 | struct ieee80211_low_level_stats *stats) |
1914 | { | 1860 | { |
1915 | struct mwl8k_cmd_802_11_get_stat *cmd; | 1861 | struct mwl8k_cmd_get_stat *cmd; |
1916 | int rc; | 1862 | int rc; |
1917 | 1863 | ||
1918 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1864 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -1939,9 +1885,9 @@ static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, | |||
1939 | } | 1885 | } |
1940 | 1886 | ||
1941 | /* | 1887 | /* |
1942 | * CMD_802_11_RADIO_CONTROL. | 1888 | * CMD_RADIO_CONTROL. |
1943 | */ | 1889 | */ |
1944 | struct mwl8k_cmd_802_11_radio_control { | 1890 | struct mwl8k_cmd_radio_control { |
1945 | struct mwl8k_cmd_pkt header; | 1891 | struct mwl8k_cmd_pkt header; |
1946 | __le16 action; | 1892 | __le16 action; |
1947 | __le16 control; | 1893 | __le16 control; |
@@ -1949,10 +1895,10 @@ struct mwl8k_cmd_802_11_radio_control { | |||
1949 | } __attribute__((packed)); | 1895 | } __attribute__((packed)); |
1950 | 1896 | ||
1951 | static int | 1897 | static int |
1952 | mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | 1898 | mwl8k_cmd_radio_control(struct ieee80211_hw *hw, bool enable, bool force) |
1953 | { | 1899 | { |
1954 | struct mwl8k_priv *priv = hw->priv; | 1900 | struct mwl8k_priv *priv = hw->priv; |
1955 | struct mwl8k_cmd_802_11_radio_control *cmd; | 1901 | struct mwl8k_cmd_radio_control *cmd; |
1956 | int rc; | 1902 | int rc; |
1957 | 1903 | ||
1958 | if (enable == priv->radio_on && !force) | 1904 | if (enable == priv->radio_on && !force) |
@@ -1977,36 +1923,32 @@ mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | |||
1977 | return rc; | 1923 | return rc; |
1978 | } | 1924 | } |
1979 | 1925 | ||
1980 | static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) | 1926 | static int mwl8k_cmd_radio_disable(struct ieee80211_hw *hw) |
1981 | { | 1927 | { |
1982 | return mwl8k_cmd_802_11_radio_control(hw, 0, 0); | 1928 | return mwl8k_cmd_radio_control(hw, 0, 0); |
1983 | } | 1929 | } |
1984 | 1930 | ||
1985 | static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) | 1931 | static int mwl8k_cmd_radio_enable(struct ieee80211_hw *hw) |
1986 | { | 1932 | { |
1987 | return mwl8k_cmd_802_11_radio_control(hw, 1, 0); | 1933 | return mwl8k_cmd_radio_control(hw, 1, 0); |
1988 | } | 1934 | } |
1989 | 1935 | ||
1990 | static int | 1936 | static int |
1991 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) | 1937 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) |
1992 | { | 1938 | { |
1993 | struct mwl8k_priv *priv; | 1939 | struct mwl8k_priv *priv = hw->priv; |
1994 | |||
1995 | if (hw == NULL || hw->priv == NULL) | ||
1996 | return -EINVAL; | ||
1997 | priv = hw->priv; | ||
1998 | 1940 | ||
1999 | priv->radio_short_preamble = short_preamble; | 1941 | priv->radio_short_preamble = short_preamble; |
2000 | 1942 | ||
2001 | return mwl8k_cmd_802_11_radio_control(hw, 1, 1); | 1943 | return mwl8k_cmd_radio_control(hw, 1, 1); |
2002 | } | 1944 | } |
2003 | 1945 | ||
2004 | /* | 1946 | /* |
2005 | * CMD_802_11_RF_TX_POWER. | 1947 | * CMD_RF_TX_POWER. |
2006 | */ | 1948 | */ |
2007 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 | 1949 | #define MWL8K_TX_POWER_LEVEL_TOTAL 8 |
2008 | 1950 | ||
2009 | struct mwl8k_cmd_802_11_rf_tx_power { | 1951 | struct mwl8k_cmd_rf_tx_power { |
2010 | struct mwl8k_cmd_pkt header; | 1952 | struct mwl8k_cmd_pkt header; |
2011 | __le16 action; | 1953 | __le16 action; |
2012 | __le16 support_level; | 1954 | __le16 support_level; |
@@ -2015,9 +1957,9 @@ struct mwl8k_cmd_802_11_rf_tx_power { | |||
2015 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; | 1957 | __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; |
2016 | } __attribute__((packed)); | 1958 | } __attribute__((packed)); |
2017 | 1959 | ||
2018 | static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) | 1960 | static int mwl8k_cmd_rf_tx_power(struct ieee80211_hw *hw, int dBm) |
2019 | { | 1961 | { |
2020 | struct mwl8k_cmd_802_11_rf_tx_power *cmd; | 1962 | struct mwl8k_cmd_rf_tx_power *cmd; |
2021 | int rc; | 1963 | int rc; |
2022 | 1964 | ||
2023 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1965 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
@@ -2159,85 +2101,60 @@ static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, | |||
2159 | } | 2101 | } |
2160 | 2102 | ||
2161 | /* | 2103 | /* |
2162 | * CMD_SET_SLOT. | 2104 | * CMD_SET_AID. |
2163 | */ | 2105 | */ |
2164 | struct mwl8k_cmd_set_slot { | 2106 | #define MWL8K_FRAME_PROT_DISABLED 0x00 |
2165 | struct mwl8k_cmd_pkt header; | 2107 | #define MWL8K_FRAME_PROT_11G 0x07 |
2166 | __le16 action; | 2108 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 |
2167 | __u8 short_slot; | 2109 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 |
2168 | } __attribute__((packed)); | ||
2169 | |||
2170 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) | ||
2171 | { | ||
2172 | struct mwl8k_cmd_set_slot *cmd; | ||
2173 | int rc; | ||
2174 | |||
2175 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2176 | if (cmd == NULL) | ||
2177 | return -ENOMEM; | ||
2178 | |||
2179 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); | ||
2180 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2181 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2182 | cmd->short_slot = short_slot_time; | ||
2183 | |||
2184 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2185 | kfree(cmd); | ||
2186 | 2110 | ||
2187 | return rc; | 2111 | struct mwl8k_cmd_update_set_aid { |
2188 | } | 2112 | struct mwl8k_cmd_pkt header; |
2113 | __le16 aid; | ||
2189 | 2114 | ||
2190 | /* | 2115 | /* AP's MAC address (BSSID) */ |
2191 | * CMD_MIMO_CONFIG. | 2116 | __u8 bssid[ETH_ALEN]; |
2192 | */ | 2117 | __le16 protection_mode; |
2193 | struct mwl8k_cmd_mimo_config { | 2118 | __u8 supp_rates[14]; |
2194 | struct mwl8k_cmd_pkt header; | ||
2195 | __le32 action; | ||
2196 | __u8 rx_antenna_map; | ||
2197 | __u8 tx_antenna_map; | ||
2198 | } __attribute__((packed)); | 2119 | } __attribute__((packed)); |
2199 | 2120 | ||
2200 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) | 2121 | static int |
2122 | mwl8k_cmd_set_aid(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
2201 | { | 2123 | { |
2202 | struct mwl8k_cmd_mimo_config *cmd; | 2124 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); |
2125 | struct mwl8k_cmd_update_set_aid *cmd; | ||
2126 | u16 prot_mode; | ||
2203 | int rc; | 2127 | int rc; |
2204 | 2128 | ||
2205 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2129 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2206 | if (cmd == NULL) | 2130 | if (cmd == NULL) |
2207 | return -ENOMEM; | 2131 | return -ENOMEM; |
2208 | 2132 | ||
2209 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); | 2133 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); |
2210 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2134 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2211 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); | 2135 | cmd->aid = cpu_to_le16(vif->bss_conf.aid); |
2212 | cmd->rx_antenna_map = rx; | ||
2213 | cmd->tx_antenna_map = tx; | ||
2214 | |||
2215 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2216 | kfree(cmd); | ||
2217 | 2136 | ||
2218 | return rc; | 2137 | memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); |
2219 | } | ||
2220 | |||
2221 | /* | ||
2222 | * CMD_ENABLE_SNIFFER. | ||
2223 | */ | ||
2224 | struct mwl8k_cmd_enable_sniffer { | ||
2225 | struct mwl8k_cmd_pkt header; | ||
2226 | __le32 action; | ||
2227 | } __attribute__((packed)); | ||
2228 | |||
2229 | static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | ||
2230 | { | ||
2231 | struct mwl8k_cmd_enable_sniffer *cmd; | ||
2232 | int rc; | ||
2233 | 2138 | ||
2234 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2139 | if (vif->bss_conf.use_cts_prot) { |
2235 | if (cmd == NULL) | 2140 | prot_mode = MWL8K_FRAME_PROT_11G; |
2236 | return -ENOMEM; | 2141 | } else { |
2142 | switch (vif->bss_conf.ht_operation_mode & | ||
2143 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2144 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2145 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2146 | break; | ||
2147 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2148 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2149 | break; | ||
2150 | default: | ||
2151 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2152 | break; | ||
2153 | } | ||
2154 | } | ||
2155 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2237 | 2156 | ||
2238 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | 2157 | memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); |
2239 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2240 | cmd->action = cpu_to_le32(!!enable); | ||
2241 | 2158 | ||
2242 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2159 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2243 | kfree(cmd); | 2160 | kfree(cmd); |
@@ -2246,37 +2163,30 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | |||
2246 | } | 2163 | } |
2247 | 2164 | ||
2248 | /* | 2165 | /* |
2249 | * CMD_SET_MAC_ADDR. | 2166 | * CMD_SET_RATE. |
2250 | */ | 2167 | */ |
2251 | struct mwl8k_cmd_set_mac_addr { | 2168 | struct mwl8k_cmd_set_rate { |
2252 | struct mwl8k_cmd_pkt header; | 2169 | struct mwl8k_cmd_pkt header; |
2253 | union { | 2170 | __u8 legacy_rates[14]; |
2254 | struct { | 2171 | |
2255 | __le16 mac_type; | 2172 | /* Bitmap for supported MCS codes. */ |
2256 | __u8 mac_addr[ETH_ALEN]; | 2173 | __u8 mcs_set[16]; |
2257 | } mbss; | 2174 | __u8 reserved[16]; |
2258 | __u8 mac_addr[ETH_ALEN]; | ||
2259 | }; | ||
2260 | } __attribute__((packed)); | 2175 | } __attribute__((packed)); |
2261 | 2176 | ||
2262 | static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | 2177 | static int |
2178 | mwl8k_cmd_set_rate(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | ||
2263 | { | 2179 | { |
2264 | struct mwl8k_priv *priv = hw->priv; | 2180 | struct mwl8k_cmd_set_rate *cmd; |
2265 | struct mwl8k_cmd_set_mac_addr *cmd; | ||
2266 | int rc; | 2181 | int rc; |
2267 | 2182 | ||
2268 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2183 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2269 | if (cmd == NULL) | 2184 | if (cmd == NULL) |
2270 | return -ENOMEM; | 2185 | return -ENOMEM; |
2271 | 2186 | ||
2272 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | 2187 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); |
2273 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2188 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2274 | if (priv->ap_fw) { | 2189 | memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); |
2275 | cmd->mbss.mac_type = 0; | ||
2276 | memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); | ||
2277 | } else { | ||
2278 | memcpy(cmd->mac_addr, mac, ETH_ALEN); | ||
2279 | } | ||
2280 | 2190 | ||
2281 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2191 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2282 | kfree(cmd); | 2192 | kfree(cmd); |
@@ -2284,29 +2194,40 @@ static int mwl8k_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | |||
2284 | return rc; | 2194 | return rc; |
2285 | } | 2195 | } |
2286 | 2196 | ||
2287 | |||
2288 | /* | 2197 | /* |
2289 | * CMD_SET_RATEADAPT_MODE. | 2198 | * CMD_FINALIZE_JOIN. |
2290 | */ | 2199 | */ |
2291 | struct mwl8k_cmd_set_rate_adapt_mode { | 2200 | #define MWL8K_FJ_BEACON_MAXLEN 128 |
2201 | |||
2202 | struct mwl8k_cmd_finalize_join { | ||
2292 | struct mwl8k_cmd_pkt header; | 2203 | struct mwl8k_cmd_pkt header; |
2293 | __le16 action; | 2204 | __le32 sleep_interval; /* Number of beacon periods to sleep */ |
2294 | __le16 mode; | 2205 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; |
2295 | } __attribute__((packed)); | 2206 | } __attribute__((packed)); |
2296 | 2207 | ||
2297 | static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | 2208 | static int mwl8k_cmd_finalize_join(struct ieee80211_hw *hw, void *frame, |
2209 | int framelen, int dtim) | ||
2298 | { | 2210 | { |
2299 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | 2211 | struct mwl8k_cmd_finalize_join *cmd; |
2212 | struct ieee80211_mgmt *payload = frame; | ||
2213 | int payload_len; | ||
2300 | int rc; | 2214 | int rc; |
2301 | 2215 | ||
2302 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2216 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2303 | if (cmd == NULL) | 2217 | if (cmd == NULL) |
2304 | return -ENOMEM; | 2218 | return -ENOMEM; |
2305 | 2219 | ||
2306 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | 2220 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); |
2307 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2221 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2308 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 2222 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); |
2309 | cmd->mode = cpu_to_le16(mode); | 2223 | |
2224 | payload_len = framelen - ieee80211_hdrlen(payload->frame_control); | ||
2225 | if (payload_len < 0) | ||
2226 | payload_len = 0; | ||
2227 | else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2228 | payload_len = MWL8K_FJ_BEACON_MAXLEN; | ||
2229 | |||
2230 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2310 | 2231 | ||
2311 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2232 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2312 | kfree(cmd); | 2233 | kfree(cmd); |
@@ -2315,59 +2236,57 @@ static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) | |||
2315 | } | 2236 | } |
2316 | 2237 | ||
2317 | /* | 2238 | /* |
2318 | * CMD_SET_WMM_MODE. | 2239 | * CMD_SET_RTS_THRESHOLD. |
2319 | */ | 2240 | */ |
2320 | struct mwl8k_cmd_set_wmm { | 2241 | struct mwl8k_cmd_set_rts_threshold { |
2321 | struct mwl8k_cmd_pkt header; | 2242 | struct mwl8k_cmd_pkt header; |
2322 | __le16 action; | 2243 | __le16 action; |
2244 | __le16 threshold; | ||
2323 | } __attribute__((packed)); | 2245 | } __attribute__((packed)); |
2324 | 2246 | ||
2325 | static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) | 2247 | static int mwl8k_cmd_set_rts_threshold(struct ieee80211_hw *hw, |
2248 | u16 action, u16 threshold) | ||
2326 | { | 2249 | { |
2327 | struct mwl8k_priv *priv = hw->priv; | 2250 | struct mwl8k_cmd_set_rts_threshold *cmd; |
2328 | struct mwl8k_cmd_set_wmm *cmd; | ||
2329 | int rc; | 2251 | int rc; |
2330 | 2252 | ||
2331 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2253 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2332 | if (cmd == NULL) | 2254 | if (cmd == NULL) |
2333 | return -ENOMEM; | 2255 | return -ENOMEM; |
2334 | 2256 | ||
2335 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); | 2257 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); |
2336 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2258 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2337 | cmd->action = cpu_to_le16(!!enable); | 2259 | cmd->action = cpu_to_le16(action); |
2260 | cmd->threshold = cpu_to_le16(threshold); | ||
2338 | 2261 | ||
2339 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2262 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2340 | kfree(cmd); | 2263 | kfree(cmd); |
2341 | 2264 | ||
2342 | if (!rc) | ||
2343 | priv->wmm_enabled = enable; | ||
2344 | |||
2345 | return rc; | 2265 | return rc; |
2346 | } | 2266 | } |
2347 | 2267 | ||
2348 | /* | 2268 | /* |
2349 | * CMD_SET_RTS_THRESHOLD. | 2269 | * CMD_SET_SLOT. |
2350 | */ | 2270 | */ |
2351 | struct mwl8k_cmd_rts_threshold { | 2271 | struct mwl8k_cmd_set_slot { |
2352 | struct mwl8k_cmd_pkt header; | 2272 | struct mwl8k_cmd_pkt header; |
2353 | __le16 action; | 2273 | __le16 action; |
2354 | __le16 threshold; | 2274 | __u8 short_slot; |
2355 | } __attribute__((packed)); | 2275 | } __attribute__((packed)); |
2356 | 2276 | ||
2357 | static int mwl8k_rts_threshold(struct ieee80211_hw *hw, | 2277 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) |
2358 | u16 action, u16 threshold) | ||
2359 | { | 2278 | { |
2360 | struct mwl8k_cmd_rts_threshold *cmd; | 2279 | struct mwl8k_cmd_set_slot *cmd; |
2361 | int rc; | 2280 | int rc; |
2362 | 2281 | ||
2363 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2282 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2364 | if (cmd == NULL) | 2283 | if (cmd == NULL) |
2365 | return -ENOMEM; | 2284 | return -ENOMEM; |
2366 | 2285 | ||
2367 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); | 2286 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); |
2368 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2287 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2369 | cmd->action = cpu_to_le16(action); | 2288 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
2370 | cmd->threshold = cpu_to_le16(threshold); | 2289 | cmd->short_slot = short_slot_time; |
2371 | 2290 | ||
2372 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2291 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2373 | kfree(cmd); | 2292 | kfree(cmd); |
@@ -2426,9 +2345,9 @@ struct mwl8k_cmd_set_edca_params { | |||
2426 | MWL8K_SET_EDCA_AIFS) | 2345 | MWL8K_SET_EDCA_AIFS) |
2427 | 2346 | ||
2428 | static int | 2347 | static int |
2429 | mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | 2348 | mwl8k_cmd_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, |
2430 | __u16 cw_min, __u16 cw_max, | 2349 | __u16 cw_min, __u16 cw_max, |
2431 | __u8 aifs, __u16 txop) | 2350 | __u8 aifs, __u16 txop) |
2432 | { | 2351 | { |
2433 | struct mwl8k_priv *priv = hw->priv; | 2352 | struct mwl8k_priv *priv = hw->priv; |
2434 | struct mwl8k_cmd_set_edca_params *cmd; | 2353 | struct mwl8k_cmd_set_edca_params *cmd; |
@@ -2467,202 +2386,60 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | |||
2467 | } | 2386 | } |
2468 | 2387 | ||
2469 | /* | 2388 | /* |
2470 | * CMD_FINALIZE_JOIN. | 2389 | * CMD_SET_WMM_MODE. |
2471 | */ | 2390 | */ |
2472 | #define MWL8K_FJ_BEACON_MAXLEN 128 | 2391 | struct mwl8k_cmd_set_wmm_mode { |
2473 | |||
2474 | struct mwl8k_cmd_finalize_join { | ||
2475 | struct mwl8k_cmd_pkt header; | 2392 | struct mwl8k_cmd_pkt header; |
2476 | __le32 sleep_interval; /* Number of beacon periods to sleep */ | 2393 | __le16 action; |
2477 | __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; | ||
2478 | } __attribute__((packed)); | 2394 | } __attribute__((packed)); |
2479 | 2395 | ||
2480 | static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, | 2396 | static int mwl8k_cmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable) |
2481 | int framelen, int dtim) | ||
2482 | { | 2397 | { |
2483 | struct mwl8k_cmd_finalize_join *cmd; | 2398 | struct mwl8k_priv *priv = hw->priv; |
2484 | struct ieee80211_mgmt *payload = frame; | 2399 | struct mwl8k_cmd_set_wmm_mode *cmd; |
2485 | int payload_len; | ||
2486 | int rc; | 2400 | int rc; |
2487 | 2401 | ||
2488 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2402 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2489 | if (cmd == NULL) | 2403 | if (cmd == NULL) |
2490 | return -ENOMEM; | 2404 | return -ENOMEM; |
2491 | 2405 | ||
2492 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); | 2406 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); |
2493 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2407 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2494 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); | 2408 | cmd->action = cpu_to_le16(!!enable); |
2495 | |||
2496 | payload_len = framelen - ieee80211_hdrlen(payload->frame_control); | ||
2497 | if (payload_len < 0) | ||
2498 | payload_len = 0; | ||
2499 | else if (payload_len > MWL8K_FJ_BEACON_MAXLEN) | ||
2500 | payload_len = MWL8K_FJ_BEACON_MAXLEN; | ||
2501 | |||
2502 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | ||
2503 | 2409 | ||
2504 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2410 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2505 | kfree(cmd); | 2411 | kfree(cmd); |
2506 | 2412 | ||
2507 | return rc; | 2413 | if (!rc) |
2508 | } | 2414 | priv->wmm_enabled = enable; |
2509 | |||
2510 | /* | ||
2511 | * CMD_UPDATE_STADB. | ||
2512 | */ | ||
2513 | struct mwl8k_cmd_update_sta_db { | ||
2514 | struct mwl8k_cmd_pkt header; | ||
2515 | |||
2516 | /* See STADB_ACTION_TYPE */ | ||
2517 | __le32 action; | ||
2518 | |||
2519 | /* Peer MAC address */ | ||
2520 | __u8 peer_addr[ETH_ALEN]; | ||
2521 | |||
2522 | __le32 reserved; | ||
2523 | |||
2524 | /* Peer info - valid during add/update. */ | ||
2525 | struct peer_capability_info peer_info; | ||
2526 | } __attribute__((packed)); | ||
2527 | |||
2528 | static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | ||
2529 | struct ieee80211_vif *vif, __u32 action) | ||
2530 | { | ||
2531 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2532 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2533 | struct mwl8k_cmd_update_sta_db *cmd; | ||
2534 | struct peer_capability_info *peer_info; | ||
2535 | int rc; | ||
2536 | |||
2537 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2538 | if (cmd == NULL) | ||
2539 | return -ENOMEM; | ||
2540 | |||
2541 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | ||
2542 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2543 | |||
2544 | cmd->action = cpu_to_le32(action); | ||
2545 | peer_info = &cmd->peer_info; | ||
2546 | memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); | ||
2547 | |||
2548 | switch (action) { | ||
2549 | case MWL8K_STA_DB_ADD_ENTRY: | ||
2550 | case MWL8K_STA_DB_MODIFY_ENTRY: | ||
2551 | /* Build peer_info block */ | ||
2552 | peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
2553 | peer_info->basic_caps = cpu_to_le16(info->assoc_capability); | ||
2554 | memcpy(peer_info->legacy_rates, mwl8k_rateids, | ||
2555 | sizeof(mwl8k_rateids)); | ||
2556 | peer_info->interop = 1; | ||
2557 | peer_info->amsdu_enabled = 0; | ||
2558 | |||
2559 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2560 | if (rc == 0) | ||
2561 | mv_vif->peer_id = peer_info->station_id; | ||
2562 | |||
2563 | break; | ||
2564 | |||
2565 | case MWL8K_STA_DB_DEL_ENTRY: | ||
2566 | case MWL8K_STA_DB_FLUSH: | ||
2567 | default: | ||
2568 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2569 | if (rc == 0) | ||
2570 | mv_vif->peer_id = 0; | ||
2571 | break; | ||
2572 | } | ||
2573 | kfree(cmd); | ||
2574 | |||
2575 | return rc; | ||
2576 | } | ||
2577 | |||
2578 | /* | ||
2579 | * CMD_SET_AID. | ||
2580 | */ | ||
2581 | #define MWL8K_FRAME_PROT_DISABLED 0x00 | ||
2582 | #define MWL8K_FRAME_PROT_11G 0x07 | ||
2583 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 | ||
2584 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 | ||
2585 | |||
2586 | struct mwl8k_cmd_update_set_aid { | ||
2587 | struct mwl8k_cmd_pkt header; | ||
2588 | __le16 aid; | ||
2589 | |||
2590 | /* AP's MAC address (BSSID) */ | ||
2591 | __u8 bssid[ETH_ALEN]; | ||
2592 | __le16 protection_mode; | ||
2593 | __u8 supp_rates[14]; | ||
2594 | } __attribute__((packed)); | ||
2595 | |||
2596 | static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | ||
2597 | struct ieee80211_vif *vif) | ||
2598 | { | ||
2599 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2600 | struct ieee80211_bss_conf *info = &mv_vif->bss_info; | ||
2601 | struct mwl8k_cmd_update_set_aid *cmd; | ||
2602 | u16 prot_mode; | ||
2603 | int rc; | ||
2604 | |||
2605 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2606 | if (cmd == NULL) | ||
2607 | return -ENOMEM; | ||
2608 | |||
2609 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); | ||
2610 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2611 | cmd->aid = cpu_to_le16(info->aid); | ||
2612 | |||
2613 | memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); | ||
2614 | |||
2615 | if (info->use_cts_prot) { | ||
2616 | prot_mode = MWL8K_FRAME_PROT_11G; | ||
2617 | } else { | ||
2618 | switch (info->ht_operation_mode & | ||
2619 | IEEE80211_HT_OP_MODE_PROTECTION) { | ||
2620 | case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: | ||
2621 | prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; | ||
2622 | break; | ||
2623 | case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: | ||
2624 | prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; | ||
2625 | break; | ||
2626 | default: | ||
2627 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2628 | break; | ||
2629 | } | ||
2630 | } | ||
2631 | cmd->protection_mode = cpu_to_le16(prot_mode); | ||
2632 | |||
2633 | memcpy(cmd->supp_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); | ||
2634 | |||
2635 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2636 | kfree(cmd); | ||
2637 | 2415 | ||
2638 | return rc; | 2416 | return rc; |
2639 | } | 2417 | } |
2640 | 2418 | ||
2641 | /* | 2419 | /* |
2642 | * CMD_SET_RATE. | 2420 | * CMD_MIMO_CONFIG. |
2643 | */ | 2421 | */ |
2644 | struct mwl8k_cmd_update_rateset { | 2422 | struct mwl8k_cmd_mimo_config { |
2645 | struct mwl8k_cmd_pkt header; | 2423 | struct mwl8k_cmd_pkt header; |
2646 | __u8 legacy_rates[14]; | 2424 | __le32 action; |
2647 | 2425 | __u8 rx_antenna_map; | |
2648 | /* Bitmap for supported MCS codes. */ | 2426 | __u8 tx_antenna_map; |
2649 | __u8 mcs_set[16]; | ||
2650 | __u8 reserved[16]; | ||
2651 | } __attribute__((packed)); | 2427 | } __attribute__((packed)); |
2652 | 2428 | ||
2653 | static int mwl8k_update_rateset(struct ieee80211_hw *hw, | 2429 | static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) |
2654 | struct ieee80211_vif *vif) | ||
2655 | { | 2430 | { |
2656 | struct mwl8k_cmd_update_rateset *cmd; | 2431 | struct mwl8k_cmd_mimo_config *cmd; |
2657 | int rc; | 2432 | int rc; |
2658 | 2433 | ||
2659 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2434 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2660 | if (cmd == NULL) | 2435 | if (cmd == NULL) |
2661 | return -ENOMEM; | 2436 | return -ENOMEM; |
2662 | 2437 | ||
2663 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); | 2438 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); |
2664 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2439 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2665 | memcpy(cmd->legacy_rates, mwl8k_rateids, sizeof(mwl8k_rateids)); | 2440 | cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); |
2441 | cmd->rx_antenna_map = rx; | ||
2442 | cmd->tx_antenna_map = tx; | ||
2666 | 2443 | ||
2667 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2444 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2668 | kfree(cmd); | 2445 | kfree(cmd); |
@@ -2755,6 +2532,169 @@ static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, | |||
2755 | return rc; | 2532 | return rc; |
2756 | } | 2533 | } |
2757 | 2534 | ||
2535 | /* | ||
2536 | * CMD_ENABLE_SNIFFER. | ||
2537 | */ | ||
2538 | struct mwl8k_cmd_enable_sniffer { | ||
2539 | struct mwl8k_cmd_pkt header; | ||
2540 | __le32 action; | ||
2541 | } __attribute__((packed)); | ||
2542 | |||
2543 | static int mwl8k_cmd_enable_sniffer(struct ieee80211_hw *hw, bool enable) | ||
2544 | { | ||
2545 | struct mwl8k_cmd_enable_sniffer *cmd; | ||
2546 | int rc; | ||
2547 | |||
2548 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2549 | if (cmd == NULL) | ||
2550 | return -ENOMEM; | ||
2551 | |||
2552 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | ||
2553 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2554 | cmd->action = cpu_to_le32(!!enable); | ||
2555 | |||
2556 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2557 | kfree(cmd); | ||
2558 | |||
2559 | return rc; | ||
2560 | } | ||
2561 | |||
2562 | /* | ||
2563 | * CMD_SET_MAC_ADDR. | ||
2564 | */ | ||
2565 | struct mwl8k_cmd_set_mac_addr { | ||
2566 | struct mwl8k_cmd_pkt header; | ||
2567 | union { | ||
2568 | struct { | ||
2569 | __le16 mac_type; | ||
2570 | __u8 mac_addr[ETH_ALEN]; | ||
2571 | } mbss; | ||
2572 | __u8 mac_addr[ETH_ALEN]; | ||
2573 | }; | ||
2574 | } __attribute__((packed)); | ||
2575 | |||
2576 | static int mwl8k_cmd_set_mac_addr(struct ieee80211_hw *hw, u8 *mac) | ||
2577 | { | ||
2578 | struct mwl8k_priv *priv = hw->priv; | ||
2579 | struct mwl8k_cmd_set_mac_addr *cmd; | ||
2580 | int rc; | ||
2581 | |||
2582 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2583 | if (cmd == NULL) | ||
2584 | return -ENOMEM; | ||
2585 | |||
2586 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_MAC_ADDR); | ||
2587 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2588 | if (priv->ap_fw) { | ||
2589 | cmd->mbss.mac_type = 0; | ||
2590 | memcpy(cmd->mbss.mac_addr, mac, ETH_ALEN); | ||
2591 | } else { | ||
2592 | memcpy(cmd->mac_addr, mac, ETH_ALEN); | ||
2593 | } | ||
2594 | |||
2595 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2596 | kfree(cmd); | ||
2597 | |||
2598 | return rc; | ||
2599 | } | ||
2600 | |||
2601 | /* | ||
2602 | * CMD_SET_RATEADAPT_MODE. | ||
2603 | */ | ||
2604 | struct mwl8k_cmd_set_rate_adapt_mode { | ||
2605 | struct mwl8k_cmd_pkt header; | ||
2606 | __le16 action; | ||
2607 | __le16 mode; | ||
2608 | } __attribute__((packed)); | ||
2609 | |||
2610 | static int mwl8k_cmd_set_rateadapt_mode(struct ieee80211_hw *hw, __u16 mode) | ||
2611 | { | ||
2612 | struct mwl8k_cmd_set_rate_adapt_mode *cmd; | ||
2613 | int rc; | ||
2614 | |||
2615 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2616 | if (cmd == NULL) | ||
2617 | return -ENOMEM; | ||
2618 | |||
2619 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); | ||
2620 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2621 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | ||
2622 | cmd->mode = cpu_to_le16(mode); | ||
2623 | |||
2624 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2625 | kfree(cmd); | ||
2626 | |||
2627 | return rc; | ||
2628 | } | ||
2629 | |||
2630 | /* | ||
2631 | * CMD_UPDATE_STADB. | ||
2632 | */ | ||
2633 | struct mwl8k_cmd_update_stadb { | ||
2634 | struct mwl8k_cmd_pkt header; | ||
2635 | |||
2636 | /* See STADB_ACTION_TYPE */ | ||
2637 | __le32 action; | ||
2638 | |||
2639 | /* Peer MAC address */ | ||
2640 | __u8 peer_addr[ETH_ALEN]; | ||
2641 | |||
2642 | __le32 reserved; | ||
2643 | |||
2644 | /* Peer info - valid during add/update. */ | ||
2645 | struct peer_capability_info peer_info; | ||
2646 | } __attribute__((packed)); | ||
2647 | |||
2648 | static int mwl8k_cmd_update_stadb(struct ieee80211_hw *hw, | ||
2649 | struct ieee80211_vif *vif, __u32 action) | ||
2650 | { | ||
2651 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
2652 | struct mwl8k_cmd_update_stadb *cmd; | ||
2653 | struct peer_capability_info *peer_info; | ||
2654 | int rc; | ||
2655 | |||
2656 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | ||
2657 | if (cmd == NULL) | ||
2658 | return -ENOMEM; | ||
2659 | |||
2660 | cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); | ||
2661 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | ||
2662 | |||
2663 | cmd->action = cpu_to_le32(action); | ||
2664 | peer_info = &cmd->peer_info; | ||
2665 | memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); | ||
2666 | |||
2667 | switch (action) { | ||
2668 | case MWL8K_STA_DB_ADD_ENTRY: | ||
2669 | case MWL8K_STA_DB_MODIFY_ENTRY: | ||
2670 | /* Build peer_info block */ | ||
2671 | peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; | ||
2672 | peer_info->basic_caps = | ||
2673 | cpu_to_le16(vif->bss_conf.assoc_capability); | ||
2674 | memcpy(peer_info->legacy_rates, mwl8k_rateids, | ||
2675 | sizeof(mwl8k_rateids)); | ||
2676 | peer_info->interop = 1; | ||
2677 | peer_info->amsdu_enabled = 0; | ||
2678 | |||
2679 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2680 | if (rc == 0) | ||
2681 | mv_vif->peer_id = peer_info->station_id; | ||
2682 | |||
2683 | break; | ||
2684 | |||
2685 | case MWL8K_STA_DB_DEL_ENTRY: | ||
2686 | case MWL8K_STA_DB_FLUSH: | ||
2687 | default: | ||
2688 | rc = mwl8k_post_cmd(hw, &cmd->header); | ||
2689 | if (rc == 0) | ||
2690 | mv_vif->peer_id = 0; | ||
2691 | break; | ||
2692 | } | ||
2693 | kfree(cmd); | ||
2694 | |||
2695 | return rc; | ||
2696 | } | ||
2697 | |||
2758 | 2698 | ||
2759 | /* | 2699 | /* |
2760 | * Interrupt handling. | 2700 | * Interrupt handling. |
@@ -2836,11 +2776,11 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2836 | 2776 | ||
2837 | rc = mwl8k_fw_lock(hw); | 2777 | rc = mwl8k_fw_lock(hw); |
2838 | if (!rc) { | 2778 | if (!rc) { |
2839 | rc = mwl8k_cmd_802_11_radio_enable(hw); | 2779 | rc = mwl8k_cmd_radio_enable(hw); |
2840 | 2780 | ||
2841 | if (!priv->ap_fw) { | 2781 | if (!priv->ap_fw) { |
2842 | if (!rc) | 2782 | if (!rc) |
2843 | rc = mwl8k_enable_sniffer(hw, 0); | 2783 | rc = mwl8k_cmd_enable_sniffer(hw, 0); |
2844 | 2784 | ||
2845 | if (!rc) | 2785 | if (!rc) |
2846 | rc = mwl8k_cmd_set_pre_scan(hw); | 2786 | rc = mwl8k_cmd_set_pre_scan(hw); |
@@ -2851,10 +2791,10 @@ static int mwl8k_start(struct ieee80211_hw *hw) | |||
2851 | } | 2791 | } |
2852 | 2792 | ||
2853 | if (!rc) | 2793 | if (!rc) |
2854 | rc = mwl8k_cmd_setrateadaptmode(hw, 0); | 2794 | rc = mwl8k_cmd_set_rateadapt_mode(hw, 0); |
2855 | 2795 | ||
2856 | if (!rc) | 2796 | if (!rc) |
2857 | rc = mwl8k_set_wmm(hw, 0); | 2797 | rc = mwl8k_cmd_set_wmm_mode(hw, 0); |
2858 | 2798 | ||
2859 | mwl8k_fw_unlock(hw); | 2799 | mwl8k_fw_unlock(hw); |
2860 | } | 2800 | } |
@@ -2873,7 +2813,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) | |||
2873 | struct mwl8k_priv *priv = hw->priv; | 2813 | struct mwl8k_priv *priv = hw->priv; |
2874 | int i; | 2814 | int i; |
2875 | 2815 | ||
2876 | mwl8k_cmd_802_11_radio_disable(hw); | 2816 | mwl8k_cmd_radio_disable(hw); |
2877 | 2817 | ||
2878 | ieee80211_stop_queues(hw); | 2818 | ieee80211_stop_queues(hw); |
2879 | 2819 | ||
@@ -2895,7 +2835,7 @@ static void mwl8k_stop(struct ieee80211_hw *hw) | |||
2895 | } | 2835 | } |
2896 | 2836 | ||
2897 | static int mwl8k_add_interface(struct ieee80211_hw *hw, | 2837 | static int mwl8k_add_interface(struct ieee80211_hw *hw, |
2898 | struct ieee80211_if_init_conf *conf) | 2838 | struct ieee80211_vif *vif) |
2899 | { | 2839 | { |
2900 | struct mwl8k_priv *priv = hw->priv; | 2840 | struct mwl8k_priv *priv = hw->priv; |
2901 | struct mwl8k_vif *mwl8k_vif; | 2841 | struct mwl8k_vif *mwl8k_vif; |
@@ -2909,7 +2849,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2909 | /* | 2849 | /* |
2910 | * We only support managed interfaces for now. | 2850 | * We only support managed interfaces for now. |
2911 | */ | 2851 | */ |
2912 | if (conf->type != NL80211_IFTYPE_STATION) | 2852 | if (vif->type != NL80211_IFTYPE_STATION) |
2913 | return -EINVAL; | 2853 | return -EINVAL; |
2914 | 2854 | ||
2915 | /* | 2855 | /* |
@@ -2925,34 +2865,31 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2925 | } | 2865 | } |
2926 | 2866 | ||
2927 | /* Clean out driver private area */ | 2867 | /* Clean out driver private area */ |
2928 | mwl8k_vif = MWL8K_VIF(conf->vif); | 2868 | mwl8k_vif = MWL8K_VIF(vif); |
2929 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | 2869 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); |
2930 | 2870 | ||
2931 | /* Set and save the mac address */ | 2871 | /* Set and save the mac address */ |
2932 | mwl8k_set_mac_addr(hw, conf->mac_addr); | 2872 | mwl8k_cmd_set_mac_addr(hw, vif->addr); |
2933 | memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); | 2873 | memcpy(mwl8k_vif->mac_addr, vif->addr, ETH_ALEN); |
2934 | |||
2935 | /* Back pointer to parent config block */ | ||
2936 | mwl8k_vif->priv = priv; | ||
2937 | 2874 | ||
2938 | /* Set Initial sequence number to zero */ | 2875 | /* Set Initial sequence number to zero */ |
2939 | mwl8k_vif->seqno = 0; | 2876 | mwl8k_vif->seqno = 0; |
2940 | 2877 | ||
2941 | priv->vif = conf->vif; | 2878 | priv->vif = vif; |
2942 | priv->current_channel = NULL; | 2879 | priv->current_channel = NULL; |
2943 | 2880 | ||
2944 | return 0; | 2881 | return 0; |
2945 | } | 2882 | } |
2946 | 2883 | ||
2947 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, | 2884 | static void mwl8k_remove_interface(struct ieee80211_hw *hw, |
2948 | struct ieee80211_if_init_conf *conf) | 2885 | struct ieee80211_vif *vif) |
2949 | { | 2886 | { |
2950 | struct mwl8k_priv *priv = hw->priv; | 2887 | struct mwl8k_priv *priv = hw->priv; |
2951 | 2888 | ||
2952 | if (priv->vif == NULL) | 2889 | if (priv->vif == NULL) |
2953 | return; | 2890 | return; |
2954 | 2891 | ||
2955 | mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); | 2892 | mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); |
2956 | 2893 | ||
2957 | priv->vif = NULL; | 2894 | priv->vif = NULL; |
2958 | } | 2895 | } |
@@ -2964,7 +2901,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2964 | int rc; | 2901 | int rc; |
2965 | 2902 | ||
2966 | if (conf->flags & IEEE80211_CONF_IDLE) { | 2903 | if (conf->flags & IEEE80211_CONF_IDLE) { |
2967 | mwl8k_cmd_802_11_radio_disable(hw); | 2904 | mwl8k_cmd_radio_disable(hw); |
2968 | priv->current_channel = NULL; | 2905 | priv->current_channel = NULL; |
2969 | return 0; | 2906 | return 0; |
2970 | } | 2907 | } |
@@ -2973,7 +2910,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2973 | if (rc) | 2910 | if (rc) |
2974 | return rc; | 2911 | return rc; |
2975 | 2912 | ||
2976 | rc = mwl8k_cmd_802_11_radio_enable(hw); | 2913 | rc = mwl8k_cmd_radio_enable(hw); |
2977 | if (rc) | 2914 | if (rc) |
2978 | goto out; | 2915 | goto out; |
2979 | 2916 | ||
@@ -2985,7 +2922,7 @@ static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | |||
2985 | 2922 | ||
2986 | if (conf->power_level > 18) | 2923 | if (conf->power_level > 18) |
2987 | conf->power_level = 18; | 2924 | conf->power_level = 18; |
2988 | rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); | 2925 | rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level); |
2989 | if (rc) | 2926 | if (rc) |
2990 | goto out; | 2927 | goto out; |
2991 | 2928 | ||
@@ -3021,14 +2958,11 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | |||
3021 | if (rc) | 2958 | if (rc) |
3022 | return; | 2959 | return; |
3023 | 2960 | ||
3024 | if (info->assoc) { | 2961 | if (vif->bss_conf.assoc) { |
3025 | memcpy(&mwl8k_vif->bss_info, info, | 2962 | memcpy(mwl8k_vif->bssid, vif->bss_conf.bssid, ETH_ALEN); |
3026 | sizeof(struct ieee80211_bss_conf)); | ||
3027 | |||
3028 | memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); | ||
3029 | 2963 | ||
3030 | /* Install rates */ | 2964 | /* Install rates */ |
3031 | rc = mwl8k_update_rateset(hw, vif); | 2965 | rc = mwl8k_cmd_set_rate(hw, vif); |
3032 | if (rc) | 2966 | if (rc) |
3033 | goto out; | 2967 | goto out; |
3034 | 2968 | ||
@@ -3039,17 +2973,18 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | |||
3039 | goto out; | 2973 | goto out; |
3040 | 2974 | ||
3041 | /* Set radio preamble */ | 2975 | /* Set radio preamble */ |
3042 | rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); | 2976 | rc = mwl8k_set_radio_preamble(hw, |
2977 | vif->bss_conf.use_short_preamble); | ||
3043 | if (rc) | 2978 | if (rc) |
3044 | goto out; | 2979 | goto out; |
3045 | 2980 | ||
3046 | /* Set slot time */ | 2981 | /* Set slot time */ |
3047 | rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); | 2982 | rc = mwl8k_cmd_set_slot(hw, vif->bss_conf.use_short_slot); |
3048 | if (rc) | 2983 | if (rc) |
3049 | goto out; | 2984 | goto out; |
3050 | 2985 | ||
3051 | /* Update peer rate info */ | 2986 | /* Update peer rate info */ |
3052 | rc = mwl8k_cmd_update_sta_db(hw, vif, | 2987 | rc = mwl8k_cmd_update_stadb(hw, vif, |
3053 | MWL8K_STA_DB_MODIFY_ENTRY); | 2988 | MWL8K_STA_DB_MODIFY_ENTRY); |
3054 | if (rc) | 2989 | if (rc) |
3055 | goto out; | 2990 | goto out; |
@@ -3066,9 +3001,7 @@ static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | |||
3066 | memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); | 3001 | memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); |
3067 | priv->capture_beacon = true; | 3002 | priv->capture_beacon = true; |
3068 | } else { | 3003 | } else { |
3069 | rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); | 3004 | rc = mwl8k_cmd_update_stadb(hw, vif, MWL8K_STA_DB_DEL_ENTRY); |
3070 | memset(&mwl8k_vif->bss_info, 0, | ||
3071 | sizeof(struct ieee80211_bss_conf)); | ||
3072 | memset(mwl8k_vif->bssid, 0, ETH_ALEN); | 3005 | memset(mwl8k_vif->bssid, 0, ETH_ALEN); |
3073 | } | 3006 | } |
3074 | 3007 | ||
@@ -3114,7 +3047,7 @@ mwl8k_configure_filter_sniffer(struct ieee80211_hw *hw, | |||
3114 | } | 3047 | } |
3115 | 3048 | ||
3116 | if (!priv->sniffer_enabled) { | 3049 | if (!priv->sniffer_enabled) { |
3117 | if (mwl8k_enable_sniffer(hw, 1)) | 3050 | if (mwl8k_cmd_enable_sniffer(hw, 1)) |
3118 | return 0; | 3051 | return 0; |
3119 | priv->sniffer_enabled = true; | 3052 | priv->sniffer_enabled = true; |
3120 | } | 3053 | } |
@@ -3161,7 +3094,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3161 | return; | 3094 | return; |
3162 | 3095 | ||
3163 | if (priv->sniffer_enabled) { | 3096 | if (priv->sniffer_enabled) { |
3164 | mwl8k_enable_sniffer(hw, 0); | 3097 | mwl8k_cmd_enable_sniffer(hw, 0); |
3165 | priv->sniffer_enabled = false; | 3098 | priv->sniffer_enabled = false; |
3166 | } | 3099 | } |
3167 | 3100 | ||
@@ -3211,7 +3144,7 @@ static void mwl8k_configure_filter(struct ieee80211_hw *hw, | |||
3211 | 3144 | ||
3212 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 3145 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
3213 | { | 3146 | { |
3214 | return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); | 3147 | return mwl8k_cmd_set_rts_threshold(hw, MWL8K_CMD_SET, value); |
3215 | } | 3148 | } |
3216 | 3149 | ||
3217 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 3150 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
@@ -3223,14 +3156,14 @@ static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
3223 | rc = mwl8k_fw_lock(hw); | 3156 | rc = mwl8k_fw_lock(hw); |
3224 | if (!rc) { | 3157 | if (!rc) { |
3225 | if (!priv->wmm_enabled) | 3158 | if (!priv->wmm_enabled) |
3226 | rc = mwl8k_set_wmm(hw, 1); | 3159 | rc = mwl8k_cmd_set_wmm_mode(hw, 1); |
3227 | 3160 | ||
3228 | if (!rc) | 3161 | if (!rc) |
3229 | rc = mwl8k_set_edca_params(hw, queue, | 3162 | rc = mwl8k_cmd_set_edca_params(hw, queue, |
3230 | params->cw_min, | 3163 | params->cw_min, |
3231 | params->cw_max, | 3164 | params->cw_max, |
3232 | params->aifs, | 3165 | params->aifs, |
3233 | params->txop); | 3166 | params->txop); |
3234 | 3167 | ||
3235 | mwl8k_fw_unlock(hw); | 3168 | mwl8k_fw_unlock(hw); |
3236 | } | 3169 | } |
@@ -3259,7 +3192,7 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, | |||
3259 | static int mwl8k_get_stats(struct ieee80211_hw *hw, | 3192 | static int mwl8k_get_stats(struct ieee80211_hw *hw, |
3260 | struct ieee80211_low_level_stats *stats) | 3193 | struct ieee80211_low_level_stats *stats) |
3261 | { | 3194 | { |
3262 | return mwl8k_cmd_802_11_get_stat(hw, stats); | 3195 | return mwl8k_cmd_get_stat(hw, stats); |
3263 | } | 3196 | } |
3264 | 3197 | ||
3265 | static const struct ieee80211_ops mwl8k_ops = { | 3198 | static const struct ieee80211_ops mwl8k_ops = { |
@@ -3300,9 +3233,9 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) | |||
3300 | struct mwl8k_priv *priv = | 3233 | struct mwl8k_priv *priv = |
3301 | container_of(work, struct mwl8k_priv, finalize_join_worker); | 3234 | container_of(work, struct mwl8k_priv, finalize_join_worker); |
3302 | struct sk_buff *skb = priv->beacon_skb; | 3235 | struct sk_buff *skb = priv->beacon_skb; |
3303 | u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; | ||
3304 | 3236 | ||
3305 | mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); | 3237 | mwl8k_cmd_finalize_join(priv->hw, skb->data, skb->len, |
3238 | priv->vif->bss_conf.dtim_period); | ||
3306 | dev_kfree_skb(skb); | 3239 | dev_kfree_skb(skb); |
3307 | 3240 | ||
3308 | priv->beacon_skb = NULL; | 3241 | priv->beacon_skb = NULL; |
@@ -3314,19 +3247,16 @@ enum { | |||
3314 | }; | 3247 | }; |
3315 | 3248 | ||
3316 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { | 3249 | static struct mwl8k_device_info mwl8k_info_tbl[] __devinitdata = { |
3317 | { | 3250 | [MWL8687] = { |
3318 | .part_name = "88w8687", | 3251 | .part_name = "88w8687", |
3319 | .helper_image = "mwl8k/helper_8687.fw", | 3252 | .helper_image = "mwl8k/helper_8687.fw", |
3320 | .fw_image = "mwl8k/fmimage_8687.fw", | 3253 | .fw_image = "mwl8k/fmimage_8687.fw", |
3321 | .rxd_ops = &rxd_8687_ops, | ||
3322 | .modes = BIT(NL80211_IFTYPE_STATION), | ||
3323 | }, | 3254 | }, |
3324 | { | 3255 | [MWL8366] = { |
3325 | .part_name = "88w8366", | 3256 | .part_name = "88w8366", |
3326 | .helper_image = "mwl8k/helper_8366.fw", | 3257 | .helper_image = "mwl8k/helper_8366.fw", |
3327 | .fw_image = "mwl8k/fmimage_8366.fw", | 3258 | .fw_image = "mwl8k/fmimage_8366.fw", |
3328 | .rxd_ops = &rxd_8366_ops, | 3259 | .ap_rxd_ops = &rxd_8366_ap_ops, |
3329 | .modes = 0, | ||
3330 | }, | 3260 | }, |
3331 | }; | 3261 | }; |
3332 | 3262 | ||
@@ -3352,6 +3282,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3352 | printed_version = 1; | 3282 | printed_version = 1; |
3353 | } | 3283 | } |
3354 | 3284 | ||
3285 | |||
3355 | rc = pci_enable_device(pdev); | 3286 | rc = pci_enable_device(pdev); |
3356 | if (rc) { | 3287 | if (rc) { |
3357 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", | 3288 | printk(KERN_ERR "%s: Cannot enable new PCI device\n", |
@@ -3368,6 +3299,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3368 | 3299 | ||
3369 | pci_set_master(pdev); | 3300 | pci_set_master(pdev); |
3370 | 3301 | ||
3302 | |||
3371 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); | 3303 | hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); |
3372 | if (hw == NULL) { | 3304 | if (hw == NULL) { |
3373 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); | 3305 | printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); |
@@ -3375,17 +3307,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3375 | goto err_free_reg; | 3307 | goto err_free_reg; |
3376 | } | 3308 | } |
3377 | 3309 | ||
3310 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3311 | pci_set_drvdata(pdev, hw); | ||
3312 | |||
3378 | priv = hw->priv; | 3313 | priv = hw->priv; |
3379 | priv->hw = hw; | 3314 | priv->hw = hw; |
3380 | priv->pdev = pdev; | 3315 | priv->pdev = pdev; |
3381 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; | 3316 | priv->device_info = &mwl8k_info_tbl[id->driver_data]; |
3382 | priv->rxd_ops = priv->device_info->rxd_ops; | ||
3383 | priv->sniffer_enabled = false; | ||
3384 | priv->wmm_enabled = false; | ||
3385 | priv->pending_tx_pkts = 0; | ||
3386 | 3317 | ||
3387 | SET_IEEE80211_DEV(hw, &pdev->dev); | ||
3388 | pci_set_drvdata(pdev, hw); | ||
3389 | 3318 | ||
3390 | priv->sram = pci_iomap(pdev, 0, 0x10000); | 3319 | priv->sram = pci_iomap(pdev, 0, 0x10000); |
3391 | if (priv->sram == NULL) { | 3320 | if (priv->sram == NULL) { |
@@ -3408,6 +3337,40 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3408 | } | 3337 | } |
3409 | } | 3338 | } |
3410 | 3339 | ||
3340 | |||
3341 | /* Reset firmware and hardware */ | ||
3342 | mwl8k_hw_reset(priv); | ||
3343 | |||
3344 | /* Ask userland hotplug daemon for the device firmware */ | ||
3345 | rc = mwl8k_request_firmware(priv); | ||
3346 | if (rc) { | ||
3347 | printk(KERN_ERR "%s: Firmware files not found\n", | ||
3348 | wiphy_name(hw->wiphy)); | ||
3349 | goto err_stop_firmware; | ||
3350 | } | ||
3351 | |||
3352 | /* Load firmware into hardware */ | ||
3353 | rc = mwl8k_load_firmware(hw); | ||
3354 | if (rc) { | ||
3355 | printk(KERN_ERR "%s: Cannot start firmware\n", | ||
3356 | wiphy_name(hw->wiphy)); | ||
3357 | goto err_stop_firmware; | ||
3358 | } | ||
3359 | |||
3360 | /* Reclaim memory once firmware is successfully loaded */ | ||
3361 | mwl8k_release_firmware(priv); | ||
3362 | |||
3363 | |||
3364 | if (priv->ap_fw) | ||
3365 | priv->rxd_ops = priv->device_info->ap_rxd_ops; | ||
3366 | else | ||
3367 | priv->rxd_ops = &rxd_sta_ops; | ||
3368 | |||
3369 | priv->sniffer_enabled = false; | ||
3370 | priv->wmm_enabled = false; | ||
3371 | priv->pending_tx_pkts = 0; | ||
3372 | |||
3373 | |||
3411 | memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); | 3374 | memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); |
3412 | priv->band.band = IEEE80211_BAND_2GHZ; | 3375 | priv->band.band = IEEE80211_BAND_2GHZ; |
3413 | priv->band.channels = priv->channels; | 3376 | priv->band.channels = priv->channels; |
@@ -3430,8 +3393,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3430 | 3393 | ||
3431 | hw->queues = MWL8K_TX_QUEUES; | 3394 | hw->queues = MWL8K_TX_QUEUES; |
3432 | 3395 | ||
3433 | hw->wiphy->interface_modes = priv->device_info->modes; | ||
3434 | |||
3435 | /* Set rssi and noise values to dBm */ | 3396 | /* Set rssi and noise values to dBm */ |
3436 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; | 3397 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; |
3437 | hw->vif_data_size = sizeof(struct mwl8k_vif); | 3398 | hw->vif_data_size = sizeof(struct mwl8k_vif); |
@@ -3452,11 +3413,11 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3452 | /* Power management cookie */ | 3413 | /* Power management cookie */ |
3453 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); | 3414 | priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); |
3454 | if (priv->cookie == NULL) | 3415 | if (priv->cookie == NULL) |
3455 | goto err_iounmap; | 3416 | goto err_stop_firmware; |
3456 | 3417 | ||
3457 | rc = mwl8k_rxq_init(hw, 0); | 3418 | rc = mwl8k_rxq_init(hw, 0); |
3458 | if (rc) | 3419 | if (rc) |
3459 | goto err_iounmap; | 3420 | goto err_free_cookie; |
3460 | rxq_refill(hw, 0, INT_MAX); | 3421 | rxq_refill(hw, 0, INT_MAX); |
3461 | 3422 | ||
3462 | mutex_init(&priv->fw_mutex); | 3423 | mutex_init(&priv->fw_mutex); |
@@ -3487,28 +3448,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3487 | goto err_free_queues; | 3448 | goto err_free_queues; |
3488 | } | 3449 | } |
3489 | 3450 | ||
3490 | /* Reset firmware and hardware */ | ||
3491 | mwl8k_hw_reset(priv); | ||
3492 | |||
3493 | /* Ask userland hotplug daemon for the device firmware */ | ||
3494 | rc = mwl8k_request_firmware(priv); | ||
3495 | if (rc) { | ||
3496 | printk(KERN_ERR "%s: Firmware files not found\n", | ||
3497 | wiphy_name(hw->wiphy)); | ||
3498 | goto err_free_irq; | ||
3499 | } | ||
3500 | |||
3501 | /* Load firmware into hardware */ | ||
3502 | rc = mwl8k_load_firmware(hw); | ||
3503 | if (rc) { | ||
3504 | printk(KERN_ERR "%s: Cannot start firmware\n", | ||
3505 | wiphy_name(hw->wiphy)); | ||
3506 | goto err_stop_firmware; | ||
3507 | } | ||
3508 | |||
3509 | /* Reclaim memory once firmware is successfully loaded */ | ||
3510 | mwl8k_release_firmware(priv); | ||
3511 | |||
3512 | /* | 3451 | /* |
3513 | * Temporarily enable interrupts. Initial firmware host | 3452 | * Temporarily enable interrupts. Initial firmware host |
3514 | * commands use interrupts and avoids polling. Disable | 3453 | * commands use interrupts and avoids polling. Disable |
@@ -3523,26 +3462,28 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3523 | rc = mwl8k_cmd_set_hw_spec(hw); | 3462 | rc = mwl8k_cmd_set_hw_spec(hw); |
3524 | } else { | 3463 | } else { |
3525 | rc = mwl8k_cmd_get_hw_spec_sta(hw); | 3464 | rc = mwl8k_cmd_get_hw_spec_sta(hw); |
3465 | |||
3466 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
3526 | } | 3467 | } |
3527 | if (rc) { | 3468 | if (rc) { |
3528 | printk(KERN_ERR "%s: Cannot initialise firmware\n", | 3469 | printk(KERN_ERR "%s: Cannot initialise firmware\n", |
3529 | wiphy_name(hw->wiphy)); | 3470 | wiphy_name(hw->wiphy)); |
3530 | goto err_stop_firmware; | 3471 | goto err_free_irq; |
3531 | } | 3472 | } |
3532 | 3473 | ||
3533 | /* Turn radio off */ | 3474 | /* Turn radio off */ |
3534 | rc = mwl8k_cmd_802_11_radio_disable(hw); | 3475 | rc = mwl8k_cmd_radio_disable(hw); |
3535 | if (rc) { | 3476 | if (rc) { |
3536 | printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); | 3477 | printk(KERN_ERR "%s: Cannot disable\n", wiphy_name(hw->wiphy)); |
3537 | goto err_stop_firmware; | 3478 | goto err_free_irq; |
3538 | } | 3479 | } |
3539 | 3480 | ||
3540 | /* Clear MAC address */ | 3481 | /* Clear MAC address */ |
3541 | rc = mwl8k_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); | 3482 | rc = mwl8k_cmd_set_mac_addr(hw, "\x00\x00\x00\x00\x00\x00"); |
3542 | if (rc) { | 3483 | if (rc) { |
3543 | printk(KERN_ERR "%s: Cannot clear MAC address\n", | 3484 | printk(KERN_ERR "%s: Cannot clear MAC address\n", |
3544 | wiphy_name(hw->wiphy)); | 3485 | wiphy_name(hw->wiphy)); |
3545 | goto err_stop_firmware; | 3486 | goto err_free_irq; |
3546 | } | 3487 | } |
3547 | 3488 | ||
3548 | /* Disable interrupts */ | 3489 | /* Disable interrupts */ |
@@ -3553,7 +3494,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3553 | if (rc) { | 3494 | if (rc) { |
3554 | printk(KERN_ERR "%s: Cannot register device\n", | 3495 | printk(KERN_ERR "%s: Cannot register device\n", |
3555 | wiphy_name(hw->wiphy)); | 3496 | wiphy_name(hw->wiphy)); |
3556 | goto err_stop_firmware; | 3497 | goto err_free_irq; |
3557 | } | 3498 | } |
3558 | 3499 | ||
3559 | printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", | 3500 | printk(KERN_INFO "%s: %s v%d, %pM, %s firmware %u.%u.%u.%u\n", |
@@ -3565,10 +3506,6 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3565 | 3506 | ||
3566 | return 0; | 3507 | return 0; |
3567 | 3508 | ||
3568 | err_stop_firmware: | ||
3569 | mwl8k_hw_reset(priv); | ||
3570 | mwl8k_release_firmware(priv); | ||
3571 | |||
3572 | err_free_irq: | 3509 | err_free_irq: |
3573 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 3510 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3574 | free_irq(priv->pdev->irq, hw); | 3511 | free_irq(priv->pdev->irq, hw); |
@@ -3578,11 +3515,16 @@ err_free_queues: | |||
3578 | mwl8k_txq_deinit(hw, i); | 3515 | mwl8k_txq_deinit(hw, i); |
3579 | mwl8k_rxq_deinit(hw, 0); | 3516 | mwl8k_rxq_deinit(hw, 0); |
3580 | 3517 | ||
3581 | err_iounmap: | 3518 | err_free_cookie: |
3582 | if (priv->cookie != NULL) | 3519 | if (priv->cookie != NULL) |
3583 | pci_free_consistent(priv->pdev, 4, | 3520 | pci_free_consistent(priv->pdev, 4, |
3584 | priv->cookie, priv->cookie_dma); | 3521 | priv->cookie, priv->cookie_dma); |
3585 | 3522 | ||
3523 | err_stop_firmware: | ||
3524 | mwl8k_hw_reset(priv); | ||
3525 | mwl8k_release_firmware(priv); | ||
3526 | |||
3527 | err_iounmap: | ||
3586 | if (priv->regs != NULL) | 3528 | if (priv->regs != NULL) |
3587 | pci_iounmap(pdev, priv->regs); | 3529 | pci_iounmap(pdev, priv->regs); |
3588 | 3530 | ||
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 7698fdd6a3a2..31ca241f7753 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #define MAX_RID_LEN 1024 | 23 | #define MAX_RID_LEN 1024 |
24 | 24 | ||
25 | /* Helper routine to record keys | 25 | /* Helper routine to record keys |
26 | * Do not call from interrupt context */ | 26 | * It is called under orinoco_lock so it may not sleep */ |
27 | static int orinoco_set_key(struct orinoco_private *priv, int index, | 27 | static int orinoco_set_key(struct orinoco_private *priv, int index, |
28 | enum orinoco_alg alg, const u8 *key, int key_len, | 28 | enum orinoco_alg alg, const u8 *key, int key_len, |
29 | const u8 *seq, int seq_len) | 29 | const u8 *seq, int seq_len) |
@@ -32,14 +32,14 @@ static int orinoco_set_key(struct orinoco_private *priv, int index, | |||
32 | kzfree(priv->keys[index].seq); | 32 | kzfree(priv->keys[index].seq); |
33 | 33 | ||
34 | if (key_len) { | 34 | if (key_len) { |
35 | priv->keys[index].key = kzalloc(key_len, GFP_KERNEL); | 35 | priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC); |
36 | if (!priv->keys[index].key) | 36 | if (!priv->keys[index].key) |
37 | goto nomem; | 37 | goto nomem; |
38 | } else | 38 | } else |
39 | priv->keys[index].key = NULL; | 39 | priv->keys[index].key = NULL; |
40 | 40 | ||
41 | if (seq_len) { | 41 | if (seq_len) { |
42 | priv->keys[index].seq = kzalloc(seq_len, GFP_KERNEL); | 42 | priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC); |
43 | if (!priv->keys[index].seq) | 43 | if (!priv->keys[index].seq) |
44 | goto free_key; | 44 | goto free_key; |
45 | } else | 45 | } else |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 18012dbfb45d..26428e4c9c60 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -216,7 +216,7 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
216 | } | 216 | } |
217 | 217 | ||
218 | static int p54_add_interface(struct ieee80211_hw *dev, | 218 | static int p54_add_interface(struct ieee80211_hw *dev, |
219 | struct ieee80211_if_init_conf *conf) | 219 | struct ieee80211_vif *vif) |
220 | { | 220 | { |
221 | struct p54_common *priv = dev->priv; | 221 | struct p54_common *priv = dev->priv; |
222 | 222 | ||
@@ -226,28 +226,28 @@ static int p54_add_interface(struct ieee80211_hw *dev, | |||
226 | return -EOPNOTSUPP; | 226 | return -EOPNOTSUPP; |
227 | } | 227 | } |
228 | 228 | ||
229 | priv->vif = conf->vif; | 229 | priv->vif = vif; |
230 | 230 | ||
231 | switch (conf->type) { | 231 | switch (vif->type) { |
232 | case NL80211_IFTYPE_STATION: | 232 | case NL80211_IFTYPE_STATION: |
233 | case NL80211_IFTYPE_ADHOC: | 233 | case NL80211_IFTYPE_ADHOC: |
234 | case NL80211_IFTYPE_AP: | 234 | case NL80211_IFTYPE_AP: |
235 | case NL80211_IFTYPE_MESH_POINT: | 235 | case NL80211_IFTYPE_MESH_POINT: |
236 | priv->mode = conf->type; | 236 | priv->mode = vif->type; |
237 | break; | 237 | break; |
238 | default: | 238 | default: |
239 | mutex_unlock(&priv->conf_mutex); | 239 | mutex_unlock(&priv->conf_mutex); |
240 | return -EOPNOTSUPP; | 240 | return -EOPNOTSUPP; |
241 | } | 241 | } |
242 | 242 | ||
243 | memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); | 243 | memcpy(priv->mac_addr, vif->addr, ETH_ALEN); |
244 | p54_setup_mac(priv); | 244 | p54_setup_mac(priv); |
245 | mutex_unlock(&priv->conf_mutex); | 245 | mutex_unlock(&priv->conf_mutex); |
246 | return 0; | 246 | return 0; |
247 | } | 247 | } |
248 | 248 | ||
249 | static void p54_remove_interface(struct ieee80211_hw *dev, | 249 | static void p54_remove_interface(struct ieee80211_hw *dev, |
250 | struct ieee80211_if_init_conf *conf) | 250 | struct ieee80211_vif *vif) |
251 | { | 251 | { |
252 | struct p54_common *priv = dev->priv; | 252 | struct p54_common *priv = dev->priv; |
253 | 253 | ||
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index bf60689aaabb..3ca824a91ad9 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -54,12 +54,12 @@ config RT61PCI | |||
54 | When compiled as a module, this driver will be called rt61pci. | 54 | When compiled as a module, this driver will be called rt61pci. |
55 | 55 | ||
56 | config RT2800PCI_PCI | 56 | config RT2800PCI_PCI |
57 | tristate | 57 | boolean |
58 | depends on PCI | 58 | depends on PCI |
59 | default y | 59 | default y |
60 | 60 | ||
61 | config RT2800PCI_SOC | 61 | config RT2800PCI_SOC |
62 | tristate | 62 | boolean |
63 | depends on RALINK_RT288X || RALINK_RT305X | 63 | depends on RALINK_RT288X || RALINK_RT305X |
64 | default y | 64 | default y |
65 | 65 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index e7f46405a418..d86d233c6810 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c | |||
@@ -451,7 +451,7 @@ static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
451 | /* | 451 | /* |
452 | * RF2420 chipset don't need any additional actions. | 452 | * RF2420 chipset don't need any additional actions. |
453 | */ | 453 | */ |
454 | if (rt2x00_rf(&rt2x00dev->chip, RF2420)) | 454 | if (rt2x00_rf(rt2x00dev, RF2420)) |
455 | return; | 455 | return; |
456 | 456 | ||
457 | /* | 457 | /* |
@@ -1343,8 +1343,7 @@ static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1343 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1343 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
1344 | rt2x00_print_chip(rt2x00dev); | 1344 | rt2x00_print_chip(rt2x00dev); |
1345 | 1345 | ||
1346 | if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && | 1346 | if (!rt2x00_rf(rt2x00dev, RF2420) && !rt2x00_rf(rt2x00dev, RF2421)) { |
1347 | !rt2x00_rf(&rt2x00dev->chip, RF2421)) { | ||
1348 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1347 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1349 | return -ENODEV; | 1348 | return -ENODEV; |
1350 | } | 1349 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index 408fcfc120f5..46cbc6ef66ab 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c | |||
@@ -440,8 +440,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
440 | /* | 440 | /* |
441 | * RT2525E and RT5222 need to flip TX I/Q | 441 | * RT2525E and RT5222 need to flip TX I/Q |
442 | */ | 442 | */ |
443 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || | 443 | if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { |
444 | rt2x00_rf(&rt2x00dev->chip, RF5222)) { | ||
445 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); | 444 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); |
446 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); | 445 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); |
447 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); | 446 | rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); |
@@ -449,7 +448,7 @@ static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
449 | /* | 448 | /* |
450 | * RT2525E does not need RX I/Q Flip. | 449 | * RT2525E does not need RX I/Q Flip. |
451 | */ | 450 | */ |
452 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) | 451 | if (rt2x00_rf(rt2x00dev, RF2525E)) |
453 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); | 452 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); |
454 | } else { | 453 | } else { |
455 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); | 454 | rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); |
@@ -475,14 +474,14 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
475 | * Switch on tuning bits. | 474 | * Switch on tuning bits. |
476 | * For RT2523 devices we do not need to update the R1 register. | 475 | * For RT2523 devices we do not need to update the R1 register. |
477 | */ | 476 | */ |
478 | if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) | 477 | if (!rt2x00_rf(rt2x00dev, RF2523)) |
479 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); | 478 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); |
480 | rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); | 479 | rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); |
481 | 480 | ||
482 | /* | 481 | /* |
483 | * For RT2525 we should first set the channel to half band higher. | 482 | * For RT2525 we should first set the channel to half band higher. |
484 | */ | 483 | */ |
485 | if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 484 | if (rt2x00_rf(rt2x00dev, RF2525)) { |
486 | static const u32 vals[] = { | 485 | static const u32 vals[] = { |
487 | 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, | 486 | 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, |
488 | 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, | 487 | 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, |
@@ -516,7 +515,7 @@ static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
516 | * Switch off tuning bits. | 515 | * Switch off tuning bits. |
517 | * For RT2523 devices we do not need to update the R1 register. | 516 | * For RT2523 devices we do not need to update the R1 register. |
518 | */ | 517 | */ |
519 | if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 518 | if (!rt2x00_rf(rt2x00dev, RF2523)) { |
520 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); | 519 | rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); |
521 | rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); | 520 | rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); |
522 | } | 521 | } |
@@ -640,7 +639,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
640 | * up to version C the link tuning should halt after 20 | 639 | * up to version C the link tuning should halt after 20 |
641 | * seconds while being associated. | 640 | * seconds while being associated. |
642 | */ | 641 | */ |
643 | if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && | 642 | if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D && |
644 | rt2x00dev->intf_associated && count > 20) | 643 | rt2x00dev->intf_associated && count > 20) |
645 | return; | 644 | return; |
646 | 645 | ||
@@ -650,7 +649,7 @@ static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
650 | * should go straight to dynamic CCA tuning when they | 649 | * should go straight to dynamic CCA tuning when they |
651 | * are not associated. | 650 | * are not associated. |
652 | */ | 651 | */ |
653 | if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || | 652 | if (rt2x00_rev(rt2x00dev) < RT2560_VERSION_D || |
654 | !rt2x00dev->intf_associated) | 653 | !rt2x00dev->intf_associated) |
655 | goto dynamic_cca_tune; | 654 | goto dynamic_cca_tune; |
656 | 655 | ||
@@ -1507,12 +1506,12 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1507 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1506 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
1508 | rt2x00_print_chip(rt2x00dev); | 1507 | rt2x00_print_chip(rt2x00dev); |
1509 | 1508 | ||
1510 | if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && | 1509 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1511 | !rt2x00_rf(&rt2x00dev->chip, RF2523) && | 1510 | !rt2x00_rf(rt2x00dev, RF2523) && |
1512 | !rt2x00_rf(&rt2x00dev->chip, RF2524) && | 1511 | !rt2x00_rf(rt2x00dev, RF2524) && |
1513 | !rt2x00_rf(&rt2x00dev->chip, RF2525) && | 1512 | !rt2x00_rf(rt2x00dev, RF2525) && |
1514 | !rt2x00_rf(&rt2x00dev->chip, RF2525E) && | 1513 | !rt2x00_rf(rt2x00dev, RF2525E) && |
1515 | !rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1514 | !rt2x00_rf(rt2x00dev, RF5222)) { |
1516 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1515 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1517 | return -ENODEV; | 1516 | return -ENODEV; |
1518 | } | 1517 | } |
@@ -1744,22 +1743,22 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1744 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 1743 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
1745 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 1744 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
1746 | 1745 | ||
1747 | if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { | 1746 | if (rt2x00_rf(rt2x00dev, RF2522)) { |
1748 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); | 1747 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); |
1749 | spec->channels = rf_vals_bg_2522; | 1748 | spec->channels = rf_vals_bg_2522; |
1750 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 1749 | } else if (rt2x00_rf(rt2x00dev, RF2523)) { |
1751 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); | 1750 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); |
1752 | spec->channels = rf_vals_bg_2523; | 1751 | spec->channels = rf_vals_bg_2523; |
1753 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { | 1752 | } else if (rt2x00_rf(rt2x00dev, RF2524)) { |
1754 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); | 1753 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); |
1755 | spec->channels = rf_vals_bg_2524; | 1754 | spec->channels = rf_vals_bg_2524; |
1756 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 1755 | } else if (rt2x00_rf(rt2x00dev, RF2525)) { |
1757 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); | 1756 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); |
1758 | spec->channels = rf_vals_bg_2525; | 1757 | spec->channels = rf_vals_bg_2525; |
1759 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 1758 | } else if (rt2x00_rf(rt2x00dev, RF2525E)) { |
1760 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); | 1759 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); |
1761 | spec->channels = rf_vals_bg_2525e; | 1760 | spec->channels = rf_vals_bg_2525e; |
1762 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1761 | } else if (rt2x00_rf(rt2x00dev, RF5222)) { |
1763 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 1762 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
1764 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); | 1763 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); |
1765 | spec->channels = rf_vals_5222; | 1764 | spec->channels = rf_vals_5222; |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 83f2592c59de..9e6f865c57f2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -565,8 +565,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
565 | /* | 565 | /* |
566 | * RT2525E and RT5222 need to flip TX I/Q | 566 | * RT2525E and RT5222 need to flip TX I/Q |
567 | */ | 567 | */ |
568 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || | 568 | if (rt2x00_rf(rt2x00dev, RF2525E) || rt2x00_rf(rt2x00dev, RF5222)) { |
569 | rt2x00_rf(&rt2x00dev->chip, RF5222)) { | ||
570 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); | 569 | rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); |
571 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); | 570 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); |
572 | rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); | 571 | rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); |
@@ -574,7 +573,7 @@ static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
574 | /* | 573 | /* |
575 | * RT2525E does not need RX I/Q Flip. | 574 | * RT2525E does not need RX I/Q Flip. |
576 | */ | 575 | */ |
577 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) | 576 | if (rt2x00_rf(rt2x00dev, RF2525E)) |
578 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); | 577 | rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); |
579 | } else { | 578 | } else { |
580 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); | 579 | rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); |
@@ -598,7 +597,7 @@ static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, | |||
598 | /* | 597 | /* |
599 | * For RT2525E we should first set the channel to half band higher. | 598 | * For RT2525E we should first set the channel to half band higher. |
600 | */ | 599 | */ |
601 | if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 600 | if (rt2x00_rf(rt2x00dev, RF2525E)) { |
602 | static const u32 vals[] = { | 601 | static const u32 vals[] = { |
603 | 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, | 602 | 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, |
604 | 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, | 603 | 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, |
@@ -793,7 +792,7 @@ static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
793 | rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); | 792 | rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); |
794 | rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); | 793 | rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); |
795 | 794 | ||
796 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { | 795 | if (rt2x00_rev(rt2x00dev) >= RT2570_VERSION_C) { |
797 | rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); | 796 | rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); |
798 | rt2x00_set_field16(®, PHY_CSR2_LNA, 0); | 797 | rt2x00_set_field16(®, PHY_CSR2_LNA, 0); |
799 | } else { | 798 | } else { |
@@ -1411,19 +1410,18 @@ static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1411 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); | 1410 | rt2x00_set_chip(rt2x00dev, RT2570, value, reg); |
1412 | rt2x00_print_chip(rt2x00dev); | 1411 | rt2x00_print_chip(rt2x00dev); |
1413 | 1412 | ||
1414 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) || | 1413 | if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0) || |
1415 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | 1414 | rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { |
1416 | |||
1417 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1415 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1418 | return -ENODEV; | 1416 | return -ENODEV; |
1419 | } | 1417 | } |
1420 | 1418 | ||
1421 | if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && | 1419 | if (!rt2x00_rf(rt2x00dev, RF2522) && |
1422 | !rt2x00_rf(&rt2x00dev->chip, RF2523) && | 1420 | !rt2x00_rf(rt2x00dev, RF2523) && |
1423 | !rt2x00_rf(&rt2x00dev->chip, RF2524) && | 1421 | !rt2x00_rf(rt2x00dev, RF2524) && |
1424 | !rt2x00_rf(&rt2x00dev->chip, RF2525) && | 1422 | !rt2x00_rf(rt2x00dev, RF2525) && |
1425 | !rt2x00_rf(&rt2x00dev->chip, RF2525E) && | 1423 | !rt2x00_rf(rt2x00dev, RF2525E) && |
1426 | !rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1424 | !rt2x00_rf(rt2x00dev, RF5222)) { |
1427 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1425 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1428 | return -ENODEV; | 1426 | return -ENODEV; |
1429 | } | 1427 | } |
@@ -1667,22 +1665,22 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
1667 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 1665 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
1668 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 1666 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
1669 | 1667 | ||
1670 | if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { | 1668 | if (rt2x00_rf(rt2x00dev, RF2522)) { |
1671 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); | 1669 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); |
1672 | spec->channels = rf_vals_bg_2522; | 1670 | spec->channels = rf_vals_bg_2522; |
1673 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { | 1671 | } else if (rt2x00_rf(rt2x00dev, RF2523)) { |
1674 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); | 1672 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); |
1675 | spec->channels = rf_vals_bg_2523; | 1673 | spec->channels = rf_vals_bg_2523; |
1676 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { | 1674 | } else if (rt2x00_rf(rt2x00dev, RF2524)) { |
1677 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); | 1675 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); |
1678 | spec->channels = rf_vals_bg_2524; | 1676 | spec->channels = rf_vals_bg_2524; |
1679 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { | 1677 | } else if (rt2x00_rf(rt2x00dev, RF2525)) { |
1680 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); | 1678 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); |
1681 | spec->channels = rf_vals_bg_2525; | 1679 | spec->channels = rf_vals_bg_2525; |
1682 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { | 1680 | } else if (rt2x00_rf(rt2x00dev, RF2525E)) { |
1683 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); | 1681 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); |
1684 | spec->channels = rf_vals_bg_2525e; | 1682 | spec->channels = rf_vals_bg_2525e; |
1685 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { | 1683 | } else if (rt2x00_rf(rt2x00dev, RF5222)) { |
1686 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 1684 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
1687 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); | 1685 | spec->num_channels = ARRAY_SIZE(rf_vals_5222); |
1688 | spec->channels = rf_vals_5222; | 1686 | spec->channels = rf_vals_5222; |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 27bf887f1453..8ff7db853286 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -37,7 +37,7 @@ | |||
37 | #include <linux/module.h> | 37 | #include <linux/module.h> |
38 | 38 | ||
39 | #include "rt2x00.h" | 39 | #include "rt2x00.h" |
40 | #if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) | 40 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
41 | #include "rt2x00usb.h" | 41 | #include "rt2x00usb.h" |
42 | #endif | 42 | #endif |
43 | #include "rt2800lib.h" | 43 | #include "rt2800lib.h" |
@@ -220,8 +220,7 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | |||
220 | /* | 220 | /* |
221 | * RT2880 and RT3052 don't support MCU requests. | 221 | * RT2880 and RT3052 don't support MCU requests. |
222 | */ | 222 | */ |
223 | if (rt2x00_rt(&rt2x00dev->chip, RT2880) || | 223 | if (rt2x00_rt(rt2x00dev, RT2880) || rt2x00_rt(rt2x00dev, RT3052)) |
224 | rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
225 | return; | 224 | return; |
226 | 225 | ||
227 | mutex_lock(&rt2x00dev->csr_mutex); | 226 | mutex_lock(&rt2x00dev->csr_mutex); |
@@ -806,12 +805,12 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
806 | unsigned int tx_pin; | 805 | unsigned int tx_pin; |
807 | u8 bbp; | 806 | u8 bbp; |
808 | 807 | ||
809 | if ((rt2x00_rt(&rt2x00dev->chip, RT3070) || | 808 | if ((rt2x00_rt(rt2x00dev, RT3070) || |
810 | rt2x00_rt(&rt2x00dev->chip, RT3090)) && | 809 | rt2x00_rt(rt2x00dev, RT3090)) && |
811 | (rt2x00_rf(&rt2x00dev->chip, RF2020) || | 810 | (rt2x00_rf(rt2x00dev, RF2020) || |
812 | rt2x00_rf(&rt2x00dev->chip, RF3020) || | 811 | rt2x00_rf(rt2x00dev, RF3020) || |
813 | rt2x00_rf(&rt2x00dev->chip, RF3021) || | 812 | rt2x00_rf(rt2x00dev, RF3021) || |
814 | rt2x00_rf(&rt2x00dev->chip, RF3022))) | 813 | rt2x00_rf(rt2x00dev, RF3022))) |
815 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); | 814 | rt2800_config_channel_rt3x(rt2x00dev, conf, rf, info); |
816 | else | 815 | else |
817 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); | 816 | rt2800_config_channel_rt2x(rt2x00dev, conf, rf, info); |
@@ -878,7 +877,7 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
878 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); | 877 | rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); |
879 | rt2800_bbp_write(rt2x00dev, 3, bbp); | 878 | rt2800_bbp_write(rt2x00dev, 3, bbp); |
880 | 879 | ||
881 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | 880 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { |
882 | if (conf_is_ht40(conf)) { | 881 | if (conf_is_ht40(conf)) { |
883 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); | 882 | rt2800_bbp_write(rt2x00dev, 69, 0x1a); |
884 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 883 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
@@ -1041,7 +1040,7 @@ static u8 rt2800_get_default_vgc(struct rt2x00_dev *rt2x00dev) | |||
1041 | { | 1040 | { |
1042 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { | 1041 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
1043 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1042 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1044 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) | 1043 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) |
1045 | return 0x1c + (2 * rt2x00dev->lna_gain); | 1044 | return 0x1c + (2 * rt2x00dev->lna_gain); |
1046 | else | 1045 | else |
1047 | return 0x2e + rt2x00dev->lna_gain; | 1046 | return 0x2e + rt2x00dev->lna_gain; |
@@ -1072,7 +1071,7 @@ EXPORT_SYMBOL_GPL(rt2800_reset_tuner); | |||
1072 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, | 1071 | void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, |
1073 | const u32 count) | 1072 | const u32 count) |
1074 | { | 1073 | { |
1075 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) | 1074 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) |
1076 | return; | 1075 | return; |
1077 | 1076 | ||
1078 | /* | 1077 | /* |
@@ -1121,7 +1120,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1121 | 1120 | ||
1122 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1121 | if (rt2x00_intf_is_usb(rt2x00dev)) { |
1123 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); | 1122 | rt2800_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); |
1124 | #if defined(CONFIG_RT2800USB) || defined(CONFIG_RT2800USB_MODULE) | 1123 | #if defined(CONFIG_RT2X00_LIB_USB) || defined(CONFIG_RT2X00_LIB_USB_MODULE) |
1125 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, | 1124 | rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, |
1126 | USB_MODE_RESET, REGISTER_TIMEOUT); | 1125 | USB_MODE_RESET, REGISTER_TIMEOUT); |
1127 | #endif | 1126 | #endif |
@@ -1158,7 +1157,7 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1158 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); | 1157 | rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); |
1159 | 1158 | ||
1160 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1159 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1161 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { | 1160 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) { |
1162 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); | 1161 | rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); |
1163 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); | 1162 | rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); |
1164 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); | 1163 | rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); |
@@ -1185,8 +1184,8 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1185 | 1184 | ||
1186 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); | 1185 | rt2800_register_read(rt2x00dev, MAX_LEN_CFG, ®); |
1187 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); | 1186 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); |
1188 | if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && | 1187 | if (rt2x00_rev(rt2x00dev) >= RT2880E_VERSION && |
1189 | rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) | 1188 | rt2x00_rev(rt2x00dev) < RT3070_VERSION) |
1190 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); | 1189 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); |
1191 | else | 1190 | else |
1192 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); | 1191 | rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); |
@@ -1465,22 +1464,22 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev) | |||
1465 | rt2800_bbp_write(rt2x00dev, 103, 0x00); | 1464 | rt2800_bbp_write(rt2x00dev, 103, 0x00); |
1466 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1465 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1467 | 1466 | ||
1468 | if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { | 1467 | if (rt2x00_rev(rt2x00dev) == RT2860C_VERSION) { |
1469 | rt2800_bbp_write(rt2x00dev, 69, 0x16); | 1468 | rt2800_bbp_write(rt2x00dev, 69, 0x16); |
1470 | rt2800_bbp_write(rt2x00dev, 73, 0x12); | 1469 | rt2800_bbp_write(rt2x00dev, 73, 0x12); |
1471 | } | 1470 | } |
1472 | 1471 | ||
1473 | if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) | 1472 | if (rt2x00_rev(rt2x00dev) > RT2860D_VERSION) |
1474 | rt2800_bbp_write(rt2x00dev, 84, 0x19); | 1473 | rt2800_bbp_write(rt2x00dev, 84, 0x19); |
1475 | 1474 | ||
1476 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1475 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1477 | rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { | 1476 | rt2x00_rev(rt2x00dev) == RT3070_VERSION) { |
1478 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); | 1477 | rt2800_bbp_write(rt2x00dev, 70, 0x0a); |
1479 | rt2800_bbp_write(rt2x00dev, 84, 0x99); | 1478 | rt2800_bbp_write(rt2x00dev, 84, 0x99); |
1480 | rt2800_bbp_write(rt2x00dev, 105, 0x05); | 1479 | rt2800_bbp_write(rt2x00dev, 105, 0x05); |
1481 | } | 1480 | } |
1482 | 1481 | ||
1483 | if (rt2x00_rt(&rt2x00dev->chip, RT3052)) { | 1482 | if (rt2x00_rt(rt2x00dev, RT3052)) { |
1484 | rt2800_bbp_write(rt2x00dev, 31, 0x08); | 1483 | rt2800_bbp_write(rt2x00dev, 31, 0x08); |
1485 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); | 1484 | rt2800_bbp_write(rt2x00dev, 78, 0x0e); |
1486 | rt2800_bbp_write(rt2x00dev, 80, 0x08); | 1485 | rt2800_bbp_write(rt2x00dev, 80, 0x08); |
@@ -1566,13 +1565,13 @@ int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev) | |||
1566 | u8 bbp; | 1565 | u8 bbp; |
1567 | 1566 | ||
1568 | if (rt2x00_intf_is_usb(rt2x00dev) && | 1567 | if (rt2x00_intf_is_usb(rt2x00dev) && |
1569 | rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) | 1568 | rt2x00_rev(rt2x00dev) != RT3070_VERSION) |
1570 | return 0; | 1569 | return 0; |
1571 | 1570 | ||
1572 | if (rt2x00_intf_is_pci(rt2x00dev)) { | 1571 | if (rt2x00_intf_is_pci(rt2x00dev)) { |
1573 | if (!rt2x00_rf(&rt2x00dev->chip, RF3020) && | 1572 | if (!rt2x00_rf(rt2x00dev, RF3020) && |
1574 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | 1573 | !rt2x00_rf(rt2x00dev, RF3021) && |
1575 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) | 1574 | !rt2x00_rf(rt2x00dev, RF3022)) |
1576 | return 0; | 1575 | return 0; |
1577 | } | 1576 | } |
1578 | 1577 | ||
@@ -1737,7 +1736,7 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1737 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); | 1736 | rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); |
1738 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); | 1737 | rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); |
1739 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); | 1738 | EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); |
1740 | } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { | 1739 | } else if (rt2x00_rev(rt2x00dev) < RT2883_VERSION) { |
1741 | /* | 1740 | /* |
1742 | * There is a max of 2 RX streams for RT28x0 series | 1741 | * There is a max of 2 RX streams for RT28x0 series |
1743 | */ | 1742 | */ |
@@ -1839,17 +1838,15 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1839 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 1838 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
1840 | 1839 | ||
1841 | if (rt2x00_intf_is_usb(rt2x00dev)) { | 1840 | if (rt2x00_intf_is_usb(rt2x00dev)) { |
1842 | struct rt2x00_chip *chip = &rt2x00dev->chip; | ||
1843 | |||
1844 | /* | 1841 | /* |
1845 | * The check for rt2860 is not a typo, some rt2870 hardware | 1842 | * The check for rt2860 is not a typo, some rt2870 hardware |
1846 | * identifies itself as rt2860 in the CSR register. | 1843 | * identifies itself as rt2860 in the CSR register. |
1847 | */ | 1844 | */ |
1848 | if (rt2x00_check_rev(chip, 0xfff00000, 0x28600000) || | 1845 | if (rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28600000) || |
1849 | rt2x00_check_rev(chip, 0xfff00000, 0x28700000) || | 1846 | rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28700000) || |
1850 | rt2x00_check_rev(chip, 0xfff00000, 0x28800000)) { | 1847 | rt2x00_check_rev(rt2x00dev, 0xfff00000, 0x28800000)) { |
1851 | rt2x00_set_chip_rt(rt2x00dev, RT2870); | 1848 | rt2x00_set_chip_rt(rt2x00dev, RT2870); |
1852 | } else if (rt2x00_check_rev(chip, 0xffff0000, 0x30700000)) { | 1849 | } else if (rt2x00_check_rev(rt2x00dev, 0xffff0000, 0x30700000)) { |
1853 | rt2x00_set_chip_rt(rt2x00dev, RT3070); | 1850 | rt2x00_set_chip_rt(rt2x00dev, RT3070); |
1854 | } else { | 1851 | } else { |
1855 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1852 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
@@ -1858,14 +1855,14 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1858 | } | 1855 | } |
1859 | rt2x00_print_chip(rt2x00dev); | 1856 | rt2x00_print_chip(rt2x00dev); |
1860 | 1857 | ||
1861 | if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && | 1858 | if (!rt2x00_rf(rt2x00dev, RF2820) && |
1862 | !rt2x00_rf(&rt2x00dev->chip, RF2850) && | 1859 | !rt2x00_rf(rt2x00dev, RF2850) && |
1863 | !rt2x00_rf(&rt2x00dev->chip, RF2720) && | 1860 | !rt2x00_rf(rt2x00dev, RF2720) && |
1864 | !rt2x00_rf(&rt2x00dev->chip, RF2750) && | 1861 | !rt2x00_rf(rt2x00dev, RF2750) && |
1865 | !rt2x00_rf(&rt2x00dev->chip, RF3020) && | 1862 | !rt2x00_rf(rt2x00dev, RF3020) && |
1866 | !rt2x00_rf(&rt2x00dev->chip, RF2020) && | 1863 | !rt2x00_rf(rt2x00dev, RF2020) && |
1867 | !rt2x00_rf(&rt2x00dev->chip, RF3021) && | 1864 | !rt2x00_rf(rt2x00dev, RF3021) && |
1868 | !rt2x00_rf(&rt2x00dev->chip, RF3022)) { | 1865 | !rt2x00_rf(rt2x00dev, RF3022)) { |
1869 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1866 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1870 | return -ENODEV; | 1867 | return -ENODEV; |
1871 | } | 1868 | } |
@@ -2013,7 +2010,6 @@ static const struct rf_channel rf_vals_302x[] = { | |||
2013 | 2010 | ||
2014 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | 2011 | int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) |
2015 | { | 2012 | { |
2016 | struct rt2x00_chip *chip = &rt2x00dev->chip; | ||
2017 | struct hw_mode_spec *spec = &rt2x00dev->spec; | 2013 | struct hw_mode_spec *spec = &rt2x00dev->spec; |
2018 | struct channel_info *info; | 2014 | struct channel_info *info; |
2019 | char *tx_power1; | 2015 | char *tx_power1; |
@@ -2049,19 +2045,19 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2049 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2045 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2050 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2046 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2051 | 2047 | ||
2052 | if (rt2x00_rf(chip, RF2820) || | 2048 | if (rt2x00_rf(rt2x00dev, RF2820) || |
2053 | rt2x00_rf(chip, RF2720) || | 2049 | rt2x00_rf(rt2x00dev, RF2720) || |
2054 | (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(chip, RF3052))) { | 2050 | (rt2x00_intf_is_pci(rt2x00dev) && rt2x00_rf(rt2x00dev, RF3052))) { |
2055 | spec->num_channels = 14; | 2051 | spec->num_channels = 14; |
2056 | spec->channels = rf_vals; | 2052 | spec->channels = rf_vals; |
2057 | } else if (rt2x00_rf(chip, RF2850) || rt2x00_rf(chip, RF2750)) { | 2053 | } else if (rt2x00_rf(rt2x00dev, RF2850) || rt2x00_rf(rt2x00dev, RF2750)) { |
2058 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2054 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2059 | spec->num_channels = ARRAY_SIZE(rf_vals); | 2055 | spec->num_channels = ARRAY_SIZE(rf_vals); |
2060 | spec->channels = rf_vals; | 2056 | spec->channels = rf_vals; |
2061 | } else if (rt2x00_rf(chip, RF3020) || | 2057 | } else if (rt2x00_rf(rt2x00dev, RF3020) || |
2062 | rt2x00_rf(chip, RF2020) || | 2058 | rt2x00_rf(rt2x00dev, RF2020) || |
2063 | rt2x00_rf(chip, RF3021) || | 2059 | rt2x00_rf(rt2x00dev, RF3021) || |
2064 | rt2x00_rf(chip, RF3022)) { | 2060 | rt2x00_rf(rt2x00dev, RF3022)) { |
2065 | spec->num_channels = ARRAY_SIZE(rf_vals_302x); | 2061 | spec->num_channels = ARRAY_SIZE(rf_vals_302x); |
2066 | spec->channels = rf_vals_302x; | 2062 | spec->channels = rf_vals_302x; |
2067 | } | 2063 | } |
@@ -2069,7 +2065,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2069 | /* | 2065 | /* |
2070 | * Initialize HT information. | 2066 | * Initialize HT information. |
2071 | */ | 2067 | */ |
2072 | if (!rt2x00_rf(chip, RF2020)) | 2068 | if (!rt2x00_rf(rt2x00dev, RF2020)) |
2073 | spec->ht.ht_supported = true; | 2069 | spec->ht.ht_supported = true; |
2074 | else | 2070 | else |
2075 | spec->ht.ht_supported = false; | 2071 | spec->ht.ht_supported = false; |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 458378c4e500..b93eabb4fbe1 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -48,14 +48,6 @@ | |||
48 | #include "rt2800.h" | 48 | #include "rt2800.h" |
49 | #include "rt2800pci.h" | 49 | #include "rt2800pci.h" |
50 | 50 | ||
51 | #ifdef CONFIG_RT2800PCI_PCI_MODULE | ||
52 | #define CONFIG_RT2800PCI_PCI | ||
53 | #endif | ||
54 | |||
55 | #ifdef CONFIG_RT2800PCI_WISOC_MODULE | ||
56 | #define CONFIG_RT2800PCI_WISOC | ||
57 | #endif | ||
58 | |||
59 | /* | 51 | /* |
60 | * Allow hardware encryption to be disabled. | 52 | * Allow hardware encryption to be disabled. |
61 | */ | 53 | */ |
@@ -87,7 +79,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
87 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 79 | rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
88 | } | 80 | } |
89 | 81 | ||
90 | #ifdef CONFIG_RT2800PCI_WISOC | 82 | #ifdef CONFIG_RT2800PCI_SOC |
91 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 83 | static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
92 | { | 84 | { |
93 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ | 85 | u32 *base_addr = (u32 *) KSEG1ADDR(0x1F040000); /* XXX for RT3052 */ |
@@ -98,7 +90,7 @@ static void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | |||
98 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 90 | static inline void rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
99 | { | 91 | { |
100 | } | 92 | } |
101 | #endif /* CONFIG_RT2800PCI_WISOC */ | 93 | #endif /* CONFIG_RT2800PCI_SOC */ |
102 | 94 | ||
103 | #ifdef CONFIG_RT2800PCI_PCI | 95 | #ifdef CONFIG_RT2800PCI_PCI |
104 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 96 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -1129,8 +1121,7 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1129 | /* | 1121 | /* |
1130 | * This device requires firmware. | 1122 | * This device requires firmware. |
1131 | */ | 1123 | */ |
1132 | if (!rt2x00_rt(&rt2x00dev->chip, RT2880) && | 1124 | if (!rt2x00_rt(rt2x00dev, RT2880) && !rt2x00_rt(rt2x00dev, RT3052)) |
1133 | !rt2x00_rt(&rt2x00dev->chip, RT3052)) | ||
1134 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 1125 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
1135 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); | 1126 | __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); |
1136 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 1127 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
@@ -1251,7 +1242,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1251 | #endif /* CONFIG_RT2800PCI_PCI */ | 1242 | #endif /* CONFIG_RT2800PCI_PCI */ |
1252 | MODULE_LICENSE("GPL"); | 1243 | MODULE_LICENSE("GPL"); |
1253 | 1244 | ||
1254 | #ifdef CONFIG_RT2800PCI_WISOC | 1245 | #ifdef CONFIG_RT2800PCI_SOC |
1255 | #if defined(CONFIG_RALINK_RT288X) | 1246 | #if defined(CONFIG_RALINK_RT288X) |
1256 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); | 1247 | __rt2x00soc_probe(RT2880, &rt2800pci_ops); |
1257 | #elif defined(CONFIG_RALINK_RT305X) | 1248 | #elif defined(CONFIG_RALINK_RT305X) |
@@ -1269,7 +1260,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1269 | .suspend = rt2x00soc_suspend, | 1260 | .suspend = rt2x00soc_suspend, |
1270 | .resume = rt2x00soc_resume, | 1261 | .resume = rt2x00soc_resume, |
1271 | }; | 1262 | }; |
1272 | #endif /* CONFIG_RT2800PCI_WISOC */ | 1263 | #endif /* CONFIG_RT2800PCI_SOC */ |
1273 | 1264 | ||
1274 | #ifdef CONFIG_RT2800PCI_PCI | 1265 | #ifdef CONFIG_RT2800PCI_PCI |
1275 | static struct pci_driver rt2800pci_driver = { | 1266 | static struct pci_driver rt2800pci_driver = { |
@@ -1286,7 +1277,7 @@ static int __init rt2800pci_init(void) | |||
1286 | { | 1277 | { |
1287 | int ret = 0; | 1278 | int ret = 0; |
1288 | 1279 | ||
1289 | #ifdef CONFIG_RT2800PCI_WISOC | 1280 | #ifdef CONFIG_RT2800PCI_SOC |
1290 | ret = platform_driver_register(&rt2800soc_driver); | 1281 | ret = platform_driver_register(&rt2800soc_driver); |
1291 | if (ret) | 1282 | if (ret) |
1292 | return ret; | 1283 | return ret; |
@@ -1294,7 +1285,7 @@ static int __init rt2800pci_init(void) | |||
1294 | #ifdef CONFIG_RT2800PCI_PCI | 1285 | #ifdef CONFIG_RT2800PCI_PCI |
1295 | ret = pci_register_driver(&rt2800pci_driver); | 1286 | ret = pci_register_driver(&rt2800pci_driver); |
1296 | if (ret) { | 1287 | if (ret) { |
1297 | #ifdef CONFIG_RT2800PCI_WISOC | 1288 | #ifdef CONFIG_RT2800PCI_SOC |
1298 | platform_driver_unregister(&rt2800soc_driver); | 1289 | platform_driver_unregister(&rt2800soc_driver); |
1299 | #endif | 1290 | #endif |
1300 | return ret; | 1291 | return ret; |
@@ -1309,7 +1300,7 @@ static void __exit rt2800pci_exit(void) | |||
1309 | #ifdef CONFIG_RT2800PCI_PCI | 1300 | #ifdef CONFIG_RT2800PCI_PCI |
1310 | pci_unregister_driver(&rt2800pci_driver); | 1301 | pci_unregister_driver(&rt2800pci_driver); |
1311 | #endif | 1302 | #endif |
1312 | #ifdef CONFIG_RT2800PCI_WISOC | 1303 | #ifdef CONFIG_RT2800PCI_SOC |
1313 | platform_driver_unregister(&rt2800soc_driver); | 1304 | platform_driver_unregister(&rt2800soc_driver); |
1314 | #endif | 1305 | #endif |
1315 | } | 1306 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 40295b454ff6..0510f020dcf5 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -92,7 +92,7 @@ static bool rt2800usb_check_crc(const u8 *data, const size_t len) | |||
92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, | 92 | static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, |
93 | const u8 *data, const size_t len) | 93 | const u8 *data, const size_t len) |
94 | { | 94 | { |
95 | u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; | 95 | u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; |
96 | size_t offset = 0; | 96 | size_t offset = 0; |
97 | 97 | ||
98 | /* | 98 | /* |
@@ -138,7 +138,7 @@ static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
138 | u32 reg; | 138 | u32 reg; |
139 | u32 offset; | 139 | u32 offset; |
140 | u32 length; | 140 | u32 length; |
141 | u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; | 141 | u16 chipset = (rt2x00_rev(rt2x00dev) >> 16) & 0xffff; |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * Check which section of the firmware we need. | 144 | * Check which section of the firmware we need. |
@@ -933,6 +933,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
933 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, | 933 | { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, |
934 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, | 934 | { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, |
935 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, | 935 | { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, |
936 | { USB_DEVICE(0x1737, 0x0079), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
936 | /* Logitec */ | 937 | /* Logitec */ |
937 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, | 938 | { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, |
938 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, | 939 | { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 194dae01d0c3..b4c6e0a6d7e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -937,25 +937,25 @@ static inline void rt2x00_print_chip(struct rt2x00_dev *rt2x00dev) | |||
937 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); | 937 | rt2x00dev->chip.rt, rt2x00dev->chip.rf, rt2x00dev->chip.rev); |
938 | } | 938 | } |
939 | 939 | ||
940 | static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) | 940 | static inline char rt2x00_rt(struct rt2x00_dev *rt2x00dev, const u16 rt) |
941 | { | 941 | { |
942 | return (chipset->rt == chip); | 942 | return (rt2x00dev->chip.rt == rt); |
943 | } | 943 | } |
944 | 944 | ||
945 | static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) | 945 | static inline char rt2x00_rf(struct rt2x00_dev *rt2x00dev, const u16 rf) |
946 | { | 946 | { |
947 | return (chipset->rf == chip); | 947 | return (rt2x00dev->chip.rf == rf); |
948 | } | 948 | } |
949 | 949 | ||
950 | static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) | 950 | static inline u32 rt2x00_rev(struct rt2x00_dev *rt2x00dev) |
951 | { | 951 | { |
952 | return chipset->rev; | 952 | return rt2x00dev->chip.rev; |
953 | } | 953 | } |
954 | 954 | ||
955 | static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, | 955 | static inline bool rt2x00_check_rev(struct rt2x00_dev *rt2x00dev, |
956 | const u32 mask, const u32 rev) | 956 | const u32 mask, const u32 rev) |
957 | { | 957 | { |
958 | return ((chipset->rev & mask) == rev); | 958 | return ((rt2x00dev->chip.rev & mask) == rev); |
959 | } | 959 | } |
960 | 960 | ||
961 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | 961 | static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, |
@@ -964,20 +964,20 @@ static inline void rt2x00_set_chip_intf(struct rt2x00_dev *rt2x00dev, | |||
964 | rt2x00dev->chip.intf = intf; | 964 | rt2x00dev->chip.intf = intf; |
965 | } | 965 | } |
966 | 966 | ||
967 | static inline bool rt2x00_intf(const struct rt2x00_chip *chipset, | 967 | static inline bool rt2x00_intf(struct rt2x00_dev *rt2x00dev, |
968 | enum rt2x00_chip_intf intf) | 968 | enum rt2x00_chip_intf intf) |
969 | { | 969 | { |
970 | return (chipset->intf == intf); | 970 | return (rt2x00dev->chip.intf == intf); |
971 | } | 971 | } |
972 | 972 | ||
973 | static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) | 973 | static inline bool rt2x00_intf_is_pci(struct rt2x00_dev *rt2x00dev) |
974 | { | 974 | { |
975 | return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_PCI); | 975 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_PCI); |
976 | } | 976 | } |
977 | 977 | ||
978 | static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) | 978 | static inline bool rt2x00_intf_is_usb(struct rt2x00_dev *rt2x00dev) |
979 | { | 979 | { |
980 | return rt2x00_intf(&rt2x00dev->chip, RT2X00_CHIP_INTF_USB); | 980 | return rt2x00_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
981 | } | 981 | } |
982 | 982 | ||
983 | /** | 983 | /** |
@@ -1019,9 +1019,9 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | |||
1019 | int rt2x00mac_start(struct ieee80211_hw *hw); | 1019 | int rt2x00mac_start(struct ieee80211_hw *hw); |
1020 | void rt2x00mac_stop(struct ieee80211_hw *hw); | 1020 | void rt2x00mac_stop(struct ieee80211_hw *hw); |
1021 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, | 1021 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, |
1022 | struct ieee80211_if_init_conf *conf); | 1022 | struct ieee80211_vif *vif); |
1023 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | 1023 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, |
1024 | struct ieee80211_if_init_conf *conf); | 1024 | struct ieee80211_vif *vif); |
1025 | int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); | 1025 | int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); |
1026 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 1026 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
1027 | unsigned int changed_flags, | 1027 | unsigned int changed_flags, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index de549c244ed8..00f1f939f1bb 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -187,10 +187,10 @@ void rt2x00mac_stop(struct ieee80211_hw *hw) | |||
187 | EXPORT_SYMBOL_GPL(rt2x00mac_stop); | 187 | EXPORT_SYMBOL_GPL(rt2x00mac_stop); |
188 | 188 | ||
189 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, | 189 | int rt2x00mac_add_interface(struct ieee80211_hw *hw, |
190 | struct ieee80211_if_init_conf *conf) | 190 | struct ieee80211_vif *vif) |
191 | { | 191 | { |
192 | struct rt2x00_dev *rt2x00dev = hw->priv; | 192 | struct rt2x00_dev *rt2x00dev = hw->priv; |
193 | struct rt2x00_intf *intf = vif_to_intf(conf->vif); | 193 | struct rt2x00_intf *intf = vif_to_intf(vif); |
194 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); | 194 | struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); |
195 | struct queue_entry *entry = NULL; | 195 | struct queue_entry *entry = NULL; |
196 | unsigned int i; | 196 | unsigned int i; |
@@ -203,7 +203,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
203 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) | 203 | !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) |
204 | return -ENODEV; | 204 | return -ENODEV; |
205 | 205 | ||
206 | switch (conf->type) { | 206 | switch (vif->type) { |
207 | case NL80211_IFTYPE_AP: | 207 | case NL80211_IFTYPE_AP: |
208 | /* | 208 | /* |
209 | * We don't support mixed combinations of | 209 | * We don't support mixed combinations of |
@@ -263,7 +263,7 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
263 | * increase interface count and start initialization. | 263 | * increase interface count and start initialization. |
264 | */ | 264 | */ |
265 | 265 | ||
266 | if (conf->type == NL80211_IFTYPE_AP) | 266 | if (vif->type == NL80211_IFTYPE_AP) |
267 | rt2x00dev->intf_ap_count++; | 267 | rt2x00dev->intf_ap_count++; |
268 | else | 268 | else |
269 | rt2x00dev->intf_sta_count++; | 269 | rt2x00dev->intf_sta_count++; |
@@ -273,16 +273,16 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
273 | mutex_init(&intf->beacon_skb_mutex); | 273 | mutex_init(&intf->beacon_skb_mutex); |
274 | intf->beacon = entry; | 274 | intf->beacon = entry; |
275 | 275 | ||
276 | if (conf->type == NL80211_IFTYPE_AP) | 276 | if (vif->type == NL80211_IFTYPE_AP) |
277 | memcpy(&intf->bssid, conf->mac_addr, ETH_ALEN); | 277 | memcpy(&intf->bssid, vif->addr, ETH_ALEN); |
278 | memcpy(&intf->mac, conf->mac_addr, ETH_ALEN); | 278 | memcpy(&intf->mac, vif->addr, ETH_ALEN); |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * The MAC adddress must be configured after the device | 281 | * The MAC adddress must be configured after the device |
282 | * has been initialized. Otherwise the device can reset | 282 | * has been initialized. Otherwise the device can reset |
283 | * the MAC registers. | 283 | * the MAC registers. |
284 | */ | 284 | */ |
285 | rt2x00lib_config_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); | 285 | rt2x00lib_config_intf(rt2x00dev, intf, vif->type, intf->mac, NULL); |
286 | 286 | ||
287 | /* | 287 | /* |
288 | * Some filters depend on the current working mode. We can force | 288 | * Some filters depend on the current working mode. We can force |
@@ -296,10 +296,10 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, | |||
296 | EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); | 296 | EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); |
297 | 297 | ||
298 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | 298 | void rt2x00mac_remove_interface(struct ieee80211_hw *hw, |
299 | struct ieee80211_if_init_conf *conf) | 299 | struct ieee80211_vif *vif) |
300 | { | 300 | { |
301 | struct rt2x00_dev *rt2x00dev = hw->priv; | 301 | struct rt2x00_dev *rt2x00dev = hw->priv; |
302 | struct rt2x00_intf *intf = vif_to_intf(conf->vif); | 302 | struct rt2x00_intf *intf = vif_to_intf(vif); |
303 | 303 | ||
304 | /* | 304 | /* |
305 | * Don't allow interfaces to be remove while | 305 | * Don't allow interfaces to be remove while |
@@ -307,11 +307,11 @@ void rt2x00mac_remove_interface(struct ieee80211_hw *hw, | |||
307 | * no interface is present. | 307 | * no interface is present. |
308 | */ | 308 | */ |
309 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || | 309 | if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || |
310 | (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || | 310 | (vif->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || |
311 | (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) | 311 | (vif->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) |
312 | return; | 312 | return; |
313 | 313 | ||
314 | if (conf->type == NL80211_IFTYPE_AP) | 314 | if (vif->type == NL80211_IFTYPE_AP) |
315 | rt2x00dev->intf_ap_count--; | 315 | rt2x00dev->intf_ap_count--; |
316 | else | 316 | else |
317 | rt2x00dev->intf_sta_count--; | 317 | rt2x00dev->intf_sta_count--; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index 0ca589306d71..c353b497a65d 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -637,8 +637,7 @@ static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, | |||
637 | rt61pci_bbp_read(rt2x00dev, 4, &r4); | 637 | rt61pci_bbp_read(rt2x00dev, 4, &r4); |
638 | rt61pci_bbp_read(rt2x00dev, 77, &r77); | 638 | rt61pci_bbp_read(rt2x00dev, 77, &r77); |
639 | 639 | ||
640 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, | 640 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF5325)); |
641 | rt2x00_rf(&rt2x00dev->chip, RF5325)); | ||
642 | 641 | ||
643 | /* | 642 | /* |
644 | * Configure the RX antenna. | 643 | * Configure the RX antenna. |
@@ -684,8 +683,7 @@ static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, | |||
684 | rt61pci_bbp_read(rt2x00dev, 4, &r4); | 683 | rt61pci_bbp_read(rt2x00dev, 4, &r4); |
685 | rt61pci_bbp_read(rt2x00dev, 77, &r77); | 684 | rt61pci_bbp_read(rt2x00dev, 77, &r77); |
686 | 685 | ||
687 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, | 686 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, rt2x00_rf(rt2x00dev, RF2529)); |
688 | rt2x00_rf(&rt2x00dev->chip, RF2529)); | ||
689 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, | 687 | rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, |
690 | !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); | 688 | !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); |
691 | 689 | ||
@@ -833,12 +831,11 @@ static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, | |||
833 | 831 | ||
834 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); | 832 | rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); |
835 | 833 | ||
836 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 834 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) |
837 | rt2x00_rf(&rt2x00dev->chip, RF5325)) | ||
838 | rt61pci_config_antenna_5x(rt2x00dev, ant); | 835 | rt61pci_config_antenna_5x(rt2x00dev, ant); |
839 | else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) | 836 | else if (rt2x00_rf(rt2x00dev, RF2527)) |
840 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 837 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
841 | else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) { | 838 | else if (rt2x00_rf(rt2x00dev, RF2529)) { |
842 | if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) | 839 | if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) |
843 | rt61pci_config_antenna_2x(rt2x00dev, ant); | 840 | rt61pci_config_antenna_2x(rt2x00dev, ant); |
844 | else | 841 | else |
@@ -879,8 +876,7 @@ static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, | |||
879 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); | 876 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); |
880 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 877 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
881 | 878 | ||
882 | smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || | 879 | smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); |
883 | rt2x00_rf(&rt2x00dev->chip, RF2527)); | ||
884 | 880 | ||
885 | rt61pci_bbp_read(rt2x00dev, 3, &r3); | 881 | rt61pci_bbp_read(rt2x00dev, 3, &r3); |
886 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); | 882 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); |
@@ -2302,10 +2298,10 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2302 | rt2x00_set_chip_rf(rt2x00dev, value, reg); | 2298 | rt2x00_set_chip_rf(rt2x00dev, value, reg); |
2303 | rt2x00_print_chip(rt2x00dev); | 2299 | rt2x00_print_chip(rt2x00dev); |
2304 | 2300 | ||
2305 | if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && | 2301 | if (!rt2x00_rf(rt2x00dev, RF5225) && |
2306 | !rt2x00_rf(&rt2x00dev->chip, RF5325) && | 2302 | !rt2x00_rf(rt2x00dev, RF5325) && |
2307 | !rt2x00_rf(&rt2x00dev->chip, RF2527) && | 2303 | !rt2x00_rf(rt2x00dev, RF2527) && |
2308 | !rt2x00_rf(&rt2x00dev->chip, RF2529)) { | 2304 | !rt2x00_rf(rt2x00dev, RF2529)) { |
2309 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 2305 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
2310 | return -ENODEV; | 2306 | return -ENODEV; |
2311 | } | 2307 | } |
@@ -2360,7 +2356,7 @@ static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
2360 | * the antenna settings should be gathered from the NIC | 2356 | * the antenna settings should be gathered from the NIC |
2361 | * eeprom word. | 2357 | * eeprom word. |
2362 | */ | 2358 | */ |
2363 | if (rt2x00_rf(&rt2x00dev->chip, RF2529) && | 2359 | if (rt2x00_rf(rt2x00dev, RF2529) && |
2364 | !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { | 2360 | !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { |
2365 | rt2x00dev->default_ant.rx = | 2361 | rt2x00dev->default_ant.rx = |
2366 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); | 2362 | ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); |
@@ -2571,8 +2567,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2571 | spec->channels = rf_vals_seq; | 2567 | spec->channels = rf_vals_seq; |
2572 | } | 2568 | } |
2573 | 2569 | ||
2574 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 2570 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF5325)) { |
2575 | rt2x00_rf(&rt2x00dev->chip, RF5325)) { | ||
2576 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2571 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2577 | spec->num_channels = ARRAY_SIZE(rf_vals_seq); | 2572 | spec->num_channels = ARRAY_SIZE(rf_vals_seq); |
2578 | } | 2573 | } |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 6ce88d3c3b65..a02691294395 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -136,8 +136,8 @@ static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, | |||
136 | * all others contain 20 bits. | 136 | * all others contain 20 bits. |
137 | */ | 137 | */ |
138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, | 138 | rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, |
139 | 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 139 | 20 + (rt2x00_rf(rt2x00dev, RF5225) || |
140 | rt2x00_rf(&rt2x00dev->chip, RF2527))); | 140 | rt2x00_rf(rt2x00dev, RF2527))); |
141 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); | 141 | rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); |
142 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); | 142 | rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); |
143 | 143 | ||
@@ -741,11 +741,9 @@ static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, | |||
741 | 741 | ||
742 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); | 742 | rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); |
743 | 743 | ||
744 | if (rt2x00_rf(&rt2x00dev->chip, RF5226) || | 744 | if (rt2x00_rf(rt2x00dev, RF5226) || rt2x00_rf(rt2x00dev, RF5225)) |
745 | rt2x00_rf(&rt2x00dev->chip, RF5225)) | ||
746 | rt73usb_config_antenna_5x(rt2x00dev, ant); | 745 | rt73usb_config_antenna_5x(rt2x00dev, ant); |
747 | else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || | 746 | else if (rt2x00_rf(rt2x00dev, RF2528) || rt2x00_rf(rt2x00dev, RF2527)) |
748 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | ||
749 | rt73usb_config_antenna_2x(rt2x00dev, ant); | 747 | rt73usb_config_antenna_2x(rt2x00dev, ant); |
750 | } | 748 | } |
751 | 749 | ||
@@ -779,8 +777,7 @@ static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, | |||
779 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); | 777 | rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); |
780 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); | 778 | rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); |
781 | 779 | ||
782 | smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || | 780 | smart = !(rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)); |
783 | rt2x00_rf(&rt2x00dev->chip, RF2527)); | ||
784 | 781 | ||
785 | rt73usb_bbp_read(rt2x00dev, 3, &r3); | 782 | rt73usb_bbp_read(rt2x00dev, 3, &r3); |
786 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); | 783 | rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); |
@@ -1210,8 +1207,7 @@ static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1210 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); | 1207 | rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); |
1211 | 1208 | ||
1212 | reg = 0x000023b0; | 1209 | reg = 0x000023b0; |
1213 | if (rt2x00_rf(&rt2x00dev->chip, RF5225) || | 1210 | if (rt2x00_rf(rt2x00dev, RF5225) || rt2x00_rf(rt2x00dev, RF2527)) |
1214 | rt2x00_rf(&rt2x00dev->chip, RF2527)) | ||
1215 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); | 1211 | rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); |
1216 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); | 1212 | rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); |
1217 | 1213 | ||
@@ -1827,16 +1823,16 @@ static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
1827 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); | 1823 | rt2x00_set_chip(rt2x00dev, RT2571, value, reg); |
1828 | rt2x00_print_chip(rt2x00dev); | 1824 | rt2x00_print_chip(rt2x00dev); |
1829 | 1825 | ||
1830 | if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || | 1826 | if (!rt2x00_check_rev(rt2x00dev, 0x000ffff0, 0x25730) || |
1831 | rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { | 1827 | rt2x00_check_rev(rt2x00dev, 0x0000000f, 0)) { |
1832 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); | 1828 | ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); |
1833 | return -ENODEV; | 1829 | return -ENODEV; |
1834 | } | 1830 | } |
1835 | 1831 | ||
1836 | if (!rt2x00_rf(&rt2x00dev->chip, RF5226) && | 1832 | if (!rt2x00_rf(rt2x00dev, RF5226) && |
1837 | !rt2x00_rf(&rt2x00dev->chip, RF2528) && | 1833 | !rt2x00_rf(rt2x00dev, RF2528) && |
1838 | !rt2x00_rf(&rt2x00dev->chip, RF5225) && | 1834 | !rt2x00_rf(rt2x00dev, RF5225) && |
1839 | !rt2x00_rf(&rt2x00dev->chip, RF2527)) { | 1835 | !rt2x00_rf(rt2x00dev, RF2527)) { |
1840 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 1836 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
1841 | return -ENODEV; | 1837 | return -ENODEV; |
1842 | } | 1838 | } |
@@ -2081,17 +2077,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
2081 | spec->supported_bands = SUPPORT_BAND_2GHZ; | 2077 | spec->supported_bands = SUPPORT_BAND_2GHZ; |
2082 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; | 2078 | spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; |
2083 | 2079 | ||
2084 | if (rt2x00_rf(&rt2x00dev->chip, RF2528)) { | 2080 | if (rt2x00_rf(rt2x00dev, RF2528)) { |
2085 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); | 2081 | spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); |
2086 | spec->channels = rf_vals_bg_2528; | 2082 | spec->channels = rf_vals_bg_2528; |
2087 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { | 2083 | } else if (rt2x00_rf(rt2x00dev, RF5226)) { |
2088 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2084 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2089 | spec->num_channels = ARRAY_SIZE(rf_vals_5226); | 2085 | spec->num_channels = ARRAY_SIZE(rf_vals_5226); |
2090 | spec->channels = rf_vals_5226; | 2086 | spec->channels = rf_vals_5226; |
2091 | } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { | 2087 | } else if (rt2x00_rf(rt2x00dev, RF2527)) { |
2092 | spec->num_channels = 14; | 2088 | spec->num_channels = 14; |
2093 | spec->channels = rf_vals_5225_2527; | 2089 | spec->channels = rf_vals_5225_2527; |
2094 | } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { | 2090 | } else if (rt2x00_rf(rt2x00dev, RF5225)) { |
2095 | spec->supported_bands |= SUPPORT_BAND_5GHZ; | 2091 | spec->supported_bands |= SUPPORT_BAND_5GHZ; |
2096 | spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); | 2092 | spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); |
2097 | spec->channels = rf_vals_5225_2527; | 2093 | spec->channels = rf_vals_5225_2527; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h index 8721282a8185..de3844fe06d8 100644 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ b/drivers/net/wireless/rtl818x/rtl8180.h | |||
@@ -60,7 +60,6 @@ struct rtl8180_priv { | |||
60 | struct rtl818x_csr __iomem *map; | 60 | struct rtl818x_csr __iomem *map; |
61 | const struct rtl818x_rf_ops *rf; | 61 | const struct rtl818x_rf_ops *rf; |
62 | struct ieee80211_vif *vif; | 62 | struct ieee80211_vif *vif; |
63 | int mode; | ||
64 | 63 | ||
65 | /* rtl8180 driver specific */ | 64 | /* rtl8180 driver specific */ |
66 | spinlock_t lock; | 65 | spinlock_t lock; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 8a40a1439984..5a2b7199f5d5 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -82,8 +82,6 @@ static const struct ieee80211_channel rtl818x_channels[] = { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | 84 | ||
85 | |||
86 | |||
87 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | 85 | void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) |
88 | { | 86 | { |
89 | struct rtl8180_priv *priv = dev->priv; | 87 | struct rtl8180_priv *priv = dev->priv; |
@@ -615,7 +613,6 @@ static int rtl8180_start(struct ieee80211_hw *dev) | |||
615 | reg |= RTL818X_CMD_TX_ENABLE; | 613 | reg |= RTL818X_CMD_TX_ENABLE; |
616 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); | 614 | rtl818x_iowrite8(priv, &priv->map->CMD, reg); |
617 | 615 | ||
618 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
619 | return 0; | 616 | return 0; |
620 | 617 | ||
621 | err_free_rings: | 618 | err_free_rings: |
@@ -633,8 +630,6 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
633 | u8 reg; | 630 | u8 reg; |
634 | int i; | 631 | int i; |
635 | 632 | ||
636 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | ||
637 | |||
638 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); | 633 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
639 | 634 | ||
640 | reg = rtl818x_ioread8(priv, &priv->map->CMD); | 635 | reg = rtl818x_ioread8(priv, &priv->map->CMD); |
@@ -657,38 +652,39 @@ static void rtl8180_stop(struct ieee80211_hw *dev) | |||
657 | } | 652 | } |
658 | 653 | ||
659 | static int rtl8180_add_interface(struct ieee80211_hw *dev, | 654 | static int rtl8180_add_interface(struct ieee80211_hw *dev, |
660 | struct ieee80211_if_init_conf *conf) | 655 | struct ieee80211_vif *vif) |
661 | { | 656 | { |
662 | struct rtl8180_priv *priv = dev->priv; | 657 | struct rtl8180_priv *priv = dev->priv; |
663 | 658 | ||
664 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 659 | /* |
665 | return -EOPNOTSUPP; | 660 | * We only support one active interface at a time. |
661 | */ | ||
662 | if (priv->vif) | ||
663 | return -EBUSY; | ||
666 | 664 | ||
667 | switch (conf->type) { | 665 | switch (vif->type) { |
668 | case NL80211_IFTYPE_STATION: | 666 | case NL80211_IFTYPE_STATION: |
669 | priv->mode = conf->type; | ||
670 | break; | 667 | break; |
671 | default: | 668 | default: |
672 | return -EOPNOTSUPP; | 669 | return -EOPNOTSUPP; |
673 | } | 670 | } |
674 | 671 | ||
675 | priv->vif = conf->vif; | 672 | priv->vif = vif; |
676 | 673 | ||
677 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 674 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
678 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], | 675 | rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], |
679 | le32_to_cpu(*(__le32 *)conf->mac_addr)); | 676 | le32_to_cpu(*(__le32 *)vif->addr)); |
680 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], | 677 | rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], |
681 | le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); | 678 | le16_to_cpu(*(__le16 *)(vif->addr + 4))); |
682 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 679 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
683 | 680 | ||
684 | return 0; | 681 | return 0; |
685 | } | 682 | } |
686 | 683 | ||
687 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, | 684 | static void rtl8180_remove_interface(struct ieee80211_hw *dev, |
688 | struct ieee80211_if_init_conf *conf) | 685 | struct ieee80211_vif *vif) |
689 | { | 686 | { |
690 | struct rtl8180_priv *priv = dev->priv; | 687 | struct rtl8180_priv *priv = dev->priv; |
691 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
692 | priv->vif = NULL; | 688 | priv->vif = NULL; |
693 | } | 689 | } |
694 | 690 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h index 6af0f3f71f3a..6bb32112e65c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ b/drivers/net/wireless/rtl818x/rtl8187.h | |||
@@ -92,7 +92,7 @@ struct rtl8187_priv { | |||
92 | struct rtl818x_csr *map; | 92 | struct rtl818x_csr *map; |
93 | const struct rtl818x_rf_ops *rf; | 93 | const struct rtl818x_rf_ops *rf; |
94 | struct ieee80211_vif *vif; | 94 | struct ieee80211_vif *vif; |
95 | int mode; | 95 | |
96 | /* The mutex protects the TX loopback state. | 96 | /* The mutex protects the TX loopback state. |
97 | * Any attempt to set channels concurrently locks the device. | 97 | * Any attempt to set channels concurrently locks the device. |
98 | */ | 98 | */ |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index bc5726dd5fe4..f336c63053c1 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1018,31 +1018,30 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | static int rtl8187_add_interface(struct ieee80211_hw *dev, | 1020 | static int rtl8187_add_interface(struct ieee80211_hw *dev, |
1021 | struct ieee80211_if_init_conf *conf) | 1021 | struct ieee80211_vif *vif) |
1022 | { | 1022 | { |
1023 | struct rtl8187_priv *priv = dev->priv; | 1023 | struct rtl8187_priv *priv = dev->priv; |
1024 | int i; | 1024 | int i; |
1025 | int ret = -EOPNOTSUPP; | 1025 | int ret = -EOPNOTSUPP; |
1026 | 1026 | ||
1027 | mutex_lock(&priv->conf_mutex); | 1027 | mutex_lock(&priv->conf_mutex); |
1028 | if (priv->mode != NL80211_IFTYPE_MONITOR) | 1028 | if (priv->vif) |
1029 | goto exit; | 1029 | goto exit; |
1030 | 1030 | ||
1031 | switch (conf->type) { | 1031 | switch (vif->type) { |
1032 | case NL80211_IFTYPE_STATION: | 1032 | case NL80211_IFTYPE_STATION: |
1033 | priv->mode = conf->type; | ||
1034 | break; | 1033 | break; |
1035 | default: | 1034 | default: |
1036 | goto exit; | 1035 | goto exit; |
1037 | } | 1036 | } |
1038 | 1037 | ||
1039 | ret = 0; | 1038 | ret = 0; |
1040 | priv->vif = conf->vif; | 1039 | priv->vif = vif; |
1041 | 1040 | ||
1042 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); | 1041 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); |
1043 | for (i = 0; i < ETH_ALEN; i++) | 1042 | for (i = 0; i < ETH_ALEN; i++) |
1044 | rtl818x_iowrite8(priv, &priv->map->MAC[i], | 1043 | rtl818x_iowrite8(priv, &priv->map->MAC[i], |
1045 | ((u8 *)conf->mac_addr)[i]); | 1044 | ((u8 *)vif->addr)[i]); |
1046 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 1045 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
1047 | 1046 | ||
1048 | exit: | 1047 | exit: |
@@ -1051,11 +1050,10 @@ exit: | |||
1051 | } | 1050 | } |
1052 | 1051 | ||
1053 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, | 1052 | static void rtl8187_remove_interface(struct ieee80211_hw *dev, |
1054 | struct ieee80211_if_init_conf *conf) | 1053 | struct ieee80211_vif *vif) |
1055 | { | 1054 | { |
1056 | struct rtl8187_priv *priv = dev->priv; | 1055 | struct rtl8187_priv *priv = dev->priv; |
1057 | mutex_lock(&priv->conf_mutex); | 1056 | mutex_lock(&priv->conf_mutex); |
1058 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1059 | priv->vif = NULL; | 1057 | priv->vif = NULL; |
1060 | mutex_unlock(&priv->conf_mutex); | 1058 | mutex_unlock(&priv->conf_mutex); |
1061 | } | 1059 | } |
@@ -1365,7 +1363,6 @@ static int __devinit rtl8187_probe(struct usb_interface *intf, | |||
1365 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; | 1363 | dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; |
1366 | 1364 | ||
1367 | 1365 | ||
1368 | priv->mode = NL80211_IFTYPE_MONITOR; | ||
1369 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | | 1366 | dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | |
1370 | IEEE80211_HW_SIGNAL_DBM | | 1367 | IEEE80211_HW_SIGNAL_DBM | |
1371 | IEEE80211_HW_RX_INCLUDES_FCS; | 1368 | IEEE80211_HW_RX_INCLUDES_FCS; |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c index ded44c045eb2..f82aa8b4bdde 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c | |||
@@ -33,7 +33,7 @@ static void led_turn_on(struct work_struct *work) | |||
33 | struct rtl8187_led *led = &priv->led_tx; | 33 | struct rtl8187_led *led = &priv->led_tx; |
34 | 34 | ||
35 | /* Don't change the LED, when the device is down. */ | 35 | /* Don't change the LED, when the device is down. */ |
36 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 36 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
37 | return ; | 37 | return ; |
38 | 38 | ||
39 | /* Skip if the LED is not registered. */ | 39 | /* Skip if the LED is not registered. */ |
@@ -71,7 +71,7 @@ static void led_turn_off(struct work_struct *work) | |||
71 | struct rtl8187_led *led = &priv->led_tx; | 71 | struct rtl8187_led *led = &priv->led_tx; |
72 | 72 | ||
73 | /* Don't change the LED, when the device is down. */ | 73 | /* Don't change the LED, when the device is down. */ |
74 | if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) | 74 | if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED) |
75 | return ; | 75 | return ; |
76 | 76 | ||
77 | /* Skip if the LED is not registered. */ | 77 | /* Skip if the LED is not registered. */ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 2e733e7bdfd4..28a808674080 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -256,7 +256,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
256 | } | 256 | } |
257 | } | 257 | } |
258 | 258 | ||
259 | if (loop >= INIT_LOOP) { | 259 | if (loop > INIT_LOOP) { |
260 | wl1251_error("timeout waiting for the hardware to " | 260 | wl1251_error("timeout waiting for the hardware to " |
261 | "complete initialization"); | 261 | "complete initialization"); |
262 | return -EIO; | 262 | return -EIO; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 6aeffbe9e401..4e373f3dbc43 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -511,13 +511,13 @@ static void wl1251_op_stop(struct ieee80211_hw *hw) | |||
511 | } | 511 | } |
512 | 512 | ||
513 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, | 513 | static int wl1251_op_add_interface(struct ieee80211_hw *hw, |
514 | struct ieee80211_if_init_conf *conf) | 514 | struct ieee80211_vif *vif) |
515 | { | 515 | { |
516 | struct wl1251 *wl = hw->priv; | 516 | struct wl1251 *wl = hw->priv; |
517 | int ret = 0; | 517 | int ret = 0; |
518 | 518 | ||
519 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 519 | wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
520 | conf->type, conf->mac_addr); | 520 | vif->type, vif->addr); |
521 | 521 | ||
522 | mutex_lock(&wl->mutex); | 522 | mutex_lock(&wl->mutex); |
523 | if (wl->vif) { | 523 | if (wl->vif) { |
@@ -525,9 +525,9 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
525 | goto out; | 525 | goto out; |
526 | } | 526 | } |
527 | 527 | ||
528 | wl->vif = conf->vif; | 528 | wl->vif = vif; |
529 | 529 | ||
530 | switch (conf->type) { | 530 | switch (vif->type) { |
531 | case NL80211_IFTYPE_STATION: | 531 | case NL80211_IFTYPE_STATION: |
532 | wl->bss_type = BSS_TYPE_STA_BSS; | 532 | wl->bss_type = BSS_TYPE_STA_BSS; |
533 | break; | 533 | break; |
@@ -539,8 +539,8 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
539 | goto out; | 539 | goto out; |
540 | } | 540 | } |
541 | 541 | ||
542 | if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { | 542 | if (memcmp(wl->mac_addr, vif->addr, ETH_ALEN)) { |
543 | memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); | 543 | memcpy(wl->mac_addr, vif->addr, ETH_ALEN); |
544 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); | 544 | SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); |
545 | ret = wl1251_acx_station_id(wl); | 545 | ret = wl1251_acx_station_id(wl); |
546 | if (ret < 0) | 546 | if (ret < 0) |
@@ -553,7 +553,7 @@ out: | |||
553 | } | 553 | } |
554 | 554 | ||
555 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | 555 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, |
556 | struct ieee80211_if_init_conf *conf) | 556 | struct ieee80211_vif *vif) |
557 | { | 557 | { |
558 | struct wl1251 *wl = hw->priv; | 558 | struct wl1251 *wl = hw->priv; |
559 | 559 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h index 94359b1a861f..d0938db043b3 100644 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ b/drivers/net/wireless/wl12xx/wl1271.h | |||
@@ -107,10 +107,9 @@ enum { | |||
107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ | 107 | CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ |
108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) | 108 | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) |
109 | 109 | ||
110 | #define WL1271_DEFAULT_BASIC_RATE_SET (CONF_TX_RATE_MASK_ALL) | ||
111 | |||
112 | #define WL1271_FW_NAME "wl1271-fw.bin" | 110 | #define WL1271_FW_NAME "wl1271-fw.bin" |
113 | #define WL1271_NVS_NAME "wl1271-nvs.bin" | 111 | #define WL1271_NVS_NAME "wl1271-nvs.bin" |
112 | #define WL1271_NVS_LEN 468 | ||
114 | 113 | ||
115 | /* | 114 | /* |
116 | * Enable/disable 802.11a support for WL1273 | 115 | * Enable/disable 802.11a support for WL1273 |
@@ -276,6 +275,7 @@ struct wl1271_debugfs { | |||
276 | 275 | ||
277 | struct dentry *retry_count; | 276 | struct dentry *retry_count; |
278 | struct dentry *excessive_retries; | 277 | struct dentry *excessive_retries; |
278 | struct dentry *gpio_power; | ||
279 | }; | 279 | }; |
280 | 280 | ||
281 | #define NUM_TX_QUEUES 4 | 281 | #define NUM_TX_QUEUES 4 |
@@ -322,6 +322,17 @@ struct wl1271 { | |||
322 | enum wl1271_state state; | 322 | enum wl1271_state state; |
323 | struct mutex mutex; | 323 | struct mutex mutex; |
324 | 324 | ||
325 | #define WL1271_FLAG_STA_RATES_CHANGED (0) | ||
326 | #define WL1271_FLAG_STA_ASSOCIATED (1) | ||
327 | #define WL1271_FLAG_JOINED (2) | ||
328 | #define WL1271_FLAG_GPIO_POWER (3) | ||
329 | #define WL1271_FLAG_TX_QUEUE_STOPPED (4) | ||
330 | #define WL1271_FLAG_SCANNING (5) | ||
331 | #define WL1271_FLAG_IN_ELP (6) | ||
332 | #define WL1271_FLAG_PSM (7) | ||
333 | #define WL1271_FLAG_PSM_REQUESTED (8) | ||
334 | unsigned long flags; | ||
335 | |||
325 | struct wl1271_partition_set part; | 336 | struct wl1271_partition_set part; |
326 | 337 | ||
327 | struct wl1271_chip chip; | 338 | struct wl1271_chip chip; |
@@ -359,7 +370,6 @@ struct wl1271 { | |||
359 | 370 | ||
360 | /* Frames scheduled for transmission, not handled yet */ | 371 | /* Frames scheduled for transmission, not handled yet */ |
361 | struct sk_buff_head tx_queue; | 372 | struct sk_buff_head tx_queue; |
362 | bool tx_queue_stopped; | ||
363 | 373 | ||
364 | struct work_struct tx_work; | 374 | struct work_struct tx_work; |
365 | 375 | ||
@@ -387,14 +397,15 @@ struct wl1271 { | |||
387 | u32 mbox_ptr[2]; | 397 | u32 mbox_ptr[2]; |
388 | 398 | ||
389 | /* Are we currently scanning */ | 399 | /* Are we currently scanning */ |
390 | bool scanning; | ||
391 | struct wl1271_scan scan; | 400 | struct wl1271_scan scan; |
392 | 401 | ||
393 | /* Our association ID */ | 402 | /* Our association ID */ |
394 | u16 aid; | 403 | u16 aid; |
395 | 404 | ||
396 | /* currently configured rate set */ | 405 | /* currently configured rate set */ |
406 | u32 sta_rate_set; | ||
397 | u32 basic_rate_set; | 407 | u32 basic_rate_set; |
408 | u32 rate_set; | ||
398 | 409 | ||
399 | /* The current band */ | 410 | /* The current band */ |
400 | enum ieee80211_band band; | 411 | enum ieee80211_band band; |
@@ -405,18 +416,9 @@ struct wl1271 { | |||
405 | unsigned int rx_config; | 416 | unsigned int rx_config; |
406 | unsigned int rx_filter; | 417 | unsigned int rx_filter; |
407 | 418 | ||
408 | /* is firmware in elp mode */ | ||
409 | bool elp; | ||
410 | |||
411 | struct completion *elp_compl; | 419 | struct completion *elp_compl; |
412 | struct delayed_work elp_work; | 420 | struct delayed_work elp_work; |
413 | 421 | ||
414 | /* we can be in psm, but not in elp, we have to differentiate */ | ||
415 | bool psm; | ||
416 | |||
417 | /* PSM mode requested */ | ||
418 | bool psm_requested; | ||
419 | |||
420 | /* retry counter for PSM entries */ | 422 | /* retry counter for PSM entries */ |
421 | u8 psm_entry_retry; | 423 | u8 psm_entry_retry; |
422 | 424 | ||
@@ -435,9 +437,6 @@ struct wl1271 { | |||
435 | 437 | ||
436 | struct ieee80211_vif *vif; | 438 | struct ieee80211_vif *vif; |
437 | 439 | ||
438 | /* Used for a workaround to send disconnect before rejoining */ | ||
439 | bool joined; | ||
440 | |||
441 | /* Current chipset configuration */ | 440 | /* Current chipset configuration */ |
442 | struct conf_drv_settings conf; | 441 | struct conf_drv_settings conf; |
443 | 442 | ||
@@ -455,7 +454,9 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
455 | 454 | ||
456 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 | 455 | #define WL1271_TX_QUEUE_MAX_LENGTH 20 |
457 | 456 | ||
458 | /* WL1271 needs a 200ms sleep after power on */ | 457 | /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power |
458 | on in case is has been shut down shortly before */ | ||
459 | #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */ | ||
459 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ | 460 | #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ |
460 | 461 | ||
461 | static inline bool wl1271_11a_enabled(void) | 462 | static inline bool wl1271_11a_enabled(void) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index 5cc89bbdac7a..0b3434843476 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -390,6 +390,35 @@ out: | |||
390 | return ret; | 390 | return ret; |
391 | } | 391 | } |
392 | 392 | ||
393 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl) | ||
394 | { | ||
395 | struct acx_dco_itrim_params *dco; | ||
396 | struct conf_itrim_settings *c = &wl->conf.itrim; | ||
397 | int ret; | ||
398 | |||
399 | wl1271_debug(DEBUG_ACX, "acx dco itrim parameters"); | ||
400 | |||
401 | dco = kzalloc(sizeof(*dco), GFP_KERNEL); | ||
402 | if (!dco) { | ||
403 | ret = -ENOMEM; | ||
404 | goto out; | ||
405 | } | ||
406 | |||
407 | dco->enable = c->enable; | ||
408 | dco->timeout = cpu_to_le32(c->timeout); | ||
409 | |||
410 | ret = wl1271_cmd_configure(wl, ACX_SET_DCO_ITRIM_PARAMS, | ||
411 | dco, sizeof(*dco)); | ||
412 | if (ret < 0) { | ||
413 | wl1271_warning("failed to set dco itrim parameters: %d", ret); | ||
414 | goto out; | ||
415 | } | ||
416 | |||
417 | out: | ||
418 | kfree(dco); | ||
419 | return ret; | ||
420 | } | ||
421 | |||
393 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) | 422 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter) |
394 | { | 423 | { |
395 | struct acx_beacon_filter_option *beacon_filter = NULL; | 424 | struct acx_beacon_filter_option *beacon_filter = NULL; |
@@ -758,10 +787,11 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) | |||
758 | return 0; | 787 | return 0; |
759 | } | 788 | } |
760 | 789 | ||
761 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | 790 | int wl1271_acx_rate_policies(struct wl1271 *wl) |
762 | { | 791 | { |
763 | struct acx_rate_policy *acx; | 792 | struct acx_rate_policy *acx; |
764 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; | 793 | struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf; |
794 | int idx = 0; | ||
765 | int ret = 0; | 795 | int ret = 0; |
766 | 796 | ||
767 | wl1271_debug(DEBUG_ACX, "acx rate policies"); | 797 | wl1271_debug(DEBUG_ACX, "acx rate policies"); |
@@ -773,12 +803,21 @@ int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates) | |||
773 | goto out; | 803 | goto out; |
774 | } | 804 | } |
775 | 805 | ||
776 | /* configure one default (one-size-fits-all) rate class */ | 806 | /* configure one basic rate class */ |
777 | acx->rate_class_cnt = cpu_to_le32(1); | 807 | idx = ACX_TX_BASIC_RATE; |
778 | acx->rate_class[0].enabled_rates = cpu_to_le32(enabled_rates); | 808 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); |
779 | acx->rate_class[0].short_retry_limit = c->short_retry_limit; | 809 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; |
780 | acx->rate_class[0].long_retry_limit = c->long_retry_limit; | 810 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; |
781 | acx->rate_class[0].aflags = c->aflags; | 811 | acx->rate_class[idx].aflags = c->aflags; |
812 | |||
813 | /* configure one AP supported rate class */ | ||
814 | idx = ACX_TX_AP_FULL_RATE; | ||
815 | acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set); | ||
816 | acx->rate_class[idx].short_retry_limit = c->short_retry_limit; | ||
817 | acx->rate_class[idx].long_retry_limit = c->long_retry_limit; | ||
818 | acx->rate_class[idx].aflags = c->aflags; | ||
819 | |||
820 | acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT); | ||
782 | 821 | ||
783 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); | 822 | ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); |
784 | if (ret < 0) { | 823 | if (ret < 0) { |
@@ -1012,59 +1051,6 @@ out: | |||
1012 | return ret; | 1051 | return ret; |
1013 | } | 1052 | } |
1014 | 1053 | ||
1015 | int wl1271_acx_smart_reflex(struct wl1271 *wl) | ||
1016 | { | ||
1017 | struct acx_smart_reflex_state *sr_state = NULL; | ||
1018 | struct acx_smart_reflex_config_params *sr_param = NULL; | ||
1019 | int i, ret; | ||
1020 | |||
1021 | wl1271_debug(DEBUG_ACX, "acx smart reflex"); | ||
1022 | |||
1023 | sr_param = kzalloc(sizeof(*sr_param), GFP_KERNEL); | ||
1024 | if (!sr_param) { | ||
1025 | ret = -ENOMEM; | ||
1026 | goto out; | ||
1027 | } | ||
1028 | |||
1029 | for (i = 0; i < CONF_SR_ERR_TBL_COUNT; i++) { | ||
1030 | struct conf_mart_reflex_err_table *e = | ||
1031 | &(wl->conf.init.sr_err_tbl[i]); | ||
1032 | |||
1033 | sr_param->error_table[i].len = e->len; | ||
1034 | sr_param->error_table[i].upper_limit = e->upper_limit; | ||
1035 | memcpy(sr_param->error_table[i].values, e->values, e->len); | ||
1036 | } | ||
1037 | |||
1038 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_PARAMS, | ||
1039 | sr_param, sizeof(*sr_param)); | ||
1040 | if (ret < 0) { | ||
1041 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1042 | goto out; | ||
1043 | } | ||
1044 | |||
1045 | sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); | ||
1046 | if (!sr_state) { | ||
1047 | ret = -ENOMEM; | ||
1048 | goto out; | ||
1049 | } | ||
1050 | |||
1051 | /* enable smart reflex */ | ||
1052 | sr_state->enable = wl->conf.init.sr_enable; | ||
1053 | |||
1054 | ret = wl1271_cmd_configure(wl, ACX_SET_SMART_REFLEX_STATE, | ||
1055 | sr_state, sizeof(*sr_state)); | ||
1056 | if (ret < 0) { | ||
1057 | wl1271_warning("failed to set smart reflex params: %d", ret); | ||
1058 | goto out; | ||
1059 | } | ||
1060 | |||
1061 | out: | ||
1062 | kfree(sr_state); | ||
1063 | kfree(sr_param); | ||
1064 | return ret; | ||
1065 | |||
1066 | } | ||
1067 | |||
1068 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) | 1054 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable) |
1069 | { | 1055 | { |
1070 | struct wl1271_acx_bet_enable *acx = NULL; | 1056 | struct wl1271_acx_bet_enable *acx = NULL; |
@@ -1132,3 +1118,31 @@ out: | |||
1132 | kfree(acx); | 1118 | kfree(acx); |
1133 | return ret; | 1119 | return ret; |
1134 | } | 1120 | } |
1121 | |||
1122 | int wl1271_acx_pm_config(struct wl1271 *wl) | ||
1123 | { | ||
1124 | struct wl1271_acx_pm_config *acx = NULL; | ||
1125 | struct conf_pm_config_settings *c = &wl->conf.pm_config; | ||
1126 | int ret = 0; | ||
1127 | |||
1128 | wl1271_debug(DEBUG_ACX, "acx pm config"); | ||
1129 | |||
1130 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1131 | if (!acx) { | ||
1132 | ret = -ENOMEM; | ||
1133 | goto out; | ||
1134 | } | ||
1135 | |||
1136 | acx->host_clk_settling_time = cpu_to_le32(c->host_clk_settling_time); | ||
1137 | acx->host_fast_wakeup_support = c->host_fast_wakeup_support; | ||
1138 | |||
1139 | ret = wl1271_cmd_configure(wl, ACX_PM_CONFIG, acx, sizeof(*acx)); | ||
1140 | if (ret < 0) { | ||
1141 | wl1271_warning("acx pm config failed: %d", ret); | ||
1142 | goto out; | ||
1143 | } | ||
1144 | |||
1145 | out: | ||
1146 | kfree(acx); | ||
1147 | return ret; | ||
1148 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h index 2ce0a8128542..1bb63af64f0e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ b/drivers/net/wireless/wl12xx/wl1271_acx.h | |||
@@ -415,23 +415,12 @@ struct acx_bt_wlan_coex { | |||
415 | u8 pad[3]; | 415 | u8 pad[3]; |
416 | } __attribute__ ((packed)); | 416 | } __attribute__ ((packed)); |
417 | 417 | ||
418 | struct acx_smart_reflex_state { | 418 | struct acx_dco_itrim_params { |
419 | struct acx_header header; | 419 | struct acx_header header; |
420 | 420 | ||
421 | u8 enable; | 421 | u8 enable; |
422 | u8 padding[3]; | 422 | u8 padding[3]; |
423 | } __attribute__ ((packed)); | 423 | __le32 timeout; |
424 | |||
425 | struct smart_reflex_err_table { | ||
426 | u8 len; | ||
427 | s8 upper_limit; | ||
428 | s8 values[14]; | ||
429 | } __attribute__ ((packed)); | ||
430 | |||
431 | struct acx_smart_reflex_config_params { | ||
432 | struct acx_header header; | ||
433 | |||
434 | struct smart_reflex_err_table error_table[3]; | ||
435 | } __attribute__ ((packed)); | 424 | } __attribute__ ((packed)); |
436 | 425 | ||
437 | #define PTA_ANTENNA_TYPE_DEF (0) | 426 | #define PTA_ANTENNA_TYPE_DEF (0) |
@@ -837,6 +826,9 @@ struct acx_rate_class { | |||
837 | u8 reserved; | 826 | u8 reserved; |
838 | }; | 827 | }; |
839 | 828 | ||
829 | #define ACX_TX_BASIC_RATE 0 | ||
830 | #define ACX_TX_AP_FULL_RATE 1 | ||
831 | #define ACX_TX_RATE_POLICY_CNT 2 | ||
840 | struct acx_rate_policy { | 832 | struct acx_rate_policy { |
841 | struct acx_header header; | 833 | struct acx_header header; |
842 | 834 | ||
@@ -877,8 +869,8 @@ struct acx_tx_config_options { | |||
877 | __le16 tx_compl_threshold; /* number of packets */ | 869 | __le16 tx_compl_threshold; /* number of packets */ |
878 | } __attribute__ ((packed)); | 870 | } __attribute__ ((packed)); |
879 | 871 | ||
880 | #define ACX_RX_MEM_BLOCKS 64 | 872 | #define ACX_RX_MEM_BLOCKS 70 |
881 | #define ACX_TX_MIN_MEM_BLOCKS 64 | 873 | #define ACX_TX_MIN_MEM_BLOCKS 40 |
882 | #define ACX_TX_DESCRIPTORS 32 | 874 | #define ACX_TX_DESCRIPTORS 32 |
883 | #define ACX_NUM_SSID_PROFILES 1 | 875 | #define ACX_NUM_SSID_PROFILES 1 |
884 | 876 | ||
@@ -969,6 +961,13 @@ struct wl1271_acx_arp_filter { | |||
969 | used. */ | 961 | used. */ |
970 | } __attribute__((packed)); | 962 | } __attribute__((packed)); |
971 | 963 | ||
964 | struct wl1271_acx_pm_config { | ||
965 | struct acx_header header; | ||
966 | |||
967 | __le32 host_clk_settling_time; | ||
968 | u8 host_fast_wakeup_support; | ||
969 | u8 padding[3]; | ||
970 | } __attribute__ ((packed)); | ||
972 | 971 | ||
973 | enum { | 972 | enum { |
974 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 973 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
@@ -1027,13 +1026,13 @@ enum { | |||
1027 | ACX_HT_BSS_OPERATION = 0x0058, | 1026 | ACX_HT_BSS_OPERATION = 0x0058, |
1028 | ACX_COEX_ACTIVITY = 0x0059, | 1027 | ACX_COEX_ACTIVITY = 0x0059, |
1029 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, | 1028 | ACX_SET_SMART_REFLEX_DEBUG = 0x005A, |
1030 | ACX_SET_SMART_REFLEX_STATE = 0x005B, | 1029 | ACX_SET_DCO_ITRIM_PARAMS = 0x0061, |
1031 | ACX_SET_SMART_REFLEX_PARAMS = 0x005F, | ||
1032 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, | 1030 | DOT11_RX_MSDU_LIFE_TIME = 0x1004, |
1033 | DOT11_CUR_TX_PWR = 0x100D, | 1031 | DOT11_CUR_TX_PWR = 0x100D, |
1034 | DOT11_RX_DOT11_MODE = 0x1012, | 1032 | DOT11_RX_DOT11_MODE = 0x1012, |
1035 | DOT11_RTS_THRESHOLD = 0x1013, | 1033 | DOT11_RTS_THRESHOLD = 0x1013, |
1036 | DOT11_GROUP_ADDRESS_TBL = 0x1014, | 1034 | DOT11_GROUP_ADDRESS_TBL = 0x1014, |
1035 | ACX_PM_CONFIG = 0x1016, | ||
1037 | 1036 | ||
1038 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, | 1037 | MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, |
1039 | 1038 | ||
@@ -1056,6 +1055,7 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, | |||
1056 | void *mc_list, u32 mc_list_len); | 1055 | void *mc_list, u32 mc_list_len); |
1057 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1056 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1058 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1057 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); |
1058 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | ||
1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1059 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1060 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); | 1061 | int wl1271_acx_conn_monit_params(struct wl1271 *wl); |
@@ -1069,7 +1069,7 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); | |||
1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, | 1069 | int wl1271_acx_cts_protect(struct wl1271 *wl, |
1070 | enum acx_ctsprotect_type ctsprotect); | 1070 | enum acx_ctsprotect_type ctsprotect); |
1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); | 1071 | int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); |
1072 | int wl1271_acx_rate_policies(struct wl1271 *wl, u32 enabled_rates); | 1072 | int wl1271_acx_rate_policies(struct wl1271 *wl); |
1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); | 1073 | int wl1271_acx_ac_cfg(struct wl1271 *wl); |
1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); | 1074 | int wl1271_acx_tid_cfg(struct wl1271 *wl); |
1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); | 1075 | int wl1271_acx_frag_threshold(struct wl1271 *wl); |
@@ -1081,5 +1081,6 @@ int wl1271_acx_smart_reflex(struct wl1271 *wl); | |||
1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); | 1081 | int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable); |
1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, | 1082 | int wl1271_acx_arp_ip_filter(struct wl1271 *wl, bool enable, u8 *address, |
1083 | u8 version); | 1083 | u8 version); |
1084 | int wl1271_acx_pm_config(struct wl1271 *wl); | ||
1084 | 1085 | ||
1085 | #endif /* __WL1271_ACX_H__ */ | 1086 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c index b7c96454cca3..e803b876f3f0 100644 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c | |||
@@ -225,9 +225,15 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl) | |||
225 | if (nvs == NULL) | 225 | if (nvs == NULL) |
226 | return -ENODEV; | 226 | return -ENODEV; |
227 | 227 | ||
228 | if (wl->nvs_len < WL1271_NVS_LEN) | ||
229 | return -EINVAL; | ||
230 | |||
228 | nvs_ptr = nvs; | 231 | nvs_ptr = nvs; |
229 | 232 | ||
230 | nvs_len = wl->nvs_len; | 233 | /* only the first part of the NVS needs to be uploaded */ |
234 | nvs_len = WL1271_NVS_LEN; | ||
235 | |||
236 | /* FIXME: read init settings from the remaining part of the NVS */ | ||
231 | 237 | ||
232 | /* Update the device MAC address into the nvs */ | 238 | /* Update the device MAC address into the nvs */ |
233 | nvs[11] = wl->mac_addr[0]; | 239 | nvs[11] = wl->mac_addr[0]; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c index 886a9bc39cc1..a74259bb596b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c | |||
@@ -209,6 +209,26 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; | 209 | gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer; |
210 | gen_parms->settings = g->settings; | 210 | gen_parms->settings = g->settings; |
211 | 211 | ||
212 | gen_parms->sr_state = g->sr_state; | ||
213 | |||
214 | memcpy(gen_parms->srf1, | ||
215 | g->srf1, | ||
216 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
217 | memcpy(gen_parms->srf2, | ||
218 | g->srf2, | ||
219 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
220 | memcpy(gen_parms->srf3, | ||
221 | g->srf3, | ||
222 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
223 | memcpy(gen_parms->sr_debug_table, | ||
224 | g->sr_debug_table, | ||
225 | CONF_MAX_SMART_REFLEX_PARAMS); | ||
226 | |||
227 | gen_parms->sr_sen_n_p = g->sr_sen_n_p; | ||
228 | gen_parms->sr_sen_n_p_gain = g->sr_sen_n_p_gain; | ||
229 | gen_parms->sr_sen_nrn = g->sr_sen_nrn; | ||
230 | gen_parms->sr_sen_prn = g->sr_sen_prn; | ||
231 | |||
212 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); | 232 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); |
213 | if (ret < 0) | 233 | if (ret < 0) |
214 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 234 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -253,6 +273,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
253 | CONF_NUMBER_OF_RATE_GROUPS); | 273 | CONF_NUMBER_OF_RATE_GROUPS); |
254 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, | 274 | memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded, |
255 | CONF_NUMBER_OF_RATE_GROUPS); | 275 | CONF_NUMBER_OF_RATE_GROUPS); |
276 | memcpy(radio_parms->tx_rate_limits_extreme, r->tx_rate_limits_extreme, | ||
277 | CONF_NUMBER_OF_RATE_GROUPS); | ||
256 | 278 | ||
257 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, | 279 | memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b, |
258 | CONF_NUMBER_OF_CHANNELS_2_4); | 280 | CONF_NUMBER_OF_CHANNELS_2_4); |
@@ -263,6 +285,11 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
263 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); | 285 | memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS); |
264 | 286 | ||
265 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; | 287 | radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss; |
288 | radio_parms->degraded_low_to_normal_threshold = | ||
289 | r->degraded_low_to_normal_threshold; | ||
290 | radio_parms->degraded_normal_to_high_threshold = | ||
291 | r->degraded_normal_to_high_threshold; | ||
292 | |||
266 | 293 | ||
267 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) | 294 | for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++) |
268 | radio_parms->tx_ref_pd_voltage_5[i] = | 295 | radio_parms->tx_ref_pd_voltage_5[i] = |
@@ -275,6 +302,8 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
275 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); | 302 | r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS); |
276 | memcpy(radio_parms->tx_rate_limits_degraded_5, | 303 | memcpy(radio_parms->tx_rate_limits_degraded_5, |
277 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); | 304 | r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS); |
305 | memcpy(radio_parms->tx_rate_limits_extreme_5, | ||
306 | r->tx_rate_limits_extreme_5, CONF_NUMBER_OF_RATE_GROUPS); | ||
278 | memcpy(radio_parms->tx_channel_limits_ofdm_5, | 307 | memcpy(radio_parms->tx_channel_limits_ofdm_5, |
279 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); | 308 | r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5); |
280 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, | 309 | memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5, |
@@ -283,6 +312,10 @@ int wl1271_cmd_radio_parms(struct wl1271 *wl) | |||
283 | CONF_NUMBER_OF_RATE_GROUPS); | 312 | CONF_NUMBER_OF_RATE_GROUPS); |
284 | memcpy(radio_parms->rx_fem_insertion_loss_5, | 313 | memcpy(radio_parms->rx_fem_insertion_loss_5, |
285 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); | 314 | r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5); |
315 | radio_parms->degraded_low_to_normal_threshold_5 = | ||
316 | r->degraded_low_to_normal_threshold_5; | ||
317 | radio_parms->degraded_normal_to_high_threshold_5 = | ||
318 | r->degraded_normal_to_high_threshold_5; | ||
286 | 319 | ||
287 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", | 320 | wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ", |
288 | radio_parms, sizeof(*radio_parms)); | 321 | radio_parms, sizeof(*radio_parms)); |
@@ -311,19 +344,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
311 | do_cal = false; | 344 | do_cal = false; |
312 | } | 345 | } |
313 | 346 | ||
314 | /* FIXME: This is a workaround, because with the current stack, we | ||
315 | * cannot know when we have disassociated. So, if we have already | ||
316 | * joined, we disconnect before joining again. */ | ||
317 | if (wl->joined) { | ||
318 | ret = wl1271_cmd_disconnect(wl); | ||
319 | if (ret < 0) { | ||
320 | wl1271_error("failed to disconnect before rejoining"); | ||
321 | goto out; | ||
322 | } | ||
323 | |||
324 | wl->joined = false; | ||
325 | } | ||
326 | |||
327 | join = kzalloc(sizeof(*join), GFP_KERNEL); | 347 | join = kzalloc(sizeof(*join), GFP_KERNEL); |
328 | if (!join) { | 348 | if (!join) { |
329 | ret = -ENOMEM; | 349 | ret = -ENOMEM; |
@@ -388,8 +408,6 @@ int wl1271_cmd_join(struct wl1271 *wl) | |||
388 | goto out_free; | 408 | goto out_free; |
389 | } | 409 | } |
390 | 410 | ||
391 | wl->joined = true; | ||
392 | |||
393 | /* | 411 | /* |
394 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to | 412 | * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to |
395 | * simplify locking we just sleep instead, for now | 413 | * simplify locking we just sleep instead, for now |
@@ -487,7 +505,7 @@ int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) | |||
487 | return 0; | 505 | return 0; |
488 | } | 506 | } |
489 | 507 | ||
490 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | 508 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable) |
491 | { | 509 | { |
492 | struct cmd_enabledisable_path *cmd; | 510 | struct cmd_enabledisable_path *cmd; |
493 | int ret; | 511 | int ret; |
@@ -501,7 +519,8 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
501 | goto out; | 519 | goto out; |
502 | } | 520 | } |
503 | 521 | ||
504 | cmd->channel = channel; | 522 | /* the channel here is only used for calibration, so hardcoded to 1 */ |
523 | cmd->channel = 1; | ||
505 | 524 | ||
506 | if (enable) { | 525 | if (enable) { |
507 | cmd_rx = CMD_ENABLE_RX; | 526 | cmd_rx = CMD_ENABLE_RX; |
@@ -514,22 +533,22 @@ int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) | |||
514 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); | 533 | ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd), 0); |
515 | if (ret < 0) { | 534 | if (ret < 0) { |
516 | wl1271_error("rx %s cmd for channel %d failed", | 535 | wl1271_error("rx %s cmd for channel %d failed", |
517 | enable ? "start" : "stop", channel); | 536 | enable ? "start" : "stop", cmd->channel); |
518 | goto out; | 537 | goto out; |
519 | } | 538 | } |
520 | 539 | ||
521 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", | 540 | wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", |
522 | enable ? "start" : "stop", channel); | 541 | enable ? "start" : "stop", cmd->channel); |
523 | 542 | ||
524 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); | 543 | ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd), 0); |
525 | if (ret < 0) { | 544 | if (ret < 0) { |
526 | wl1271_error("tx %s cmd for channel %d failed", | 545 | wl1271_error("tx %s cmd for channel %d failed", |
527 | enable ? "start" : "stop", channel); | 546 | enable ? "start" : "stop", cmd->channel); |
528 | return ret; | 547 | return ret; |
529 | } | 548 | } |
530 | 549 | ||
531 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", | 550 | wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", |
532 | enable ? "start" : "stop", channel); | 551 | enable ? "start" : "stop", cmd->channel); |
533 | 552 | ||
534 | out: | 553 | out: |
535 | kfree(cmd); | 554 | kfree(cmd); |
@@ -636,7 +655,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
636 | channels = wl->hw->wiphy->bands[ieee_band]->channels; | 655 | channels = wl->hw->wiphy->bands[ieee_band]->channels; |
637 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; | 656 | n_ch = wl->hw->wiphy->bands[ieee_band]->n_channels; |
638 | 657 | ||
639 | if (wl->scanning) | 658 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) |
640 | return -EINVAL; | 659 | return -EINVAL; |
641 | 660 | ||
642 | params = kzalloc(sizeof(*params), GFP_KERNEL); | 661 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
@@ -711,7 +730,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
711 | 730 | ||
712 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); | 731 | wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); |
713 | 732 | ||
714 | wl->scanning = true; | 733 | set_bit(WL1271_FLAG_SCANNING, &wl->flags); |
715 | if (wl1271_11a_enabled()) { | 734 | if (wl1271_11a_enabled()) { |
716 | wl->scan.state = band; | 735 | wl->scan.state = band; |
717 | if (band == WL1271_SCAN_BAND_DUAL) { | 736 | if (band == WL1271_SCAN_BAND_DUAL) { |
@@ -729,7 +748,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, | |||
729 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); | 748 | ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params), 0); |
730 | if (ret < 0) { | 749 | if (ret < 0) { |
731 | wl1271_error("SCAN failed"); | 750 | wl1271_error("SCAN failed"); |
732 | wl->scanning = false; | 751 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
733 | goto out; | 752 | goto out; |
734 | } | 753 | } |
735 | 754 | ||
@@ -777,7 +796,7 @@ out: | |||
777 | return ret; | 796 | return ret; |
778 | } | 797 | } |
779 | 798 | ||
780 | static int wl1271_build_basic_rates(char *rates, u8 band) | 799 | static int wl1271_build_basic_rates(u8 *rates, u8 band) |
781 | { | 800 | { |
782 | u8 index = 0; | 801 | u8 index = 0; |
783 | 802 | ||
@@ -804,7 +823,7 @@ static int wl1271_build_basic_rates(char *rates, u8 band) | |||
804 | return index; | 823 | return index; |
805 | } | 824 | } |
806 | 825 | ||
807 | static int wl1271_build_extended_rates(char *rates, u8 band) | 826 | static int wl1271_build_extended_rates(u8 *rates, u8 band) |
808 | { | 827 | { |
809 | u8 index = 0; | 828 | u8 index = 0; |
810 | 829 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h index b4fa4acb9229..09fe91297acf 100644 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h | |||
@@ -37,7 +37,7 @@ int wl1271_cmd_join(struct wl1271 *wl); | |||
37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); | 37 | int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); |
38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); | 38 | int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); |
39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); | 39 | int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); |
40 | int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable); | 40 | int wl1271_cmd_data_path(struct wl1271 *wl, bool enable); |
41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); | 41 | int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); |
42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, | 42 | int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, |
43 | size_t len); | 43 | size_t len); |
@@ -437,6 +437,21 @@ struct wl1271_general_parms_cmd { | |||
437 | u8 tx_bip_fem_autodetect; | 437 | u8 tx_bip_fem_autodetect; |
438 | u8 tx_bip_fem_manufacturer; | 438 | u8 tx_bip_fem_manufacturer; |
439 | u8 settings; | 439 | u8 settings; |
440 | |||
441 | u8 sr_state; | ||
442 | |||
443 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
444 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
445 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
446 | |||
447 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
448 | |||
449 | u8 sr_sen_n_p; | ||
450 | u8 sr_sen_n_p_gain; | ||
451 | u8 sr_sen_nrn; | ||
452 | u8 sr_sen_prn; | ||
453 | |||
454 | u8 padding[3]; | ||
440 | } __attribute__ ((packed)); | 455 | } __attribute__ ((packed)); |
441 | 456 | ||
442 | struct wl1271_radio_parms_cmd { | 457 | struct wl1271_radio_parms_cmd { |
@@ -458,11 +473,12 @@ struct wl1271_radio_parms_cmd { | |||
458 | /* Dynamic radio parameters */ | 473 | /* Dynamic radio parameters */ |
459 | /* 2.4GHz */ | 474 | /* 2.4GHz */ |
460 | __le16 tx_ref_pd_voltage; | 475 | __le16 tx_ref_pd_voltage; |
461 | s8 tx_ref_power; | 476 | u8 tx_ref_power; |
462 | s8 tx_offset_db; | 477 | s8 tx_offset_db; |
463 | 478 | ||
464 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | 479 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
465 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | 480 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
481 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
466 | 482 | ||
467 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 483 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
468 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 484 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
@@ -471,15 +487,19 @@ struct wl1271_radio_parms_cmd { | |||
471 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | 487 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
472 | u8 rx_fem_insertion_loss; | 488 | u8 rx_fem_insertion_loss; |
473 | 489 | ||
474 | u8 padding2; | 490 | u8 degraded_low_to_normal_threshold; |
491 | u8 degraded_normal_to_high_threshold; | ||
492 | |||
493 | u8 padding1; /* our own padding, not in ref driver */ | ||
475 | 494 | ||
476 | /* 5GHz */ | 495 | /* 5GHz */ |
477 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 496 | __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
478 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 497 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
479 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 498 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
480 | 499 | ||
481 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | 500 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
482 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | 501 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
502 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
483 | 503 | ||
484 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | 504 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
485 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | 505 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
@@ -488,7 +508,10 @@ struct wl1271_radio_parms_cmd { | |||
488 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | 508 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
489 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 509 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
490 | 510 | ||
491 | u8 padding3[2]; | 511 | u8 degraded_low_to_normal_threshold_5; |
512 | u8 degraded_normal_to_high_threshold_5; | ||
513 | |||
514 | u8 padding2[2]; | ||
492 | } __attribute__ ((packed)); | 515 | } __attribute__ ((packed)); |
493 | 516 | ||
494 | struct wl1271_cmd_cal_channel_tune { | 517 | struct wl1271_cmd_cal_channel_tune { |
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h index 565373ede265..1993d63c214e 100644 --- a/drivers/net/wireless/wl12xx/wl1271_conf.h +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h | |||
@@ -258,7 +258,8 @@ struct conf_rx_settings { | |||
258 | #define CONF_TX_MAX_RATE_CLASSES 8 | 258 | #define CONF_TX_MAX_RATE_CLASSES 8 |
259 | 259 | ||
260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 | 260 | #define CONF_TX_RATE_MASK_UNSPECIFIED 0 |
261 | #define CONF_TX_RATE_MASK_ALL 0x1eff | 261 | #define CONF_TX_RATE_MASK_BASIC (CONF_HW_BIT_RATE_1MBPS | \ |
262 | CONF_HW_BIT_RATE_2MBPS) | ||
262 | #define CONF_TX_RATE_RETRY_LIMIT 10 | 263 | #define CONF_TX_RATE_RETRY_LIMIT 10 |
263 | 264 | ||
264 | struct conf_tx_rate_class { | 265 | struct conf_tx_rate_class { |
@@ -722,31 +723,6 @@ struct conf_conn_settings { | |||
722 | u8 psm_entry_retries; | 723 | u8 psm_entry_retries; |
723 | }; | 724 | }; |
724 | 725 | ||
725 | #define CONF_SR_ERR_TBL_MAX_VALUES 14 | ||
726 | |||
727 | struct conf_mart_reflex_err_table { | ||
728 | /* | ||
729 | * Length of the error table values table. | ||
730 | * | ||
731 | * Range: 0 - CONF_SR_ERR_TBL_MAX_VALUES | ||
732 | */ | ||
733 | u8 len; | ||
734 | |||
735 | /* | ||
736 | * Smart Reflex error table upper limit. | ||
737 | * | ||
738 | * Range: s8 | ||
739 | */ | ||
740 | s8 upper_limit; | ||
741 | |||
742 | /* | ||
743 | * Smart Reflex error table values. | ||
744 | * | ||
745 | * Range: s8 | ||
746 | */ | ||
747 | s8 values[CONF_SR_ERR_TBL_MAX_VALUES]; | ||
748 | }; | ||
749 | |||
750 | enum { | 726 | enum { |
751 | CONF_REF_CLK_19_2_E, | 727 | CONF_REF_CLK_19_2_E, |
752 | CONF_REF_CLK_26_E, | 728 | CONF_REF_CLK_26_E, |
@@ -759,6 +735,9 @@ enum single_dual_band_enum { | |||
759 | CONF_DUAL_BAND | 735 | CONF_DUAL_BAND |
760 | }; | 736 | }; |
761 | 737 | ||
738 | |||
739 | #define CONF_MAX_SMART_REFLEX_PARAMS 16 | ||
740 | |||
762 | struct conf_general_parms { | 741 | struct conf_general_parms { |
763 | /* | 742 | /* |
764 | * RF Reference Clock type / speed | 743 | * RF Reference Clock type / speed |
@@ -815,6 +794,20 @@ struct conf_general_parms { | |||
815 | * Range: Unknown | 794 | * Range: Unknown |
816 | */ | 795 | */ |
817 | u8 settings; | 796 | u8 settings; |
797 | |||
798 | /* Smart reflex settings */ | ||
799 | u8 sr_state; | ||
800 | |||
801 | s8 srf1[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
802 | s8 srf2[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
803 | s8 srf3[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
804 | |||
805 | s8 sr_debug_table[CONF_MAX_SMART_REFLEX_PARAMS]; | ||
806 | |||
807 | u8 sr_sen_n_p; | ||
808 | u8 sr_sen_n_p_gain; | ||
809 | u8 sr_sen_nrn; | ||
810 | u8 sr_sen_prn; | ||
818 | }; | 811 | }; |
819 | 812 | ||
820 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 | 813 | #define CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE 15 |
@@ -847,12 +840,13 @@ struct conf_radio_parms { | |||
847 | * | 840 | * |
848 | * Range: unknown | 841 | * Range: unknown |
849 | */ | 842 | */ |
850 | s16 tx_ref_pd_voltage; | 843 | u16 tx_ref_pd_voltage; |
851 | s8 tx_ref_power; | 844 | u8 tx_ref_power; |
852 | s8 tx_offset_db; | 845 | s8 tx_offset_db; |
853 | 846 | ||
854 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; | 847 | s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS]; |
855 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; | 848 | s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS]; |
849 | s8 tx_rate_limits_extreme[CONF_NUMBER_OF_RATE_GROUPS]; | ||
856 | 850 | ||
857 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; | 851 | s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4]; |
858 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; | 852 | s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4]; |
@@ -861,17 +855,22 @@ struct conf_radio_parms { | |||
861 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; | 855 | u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS]; |
862 | u8 rx_fem_insertion_loss; | 856 | u8 rx_fem_insertion_loss; |
863 | 857 | ||
858 | u8 degraded_low_to_normal_threshold; | ||
859 | u8 degraded_normal_to_high_threshold; | ||
860 | |||
861 | |||
864 | /* | 862 | /* |
865 | * Dynamic radio parameters for 5GHz | 863 | * Dynamic radio parameters for 5GHz |
866 | * | 864 | * |
867 | * Range: unknown | 865 | * Range: unknown |
868 | */ | 866 | */ |
869 | s16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 867 | u16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
870 | s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 868 | u8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
871 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 869 | s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
872 | 870 | ||
873 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; | 871 | s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS]; |
874 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; | 872 | s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS]; |
873 | s8 tx_rate_limits_extreme_5[CONF_NUMBER_OF_RATE_GROUPS]; | ||
875 | 874 | ||
876 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; | 875 | s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5]; |
877 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; | 876 | s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS]; |
@@ -879,33 +878,46 @@ struct conf_radio_parms { | |||
879 | /* FIXME: this is inconsistent with the types for 2.4GHz */ | 878 | /* FIXME: this is inconsistent with the types for 2.4GHz */ |
880 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; | 879 | s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS]; |
881 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; | 880 | s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5]; |
882 | }; | ||
883 | 881 | ||
884 | #define CONF_SR_ERR_TBL_COUNT 3 | 882 | u8 degraded_low_to_normal_threshold_5; |
883 | u8 degraded_normal_to_high_threshold_5; | ||
884 | }; | ||
885 | 885 | ||
886 | struct conf_init_settings { | 886 | struct conf_init_settings { |
887 | /* | 887 | /* |
888 | * Configure Smart Reflex error table values. | 888 | * Configure general parameters. |
889 | */ | 889 | */ |
890 | struct conf_mart_reflex_err_table sr_err_tbl[CONF_SR_ERR_TBL_COUNT]; | 890 | struct conf_general_parms genparam; |
891 | 891 | ||
892 | /* | 892 | /* |
893 | * Smart Reflex enable flag. | 893 | * Configure radio parameters. |
894 | * | ||
895 | * Range: 1 - Smart Reflex enabled, 0 - Smart Reflex disabled | ||
896 | */ | 894 | */ |
897 | u8 sr_enable; | 895 | struct conf_radio_parms radioparam; |
898 | 896 | ||
897 | }; | ||
898 | |||
899 | struct conf_itrim_settings { | ||
900 | /* enable dco itrim */ | ||
901 | u8 enable; | ||
902 | |||
903 | /* moderation timeout in microsecs from the last TX */ | ||
904 | u32 timeout; | ||
905 | }; | ||
906 | |||
907 | struct conf_pm_config_settings { | ||
899 | /* | 908 | /* |
900 | * Configure general parameters. | 909 | * Host clock settling time |
910 | * | ||
911 | * Range: 0 - 30000 us | ||
901 | */ | 912 | */ |
902 | struct conf_general_parms genparam; | 913 | u32 host_clk_settling_time; |
903 | 914 | ||
904 | /* | 915 | /* |
905 | * Configure radio parameters. | 916 | * Host fast wakeup support |
917 | * | ||
918 | * Range: true, false | ||
906 | */ | 919 | */ |
907 | struct conf_radio_parms radioparam; | 920 | bool host_fast_wakeup_support; |
908 | |||
909 | }; | 921 | }; |
910 | 922 | ||
911 | struct conf_drv_settings { | 923 | struct conf_drv_settings { |
@@ -914,6 +926,8 @@ struct conf_drv_settings { | |||
914 | struct conf_tx_settings tx; | 926 | struct conf_tx_settings tx; |
915 | struct conf_conn_settings conn; | 927 | struct conf_conn_settings conn; |
916 | struct conf_init_settings init; | 928 | struct conf_init_settings init; |
929 | struct conf_itrim_settings itrim; | ||
930 | struct conf_pm_config_settings pm_config; | ||
917 | }; | 931 | }; |
918 | 932 | ||
919 | #endif | 933 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c index c1805e5f8964..8d7588ca68fd 100644 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c | |||
@@ -237,6 +237,64 @@ static const struct file_operations tx_queue_len_ops = { | |||
237 | .open = wl1271_open_file_generic, | 237 | .open = wl1271_open_file_generic, |
238 | }; | 238 | }; |
239 | 239 | ||
240 | static ssize_t gpio_power_read(struct file *file, char __user *user_buf, | ||
241 | size_t count, loff_t *ppos) | ||
242 | { | ||
243 | struct wl1271 *wl = file->private_data; | ||
244 | bool state = test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
245 | |||
246 | int res; | ||
247 | char buf[10]; | ||
248 | |||
249 | res = scnprintf(buf, sizeof(buf), "%d\n", state); | ||
250 | |||
251 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
252 | } | ||
253 | |||
254 | static ssize_t gpio_power_write(struct file *file, | ||
255 | const char __user *user_buf, | ||
256 | size_t count, loff_t *ppos) | ||
257 | { | ||
258 | struct wl1271 *wl = file->private_data; | ||
259 | char buf[10]; | ||
260 | size_t len; | ||
261 | unsigned long value; | ||
262 | int ret; | ||
263 | |||
264 | mutex_lock(&wl->mutex); | ||
265 | |||
266 | len = min(count, sizeof(buf) - 1); | ||
267 | if (copy_from_user(buf, user_buf, len)) { | ||
268 | ret = -EFAULT; | ||
269 | goto out; | ||
270 | } | ||
271 | buf[len] = '\0'; | ||
272 | |||
273 | ret = strict_strtoul(buf, 0, &value); | ||
274 | if (ret < 0) { | ||
275 | wl1271_warning("illegal value in gpio_power"); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | if (value) { | ||
280 | wl->set_power(true); | ||
281 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
282 | } else { | ||
283 | wl->set_power(false); | ||
284 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
285 | } | ||
286 | |||
287 | out: | ||
288 | mutex_unlock(&wl->mutex); | ||
289 | return count; | ||
290 | } | ||
291 | |||
292 | static const struct file_operations gpio_power_ops = { | ||
293 | .read = gpio_power_read, | ||
294 | .write = gpio_power_write, | ||
295 | .open = wl1271_open_file_generic | ||
296 | }; | ||
297 | |||
240 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) | 298 | static void wl1271_debugfs_delete_files(struct wl1271 *wl) |
241 | { | 299 | { |
242 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); | 300 | DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); |
@@ -333,6 +391,8 @@ static void wl1271_debugfs_delete_files(struct wl1271 *wl) | |||
333 | DEBUGFS_DEL(tx_queue_len); | 391 | DEBUGFS_DEL(tx_queue_len); |
334 | DEBUGFS_DEL(retry_count); | 392 | DEBUGFS_DEL(retry_count); |
335 | DEBUGFS_DEL(excessive_retries); | 393 | DEBUGFS_DEL(excessive_retries); |
394 | |||
395 | DEBUGFS_DEL(gpio_power); | ||
336 | } | 396 | } |
337 | 397 | ||
338 | static int wl1271_debugfs_add_files(struct wl1271 *wl) | 398 | static int wl1271_debugfs_add_files(struct wl1271 *wl) |
@@ -434,6 +494,8 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl) | |||
434 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); | 494 | DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); |
435 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); | 495 | DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); |
436 | 496 | ||
497 | DEBUGFS_ADD(gpio_power, wl->debugfs.rootdir); | ||
498 | |||
437 | out: | 499 | out: |
438 | if (ret < 0) | 500 | if (ret < 0) |
439 | wl1271_debugfs_delete_files(wl); | 501 | wl1271_debugfs_delete_files(wl); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c index d13fdd99c85c..0a145afc9905 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ b/drivers/net/wireless/wl12xx/wl1271_event.c | |||
@@ -35,7 +35,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", | 35 | wl1271_debug(DEBUG_EVENT, "status: 0x%x", |
36 | mbox->scheduled_scan_status); | 36 | mbox->scheduled_scan_status); |
37 | 37 | ||
38 | if (wl->scanning) { | 38 | if (test_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { | 39 | if (wl->scan.state == WL1271_SCAN_BAND_DUAL) { |
40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, | 40 | wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, |
41 | NULL, size); | 41 | NULL, size); |
@@ -43,7 +43,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
43 | * to the wl1271_cmd_scan function that we are not | 43 | * to the wl1271_cmd_scan function that we are not |
44 | * scanning as it checks that. | 44 | * scanning as it checks that. |
45 | */ | 45 | */ |
46 | wl->scanning = false; | 46 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, | 47 | wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len, |
48 | wl->scan.active, | 48 | wl->scan.active, |
49 | wl->scan.high_prio, | 49 | wl->scan.high_prio, |
@@ -62,7 +62,7 @@ static int wl1271_event_scan_complete(struct wl1271 *wl, | |||
62 | mutex_unlock(&wl->mutex); | 62 | mutex_unlock(&wl->mutex); |
63 | ieee80211_scan_completed(wl->hw, false); | 63 | ieee80211_scan_completed(wl->hw, false); |
64 | mutex_lock(&wl->mutex); | 64 | mutex_lock(&wl->mutex); |
65 | wl->scanning = false; | 65 | clear_bit(WL1271_FLAG_SCANNING, &wl->flags); |
66 | } | 66 | } |
67 | } | 67 | } |
68 | return 0; | 68 | return 0; |
@@ -78,7 +78,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
78 | 78 | ||
79 | switch (mbox->ps_status) { | 79 | switch (mbox->ps_status) { |
80 | case EVENT_ENTER_POWER_SAVE_FAIL: | 80 | case EVENT_ENTER_POWER_SAVE_FAIL: |
81 | if (!wl->psm) { | 81 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
82 | wl->psm_entry_retry = 0; | 82 | wl->psm_entry_retry = 0; |
83 | break; | 83 | break; |
84 | } | 84 | } |
@@ -89,7 +89,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
89 | } else { | 89 | } else { |
90 | wl1271_error("PSM entry failed, giving up.\n"); | 90 | wl1271_error("PSM entry failed, giving up.\n"); |
91 | wl->psm_entry_retry = 0; | 91 | wl->psm_entry_retry = 0; |
92 | *beacon_loss = true; | ||
93 | } | 92 | } |
94 | break; | 93 | break; |
95 | case EVENT_ENTER_POWER_SAVE_SUCCESS: | 94 | case EVENT_ENTER_POWER_SAVE_SUCCESS: |
@@ -136,7 +135,8 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
136 | * filtering) is enabled. Without PSM, the stack will receive all | 135 | * filtering) is enabled. Without PSM, the stack will receive all |
137 | * beacons and can detect beacon loss by itself. | 136 | * beacons and can detect beacon loss by itself. |
138 | */ | 137 | */ |
139 | if (vector & BSS_LOSE_EVENT_ID && wl->psm) { | 138 | if (vector & BSS_LOSE_EVENT_ID && |
139 | test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); | 140 | wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); |
141 | 141 | ||
142 | /* indicate to the stack, that beacons have been lost */ | 142 | /* indicate to the stack, that beacons have been lost */ |
@@ -150,7 +150,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
150 | return ret; | 150 | return ret; |
151 | } | 151 | } |
152 | 152 | ||
153 | if (beacon_loss) { | 153 | if (wl->vif && beacon_loss) { |
154 | /* Obviously, it's dangerous to release the mutex while | 154 | /* Obviously, it's dangerous to release the mutex while |
155 | we are holding many of the variables in the wl struct. | 155 | we are holding many of the variables in the wl struct. |
156 | That's why it's done last in the function, and care must | 156 | That's why it's done last in the function, and care must |
@@ -184,7 +184,7 @@ void wl1271_event_mbox_config(struct wl1271 *wl) | |||
184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); | 184 | wl->mbox_ptr[0], wl->mbox_ptr[1]); |
185 | } | 185 | } |
186 | 186 | ||
187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | 187 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) |
188 | { | 188 | { |
189 | struct event_mailbox mbox; | 189 | struct event_mailbox mbox; |
190 | int ret; | 190 | int ret; |
@@ -204,9 +204,7 @@ int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num, bool do_ack) | |||
204 | return ret; | 204 | return ret; |
205 | 205 | ||
206 | /* then we let the firmware know it can go on...*/ | 206 | /* then we let the firmware know it can go on...*/ |
207 | if (do_ack) | 207 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); |
208 | wl1271_spi_write32(wl, ACX_REG_INTERRUPT_TRIG, | ||
209 | INTR_TRIG_EVENT_ACK); | ||
210 | 208 | ||
211 | return 0; | 209 | return 0; |
212 | } | 210 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h index 4e3f55ebb1a8..278f9206aa56 100644 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ b/drivers/net/wireless/wl12xx/wl1271_event.h | |||
@@ -112,6 +112,6 @@ struct event_mailbox { | |||
112 | 112 | ||
113 | int wl1271_event_unmask(struct wl1271 *wl); | 113 | int wl1271_event_unmask(struct wl1271 *wl); |
114 | void wl1271_event_mbox_config(struct wl1271 *wl); | 114 | void wl1271_event_mbox_config(struct wl1271 *wl); |
115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox, bool do_ack); | 115 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
116 | 116 | ||
117 | #endif | 117 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c index 11249b436cf1..c9848eecb767 100644 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ b/drivers/net/wireless/wl12xx/wl1271_init.c | |||
@@ -229,6 +229,10 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
229 | if (ret < 0) | 229 | if (ret < 0) |
230 | goto out_free_memmap; | 230 | goto out_free_memmap; |
231 | 231 | ||
232 | ret = wl1271_acx_dco_itrim_params(wl); | ||
233 | if (ret < 0) | ||
234 | goto out_free_memmap; | ||
235 | |||
232 | /* Initialize connection monitoring thresholds */ | 236 | /* Initialize connection monitoring thresholds */ |
233 | ret = wl1271_acx_conn_monit_params(wl); | 237 | ret = wl1271_acx_conn_monit_params(wl); |
234 | if (ret < 0) | 238 | if (ret < 0) |
@@ -280,12 +284,12 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
280 | goto out_free_memmap; | 284 | goto out_free_memmap; |
281 | 285 | ||
282 | /* Configure TX rate classes */ | 286 | /* Configure TX rate classes */ |
283 | ret = wl1271_acx_rate_policies(wl, CONF_TX_RATE_MASK_ALL); | 287 | ret = wl1271_acx_rate_policies(wl); |
284 | if (ret < 0) | 288 | if (ret < 0) |
285 | goto out_free_memmap; | 289 | goto out_free_memmap; |
286 | 290 | ||
287 | /* Enable data path */ | 291 | /* Enable data path */ |
288 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 292 | ret = wl1271_cmd_data_path(wl, 1); |
289 | if (ret < 0) | 293 | if (ret < 0) |
290 | goto out_free_memmap; | 294 | goto out_free_memmap; |
291 | 295 | ||
@@ -299,8 +303,8 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
299 | if (ret < 0) | 303 | if (ret < 0) |
300 | goto out_free_memmap; | 304 | goto out_free_memmap; |
301 | 305 | ||
302 | /* Configure smart reflex */ | 306 | /* configure PM */ |
303 | ret = wl1271_acx_smart_reflex(wl); | 307 | ret = wl1271_acx_pm_config(wl); |
304 | if (ret < 0) | 308 | if (ret < 0) |
305 | goto out_free_memmap; | 309 | goto out_free_memmap; |
306 | 310 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index b62c00ff42fe..e4867b895c43 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include "wl1271_cmd.h" | 47 | #include "wl1271_cmd.h" |
48 | #include "wl1271_boot.h" | 48 | #include "wl1271_boot.h" |
49 | 49 | ||
50 | #define WL1271_BOOT_RETRIES 3 | ||
51 | |||
50 | static struct conf_drv_settings default_conf = { | 52 | static struct conf_drv_settings default_conf = { |
51 | .sg = { | 53 | .sg = { |
52 | .per_threshold = 7500, | 54 | .per_threshold = 7500, |
@@ -67,16 +69,17 @@ static struct conf_drv_settings default_conf = { | |||
67 | .ps_poll_timeout = 15, | 69 | .ps_poll_timeout = 15, |
68 | .upsd_timeout = 15, | 70 | .upsd_timeout = 15, |
69 | .rts_threshold = 2347, | 71 | .rts_threshold = 2347, |
70 | .rx_cca_threshold = 0xFFEF, | 72 | .rx_cca_threshold = 0, |
71 | .irq_blk_threshold = 0, | 73 | .irq_blk_threshold = 0xFFFF, |
72 | .irq_pkt_threshold = USHORT_MAX, | 74 | .irq_pkt_threshold = 0, |
73 | .irq_timeout = 5, | 75 | .irq_timeout = 600, |
74 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, | 76 | .queue_type = CONF_RX_QUEUE_TYPE_LOW_PRIORITY, |
75 | }, | 77 | }, |
76 | .tx = { | 78 | .tx = { |
77 | .tx_energy_detection = 0, | 79 | .tx_energy_detection = 0, |
78 | .rc_conf = { | 80 | .rc_conf = { |
79 | .enabled_rates = CONF_TX_RATE_MASK_UNSPECIFIED, | 81 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS | |
82 | CONF_HW_BIT_RATE_2MBPS, | ||
80 | .short_retry_limit = 10, | 83 | .short_retry_limit = 10, |
81 | .long_retry_limit = 10, | 84 | .long_retry_limit = 10, |
82 | .aflags = 0 | 85 | .aflags = 0 |
@@ -172,8 +175,8 @@ static struct conf_drv_settings default_conf = { | |||
172 | } | 175 | } |
173 | }, | 176 | }, |
174 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, | 177 | .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, |
175 | .tx_compl_timeout = 5, | 178 | .tx_compl_timeout = 700, |
176 | .tx_compl_threshold = 5 | 179 | .tx_compl_threshold = 4 |
177 | }, | 180 | }, |
178 | .conn = { | 181 | .conn = { |
179 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 182 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
@@ -186,12 +189,12 @@ static struct conf_drv_settings default_conf = { | |||
186 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 189 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
187 | } | 190 | } |
188 | }, | 191 | }, |
189 | .synch_fail_thold = 5, | 192 | .synch_fail_thold = 10, |
190 | .bss_lose_timeout = 100, | 193 | .bss_lose_timeout = 100, |
191 | .beacon_rx_timeout = 10000, | 194 | .beacon_rx_timeout = 10000, |
192 | .broadcast_timeout = 20000, | 195 | .broadcast_timeout = 20000, |
193 | .rx_broadcast_in_ps = 1, | 196 | .rx_broadcast_in_ps = 1, |
194 | .ps_poll_threshold = 4, | 197 | .ps_poll_threshold = 20, |
195 | .sig_trigger_count = 2, | 198 | .sig_trigger_count = 2, |
196 | .sig_trigger = { | 199 | .sig_trigger = { |
197 | [0] = { | 200 | [0] = { |
@@ -226,46 +229,35 @@ static struct conf_drv_settings default_conf = { | |||
226 | .psm_entry_retries = 3 | 229 | .psm_entry_retries = 3 |
227 | }, | 230 | }, |
228 | .init = { | 231 | .init = { |
229 | .sr_err_tbl = { | ||
230 | [0] = { | ||
231 | .len = 7, | ||
232 | .upper_limit = 0x03, | ||
233 | .values = { | ||
234 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
235 | 0x00 } | ||
236 | }, | ||
237 | [1] = { | ||
238 | .len = 7, | ||
239 | .upper_limit = 0x03, | ||
240 | .values = { | ||
241 | 0x18, 0x10, 0x05, 0xf6, 0xf0, 0xe8, | ||
242 | 0x00 } | ||
243 | }, | ||
244 | [2] = { | ||
245 | .len = 7, | ||
246 | .upper_limit = 0x03, | ||
247 | .values = { | ||
248 | 0x18, 0x10, 0x05, 0xfb, 0xf0, 0xe8, | ||
249 | 0x00 } | ||
250 | } | ||
251 | }, | ||
252 | .sr_enable = 1, | ||
253 | .genparam = { | 232 | .genparam = { |
254 | .ref_clk = CONF_REF_CLK_38_4_E, | 233 | .ref_clk = CONF_REF_CLK_38_4_E, |
255 | .settling_time = 5, | 234 | .settling_time = 5, |
256 | .clk_valid_on_wakeup = 0, | 235 | .clk_valid_on_wakeup = 0, |
257 | .dc2dcmode = 0, | 236 | .dc2dcmode = 0, |
258 | .single_dual_band = CONF_SINGLE_BAND, | 237 | .single_dual_band = CONF_SINGLE_BAND, |
259 | .tx_bip_fem_autodetect = 0, | 238 | .tx_bip_fem_autodetect = 1, |
260 | .tx_bip_fem_manufacturer = 1, | 239 | .tx_bip_fem_manufacturer = 1, |
261 | .settings = 1, | 240 | .settings = 1, |
241 | .sr_state = 1, | ||
242 | .srf1 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
243 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
244 | .srf2 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
245 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
246 | .srf3 = { 0x07, 0x03, 0x18, 0x10, 0x05, 0xfb, 0xf0, | ||
247 | 0xe8, 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
248 | .sr_debug_table = { 0, 0, 0, 0, 0, 0, 0, 0, | ||
249 | 0, 0, 0, 0, 0, 0, 0, 0 }, | ||
250 | .sr_sen_n_p = 0, | ||
251 | .sr_sen_n_p_gain = 0, | ||
252 | .sr_sen_nrn = 0, | ||
253 | .sr_sen_prn = 0, | ||
262 | }, | 254 | }, |
263 | .radioparam = { | 255 | .radioparam = { |
264 | .rx_trace_loss = 10, | 256 | .rx_trace_loss = 0x24, |
265 | .tx_trace_loss = 10, | 257 | .tx_trace_loss = 0x0, |
266 | .rx_rssi_and_proc_compens = { | 258 | .rx_rssi_and_proc_compens = { |
267 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, | 259 | 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, |
268 | 0xfc, 0x00, 0x08, 0x10, 0xf0, 0xf8, | 260 | 0xfc, 0x00, 0x80, 0x10, 0xf0, 0xf8, |
269 | 0x00, 0x0a, 0x14 }, | 261 | 0x00, 0x0a, 0x14 }, |
270 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | 262 | .rx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, |
271 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, | 263 | .tx_trace_loss_5 = { 0, 0, 0, 0, 0, 0, 0 }, |
@@ -273,13 +265,15 @@ static struct conf_drv_settings default_conf = { | |||
273 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 265 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
274 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 266 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
275 | 0x00, 0x00, 0x00 }, | 267 | 0x00, 0x00, 0x00 }, |
276 | .tx_ref_pd_voltage = 0x24e, | 268 | .tx_ref_pd_voltage = 0x1a9, |
277 | .tx_ref_power = 0x78, | 269 | .tx_ref_power = 0x80, |
278 | .tx_offset_db = 0x0, | 270 | .tx_offset_db = 0x0, |
279 | .tx_rate_limits_normal = { | 271 | .tx_rate_limits_normal = { |
280 | 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }, | 272 | 0x1d, 0x1f, 0x24, 0x28, 0x28, 0x29 }, |
281 | .tx_rate_limits_degraded = { | 273 | .tx_rate_limits_degraded = { |
282 | 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | 274 | 0x19, 0x1f, 0x22, 0x23, 0x27, 0x28 }, |
275 | .tx_rate_limits_extreme = { | ||
276 | 0x19, 0x1c, 0x1e, 0x20, 0x24, 0x25 }, | ||
283 | .tx_channel_limits_11b = { | 277 | .tx_channel_limits_11b = { |
284 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, | 278 | 0x22, 0x50, 0x50, 0x50, 0x50, 0x50, |
285 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, | 279 | 0x50, 0x50, 0x50, 0x50, 0x22, 0x50, |
@@ -289,10 +283,12 @@ static struct conf_drv_settings default_conf = { | |||
289 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, | 283 | 0x50, 0x50, 0x50, 0x50, 0x20, 0x50, |
290 | 0x20, 0x50 }, | 284 | 0x20, 0x50 }, |
291 | .tx_pdv_rate_offsets = { | 285 | .tx_pdv_rate_offsets = { |
292 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, | 286 | 0x07, 0x08, 0x04, 0x02, 0x02, 0x00 }, |
293 | .tx_ibias = { | 287 | .tx_ibias = { |
294 | 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }, | 288 | 0x11, 0x11, 0x15, 0x11, 0x15, 0x0f }, |
295 | .rx_fem_insertion_loss = 0x14, | 289 | .rx_fem_insertion_loss = 0x0e, |
290 | .degraded_low_to_normal_threshold = 0x1e, | ||
291 | .degraded_normal_to_high_threshold = 0x2d, | ||
296 | .tx_ref_pd_voltage_5 = { | 292 | .tx_ref_pd_voltage_5 = { |
297 | 0x0190, 0x01a4, 0x01c3, 0x01d8, | 293 | 0x0190, 0x01a4, 0x01c3, 0x01d8, |
298 | 0x020a, 0x021c }, | 294 | 0x020a, 0x021c }, |
@@ -304,6 +300,8 @@ static struct conf_drv_settings default_conf = { | |||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | 300 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, |
305 | .tx_rate_limits_degraded_5 = { | 301 | .tx_rate_limits_degraded_5 = { |
306 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | 302 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, |
303 | .tx_rate_limits_extreme_5 = { | ||
304 | 0x1b, 0x1e, 0x21, 0x23, 0x27, 0x00 }, | ||
307 | .tx_channel_limits_ofdm_5 = { | 305 | .tx_channel_limits_ofdm_5 = { |
308 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | 306 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, |
309 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, | 307 | 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, |
@@ -315,8 +313,18 @@ static struct conf_drv_settings default_conf = { | |||
315 | .tx_ibias_5 = { | 313 | .tx_ibias_5 = { |
316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, | 314 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, |
317 | .rx_fem_insertion_loss_5 = { | 315 | .rx_fem_insertion_loss_5 = { |
318 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 } | 316 | 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 }, |
317 | .degraded_low_to_normal_threshold_5 = 0x00, | ||
318 | .degraded_normal_to_high_threshold_5 = 0x00 | ||
319 | } | 319 | } |
320 | }, | ||
321 | .itrim = { | ||
322 | .enable = false, | ||
323 | .timeout = 50000, | ||
324 | }, | ||
325 | .pm_config = { | ||
326 | .host_clk_settling_time = 5000, | ||
327 | .host_fast_wakeup_support = false | ||
320 | } | 328 | } |
321 | }; | 329 | }; |
322 | 330 | ||
@@ -359,7 +367,7 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
359 | if (ret < 0) | 367 | if (ret < 0) |
360 | return ret; | 368 | return ret; |
361 | 369 | ||
362 | ret = wl1271_cmd_data_path(wl, wl->channel, 1); | 370 | ret = wl1271_cmd_data_path(wl, 1); |
363 | if (ret < 0) | 371 | if (ret < 0) |
364 | return ret; | 372 | return ret; |
365 | 373 | ||
@@ -374,11 +382,13 @@ static void wl1271_disable_interrupts(struct wl1271 *wl) | |||
374 | static void wl1271_power_off(struct wl1271 *wl) | 382 | static void wl1271_power_off(struct wl1271 *wl) |
375 | { | 383 | { |
376 | wl->set_power(false); | 384 | wl->set_power(false); |
385 | clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
377 | } | 386 | } |
378 | 387 | ||
379 | static void wl1271_power_on(struct wl1271 *wl) | 388 | static void wl1271_power_on(struct wl1271 *wl) |
380 | { | 389 | { |
381 | wl->set_power(true); | 390 | wl->set_power(true); |
391 | set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags); | ||
382 | } | 392 | } |
383 | 393 | ||
384 | static void wl1271_fw_status(struct wl1271 *wl, | 394 | static void wl1271_fw_status(struct wl1271 *wl, |
@@ -447,14 +457,13 @@ static void wl1271_irq_work(struct work_struct *work) | |||
447 | intr &= WL1271_INTR_MASK; | 457 | intr &= WL1271_INTR_MASK; |
448 | 458 | ||
449 | if (intr & WL1271_ACX_INTR_EVENT_A) { | 459 | if (intr & WL1271_ACX_INTR_EVENT_A) { |
450 | bool do_ack = (intr & WL1271_ACX_INTR_EVENT_B) ? false : true; | ||
451 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); | 460 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_A"); |
452 | wl1271_event_handle(wl, 0, do_ack); | 461 | wl1271_event_handle(wl, 0); |
453 | } | 462 | } |
454 | 463 | ||
455 | if (intr & WL1271_ACX_INTR_EVENT_B) { | 464 | if (intr & WL1271_ACX_INTR_EVENT_B) { |
456 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); | 465 | wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_EVENT_B"); |
457 | wl1271_event_handle(wl, 1, true); | 466 | wl1271_event_handle(wl, 1); |
458 | } | 467 | } |
459 | 468 | ||
460 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) | 469 | if (intr & WL1271_ACX_INTR_INIT_COMPLETE) |
@@ -614,6 +623,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
614 | struct wl1271_partition_set partition; | 623 | struct wl1271_partition_set partition; |
615 | int ret = 0; | 624 | int ret = 0; |
616 | 625 | ||
626 | msleep(WL1271_PRE_POWER_ON_SLEEP); | ||
617 | wl1271_power_on(wl); | 627 | wl1271_power_on(wl); |
618 | msleep(WL1271_POWER_ON_SLEEP); | 628 | msleep(WL1271_POWER_ON_SLEEP); |
619 | wl1271_spi_reset(wl); | 629 | wl1271_spi_reset(wl); |
@@ -643,7 +653,7 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
643 | 653 | ||
644 | ret = wl1271_setup(wl); | 654 | ret = wl1271_setup(wl); |
645 | if (ret < 0) | 655 | if (ret < 0) |
646 | goto out_power_off; | 656 | goto out; |
647 | break; | 657 | break; |
648 | case CHIP_ID_1271_PG20: | 658 | case CHIP_ID_1271_PG20: |
649 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 659 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
@@ -651,38 +661,34 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
651 | 661 | ||
652 | ret = wl1271_setup(wl); | 662 | ret = wl1271_setup(wl); |
653 | if (ret < 0) | 663 | if (ret < 0) |
654 | goto out_power_off; | 664 | goto out; |
655 | break; | 665 | break; |
656 | default: | 666 | default: |
657 | wl1271_error("unsupported chip id: 0x%x", wl->chip.id); | 667 | wl1271_warning("unsupported chip id: 0x%x", wl->chip.id); |
658 | ret = -ENODEV; | 668 | ret = -ENODEV; |
659 | goto out_power_off; | 669 | goto out; |
660 | } | 670 | } |
661 | 671 | ||
662 | if (wl->fw == NULL) { | 672 | if (wl->fw == NULL) { |
663 | ret = wl1271_fetch_firmware(wl); | 673 | ret = wl1271_fetch_firmware(wl); |
664 | if (ret < 0) | 674 | if (ret < 0) |
665 | goto out_power_off; | 675 | goto out; |
666 | } | 676 | } |
667 | 677 | ||
668 | /* No NVS from netlink, try to get it from the filesystem */ | 678 | /* No NVS from netlink, try to get it from the filesystem */ |
669 | if (wl->nvs == NULL) { | 679 | if (wl->nvs == NULL) { |
670 | ret = wl1271_fetch_nvs(wl); | 680 | ret = wl1271_fetch_nvs(wl); |
671 | if (ret < 0) | 681 | if (ret < 0) |
672 | goto out_power_off; | 682 | goto out; |
673 | } | 683 | } |
674 | 684 | ||
675 | goto out; | ||
676 | |||
677 | out_power_off: | ||
678 | wl1271_power_off(wl); | ||
679 | |||
680 | out: | 685 | out: |
681 | return ret; | 686 | return ret; |
682 | } | 687 | } |
683 | 688 | ||
684 | int wl1271_plt_start(struct wl1271 *wl) | 689 | int wl1271_plt_start(struct wl1271 *wl) |
685 | { | 690 | { |
691 | int retries = WL1271_BOOT_RETRIES; | ||
686 | int ret; | 692 | int ret; |
687 | 693 | ||
688 | mutex_lock(&wl->mutex); | 694 | mutex_lock(&wl->mutex); |
@@ -696,35 +702,48 @@ int wl1271_plt_start(struct wl1271 *wl) | |||
696 | goto out; | 702 | goto out; |
697 | } | 703 | } |
698 | 704 | ||
699 | wl->state = WL1271_STATE_PLT; | 705 | while (retries) { |
700 | 706 | retries--; | |
701 | ret = wl1271_chip_wakeup(wl); | 707 | ret = wl1271_chip_wakeup(wl); |
702 | if (ret < 0) | 708 | if (ret < 0) |
703 | goto out; | 709 | goto power_off; |
704 | |||
705 | ret = wl1271_boot(wl); | ||
706 | if (ret < 0) | ||
707 | goto out_power_off; | ||
708 | |||
709 | wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); | ||
710 | 710 | ||
711 | ret = wl1271_plt_init(wl); | 711 | ret = wl1271_boot(wl); |
712 | if (ret < 0) | 712 | if (ret < 0) |
713 | goto out_irq_disable; | 713 | goto power_off; |
714 | 714 | ||
715 | /* Make sure power saving is disabled */ | 715 | ret = wl1271_plt_init(wl); |
716 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | 716 | if (ret < 0) |
717 | if (ret < 0) | 717 | goto irq_disable; |
718 | goto out_irq_disable; | ||
719 | 718 | ||
720 | goto out; | 719 | /* Make sure power saving is disabled */ |
720 | ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM); | ||
721 | if (ret < 0) | ||
722 | goto irq_disable; | ||
721 | 723 | ||
722 | out_irq_disable: | 724 | wl->state = WL1271_STATE_PLT; |
723 | wl1271_disable_interrupts(wl); | 725 | wl1271_notice("firmware booted in PLT mode (%s)", |
726 | wl->chip.fw_ver); | ||
727 | goto out; | ||
724 | 728 | ||
725 | out_power_off: | 729 | irq_disable: |
726 | wl1271_power_off(wl); | 730 | wl1271_disable_interrupts(wl); |
731 | mutex_unlock(&wl->mutex); | ||
732 | /* Unlocking the mutex in the middle of handling is | ||
733 | inherently unsafe. In this case we deem it safe to do, | ||
734 | because we need to let any possibly pending IRQ out of | ||
735 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
736 | work function will not do anything.) Also, any other | ||
737 | possible concurrent operations will fail due to the | ||
738 | current state, hence the wl1271 struct should be safe. */ | ||
739 | cancel_work_sync(&wl->irq_work); | ||
740 | mutex_lock(&wl->mutex); | ||
741 | power_off: | ||
742 | wl1271_power_off(wl); | ||
743 | } | ||
727 | 744 | ||
745 | wl1271_error("firmware boot in PLT mode failed despite %d retries", | ||
746 | WL1271_BOOT_RETRIES); | ||
728 | out: | 747 | out: |
729 | mutex_unlock(&wl->mutex); | 748 | mutex_unlock(&wl->mutex); |
730 | 749 | ||
@@ -762,7 +781,20 @@ out: | |||
762 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | 781 | static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) |
763 | { | 782 | { |
764 | struct wl1271 *wl = hw->priv; | 783 | struct wl1271 *wl = hw->priv; |
784 | struct ieee80211_conf *conf = &hw->conf; | ||
785 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
786 | struct ieee80211_sta *sta = txinfo->control.sta; | ||
787 | unsigned long flags; | ||
765 | 788 | ||
789 | /* peek into the rates configured in the STA entry */ | ||
790 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
791 | if (sta && sta->supp_rates[conf->channel->band] != wl->sta_rate_set) { | ||
792 | wl->sta_rate_set = sta->supp_rates[conf->channel->band]; | ||
793 | set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags); | ||
794 | } | ||
795 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
796 | |||
797 | /* queue the packet */ | ||
766 | skb_queue_tail(&wl->tx_queue, skb); | 798 | skb_queue_tail(&wl->tx_queue, skb); |
767 | 799 | ||
768 | /* | 800 | /* |
@@ -784,7 +816,7 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
784 | * protected. Maybe fix this by removing the stupid | 816 | * protected. Maybe fix this by removing the stupid |
785 | * variable altogether and checking the real queue state? | 817 | * variable altogether and checking the real queue state? |
786 | */ | 818 | */ |
787 | wl->tx_queue_stopped = true; | 819 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
788 | } | 820 | } |
789 | 821 | ||
790 | return NETDEV_TX_OK; | 822 | return NETDEV_TX_OK; |
@@ -880,6 +912,7 @@ static struct notifier_block wl1271_dev_notifier = { | |||
880 | static int wl1271_op_start(struct ieee80211_hw *hw) | 912 | static int wl1271_op_start(struct ieee80211_hw *hw) |
881 | { | 913 | { |
882 | struct wl1271 *wl = hw->priv; | 914 | struct wl1271 *wl = hw->priv; |
915 | int retries = WL1271_BOOT_RETRIES; | ||
883 | int ret = 0; | 916 | int ret = 0; |
884 | 917 | ||
885 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 918 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -893,30 +926,42 @@ static int wl1271_op_start(struct ieee80211_hw *hw) | |||
893 | goto out; | 926 | goto out; |
894 | } | 927 | } |
895 | 928 | ||
896 | ret = wl1271_chip_wakeup(wl); | 929 | while (retries) { |
897 | if (ret < 0) | 930 | retries--; |
898 | goto out; | 931 | ret = wl1271_chip_wakeup(wl); |
899 | 932 | if (ret < 0) | |
900 | ret = wl1271_boot(wl); | 933 | goto power_off; |
901 | if (ret < 0) | ||
902 | goto out_power_off; | ||
903 | |||
904 | ret = wl1271_hw_init(wl); | ||
905 | if (ret < 0) | ||
906 | goto out_irq_disable; | ||
907 | |||
908 | wl->state = WL1271_STATE_ON; | ||
909 | 934 | ||
910 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); | 935 | ret = wl1271_boot(wl); |
936 | if (ret < 0) | ||
937 | goto power_off; | ||
911 | 938 | ||
912 | goto out; | 939 | ret = wl1271_hw_init(wl); |
940 | if (ret < 0) | ||
941 | goto irq_disable; | ||
913 | 942 | ||
914 | out_irq_disable: | 943 | wl->state = WL1271_STATE_ON; |
915 | wl1271_disable_interrupts(wl); | 944 | wl1271_info("firmware booted (%s)", wl->chip.fw_ver); |
945 | goto out; | ||
916 | 946 | ||
917 | out_power_off: | 947 | irq_disable: |
918 | wl1271_power_off(wl); | 948 | wl1271_disable_interrupts(wl); |
949 | mutex_unlock(&wl->mutex); | ||
950 | /* Unlocking the mutex in the middle of handling is | ||
951 | inherently unsafe. In this case we deem it safe to do, | ||
952 | because we need to let any possibly pending IRQ out of | ||
953 | the system (and while we are WL1271_STATE_OFF the IRQ | ||
954 | work function will not do anything.) Also, any other | ||
955 | possible concurrent operations will fail due to the | ||
956 | current state, hence the wl1271 struct should be safe. */ | ||
957 | cancel_work_sync(&wl->irq_work); | ||
958 | mutex_lock(&wl->mutex); | ||
959 | power_off: | ||
960 | wl1271_power_off(wl); | ||
961 | } | ||
919 | 962 | ||
963 | wl1271_error("firmware boot failed despite %d retries", | ||
964 | WL1271_BOOT_RETRIES); | ||
920 | out: | 965 | out: |
921 | mutex_unlock(&wl->mutex); | 966 | mutex_unlock(&wl->mutex); |
922 | 967 | ||
@@ -944,11 +989,10 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
944 | 989 | ||
945 | WARN_ON(wl->state != WL1271_STATE_ON); | 990 | WARN_ON(wl->state != WL1271_STATE_ON); |
946 | 991 | ||
947 | if (wl->scanning) { | 992 | if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) { |
948 | mutex_unlock(&wl->mutex); | 993 | mutex_unlock(&wl->mutex); |
949 | ieee80211_scan_completed(wl->hw, true); | 994 | ieee80211_scan_completed(wl->hw, true); |
950 | mutex_lock(&wl->mutex); | 995 | mutex_lock(&wl->mutex); |
951 | wl->scanning = false; | ||
952 | } | 996 | } |
953 | 997 | ||
954 | wl->state = WL1271_STATE_OFF; | 998 | wl->state = WL1271_STATE_OFF; |
@@ -973,10 +1017,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
973 | wl->band = IEEE80211_BAND_2GHZ; | 1017 | wl->band = IEEE80211_BAND_2GHZ; |
974 | 1018 | ||
975 | wl->rx_counter = 0; | 1019 | wl->rx_counter = 0; |
976 | wl->elp = false; | ||
977 | wl->psm = 0; | ||
978 | wl->psm_entry_retry = 0; | 1020 | wl->psm_entry_retry = 0; |
979 | wl->tx_queue_stopped = false; | ||
980 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1021 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
981 | wl->tx_blocks_available = 0; | 1022 | wl->tx_blocks_available = 0; |
982 | wl->tx_results_count = 0; | 1023 | wl->tx_results_count = 0; |
@@ -986,7 +1027,9 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
986 | wl->tx_security_seq_32 = 0; | 1027 | wl->tx_security_seq_32 = 0; |
987 | wl->time_offset = 0; | 1028 | wl->time_offset = 0; |
988 | wl->session_counter = 0; | 1029 | wl->session_counter = 0; |
989 | wl->joined = false; | 1030 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; |
1031 | wl->sta_rate_set = 0; | ||
1032 | wl->flags = 0; | ||
990 | 1033 | ||
991 | for (i = 0; i < NUM_TX_QUEUES; i++) | 1034 | for (i = 0; i < NUM_TX_QUEUES; i++) |
992 | wl->tx_blocks_freed[i] = 0; | 1035 | wl->tx_blocks_freed[i] = 0; |
@@ -996,13 +1039,13 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
996 | } | 1039 | } |
997 | 1040 | ||
998 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, | 1041 | static int wl1271_op_add_interface(struct ieee80211_hw *hw, |
999 | struct ieee80211_if_init_conf *conf) | 1042 | struct ieee80211_vif *vif) |
1000 | { | 1043 | { |
1001 | struct wl1271 *wl = hw->priv; | 1044 | struct wl1271 *wl = hw->priv; |
1002 | int ret = 0; | 1045 | int ret = 0; |
1003 | 1046 | ||
1004 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", | 1047 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
1005 | conf->type, conf->mac_addr); | 1048 | vif->type, vif->addr); |
1006 | 1049 | ||
1007 | mutex_lock(&wl->mutex); | 1050 | mutex_lock(&wl->mutex); |
1008 | if (wl->vif) { | 1051 | if (wl->vif) { |
@@ -1010,9 +1053,9 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
1010 | goto out; | 1053 | goto out; |
1011 | } | 1054 | } |
1012 | 1055 | ||
1013 | wl->vif = conf->vif; | 1056 | wl->vif = vif; |
1014 | 1057 | ||
1015 | switch (conf->type) { | 1058 | switch (vif->type) { |
1016 | case NL80211_IFTYPE_STATION: | 1059 | case NL80211_IFTYPE_STATION: |
1017 | wl->bss_type = BSS_TYPE_STA_BSS; | 1060 | wl->bss_type = BSS_TYPE_STA_BSS; |
1018 | break; | 1061 | break; |
@@ -1032,7 +1075,7 @@ out: | |||
1032 | } | 1075 | } |
1033 | 1076 | ||
1034 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | 1077 | static void wl1271_op_remove_interface(struct ieee80211_hw *hw, |
1035 | struct ieee80211_if_init_conf *conf) | 1078 | struct ieee80211_vif *vif) |
1036 | { | 1079 | { |
1037 | struct wl1271 *wl = hw->priv; | 1080 | struct wl1271 *wl = hw->priv; |
1038 | 1081 | ||
@@ -1109,6 +1152,51 @@ out: | |||
1109 | } | 1152 | } |
1110 | #endif | 1153 | #endif |
1111 | 1154 | ||
1155 | static int wl1271_join_channel(struct wl1271 *wl, int channel) | ||
1156 | { | ||
1157 | int ret = 0; | ||
1158 | /* we need to use a dummy BSSID for now */ | ||
1159 | static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde, | ||
1160 | 0xad, 0xbe, 0xef }; | ||
1161 | |||
1162 | /* the dummy join is not required for ad-hoc */ | ||
1163 | if (wl->bss_type == BSS_TYPE_IBSS) | ||
1164 | goto out; | ||
1165 | |||
1166 | /* disable mac filter, so we hear everything */ | ||
1167 | wl->rx_config &= ~CFG_BSSID_FILTER_EN; | ||
1168 | |||
1169 | wl->channel = channel; | ||
1170 | memcpy(wl->bssid, dummy_bssid, ETH_ALEN); | ||
1171 | |||
1172 | ret = wl1271_cmd_join(wl); | ||
1173 | if (ret < 0) | ||
1174 | goto out; | ||
1175 | |||
1176 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1177 | |||
1178 | out: | ||
1179 | return ret; | ||
1180 | } | ||
1181 | |||
1182 | static int wl1271_unjoin_channel(struct wl1271 *wl) | ||
1183 | { | ||
1184 | int ret; | ||
1185 | |||
1186 | /* to stop listening to a channel, we disconnect */ | ||
1187 | ret = wl1271_cmd_disconnect(wl); | ||
1188 | if (ret < 0) | ||
1189 | goto out; | ||
1190 | |||
1191 | clear_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1192 | wl->channel = 0; | ||
1193 | memset(wl->bssid, 0, ETH_ALEN); | ||
1194 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | ||
1195 | |||
1196 | out: | ||
1197 | return ret; | ||
1198 | } | ||
1199 | |||
1112 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | 1200 | static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) |
1113 | { | 1201 | { |
1114 | struct wl1271 *wl = hw->priv; | 1202 | struct wl1271 *wl = hw->priv; |
@@ -1117,10 +1205,11 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1117 | 1205 | ||
1118 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1206 | channel = ieee80211_frequency_to_channel(conf->channel->center_freq); |
1119 | 1207 | ||
1120 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", | 1208 | wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s", |
1121 | channel, | 1209 | channel, |
1122 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", | 1210 | conf->flags & IEEE80211_CONF_PS ? "on" : "off", |
1123 | conf->power_level); | 1211 | conf->power_level, |
1212 | conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use"); | ||
1124 | 1213 | ||
1125 | mutex_lock(&wl->mutex); | 1214 | mutex_lock(&wl->mutex); |
1126 | 1215 | ||
@@ -1130,34 +1219,44 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) | |||
1130 | if (ret < 0) | 1219 | if (ret < 0) |
1131 | goto out; | 1220 | goto out; |
1132 | 1221 | ||
1133 | if (channel != wl->channel) { | 1222 | if (changed & IEEE80211_CONF_CHANGE_IDLE) { |
1134 | /* | 1223 | if (conf->flags & IEEE80211_CONF_IDLE && |
1135 | * We assume that the stack will configure the right channel | 1224 | test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1136 | * before associating, so we don't need to send a join | 1225 | wl1271_unjoin_channel(wl); |
1137 | * command here. We will join the right channel when the | 1226 | else if (!(conf->flags & IEEE80211_CONF_IDLE)) |
1138 | * BSSID changes | 1227 | wl1271_join_channel(wl, channel); |
1139 | */ | 1228 | |
1140 | wl->channel = channel; | 1229 | if (conf->flags & IEEE80211_CONF_IDLE) { |
1230 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1231 | wl->sta_rate_set = 0; | ||
1232 | wl1271_acx_rate_policies(wl); | ||
1233 | } | ||
1141 | } | 1234 | } |
1142 | 1235 | ||
1143 | if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { | 1236 | /* if the channel changes while joined, join again */ |
1144 | wl1271_info("psm enabled"); | 1237 | if (channel != wl->channel && test_bit(WL1271_FLAG_JOINED, &wl->flags)) |
1238 | wl1271_join_channel(wl, channel); | ||
1145 | 1239 | ||
1146 | wl->psm_requested = true; | 1240 | if (conf->flags & IEEE80211_CONF_PS && |
1241 | !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { | ||
1242 | set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); | ||
1147 | 1243 | ||
1148 | /* | 1244 | /* |
1149 | * We enter PSM only if we're already associated. | 1245 | * We enter PSM only if we're already associated. |
1150 | * If we're not, we'll enter it when joining an SSID, | 1246 | * If we're not, we'll enter it when joining an SSID, |
1151 | * through the bss_info_changed() hook. | 1247 | * through the bss_info_changed() hook. |
1152 | */ | 1248 | */ |
1153 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | 1249 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) { |
1250 | wl1271_info("psm enabled"); | ||
1251 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
1252 | } | ||
1154 | } else if (!(conf->flags & IEEE80211_CONF_PS) && | 1253 | } else if (!(conf->flags & IEEE80211_CONF_PS) && |
1155 | wl->psm_requested) { | 1254 | test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { |
1156 | wl1271_info("psm disabled"); | 1255 | wl1271_info("psm disabled"); |
1157 | 1256 | ||
1158 | wl->psm_requested = false; | 1257 | clear_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); |
1159 | 1258 | ||
1160 | if (wl->psm) | 1259 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) |
1161 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); | 1260 | ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); |
1162 | } | 1261 | } |
1163 | 1262 | ||
@@ -1440,22 +1539,6 @@ out: | |||
1440 | return ret; | 1539 | return ret; |
1441 | } | 1540 | } |
1442 | 1541 | ||
1443 | static u32 wl1271_enabled_rates_get(struct wl1271 *wl, u64 basic_rate_set) | ||
1444 | { | ||
1445 | struct ieee80211_supported_band *band; | ||
1446 | u32 enabled_rates = 0; | ||
1447 | int bit; | ||
1448 | |||
1449 | band = wl->hw->wiphy->bands[wl->band]; | ||
1450 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
1451 | if (basic_rate_set & 0x1) | ||
1452 | enabled_rates |= band->bitrates[bit].hw_value; | ||
1453 | basic_rate_set >>= 1; | ||
1454 | } | ||
1455 | |||
1456 | return enabled_rates; | ||
1457 | } | ||
1458 | |||
1459 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | 1542 | static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, |
1460 | struct ieee80211_vif *vif, | 1543 | struct ieee80211_vif *vif, |
1461 | struct ieee80211_bss_conf *bss_conf, | 1544 | struct ieee80211_bss_conf *bss_conf, |
@@ -1473,9 +1556,68 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1473 | if (ret < 0) | 1556 | if (ret < 0) |
1474 | goto out; | 1557 | goto out; |
1475 | 1558 | ||
1559 | if ((changed & BSS_CHANGED_BSSID) && | ||
1560 | /* | ||
1561 | * Now we know the correct bssid, so we send a new join command | ||
1562 | * and enable the BSSID filter | ||
1563 | */ | ||
1564 | memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) { | ||
1565 | wl->rx_config |= CFG_BSSID_FILTER_EN; | ||
1566 | memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); | ||
1567 | ret = wl1271_cmd_build_null_data(wl); | ||
1568 | if (ret < 0) { | ||
1569 | wl1271_warning("cmd buld null data failed %d", | ||
1570 | ret); | ||
1571 | goto out_sleep; | ||
1572 | } | ||
1573 | ret = wl1271_cmd_join(wl); | ||
1574 | if (ret < 0) { | ||
1575 | wl1271_warning("cmd join failed %d", ret); | ||
1576 | goto out_sleep; | ||
1577 | } | ||
1578 | set_bit(WL1271_FLAG_JOINED, &wl->flags); | ||
1579 | } | ||
1580 | |||
1581 | if (wl->bss_type == BSS_TYPE_IBSS) { | ||
1582 | /* FIXME: This implements rudimentary ad-hoc support - | ||
1583 | proper templates are on the wish list and notification | ||
1584 | on when they change. This patch will update the templates | ||
1585 | on every call to this function. Also, the firmware will not | ||
1586 | answer to probe-requests as it does not have the proper | ||
1587 | SSID set in the JOIN command. The probe-response template | ||
1588 | is set nevertheless, as the FW will ASSERT without it */ | ||
1589 | struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); | ||
1590 | |||
1591 | if (beacon) { | ||
1592 | struct ieee80211_hdr *hdr; | ||
1593 | ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, | ||
1594 | beacon->data, | ||
1595 | beacon->len); | ||
1596 | |||
1597 | if (ret < 0) { | ||
1598 | dev_kfree_skb(beacon); | ||
1599 | goto out_sleep; | ||
1600 | } | ||
1601 | |||
1602 | hdr = (struct ieee80211_hdr *) beacon->data; | ||
1603 | hdr->frame_control = cpu_to_le16( | ||
1604 | IEEE80211_FTYPE_MGMT | | ||
1605 | IEEE80211_STYPE_PROBE_RESP); | ||
1606 | |||
1607 | ret = wl1271_cmd_template_set(wl, | ||
1608 | CMD_TEMPL_PROBE_RESPONSE, | ||
1609 | beacon->data, | ||
1610 | beacon->len); | ||
1611 | dev_kfree_skb(beacon); | ||
1612 | if (ret < 0) | ||
1613 | goto out_sleep; | ||
1614 | } | ||
1615 | } | ||
1616 | |||
1476 | if (changed & BSS_CHANGED_ASSOC) { | 1617 | if (changed & BSS_CHANGED_ASSOC) { |
1477 | if (bss_conf->assoc) { | 1618 | if (bss_conf->assoc) { |
1478 | wl->aid = bss_conf->aid; | 1619 | wl->aid = bss_conf->aid; |
1620 | set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
1479 | 1621 | ||
1480 | /* | 1622 | /* |
1481 | * with wl1271, we don't need to update the | 1623 | * with wl1271, we don't need to update the |
@@ -1492,7 +1634,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1492 | goto out_sleep; | 1634 | goto out_sleep; |
1493 | 1635 | ||
1494 | /* If we want to go in PSM but we're not there yet */ | 1636 | /* If we want to go in PSM but we're not there yet */ |
1495 | if (wl->psm_requested && !wl->psm) { | 1637 | if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) && |
1638 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1496 | mode = STATION_POWER_SAVE_MODE; | 1639 | mode = STATION_POWER_SAVE_MODE; |
1497 | ret = wl1271_ps_set_mode(wl, mode); | 1640 | ret = wl1271_ps_set_mode(wl, mode); |
1498 | if (ret < 0) | 1641 | if (ret < 0) |
@@ -1500,7 +1643,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1500 | } | 1643 | } |
1501 | } else { | 1644 | } else { |
1502 | /* use defaults when not associated */ | 1645 | /* use defaults when not associated */ |
1503 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1646 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); |
1504 | wl->aid = 0; | 1647 | wl->aid = 0; |
1505 | } | 1648 | } |
1506 | 1649 | ||
@@ -1535,17 +1678,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1535 | } | 1678 | } |
1536 | } | 1679 | } |
1537 | 1680 | ||
1538 | if (changed & BSS_CHANGED_BASIC_RATES) { | ||
1539 | wl->basic_rate_set = wl1271_enabled_rates_get( | ||
1540 | wl, bss_conf->basic_rates); | ||
1541 | |||
1542 | ret = wl1271_acx_rate_policies(wl, wl->basic_rate_set); | ||
1543 | if (ret < 0) { | ||
1544 | wl1271_warning("Set rate policies failed %d", ret); | ||
1545 | goto out_sleep; | ||
1546 | } | ||
1547 | } | ||
1548 | |||
1549 | out_sleep: | 1681 | out_sleep: |
1550 | wl1271_ps_elp_sleep(wl); | 1682 | wl1271_ps_elp_sleep(wl); |
1551 | 1683 | ||
@@ -1599,19 +1731,19 @@ static struct ieee80211_rate wl1271_rates[] = { | |||
1599 | 1731 | ||
1600 | /* can't be const, mac80211 writes to this */ | 1732 | /* can't be const, mac80211 writes to this */ |
1601 | static struct ieee80211_channel wl1271_channels[] = { | 1733 | static struct ieee80211_channel wl1271_channels[] = { |
1602 | { .hw_value = 1, .center_freq = 2412}, | 1734 | { .hw_value = 1, .center_freq = 2412, .max_power = 25 }, |
1603 | { .hw_value = 2, .center_freq = 2417}, | 1735 | { .hw_value = 2, .center_freq = 2417, .max_power = 25 }, |
1604 | { .hw_value = 3, .center_freq = 2422}, | 1736 | { .hw_value = 3, .center_freq = 2422, .max_power = 25 }, |
1605 | { .hw_value = 4, .center_freq = 2427}, | 1737 | { .hw_value = 4, .center_freq = 2427, .max_power = 25 }, |
1606 | { .hw_value = 5, .center_freq = 2432}, | 1738 | { .hw_value = 5, .center_freq = 2432, .max_power = 25 }, |
1607 | { .hw_value = 6, .center_freq = 2437}, | 1739 | { .hw_value = 6, .center_freq = 2437, .max_power = 25 }, |
1608 | { .hw_value = 7, .center_freq = 2442}, | 1740 | { .hw_value = 7, .center_freq = 2442, .max_power = 25 }, |
1609 | { .hw_value = 8, .center_freq = 2447}, | 1741 | { .hw_value = 8, .center_freq = 2447, .max_power = 25 }, |
1610 | { .hw_value = 9, .center_freq = 2452}, | 1742 | { .hw_value = 9, .center_freq = 2452, .max_power = 25 }, |
1611 | { .hw_value = 10, .center_freq = 2457}, | 1743 | { .hw_value = 10, .center_freq = 2457, .max_power = 25 }, |
1612 | { .hw_value = 11, .center_freq = 2462}, | 1744 | { .hw_value = 11, .center_freq = 2462, .max_power = 25 }, |
1613 | { .hw_value = 12, .center_freq = 2467}, | 1745 | { .hw_value = 12, .center_freq = 2467, .max_power = 25 }, |
1614 | { .hw_value = 13, .center_freq = 2472}, | 1746 | { .hw_value = 13, .center_freq = 2472, .max_power = 25 }, |
1615 | }; | 1747 | }; |
1616 | 1748 | ||
1617 | /* can't be const, mac80211 writes to this */ | 1749 | /* can't be const, mac80211 writes to this */ |
@@ -1757,7 +1889,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) | |||
1757 | IEEE80211_HW_BEACON_FILTER | | 1889 | IEEE80211_HW_BEACON_FILTER | |
1758 | IEEE80211_HW_SUPPORTS_PS; | 1890 | IEEE80211_HW_SUPPORTS_PS; |
1759 | 1891 | ||
1760 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1892 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1893 | BIT(NL80211_IFTYPE_ADHOC); | ||
1761 | wl->hw->wiphy->max_scan_ssids = 1; | 1894 | wl->hw->wiphy->max_scan_ssids = 1; |
1762 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; | 1895 | wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; |
1763 | 1896 | ||
@@ -1818,21 +1951,18 @@ static int __devinit wl1271_probe(struct spi_device *spi) | |||
1818 | 1951 | ||
1819 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); | 1952 | INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work); |
1820 | wl->channel = WL1271_DEFAULT_CHANNEL; | 1953 | wl->channel = WL1271_DEFAULT_CHANNEL; |
1821 | wl->scanning = false; | ||
1822 | wl->default_key = 0; | 1954 | wl->default_key = 0; |
1823 | wl->rx_counter = 0; | 1955 | wl->rx_counter = 0; |
1824 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; | 1956 | wl->rx_config = WL1271_DEFAULT_RX_CONFIG; |
1825 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; | 1957 | wl->rx_filter = WL1271_DEFAULT_RX_FILTER; |
1826 | wl->elp = false; | ||
1827 | wl->psm = 0; | ||
1828 | wl->psm_requested = false; | ||
1829 | wl->psm_entry_retry = 0; | 1958 | wl->psm_entry_retry = 0; |
1830 | wl->tx_queue_stopped = false; | ||
1831 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; | 1959 | wl->power_level = WL1271_DEFAULT_POWER_LEVEL; |
1832 | wl->basic_rate_set = WL1271_DEFAULT_BASIC_RATE_SET; | 1960 | wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; |
1961 | wl->rate_set = CONF_TX_RATE_MASK_BASIC; | ||
1962 | wl->sta_rate_set = 0; | ||
1833 | wl->band = IEEE80211_BAND_2GHZ; | 1963 | wl->band = IEEE80211_BAND_2GHZ; |
1834 | wl->vif = NULL; | 1964 | wl->vif = NULL; |
1835 | wl->joined = false; | 1965 | wl->flags = 0; |
1836 | 1966 | ||
1837 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 1967 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
1838 | wl->tx_frames[i] = NULL; | 1968 | wl->tx_frames[i] = NULL; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c index 507cd91d7eed..e407790f6771 100644 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ b/drivers/net/wireless/wl12xx/wl1271_ps.c | |||
@@ -39,12 +39,13 @@ void wl1271_elp_work(struct work_struct *work) | |||
39 | 39 | ||
40 | mutex_lock(&wl->mutex); | 40 | mutex_lock(&wl->mutex); |
41 | 41 | ||
42 | if (wl->elp || !wl->psm) | 42 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
43 | !test_bit(WL1271_FLAG_PSM, &wl->flags)) | ||
43 | goto out; | 44 | goto out; |
44 | 45 | ||
45 | wl1271_debug(DEBUG_PSM, "chip to elp"); | 46 | wl1271_debug(DEBUG_PSM, "chip to elp"); |
46 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 47 | wl1271_raw_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
47 | wl->elp = true; | 48 | set_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
48 | 49 | ||
49 | out: | 50 | out: |
50 | mutex_unlock(&wl->mutex); | 51 | mutex_unlock(&wl->mutex); |
@@ -55,7 +56,7 @@ out: | |||
55 | /* Routines to toggle sleep mode while in ELP */ | 56 | /* Routines to toggle sleep mode while in ELP */ |
56 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 57 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
57 | { | 58 | { |
58 | if (wl->psm) { | 59 | if (test_bit(WL1271_FLAG_PSM, &wl->flags)) { |
59 | cancel_delayed_work(&wl->elp_work); | 60 | cancel_delayed_work(&wl->elp_work); |
60 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 61 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, |
61 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 62 | msecs_to_jiffies(ELP_ENTRY_DELAY)); |
@@ -70,7 +71,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
70 | u32 start_time = jiffies; | 71 | u32 start_time = jiffies; |
71 | bool pending = false; | 72 | bool pending = false; |
72 | 73 | ||
73 | if (!wl->elp) | 74 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
74 | return 0; | 75 | return 0; |
75 | 76 | ||
76 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); | 77 | wl1271_debug(DEBUG_PSM, "waking up chip from elp"); |
@@ -101,7 +102,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) | |||
101 | } | 102 | } |
102 | } | 103 | } |
103 | 104 | ||
104 | wl->elp = false; | 105 | clear_bit(WL1271_FLAG_IN_ELP, &wl->flags); |
105 | 106 | ||
106 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", | 107 | wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", |
107 | jiffies_to_msecs(jiffies - start_time)); | 108 | jiffies_to_msecs(jiffies - start_time)); |
@@ -143,7 +144,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
143 | if (ret < 0) | 144 | if (ret < 0) |
144 | return ret; | 145 | return ret; |
145 | 146 | ||
146 | wl->psm = 1; | 147 | set_bit(WL1271_FLAG_PSM, &wl->flags); |
147 | break; | 148 | break; |
148 | case STATION_ACTIVE_MODE: | 149 | case STATION_ACTIVE_MODE: |
149 | default: | 150 | default: |
@@ -166,7 +167,7 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) | |||
166 | if (ret < 0) | 167 | if (ret < 0) |
167 | return ret; | 168 | return ret; |
168 | 169 | ||
169 | wl->psm = 0; | 170 | clear_bit(WL1271_FLAG_PSM, &wl->flags); |
170 | break; | 171 | break; |
171 | } | 172 | } |
172 | 173 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 00af065c77c2..a288cc317d7b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -121,6 +121,11 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | |||
121 | pad = pad - skb->len; | 121 | pad = pad - skb->len; |
122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; | 122 | tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; |
123 | 123 | ||
124 | /* if the packets are destined for AP (have a STA entry) send them | ||
125 | with AP rate policies, otherwise use default basic rates */ | ||
126 | if (control->control.sta) | ||
127 | tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY; | ||
128 | |||
124 | desc->tx_attr = cpu_to_le16(tx_attr); | 129 | desc->tx_attr = cpu_to_le16(tx_attr); |
125 | 130 | ||
126 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); | 131 | wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); |
@@ -214,18 +219,50 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
214 | return ret; | 219 | return ret; |
215 | } | 220 | } |
216 | 221 | ||
222 | static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) | ||
223 | { | ||
224 | struct ieee80211_supported_band *band; | ||
225 | u32 enabled_rates = 0; | ||
226 | int bit; | ||
227 | |||
228 | band = wl->hw->wiphy->bands[wl->band]; | ||
229 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
230 | if (rate_set & 0x1) | ||
231 | enabled_rates |= band->bitrates[bit].hw_value; | ||
232 | rate_set >>= 1; | ||
233 | } | ||
234 | |||
235 | return enabled_rates; | ||
236 | } | ||
237 | |||
217 | void wl1271_tx_work(struct work_struct *work) | 238 | void wl1271_tx_work(struct work_struct *work) |
218 | { | 239 | { |
219 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); | 240 | struct wl1271 *wl = container_of(work, struct wl1271, tx_work); |
220 | struct sk_buff *skb; | 241 | struct sk_buff *skb; |
221 | bool woken_up = false; | 242 | bool woken_up = false; |
243 | u32 sta_rates = 0; | ||
222 | int ret; | 244 | int ret; |
223 | 245 | ||
246 | /* check if the rates supported by the AP have changed */ | ||
247 | if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED, | ||
248 | &wl->flags))) { | ||
249 | unsigned long flags; | ||
250 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
251 | sta_rates = wl->sta_rate_set; | ||
252 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
253 | } | ||
254 | |||
224 | mutex_lock(&wl->mutex); | 255 | mutex_lock(&wl->mutex); |
225 | 256 | ||
226 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 257 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
227 | goto out; | 258 | goto out; |
228 | 259 | ||
260 | /* if rates have changed, re-configure the rate policy */ | ||
261 | if (unlikely(sta_rates)) { | ||
262 | wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); | ||
263 | wl1271_acx_rate_policies(wl); | ||
264 | } | ||
265 | |||
229 | while ((skb = skb_dequeue(&wl->tx_queue))) { | 266 | while ((skb = skb_dequeue(&wl->tx_queue))) { |
230 | if (!woken_up) { | 267 | if (!woken_up) { |
231 | ret = wl1271_ps_elp_wakeup(wl, false); | 268 | ret = wl1271_ps_elp_wakeup(wl, false); |
@@ -240,18 +277,18 @@ void wl1271_tx_work(struct work_struct *work) | |||
240 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " | 277 | wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " |
241 | "stop queues"); | 278 | "stop queues"); |
242 | ieee80211_stop_queues(wl->hw); | 279 | ieee80211_stop_queues(wl->hw); |
243 | wl->tx_queue_stopped = true; | 280 | set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); |
244 | skb_queue_head(&wl->tx_queue, skb); | 281 | skb_queue_head(&wl->tx_queue, skb); |
245 | goto out; | 282 | goto out; |
246 | } else if (ret < 0) { | 283 | } else if (ret < 0) { |
247 | dev_kfree_skb(skb); | 284 | dev_kfree_skb(skb); |
248 | goto out; | 285 | goto out; |
249 | } else if (wl->tx_queue_stopped) { | 286 | } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, |
287 | &wl->flags)) { | ||
250 | /* firmware buffer has space, restart queues */ | 288 | /* firmware buffer has space, restart queues */ |
251 | wl1271_debug(DEBUG_TX, | 289 | wl1271_debug(DEBUG_TX, |
252 | "complete_packet: waking queues"); | 290 | "complete_packet: waking queues"); |
253 | ieee80211_wake_queues(wl->hw); | 291 | ieee80211_wake_queues(wl->hw); |
254 | wl->tx_queue_stopped = false; | ||
255 | } | 292 | } |
256 | } | 293 | } |
257 | 294 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index dfa1b9bc22c8..7ca95c414fa8 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -1325,151 +1325,11 @@ int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) | |||
1325 | return r; | 1325 | return r; |
1326 | } | 1326 | } |
1327 | 1327 | ||
1328 | static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size) | ||
1329 | { | ||
1330 | static const u16 constants[] = { | ||
1331 | 715, 655, 585, 540, 470, 410, 360, 315, | ||
1332 | 270, 235, 205, 175, 150, 125, 105, 85, | ||
1333 | 65, 50, 40, 25, 15 | ||
1334 | }; | ||
1335 | |||
1336 | int i; | ||
1337 | u32 x; | ||
1338 | |||
1339 | /* It seems that their quality parameter is somehow per signal | ||
1340 | * and is now transferred per bit. | ||
1341 | */ | ||
1342 | switch (zd_rate) { | ||
1343 | case ZD_OFDM_RATE_6M: | ||
1344 | case ZD_OFDM_RATE_12M: | ||
1345 | case ZD_OFDM_RATE_24M: | ||
1346 | size *= 2; | ||
1347 | break; | ||
1348 | case ZD_OFDM_RATE_9M: | ||
1349 | case ZD_OFDM_RATE_18M: | ||
1350 | case ZD_OFDM_RATE_36M: | ||
1351 | case ZD_OFDM_RATE_54M: | ||
1352 | size *= 4; | ||
1353 | size /= 3; | ||
1354 | break; | ||
1355 | case ZD_OFDM_RATE_48M: | ||
1356 | size *= 3; | ||
1357 | size /= 2; | ||
1358 | break; | ||
1359 | default: | ||
1360 | return -EINVAL; | ||
1361 | } | ||
1362 | |||
1363 | x = (10000 * status_quality)/size; | ||
1364 | for (i = 0; i < ARRAY_SIZE(constants); i++) { | ||
1365 | if (x > constants[i]) | ||
1366 | break; | ||
1367 | } | ||
1368 | |||
1369 | switch (zd_rate) { | ||
1370 | case ZD_OFDM_RATE_6M: | ||
1371 | case ZD_OFDM_RATE_9M: | ||
1372 | i += 3; | ||
1373 | break; | ||
1374 | case ZD_OFDM_RATE_12M: | ||
1375 | case ZD_OFDM_RATE_18M: | ||
1376 | i += 5; | ||
1377 | break; | ||
1378 | case ZD_OFDM_RATE_24M: | ||
1379 | case ZD_OFDM_RATE_36M: | ||
1380 | i += 9; | ||
1381 | break; | ||
1382 | case ZD_OFDM_RATE_48M: | ||
1383 | case ZD_OFDM_RATE_54M: | ||
1384 | i += 15; | ||
1385 | break; | ||
1386 | default: | ||
1387 | return -EINVAL; | ||
1388 | } | ||
1389 | |||
1390 | return i; | ||
1391 | } | ||
1392 | |||
1393 | static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size) | ||
1394 | { | ||
1395 | int r; | ||
1396 | |||
1397 | r = ofdm_qual_db(status_quality, zd_rate, size); | ||
1398 | ZD_ASSERT(r >= 0); | ||
1399 | if (r < 0) | ||
1400 | r = 0; | ||
1401 | |||
1402 | r = (r * 100)/29; | ||
1403 | return r <= 100 ? r : 100; | ||
1404 | } | ||
1405 | |||
1406 | static unsigned int log10times100(unsigned int x) | ||
1407 | { | ||
1408 | static const u8 log10[] = { | ||
1409 | 0, | ||
1410 | 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, | ||
1411 | 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, | ||
1412 | 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, | ||
1413 | 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, | ||
1414 | 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, | ||
1415 | 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, | ||
1416 | 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, | ||
1417 | 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, | ||
1418 | 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, | ||
1419 | 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, | ||
1420 | 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, | ||
1421 | 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, | ||
1422 | 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, | ||
1423 | 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, | ||
1424 | 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, | ||
1425 | 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, | ||
1426 | 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, | ||
1427 | 223, 223, 223, 224, 224, 224, 224, | ||
1428 | }; | ||
1429 | |||
1430 | return x < ARRAY_SIZE(log10) ? log10[x] : 225; | ||
1431 | } | ||
1432 | |||
1433 | enum { | ||
1434 | MAX_CCK_EVM_DB = 45, | ||
1435 | }; | ||
1436 | |||
1437 | static int cck_evm_db(u8 status_quality) | ||
1438 | { | ||
1439 | return (20 * log10times100(status_quality)) / 100; | ||
1440 | } | ||
1441 | |||
1442 | static int cck_snr_db(u8 status_quality) | ||
1443 | { | ||
1444 | int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); | ||
1445 | ZD_ASSERT(r >= 0); | ||
1446 | return r; | ||
1447 | } | ||
1448 | |||
1449 | static int cck_qual_percent(u8 status_quality) | ||
1450 | { | ||
1451 | int r; | ||
1452 | |||
1453 | r = cck_snr_db(status_quality); | ||
1454 | r = (100*r)/17; | ||
1455 | return r <= 100 ? r : 100; | ||
1456 | } | ||
1457 | |||
1458 | static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame) | 1328 | static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame) |
1459 | { | 1329 | { |
1460 | return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame); | 1330 | return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame); |
1461 | } | 1331 | } |
1462 | 1332 | ||
1463 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
1464 | const struct rx_status *status) | ||
1465 | { | ||
1466 | return (status->frame_status&ZD_RX_OFDM) ? | ||
1467 | ofdm_qual_percent(status->signal_quality_ofdm, | ||
1468 | zd_rate_from_ofdm_plcp_header(rx_frame), | ||
1469 | size) : | ||
1470 | cck_qual_percent(status->signal_quality_cck); | ||
1471 | } | ||
1472 | |||
1473 | /** | 1333 | /** |
1474 | * zd_rx_rate - report zd-rate | 1334 | * zd_rx_rate - report zd-rate |
1475 | * @rx_frame - received frame | 1335 | * @rx_frame - received frame |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h index 9fd8f3508d66..f8bbf7d302ae 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ b/drivers/net/wireless/zd1211rw/zd_chip.h | |||
@@ -929,9 +929,6 @@ static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) | |||
929 | 929 | ||
930 | struct rx_status; | 930 | struct rx_status; |
931 | 931 | ||
932 | u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, | ||
933 | const struct rx_status *status); | ||
934 | |||
935 | u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status); | 932 | u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status); |
936 | 933 | ||
937 | struct zd_mc_hash { | 934 | struct zd_mc_hash { |
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index cf51e8f8174b..709fe5e06f73 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -828,9 +828,6 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
828 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; | 828 | stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; |
829 | stats.band = IEEE80211_BAND_2GHZ; | 829 | stats.band = IEEE80211_BAND_2GHZ; |
830 | stats.signal = status->signal_strength; | 830 | stats.signal = status->signal_strength; |
831 | stats.qual = zd_rx_qual_percent(buffer, | ||
832 | length - sizeof(struct rx_status), | ||
833 | status); | ||
834 | 831 | ||
835 | rate = zd_rx_rate(buffer, status); | 832 | rate = zd_rx_rate(buffer, status); |
836 | 833 | ||
@@ -872,7 +869,7 @@ int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) | |||
872 | } | 869 | } |
873 | 870 | ||
874 | static int zd_op_add_interface(struct ieee80211_hw *hw, | 871 | static int zd_op_add_interface(struct ieee80211_hw *hw, |
875 | struct ieee80211_if_init_conf *conf) | 872 | struct ieee80211_vif *vif) |
876 | { | 873 | { |
877 | struct zd_mac *mac = zd_hw_mac(hw); | 874 | struct zd_mac *mac = zd_hw_mac(hw); |
878 | 875 | ||
@@ -880,22 +877,22 @@ static int zd_op_add_interface(struct ieee80211_hw *hw, | |||
880 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) | 877 | if (mac->type != NL80211_IFTYPE_UNSPECIFIED) |
881 | return -EOPNOTSUPP; | 878 | return -EOPNOTSUPP; |
882 | 879 | ||
883 | switch (conf->type) { | 880 | switch (vif->type) { |
884 | case NL80211_IFTYPE_MONITOR: | 881 | case NL80211_IFTYPE_MONITOR: |
885 | case NL80211_IFTYPE_MESH_POINT: | 882 | case NL80211_IFTYPE_MESH_POINT: |
886 | case NL80211_IFTYPE_STATION: | 883 | case NL80211_IFTYPE_STATION: |
887 | case NL80211_IFTYPE_ADHOC: | 884 | case NL80211_IFTYPE_ADHOC: |
888 | mac->type = conf->type; | 885 | mac->type = vif->type; |
889 | break; | 886 | break; |
890 | default: | 887 | default: |
891 | return -EOPNOTSUPP; | 888 | return -EOPNOTSUPP; |
892 | } | 889 | } |
893 | 890 | ||
894 | return zd_write_mac_addr(&mac->chip, conf->mac_addr); | 891 | return zd_write_mac_addr(&mac->chip, vif->addr); |
895 | } | 892 | } |
896 | 893 | ||
897 | static void zd_op_remove_interface(struct ieee80211_hw *hw, | 894 | static void zd_op_remove_interface(struct ieee80211_hw *hw, |
898 | struct ieee80211_if_init_conf *conf) | 895 | struct ieee80211_vif *vif) |
899 | { | 896 | { |
900 | struct zd_mac *mac = zd_hw_mac(hw); | 897 | struct zd_mac *mac = zd_hw_mac(hw); |
901 | mac->type = NL80211_IFTYPE_UNSPECIFIED; | 898 | mac->type = NL80211_IFTYPE_UNSPECIFIED; |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index d62edc7df3ae..aeea282bd2fe 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1085,12 +1085,12 @@ enum ieee80211_eid { | |||
1085 | WLAN_EID_TIM = 5, | 1085 | WLAN_EID_TIM = 5, |
1086 | WLAN_EID_IBSS_PARAMS = 6, | 1086 | WLAN_EID_IBSS_PARAMS = 6, |
1087 | WLAN_EID_CHALLENGE = 16, | 1087 | WLAN_EID_CHALLENGE = 16, |
1088 | /* 802.11d */ | 1088 | |
1089 | WLAN_EID_COUNTRY = 7, | 1089 | WLAN_EID_COUNTRY = 7, |
1090 | WLAN_EID_HP_PARAMS = 8, | 1090 | WLAN_EID_HP_PARAMS = 8, |
1091 | WLAN_EID_HP_TABLE = 9, | 1091 | WLAN_EID_HP_TABLE = 9, |
1092 | WLAN_EID_REQUEST = 10, | 1092 | WLAN_EID_REQUEST = 10, |
1093 | /* 802.11e */ | 1093 | |
1094 | WLAN_EID_QBSS_LOAD = 11, | 1094 | WLAN_EID_QBSS_LOAD = 11, |
1095 | WLAN_EID_EDCA_PARAM_SET = 12, | 1095 | WLAN_EID_EDCA_PARAM_SET = 12, |
1096 | WLAN_EID_TSPEC = 13, | 1096 | WLAN_EID_TSPEC = 13, |
@@ -1113,7 +1113,7 @@ enum ieee80211_eid { | |||
1113 | WLAN_EID_PREP = 69, | 1113 | WLAN_EID_PREP = 69, |
1114 | WLAN_EID_PERR = 70, | 1114 | WLAN_EID_PERR = 70, |
1115 | WLAN_EID_RANN = 49, /* compatible with FreeBSD */ | 1115 | WLAN_EID_RANN = 49, /* compatible with FreeBSD */ |
1116 | /* 802.11h */ | 1116 | |
1117 | WLAN_EID_PWR_CONSTRAINT = 32, | 1117 | WLAN_EID_PWR_CONSTRAINT = 32, |
1118 | WLAN_EID_PWR_CAPABILITY = 33, | 1118 | WLAN_EID_PWR_CAPABILITY = 33, |
1119 | WLAN_EID_TPC_REQUEST = 34, | 1119 | WLAN_EID_TPC_REQUEST = 34, |
@@ -1124,20 +1124,41 @@ enum ieee80211_eid { | |||
1124 | WLAN_EID_MEASURE_REPORT = 39, | 1124 | WLAN_EID_MEASURE_REPORT = 39, |
1125 | WLAN_EID_QUIET = 40, | 1125 | WLAN_EID_QUIET = 40, |
1126 | WLAN_EID_IBSS_DFS = 41, | 1126 | WLAN_EID_IBSS_DFS = 41, |
1127 | /* 802.11g */ | 1127 | |
1128 | WLAN_EID_ERP_INFO = 42, | 1128 | WLAN_EID_ERP_INFO = 42, |
1129 | WLAN_EID_EXT_SUPP_RATES = 50, | 1129 | WLAN_EID_EXT_SUPP_RATES = 50, |
1130 | /* 802.11n */ | 1130 | |
1131 | WLAN_EID_HT_CAPABILITY = 45, | 1131 | WLAN_EID_HT_CAPABILITY = 45, |
1132 | WLAN_EID_HT_INFORMATION = 61, | 1132 | WLAN_EID_HT_INFORMATION = 61, |
1133 | /* 802.11i */ | 1133 | |
1134 | WLAN_EID_RSN = 48, | 1134 | WLAN_EID_RSN = 48, |
1135 | WLAN_EID_TIMEOUT_INTERVAL = 56, | 1135 | WLAN_EID_MMIE = 76, |
1136 | WLAN_EID_MMIE = 76 /* 802.11w */, | ||
1137 | WLAN_EID_WPA = 221, | 1136 | WLAN_EID_WPA = 221, |
1138 | WLAN_EID_GENERIC = 221, | 1137 | WLAN_EID_GENERIC = 221, |
1139 | WLAN_EID_VENDOR_SPECIFIC = 221, | 1138 | WLAN_EID_VENDOR_SPECIFIC = 221, |
1140 | WLAN_EID_QOS_PARAMETER = 222 | 1139 | WLAN_EID_QOS_PARAMETER = 222, |
1140 | |||
1141 | WLAN_EID_AP_CHAN_REPORT = 51, | ||
1142 | WLAN_EID_NEIGHBOR_REPORT = 52, | ||
1143 | WLAN_EID_RCPI = 53, | ||
1144 | WLAN_EID_BSS_AVG_ACCESS_DELAY = 63, | ||
1145 | WLAN_EID_ANTENNA_INFO = 64, | ||
1146 | WLAN_EID_RSNI = 65, | ||
1147 | WLAN_EID_MEASUREMENT_PILOT_TX_INFO = 66, | ||
1148 | WLAN_EID_BSS_AVAILABLE_CAPACITY = 67, | ||
1149 | WLAN_EID_BSS_AC_ACCESS_DELAY = 68, | ||
1150 | WLAN_EID_RRM_ENABLED_CAPABILITIES = 70, | ||
1151 | WLAN_EID_MULTIPLE_BSSID = 71, | ||
1152 | |||
1153 | WLAN_EID_MOBILITY_DOMAIN = 54, | ||
1154 | WLAN_EID_FAST_BSS_TRANSITION = 55, | ||
1155 | WLAN_EID_TIMEOUT_INTERVAL = 56, | ||
1156 | WLAN_EID_RIC_DATA = 57, | ||
1157 | WLAN_EID_RIC_DESCRIPTOR = 75, | ||
1158 | |||
1159 | WLAN_EID_DSE_REGISTERED_LOCATION = 58, | ||
1160 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, | ||
1161 | WLAN_EID_EXT_CHANSWITCH_ANN = 60, | ||
1141 | }; | 1162 | }; |
1142 | 1163 | ||
1143 | /* Action category code */ | 1164 | /* Action category code */ |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index da8ea2e19273..2bfbe88837ef 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -270,6 +270,31 @@ | |||
270 | * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices | 270 | * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices |
271 | * associated with this wiphy must be down and will follow. | 271 | * associated with this wiphy must be down and will follow. |
272 | * | 272 | * |
273 | * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified | ||
274 | * channel for the specified amount of time. This can be used to do | ||
275 | * off-channel operations like transmit a Public Action frame and wait for | ||
276 | * a response while being associated to an AP on another channel. | ||
277 | * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify which | ||
278 | * radio is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the | ||
279 | * frequency for the operation and %NL80211_ATTR_WIPHY_CHANNEL_TYPE may be | ||
280 | * optionally used to specify additional channel parameters. | ||
281 | * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds | ||
282 | * to remain on the channel. This command is also used as an event to | ||
283 | * notify when the requested duration starts (it may take a while for the | ||
284 | * driver to schedule this time due to other concurrent needs for the | ||
285 | * radio). | ||
286 | * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) | ||
287 | * that will be included with any events pertaining to this request; | ||
288 | * the cookie is also used to cancel the request. | ||
289 | * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a | ||
290 | * pending remain-on-channel duration if the desired operation has been | ||
291 | * completed prior to expiration of the originally requested duration. | ||
292 | * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the | ||
293 | * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to | ||
294 | * uniquely identify the request. | ||
295 | * This command is also used as an event to notify when a requested | ||
296 | * remain-on-channel duration has expired. | ||
297 | * | ||
273 | * @NL80211_CMD_MAX: highest used command number | 298 | * @NL80211_CMD_MAX: highest used command number |
274 | * @__NL80211_CMD_AFTER_LAST: internal use | 299 | * @__NL80211_CMD_AFTER_LAST: internal use |
275 | */ | 300 | */ |
@@ -353,6 +378,9 @@ enum nl80211_commands { | |||
353 | NL80211_CMD_DEL_PMKSA, | 378 | NL80211_CMD_DEL_PMKSA, |
354 | NL80211_CMD_FLUSH_PMKSA, | 379 | NL80211_CMD_FLUSH_PMKSA, |
355 | 380 | ||
381 | NL80211_CMD_REMAIN_ON_CHANNEL, | ||
382 | NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | ||
383 | |||
356 | /* add new commands above here */ | 384 | /* add new commands above here */ |
357 | 385 | ||
358 | /* used to define NL80211_CMD_MAX below */ | 386 | /* used to define NL80211_CMD_MAX below */ |
@@ -606,6 +634,10 @@ enum nl80211_commands { | |||
606 | * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can | 634 | * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can |
607 | * cache, a wiphy attribute. | 635 | * cache, a wiphy attribute. |
608 | * | 636 | * |
637 | * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32. | ||
638 | * | ||
639 | * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. | ||
640 | * | ||
609 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 641 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
610 | * @__NL80211_ATTR_AFTER_LAST: internal use | 642 | * @__NL80211_ATTR_AFTER_LAST: internal use |
611 | */ | 643 | */ |
@@ -743,6 +775,10 @@ enum nl80211_attrs { | |||
743 | NL80211_ATTR_PMKID, | 775 | NL80211_ATTR_PMKID, |
744 | NL80211_ATTR_MAX_NUM_PMKIDS, | 776 | NL80211_ATTR_MAX_NUM_PMKIDS, |
745 | 777 | ||
778 | NL80211_ATTR_DURATION, | ||
779 | |||
780 | NL80211_ATTR_COOKIE, | ||
781 | |||
746 | /* add attributes here, update the policy in nl80211.c */ | 782 | /* add attributes here, update the policy in nl80211.c */ |
747 | 783 | ||
748 | __NL80211_ATTR_AFTER_LAST, | 784 | __NL80211_ATTR_AFTER_LAST, |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 542a477a94da..add79930f47d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -988,6 +988,15 @@ struct cfg80211_pmksa { | |||
988 | * | 988 | * |
989 | * @dump_survey: get site survey information. | 989 | * @dump_survey: get site survey information. |
990 | * | 990 | * |
991 | * @remain_on_channel: Request the driver to remain awake on the specified | ||
992 | * channel for the specified duration to complete an off-channel | ||
993 | * operation (e.g., public action frame exchange). When the driver is | ||
994 | * ready on the requested channel, it must indicate this with an event | ||
995 | * notification by calling cfg80211_ready_on_channel(). | ||
996 | * @cancel_remain_on_channel: Cancel an on-going remain-on-channel operation. | ||
997 | * This allows the operation to be terminated prior to timeout based on | ||
998 | * the duration value. | ||
999 | * | ||
991 | * @testmode_cmd: run a test mode command | 1000 | * @testmode_cmd: run a test mode command |
992 | * | 1001 | * |
993 | * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac | 1002 | * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac |
@@ -1123,6 +1132,16 @@ struct cfg80211_ops { | |||
1123 | struct cfg80211_pmksa *pmksa); | 1132 | struct cfg80211_pmksa *pmksa); |
1124 | int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev); | 1133 | int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev); |
1125 | 1134 | ||
1135 | int (*remain_on_channel)(struct wiphy *wiphy, | ||
1136 | struct net_device *dev, | ||
1137 | struct ieee80211_channel *chan, | ||
1138 | enum nl80211_channel_type channel_type, | ||
1139 | unsigned int duration, | ||
1140 | u64 *cookie); | ||
1141 | int (*cancel_remain_on_channel)(struct wiphy *wiphy, | ||
1142 | struct net_device *dev, | ||
1143 | u64 cookie); | ||
1144 | |||
1126 | /* some temporary stuff to finish wext */ | 1145 | /* some temporary stuff to finish wext */ |
1127 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, | 1146 | int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, |
1128 | bool enabled, int timeout); | 1147 | bool enabled, int timeout); |
@@ -2147,5 +2166,45 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid, | |||
2147 | void cfg80211_disconnected(struct net_device *dev, u16 reason, | 2166 | void cfg80211_disconnected(struct net_device *dev, u16 reason, |
2148 | u8 *ie, size_t ie_len, gfp_t gfp); | 2167 | u8 *ie, size_t ie_len, gfp_t gfp); |
2149 | 2168 | ||
2169 | /** | ||
2170 | * cfg80211_ready_on_channel - notification of remain_on_channel start | ||
2171 | * @dev: network device | ||
2172 | * @cookie: the request cookie | ||
2173 | * @chan: The current channel (from remain_on_channel request) | ||
2174 | * @channel_type: Channel type | ||
2175 | * @duration: Duration in milliseconds that the driver intents to remain on the | ||
2176 | * channel | ||
2177 | * @gfp: allocation flags | ||
2178 | */ | ||
2179 | void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie, | ||
2180 | struct ieee80211_channel *chan, | ||
2181 | enum nl80211_channel_type channel_type, | ||
2182 | unsigned int duration, gfp_t gfp); | ||
2183 | |||
2184 | /** | ||
2185 | * cfg80211_remain_on_channel_expired - remain_on_channel duration expired | ||
2186 | * @dev: network device | ||
2187 | * @cookie: the request cookie | ||
2188 | * @chan: The current channel (from remain_on_channel request) | ||
2189 | * @channel_type: Channel type | ||
2190 | * @gfp: allocation flags | ||
2191 | */ | ||
2192 | void cfg80211_remain_on_channel_expired(struct net_device *dev, | ||
2193 | u64 cookie, | ||
2194 | struct ieee80211_channel *chan, | ||
2195 | enum nl80211_channel_type channel_type, | ||
2196 | gfp_t gfp); | ||
2197 | |||
2198 | |||
2199 | /** | ||
2200 | * cfg80211_new_sta - notify userspace about station | ||
2201 | * | ||
2202 | * @dev: the netdev | ||
2203 | * @mac_addr: the station's address | ||
2204 | * @sinfo: the station information | ||
2205 | * @gfp: allocation flags | ||
2206 | */ | ||
2207 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | ||
2208 | struct station_info *sinfo, gfp_t gfp); | ||
2150 | 2209 | ||
2151 | #endif /* __NET_CFG80211_H */ | 2210 | #endif /* __NET_CFG80211_H */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 494ac69ff477..f073a2a50574 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -547,7 +547,6 @@ enum mac80211_rx_flags { | |||
547 | * unspecified depending on the hardware capabilities flags | 547 | * unspecified depending on the hardware capabilities flags |
548 | * @IEEE80211_HW_SIGNAL_* | 548 | * @IEEE80211_HW_SIGNAL_* |
549 | * @noise: noise when receiving this frame, in dBm. | 549 | * @noise: noise when receiving this frame, in dBm. |
550 | * @qual: overall signal quality indication, in percent (0-100). | ||
551 | * @antenna: antenna used | 550 | * @antenna: antenna used |
552 | * @rate_idx: index of data rate into band's supported rates or MCS index if | 551 | * @rate_idx: index of data rate into band's supported rates or MCS index if |
553 | * HT rates are use (RX_FLAG_HT) | 552 | * HT rates are use (RX_FLAG_HT) |
@@ -559,7 +558,6 @@ struct ieee80211_rx_status { | |||
559 | int freq; | 558 | int freq; |
560 | int signal; | 559 | int signal; |
561 | int noise; | 560 | int noise; |
562 | int __deprecated qual; | ||
563 | int antenna; | 561 | int antenna; |
564 | int rate_idx; | 562 | int rate_idx; |
565 | int flag; | 563 | int flag; |
@@ -702,33 +700,6 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) | |||
702 | } | 700 | } |
703 | 701 | ||
704 | /** | 702 | /** |
705 | * struct ieee80211_if_init_conf - initial configuration of an interface | ||
706 | * | ||
707 | * @vif: pointer to a driver-use per-interface structure. The pointer | ||
708 | * itself is also used for various functions including | ||
709 | * ieee80211_beacon_get() and ieee80211_get_buffered_bc(). | ||
710 | * @type: one of &enum nl80211_iftype constants. Determines the type of | ||
711 | * added/removed interface. | ||
712 | * @mac_addr: pointer to MAC address of the interface. This pointer is valid | ||
713 | * until the interface is removed (i.e. it cannot be used after | ||
714 | * remove_interface() callback was called for this interface). | ||
715 | * | ||
716 | * This structure is used in add_interface() and remove_interface() | ||
717 | * callbacks of &struct ieee80211_hw. | ||
718 | * | ||
719 | * When you allow multiple interfaces to be added to your PHY, take care | ||
720 | * that the hardware can actually handle multiple MAC addresses. However, | ||
721 | * also take care that when there's no interface left with mac_addr != %NULL | ||
722 | * you remove the MAC address from the device to avoid acknowledging packets | ||
723 | * in pure monitor mode. | ||
724 | */ | ||
725 | struct ieee80211_if_init_conf { | ||
726 | enum nl80211_iftype type; | ||
727 | struct ieee80211_vif *vif; | ||
728 | void *mac_addr; | ||
729 | }; | ||
730 | |||
731 | /** | ||
732 | * enum ieee80211_key_alg - key algorithm | 703 | * enum ieee80211_key_alg - key algorithm |
733 | * @ALG_WEP: WEP40 or WEP104 | 704 | * @ALG_WEP: WEP40 or WEP104 |
734 | * @ALG_TKIP: TKIP | 705 | * @ALG_TKIP: TKIP |
@@ -1410,7 +1381,7 @@ enum ieee80211_ampdu_mlme_action { | |||
1410 | * When the device is started it should not have a MAC address | 1381 | * When the device is started it should not have a MAC address |
1411 | * to avoid acknowledging frames before a non-monitor device | 1382 | * to avoid acknowledging frames before a non-monitor device |
1412 | * is added. | 1383 | * is added. |
1413 | * Must be implemented. | 1384 | * Must be implemented and can sleep. |
1414 | * | 1385 | * |
1415 | * @stop: Called after last netdevice attached to the hardware | 1386 | * @stop: Called after last netdevice attached to the hardware |
1416 | * is disabled. This should turn off the hardware (at least | 1387 | * is disabled. This should turn off the hardware (at least |
@@ -1418,7 +1389,7 @@ enum ieee80211_ampdu_mlme_action { | |||
1418 | * May be called right after add_interface if that rejects | 1389 | * May be called right after add_interface if that rejects |
1419 | * an interface. If you added any work onto the mac80211 workqueue | 1390 | * an interface. If you added any work onto the mac80211 workqueue |
1420 | * you should ensure to cancel it on this callback. | 1391 | * you should ensure to cancel it on this callback. |
1421 | * Must be implemented. | 1392 | * Must be implemented and can sleep. |
1422 | * | 1393 | * |
1423 | * @add_interface: Called when a netdevice attached to the hardware is | 1394 | * @add_interface: Called when a netdevice attached to the hardware is |
1424 | * enabled. Because it is not called for monitor mode devices, @start | 1395 | * enabled. Because it is not called for monitor mode devices, @start |
@@ -1428,7 +1399,7 @@ enum ieee80211_ampdu_mlme_action { | |||
1428 | * interface is given in the conf parameter. | 1399 | * interface is given in the conf parameter. |
1429 | * The callback may refuse to add an interface by returning a | 1400 | * The callback may refuse to add an interface by returning a |
1430 | * negative error code (which will be seen in userspace.) | 1401 | * negative error code (which will be seen in userspace.) |
1431 | * Must be implemented. | 1402 | * Must be implemented and can sleep. |
1432 | * | 1403 | * |
1433 | * @remove_interface: Notifies a driver that an interface is going down. | 1404 | * @remove_interface: Notifies a driver that an interface is going down. |
1434 | * The @stop callback is called after this if it is the last interface | 1405 | * The @stop callback is called after this if it is the last interface |
@@ -1437,19 +1408,20 @@ enum ieee80211_ampdu_mlme_action { | |||
1437 | * must be cleared so the device no longer acknowledges packets, | 1408 | * must be cleared so the device no longer acknowledges packets, |
1438 | * the mac_addr member of the conf structure is, however, set to the | 1409 | * the mac_addr member of the conf structure is, however, set to the |
1439 | * MAC address of the device going away. | 1410 | * MAC address of the device going away. |
1440 | * Hence, this callback must be implemented. | 1411 | * Hence, this callback must be implemented. It can sleep. |
1441 | * | 1412 | * |
1442 | * @config: Handler for configuration requests. IEEE 802.11 code calls this | 1413 | * @config: Handler for configuration requests. IEEE 802.11 code calls this |
1443 | * function to change hardware configuration, e.g., channel. | 1414 | * function to change hardware configuration, e.g., channel. |
1444 | * This function should never fail but returns a negative error code | 1415 | * This function should never fail but returns a negative error code |
1445 | * if it does. | 1416 | * if it does. The callback can sleep. |
1446 | * | 1417 | * |
1447 | * @bss_info_changed: Handler for configuration requests related to BSS | 1418 | * @bss_info_changed: Handler for configuration requests related to BSS |
1448 | * parameters that may vary during BSS's lifespan, and may affect low | 1419 | * parameters that may vary during BSS's lifespan, and may affect low |
1449 | * level driver (e.g. assoc/disassoc status, erp parameters). | 1420 | * level driver (e.g. assoc/disassoc status, erp parameters). |
1450 | * This function should not be used if no BSS has been set, unless | 1421 | * This function should not be used if no BSS has been set, unless |
1451 | * for association indication. The @changed parameter indicates which | 1422 | * for association indication. The @changed parameter indicates which |
1452 | * of the bss parameters has changed when a call is made. | 1423 | * of the bss parameters has changed when a call is made. The callback |
1424 | * can sleep. | ||
1453 | * | 1425 | * |
1454 | * @prepare_multicast: Prepare for multicast filter configuration. | 1426 | * @prepare_multicast: Prepare for multicast filter configuration. |
1455 | * This callback is optional, and its return value is passed | 1427 | * This callback is optional, and its return value is passed |
@@ -1457,20 +1429,22 @@ enum ieee80211_ampdu_mlme_action { | |||
1457 | * | 1429 | * |
1458 | * @configure_filter: Configure the device's RX filter. | 1430 | * @configure_filter: Configure the device's RX filter. |
1459 | * See the section "Frame filtering" for more information. | 1431 | * See the section "Frame filtering" for more information. |
1460 | * This callback must be implemented. | 1432 | * This callback must be implemented and can sleep. |
1461 | * | 1433 | * |
1462 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 1434 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
1463 | * must be set or cleared for a given STA. Must be atomic. | 1435 | * must be set or cleared for a given STA. Must be atomic. |
1464 | * | 1436 | * |
1465 | * @set_key: See the section "Hardware crypto acceleration" | 1437 | * @set_key: See the section "Hardware crypto acceleration" |
1466 | * This callback can sleep, and is only called between add_interface | 1438 | * This callback is only called between add_interface and |
1467 | * and remove_interface calls, i.e. while the given virtual interface | 1439 | * remove_interface calls, i.e. while the given virtual interface |
1468 | * is enabled. | 1440 | * is enabled. |
1469 | * Returns a negative error code if the key can't be added. | 1441 | * Returns a negative error code if the key can't be added. |
1442 | * The callback can sleep. | ||
1470 | * | 1443 | * |
1471 | * @update_tkip_key: See the section "Hardware crypto acceleration" | 1444 | * @update_tkip_key: See the section "Hardware crypto acceleration" |
1472 | * This callback will be called in the context of Rx. Called for drivers | 1445 | * This callback will be called in the context of Rx. Called for drivers |
1473 | * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. | 1446 | * which set IEEE80211_KEY_FLAG_TKIP_REQ_RX_P1_KEY. |
1447 | * The callback can sleep. | ||
1474 | * | 1448 | * |
1475 | * @hw_scan: Ask the hardware to service the scan request, no need to start | 1449 | * @hw_scan: Ask the hardware to service the scan request, no need to start |
1476 | * the scan state machine in stack. The scan must honour the channel | 1450 | * the scan state machine in stack. The scan must honour the channel |
@@ -1484,21 +1458,28 @@ enum ieee80211_ampdu_mlme_action { | |||
1484 | * When the scan finishes, ieee80211_scan_completed() must be called; | 1458 | * When the scan finishes, ieee80211_scan_completed() must be called; |
1485 | * note that it also must be called when the scan cannot finish due to | 1459 | * note that it also must be called when the scan cannot finish due to |
1486 | * any error unless this callback returned a negative error code. | 1460 | * any error unless this callback returned a negative error code. |
1461 | * The callback can sleep. | ||
1487 | * | 1462 | * |
1488 | * @sw_scan_start: Notifier function that is called just before a software scan | 1463 | * @sw_scan_start: Notifier function that is called just before a software scan |
1489 | * is started. Can be NULL, if the driver doesn't need this notification. | 1464 | * is started. Can be NULL, if the driver doesn't need this notification. |
1465 | * The callback can sleep. | ||
1490 | * | 1466 | * |
1491 | * @sw_scan_complete: Notifier function that is called just after a software scan | 1467 | * @sw_scan_complete: Notifier function that is called just after a |
1492 | * finished. Can be NULL, if the driver doesn't need this notification. | 1468 | * software scan finished. Can be NULL, if the driver doesn't need |
1469 | * this notification. | ||
1470 | * The callback can sleep. | ||
1493 | * | 1471 | * |
1494 | * @get_stats: Return low-level statistics. | 1472 | * @get_stats: Return low-level statistics. |
1495 | * Returns zero if statistics are available. | 1473 | * Returns zero if statistics are available. |
1474 | * The callback can sleep. | ||
1496 | * | 1475 | * |
1497 | * @get_tkip_seq: If your device implements TKIP encryption in hardware this | 1476 | * @get_tkip_seq: If your device implements TKIP encryption in hardware this |
1498 | * callback should be provided to read the TKIP transmit IVs (both IV32 | 1477 | * callback should be provided to read the TKIP transmit IVs (both IV32 |
1499 | * and IV16) for the given key from hardware. | 1478 | * and IV16) for the given key from hardware. |
1479 | * The callback must be atomic. | ||
1500 | * | 1480 | * |
1501 | * @set_rts_threshold: Configuration of RTS threshold (if device needs it) | 1481 | * @set_rts_threshold: Configuration of RTS threshold (if device needs it) |
1482 | * The callback can sleep. | ||
1502 | * | 1483 | * |
1503 | * @sta_notify: Notifies low level driver about addition, removal or power | 1484 | * @sta_notify: Notifies low level driver about addition, removal or power |
1504 | * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. | 1485 | * state transition of an associated station, AP, IBSS/WDS/mesh peer etc. |
@@ -1507,30 +1488,36 @@ enum ieee80211_ampdu_mlme_action { | |||
1507 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), | 1488 | * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), |
1508 | * bursting) for a hardware TX queue. | 1489 | * bursting) for a hardware TX queue. |
1509 | * Returns a negative error code on failure. | 1490 | * Returns a negative error code on failure. |
1491 | * The callback can sleep. | ||
1510 | * | 1492 | * |
1511 | * @get_tx_stats: Get statistics of the current TX queue status. This is used | 1493 | * @get_tx_stats: Get statistics of the current TX queue status. This is used |
1512 | * to get number of currently queued packets (queue length), maximum queue | 1494 | * to get number of currently queued packets (queue length), maximum queue |
1513 | * size (limit), and total number of packets sent using each TX queue | 1495 | * size (limit), and total number of packets sent using each TX queue |
1514 | * (count). The 'stats' pointer points to an array that has hw->queues | 1496 | * (count). The 'stats' pointer points to an array that has hw->queues |
1515 | * items. | 1497 | * items. |
1498 | * The callback must be atomic. | ||
1516 | * | 1499 | * |
1517 | * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, | 1500 | * @get_tsf: Get the current TSF timer value from firmware/hardware. Currently, |
1518 | * this is only used for IBSS mode BSSID merging and debugging. Is not a | 1501 | * this is only used for IBSS mode BSSID merging and debugging. Is not a |
1519 | * required function. | 1502 | * required function. |
1503 | * The callback can sleep. | ||
1520 | * | 1504 | * |
1521 | * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware. | 1505 | * @set_tsf: Set the TSF timer to the specified value in the firmware/hardware. |
1522 | * Currently, this is only used for IBSS mode debugging. Is not a | 1506 | * Currently, this is only used for IBSS mode debugging. Is not a |
1523 | * required function. | 1507 | * required function. |
1508 | * The callback can sleep. | ||
1524 | * | 1509 | * |
1525 | * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize | 1510 | * @reset_tsf: Reset the TSF timer and allow firmware/hardware to synchronize |
1526 | * with other STAs in the IBSS. This is only used in IBSS mode. This | 1511 | * with other STAs in the IBSS. This is only used in IBSS mode. This |
1527 | * function is optional if the firmware/hardware takes full care of | 1512 | * function is optional if the firmware/hardware takes full care of |
1528 | * TSF synchronization. | 1513 | * TSF synchronization. |
1514 | * The callback can sleep. | ||
1529 | * | 1515 | * |
1530 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. | 1516 | * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us. |
1531 | * This is needed only for IBSS mode and the result of this function is | 1517 | * This is needed only for IBSS mode and the result of this function is |
1532 | * used to determine whether to reply to Probe Requests. | 1518 | * used to determine whether to reply to Probe Requests. |
1533 | * Returns non-zero if this device sent the last beacon. | 1519 | * Returns non-zero if this device sent the last beacon. |
1520 | * The callback can sleep. | ||
1534 | * | 1521 | * |
1535 | * @ampdu_action: Perform a certain A-MPDU action | 1522 | * @ampdu_action: Perform a certain A-MPDU action |
1536 | * The RA/TID combination determines the destination and TID we want | 1523 | * The RA/TID combination determines the destination and TID we want |
@@ -1539,21 +1526,28 @@ enum ieee80211_ampdu_mlme_action { | |||
1539 | * is the first frame we expect to perform the action on. Notice | 1526 | * is the first frame we expect to perform the action on. Notice |
1540 | * that TX/RX_STOP can pass NULL for this parameter. | 1527 | * that TX/RX_STOP can pass NULL for this parameter. |
1541 | * Returns a negative error code on failure. | 1528 | * Returns a negative error code on failure. |
1529 | * The callback must be atomic. | ||
1542 | * | 1530 | * |
1543 | * @rfkill_poll: Poll rfkill hardware state. If you need this, you also | 1531 | * @rfkill_poll: Poll rfkill hardware state. If you need this, you also |
1544 | * need to set wiphy->rfkill_poll to %true before registration, | 1532 | * need to set wiphy->rfkill_poll to %true before registration, |
1545 | * and need to call wiphy_rfkill_set_hw_state() in the callback. | 1533 | * and need to call wiphy_rfkill_set_hw_state() in the callback. |
1534 | * The callback can sleep. | ||
1546 | * | 1535 | * |
1547 | * @testmode_cmd: Implement a cfg80211 test mode command. | 1536 | * @testmode_cmd: Implement a cfg80211 test mode command. |
1537 | * The callback can sleep. | ||
1538 | * | ||
1539 | * @flush: Flush all pending frames from the hardware queue, making sure | ||
1540 | * that the hardware queues are empty. If the parameter @drop is set | ||
1541 | * to %true, pending frames may be dropped. The callback can sleep. | ||
1548 | */ | 1542 | */ |
1549 | struct ieee80211_ops { | 1543 | struct ieee80211_ops { |
1550 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); | 1544 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); |
1551 | int (*start)(struct ieee80211_hw *hw); | 1545 | int (*start)(struct ieee80211_hw *hw); |
1552 | void (*stop)(struct ieee80211_hw *hw); | 1546 | void (*stop)(struct ieee80211_hw *hw); |
1553 | int (*add_interface)(struct ieee80211_hw *hw, | 1547 | int (*add_interface)(struct ieee80211_hw *hw, |
1554 | struct ieee80211_if_init_conf *conf); | 1548 | struct ieee80211_vif *vif); |
1555 | void (*remove_interface)(struct ieee80211_hw *hw, | 1549 | void (*remove_interface)(struct ieee80211_hw *hw, |
1556 | struct ieee80211_if_init_conf *conf); | 1550 | struct ieee80211_vif *vif); |
1557 | int (*config)(struct ieee80211_hw *hw, u32 changed); | 1551 | int (*config)(struct ieee80211_hw *hw, u32 changed); |
1558 | void (*bss_info_changed)(struct ieee80211_hw *hw, | 1552 | void (*bss_info_changed)(struct ieee80211_hw *hw, |
1559 | struct ieee80211_vif *vif, | 1553 | struct ieee80211_vif *vif, |
@@ -1601,6 +1595,7 @@ struct ieee80211_ops { | |||
1601 | #ifdef CONFIG_NL80211_TESTMODE | 1595 | #ifdef CONFIG_NL80211_TESTMODE |
1602 | int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); | 1596 | int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); |
1603 | #endif | 1597 | #endif |
1598 | void (*flush)(struct ieee80211_hw *hw, bool drop); | ||
1604 | }; | 1599 | }; |
1605 | 1600 | ||
1606 | /** | 1601 | /** |
@@ -1840,7 +1835,7 @@ void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | |||
1840 | /** | 1835 | /** |
1841 | * ieee80211_beacon_get_tim - beacon generation function | 1836 | * ieee80211_beacon_get_tim - beacon generation function |
1842 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1837 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1843 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1838 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1844 | * @tim_offset: pointer to variable that will receive the TIM IE offset. | 1839 | * @tim_offset: pointer to variable that will receive the TIM IE offset. |
1845 | * Set to 0 if invalid (in non-AP modes). | 1840 | * Set to 0 if invalid (in non-AP modes). |
1846 | * @tim_length: pointer to variable that will receive the TIM IE length, | 1841 | * @tim_length: pointer to variable that will receive the TIM IE length, |
@@ -1868,7 +1863,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
1868 | /** | 1863 | /** |
1869 | * ieee80211_beacon_get - beacon generation function | 1864 | * ieee80211_beacon_get - beacon generation function |
1870 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1865 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1871 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1866 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1872 | * | 1867 | * |
1873 | * See ieee80211_beacon_get_tim(). | 1868 | * See ieee80211_beacon_get_tim(). |
1874 | */ | 1869 | */ |
@@ -1881,7 +1876,7 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
1881 | /** | 1876 | /** |
1882 | * ieee80211_rts_get - RTS frame generation function | 1877 | * ieee80211_rts_get - RTS frame generation function |
1883 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1878 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1884 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1879 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1885 | * @frame: pointer to the frame that is going to be protected by the RTS. | 1880 | * @frame: pointer to the frame that is going to be protected by the RTS. |
1886 | * @frame_len: the frame length (in octets). | 1881 | * @frame_len: the frame length (in octets). |
1887 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1882 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
@@ -1900,7 +1895,7 @@ void ieee80211_rts_get(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1900 | /** | 1895 | /** |
1901 | * ieee80211_rts_duration - Get the duration field for an RTS frame | 1896 | * ieee80211_rts_duration - Get the duration field for an RTS frame |
1902 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1897 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1903 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1898 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1904 | * @frame_len: the length of the frame that is going to be protected by the RTS. | 1899 | * @frame_len: the length of the frame that is going to be protected by the RTS. |
1905 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1900 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1906 | * | 1901 | * |
@@ -1915,7 +1910,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, | |||
1915 | /** | 1910 | /** |
1916 | * ieee80211_ctstoself_get - CTS-to-self frame generation function | 1911 | * ieee80211_ctstoself_get - CTS-to-self frame generation function |
1917 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1912 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1918 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1913 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1919 | * @frame: pointer to the frame that is going to be protected by the CTS-to-self. | 1914 | * @frame: pointer to the frame that is going to be protected by the CTS-to-self. |
1920 | * @frame_len: the frame length (in octets). | 1915 | * @frame_len: the frame length (in octets). |
1921 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1916 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
@@ -1935,7 +1930,7 @@ void ieee80211_ctstoself_get(struct ieee80211_hw *hw, | |||
1935 | /** | 1930 | /** |
1936 | * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame | 1931 | * ieee80211_ctstoself_duration - Get the duration field for a CTS-to-self frame |
1937 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1932 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1938 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1933 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1939 | * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. | 1934 | * @frame_len: the length of the frame that is going to be protected by the CTS-to-self. |
1940 | * @frame_txctl: &struct ieee80211_tx_info of the frame. | 1935 | * @frame_txctl: &struct ieee80211_tx_info of the frame. |
1941 | * | 1936 | * |
@@ -1951,7 +1946,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
1951 | /** | 1946 | /** |
1952 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame | 1947 | * ieee80211_generic_frame_duration - Calculate the duration field for a frame |
1953 | * @hw: pointer obtained from ieee80211_alloc_hw(). | 1948 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
1954 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1949 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1955 | * @frame_len: the length of the frame. | 1950 | * @frame_len: the length of the frame. |
1956 | * @rate: the rate at which the frame is going to be transmitted. | 1951 | * @rate: the rate at which the frame is going to be transmitted. |
1957 | * | 1952 | * |
@@ -1966,7 +1961,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, | |||
1966 | /** | 1961 | /** |
1967 | * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames | 1962 | * ieee80211_get_buffered_bc - accessing buffered broadcast and multicast frames |
1968 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 1963 | * @hw: pointer as obtained from ieee80211_alloc_hw(). |
1969 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 1964 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
1970 | * | 1965 | * |
1971 | * Function for accessing buffered broadcast and multicast frames. If | 1966 | * Function for accessing buffered broadcast and multicast frames. If |
1972 | * hardware/firmware does not implement buffering of broadcast/multicast | 1967 | * hardware/firmware does not implement buffering of broadcast/multicast |
@@ -2134,7 +2129,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid); | |||
2134 | 2129 | ||
2135 | /** | 2130 | /** |
2136 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. | 2131 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. |
2137 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf | 2132 | * @vif: &struct ieee80211_vif pointer from the add_interface callback |
2138 | * @ra: receiver address of the BA session recipient. | 2133 | * @ra: receiver address of the BA session recipient. |
2139 | * @tid: the TID to BA on. | 2134 | * @tid: the TID to BA on. |
2140 | * | 2135 | * |
@@ -2145,7 +2140,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); | |||
2145 | 2140 | ||
2146 | /** | 2141 | /** |
2147 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. | 2142 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. |
2148 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf | 2143 | * @vif: &struct ieee80211_vif pointer from the add_interface callback |
2149 | * @ra: receiver address of the BA session recipient. | 2144 | * @ra: receiver address of the BA session recipient. |
2150 | * @tid: the TID to BA on. | 2145 | * @tid: the TID to BA on. |
2151 | * | 2146 | * |
@@ -2173,7 +2168,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid, | |||
2173 | 2168 | ||
2174 | /** | 2169 | /** |
2175 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. | 2170 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. |
2176 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf | 2171 | * @vif: &struct ieee80211_vif pointer from the add_interface callback |
2177 | * @ra: receiver address of the BA session recipient. | 2172 | * @ra: receiver address of the BA session recipient. |
2178 | * @tid: the desired TID to BA on. | 2173 | * @tid: the desired TID to BA on. |
2179 | * | 2174 | * |
@@ -2184,7 +2179,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); | |||
2184 | 2179 | ||
2185 | /** | 2180 | /** |
2186 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. | 2181 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. |
2187 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf | 2182 | * @vif: &struct ieee80211_vif pointer from the add_interface callback |
2188 | * @ra: receiver address of the BA session recipient. | 2183 | * @ra: receiver address of the BA session recipient. |
2189 | * @tid: the desired TID to BA on. | 2184 | * @tid: the desired TID to BA on. |
2190 | * | 2185 | * |
@@ -2263,7 +2258,7 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
2263 | /** | 2258 | /** |
2264 | * ieee80211_beacon_loss - inform hardware does not receive beacons | 2259 | * ieee80211_beacon_loss - inform hardware does not receive beacons |
2265 | * | 2260 | * |
2266 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf. | 2261 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. |
2267 | * | 2262 | * |
2268 | * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and | 2263 | * When beacon filtering is enabled with IEEE80211_HW_BEACON_FILTERING and |
2269 | * IEEE80211_CONF_PS is set, the driver needs to inform whenever the | 2264 | * IEEE80211_CONF_PS is set, the driver needs to inform whenever the |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 298cfcc1bf8d..04420291e7ad 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -6,10 +6,10 @@ mac80211-y := \ | |||
6 | sta_info.o \ | 6 | sta_info.o \ |
7 | wep.o \ | 7 | wep.o \ |
8 | wpa.o \ | 8 | wpa.o \ |
9 | scan.o \ | 9 | scan.o offchannel.o \ |
10 | ht.o agg-tx.o agg-rx.o \ | 10 | ht.o agg-tx.o agg-rx.o \ |
11 | ibss.o \ | 11 | ibss.o \ |
12 | mlme.o \ | 12 | mlme.o work.o \ |
13 | iface.o \ | 13 | iface.o \ |
14 | rate.o \ | 14 | rate.o \ |
15 | michael.o \ | 15 | michael.o \ |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 63843e3e576a..2e5e841e9b7b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -78,17 +78,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
78 | enum nl80211_iftype type, u32 *flags, | 78 | enum nl80211_iftype type, u32 *flags, |
79 | struct vif_params *params) | 79 | struct vif_params *params) |
80 | { | 80 | { |
81 | struct ieee80211_sub_if_data *sdata; | 81 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
82 | int ret; | 82 | int ret; |
83 | 83 | ||
84 | if (netif_running(dev)) | 84 | if (ieee80211_sdata_running(sdata)) |
85 | return -EBUSY; | 85 | return -EBUSY; |
86 | 86 | ||
87 | if (!nl80211_params_check(type, params)) | 87 | if (!nl80211_params_check(type, params)) |
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | 89 | ||
90 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
91 | |||
92 | ret = ieee80211_if_change_type(sdata, type); | 90 | ret = ieee80211_if_change_type(sdata, type); |
93 | if (ret) | 91 | if (ret) |
94 | return ret; | 92 | return ret; |
@@ -1345,7 +1343,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1345 | return 0; | 1343 | return 0; |
1346 | } | 1344 | } |
1347 | 1345 | ||
1348 | ap = sdata->u.mgd.associated->cbss.bssid; | 1346 | ap = sdata->u.mgd.associated->bssid; |
1349 | 1347 | ||
1350 | if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { | 1348 | if (smps_mode == IEEE80211_SMPS_AUTOMATIC) { |
1351 | if (sdata->u.mgd.powersave) | 1349 | if (sdata->u.mgd.powersave) |
@@ -1443,6 +1441,28 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
1443 | return -EINVAL; | 1441 | return -EINVAL; |
1444 | } | 1442 | } |
1445 | 1443 | ||
1444 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | ||
1445 | struct net_device *dev, | ||
1446 | struct ieee80211_channel *chan, | ||
1447 | enum nl80211_channel_type channel_type, | ||
1448 | unsigned int duration, | ||
1449 | u64 *cookie) | ||
1450 | { | ||
1451 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1452 | |||
1453 | return ieee80211_wk_remain_on_channel(sdata, chan, channel_type, | ||
1454 | duration, cookie); | ||
1455 | } | ||
1456 | |||
1457 | static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | ||
1458 | struct net_device *dev, | ||
1459 | u64 cookie) | ||
1460 | { | ||
1461 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1462 | |||
1463 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | ||
1464 | } | ||
1465 | |||
1446 | struct cfg80211_ops mac80211_config_ops = { | 1466 | struct cfg80211_ops mac80211_config_ops = { |
1447 | .add_virtual_intf = ieee80211_add_iface, | 1467 | .add_virtual_intf = ieee80211_add_iface, |
1448 | .del_virtual_intf = ieee80211_del_iface, | 1468 | .del_virtual_intf = ieee80211_del_iface, |
@@ -1489,4 +1509,6 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1489 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) | 1509 | CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd) |
1490 | .set_power_mgmt = ieee80211_set_power_mgmt, | 1510 | .set_power_mgmt = ieee80211_set_power_mgmt, |
1491 | .set_bitrate_mask = ieee80211_set_bitrate_mask, | 1511 | .set_bitrate_mask = ieee80211_set_bitrate_mask, |
1512 | .remain_on_channel = ieee80211_remain_on_channel, | ||
1513 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | ||
1492 | }; | 1514 | }; |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index 355983503885..59f6e3bcbd09 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -133,7 +133,6 @@ IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC); | |||
133 | /* STA attributes */ | 133 | /* STA attributes */ |
134 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); | 134 | IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC); |
135 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); | 135 | IEEE80211_IF_FILE(aid, u.mgd.aid, DEC); |
136 | IEEE80211_IF_FILE(capab, u.mgd.capab, HEX); | ||
137 | 136 | ||
138 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, | 137 | static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata, |
139 | enum ieee80211_smps_mode smps_mode) | 138 | enum ieee80211_smps_mode smps_mode) |
@@ -270,7 +269,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
270 | 269 | ||
271 | DEBUGFS_ADD(bssid, sta); | 270 | DEBUGFS_ADD(bssid, sta); |
272 | DEBUGFS_ADD(aid, sta); | 271 | DEBUGFS_ADD(aid, sta); |
273 | DEBUGFS_ADD(capab, sta); | ||
274 | DEBUGFS_ADD_MODE(smps, 0600); | 272 | DEBUGFS_ADD_MODE(smps, 0600); |
275 | } | 273 | } |
276 | 274 | ||
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 727e4cf7b8a6..8757ea73d544 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -14,6 +14,8 @@ static inline int drv_start(struct ieee80211_local *local) | |||
14 | { | 14 | { |
15 | int ret; | 15 | int ret; |
16 | 16 | ||
17 | might_sleep(); | ||
18 | |||
17 | local->started = true; | 19 | local->started = true; |
18 | smp_mb(); | 20 | smp_mb(); |
19 | ret = local->ops->start(&local->hw); | 21 | ret = local->ops->start(&local->hw); |
@@ -23,6 +25,8 @@ static inline int drv_start(struct ieee80211_local *local) | |||
23 | 25 | ||
24 | static inline void drv_stop(struct ieee80211_local *local) | 26 | static inline void drv_stop(struct ieee80211_local *local) |
25 | { | 27 | { |
28 | might_sleep(); | ||
29 | |||
26 | local->ops->stop(&local->hw); | 30 | local->ops->stop(&local->hw); |
27 | trace_drv_stop(local); | 31 | trace_drv_stop(local); |
28 | 32 | ||
@@ -36,23 +40,33 @@ static inline void drv_stop(struct ieee80211_local *local) | |||
36 | } | 40 | } |
37 | 41 | ||
38 | static inline int drv_add_interface(struct ieee80211_local *local, | 42 | static inline int drv_add_interface(struct ieee80211_local *local, |
39 | struct ieee80211_if_init_conf *conf) | 43 | struct ieee80211_vif *vif) |
40 | { | 44 | { |
41 | int ret = local->ops->add_interface(&local->hw, conf); | 45 | int ret; |
42 | trace_drv_add_interface(local, vif_to_sdata(conf->vif), ret); | 46 | |
47 | might_sleep(); | ||
48 | |||
49 | ret = local->ops->add_interface(&local->hw, vif); | ||
50 | trace_drv_add_interface(local, vif_to_sdata(vif), ret); | ||
43 | return ret; | 51 | return ret; |
44 | } | 52 | } |
45 | 53 | ||
46 | static inline void drv_remove_interface(struct ieee80211_local *local, | 54 | static inline void drv_remove_interface(struct ieee80211_local *local, |
47 | struct ieee80211_if_init_conf *conf) | 55 | struct ieee80211_vif *vif) |
48 | { | 56 | { |
49 | local->ops->remove_interface(&local->hw, conf); | 57 | might_sleep(); |
50 | trace_drv_remove_interface(local, vif_to_sdata(conf->vif)); | 58 | |
59 | local->ops->remove_interface(&local->hw, vif); | ||
60 | trace_drv_remove_interface(local, vif_to_sdata(vif)); | ||
51 | } | 61 | } |
52 | 62 | ||
53 | static inline int drv_config(struct ieee80211_local *local, u32 changed) | 63 | static inline int drv_config(struct ieee80211_local *local, u32 changed) |
54 | { | 64 | { |
55 | int ret = local->ops->config(&local->hw, changed); | 65 | int ret; |
66 | |||
67 | might_sleep(); | ||
68 | |||
69 | ret = local->ops->config(&local->hw, changed); | ||
56 | trace_drv_config(local, changed, ret); | 70 | trace_drv_config(local, changed, ret); |
57 | return ret; | 71 | return ret; |
58 | } | 72 | } |
@@ -62,6 +76,8 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
62 | struct ieee80211_bss_conf *info, | 76 | struct ieee80211_bss_conf *info, |
63 | u32 changed) | 77 | u32 changed) |
64 | { | 78 | { |
79 | might_sleep(); | ||
80 | |||
65 | if (local->ops->bss_info_changed) | 81 | if (local->ops->bss_info_changed) |
66 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); | 82 | local->ops->bss_info_changed(&local->hw, &sdata->vif, info, changed); |
67 | trace_drv_bss_info_changed(local, sdata, info, changed); | 83 | trace_drv_bss_info_changed(local, sdata, info, changed); |
@@ -111,7 +127,11 @@ static inline int drv_set_key(struct ieee80211_local *local, | |||
111 | struct ieee80211_sta *sta, | 127 | struct ieee80211_sta *sta, |
112 | struct ieee80211_key_conf *key) | 128 | struct ieee80211_key_conf *key) |
113 | { | 129 | { |
114 | int ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | 130 | int ret; |
131 | |||
132 | might_sleep(); | ||
133 | |||
134 | ret = local->ops->set_key(&local->hw, cmd, &sdata->vif, sta, key); | ||
115 | trace_drv_set_key(local, cmd, sdata, sta, key, ret); | 135 | trace_drv_set_key(local, cmd, sdata, sta, key, ret); |
116 | return ret; | 136 | return ret; |
117 | } | 137 | } |
@@ -121,6 +141,8 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
121 | const u8 *address, u32 iv32, | 141 | const u8 *address, u32 iv32, |
122 | u16 *phase1key) | 142 | u16 *phase1key) |
123 | { | 143 | { |
144 | might_sleep(); | ||
145 | |||
124 | if (local->ops->update_tkip_key) | 146 | if (local->ops->update_tkip_key) |
125 | local->ops->update_tkip_key(&local->hw, conf, address, | 147 | local->ops->update_tkip_key(&local->hw, conf, address, |
126 | iv32, phase1key); | 148 | iv32, phase1key); |
@@ -130,13 +152,19 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
130 | static inline int drv_hw_scan(struct ieee80211_local *local, | 152 | static inline int drv_hw_scan(struct ieee80211_local *local, |
131 | struct cfg80211_scan_request *req) | 153 | struct cfg80211_scan_request *req) |
132 | { | 154 | { |
133 | int ret = local->ops->hw_scan(&local->hw, req); | 155 | int ret; |
156 | |||
157 | might_sleep(); | ||
158 | |||
159 | ret = local->ops->hw_scan(&local->hw, req); | ||
134 | trace_drv_hw_scan(local, req, ret); | 160 | trace_drv_hw_scan(local, req, ret); |
135 | return ret; | 161 | return ret; |
136 | } | 162 | } |
137 | 163 | ||
138 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 164 | static inline void drv_sw_scan_start(struct ieee80211_local *local) |
139 | { | 165 | { |
166 | might_sleep(); | ||
167 | |||
140 | if (local->ops->sw_scan_start) | 168 | if (local->ops->sw_scan_start) |
141 | local->ops->sw_scan_start(&local->hw); | 169 | local->ops->sw_scan_start(&local->hw); |
142 | trace_drv_sw_scan_start(local); | 170 | trace_drv_sw_scan_start(local); |
@@ -144,6 +172,8 @@ static inline void drv_sw_scan_start(struct ieee80211_local *local) | |||
144 | 172 | ||
145 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | 173 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) |
146 | { | 174 | { |
175 | might_sleep(); | ||
176 | |||
147 | if (local->ops->sw_scan_complete) | 177 | if (local->ops->sw_scan_complete) |
148 | local->ops->sw_scan_complete(&local->hw); | 178 | local->ops->sw_scan_complete(&local->hw); |
149 | trace_drv_sw_scan_complete(local); | 179 | trace_drv_sw_scan_complete(local); |
@@ -154,6 +184,8 @@ static inline int drv_get_stats(struct ieee80211_local *local, | |||
154 | { | 184 | { |
155 | int ret = -EOPNOTSUPP; | 185 | int ret = -EOPNOTSUPP; |
156 | 186 | ||
187 | might_sleep(); | ||
188 | |||
157 | if (local->ops->get_stats) | 189 | if (local->ops->get_stats) |
158 | ret = local->ops->get_stats(&local->hw, stats); | 190 | ret = local->ops->get_stats(&local->hw, stats); |
159 | trace_drv_get_stats(local, stats, ret); | 191 | trace_drv_get_stats(local, stats, ret); |
@@ -173,6 +205,9 @@ static inline int drv_set_rts_threshold(struct ieee80211_local *local, | |||
173 | u32 value) | 205 | u32 value) |
174 | { | 206 | { |
175 | int ret = 0; | 207 | int ret = 0; |
208 | |||
209 | might_sleep(); | ||
210 | |||
176 | if (local->ops->set_rts_threshold) | 211 | if (local->ops->set_rts_threshold) |
177 | ret = local->ops->set_rts_threshold(&local->hw, value); | 212 | ret = local->ops->set_rts_threshold(&local->hw, value); |
178 | trace_drv_set_rts_threshold(local, value, ret); | 213 | trace_drv_set_rts_threshold(local, value, ret); |
@@ -193,6 +228,9 @@ static inline int drv_conf_tx(struct ieee80211_local *local, u16 queue, | |||
193 | const struct ieee80211_tx_queue_params *params) | 228 | const struct ieee80211_tx_queue_params *params) |
194 | { | 229 | { |
195 | int ret = -EOPNOTSUPP; | 230 | int ret = -EOPNOTSUPP; |
231 | |||
232 | might_sleep(); | ||
233 | |||
196 | if (local->ops->conf_tx) | 234 | if (local->ops->conf_tx) |
197 | ret = local->ops->conf_tx(&local->hw, queue, params); | 235 | ret = local->ops->conf_tx(&local->hw, queue, params); |
198 | trace_drv_conf_tx(local, queue, params, ret); | 236 | trace_drv_conf_tx(local, queue, params, ret); |
@@ -210,6 +248,9 @@ static inline int drv_get_tx_stats(struct ieee80211_local *local, | |||
210 | static inline u64 drv_get_tsf(struct ieee80211_local *local) | 248 | static inline u64 drv_get_tsf(struct ieee80211_local *local) |
211 | { | 249 | { |
212 | u64 ret = -1ULL; | 250 | u64 ret = -1ULL; |
251 | |||
252 | might_sleep(); | ||
253 | |||
213 | if (local->ops->get_tsf) | 254 | if (local->ops->get_tsf) |
214 | ret = local->ops->get_tsf(&local->hw); | 255 | ret = local->ops->get_tsf(&local->hw); |
215 | trace_drv_get_tsf(local, ret); | 256 | trace_drv_get_tsf(local, ret); |
@@ -218,6 +259,8 @@ static inline u64 drv_get_tsf(struct ieee80211_local *local) | |||
218 | 259 | ||
219 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | 260 | static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) |
220 | { | 261 | { |
262 | might_sleep(); | ||
263 | |||
221 | if (local->ops->set_tsf) | 264 | if (local->ops->set_tsf) |
222 | local->ops->set_tsf(&local->hw, tsf); | 265 | local->ops->set_tsf(&local->hw, tsf); |
223 | trace_drv_set_tsf(local, tsf); | 266 | trace_drv_set_tsf(local, tsf); |
@@ -225,6 +268,8 @@ static inline void drv_set_tsf(struct ieee80211_local *local, u64 tsf) | |||
225 | 268 | ||
226 | static inline void drv_reset_tsf(struct ieee80211_local *local) | 269 | static inline void drv_reset_tsf(struct ieee80211_local *local) |
227 | { | 270 | { |
271 | might_sleep(); | ||
272 | |||
228 | if (local->ops->reset_tsf) | 273 | if (local->ops->reset_tsf) |
229 | local->ops->reset_tsf(&local->hw); | 274 | local->ops->reset_tsf(&local->hw); |
230 | trace_drv_reset_tsf(local); | 275 | trace_drv_reset_tsf(local); |
@@ -233,6 +278,9 @@ static inline void drv_reset_tsf(struct ieee80211_local *local) | |||
233 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) | 278 | static inline int drv_tx_last_beacon(struct ieee80211_local *local) |
234 | { | 279 | { |
235 | int ret = 1; | 280 | int ret = 1; |
281 | |||
282 | might_sleep(); | ||
283 | |||
236 | if (local->ops->tx_last_beacon) | 284 | if (local->ops->tx_last_beacon) |
237 | ret = local->ops->tx_last_beacon(&local->hw); | 285 | ret = local->ops->tx_last_beacon(&local->hw); |
238 | trace_drv_tx_last_beacon(local, ret); | 286 | trace_drv_tx_last_beacon(local, ret); |
@@ -256,7 +304,18 @@ static inline int drv_ampdu_action(struct ieee80211_local *local, | |||
256 | 304 | ||
257 | static inline void drv_rfkill_poll(struct ieee80211_local *local) | 305 | static inline void drv_rfkill_poll(struct ieee80211_local *local) |
258 | { | 306 | { |
307 | might_sleep(); | ||
308 | |||
259 | if (local->ops->rfkill_poll) | 309 | if (local->ops->rfkill_poll) |
260 | local->ops->rfkill_poll(&local->hw); | 310 | local->ops->rfkill_poll(&local->hw); |
261 | } | 311 | } |
312 | |||
313 | static inline void drv_flush(struct ieee80211_local *local, bool drop) | ||
314 | { | ||
315 | might_sleep(); | ||
316 | |||
317 | trace_drv_flush(local, drop); | ||
318 | if (local->ops->flush) | ||
319 | local->ops->flush(&local->hw, drop); | ||
320 | } | ||
262 | #endif /* __MAC80211_DRIVER_OPS */ | 321 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 7a849b920165..977cc7528bc6 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -690,6 +690,27 @@ TRACE_EVENT(drv_ampdu_action, | |||
690 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | 690 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret |
691 | ) | 691 | ) |
692 | ); | 692 | ); |
693 | |||
694 | TRACE_EVENT(drv_flush, | ||
695 | TP_PROTO(struct ieee80211_local *local, bool drop), | ||
696 | |||
697 | TP_ARGS(local, drop), | ||
698 | |||
699 | TP_STRUCT__entry( | ||
700 | LOCAL_ENTRY | ||
701 | __field(bool, drop) | ||
702 | ), | ||
703 | |||
704 | TP_fast_assign( | ||
705 | LOCAL_ASSIGN; | ||
706 | __entry->drop = drop; | ||
707 | ), | ||
708 | |||
709 | TP_printk( | ||
710 | LOCAL_PR_FMT " drop:%d", | ||
711 | LOCAL_PR_ARG, __entry->drop | ||
712 | ) | ||
713 | ); | ||
693 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 714 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
694 | 715 | ||
695 | #undef TRACE_INCLUDE_PATH | 716 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index ef6c6b2401d1..5bcde4c3fba1 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -187,15 +187,17 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
187 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 187 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
188 | struct ieee80211_bss *bss) | 188 | struct ieee80211_bss *bss) |
189 | { | 189 | { |
190 | struct cfg80211_bss *cbss = | ||
191 | container_of((void *)bss, struct cfg80211_bss, priv); | ||
190 | struct ieee80211_supported_band *sband; | 192 | struct ieee80211_supported_band *sband; |
191 | u32 basic_rates; | 193 | u32 basic_rates; |
192 | int i, j; | 194 | int i, j; |
193 | u16 beacon_int = bss->cbss.beacon_interval; | 195 | u16 beacon_int = cbss->beacon_interval; |
194 | 196 | ||
195 | if (beacon_int < 10) | 197 | if (beacon_int < 10) |
196 | beacon_int = 10; | 198 | beacon_int = 10; |
197 | 199 | ||
198 | sband = sdata->local->hw.wiphy->bands[bss->cbss.channel->band]; | 200 | sband = sdata->local->hw.wiphy->bands[cbss->channel->band]; |
199 | 201 | ||
200 | basic_rates = 0; | 202 | basic_rates = 0; |
201 | 203 | ||
@@ -212,12 +214,12 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
212 | } | 214 | } |
213 | } | 215 | } |
214 | 216 | ||
215 | __ieee80211_sta_join_ibss(sdata, bss->cbss.bssid, | 217 | __ieee80211_sta_join_ibss(sdata, cbss->bssid, |
216 | beacon_int, | 218 | beacon_int, |
217 | bss->cbss.channel, | 219 | cbss->channel, |
218 | basic_rates, | 220 | basic_rates, |
219 | bss->cbss.capability, | 221 | cbss->capability, |
220 | bss->cbss.tsf); | 222 | cbss->tsf); |
221 | } | 223 | } |
222 | 224 | ||
223 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 225 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
@@ -229,6 +231,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
229 | { | 231 | { |
230 | struct ieee80211_local *local = sdata->local; | 232 | struct ieee80211_local *local = sdata->local; |
231 | int freq; | 233 | int freq; |
234 | struct cfg80211_bss *cbss; | ||
232 | struct ieee80211_bss *bss; | 235 | struct ieee80211_bss *bss; |
233 | struct sta_info *sta; | 236 | struct sta_info *sta; |
234 | struct ieee80211_channel *channel; | 237 | struct ieee80211_channel *channel; |
@@ -283,8 +286,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
283 | if (!bss) | 286 | if (!bss) |
284 | return; | 287 | return; |
285 | 288 | ||
289 | cbss = container_of((void *)bss, struct cfg80211_bss, priv); | ||
290 | |||
286 | /* was just updated in ieee80211_bss_info_update */ | 291 | /* was just updated in ieee80211_bss_info_update */ |
287 | beacon_timestamp = bss->cbss.tsf; | 292 | beacon_timestamp = cbss->tsf; |
288 | 293 | ||
289 | /* check if we need to merge IBSS */ | 294 | /* check if we need to merge IBSS */ |
290 | 295 | ||
@@ -297,11 +302,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
297 | goto put_bss; | 302 | goto put_bss; |
298 | 303 | ||
299 | /* not an IBSS */ | 304 | /* not an IBSS */ |
300 | if (!(bss->cbss.capability & WLAN_CAPABILITY_IBSS)) | 305 | if (!(cbss->capability & WLAN_CAPABILITY_IBSS)) |
301 | goto put_bss; | 306 | goto put_bss; |
302 | 307 | ||
303 | /* different channel */ | 308 | /* different channel */ |
304 | if (bss->cbss.channel != local->oper_channel) | 309 | if (cbss->channel != local->oper_channel) |
305 | goto put_bss; | 310 | goto put_bss; |
306 | 311 | ||
307 | /* different SSID */ | 312 | /* different SSID */ |
@@ -311,7 +316,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
311 | goto put_bss; | 316 | goto put_bss; |
312 | 317 | ||
313 | /* same BSSID */ | 318 | /* same BSSID */ |
314 | if (memcmp(bss->cbss.bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) | 319 | if (memcmp(cbss->bssid, sdata->u.ibss.bssid, ETH_ALEN) == 0) |
315 | goto put_bss; | 320 | goto put_bss; |
316 | 321 | ||
317 | if (rx_status->flag & RX_FLAG_TSFT) { | 322 | if (rx_status->flag & RX_FLAG_TSFT) { |
@@ -382,6 +387,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
382 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 387 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
383 | u8 *bssid,u8 *addr, u32 supp_rates) | 388 | u8 *bssid,u8 *addr, u32 supp_rates) |
384 | { | 389 | { |
390 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||
385 | struct ieee80211_local *local = sdata->local; | 391 | struct ieee80211_local *local = sdata->local; |
386 | struct sta_info *sta; | 392 | struct sta_info *sta; |
387 | int band = local->hw.conf.channel->band; | 393 | int band = local->hw.conf.channel->band; |
@@ -397,6 +403,9 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
397 | return NULL; | 403 | return NULL; |
398 | } | 404 | } |
399 | 405 | ||
406 | if (ifibss->state == IEEE80211_IBSS_MLME_SEARCH) | ||
407 | return NULL; | ||
408 | |||
400 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) | 409 | if (compare_ether_addr(bssid, sdata->u.ibss.bssid)) |
401 | return NULL; | 410 | return NULL; |
402 | 411 | ||
@@ -514,7 +523,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
514 | { | 523 | { |
515 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 524 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
516 | struct ieee80211_local *local = sdata->local; | 525 | struct ieee80211_local *local = sdata->local; |
517 | struct ieee80211_bss *bss; | 526 | struct cfg80211_bss *cbss; |
518 | struct ieee80211_channel *chan = NULL; | 527 | struct ieee80211_channel *chan = NULL; |
519 | const u8 *bssid = NULL; | 528 | const u8 *bssid = NULL; |
520 | int active_ibss; | 529 | int active_ibss; |
@@ -538,21 +547,23 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
538 | chan = ifibss->channel; | 547 | chan = ifibss->channel; |
539 | if (!is_zero_ether_addr(ifibss->bssid)) | 548 | if (!is_zero_ether_addr(ifibss->bssid)) |
540 | bssid = ifibss->bssid; | 549 | bssid = ifibss->bssid; |
541 | bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, | 550 | cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, |
542 | ifibss->ssid, ifibss->ssid_len, | 551 | ifibss->ssid, ifibss->ssid_len, |
543 | WLAN_CAPABILITY_IBSS | | 552 | WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY, |
544 | WLAN_CAPABILITY_PRIVACY, | 553 | capability); |
545 | capability); | 554 | |
555 | if (cbss) { | ||
556 | struct ieee80211_bss *bss; | ||
546 | 557 | ||
547 | if (bss) { | 558 | bss = (void *)cbss->priv; |
548 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 559 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
549 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " | 560 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " |
550 | "%pM\n", bss->cbss.bssid, ifibss->bssid); | 561 | "%pM\n", cbss->bssid, ifibss->bssid); |
551 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 562 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
552 | 563 | ||
553 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" | 564 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" |
554 | " based on configured SSID\n", | 565 | " based on configured SSID\n", |
555 | sdata->name, bss->cbss.bssid); | 566 | sdata->name, cbss->bssid); |
556 | 567 | ||
557 | ieee80211_sta_join_ibss(sdata, bss); | 568 | ieee80211_sta_join_ibss(sdata, bss); |
558 | ieee80211_rx_bss_put(local, bss); | 569 | ieee80211_rx_bss_put(local, bss); |
@@ -744,7 +755,7 @@ static void ieee80211_ibss_work(struct work_struct *work) | |||
744 | if (WARN_ON(local->suspended)) | 755 | if (WARN_ON(local->suspended)) |
745 | return; | 756 | return; |
746 | 757 | ||
747 | if (!netif_running(sdata->dev)) | 758 | if (!ieee80211_sdata_running(sdata)) |
748 | return; | 759 | return; |
749 | 760 | ||
750 | if (local->scanning) | 761 | if (local->scanning) |
@@ -827,7 +838,7 @@ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local) | |||
827 | 838 | ||
828 | mutex_lock(&local->iflist_mtx); | 839 | mutex_lock(&local->iflist_mtx); |
829 | list_for_each_entry(sdata, &local->interfaces, list) { | 840 | list_for_each_entry(sdata, &local->interfaces, list) { |
830 | if (!netif_running(sdata->dev)) | 841 | if (!ieee80211_sdata_running(sdata)) |
831 | continue; | 842 | continue; |
832 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) | 843 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC) |
833 | continue; | 844 | continue; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 88b0ba6c7484..a27921ee6e63 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -71,9 +71,6 @@ struct ieee80211_fragment_entry { | |||
71 | 71 | ||
72 | 72 | ||
73 | struct ieee80211_bss { | 73 | struct ieee80211_bss { |
74 | /* Yes, this is a hack */ | ||
75 | struct cfg80211_bss cbss; | ||
76 | |||
77 | /* don't want to look up all the time */ | 74 | /* don't want to look up all the time */ |
78 | size_t ssid_len; | 75 | size_t ssid_len; |
79 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 76 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
@@ -227,31 +224,78 @@ struct mesh_preq_queue { | |||
227 | u8 flags; | 224 | u8 flags; |
228 | }; | 225 | }; |
229 | 226 | ||
230 | enum ieee80211_mgd_state { | 227 | enum ieee80211_work_type { |
231 | IEEE80211_MGD_STATE_IDLE, | 228 | IEEE80211_WORK_ABORT, |
232 | IEEE80211_MGD_STATE_PROBE, | 229 | IEEE80211_WORK_DIRECT_PROBE, |
233 | IEEE80211_MGD_STATE_AUTH, | 230 | IEEE80211_WORK_AUTH, |
234 | IEEE80211_MGD_STATE_ASSOC, | 231 | IEEE80211_WORK_ASSOC, |
232 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | ||
235 | }; | 233 | }; |
236 | 234 | ||
237 | struct ieee80211_mgd_work { | 235 | /** |
236 | * enum work_done_result - indicates what to do after work was done | ||
237 | * | ||
238 | * @WORK_DONE_DESTROY: This work item is no longer needed, destroy. | ||
239 | * @WORK_DONE_REQUEUE: This work item was reset to be reused, and | ||
240 | * should be requeued. | ||
241 | */ | ||
242 | enum work_done_result { | ||
243 | WORK_DONE_DESTROY, | ||
244 | WORK_DONE_REQUEUE, | ||
245 | }; | ||
246 | |||
247 | struct ieee80211_work { | ||
238 | struct list_head list; | 248 | struct list_head list; |
239 | struct ieee80211_bss *bss; | 249 | |
240 | int ie_len; | 250 | struct rcu_head rcu_head; |
241 | u8 prev_bssid[ETH_ALEN]; | 251 | |
242 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 252 | struct ieee80211_sub_if_data *sdata; |
243 | u8 ssid_len; | 253 | |
254 | enum work_done_result (*done)(struct ieee80211_work *wk, | ||
255 | struct sk_buff *skb); | ||
256 | |||
257 | struct ieee80211_channel *chan; | ||
258 | enum nl80211_channel_type chan_type; | ||
259 | |||
244 | unsigned long timeout; | 260 | unsigned long timeout; |
245 | enum ieee80211_mgd_state state; | 261 | enum ieee80211_work_type type; |
246 | u16 auth_alg, auth_transaction; | ||
247 | 262 | ||
248 | int tries; | 263 | u8 filter_ta[ETH_ALEN]; |
264 | |||
265 | bool started; | ||
249 | 266 | ||
250 | u8 key[WLAN_KEY_LEN_WEP104]; | 267 | union { |
251 | u8 key_len, key_idx; | 268 | struct { |
269 | int tries; | ||
270 | u16 algorithm, transaction; | ||
271 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
272 | u8 ssid_len; | ||
273 | u8 key[WLAN_KEY_LEN_WEP104]; | ||
274 | u8 key_len, key_idx; | ||
275 | bool privacy; | ||
276 | } probe_auth; | ||
277 | struct { | ||
278 | struct cfg80211_bss *bss; | ||
279 | const u8 *supp_rates; | ||
280 | const u8 *ht_information_ie; | ||
281 | enum ieee80211_smps_mode smps; | ||
282 | int tries; | ||
283 | u16 capability; | ||
284 | u8 prev_bssid[ETH_ALEN]; | ||
285 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
286 | u8 ssid_len; | ||
287 | u8 supp_rates_len; | ||
288 | bool wmm_used, use_11n; | ||
289 | } assoc; | ||
290 | struct { | ||
291 | u32 duration; | ||
292 | bool started; | ||
293 | } remain; | ||
294 | }; | ||
252 | 295 | ||
296 | int ie_len; | ||
253 | /* must be last */ | 297 | /* must be last */ |
254 | u8 ie[0]; /* for auth or assoc frame, not probe */ | 298 | u8 ie[0]; |
255 | }; | 299 | }; |
256 | 300 | ||
257 | /* flags used in struct ieee80211_if_managed.flags */ | 301 | /* flags used in struct ieee80211_if_managed.flags */ |
@@ -259,17 +303,11 @@ enum ieee80211_sta_flags { | |||
259 | IEEE80211_STA_BEACON_POLL = BIT(0), | 303 | IEEE80211_STA_BEACON_POLL = BIT(0), |
260 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 304 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
261 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 305 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
262 | IEEE80211_STA_WMM_ENABLED = BIT(3), | ||
263 | IEEE80211_STA_DISABLE_11N = BIT(4), | 306 | IEEE80211_STA_DISABLE_11N = BIT(4), |
264 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | 307 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
265 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 308 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
266 | }; | 309 | }; |
267 | 310 | ||
268 | /* flags for MLME request */ | ||
269 | enum ieee80211_sta_request { | ||
270 | IEEE80211_STA_REQ_SCAN, | ||
271 | }; | ||
272 | |||
273 | struct ieee80211_if_managed { | 311 | struct ieee80211_if_managed { |
274 | struct timer_list timer; | 312 | struct timer_list timer; |
275 | struct timer_list conn_mon_timer; | 313 | struct timer_list conn_mon_timer; |
@@ -284,14 +322,11 @@ struct ieee80211_if_managed { | |||
284 | int probe_send_count; | 322 | int probe_send_count; |
285 | 323 | ||
286 | struct mutex mtx; | 324 | struct mutex mtx; |
287 | struct ieee80211_bss *associated; | 325 | struct cfg80211_bss *associated; |
288 | struct ieee80211_mgd_work *old_associate_work; | ||
289 | struct list_head work_list; | ||
290 | 326 | ||
291 | u8 bssid[ETH_ALEN]; | 327 | u8 bssid[ETH_ALEN]; |
292 | 328 | ||
293 | u16 aid; | 329 | u16 aid; |
294 | u16 capab; | ||
295 | 330 | ||
296 | struct sk_buff_head skb_queue; | 331 | struct sk_buff_head skb_queue; |
297 | 332 | ||
@@ -300,8 +335,6 @@ struct ieee80211_if_managed { | |||
300 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ | 335 | enum ieee80211_smps_mode req_smps, /* requested smps mode */ |
301 | ap_smps; /* smps mode AP thinks we're in */ | 336 | ap_smps; /* smps mode AP thinks we're in */ |
302 | 337 | ||
303 | unsigned long request; | ||
304 | |||
305 | unsigned int flags; | 338 | unsigned int flags; |
306 | 339 | ||
307 | u32 beacon_crc; | 340 | u32 beacon_crc; |
@@ -568,6 +601,15 @@ struct ieee80211_local { | |||
568 | const struct ieee80211_ops *ops; | 601 | const struct ieee80211_ops *ops; |
569 | 602 | ||
570 | /* | 603 | /* |
604 | * work stuff, potentially off-channel (in the future) | ||
605 | */ | ||
606 | struct mutex work_mtx; | ||
607 | struct list_head work_list; | ||
608 | struct timer_list work_timer; | ||
609 | struct work_struct work_work; | ||
610 | struct sk_buff_head work_skb_queue; | ||
611 | |||
612 | /* | ||
571 | * private workqueue to mac80211. mac80211 makes this accessible | 613 | * private workqueue to mac80211. mac80211 makes this accessible |
572 | * via ieee80211_queue_work() | 614 | * via ieee80211_queue_work() |
573 | */ | 615 | */ |
@@ -695,6 +737,10 @@ struct ieee80211_local { | |||
695 | enum nl80211_channel_type oper_channel_type; | 737 | enum nl80211_channel_type oper_channel_type; |
696 | struct ieee80211_channel *oper_channel, *csa_channel; | 738 | struct ieee80211_channel *oper_channel, *csa_channel; |
697 | 739 | ||
740 | /* Temporary remain-on-channel for off-channel operations */ | ||
741 | struct ieee80211_channel *tmp_channel; | ||
742 | enum nl80211_channel_type tmp_channel_type; | ||
743 | |||
698 | /* SNMP counters */ | 744 | /* SNMP counters */ |
699 | /* dot11CountersTable */ | 745 | /* dot11CountersTable */ |
700 | u32 dot11TransmittedFragmentCount; | 746 | u32 dot11TransmittedFragmentCount; |
@@ -752,7 +798,7 @@ struct ieee80211_local { | |||
752 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 798 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
753 | 799 | ||
754 | bool pspolling; | 800 | bool pspolling; |
755 | bool scan_ps_enabled; | 801 | bool offchannel_ps_enabled; |
756 | /* | 802 | /* |
757 | * PS can only be enabled when we have exactly one managed | 803 | * PS can only be enabled when we have exactly one managed |
758 | * interface (and monitors) in PS, this then points there. | 804 | * interface (and monitors) in PS, this then points there. |
@@ -947,6 +993,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | |||
947 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 993 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
948 | struct ieee80211_bss *bss); | 994 | struct ieee80211_bss *bss); |
949 | 995 | ||
996 | /* off-channel helpers */ | ||
997 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); | ||
998 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local); | ||
999 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
1000 | bool enable_beaconing); | ||
1001 | |||
950 | /* interface handling */ | 1002 | /* interface handling */ |
951 | int ieee80211_iface_init(void); | 1003 | int ieee80211_iface_init(void); |
952 | void ieee80211_iface_exit(void); | 1004 | void ieee80211_iface_exit(void); |
@@ -960,6 +1012,11 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); | |||
960 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); | 1012 | u32 __ieee80211_recalc_idle(struct ieee80211_local *local); |
961 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1013 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
962 | 1014 | ||
1015 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | ||
1016 | { | ||
1017 | return netif_running(sdata->dev); | ||
1018 | } | ||
1019 | |||
963 | /* tx handling */ | 1020 | /* tx handling */ |
964 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); | 1021 | void ieee80211_clear_tx_pending(struct ieee80211_local *local); |
965 | void ieee80211_tx_pending(unsigned long data); | 1022 | void ieee80211_tx_pending(unsigned long data); |
@@ -1106,6 +1163,24 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
1106 | void ieee80211_recalc_smps(struct ieee80211_local *local, | 1163 | void ieee80211_recalc_smps(struct ieee80211_local *local, |
1107 | struct ieee80211_sub_if_data *forsdata); | 1164 | struct ieee80211_sub_if_data *forsdata); |
1108 | 1165 | ||
1166 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | ||
1167 | const u8 *ids, int n_ids, size_t offset); | ||
1168 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | ||
1169 | |||
1170 | /* internal work items */ | ||
1171 | void ieee80211_work_init(struct ieee80211_local *local); | ||
1172 | void ieee80211_add_work(struct ieee80211_work *wk); | ||
1173 | void free_work(struct ieee80211_work *wk); | ||
1174 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata); | ||
1175 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
1176 | struct sk_buff *skb); | ||
1177 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1178 | struct ieee80211_channel *chan, | ||
1179 | enum nl80211_channel_type channel_type, | ||
1180 | unsigned int duration, u64 *cookie); | ||
1181 | int ieee80211_wk_cancel_remain_on_channel( | ||
1182 | struct ieee80211_sub_if_data *sdata, u64 cookie); | ||
1183 | |||
1109 | #ifdef CONFIG_MAC80211_NOINLINE | 1184 | #ifdef CONFIG_MAC80211_NOINLINE |
1110 | #define debug_noinline noinline | 1185 | #define debug_noinline noinline |
1111 | #else | 1186 | #else |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index a6e6da3cab70..00a1f4ccdaf1 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -65,7 +65,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) | |||
65 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 65 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
66 | int ret; | 66 | int ret; |
67 | 67 | ||
68 | if (netif_running(dev)) | 68 | if (ieee80211_sdata_running(sdata)) |
69 | return -EBUSY; | 69 | return -EBUSY; |
70 | 70 | ||
71 | ret = eth_mac_addr(dev, addr); | 71 | ret = eth_mac_addr(dev, addr); |
@@ -96,7 +96,6 @@ static int ieee80211_open(struct net_device *dev) | |||
96 | struct ieee80211_sub_if_data *nsdata; | 96 | struct ieee80211_sub_if_data *nsdata; |
97 | struct ieee80211_local *local = sdata->local; | 97 | struct ieee80211_local *local = sdata->local; |
98 | struct sta_info *sta; | 98 | struct sta_info *sta; |
99 | struct ieee80211_if_init_conf conf; | ||
100 | u32 changed = 0; | 99 | u32 changed = 0; |
101 | int res; | 100 | int res; |
102 | u32 hw_reconf_flags = 0; | 101 | u32 hw_reconf_flags = 0; |
@@ -111,7 +110,7 @@ static int ieee80211_open(struct net_device *dev) | |||
111 | list_for_each_entry(nsdata, &local->interfaces, list) { | 110 | list_for_each_entry(nsdata, &local->interfaces, list) { |
112 | struct net_device *ndev = nsdata->dev; | 111 | struct net_device *ndev = nsdata->dev; |
113 | 112 | ||
114 | if (ndev != dev && netif_running(ndev)) { | 113 | if (ndev != dev && ieee80211_sdata_running(nsdata)) { |
115 | /* | 114 | /* |
116 | * Allow only a single IBSS interface to be up at any | 115 | * Allow only a single IBSS interface to be up at any |
117 | * time. This is restricted because beacon distribution | 116 | * time. This is restricted because beacon distribution |
@@ -197,7 +196,7 @@ static int ieee80211_open(struct net_device *dev) | |||
197 | struct net_device *ndev = nsdata->dev; | 196 | struct net_device *ndev = nsdata->dev; |
198 | 197 | ||
199 | /* | 198 | /* |
200 | * No need to check netif_running since we do not allow | 199 | * No need to check running since we do not allow |
201 | * it to start up with this invalid address. | 200 | * it to start up with this invalid address. |
202 | */ | 201 | */ |
203 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { | 202 | if (compare_ether_addr(null_addr, ndev->dev_addr) == 0) { |
@@ -248,10 +247,7 @@ static int ieee80211_open(struct net_device *dev) | |||
248 | ieee80211_configure_filter(local); | 247 | ieee80211_configure_filter(local); |
249 | break; | 248 | break; |
250 | default: | 249 | default: |
251 | conf.vif = &sdata->vif; | 250 | res = drv_add_interface(local, &sdata->vif); |
252 | conf.type = sdata->vif.type; | ||
253 | conf.mac_addr = sdata->vif.addr; | ||
254 | res = drv_add_interface(local, &conf); | ||
255 | if (res) | 251 | if (res) |
256 | goto err_stop; | 252 | goto err_stop; |
257 | 253 | ||
@@ -334,7 +330,7 @@ static int ieee80211_open(struct net_device *dev) | |||
334 | 330 | ||
335 | return 0; | 331 | return 0; |
336 | err_del_interface: | 332 | err_del_interface: |
337 | drv_remove_interface(local, &conf); | 333 | drv_remove_interface(local, &sdata->vif); |
338 | err_stop: | 334 | err_stop: |
339 | if (!local->open_count) | 335 | if (!local->open_count) |
340 | drv_stop(local); | 336 | drv_stop(local); |
@@ -349,7 +345,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
349 | { | 345 | { |
350 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 346 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
351 | struct ieee80211_local *local = sdata->local; | 347 | struct ieee80211_local *local = sdata->local; |
352 | struct ieee80211_if_init_conf conf; | ||
353 | struct sta_info *sta; | 348 | struct sta_info *sta; |
354 | unsigned long flags; | 349 | unsigned long flags; |
355 | struct sk_buff *skb, *tmp; | 350 | struct sk_buff *skb, *tmp; |
@@ -362,6 +357,11 @@ static int ieee80211_stop(struct net_device *dev) | |||
362 | netif_stop_queue(dev); | 357 | netif_stop_queue(dev); |
363 | 358 | ||
364 | /* | 359 | /* |
360 | * Purge work for this interface. | ||
361 | */ | ||
362 | ieee80211_work_purge(sdata); | ||
363 | |||
364 | /* | ||
365 | * Now delete all active aggregation sessions. | 365 | * Now delete all active aggregation sessions. |
366 | */ | 366 | */ |
367 | rcu_read_lock(); | 367 | rcu_read_lock(); |
@@ -528,12 +528,9 @@ static int ieee80211_stop(struct net_device *dev) | |||
528 | BSS_CHANGED_BEACON_ENABLED); | 528 | BSS_CHANGED_BEACON_ENABLED); |
529 | } | 529 | } |
530 | 530 | ||
531 | conf.vif = &sdata->vif; | ||
532 | conf.type = sdata->vif.type; | ||
533 | conf.mac_addr = sdata->vif.addr; | ||
534 | /* disable all keys for as long as this netdev is down */ | 531 | /* disable all keys for as long as this netdev is down */ |
535 | ieee80211_disable_keys(sdata); | 532 | ieee80211_disable_keys(sdata); |
536 | drv_remove_interface(local, &conf); | 533 | drv_remove_interface(local, &sdata->vif); |
537 | } | 534 | } |
538 | 535 | ||
539 | sdata->bss = NULL; | 536 | sdata->bss = NULL; |
@@ -756,7 +753,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
756 | * and goes into the requested mode. | 753 | * and goes into the requested mode. |
757 | */ | 754 | */ |
758 | 755 | ||
759 | if (netif_running(sdata->dev)) | 756 | if (ieee80211_sdata_running(sdata)) |
760 | return -EBUSY; | 757 | return -EBUSY; |
761 | 758 | ||
762 | /* Purge and reset type-dependent state. */ | 759 | /* Purge and reset type-dependent state. */ |
@@ -917,6 +914,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
917 | wiphy_name(local->hw.wiphy)); | 914 | wiphy_name(local->hw.wiphy)); |
918 | #endif | 915 | #endif |
919 | 916 | ||
917 | drv_flush(local, false); | ||
918 | |||
920 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 919 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
921 | return IEEE80211_CONF_CHANGE_IDLE; | 920 | return IEEE80211_CONF_CHANGE_IDLE; |
922 | } | 921 | } |
@@ -926,16 +925,18 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
926 | struct ieee80211_sub_if_data *sdata; | 925 | struct ieee80211_sub_if_data *sdata; |
927 | int count = 0; | 926 | int count = 0; |
928 | 927 | ||
928 | if (!list_empty(&local->work_list)) | ||
929 | return ieee80211_idle_off(local, "working"); | ||
930 | |||
929 | if (local->scanning) | 931 | if (local->scanning) |
930 | return ieee80211_idle_off(local, "scanning"); | 932 | return ieee80211_idle_off(local, "scanning"); |
931 | 933 | ||
932 | list_for_each_entry(sdata, &local->interfaces, list) { | 934 | list_for_each_entry(sdata, &local->interfaces, list) { |
933 | if (!netif_running(sdata->dev)) | 935 | if (!ieee80211_sdata_running(sdata)) |
934 | continue; | 936 | continue; |
935 | /* do not count disabled managed interfaces */ | 937 | /* do not count disabled managed interfaces */ |
936 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 938 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
937 | !sdata->u.mgd.associated && | 939 | !sdata->u.mgd.associated) |
938 | list_empty(&sdata->u.mgd.work_list)) | ||
939 | continue; | 940 | continue; |
940 | /* do not count unused IBSS interfaces */ | 941 | /* do not count unused IBSS interfaces */ |
941 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 942 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 32ee6d0ee34d..8160d9c5372e 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -443,7 +443,7 @@ void ieee80211_key_link(struct ieee80211_key *key, | |||
443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); | 443 | add_todo(old_key, KEY_FLAG_TODO_DELETE); |
444 | 444 | ||
445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); | 445 | add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); |
446 | if (netif_running(sdata->dev)) | 446 | if (ieee80211_sdata_running(sdata)) |
447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); | 447 | add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD); |
448 | 448 | ||
449 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); | 449 | spin_unlock_irqrestore(&sdata->local->key_lock, flags); |
@@ -509,7 +509,7 @@ void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata) | |||
509 | { | 509 | { |
510 | ASSERT_RTNL(); | 510 | ASSERT_RTNL(); |
511 | 511 | ||
512 | if (WARN_ON(!netif_running(sdata->dev))) | 512 | if (WARN_ON(!ieee80211_sdata_running(sdata))) |
513 | return; | 513 | return; |
514 | 514 | ||
515 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); | 515 | ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d4426748ab10..d0a14d953f08 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -107,6 +107,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
107 | if (scan_chan) { | 107 | if (scan_chan) { |
108 | chan = scan_chan; | 108 | chan = scan_chan; |
109 | channel_type = NL80211_CHAN_NO_HT; | 109 | channel_type = NL80211_CHAN_NO_HT; |
110 | } else if (local->tmp_channel) { | ||
111 | chan = scan_chan = local->tmp_channel; | ||
112 | channel_type = local->tmp_channel_type; | ||
110 | } else { | 113 | } else { |
111 | chan = local->oper_channel; | 114 | chan = local->oper_channel; |
112 | channel_type = local->oper_channel_type; | 115 | channel_type = local->oper_channel_type; |
@@ -212,7 +215,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
212 | } | 215 | } |
213 | 216 | ||
214 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | 217 | if (changed & BSS_CHANGED_BEACON_ENABLED) { |
215 | if (local->quiescing || !netif_running(sdata->dev) || | 218 | if (local->quiescing || !ieee80211_sdata_running(sdata) || |
216 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { | 219 | test_bit(SCAN_SW_SCANNING, &local->scanning)) { |
217 | sdata->vif.bss_conf.enable_beacon = false; | 220 | sdata->vif.bss_conf.enable_beacon = false; |
218 | } else { | 221 | } else { |
@@ -359,9 +362,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
359 | WIPHY_FLAG_4ADDR_STATION; | 362 | WIPHY_FLAG_4ADDR_STATION; |
360 | wiphy->privid = mac80211_wiphy_privid; | 363 | wiphy->privid = mac80211_wiphy_privid; |
361 | 364 | ||
362 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | 365 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss); |
363 | wiphy->bss_priv_size = sizeof(struct ieee80211_bss) - | ||
364 | sizeof(struct cfg80211_bss); | ||
365 | 366 | ||
366 | local = wiphy_priv(wiphy); | 367 | local = wiphy_priv(wiphy); |
367 | 368 | ||
@@ -395,6 +396,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
395 | 396 | ||
396 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 397 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
397 | 398 | ||
399 | ieee80211_work_init(local); | ||
400 | |||
398 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 401 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
399 | 402 | ||
400 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | 403 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e0bd85e3d4b6..61080c5fad50 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -645,7 +645,7 @@ static void ieee80211_mesh_work(struct work_struct *work) | |||
645 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 645 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
646 | struct sk_buff *skb; | 646 | struct sk_buff *skb; |
647 | 647 | ||
648 | if (!netif_running(sdata->dev)) | 648 | if (!ieee80211_sdata_running(sdata)) |
649 | return; | 649 | return; |
650 | 650 | ||
651 | if (local->scanning) | 651 | if (local->scanning) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2f9ed8b9c3f0..72920ee07885 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -77,12 +77,6 @@ enum rx_mgmt_action { | |||
77 | 77 | ||
78 | /* caller must tell cfg80211 about internal error */ | 78 | /* caller must tell cfg80211 about internal error */ |
79 | RX_MGMT_CFG80211_ASSOC_ERROR, | 79 | RX_MGMT_CFG80211_ASSOC_ERROR, |
80 | |||
81 | /* caller must call cfg80211_auth_timeout() & free work */ | ||
82 | RX_MGMT_CFG80211_AUTH_TO, | ||
83 | |||
84 | /* caller must call cfg80211_assoc_timeout() & free work */ | ||
85 | RX_MGMT_CFG80211_ASSOC_TO, | ||
86 | }; | 80 | }; |
87 | 81 | ||
88 | /* utils */ | 82 | /* utils */ |
@@ -125,27 +119,6 @@ static int ecw2cw(int ecw) | |||
125 | return (1 << ecw) - 1; | 119 | return (1 << ecw) - 1; |
126 | } | 120 | } |
127 | 121 | ||
128 | static int ieee80211_compatible_rates(struct ieee80211_bss *bss, | ||
129 | struct ieee80211_supported_band *sband, | ||
130 | u32 *rates) | ||
131 | { | ||
132 | int i, j, count; | ||
133 | *rates = 0; | ||
134 | count = 0; | ||
135 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
136 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | ||
137 | |||
138 | for (j = 0; j < sband->n_bitrates; j++) | ||
139 | if (sband->bitrates[j].bitrate == rate) { | ||
140 | *rates |= BIT(j); | ||
141 | count++; | ||
142 | break; | ||
143 | } | ||
144 | } | ||
145 | |||
146 | return count; | ||
147 | } | ||
148 | |||
149 | /* | 122 | /* |
150 | * ieee80211_enable_ht should be called only after the operating band | 123 | * ieee80211_enable_ht should be called only after the operating band |
151 | * has been determined as ht configuration depends on the hw's | 124 | * has been determined as ht configuration depends on the hw's |
@@ -231,264 +204,6 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
231 | 204 | ||
232 | /* frame sending functions */ | 205 | /* frame sending functions */ |
233 | 206 | ||
234 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | ||
235 | struct ieee80211_mgd_work *wk) | ||
236 | { | ||
237 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
238 | struct ieee80211_local *local = sdata->local; | ||
239 | struct sk_buff *skb; | ||
240 | struct ieee80211_mgmt *mgmt; | ||
241 | u8 *pos; | ||
242 | const u8 *ies, *ht_ie; | ||
243 | int i, len, count, rates_len, supp_rates_len; | ||
244 | u16 capab; | ||
245 | int wmm = 0; | ||
246 | struct ieee80211_supported_band *sband; | ||
247 | u32 rates = 0; | ||
248 | |||
249 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | ||
250 | sizeof(*mgmt) + 200 + wk->ie_len + | ||
251 | wk->ssid_len); | ||
252 | if (!skb) { | ||
253 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | ||
254 | "frame\n", sdata->name); | ||
255 | return; | ||
256 | } | ||
257 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
258 | |||
259 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
260 | |||
261 | capab = ifmgd->capab; | ||
262 | |||
263 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) { | ||
264 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
265 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
266 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
267 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
268 | } | ||
269 | |||
270 | if (wk->bss->cbss.capability & WLAN_CAPABILITY_PRIVACY) | ||
271 | capab |= WLAN_CAPABILITY_PRIVACY; | ||
272 | if (wk->bss->wmm_used) | ||
273 | wmm = 1; | ||
274 | |||
275 | /* get all rates supported by the device and the AP as | ||
276 | * some APs don't like getting a superset of their rates | ||
277 | * in the association request (e.g. D-Link DAP 1353 in | ||
278 | * b-only mode) */ | ||
279 | rates_len = ieee80211_compatible_rates(wk->bss, sband, &rates); | ||
280 | |||
281 | if ((wk->bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | ||
282 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | ||
283 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | ||
284 | |||
285 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
286 | memset(mgmt, 0, 24); | ||
287 | memcpy(mgmt->da, wk->bss->cbss.bssid, ETH_ALEN); | ||
288 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
289 | memcpy(mgmt->bssid, wk->bss->cbss.bssid, ETH_ALEN); | ||
290 | |||
291 | if (!is_zero_ether_addr(wk->prev_bssid)) { | ||
292 | skb_put(skb, 10); | ||
293 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
294 | IEEE80211_STYPE_REASSOC_REQ); | ||
295 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | ||
296 | mgmt->u.reassoc_req.listen_interval = | ||
297 | cpu_to_le16(local->hw.conf.listen_interval); | ||
298 | memcpy(mgmt->u.reassoc_req.current_ap, wk->prev_bssid, | ||
299 | ETH_ALEN); | ||
300 | } else { | ||
301 | skb_put(skb, 4); | ||
302 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
303 | IEEE80211_STYPE_ASSOC_REQ); | ||
304 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | ||
305 | mgmt->u.assoc_req.listen_interval = | ||
306 | cpu_to_le16(local->hw.conf.listen_interval); | ||
307 | } | ||
308 | |||
309 | /* SSID */ | ||
310 | ies = pos = skb_put(skb, 2 + wk->ssid_len); | ||
311 | *pos++ = WLAN_EID_SSID; | ||
312 | *pos++ = wk->ssid_len; | ||
313 | memcpy(pos, wk->ssid, wk->ssid_len); | ||
314 | |||
315 | /* add all rates which were marked to be used above */ | ||
316 | supp_rates_len = rates_len; | ||
317 | if (supp_rates_len > 8) | ||
318 | supp_rates_len = 8; | ||
319 | |||
320 | len = sband->n_bitrates; | ||
321 | pos = skb_put(skb, supp_rates_len + 2); | ||
322 | *pos++ = WLAN_EID_SUPP_RATES; | ||
323 | *pos++ = supp_rates_len; | ||
324 | |||
325 | count = 0; | ||
326 | for (i = 0; i < sband->n_bitrates; i++) { | ||
327 | if (BIT(i) & rates) { | ||
328 | int rate = sband->bitrates[i].bitrate; | ||
329 | *pos++ = (u8) (rate / 5); | ||
330 | if (++count == 8) | ||
331 | break; | ||
332 | } | ||
333 | } | ||
334 | |||
335 | if (rates_len > count) { | ||
336 | pos = skb_put(skb, rates_len - count + 2); | ||
337 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
338 | *pos++ = rates_len - count; | ||
339 | |||
340 | for (i++; i < sband->n_bitrates; i++) { | ||
341 | if (BIT(i) & rates) { | ||
342 | int rate = sband->bitrates[i].bitrate; | ||
343 | *pos++ = (u8) (rate / 5); | ||
344 | } | ||
345 | } | ||
346 | } | ||
347 | |||
348 | if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { | ||
349 | /* 1. power capabilities */ | ||
350 | pos = skb_put(skb, 4); | ||
351 | *pos++ = WLAN_EID_PWR_CAPABILITY; | ||
352 | *pos++ = 2; | ||
353 | *pos++ = 0; /* min tx power */ | ||
354 | *pos++ = local->hw.conf.channel->max_power; /* max tx power */ | ||
355 | |||
356 | /* 2. supported channels */ | ||
357 | /* TODO: get this in reg domain format */ | ||
358 | pos = skb_put(skb, 2 * sband->n_channels + 2); | ||
359 | *pos++ = WLAN_EID_SUPPORTED_CHANNELS; | ||
360 | *pos++ = 2 * sband->n_channels; | ||
361 | for (i = 0; i < sband->n_channels; i++) { | ||
362 | *pos++ = ieee80211_frequency_to_channel( | ||
363 | sband->channels[i].center_freq); | ||
364 | *pos++ = 1; /* one channel in the subband*/ | ||
365 | } | ||
366 | } | ||
367 | |||
368 | if (wk->ie_len && wk->ie) { | ||
369 | pos = skb_put(skb, wk->ie_len); | ||
370 | memcpy(pos, wk->ie, wk->ie_len); | ||
371 | } | ||
372 | |||
373 | if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) { | ||
374 | pos = skb_put(skb, 9); | ||
375 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
376 | *pos++ = 7; /* len */ | ||
377 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
378 | *pos++ = 0x50; | ||
379 | *pos++ = 0xf2; | ||
380 | *pos++ = 2; /* WME */ | ||
381 | *pos++ = 0; /* WME info */ | ||
382 | *pos++ = 1; /* WME ver */ | ||
383 | *pos++ = 0; | ||
384 | } | ||
385 | |||
386 | /* wmm support is a must to HT */ | ||
387 | /* | ||
388 | * IEEE802.11n does not allow TKIP/WEP as pairwise | ||
389 | * ciphers in HT mode. We still associate in non-ht | ||
390 | * mode (11a/b/g) if any one of these ciphers is | ||
391 | * configured as pairwise. | ||
392 | */ | ||
393 | if (wmm && (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && | ||
394 | sband->ht_cap.ht_supported && | ||
395 | (ht_ie = ieee80211_bss_get_ie(&wk->bss->cbss, WLAN_EID_HT_INFORMATION)) && | ||
396 | ht_ie[1] >= sizeof(struct ieee80211_ht_info) && | ||
397 | (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))) { | ||
398 | struct ieee80211_ht_info *ht_info = | ||
399 | (struct ieee80211_ht_info *)(ht_ie + 2); | ||
400 | u16 cap = sband->ht_cap.cap; | ||
401 | __le16 tmp; | ||
402 | u32 flags = local->hw.conf.channel->flags; | ||
403 | |||
404 | /* determine capability flags */ | ||
405 | |||
406 | if (ieee80211_disable_40mhz_24ghz && | ||
407 | sband->band == IEEE80211_BAND_2GHZ) { | ||
408 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
409 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
410 | } | ||
411 | |||
412 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
413 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
414 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | ||
415 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
416 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
417 | } | ||
418 | break; | ||
419 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
420 | if (flags & IEEE80211_CHAN_NO_HT40MINUS) { | ||
421 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
422 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
423 | } | ||
424 | break; | ||
425 | } | ||
426 | |||
427 | /* set SM PS mode properly */ | ||
428 | cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
429 | /* new association always uses requested smps mode */ | ||
430 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | ||
431 | if (ifmgd->powersave) | ||
432 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
433 | else | ||
434 | ifmgd->ap_smps = IEEE80211_SMPS_OFF; | ||
435 | } else | ||
436 | ifmgd->ap_smps = ifmgd->req_smps; | ||
437 | |||
438 | switch (ifmgd->ap_smps) { | ||
439 | case IEEE80211_SMPS_AUTOMATIC: | ||
440 | case IEEE80211_SMPS_NUM_MODES: | ||
441 | WARN_ON(1); | ||
442 | case IEEE80211_SMPS_OFF: | ||
443 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
444 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
445 | break; | ||
446 | case IEEE80211_SMPS_STATIC: | ||
447 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
448 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
449 | break; | ||
450 | case IEEE80211_SMPS_DYNAMIC: | ||
451 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
452 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
453 | break; | ||
454 | } | ||
455 | |||
456 | /* reserve and fill IE */ | ||
457 | |||
458 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
459 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
460 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
461 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
462 | |||
463 | /* capability flags */ | ||
464 | tmp = cpu_to_le16(cap); | ||
465 | memcpy(pos, &tmp, sizeof(u16)); | ||
466 | pos += sizeof(u16); | ||
467 | |||
468 | /* AMPDU parameters */ | ||
469 | *pos++ = sband->ht_cap.ampdu_factor | | ||
470 | (sband->ht_cap.ampdu_density << | ||
471 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
472 | |||
473 | /* MCS set */ | ||
474 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | ||
475 | pos += sizeof(sband->ht_cap.mcs); | ||
476 | |||
477 | /* extended capabilities */ | ||
478 | pos += sizeof(__le16); | ||
479 | |||
480 | /* BF capabilities */ | ||
481 | pos += sizeof(__le32); | ||
482 | |||
483 | /* antenna selection */ | ||
484 | pos += sizeof(u8); | ||
485 | } | ||
486 | |||
487 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
488 | ieee80211_tx_skb(sdata, skb); | ||
489 | } | ||
490 | |||
491 | |||
492 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | 207 | static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, |
493 | const u8 *bssid, u16 stype, u16 reason, | 208 | const u8 *bssid, u16 stype, u16 reason, |
494 | void *cookie) | 209 | void *cookie) |
@@ -604,7 +319,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
604 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); | 319 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); |
605 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 320 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
606 | 321 | ||
607 | if (!netif_running(sdata->dev)) | 322 | if (!ieee80211_sdata_running(sdata)) |
608 | return; | 323 | return; |
609 | 324 | ||
610 | mutex_lock(&ifmgd->mtx); | 325 | mutex_lock(&ifmgd->mtx); |
@@ -615,7 +330,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
615 | ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); | 330 | ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL); |
616 | 331 | ||
617 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 332 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
618 | ifmgd->associated->cbss.channel = sdata->local->oper_channel; | 333 | ifmgd->associated->channel = sdata->local->oper_channel; |
619 | 334 | ||
620 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 335 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
621 | IEEE80211_QUEUE_STOP_REASON_CSA); | 336 | IEEE80211_QUEUE_STOP_REASON_CSA); |
@@ -642,6 +357,8 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
642 | struct ieee80211_channel_sw_ie *sw_elem, | 357 | struct ieee80211_channel_sw_ie *sw_elem, |
643 | struct ieee80211_bss *bss) | 358 | struct ieee80211_bss *bss) |
644 | { | 359 | { |
360 | struct cfg80211_bss *cbss = | ||
361 | container_of((void *)bss, struct cfg80211_bss, priv); | ||
645 | struct ieee80211_channel *new_ch; | 362 | struct ieee80211_channel *new_ch; |
646 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 363 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
647 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); | 364 | int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num); |
@@ -675,7 +392,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
675 | mod_timer(&ifmgd->chswitch_timer, | 392 | mod_timer(&ifmgd->chswitch_timer, |
676 | jiffies + | 393 | jiffies + |
677 | msecs_to_jiffies(sw_elem->count * | 394 | msecs_to_jiffies(sw_elem->count * |
678 | bss->cbss.beacon_interval)); | 395 | cbss->beacon_interval)); |
679 | } | 396 | } |
680 | } | 397 | } |
681 | 398 | ||
@@ -749,8 +466,13 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
749 | return; | 466 | return; |
750 | } | 467 | } |
751 | 468 | ||
469 | if (!list_empty(&local->work_list)) { | ||
470 | local->ps_sdata = NULL; | ||
471 | goto change; | ||
472 | } | ||
473 | |||
752 | list_for_each_entry(sdata, &local->interfaces, list) { | 474 | list_for_each_entry(sdata, &local->interfaces, list) { |
753 | if (!netif_running(sdata->dev)) | 475 | if (!ieee80211_sdata_running(sdata)) |
754 | continue; | 476 | continue; |
755 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 477 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
756 | continue; | 478 | continue; |
@@ -759,7 +481,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
759 | } | 481 | } |
760 | 482 | ||
761 | if (count == 1 && found->u.mgd.powersave && | 483 | if (count == 1 && found->u.mgd.powersave && |
762 | found->u.mgd.associated && list_empty(&found->u.mgd.work_list) && | 484 | found->u.mgd.associated && |
763 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | | 485 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | |
764 | IEEE80211_STA_CONNECTION_POLL))) { | 486 | IEEE80211_STA_CONNECTION_POLL))) { |
765 | s32 beaconint_us; | 487 | s32 beaconint_us; |
@@ -787,6 +509,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
787 | local->ps_sdata = NULL; | 509 | local->ps_sdata = NULL; |
788 | } | 510 | } |
789 | 511 | ||
512 | change: | ||
790 | ieee80211_change_ps(local); | 513 | ieee80211_change_ps(local); |
791 | } | 514 | } |
792 | 515 | ||
@@ -846,7 +569,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
846 | int count; | 569 | int count; |
847 | u8 *pos; | 570 | u8 *pos; |
848 | 571 | ||
849 | if (!(ifmgd->flags & IEEE80211_STA_WMM_ENABLED)) | 572 | if (local->hw.queues < 4) |
850 | return; | 573 | return; |
851 | 574 | ||
852 | if (!wmm_param) | 575 | if (!wmm_param) |
@@ -949,25 +672,24 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
949 | } | 672 | } |
950 | 673 | ||
951 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | 674 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
952 | struct ieee80211_mgd_work *wk, | 675 | struct cfg80211_bss *cbss, |
953 | u32 bss_info_changed) | 676 | u32 bss_info_changed) |
954 | { | 677 | { |
678 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
955 | struct ieee80211_local *local = sdata->local; | 679 | struct ieee80211_local *local = sdata->local; |
956 | struct ieee80211_bss *bss = wk->bss; | ||
957 | 680 | ||
958 | bss_info_changed |= BSS_CHANGED_ASSOC; | 681 | bss_info_changed |= BSS_CHANGED_ASSOC; |
959 | /* set timing information */ | 682 | /* set timing information */ |
960 | sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval; | 683 | sdata->vif.bss_conf.beacon_int = cbss->beacon_interval; |
961 | sdata->vif.bss_conf.timestamp = bss->cbss.tsf; | 684 | sdata->vif.bss_conf.timestamp = cbss->tsf; |
962 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; | 685 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; |
963 | 686 | ||
964 | bss_info_changed |= BSS_CHANGED_BEACON_INT; | 687 | bss_info_changed |= BSS_CHANGED_BEACON_INT; |
965 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, | 688 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
966 | bss->cbss.capability, bss->has_erp_value, bss->erp_value); | 689 | cbss->capability, bss->has_erp_value, bss->erp_value); |
967 | 690 | ||
968 | sdata->u.mgd.associated = bss; | 691 | sdata->u.mgd.associated = cbss; |
969 | sdata->u.mgd.old_associate_work = wk; | 692 | memcpy(sdata->u.mgd.bssid, cbss->bssid, ETH_ALEN); |
970 | memcpy(sdata->u.mgd.bssid, bss->cbss.bssid, ETH_ALEN); | ||
971 | 693 | ||
972 | /* just to be sure */ | 694 | /* just to be sure */ |
973 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 695 | sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
@@ -1005,93 +727,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1005 | netif_carrier_on(sdata->dev); | 727 | netif_carrier_on(sdata->dev); |
1006 | } | 728 | } |
1007 | 729 | ||
1008 | static enum rx_mgmt_action __must_check | 730 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata) |
1009 | ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | ||
1010 | struct ieee80211_mgd_work *wk) | ||
1011 | { | ||
1012 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1013 | struct ieee80211_local *local = sdata->local; | ||
1014 | |||
1015 | wk->tries++; | ||
1016 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | ||
1017 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", | ||
1018 | sdata->name, wk->bss->cbss.bssid); | ||
1019 | |||
1020 | /* | ||
1021 | * Most likely AP is not in the range so remove the | ||
1022 | * bss struct for that AP. | ||
1023 | */ | ||
1024 | cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); | ||
1025 | |||
1026 | /* | ||
1027 | * We might have a pending scan which had no chance to run yet | ||
1028 | * due to work needing to be done. Hence, queue the STAs work | ||
1029 | * again for that. | ||
1030 | */ | ||
1031 | ieee80211_queue_work(&local->hw, &ifmgd->work); | ||
1032 | return RX_MGMT_CFG80211_AUTH_TO; | ||
1033 | } | ||
1034 | |||
1035 | printk(KERN_DEBUG "%s: direct probe to AP %pM (try %d)\n", | ||
1036 | sdata->name, wk->bss->cbss.bssid, | ||
1037 | wk->tries); | ||
1038 | |||
1039 | /* | ||
1040 | * Direct probe is sent to broadcast address as some APs | ||
1041 | * will not answer to direct packet in unassociated state. | ||
1042 | */ | ||
1043 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); | ||
1044 | |||
1045 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
1046 | run_again(ifmgd, wk->timeout); | ||
1047 | |||
1048 | return RX_MGMT_NONE; | ||
1049 | } | ||
1050 | |||
1051 | |||
1052 | static enum rx_mgmt_action __must_check | ||
1053 | ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | ||
1054 | struct ieee80211_mgd_work *wk) | ||
1055 | { | ||
1056 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1057 | struct ieee80211_local *local = sdata->local; | ||
1058 | |||
1059 | wk->tries++; | ||
1060 | if (wk->tries > IEEE80211_AUTH_MAX_TRIES) { | ||
1061 | printk(KERN_DEBUG "%s: authentication with AP %pM" | ||
1062 | " timed out\n", | ||
1063 | sdata->name, wk->bss->cbss.bssid); | ||
1064 | |||
1065 | /* | ||
1066 | * Most likely AP is not in the range so remove the | ||
1067 | * bss struct for that AP. | ||
1068 | */ | ||
1069 | cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); | ||
1070 | |||
1071 | /* | ||
1072 | * We might have a pending scan which had no chance to run yet | ||
1073 | * due to work needing to be done. Hence, queue the STAs work | ||
1074 | * again for that. | ||
1075 | */ | ||
1076 | ieee80211_queue_work(&local->hw, &ifmgd->work); | ||
1077 | return RX_MGMT_CFG80211_AUTH_TO; | ||
1078 | } | ||
1079 | |||
1080 | printk(KERN_DEBUG "%s: authenticate with AP %pM (try %d)\n", | ||
1081 | sdata->name, wk->bss->cbss.bssid, wk->tries); | ||
1082 | |||
1083 | ieee80211_send_auth(sdata, 1, wk->auth_alg, wk->ie, wk->ie_len, | ||
1084 | wk->bss->cbss.bssid, NULL, 0, 0); | ||
1085 | wk->auth_transaction = 2; | ||
1086 | |||
1087 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
1088 | run_again(ifmgd, wk->timeout); | ||
1089 | |||
1090 | return RX_MGMT_NONE; | ||
1091 | } | ||
1092 | |||
1093 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | ||
1094 | bool deauth) | ||
1095 | { | 731 | { |
1096 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 732 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1097 | struct ieee80211_local *local = sdata->local; | 733 | struct ieee80211_local *local = sdata->local; |
@@ -1104,21 +740,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1104 | if (WARN_ON(!ifmgd->associated)) | 740 | if (WARN_ON(!ifmgd->associated)) |
1105 | return; | 741 | return; |
1106 | 742 | ||
1107 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | 743 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
1108 | 744 | ||
1109 | ifmgd->associated = NULL; | 745 | ifmgd->associated = NULL; |
1110 | memset(ifmgd->bssid, 0, ETH_ALEN); | 746 | memset(ifmgd->bssid, 0, ETH_ALEN); |
1111 | 747 | ||
1112 | if (deauth) { | ||
1113 | kfree(ifmgd->old_associate_work); | ||
1114 | ifmgd->old_associate_work = NULL; | ||
1115 | } else { | ||
1116 | struct ieee80211_mgd_work *wk = ifmgd->old_associate_work; | ||
1117 | |||
1118 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1119 | list_add(&wk->list, &ifmgd->work_list); | ||
1120 | } | ||
1121 | |||
1122 | /* | 748 | /* |
1123 | * we need to commit the associated = NULL change because the | 749 | * we need to commit the associated = NULL change because the |
1124 | * scan code uses that to determine whether this iface should | 750 | * scan code uses that to determine whether this iface should |
@@ -1187,44 +813,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1187 | sta_info_destroy(sta); | 813 | sta_info_destroy(sta); |
1188 | } | 814 | } |
1189 | 815 | ||
1190 | static enum rx_mgmt_action __must_check | ||
1191 | ieee80211_associate(struct ieee80211_sub_if_data *sdata, | ||
1192 | struct ieee80211_mgd_work *wk) | ||
1193 | { | ||
1194 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1195 | struct ieee80211_local *local = sdata->local; | ||
1196 | |||
1197 | wk->tries++; | ||
1198 | if (wk->tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
1199 | printk(KERN_DEBUG "%s: association with AP %pM" | ||
1200 | " timed out\n", | ||
1201 | sdata->name, wk->bss->cbss.bssid); | ||
1202 | |||
1203 | /* | ||
1204 | * Most likely AP is not in the range so remove the | ||
1205 | * bss struct for that AP. | ||
1206 | */ | ||
1207 | cfg80211_unlink_bss(local->hw.wiphy, &wk->bss->cbss); | ||
1208 | |||
1209 | /* | ||
1210 | * We might have a pending scan which had no chance to run yet | ||
1211 | * due to work needing to be done. Hence, queue the STAs work | ||
1212 | * again for that. | ||
1213 | */ | ||
1214 | ieee80211_queue_work(&local->hw, &ifmgd->work); | ||
1215 | return RX_MGMT_CFG80211_ASSOC_TO; | ||
1216 | } | ||
1217 | |||
1218 | printk(KERN_DEBUG "%s: associate with AP %pM (try %d)\n", | ||
1219 | sdata->name, wk->bss->cbss.bssid, wk->tries); | ||
1220 | ieee80211_send_assoc(sdata, wk); | ||
1221 | |||
1222 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | ||
1223 | run_again(ifmgd, wk->timeout); | ||
1224 | |||
1225 | return RX_MGMT_NONE; | ||
1226 | } | ||
1227 | |||
1228 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 816 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
1229 | struct ieee80211_hdr *hdr) | 817 | struct ieee80211_hdr *hdr) |
1230 | { | 818 | { |
@@ -1248,8 +836,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1248 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 836 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1249 | const u8 *ssid; | 837 | const u8 *ssid; |
1250 | 838 | ||
1251 | ssid = ieee80211_bss_get_ie(&ifmgd->associated->cbss, WLAN_EID_SSID); | 839 | ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID); |
1252 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | 840 | ieee80211_send_probe_req(sdata, ifmgd->associated->bssid, |
1253 | ssid + 2, ssid[1], NULL, 0); | 841 | ssid + 2, ssid[1], NULL, 0); |
1254 | 842 | ||
1255 | ifmgd->probe_send_count++; | 843 | ifmgd->probe_send_count++; |
@@ -1263,12 +851,15 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
1263 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 851 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1264 | bool already = false; | 852 | bool already = false; |
1265 | 853 | ||
1266 | if (!netif_running(sdata->dev)) | 854 | if (!ieee80211_sdata_running(sdata)) |
1267 | return; | 855 | return; |
1268 | 856 | ||
1269 | if (sdata->local->scanning) | 857 | if (sdata->local->scanning) |
1270 | return; | 858 | return; |
1271 | 859 | ||
860 | if (sdata->local->tmp_channel) | ||
861 | return; | ||
862 | |||
1272 | mutex_lock(&ifmgd->mtx); | 863 | mutex_lock(&ifmgd->mtx); |
1273 | 864 | ||
1274 | if (!ifmgd->associated) | 865 | if (!ifmgd->associated) |
@@ -1330,88 +921,8 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif) | |||
1330 | } | 921 | } |
1331 | EXPORT_SYMBOL(ieee80211_beacon_loss); | 922 | EXPORT_SYMBOL(ieee80211_beacon_loss); |
1332 | 923 | ||
1333 | static void ieee80211_auth_completed(struct ieee80211_sub_if_data *sdata, | ||
1334 | struct ieee80211_mgd_work *wk) | ||
1335 | { | ||
1336 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1337 | printk(KERN_DEBUG "%s: authenticated\n", sdata->name); | ||
1338 | } | ||
1339 | |||
1340 | |||
1341 | static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, | ||
1342 | struct ieee80211_mgd_work *wk, | ||
1343 | struct ieee80211_mgmt *mgmt, | ||
1344 | size_t len) | ||
1345 | { | ||
1346 | u8 *pos; | ||
1347 | struct ieee802_11_elems elems; | ||
1348 | |||
1349 | pos = mgmt->u.auth.variable; | ||
1350 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1351 | if (!elems.challenge) | ||
1352 | return; | ||
1353 | ieee80211_send_auth(sdata, 3, wk->auth_alg, | ||
1354 | elems.challenge - 2, elems.challenge_len + 2, | ||
1355 | wk->bss->cbss.bssid, | ||
1356 | wk->key, wk->key_len, wk->key_idx); | ||
1357 | wk->auth_transaction = 4; | ||
1358 | } | ||
1359 | |||
1360 | static enum rx_mgmt_action __must_check | ||
1361 | ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | ||
1362 | struct ieee80211_mgd_work *wk, | ||
1363 | struct ieee80211_mgmt *mgmt, size_t len) | ||
1364 | { | ||
1365 | u16 auth_alg, auth_transaction, status_code; | ||
1366 | |||
1367 | if (wk->state != IEEE80211_MGD_STATE_AUTH) | ||
1368 | return RX_MGMT_NONE; | ||
1369 | |||
1370 | if (len < 24 + 6) | ||
1371 | return RX_MGMT_NONE; | ||
1372 | |||
1373 | if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) | ||
1374 | return RX_MGMT_NONE; | ||
1375 | |||
1376 | if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
1377 | return RX_MGMT_NONE; | ||
1378 | |||
1379 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
1380 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
1381 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
1382 | |||
1383 | if (auth_alg != wk->auth_alg || | ||
1384 | auth_transaction != wk->auth_transaction) | ||
1385 | return RX_MGMT_NONE; | ||
1386 | |||
1387 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
1388 | list_del(&wk->list); | ||
1389 | kfree(wk); | ||
1390 | return RX_MGMT_CFG80211_AUTH; | ||
1391 | } | ||
1392 | |||
1393 | switch (wk->auth_alg) { | ||
1394 | case WLAN_AUTH_OPEN: | ||
1395 | case WLAN_AUTH_LEAP: | ||
1396 | case WLAN_AUTH_FT: | ||
1397 | ieee80211_auth_completed(sdata, wk); | ||
1398 | return RX_MGMT_CFG80211_AUTH; | ||
1399 | case WLAN_AUTH_SHARED_KEY: | ||
1400 | if (wk->auth_transaction == 4) { | ||
1401 | ieee80211_auth_completed(sdata, wk); | ||
1402 | return RX_MGMT_CFG80211_AUTH; | ||
1403 | } else | ||
1404 | ieee80211_auth_challenge(sdata, wk, mgmt, len); | ||
1405 | break; | ||
1406 | } | ||
1407 | |||
1408 | return RX_MGMT_NONE; | ||
1409 | } | ||
1410 | |||
1411 | |||
1412 | static enum rx_mgmt_action __must_check | 924 | static enum rx_mgmt_action __must_check |
1413 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 925 | ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
1414 | struct ieee80211_mgd_work *wk, | ||
1415 | struct ieee80211_mgmt *mgmt, size_t len) | 926 | struct ieee80211_mgmt *mgmt, size_t len) |
1416 | { | 927 | { |
1417 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 928 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
@@ -1423,23 +934,15 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1423 | 934 | ||
1424 | ASSERT_MGD_MTX(ifmgd); | 935 | ASSERT_MGD_MTX(ifmgd); |
1425 | 936 | ||
1426 | if (wk) | 937 | bssid = ifmgd->associated->bssid; |
1427 | bssid = wk->bss->cbss.bssid; | ||
1428 | else | ||
1429 | bssid = ifmgd->associated->cbss.bssid; | ||
1430 | 938 | ||
1431 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 939 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1432 | 940 | ||
1433 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", | 941 | printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", |
1434 | sdata->name, bssid, reason_code); | 942 | sdata->name, bssid, reason_code); |
1435 | 943 | ||
1436 | if (!wk) { | 944 | ieee80211_set_disassoc(sdata); |
1437 | ieee80211_set_disassoc(sdata, true); | 945 | ieee80211_recalc_idle(sdata->local); |
1438 | ieee80211_recalc_idle(sdata->local); | ||
1439 | } else { | ||
1440 | list_del(&wk->list); | ||
1441 | kfree(wk); | ||
1442 | } | ||
1443 | 946 | ||
1444 | return RX_MGMT_CFG80211_DEAUTH; | 947 | return RX_MGMT_CFG80211_DEAUTH; |
1445 | } | 948 | } |
@@ -1460,7 +963,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1460 | if (WARN_ON(!ifmgd->associated)) | 963 | if (WARN_ON(!ifmgd->associated)) |
1461 | return RX_MGMT_NONE; | 964 | return RX_MGMT_NONE; |
1462 | 965 | ||
1463 | if (WARN_ON(memcmp(ifmgd->associated->cbss.bssid, mgmt->sa, ETH_ALEN))) | 966 | if (WARN_ON(memcmp(ifmgd->associated->bssid, mgmt->sa, ETH_ALEN))) |
1464 | return RX_MGMT_NONE; | 967 | return RX_MGMT_NONE; |
1465 | 968 | ||
1466 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 969 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
@@ -1468,96 +971,57 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1468 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", | 971 | printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", |
1469 | sdata->name, mgmt->sa, reason_code); | 972 | sdata->name, mgmt->sa, reason_code); |
1470 | 973 | ||
1471 | ieee80211_set_disassoc(sdata, false); | 974 | ieee80211_set_disassoc(sdata); |
1472 | ieee80211_recalc_idle(sdata->local); | 975 | ieee80211_recalc_idle(sdata->local); |
1473 | return RX_MGMT_CFG80211_DISASSOC; | 976 | return RX_MGMT_CFG80211_DISASSOC; |
1474 | } | 977 | } |
1475 | 978 | ||
1476 | 979 | ||
1477 | static enum rx_mgmt_action __must_check | 980 | static bool ieee80211_assoc_success(struct ieee80211_work *wk, |
1478 | ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | 981 | struct ieee80211_mgmt *mgmt, size_t len) |
1479 | struct ieee80211_mgd_work *wk, | ||
1480 | struct ieee80211_mgmt *mgmt, size_t len, | ||
1481 | bool reassoc) | ||
1482 | { | 982 | { |
983 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
1483 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 984 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1484 | struct ieee80211_local *local = sdata->local; | 985 | struct ieee80211_local *local = sdata->local; |
1485 | struct ieee80211_supported_band *sband; | 986 | struct ieee80211_supported_band *sband; |
1486 | struct sta_info *sta; | 987 | struct sta_info *sta; |
988 | struct cfg80211_bss *cbss = wk->assoc.bss; | ||
989 | u8 *pos; | ||
1487 | u32 rates, basic_rates; | 990 | u32 rates, basic_rates; |
1488 | u16 capab_info, status_code, aid; | 991 | u16 capab_info, aid; |
1489 | struct ieee802_11_elems elems; | 992 | struct ieee802_11_elems elems; |
1490 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; | 993 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1491 | u8 *pos; | ||
1492 | u32 changed = 0; | 994 | u32 changed = 0; |
1493 | int i, j, err; | 995 | int i, j, err; |
1494 | bool have_higher_than_11mbit = false; | 996 | bool have_higher_than_11mbit = false; |
1495 | u16 ap_ht_cap_flags; | 997 | u16 ap_ht_cap_flags; |
1496 | 998 | ||
1497 | /* | 999 | /* AssocResp and ReassocResp have identical structure */ |
1498 | * AssocResp and ReassocResp have identical structure, so process both | ||
1499 | * of them in this function. | ||
1500 | */ | ||
1501 | |||
1502 | if (len < 24 + 6) | ||
1503 | return RX_MGMT_NONE; | ||
1504 | 1000 | ||
1505 | if (memcmp(wk->bss->cbss.bssid, mgmt->sa, ETH_ALEN) != 0) | ||
1506 | return RX_MGMT_NONE; | ||
1507 | |||
1508 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | ||
1509 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
1510 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 1001 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
1511 | 1002 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | |
1512 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | ||
1513 | "status=%d aid=%d)\n", | ||
1514 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | ||
1515 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
1516 | |||
1517 | pos = mgmt->u.assoc_resp.variable; | ||
1518 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1519 | |||
1520 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
1521 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
1522 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
1523 | u32 tu, ms; | ||
1524 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
1525 | ms = tu * 1024 / 1000; | ||
1526 | printk(KERN_DEBUG "%s: AP rejected association temporarily; " | ||
1527 | "comeback duration %u TU (%u ms)\n", | ||
1528 | sdata->name, tu, ms); | ||
1529 | wk->timeout = jiffies + msecs_to_jiffies(ms); | ||
1530 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
1531 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); | ||
1532 | return RX_MGMT_NONE; | ||
1533 | } | ||
1534 | |||
1535 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
1536 | printk(KERN_DEBUG "%s: AP denied association (code=%d)\n", | ||
1537 | sdata->name, status_code); | ||
1538 | wk->state = IEEE80211_MGD_STATE_IDLE; | ||
1539 | return RX_MGMT_CFG80211_ASSOC; | ||
1540 | } | ||
1541 | 1003 | ||
1542 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) | 1004 | if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) |
1543 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " | 1005 | printk(KERN_DEBUG "%s: invalid aid value %d; bits 15:14 not " |
1544 | "set\n", sdata->name, aid); | 1006 | "set\n", sdata->name, aid); |
1545 | aid &= ~(BIT(15) | BIT(14)); | 1007 | aid &= ~(BIT(15) | BIT(14)); |
1546 | 1008 | ||
1009 | pos = mgmt->u.assoc_resp.variable; | ||
1010 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
1011 | |||
1547 | if (!elems.supp_rates) { | 1012 | if (!elems.supp_rates) { |
1548 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", | 1013 | printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n", |
1549 | sdata->name); | 1014 | sdata->name); |
1550 | return RX_MGMT_NONE; | 1015 | return false; |
1551 | } | 1016 | } |
1552 | 1017 | ||
1553 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | ||
1554 | ifmgd->aid = aid; | 1018 | ifmgd->aid = aid; |
1555 | 1019 | ||
1556 | sta = sta_info_alloc(sdata, wk->bss->cbss.bssid, GFP_KERNEL); | 1020 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); |
1557 | if (!sta) { | 1021 | if (!sta) { |
1558 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" | 1022 | printk(KERN_DEBUG "%s: failed to alloc STA entry for" |
1559 | " the AP\n", sdata->name); | 1023 | " the AP\n", sdata->name); |
1560 | return RX_MGMT_CFG80211_ASSOC_ERROR; | 1024 | return false; |
1561 | } | 1025 | } |
1562 | 1026 | ||
1563 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | | 1027 | set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | |
@@ -1641,22 +1105,19 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1641 | else | 1105 | else |
1642 | ieee80211_set_wmm_default(sdata); | 1106 | ieee80211_set_wmm_default(sdata); |
1643 | 1107 | ||
1108 | local->oper_channel = wk->chan; | ||
1109 | |||
1644 | if (elems.ht_info_elem && elems.wmm_param && | 1110 | if (elems.ht_info_elem && elems.wmm_param && |
1645 | (ifmgd->flags & IEEE80211_STA_WMM_ENABLED) && | 1111 | (sdata->local->hw.queues >= 4) && |
1646 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 1112 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) |
1647 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | 1113 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, |
1648 | wk->bss->cbss.bssid, | 1114 | cbss->bssid, ap_ht_cap_flags); |
1649 | ap_ht_cap_flags); | ||
1650 | |||
1651 | /* delete work item -- must be before set_associated for PS */ | ||
1652 | list_del(&wk->list); | ||
1653 | 1115 | ||
1654 | /* set AID and assoc capability, | 1116 | /* set AID and assoc capability, |
1655 | * ieee80211_set_associated() will tell the driver */ | 1117 | * ieee80211_set_associated() will tell the driver */ |
1656 | bss_conf->aid = aid; | 1118 | bss_conf->aid = aid; |
1657 | bss_conf->assoc_capability = capab_info; | 1119 | bss_conf->assoc_capability = capab_info; |
1658 | /* this will take ownership of wk */ | 1120 | ieee80211_set_associated(sdata, cbss, changed); |
1659 | ieee80211_set_associated(sdata, wk, changed); | ||
1660 | 1121 | ||
1661 | /* | 1122 | /* |
1662 | * Start timer to probe the connection to the AP now. | 1123 | * Start timer to probe the connection to the AP now. |
@@ -1665,7 +1126,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1665 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); | 1126 | ieee80211_sta_rx_notify(sdata, (struct ieee80211_hdr *)mgmt); |
1666 | mod_beacon_timer(sdata); | 1127 | mod_beacon_timer(sdata); |
1667 | 1128 | ||
1668 | return RX_MGMT_CFG80211_ASSOC; | 1129 | return true; |
1669 | } | 1130 | } |
1670 | 1131 | ||
1671 | 1132 | ||
@@ -1700,7 +1161,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1700 | return; | 1161 | return; |
1701 | 1162 | ||
1702 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && | 1163 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && |
1703 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->cbss.bssid, | 1164 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, |
1704 | ETH_ALEN) == 0)) { | 1165 | ETH_ALEN) == 0)) { |
1705 | struct ieee80211_channel_sw_ie *sw_elem = | 1166 | struct ieee80211_channel_sw_ie *sw_elem = |
1706 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; | 1167 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; |
@@ -1710,12 +1171,12 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1710 | 1171 | ||
1711 | 1172 | ||
1712 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | 1173 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, |
1713 | struct ieee80211_mgd_work *wk, | 1174 | struct sk_buff *skb) |
1714 | struct ieee80211_mgmt *mgmt, size_t len, | ||
1715 | struct ieee80211_rx_status *rx_status) | ||
1716 | { | 1175 | { |
1176 | struct ieee80211_mgmt *mgmt = (void *)skb->data; | ||
1717 | struct ieee80211_if_managed *ifmgd; | 1177 | struct ieee80211_if_managed *ifmgd; |
1718 | size_t baselen; | 1178 | struct ieee80211_rx_status *rx_status = (void *) skb->cb; |
1179 | size_t baselen, len = skb->len; | ||
1719 | struct ieee802_11_elems elems; | 1180 | struct ieee802_11_elems elems; |
1720 | 1181 | ||
1721 | ifmgd = &sdata->u.mgd; | 1182 | ifmgd = &sdata->u.mgd; |
@@ -1734,17 +1195,8 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
1734 | 1195 | ||
1735 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); | 1196 | ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, false); |
1736 | 1197 | ||
1737 | /* direct probe may be part of the association flow */ | ||
1738 | if (wk && wk->state == IEEE80211_MGD_STATE_PROBE) { | ||
1739 | printk(KERN_DEBUG "%s: direct probe responded\n", | ||
1740 | sdata->name); | ||
1741 | wk->tries = 0; | ||
1742 | wk->state = IEEE80211_MGD_STATE_AUTH; | ||
1743 | WARN_ON(ieee80211_authenticate(sdata, wk) != RX_MGMT_NONE); | ||
1744 | } | ||
1745 | |||
1746 | if (ifmgd->associated && | 1198 | if (ifmgd->associated && |
1747 | memcmp(mgmt->bssid, ifmgd->associated->cbss.bssid, ETH_ALEN) == 0 && | 1199 | memcmp(mgmt->bssid, ifmgd->associated->bssid, ETH_ALEN) == 0 && |
1748 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | | 1200 | ifmgd->flags & (IEEE80211_STA_BEACON_POLL | |
1749 | IEEE80211_STA_CONNECTION_POLL)) { | 1201 | IEEE80211_STA_CONNECTION_POLL)) { |
1750 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | | 1202 | ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | |
@@ -1817,7 +1269,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1817 | if (!ifmgd->associated) | 1269 | if (!ifmgd->associated) |
1818 | return; | 1270 | return; |
1819 | 1271 | ||
1820 | bssid = ifmgd->associated->cbss.bssid; | 1272 | bssid = ifmgd->associated->bssid; |
1821 | 1273 | ||
1822 | /* | 1274 | /* |
1823 | * And in theory even frames from a different AP we were just | 1275 | * And in theory even frames from a different AP we were just |
@@ -1956,9 +1408,6 @@ ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1956 | switch (fc & IEEE80211_FCTL_STYPE) { | 1408 | switch (fc & IEEE80211_FCTL_STYPE) { |
1957 | case IEEE80211_STYPE_PROBE_RESP: | 1409 | case IEEE80211_STYPE_PROBE_RESP: |
1958 | case IEEE80211_STYPE_BEACON: | 1410 | case IEEE80211_STYPE_BEACON: |
1959 | case IEEE80211_STYPE_AUTH: | ||
1960 | case IEEE80211_STYPE_ASSOC_RESP: | ||
1961 | case IEEE80211_STYPE_REASSOC_RESP: | ||
1962 | case IEEE80211_STYPE_DEAUTH: | 1411 | case IEEE80211_STYPE_DEAUTH: |
1963 | case IEEE80211_STYPE_DISASSOC: | 1412 | case IEEE80211_STYPE_DISASSOC: |
1964 | case IEEE80211_STYPE_ACTION: | 1413 | case IEEE80211_STYPE_ACTION: |
@@ -1976,7 +1425,6 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1976 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1425 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1977 | struct ieee80211_rx_status *rx_status; | 1426 | struct ieee80211_rx_status *rx_status; |
1978 | struct ieee80211_mgmt *mgmt; | 1427 | struct ieee80211_mgmt *mgmt; |
1979 | struct ieee80211_mgd_work *wk; | ||
1980 | enum rx_mgmt_action rma = RX_MGMT_NONE; | 1428 | enum rx_mgmt_action rma = RX_MGMT_NONE; |
1981 | u16 fc; | 1429 | u16 fc; |
1982 | 1430 | ||
@@ -1987,20 +1435,17 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
1987 | mutex_lock(&ifmgd->mtx); | 1435 | mutex_lock(&ifmgd->mtx); |
1988 | 1436 | ||
1989 | if (ifmgd->associated && | 1437 | if (ifmgd->associated && |
1990 | memcmp(ifmgd->associated->cbss.bssid, mgmt->bssid, | 1438 | memcmp(ifmgd->associated->bssid, mgmt->bssid, ETH_ALEN) == 0) { |
1991 | ETH_ALEN) == 0) { | ||
1992 | switch (fc & IEEE80211_FCTL_STYPE) { | 1439 | switch (fc & IEEE80211_FCTL_STYPE) { |
1993 | case IEEE80211_STYPE_BEACON: | 1440 | case IEEE80211_STYPE_BEACON: |
1994 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, | 1441 | ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, |
1995 | rx_status); | 1442 | rx_status); |
1996 | break; | 1443 | break; |
1997 | case IEEE80211_STYPE_PROBE_RESP: | 1444 | case IEEE80211_STYPE_PROBE_RESP: |
1998 | ieee80211_rx_mgmt_probe_resp(sdata, NULL, mgmt, | 1445 | ieee80211_rx_mgmt_probe_resp(sdata, skb); |
1999 | skb->len, rx_status); | ||
2000 | break; | 1446 | break; |
2001 | case IEEE80211_STYPE_DEAUTH: | 1447 | case IEEE80211_STYPE_DEAUTH: |
2002 | rma = ieee80211_rx_mgmt_deauth(sdata, NULL, | 1448 | rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len); |
2003 | mgmt, skb->len); | ||
2004 | break; | 1449 | break; |
2005 | case IEEE80211_STYPE_DISASSOC: | 1450 | case IEEE80211_STYPE_DISASSOC: |
2006 | rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); | 1451 | rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len); |
@@ -2009,7 +1454,7 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2009 | /* XXX: differentiate, can only happen for CSA now! */ | 1454 | /* XXX: differentiate, can only happen for CSA now! */ |
2010 | ieee80211_sta_process_chanswitch(sdata, | 1455 | ieee80211_sta_process_chanswitch(sdata, |
2011 | &mgmt->u.action.u.chan_switch.sw_elem, | 1456 | &mgmt->u.action.u.chan_switch.sw_elem, |
2012 | ifmgd->associated); | 1457 | (void *)ifmgd->associated->priv); |
2013 | break; | 1458 | break; |
2014 | } | 1459 | } |
2015 | mutex_unlock(&ifmgd->mtx); | 1460 | mutex_unlock(&ifmgd->mtx); |
@@ -2030,62 +1475,11 @@ static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
2030 | goto out; | 1475 | goto out; |
2031 | } | 1476 | } |
2032 | 1477 | ||
2033 | list_for_each_entry(wk, &ifmgd->work_list, list) { | ||
2034 | if (memcmp(wk->bss->cbss.bssid, mgmt->bssid, ETH_ALEN) != 0) | ||
2035 | continue; | ||
2036 | |||
2037 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
2038 | case IEEE80211_STYPE_PROBE_RESP: | ||
2039 | ieee80211_rx_mgmt_probe_resp(sdata, wk, mgmt, skb->len, | ||
2040 | rx_status); | ||
2041 | break; | ||
2042 | case IEEE80211_STYPE_AUTH: | ||
2043 | rma = ieee80211_rx_mgmt_auth(sdata, wk, mgmt, skb->len); | ||
2044 | break; | ||
2045 | case IEEE80211_STYPE_ASSOC_RESP: | ||
2046 | rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt, | ||
2047 | skb->len, false); | ||
2048 | break; | ||
2049 | case IEEE80211_STYPE_REASSOC_RESP: | ||
2050 | rma = ieee80211_rx_mgmt_assoc_resp(sdata, wk, mgmt, | ||
2051 | skb->len, true); | ||
2052 | break; | ||
2053 | case IEEE80211_STYPE_DEAUTH: | ||
2054 | rma = ieee80211_rx_mgmt_deauth(sdata, wk, mgmt, | ||
2055 | skb->len); | ||
2056 | break; | ||
2057 | } | ||
2058 | /* | ||
2059 | * We've processed this frame for that work, so it can't | ||
2060 | * belong to another work struct. | ||
2061 | * NB: this is also required for correctness because the | ||
2062 | * called functions can free 'wk', and for 'rma'! | ||
2063 | */ | ||
2064 | break; | ||
2065 | } | ||
2066 | |||
2067 | mutex_unlock(&ifmgd->mtx); | 1478 | mutex_unlock(&ifmgd->mtx); |
2068 | 1479 | ||
2069 | switch (rma) { | 1480 | if (skb->len >= 24 + 2 /* mgmt + deauth reason */ && |
2070 | case RX_MGMT_NONE: | 1481 | (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH) |
2071 | /* no action */ | ||
2072 | break; | ||
2073 | case RX_MGMT_CFG80211_AUTH: | ||
2074 | cfg80211_send_rx_auth(sdata->dev, (u8 *) mgmt, skb->len); | ||
2075 | break; | ||
2076 | case RX_MGMT_CFG80211_ASSOC: | ||
2077 | cfg80211_send_rx_assoc(sdata->dev, (u8 *) mgmt, skb->len); | ||
2078 | break; | ||
2079 | case RX_MGMT_CFG80211_DEAUTH: | ||
2080 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); | 1482 | cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len); |
2081 | break; | ||
2082 | case RX_MGMT_CFG80211_ASSOC_ERROR: | ||
2083 | /* an internal error -- pretend timeout for now */ | ||
2084 | cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid); | ||
2085 | break; | ||
2086 | default: | ||
2087 | WARN(1, "unexpected: %d", rma); | ||
2088 | } | ||
2089 | 1483 | ||
2090 | out: | 1484 | out: |
2091 | kfree_skb(skb); | 1485 | kfree_skb(skb); |
@@ -2113,12 +1507,8 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2113 | struct ieee80211_local *local = sdata->local; | 1507 | struct ieee80211_local *local = sdata->local; |
2114 | struct ieee80211_if_managed *ifmgd; | 1508 | struct ieee80211_if_managed *ifmgd; |
2115 | struct sk_buff *skb; | 1509 | struct sk_buff *skb; |
2116 | struct ieee80211_mgd_work *wk, *tmp; | ||
2117 | LIST_HEAD(free_work); | ||
2118 | enum rx_mgmt_action rma; | ||
2119 | bool anybusy = false; | ||
2120 | 1510 | ||
2121 | if (!netif_running(sdata->dev)) | 1511 | if (!ieee80211_sdata_running(sdata)) |
2122 | return; | 1512 | return; |
2123 | 1513 | ||
2124 | if (local->scanning) | 1514 | if (local->scanning) |
@@ -2149,7 +1539,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2149 | ifmgd->associated) { | 1539 | ifmgd->associated) { |
2150 | u8 bssid[ETH_ALEN]; | 1540 | u8 bssid[ETH_ALEN]; |
2151 | 1541 | ||
2152 | memcpy(bssid, ifmgd->associated->cbss.bssid, ETH_ALEN); | 1542 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); |
2153 | if (time_is_after_jiffies(ifmgd->probe_timeout)) | 1543 | if (time_is_after_jiffies(ifmgd->probe_timeout)) |
2154 | run_again(ifmgd, ifmgd->probe_timeout); | 1544 | run_again(ifmgd, ifmgd->probe_timeout); |
2155 | 1545 | ||
@@ -2171,7 +1561,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2171 | printk(KERN_DEBUG "No probe response from AP %pM" | 1561 | printk(KERN_DEBUG "No probe response from AP %pM" |
2172 | " after %dms, disconnecting.\n", | 1562 | " after %dms, disconnecting.\n", |
2173 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); | 1563 | bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); |
2174 | ieee80211_set_disassoc(sdata, true); | 1564 | ieee80211_set_disassoc(sdata); |
2175 | ieee80211_recalc_idle(local); | 1565 | ieee80211_recalc_idle(local); |
2176 | mutex_unlock(&ifmgd->mtx); | 1566 | mutex_unlock(&ifmgd->mtx); |
2177 | /* | 1567 | /* |
@@ -2186,87 +1576,7 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
2186 | } | 1576 | } |
2187 | } | 1577 | } |
2188 | 1578 | ||
2189 | |||
2190 | ieee80211_recalc_idle(local); | ||
2191 | |||
2192 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { | ||
2193 | if (time_is_after_jiffies(wk->timeout)) { | ||
2194 | /* | ||
2195 | * This work item isn't supposed to be worked on | ||
2196 | * right now, but take care to adjust the timer | ||
2197 | * properly. | ||
2198 | */ | ||
2199 | run_again(ifmgd, wk->timeout); | ||
2200 | continue; | ||
2201 | } | ||
2202 | |||
2203 | switch (wk->state) { | ||
2204 | default: | ||
2205 | WARN_ON(1); | ||
2206 | /* fall through */ | ||
2207 | case IEEE80211_MGD_STATE_IDLE: | ||
2208 | /* nothing */ | ||
2209 | rma = RX_MGMT_NONE; | ||
2210 | break; | ||
2211 | case IEEE80211_MGD_STATE_PROBE: | ||
2212 | rma = ieee80211_direct_probe(sdata, wk); | ||
2213 | break; | ||
2214 | case IEEE80211_MGD_STATE_AUTH: | ||
2215 | rma = ieee80211_authenticate(sdata, wk); | ||
2216 | break; | ||
2217 | case IEEE80211_MGD_STATE_ASSOC: | ||
2218 | rma = ieee80211_associate(sdata, wk); | ||
2219 | break; | ||
2220 | } | ||
2221 | |||
2222 | switch (rma) { | ||
2223 | case RX_MGMT_NONE: | ||
2224 | /* no action required */ | ||
2225 | break; | ||
2226 | case RX_MGMT_CFG80211_AUTH_TO: | ||
2227 | case RX_MGMT_CFG80211_ASSOC_TO: | ||
2228 | list_del(&wk->list); | ||
2229 | list_add(&wk->list, &free_work); | ||
2230 | wk->tries = rma; /* small abuse but only local */ | ||
2231 | break; | ||
2232 | default: | ||
2233 | WARN(1, "unexpected: %d", rma); | ||
2234 | } | ||
2235 | } | ||
2236 | |||
2237 | list_for_each_entry(wk, &ifmgd->work_list, list) { | ||
2238 | if (wk->state != IEEE80211_MGD_STATE_IDLE) { | ||
2239 | anybusy = true; | ||
2240 | break; | ||
2241 | } | ||
2242 | } | ||
2243 | if (!anybusy && | ||
2244 | test_and_clear_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request)) | ||
2245 | ieee80211_queue_delayed_work(&local->hw, | ||
2246 | &local->scan_work, | ||
2247 | round_jiffies_relative(0)); | ||
2248 | |||
2249 | mutex_unlock(&ifmgd->mtx); | 1579 | mutex_unlock(&ifmgd->mtx); |
2250 | |||
2251 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | ||
2252 | switch (wk->tries) { | ||
2253 | case RX_MGMT_CFG80211_AUTH_TO: | ||
2254 | cfg80211_send_auth_timeout(sdata->dev, | ||
2255 | wk->bss->cbss.bssid); | ||
2256 | break; | ||
2257 | case RX_MGMT_CFG80211_ASSOC_TO: | ||
2258 | cfg80211_send_assoc_timeout(sdata->dev, | ||
2259 | wk->bss->cbss.bssid); | ||
2260 | break; | ||
2261 | default: | ||
2262 | WARN(1, "unexpected: %d", wk->tries); | ||
2263 | } | ||
2264 | |||
2265 | list_del(&wk->list); | ||
2266 | kfree(wk); | ||
2267 | } | ||
2268 | |||
2269 | ieee80211_recalc_idle(local); | ||
2270 | } | 1580 | } |
2271 | 1581 | ||
2272 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) | 1582 | static void ieee80211_sta_bcn_mon_timer(unsigned long data) |
@@ -2375,12 +1685,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2375 | (unsigned long) sdata); | 1685 | (unsigned long) sdata); |
2376 | skb_queue_head_init(&ifmgd->skb_queue); | 1686 | skb_queue_head_init(&ifmgd->skb_queue); |
2377 | 1687 | ||
2378 | INIT_LIST_HEAD(&ifmgd->work_list); | ||
2379 | |||
2380 | ifmgd->capab = WLAN_CAPABILITY_ESS; | ||
2381 | ifmgd->flags = 0; | 1688 | ifmgd->flags = 0; |
2382 | if (sdata->local->hw.queues >= 4) | ||
2383 | ifmgd->flags |= IEEE80211_STA_WMM_ENABLED; | ||
2384 | 1689 | ||
2385 | mutex_init(&ifmgd->mtx); | 1690 | mutex_init(&ifmgd->mtx); |
2386 | 1691 | ||
@@ -2418,12 +1723,34 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
2418 | } | 1723 | } |
2419 | 1724 | ||
2420 | /* config hooks */ | 1725 | /* config hooks */ |
1726 | static enum work_done_result | ||
1727 | ieee80211_probe_auth_done(struct ieee80211_work *wk, | ||
1728 | struct sk_buff *skb) | ||
1729 | { | ||
1730 | if (!skb) { | ||
1731 | cfg80211_send_auth_timeout(wk->sdata->dev, wk->filter_ta); | ||
1732 | return WORK_DONE_DESTROY; | ||
1733 | } | ||
1734 | |||
1735 | if (wk->type == IEEE80211_WORK_AUTH) { | ||
1736 | cfg80211_send_rx_auth(wk->sdata->dev, skb->data, skb->len); | ||
1737 | return WORK_DONE_DESTROY; | ||
1738 | } | ||
1739 | |||
1740 | mutex_lock(&wk->sdata->u.mgd.mtx); | ||
1741 | ieee80211_rx_mgmt_probe_resp(wk->sdata, skb); | ||
1742 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
1743 | |||
1744 | wk->type = IEEE80211_WORK_AUTH; | ||
1745 | wk->probe_auth.tries = 0; | ||
1746 | return WORK_DONE_REQUEUE; | ||
1747 | } | ||
1748 | |||
2421 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | 1749 | int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, |
2422 | struct cfg80211_auth_request *req) | 1750 | struct cfg80211_auth_request *req) |
2423 | { | 1751 | { |
2424 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
2425 | const u8 *ssid; | 1752 | const u8 *ssid; |
2426 | struct ieee80211_mgd_work *wk; | 1753 | struct ieee80211_work *wk; |
2427 | u16 auth_alg; | 1754 | u16 auth_alg; |
2428 | 1755 | ||
2429 | switch (req->auth_type) { | 1756 | switch (req->auth_type) { |
@@ -2447,7 +1774,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2447 | if (!wk) | 1774 | if (!wk) |
2448 | return -ENOMEM; | 1775 | return -ENOMEM; |
2449 | 1776 | ||
2450 | wk->bss = (void *)req->bss; | 1777 | memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN);; |
2451 | 1778 | ||
2452 | if (req->ie && req->ie_len) { | 1779 | if (req->ie && req->ie_len) { |
2453 | memcpy(wk->ie, req->ie, req->ie_len); | 1780 | memcpy(wk->ie, req->ie, req->ie_len); |
@@ -2455,66 +1782,76 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, | |||
2455 | } | 1782 | } |
2456 | 1783 | ||
2457 | if (req->key && req->key_len) { | 1784 | if (req->key && req->key_len) { |
2458 | wk->key_len = req->key_len; | 1785 | wk->probe_auth.key_len = req->key_len; |
2459 | wk->key_idx = req->key_idx; | 1786 | wk->probe_auth.key_idx = req->key_idx; |
2460 | memcpy(wk->key, req->key, req->key_len); | 1787 | memcpy(wk->probe_auth.key, req->key, req->key_len); |
2461 | } | 1788 | } |
2462 | 1789 | ||
2463 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | 1790 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); |
2464 | memcpy(wk->ssid, ssid + 2, ssid[1]); | 1791 | memcpy(wk->probe_auth.ssid, ssid + 2, ssid[1]); |
2465 | wk->ssid_len = ssid[1]; | 1792 | wk->probe_auth.ssid_len = ssid[1]; |
2466 | 1793 | ||
2467 | wk->state = IEEE80211_MGD_STATE_PROBE; | 1794 | wk->probe_auth.algorithm = auth_alg; |
2468 | wk->auth_alg = auth_alg; | 1795 | wk->probe_auth.privacy = req->bss->capability & WLAN_CAPABILITY_PRIVACY; |
2469 | wk->timeout = jiffies; /* run right away */ | ||
2470 | 1796 | ||
2471 | /* | 1797 | wk->type = IEEE80211_WORK_DIRECT_PROBE; |
2472 | * XXX: if still associated need to tell AP that we're going | 1798 | wk->chan = req->bss->channel; |
2473 | * to sleep and then change channel etc. | 1799 | wk->sdata = sdata; |
2474 | */ | 1800 | wk->done = ieee80211_probe_auth_done; |
2475 | sdata->local->oper_channel = req->bss->channel; | ||
2476 | ieee80211_hw_config(sdata->local, 0); | ||
2477 | 1801 | ||
2478 | mutex_lock(&ifmgd->mtx); | 1802 | ieee80211_add_work(wk); |
2479 | list_add(&wk->list, &sdata->u.mgd.work_list); | ||
2480 | mutex_unlock(&ifmgd->mtx); | ||
2481 | |||
2482 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); | ||
2483 | return 0; | 1803 | return 0; |
2484 | } | 1804 | } |
2485 | 1805 | ||
2486 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | 1806 | static enum work_done_result ieee80211_assoc_done(struct ieee80211_work *wk, |
2487 | struct cfg80211_assoc_request *req) | 1807 | struct sk_buff *skb) |
2488 | { | 1808 | { |
2489 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1809 | struct ieee80211_mgmt *mgmt; |
2490 | struct ieee80211_mgd_work *wk, *found = NULL; | 1810 | u16 status; |
2491 | int i, err; | ||
2492 | 1811 | ||
2493 | mutex_lock(&ifmgd->mtx); | 1812 | if (!skb) { |
1813 | cfg80211_send_assoc_timeout(wk->sdata->dev, wk->filter_ta); | ||
1814 | return WORK_DONE_DESTROY; | ||
1815 | } | ||
2494 | 1816 | ||
2495 | list_for_each_entry(wk, &ifmgd->work_list, list) { | 1817 | mgmt = (void *)skb->data; |
2496 | if (&wk->bss->cbss == req->bss && | 1818 | status = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
2497 | wk->state == IEEE80211_MGD_STATE_IDLE) { | 1819 | |
2498 | found = wk; | 1820 | if (status == WLAN_STATUS_SUCCESS) { |
2499 | break; | 1821 | mutex_lock(&wk->sdata->u.mgd.mtx); |
1822 | if (!ieee80211_assoc_success(wk, mgmt, skb->len)) { | ||
1823 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
1824 | /* oops -- internal error -- send timeout for now */ | ||
1825 | cfg80211_send_assoc_timeout(wk->sdata->dev, | ||
1826 | wk->filter_ta); | ||
1827 | return WORK_DONE_DESTROY; | ||
2500 | } | 1828 | } |
1829 | mutex_unlock(&wk->sdata->u.mgd.mtx); | ||
2501 | } | 1830 | } |
2502 | 1831 | ||
2503 | if (!found) { | 1832 | cfg80211_send_rx_assoc(wk->sdata->dev, skb->data, skb->len); |
2504 | err = -ENOLINK; | 1833 | return WORK_DONE_DESTROY; |
2505 | goto out; | 1834 | } |
2506 | } | ||
2507 | 1835 | ||
2508 | list_del(&found->list); | 1836 | int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, |
1837 | struct cfg80211_assoc_request *req) | ||
1838 | { | ||
1839 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
1840 | struct ieee80211_bss *bss = (void *)req->bss->priv; | ||
1841 | struct ieee80211_work *wk; | ||
1842 | const u8 *ssid; | ||
1843 | int i; | ||
2509 | 1844 | ||
2510 | wk = krealloc(found, sizeof(*wk) + req->ie_len, GFP_KERNEL); | 1845 | mutex_lock(&ifmgd->mtx); |
2511 | if (!wk) { | 1846 | if (ifmgd->associated) { |
2512 | list_add(&found->list, &ifmgd->work_list); | 1847 | mutex_unlock(&ifmgd->mtx); |
2513 | err = -ENOMEM; | 1848 | return -EALREADY; |
2514 | goto out; | ||
2515 | } | 1849 | } |
1850 | mutex_unlock(&ifmgd->mtx); | ||
2516 | 1851 | ||
2517 | list_add(&wk->list, &ifmgd->work_list); | 1852 | wk = kzalloc(sizeof(*wk) + req->ie_len, GFP_KERNEL); |
1853 | if (!wk) | ||
1854 | return -ENOMEM; | ||
2518 | 1855 | ||
2519 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 1856 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; |
2520 | 1857 | ||
@@ -2524,8 +1861,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2524 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) | 1861 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) |
2525 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 1862 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
2526 | 1863 | ||
2527 | sdata->local->oper_channel = req->bss->channel; | ||
2528 | ieee80211_hw_config(sdata->local, 0); | ||
2529 | 1864 | ||
2530 | if (req->ie && req->ie_len) { | 1865 | if (req->ie && req->ie_len) { |
2531 | memcpy(wk->ie, req->ie, req->ie_len); | 1866 | memcpy(wk->ie, req->ie, req->ie_len); |
@@ -2533,12 +1868,46 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2533 | } else | 1868 | } else |
2534 | wk->ie_len = 0; | 1869 | wk->ie_len = 0; |
2535 | 1870 | ||
1871 | wk->assoc.bss = req->bss; | ||
1872 | |||
1873 | memcpy(wk->filter_ta, req->bss->bssid, ETH_ALEN); | ||
1874 | |||
1875 | /* new association always uses requested smps mode */ | ||
1876 | if (ifmgd->req_smps == IEEE80211_SMPS_AUTOMATIC) { | ||
1877 | if (ifmgd->powersave) | ||
1878 | ifmgd->ap_smps = IEEE80211_SMPS_DYNAMIC; | ||
1879 | else | ||
1880 | ifmgd->ap_smps = IEEE80211_SMPS_OFF; | ||
1881 | } else | ||
1882 | ifmgd->ap_smps = ifmgd->req_smps; | ||
1883 | |||
1884 | wk->assoc.smps = ifmgd->ap_smps; | ||
1885 | /* | ||
1886 | * IEEE802.11n does not allow TKIP/WEP as pairwise ciphers in HT mode. | ||
1887 | * We still associate in non-HT mode (11a/b/g) if any one of these | ||
1888 | * ciphers is configured as pairwise. | ||
1889 | * We can set this to true for non-11n hardware, that'll be checked | ||
1890 | * separately along with the peer capabilities. | ||
1891 | */ | ||
1892 | wk->assoc.use_11n = !(ifmgd->flags & IEEE80211_STA_DISABLE_11N); | ||
1893 | wk->assoc.capability = req->bss->capability; | ||
1894 | wk->assoc.wmm_used = bss->wmm_used; | ||
1895 | wk->assoc.supp_rates = bss->supp_rates; | ||
1896 | wk->assoc.supp_rates_len = bss->supp_rates_len; | ||
1897 | wk->assoc.ht_information_ie = | ||
1898 | ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION); | ||
1899 | |||
1900 | ssid = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); | ||
1901 | memcpy(wk->assoc.ssid, ssid + 2, ssid[1]); | ||
1902 | wk->assoc.ssid_len = ssid[1]; | ||
1903 | |||
2536 | if (req->prev_bssid) | 1904 | if (req->prev_bssid) |
2537 | memcpy(wk->prev_bssid, req->prev_bssid, ETH_ALEN); | 1905 | memcpy(wk->assoc.prev_bssid, req->prev_bssid, ETH_ALEN); |
2538 | 1906 | ||
2539 | wk->state = IEEE80211_MGD_STATE_ASSOC; | 1907 | wk->type = IEEE80211_WORK_ASSOC; |
2540 | wk->tries = 0; | 1908 | wk->chan = req->bss->channel; |
2541 | wk->timeout = jiffies; /* run right away */ | 1909 | wk->sdata = sdata; |
1910 | wk->done = ieee80211_assoc_done; | ||
2542 | 1911 | ||
2543 | if (req->use_mfp) { | 1912 | if (req->use_mfp) { |
2544 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; | 1913 | ifmgd->mfp = IEEE80211_MFP_REQUIRED; |
@@ -2553,67 +1922,57 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
2553 | else | 1922 | else |
2554 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; | 1923 | ifmgd->flags &= ~IEEE80211_STA_CONTROL_PORT; |
2555 | 1924 | ||
2556 | ieee80211_queue_work(&sdata->local->hw, &sdata->u.mgd.work); | 1925 | ieee80211_add_work(wk); |
2557 | 1926 | return 0; | |
2558 | err = 0; | ||
2559 | |||
2560 | out: | ||
2561 | mutex_unlock(&ifmgd->mtx); | ||
2562 | return err; | ||
2563 | } | 1927 | } |
2564 | 1928 | ||
2565 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | 1929 | int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, |
2566 | struct cfg80211_deauth_request *req, | 1930 | struct cfg80211_deauth_request *req, |
2567 | void *cookie) | 1931 | void *cookie) |
2568 | { | 1932 | { |
1933 | struct ieee80211_local *local = sdata->local; | ||
2569 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1934 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2570 | struct ieee80211_mgd_work *wk; | 1935 | struct ieee80211_work *wk; |
2571 | const u8 *bssid = NULL; | 1936 | const u8 *bssid = req->bss->bssid; |
2572 | bool not_auth_yet = false; | ||
2573 | 1937 | ||
2574 | mutex_lock(&ifmgd->mtx); | 1938 | mutex_lock(&ifmgd->mtx); |
2575 | 1939 | ||
2576 | if (ifmgd->associated && &ifmgd->associated->cbss == req->bss) { | 1940 | if (ifmgd->associated == req->bss) { |
2577 | bssid = req->bss->bssid; | 1941 | bssid = req->bss->bssid; |
2578 | ieee80211_set_disassoc(sdata, true); | 1942 | ieee80211_set_disassoc(sdata); |
2579 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { | 1943 | mutex_unlock(&ifmgd->mtx); |
2580 | if (&wk->bss->cbss == req->bss) { | 1944 | } else { |
2581 | bssid = req->bss->bssid; | 1945 | bool not_auth_yet = false; |
2582 | if (wk->state == IEEE80211_MGD_STATE_PROBE) | 1946 | |
2583 | not_auth_yet = true; | 1947 | mutex_unlock(&ifmgd->mtx); |
1948 | |||
1949 | mutex_lock(&local->work_mtx); | ||
1950 | list_for_each_entry(wk, &local->work_list, list) { | ||
1951 | if (wk->type != IEEE80211_WORK_DIRECT_PROBE) | ||
1952 | continue; | ||
1953 | if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN)) | ||
1954 | continue; | ||
1955 | not_auth_yet = true; | ||
2584 | list_del(&wk->list); | 1956 | list_del(&wk->list); |
2585 | kfree(wk); | 1957 | free_work(wk); |
2586 | break; | 1958 | break; |
2587 | } | 1959 | } |
2588 | } | 1960 | mutex_unlock(&local->work_mtx); |
2589 | 1961 | ||
2590 | /* | 1962 | /* |
2591 | * If somebody requests authentication and we haven't | 1963 | * If somebody requests authentication and we haven't |
2592 | * sent out an auth frame yet there's no need to send | 1964 | * sent out an auth frame yet there's no need to send |
2593 | * out a deauth frame either. If the state was PROBE, | 1965 | * out a deauth frame either. If the state was PROBE, |
2594 | * then this is the case. If it's AUTH we have sent a | 1966 | * then this is the case. If it's AUTH we have sent a |
2595 | * frame, and if it's IDLE we have completed the auth | 1967 | * frame, and if it's IDLE we have completed the auth |
2596 | * process already. | 1968 | * process already. |
2597 | */ | 1969 | */ |
2598 | if (not_auth_yet) { | 1970 | if (not_auth_yet) { |
2599 | mutex_unlock(&ifmgd->mtx); | 1971 | __cfg80211_auth_canceled(sdata->dev, bssid); |
2600 | __cfg80211_auth_canceled(sdata->dev, bssid); | 1972 | return 0; |
2601 | return 0; | 1973 | } |
2602 | } | ||
2603 | |||
2604 | /* | ||
2605 | * cfg80211 should catch this ... but it's racy since | ||
2606 | * we can receive a deauth frame, process it, hand it | ||
2607 | * to cfg80211 while that's in a locked section already | ||
2608 | * trying to tell us that the user wants to disconnect. | ||
2609 | */ | ||
2610 | if (!bssid) { | ||
2611 | mutex_unlock(&ifmgd->mtx); | ||
2612 | return -ENOLINK; | ||
2613 | } | 1974 | } |
2614 | 1975 | ||
2615 | mutex_unlock(&ifmgd->mtx); | ||
2616 | |||
2617 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", | 1976 | printk(KERN_DEBUG "%s: deauthenticating from %pM by local choice (reason=%d)\n", |
2618 | sdata->name, bssid, req->reason_code); | 1977 | sdata->name, bssid, req->reason_code); |
2619 | 1978 | ||
@@ -2640,7 +1999,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2640 | * to cfg80211 while that's in a locked section already | 1999 | * to cfg80211 while that's in a locked section already |
2641 | * trying to tell us that the user wants to disconnect. | 2000 | * trying to tell us that the user wants to disconnect. |
2642 | */ | 2001 | */ |
2643 | if (&ifmgd->associated->cbss != req->bss) { | 2002 | if (ifmgd->associated != req->bss) { |
2644 | mutex_unlock(&ifmgd->mtx); | 2003 | mutex_unlock(&ifmgd->mtx); |
2645 | return -ENOLINK; | 2004 | return -ENOLINK; |
2646 | } | 2005 | } |
@@ -2648,7 +2007,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
2648 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", | 2007 | printk(KERN_DEBUG "%s: disassociating from %pM by local choice (reason=%d)\n", |
2649 | sdata->name, req->bss->bssid, req->reason_code); | 2008 | sdata->name, req->bss->bssid, req->reason_code); |
2650 | 2009 | ||
2651 | ieee80211_set_disassoc(sdata, false); | 2010 | ieee80211_set_disassoc(sdata); |
2652 | 2011 | ||
2653 | mutex_unlock(&ifmgd->mtx); | 2012 | mutex_unlock(&ifmgd->mtx); |
2654 | 2013 | ||
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c new file mode 100644 index 000000000000..a7bbfc40a648 --- /dev/null +++ b/net/mac80211/offchannel.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Off-channel operation helpers | ||
3 | * | ||
4 | * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | #include <net/mac80211.h> | ||
16 | #include "ieee80211_i.h" | ||
17 | |||
18 | /* | ||
19 | * inform AP that we will go to sleep so that it will buffer the frames | ||
20 | * while we scan | ||
21 | */ | ||
22 | static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | ||
23 | { | ||
24 | struct ieee80211_local *local = sdata->local; | ||
25 | |||
26 | local->offchannel_ps_enabled = false; | ||
27 | |||
28 | /* FIXME: what to do when local->pspolling is true? */ | ||
29 | |||
30 | del_timer_sync(&local->dynamic_ps_timer); | ||
31 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
32 | |||
33 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
34 | local->offchannel_ps_enabled = true; | ||
35 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
36 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
37 | } | ||
38 | |||
39 | if (!(local->offchannel_ps_enabled) || | ||
40 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | ||
41 | /* | ||
42 | * If power save was enabled, no need to send a nullfunc | ||
43 | * frame because AP knows that we are sleeping. But if the | ||
44 | * hardware is creating the nullfunc frame for power save | ||
45 | * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not | ||
46 | * enabled) and power save was enabled, the firmware just | ||
47 | * sent a null frame with power save disabled. So we need | ||
48 | * to send a new nullfunc frame to inform the AP that we | ||
49 | * are again sleeping. | ||
50 | */ | ||
51 | ieee80211_send_nullfunc(local, sdata, 1); | ||
52 | } | ||
53 | |||
54 | /* inform AP that we are awake again, unless power save is enabled */ | ||
55 | static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | ||
56 | { | ||
57 | struct ieee80211_local *local = sdata->local; | ||
58 | |||
59 | if (!local->ps_sdata) | ||
60 | ieee80211_send_nullfunc(local, sdata, 0); | ||
61 | else if (local->offchannel_ps_enabled) { | ||
62 | /* | ||
63 | * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware | ||
64 | * will send a nullfunc frame with the powersave bit set | ||
65 | * even though the AP already knows that we are sleeping. | ||
66 | * This could be avoided by sending a null frame with power | ||
67 | * save bit disabled before enabling the power save, but | ||
68 | * this doesn't gain anything. | ||
69 | * | ||
70 | * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need | ||
71 | * to send a nullfunc frame because AP already knows that | ||
72 | * we are sleeping, let's just enable power save mode in | ||
73 | * hardware. | ||
74 | */ | ||
75 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
76 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
77 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | ||
78 | /* | ||
79 | * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer | ||
80 | * had been running before leaving the operating channel, | ||
81 | * restart the timer now and send a nullfunc frame to inform | ||
82 | * the AP that we are awake. | ||
83 | */ | ||
84 | ieee80211_send_nullfunc(local, sdata, 0); | ||
85 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
86 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
87 | } | ||
88 | } | ||
89 | |||
90 | void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | ||
91 | { | ||
92 | struct ieee80211_sub_if_data *sdata; | ||
93 | |||
94 | mutex_lock(&local->iflist_mtx); | ||
95 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
96 | if (!ieee80211_sdata_running(sdata)) | ||
97 | continue; | ||
98 | |||
99 | /* disable beaconing */ | ||
100 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
101 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
102 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
103 | ieee80211_bss_info_change_notify( | ||
104 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
105 | |||
106 | /* | ||
107 | * only handle non-STA interfaces here, STA interfaces | ||
108 | * are handled in ieee80211_offchannel_stop_station(), | ||
109 | * e.g., from the background scan state machine. | ||
110 | * | ||
111 | * In addition, do not stop monitor interface to allow it to be | ||
112 | * used from user space controlled off-channel operations. | ||
113 | */ | ||
114 | if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
115 | sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
116 | netif_stop_queue(sdata->dev); | ||
117 | } | ||
118 | mutex_unlock(&local->iflist_mtx); | ||
119 | } | ||
120 | |||
121 | void ieee80211_offchannel_stop_station(struct ieee80211_local *local) | ||
122 | { | ||
123 | struct ieee80211_sub_if_data *sdata; | ||
124 | |||
125 | /* | ||
126 | * notify the AP about us leaving the channel and stop all STA interfaces | ||
127 | */ | ||
128 | mutex_lock(&local->iflist_mtx); | ||
129 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
130 | if (!ieee80211_sdata_running(sdata)) | ||
131 | continue; | ||
132 | |||
133 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
134 | netif_stop_queue(sdata->dev); | ||
135 | if (sdata->u.mgd.associated) | ||
136 | ieee80211_offchannel_ps_enable(sdata); | ||
137 | } | ||
138 | } | ||
139 | mutex_unlock(&local->iflist_mtx); | ||
140 | } | ||
141 | |||
142 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
143 | bool enable_beaconing) | ||
144 | { | ||
145 | struct ieee80211_sub_if_data *sdata; | ||
146 | |||
147 | mutex_lock(&local->iflist_mtx); | ||
148 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
149 | if (!ieee80211_sdata_running(sdata)) | ||
150 | continue; | ||
151 | |||
152 | /* Tell AP we're back */ | ||
153 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
154 | if (sdata->u.mgd.associated) | ||
155 | ieee80211_offchannel_ps_disable(sdata); | ||
156 | netif_wake_queue(sdata->dev); | ||
157 | } | ||
158 | |||
159 | /* re-enable beaconing */ | ||
160 | if (enable_beaconing && | ||
161 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
162 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
163 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT)) | ||
164 | ieee80211_bss_info_change_notify( | ||
165 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
166 | } | ||
167 | mutex_unlock(&local->iflist_mtx); | ||
168 | } | ||
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 05e161c3cbc5..47f818959ad7 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -10,7 +10,6 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
10 | { | 10 | { |
11 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
13 | struct ieee80211_if_init_conf conf; | ||
14 | struct sta_info *sta; | 13 | struct sta_info *sta; |
15 | unsigned long flags; | 14 | unsigned long flags; |
16 | 15 | ||
@@ -93,17 +92,14 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
93 | break; | 92 | break; |
94 | } | 93 | } |
95 | 94 | ||
96 | if (!netif_running(sdata->dev)) | 95 | if (!ieee80211_sdata_running(sdata)) |
97 | continue; | 96 | continue; |
98 | 97 | ||
99 | /* disable beaconing */ | 98 | /* disable beaconing */ |
100 | ieee80211_bss_info_change_notify(sdata, | 99 | ieee80211_bss_info_change_notify(sdata, |
101 | BSS_CHANGED_BEACON_ENABLED); | 100 | BSS_CHANGED_BEACON_ENABLED); |
102 | 101 | ||
103 | conf.vif = &sdata->vif; | 102 | drv_remove_interface(local, &sdata->vif); |
104 | conf.type = sdata->vif.type; | ||
105 | conf.mac_addr = sdata->vif.addr; | ||
106 | drv_remove_interface(local, &conf); | ||
107 | } | 103 | } |
108 | 104 | ||
109 | /* stop hardware - this must stop RX */ | 105 | /* stop hardware - this must stop RX */ |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6cbf1a7b3157..bfcf09eb64b4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -289,7 +289,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
289 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) | 289 | if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) |
290 | continue; | 290 | continue; |
291 | 291 | ||
292 | if (!netif_running(sdata->dev)) | 292 | if (!ieee80211_sdata_running(sdata)) |
293 | continue; | 293 | continue; |
294 | 294 | ||
295 | if (prev_dev) { | 295 | if (prev_dev) { |
@@ -1945,6 +1945,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
1945 | { | 1945 | { |
1946 | struct ieee80211_sub_if_data *sdata = rx->sdata; | 1946 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1947 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1947 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1948 | ieee80211_rx_result rxs; | ||
1948 | 1949 | ||
1949 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1950 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
1950 | return RX_DROP_MONITOR; | 1951 | return RX_DROP_MONITOR; |
@@ -1952,6 +1953,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | |||
1952 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) | 1953 | if (ieee80211_drop_unencrypted(rx, mgmt->frame_control)) |
1953 | return RX_DROP_MONITOR; | 1954 | return RX_DROP_MONITOR; |
1954 | 1955 | ||
1956 | rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb); | ||
1957 | if (rxs != RX_CONTINUE) | ||
1958 | return rxs; | ||
1959 | |||
1955 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 1960 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
1956 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); | 1961 | return ieee80211_mesh_rx_mgmt(sdata, rx->skb); |
1957 | 1962 | ||
@@ -2056,7 +2061,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, | |||
2056 | skb->protocol = htons(ETH_P_802_2); | 2061 | skb->protocol = htons(ETH_P_802_2); |
2057 | 2062 | ||
2058 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2063 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2059 | if (!netif_running(sdata->dev)) | 2064 | if (!ieee80211_sdata_running(sdata)) |
2060 | continue; | 2065 | continue; |
2061 | 2066 | ||
2062 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || | 2067 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || |
@@ -2318,7 +2323,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2318 | } | 2323 | } |
2319 | if (!found_sta) { | 2324 | if (!found_sta) { |
2320 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2325 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2321 | if (!netif_running(sdata->dev)) | 2326 | if (!ieee80211_sdata_running(sdata)) |
2322 | continue; | 2327 | continue; |
2323 | 2328 | ||
2324 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 2329 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 66da0ab1d8fa..365f40975511 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -29,16 +29,19 @@ struct ieee80211_bss * | |||
29 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 29 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
30 | u8 *ssid, u8 ssid_len) | 30 | u8 *ssid, u8 ssid_len) |
31 | { | 31 | { |
32 | return (void *)cfg80211_get_bss(local->hw.wiphy, | 32 | struct cfg80211_bss *cbss; |
33 | ieee80211_get_channel(local->hw.wiphy, | 33 | |
34 | freq), | 34 | cbss = cfg80211_get_bss(local->hw.wiphy, |
35 | bssid, ssid, ssid_len, | 35 | ieee80211_get_channel(local->hw.wiphy, freq), |
36 | 0, 0); | 36 | bssid, ssid, ssid_len, 0, 0); |
37 | if (!cbss) | ||
38 | return NULL; | ||
39 | return (void *)cbss->priv; | ||
37 | } | 40 | } |
38 | 41 | ||
39 | static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) | 42 | static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) |
40 | { | 43 | { |
41 | struct ieee80211_bss *bss = (void *)cbss; | 44 | struct ieee80211_bss *bss = (void *)cbss->priv; |
42 | 45 | ||
43 | kfree(bss_mesh_id(bss)); | 46 | kfree(bss_mesh_id(bss)); |
44 | kfree(bss_mesh_cfg(bss)); | 47 | kfree(bss_mesh_cfg(bss)); |
@@ -47,7 +50,9 @@ static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) | |||
47 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 50 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
48 | struct ieee80211_bss *bss) | 51 | struct ieee80211_bss *bss) |
49 | { | 52 | { |
50 | cfg80211_put_bss((struct cfg80211_bss *)bss); | 53 | if (!bss) |
54 | return; | ||
55 | cfg80211_put_bss(container_of((void *)bss, struct cfg80211_bss, priv)); | ||
51 | } | 56 | } |
52 | 57 | ||
53 | struct ieee80211_bss * | 58 | struct ieee80211_bss * |
@@ -59,6 +64,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
59 | struct ieee80211_channel *channel, | 64 | struct ieee80211_channel *channel, |
60 | bool beacon) | 65 | bool beacon) |
61 | { | 66 | { |
67 | struct cfg80211_bss *cbss; | ||
62 | struct ieee80211_bss *bss; | 68 | struct ieee80211_bss *bss; |
63 | int clen; | 69 | int clen; |
64 | s32 signal = 0; | 70 | s32 signal = 0; |
@@ -68,13 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
68 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 74 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) |
69 | signal = (rx_status->signal * 100) / local->hw.max_signal; | 75 | signal = (rx_status->signal * 100) / local->hw.max_signal; |
70 | 76 | ||
71 | bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel, | 77 | cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel, |
72 | mgmt, len, signal, GFP_ATOMIC); | 78 | mgmt, len, signal, GFP_ATOMIC); |
73 | 79 | ||
74 | if (!bss) | 80 | if (!cbss) |
75 | return NULL; | 81 | return NULL; |
76 | 82 | ||
77 | bss->cbss.free_priv = ieee80211_rx_bss_free; | 83 | cbss->free_priv = ieee80211_rx_bss_free; |
84 | bss = (void *)cbss->priv; | ||
78 | 85 | ||
79 | /* save the ERP value so that it is available at association time */ | 86 | /* save the ERP value so that it is available at association time */ |
80 | if (elems->erp_info && elems->erp_info_len >= 1) { | 87 | if (elems->erp_info && elems->erp_info_len >= 1) { |
@@ -220,82 +227,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
220 | return true; | 227 | return true; |
221 | } | 228 | } |
222 | 229 | ||
223 | /* | ||
224 | * inform AP that we will go to sleep so that it will buffer the frames | ||
225 | * while we scan | ||
226 | */ | ||
227 | static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata) | ||
228 | { | ||
229 | struct ieee80211_local *local = sdata->local; | ||
230 | |||
231 | local->scan_ps_enabled = false; | ||
232 | |||
233 | /* FIXME: what to do when local->pspolling is true? */ | ||
234 | |||
235 | del_timer_sync(&local->dynamic_ps_timer); | ||
236 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
237 | |||
238 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
239 | local->scan_ps_enabled = true; | ||
240 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
241 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
242 | } | ||
243 | |||
244 | if (!(local->scan_ps_enabled) || | ||
245 | !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | ||
246 | /* | ||
247 | * If power save was enabled, no need to send a nullfunc | ||
248 | * frame because AP knows that we are sleeping. But if the | ||
249 | * hardware is creating the nullfunc frame for power save | ||
250 | * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not | ||
251 | * enabled) and power save was enabled, the firmware just | ||
252 | * sent a null frame with power save disabled. So we need | ||
253 | * to send a new nullfunc frame to inform the AP that we | ||
254 | * are again sleeping. | ||
255 | */ | ||
256 | ieee80211_send_nullfunc(local, sdata, 1); | ||
257 | } | ||
258 | |||
259 | /* inform AP that we are awake again, unless power save is enabled */ | ||
260 | static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata) | ||
261 | { | ||
262 | struct ieee80211_local *local = sdata->local; | ||
263 | |||
264 | if (!local->ps_sdata) | ||
265 | ieee80211_send_nullfunc(local, sdata, 0); | ||
266 | else if (local->scan_ps_enabled) { | ||
267 | /* | ||
268 | * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware | ||
269 | * will send a nullfunc frame with the powersave bit set | ||
270 | * even though the AP already knows that we are sleeping. | ||
271 | * This could be avoided by sending a null frame with power | ||
272 | * save bit disabled before enabling the power save, but | ||
273 | * this doesn't gain anything. | ||
274 | * | ||
275 | * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need | ||
276 | * to send a nullfunc frame because AP already knows that | ||
277 | * we are sleeping, let's just enable power save mode in | ||
278 | * hardware. | ||
279 | */ | ||
280 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
281 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
282 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | ||
283 | /* | ||
284 | * If IEEE80211_CONF_PS was not set and the dynamic_ps_timer | ||
285 | * had been running before leaving the operating channel, | ||
286 | * restart the timer now and send a nullfunc frame to inform | ||
287 | * the AP that we are awake. | ||
288 | */ | ||
289 | ieee80211_send_nullfunc(local, sdata, 0); | ||
290 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
291 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | ||
292 | } | ||
293 | } | ||
294 | |||
295 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | 230 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) |
296 | { | 231 | { |
297 | struct ieee80211_local *local = hw_to_local(hw); | 232 | struct ieee80211_local *local = hw_to_local(hw); |
298 | struct ieee80211_sub_if_data *sdata; | ||
299 | bool was_hw_scan; | 233 | bool was_hw_scan; |
300 | 234 | ||
301 | mutex_lock(&local->scan_mtx); | 235 | mutex_lock(&local->scan_mtx); |
@@ -344,28 +278,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
344 | 278 | ||
345 | drv_sw_scan_complete(local); | 279 | drv_sw_scan_complete(local); |
346 | 280 | ||
347 | mutex_lock(&local->iflist_mtx); | 281 | ieee80211_offchannel_return(local, true); |
348 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
349 | if (!netif_running(sdata->dev)) | ||
350 | continue; | ||
351 | |||
352 | /* Tell AP we're back */ | ||
353 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
354 | if (sdata->u.mgd.associated) { | ||
355 | ieee80211_scan_ps_disable(sdata); | ||
356 | netif_wake_queue(sdata->dev); | ||
357 | } | ||
358 | } else | ||
359 | netif_wake_queue(sdata->dev); | ||
360 | |||
361 | /* re-enable beaconing */ | ||
362 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
363 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
364 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
365 | ieee80211_bss_info_change_notify( | ||
366 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
367 | } | ||
368 | mutex_unlock(&local->iflist_mtx); | ||
369 | 282 | ||
370 | done: | 283 | done: |
371 | ieee80211_recalc_idle(local); | 284 | ieee80211_recalc_idle(local); |
@@ -377,8 +290,6 @@ EXPORT_SYMBOL(ieee80211_scan_completed); | |||
377 | 290 | ||
378 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) | 291 | static int ieee80211_start_sw_scan(struct ieee80211_local *local) |
379 | { | 292 | { |
380 | struct ieee80211_sub_if_data *sdata; | ||
381 | |||
382 | /* | 293 | /* |
383 | * Hardware/driver doesn't support hw_scan, so use software | 294 | * Hardware/driver doesn't support hw_scan, so use software |
384 | * scanning instead. First send a nullfunc frame with power save | 295 | * scanning instead. First send a nullfunc frame with power save |
@@ -394,33 +305,15 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
394 | */ | 305 | */ |
395 | drv_sw_scan_start(local); | 306 | drv_sw_scan_start(local); |
396 | 307 | ||
397 | mutex_lock(&local->iflist_mtx); | 308 | ieee80211_offchannel_stop_beaconing(local); |
398 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
399 | if (!netif_running(sdata->dev)) | ||
400 | continue; | ||
401 | |||
402 | /* disable beaconing */ | ||
403 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
404 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
405 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
406 | ieee80211_bss_info_change_notify( | ||
407 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
408 | |||
409 | /* | ||
410 | * only handle non-STA interfaces here, STA interfaces | ||
411 | * are handled in the scan state machine | ||
412 | */ | ||
413 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
414 | netif_stop_queue(sdata->dev); | ||
415 | } | ||
416 | mutex_unlock(&local->iflist_mtx); | ||
417 | 309 | ||
418 | local->next_scan_state = SCAN_DECISION; | 310 | local->next_scan_state = SCAN_DECISION; |
419 | local->scan_channel_idx = 0; | 311 | local->scan_channel_idx = 0; |
420 | 312 | ||
313 | drv_flush(local, false); | ||
314 | |||
421 | ieee80211_configure_filter(local); | 315 | ieee80211_configure_filter(local); |
422 | 316 | ||
423 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
424 | ieee80211_queue_delayed_work(&local->hw, | 317 | ieee80211_queue_delayed_work(&local->hw, |
425 | &local->scan_work, | 318 | &local->scan_work, |
426 | IEEE80211_CHANNEL_TIME); | 319 | IEEE80211_CHANNEL_TIME); |
@@ -433,7 +326,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
433 | struct cfg80211_scan_request *req) | 326 | struct cfg80211_scan_request *req) |
434 | { | 327 | { |
435 | struct ieee80211_local *local = sdata->local; | 328 | struct ieee80211_local *local = sdata->local; |
436 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
437 | int rc; | 329 | int rc; |
438 | 330 | ||
439 | if (local->scan_req) | 331 | if (local->scan_req) |
@@ -463,11 +355,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
463 | local->scan_req = req; | 355 | local->scan_req = req; |
464 | local->scan_sdata = sdata; | 356 | local->scan_sdata = sdata; |
465 | 357 | ||
466 | if (req != local->int_scan_req && | 358 | if (!list_empty(&local->work_list)) { |
467 | sdata->vif.type == NL80211_IFTYPE_STATION && | 359 | /* wait for the work to finish/time out */ |
468 | !list_empty(&ifmgd->work_list)) { | ||
469 | /* actually wait for the work it's doing to finish/time out */ | ||
470 | set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); | ||
471 | return 0; | 360 | return 0; |
472 | } | 361 | } |
473 | 362 | ||
@@ -526,7 +415,7 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
526 | /* check if at least one STA interface is associated */ | 415 | /* check if at least one STA interface is associated */ |
527 | mutex_lock(&local->iflist_mtx); | 416 | mutex_lock(&local->iflist_mtx); |
528 | list_for_each_entry(sdata, &local->interfaces, list) { | 417 | list_for_each_entry(sdata, &local->interfaces, list) { |
529 | if (!netif_running(sdata->dev)) | 418 | if (!ieee80211_sdata_running(sdata)) |
530 | continue; | 419 | continue; |
531 | 420 | ||
532 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 421 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
@@ -564,56 +453,35 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, | |||
564 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | 453 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, |
565 | unsigned long *next_delay) | 454 | unsigned long *next_delay) |
566 | { | 455 | { |
567 | struct ieee80211_sub_if_data *sdata; | 456 | ieee80211_offchannel_stop_station(local); |
457 | |||
458 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
568 | 459 | ||
569 | /* | 460 | /* |
570 | * notify the AP about us leaving the channel and stop all STA interfaces | 461 | * What if the nullfunc frames didn't arrive? |
571 | */ | 462 | */ |
572 | mutex_lock(&local->iflist_mtx); | 463 | drv_flush(local, false); |
573 | list_for_each_entry(sdata, &local->interfaces, list) { | 464 | if (local->ops->flush) |
574 | if (!netif_running(sdata->dev)) | 465 | *next_delay = 0; |
575 | continue; | 466 | else |
576 | 467 | *next_delay = HZ / 10; | |
577 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
578 | netif_stop_queue(sdata->dev); | ||
579 | if (sdata->u.mgd.associated) | ||
580 | ieee80211_scan_ps_enable(sdata); | ||
581 | } | ||
582 | } | ||
583 | mutex_unlock(&local->iflist_mtx); | ||
584 | |||
585 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
586 | 468 | ||
587 | /* advance to the next channel to be scanned */ | 469 | /* advance to the next channel to be scanned */ |
588 | *next_delay = HZ / 10; | ||
589 | local->next_scan_state = SCAN_SET_CHANNEL; | 470 | local->next_scan_state = SCAN_SET_CHANNEL; |
590 | } | 471 | } |
591 | 472 | ||
592 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, | 473 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, |
593 | unsigned long *next_delay) | 474 | unsigned long *next_delay) |
594 | { | 475 | { |
595 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
596 | |||
597 | /* switch back to the operating channel */ | 476 | /* switch back to the operating channel */ |
598 | local->scan_channel = NULL; | 477 | local->scan_channel = NULL; |
599 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 478 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
600 | 479 | ||
601 | /* | 480 | /* |
602 | * notify the AP about us being back and restart all STA interfaces | 481 | * Only re-enable station mode interface now; beaconing will be |
482 | * re-enabled once the full scan has been completed. | ||
603 | */ | 483 | */ |
604 | mutex_lock(&local->iflist_mtx); | 484 | ieee80211_offchannel_return(local, false); |
605 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
606 | if (!netif_running(sdata->dev)) | ||
607 | continue; | ||
608 | |||
609 | /* Tell AP we're back */ | ||
610 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
611 | if (sdata->u.mgd.associated) | ||
612 | ieee80211_scan_ps_disable(sdata); | ||
613 | netif_wake_queue(sdata->dev); | ||
614 | } | ||
615 | } | ||
616 | mutex_unlock(&local->iflist_mtx); | ||
617 | 485 | ||
618 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | 486 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); |
619 | 487 | ||
@@ -727,7 +595,7 @@ void ieee80211_scan_work(struct work_struct *work) | |||
727 | /* | 595 | /* |
728 | * Avoid re-scheduling when the sdata is going away. | 596 | * Avoid re-scheduling when the sdata is going away. |
729 | */ | 597 | */ |
730 | if (!netif_running(sdata->dev)) { | 598 | if (!ieee80211_sdata_running(sdata)) { |
731 | ieee80211_scan_completed(&local->hw, true); | 599 | ieee80211_scan_completed(&local->hw, true); |
732 | return; | 600 | return; |
733 | } | 601 | } |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d1a77e79d7a9..47da552ce8a6 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -359,6 +359,7 @@ int sta_info_insert(struct sta_info *sta) | |||
359 | { | 359 | { |
360 | struct ieee80211_local *local = sta->local; | 360 | struct ieee80211_local *local = sta->local; |
361 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 361 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
362 | struct station_info sinfo; | ||
362 | unsigned long flags; | 363 | unsigned long flags; |
363 | int err = 0; | 364 | int err = 0; |
364 | 365 | ||
@@ -367,7 +368,7 @@ int sta_info_insert(struct sta_info *sta) | |||
367 | * something inserts a STA (on one CPU) without holding the RTNL | 368 | * something inserts a STA (on one CPU) without holding the RTNL |
368 | * and another CPU turns off the net device. | 369 | * and another CPU turns off the net device. |
369 | */ | 370 | */ |
370 | if (unlikely(!netif_running(sdata->dev))) { | 371 | if (unlikely(!ieee80211_sdata_running(sdata))) { |
371 | err = -ENETDOWN; | 372 | err = -ENETDOWN; |
372 | goto out_free; | 373 | goto out_free; |
373 | } | 374 | } |
@@ -408,6 +409,10 @@ int sta_info_insert(struct sta_info *sta) | |||
408 | 409 | ||
409 | spin_unlock_irqrestore(&local->sta_lock, flags); | 410 | spin_unlock_irqrestore(&local->sta_lock, flags); |
410 | 411 | ||
412 | sinfo.filled = 0; | ||
413 | sinfo.generation = local->sta_generation; | ||
414 | cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_ATOMIC); | ||
415 | |||
411 | #ifdef CONFIG_MAC80211_DEBUGFS | 416 | #ifdef CONFIG_MAC80211_DEBUGFS |
412 | /* | 417 | /* |
413 | * Debugfs entry adding might sleep, so schedule process | 418 | * Debugfs entry adding might sleep, so schedule process |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 0c0850d37dda..0ebcdda24200 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -351,7 +351,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
351 | rcu_read_lock(); | 351 | rcu_read_lock(); |
352 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 352 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
353 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | 353 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
354 | if (!netif_running(sdata->dev)) | 354 | if (!ieee80211_sdata_running(sdata)) |
355 | continue; | 355 | continue; |
356 | 356 | ||
357 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | 357 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index ac48c86ae6b3..7bba49d2b6ca 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1418,6 +1418,10 @@ static bool need_dynamic_ps(struct ieee80211_local *local) | |||
1418 | if (!local->ps_sdata) | 1418 | if (!local->ps_sdata) |
1419 | return false; | 1419 | return false; |
1420 | 1420 | ||
1421 | /* No point if we're going to suspend */ | ||
1422 | if (local->quiescing) | ||
1423 | return false; | ||
1424 | |||
1421 | return true; | 1425 | return true; |
1422 | } | 1426 | } |
1423 | 1427 | ||
@@ -1469,7 +1473,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1469 | 1473 | ||
1470 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, | 1474 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, |
1471 | list) { | 1475 | list) { |
1472 | if (!netif_running(tmp_sdata->dev)) | 1476 | if (!ieee80211_sdata_running(tmp_sdata)) |
1473 | continue; | 1477 | continue; |
1474 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) | 1478 | if (tmp_sdata->vif.type != NL80211_IFTYPE_AP) |
1475 | continue; | 1479 | continue; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b01972579c7c..7e38858a9280 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -468,7 +468,7 @@ void ieee80211_iterate_active_interfaces( | |||
468 | case NL80211_IFTYPE_MESH_POINT: | 468 | case NL80211_IFTYPE_MESH_POINT: |
469 | break; | 469 | break; |
470 | } | 470 | } |
471 | if (netif_running(sdata->dev)) | 471 | if (ieee80211_sdata_running(sdata)) |
472 | iterator(data, sdata->vif.addr, | 472 | iterator(data, sdata->vif.addr, |
473 | &sdata->vif); | 473 | &sdata->vif); |
474 | } | 474 | } |
@@ -502,7 +502,7 @@ void ieee80211_iterate_active_interfaces_atomic( | |||
502 | case NL80211_IFTYPE_MESH_POINT: | 502 | case NL80211_IFTYPE_MESH_POINT: |
503 | break; | 503 | break; |
504 | } | 504 | } |
505 | if (netif_running(sdata->dev)) | 505 | if (ieee80211_sdata_running(sdata)) |
506 | iterator(data, sdata->vif.addr, | 506 | iterator(data, sdata->vif.addr, |
507 | &sdata->vif); | 507 | &sdata->vif); |
508 | } | 508 | } |
@@ -881,30 +881,66 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
881 | enum ieee80211_band band) | 881 | enum ieee80211_band band) |
882 | { | 882 | { |
883 | struct ieee80211_supported_band *sband; | 883 | struct ieee80211_supported_band *sband; |
884 | u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; | 884 | u8 *pos; |
885 | int i; | 885 | size_t offset = 0, noffset; |
886 | int supp_rates_len, i; | ||
886 | 887 | ||
887 | sband = local->hw.wiphy->bands[band]; | 888 | sband = local->hw.wiphy->bands[band]; |
888 | 889 | ||
889 | pos = buffer; | 890 | pos = buffer; |
890 | 891 | ||
892 | supp_rates_len = min_t(int, sband->n_bitrates, 8); | ||
893 | |||
891 | *pos++ = WLAN_EID_SUPP_RATES; | 894 | *pos++ = WLAN_EID_SUPP_RATES; |
892 | supp_rates_len = pos; | 895 | *pos++ = supp_rates_len; |
893 | *pos++ = 0; | 896 | |
894 | 897 | for (i = 0; i < supp_rates_len; i++) { | |
895 | for (i = 0; i < sband->n_bitrates; i++) { | 898 | int rate = sband->bitrates[i].bitrate; |
896 | struct ieee80211_rate *rate = &sband->bitrates[i]; | 899 | *pos++ = (u8) (rate / 5); |
897 | 900 | } | |
898 | if (esupp_rates_len) { | 901 | |
899 | *esupp_rates_len += 1; | 902 | /* insert "request information" if in custom IEs */ |
900 | } else if (*supp_rates_len == 8) { | 903 | if (ie && ie_len) { |
901 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 904 | static const u8 before_extrates[] = { |
902 | esupp_rates_len = pos; | 905 | WLAN_EID_SSID, |
903 | *pos++ = 1; | 906 | WLAN_EID_SUPP_RATES, |
904 | } else | 907 | WLAN_EID_REQUEST, |
905 | *supp_rates_len += 1; | 908 | }; |
909 | noffset = ieee80211_ie_split(ie, ie_len, | ||
910 | before_extrates, | ||
911 | ARRAY_SIZE(before_extrates), | ||
912 | offset); | ||
913 | memcpy(pos, ie + offset, noffset - offset); | ||
914 | pos += noffset - offset; | ||
915 | offset = noffset; | ||
916 | } | ||
906 | 917 | ||
907 | *pos++ = rate->bitrate / 5; | 918 | if (sband->n_bitrates > i) { |
919 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
920 | *pos++ = sband->n_bitrates - i; | ||
921 | |||
922 | for (; i < sband->n_bitrates; i++) { | ||
923 | int rate = sband->bitrates[i].bitrate; | ||
924 | *pos++ = (u8) (rate / 5); | ||
925 | } | ||
926 | } | ||
927 | |||
928 | /* insert custom IEs that go before HT */ | ||
929 | if (ie && ie_len) { | ||
930 | static const u8 before_ht[] = { | ||
931 | WLAN_EID_SSID, | ||
932 | WLAN_EID_SUPP_RATES, | ||
933 | WLAN_EID_REQUEST, | ||
934 | WLAN_EID_EXT_SUPP_RATES, | ||
935 | WLAN_EID_DS_PARAMS, | ||
936 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
937 | }; | ||
938 | noffset = ieee80211_ie_split(ie, ie_len, | ||
939 | before_ht, ARRAY_SIZE(before_ht), | ||
940 | offset); | ||
941 | memcpy(pos, ie + offset, noffset - offset); | ||
942 | pos += noffset - offset; | ||
943 | offset = noffset; | ||
908 | } | 944 | } |
909 | 945 | ||
910 | if (sband->ht_cap.ht_supported) { | 946 | if (sband->ht_cap.ht_supported) { |
@@ -936,9 +972,11 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
936 | * that calculates local->scan_ies_len. | 972 | * that calculates local->scan_ies_len. |
937 | */ | 973 | */ |
938 | 974 | ||
939 | if (ie) { | 975 | /* add any remaining custom IEs */ |
940 | memcpy(pos, ie, ie_len); | 976 | if (ie && ie_len) { |
941 | pos += ie_len; | 977 | noffset = ie_len; |
978 | memcpy(pos, ie + offset, noffset - offset); | ||
979 | pos += noffset - offset; | ||
942 | } | 980 | } |
943 | 981 | ||
944 | return pos - buffer; | 982 | return pos - buffer; |
@@ -1037,7 +1075,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1037 | { | 1075 | { |
1038 | struct ieee80211_hw *hw = &local->hw; | 1076 | struct ieee80211_hw *hw = &local->hw; |
1039 | struct ieee80211_sub_if_data *sdata; | 1077 | struct ieee80211_sub_if_data *sdata; |
1040 | struct ieee80211_if_init_conf conf; | ||
1041 | struct sta_info *sta; | 1078 | struct sta_info *sta; |
1042 | unsigned long flags; | 1079 | unsigned long flags; |
1043 | int res; | 1080 | int res; |
@@ -1047,7 +1084,19 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1047 | 1084 | ||
1048 | /* restart hardware */ | 1085 | /* restart hardware */ |
1049 | if (local->open_count) { | 1086 | if (local->open_count) { |
1087 | /* | ||
1088 | * Upon resume hardware can sometimes be goofy due to | ||
1089 | * various platform / driver / bus issues, so restarting | ||
1090 | * the device may at times not work immediately. Propagate | ||
1091 | * the error. | ||
1092 | */ | ||
1050 | res = drv_start(local); | 1093 | res = drv_start(local); |
1094 | if (res) { | ||
1095 | WARN(local->suspended, "Harware became unavailable " | ||
1096 | "upon resume. This is could be a software issue" | ||
1097 | "prior to suspend or a harware issue\n"); | ||
1098 | return res; | ||
1099 | } | ||
1051 | 1100 | ||
1052 | ieee80211_led_radio(local, true); | 1101 | ieee80211_led_radio(local, true); |
1053 | } | 1102 | } |
@@ -1056,12 +1105,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1056 | list_for_each_entry(sdata, &local->interfaces, list) { | 1105 | list_for_each_entry(sdata, &local->interfaces, list) { |
1057 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 1106 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
1058 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | 1107 | sdata->vif.type != NL80211_IFTYPE_MONITOR && |
1059 | netif_running(sdata->dev)) { | 1108 | ieee80211_sdata_running(sdata)) |
1060 | conf.vif = &sdata->vif; | 1109 | res = drv_add_interface(local, &sdata->vif); |
1061 | conf.type = sdata->vif.type; | ||
1062 | conf.mac_addr = sdata->vif.addr; | ||
1063 | res = drv_add_interface(local, &conf); | ||
1064 | } | ||
1065 | } | 1110 | } |
1066 | 1111 | ||
1067 | /* add STAs back */ | 1112 | /* add STAs back */ |
@@ -1103,7 +1148,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1103 | /* Finally also reconfigure all the BSS information */ | 1148 | /* Finally also reconfigure all the BSS information */ |
1104 | list_for_each_entry(sdata, &local->interfaces, list) { | 1149 | list_for_each_entry(sdata, &local->interfaces, list) { |
1105 | u32 changed = ~0; | 1150 | u32 changed = ~0; |
1106 | if (!netif_running(sdata->dev)) | 1151 | if (!ieee80211_sdata_running(sdata)) |
1107 | continue; | 1152 | continue; |
1108 | switch (sdata->vif.type) { | 1153 | switch (sdata->vif.type) { |
1109 | case NL80211_IFTYPE_STATION: | 1154 | case NL80211_IFTYPE_STATION: |
@@ -1131,7 +1176,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1131 | 1176 | ||
1132 | /* add back keys */ | 1177 | /* add back keys */ |
1133 | list_for_each_entry(sdata, &local->interfaces, list) | 1178 | list_for_each_entry(sdata, &local->interfaces, list) |
1134 | if (netif_running(sdata->dev)) | 1179 | if (ieee80211_sdata_running(sdata)) |
1135 | ieee80211_enable_keys(sdata); | 1180 | ieee80211_enable_keys(sdata); |
1136 | 1181 | ||
1137 | ieee80211_wake_queues_by_reason(hw, | 1182 | ieee80211_wake_queues_by_reason(hw, |
@@ -1252,3 +1297,59 @@ void ieee80211_recalc_smps(struct ieee80211_local *local, | |||
1252 | /* changed flag is auto-detected for this */ | 1297 | /* changed flag is auto-detected for this */ |
1253 | ieee80211_hw_config(local, 0); | 1298 | ieee80211_hw_config(local, 0); |
1254 | } | 1299 | } |
1300 | |||
1301 | static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id) | ||
1302 | { | ||
1303 | int i; | ||
1304 | |||
1305 | for (i = 0; i < n_ids; i++) | ||
1306 | if (ids[i] == id) | ||
1307 | return true; | ||
1308 | return false; | ||
1309 | } | ||
1310 | |||
1311 | /** | ||
1312 | * ieee80211_ie_split - split an IE buffer according to ordering | ||
1313 | * | ||
1314 | * @ies: the IE buffer | ||
1315 | * @ielen: the length of the IE buffer | ||
1316 | * @ids: an array with element IDs that are allowed before | ||
1317 | * the split | ||
1318 | * @n_ids: the size of the element ID array | ||
1319 | * @offset: offset where to start splitting in the buffer | ||
1320 | * | ||
1321 | * This function splits an IE buffer by updating the @offset | ||
1322 | * variable to point to the location where the buffer should be | ||
1323 | * split. | ||
1324 | * | ||
1325 | * It assumes that the given IE buffer is well-formed, this | ||
1326 | * has to be guaranteed by the caller! | ||
1327 | * | ||
1328 | * It also assumes that the IEs in the buffer are ordered | ||
1329 | * correctly, if not the result of using this function will not | ||
1330 | * be ordered correctly either, i.e. it does no reordering. | ||
1331 | * | ||
1332 | * The function returns the offset where the next part of the | ||
1333 | * buffer starts, which may be @ielen if the entire (remainder) | ||
1334 | * of the buffer should be used. | ||
1335 | */ | ||
1336 | size_t ieee80211_ie_split(const u8 *ies, size_t ielen, | ||
1337 | const u8 *ids, int n_ids, size_t offset) | ||
1338 | { | ||
1339 | size_t pos = offset; | ||
1340 | |||
1341 | while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) | ||
1342 | pos += 2 + ies[pos + 1]; | ||
1343 | |||
1344 | return pos; | ||
1345 | } | ||
1346 | |||
1347 | size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset) | ||
1348 | { | ||
1349 | size_t pos = offset; | ||
1350 | |||
1351 | while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC) | ||
1352 | pos += 2 + ies[pos + 1]; | ||
1353 | |||
1354 | return pos; | ||
1355 | } | ||
diff --git a/net/mac80211/work.c b/net/mac80211/work.c new file mode 100644 index 000000000000..ea89ed70734d --- /dev/null +++ b/net/mac80211/work.c | |||
@@ -0,0 +1,1086 @@ | |||
1 | /* | ||
2 | * mac80211 work implementation | ||
3 | * | ||
4 | * Copyright 2003-2008, Jouni Malinen <j@w1.fi> | ||
5 | * Copyright 2004, Instant802 Networks, Inc. | ||
6 | * Copyright 2005, Devicescape Software, Inc. | ||
7 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
8 | * Copyright 2007, Michael Wu <flamingice@sourmilk.net> | ||
9 | * Copyright 2009, Johannes Berg <johannes@sipsolutions.net> | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/delay.h> | ||
17 | #include <linux/if_ether.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <linux/if_arp.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/crc32.h> | ||
22 | #include <net/mac80211.h> | ||
23 | #include <asm/unaligned.h> | ||
24 | |||
25 | #include "ieee80211_i.h" | ||
26 | #include "rate.h" | ||
27 | |||
28 | #define IEEE80211_AUTH_TIMEOUT (HZ / 5) | ||
29 | #define IEEE80211_AUTH_MAX_TRIES 3 | ||
30 | #define IEEE80211_ASSOC_TIMEOUT (HZ / 5) | ||
31 | #define IEEE80211_ASSOC_MAX_TRIES 3 | ||
32 | #define IEEE80211_MAX_PROBE_TRIES 5 | ||
33 | |||
34 | enum work_action { | ||
35 | WORK_ACT_NONE, | ||
36 | WORK_ACT_TIMEOUT, | ||
37 | WORK_ACT_DONE, | ||
38 | }; | ||
39 | |||
40 | |||
41 | /* utils */ | ||
42 | static inline void ASSERT_WORK_MTX(struct ieee80211_local *local) | ||
43 | { | ||
44 | WARN_ON(!mutex_is_locked(&local->work_mtx)); | ||
45 | } | ||
46 | |||
47 | /* | ||
48 | * We can have multiple work items (and connection probing) | ||
49 | * scheduling this timer, but we need to take care to only | ||
50 | * reschedule it when it should fire _earlier_ than it was | ||
51 | * asked for before, or if it's not pending right now. This | ||
52 | * function ensures that. Note that it then is required to | ||
53 | * run this function for all timeouts after the first one | ||
54 | * has happened -- the work that runs from this timer will | ||
55 | * do that. | ||
56 | */ | ||
57 | static void run_again(struct ieee80211_local *local, | ||
58 | unsigned long timeout) | ||
59 | { | ||
60 | ASSERT_WORK_MTX(local); | ||
61 | |||
62 | if (!timer_pending(&local->work_timer) || | ||
63 | time_before(timeout, local->work_timer.expires)) | ||
64 | mod_timer(&local->work_timer, timeout); | ||
65 | } | ||
66 | |||
67 | static void work_free_rcu(struct rcu_head *head) | ||
68 | { | ||
69 | struct ieee80211_work *wk = | ||
70 | container_of(head, struct ieee80211_work, rcu_head); | ||
71 | |||
72 | kfree(wk); | ||
73 | } | ||
74 | |||
75 | void free_work(struct ieee80211_work *wk) | ||
76 | { | ||
77 | call_rcu(&wk->rcu_head, work_free_rcu); | ||
78 | } | ||
79 | |||
80 | static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len, | ||
81 | struct ieee80211_supported_band *sband, | ||
82 | u32 *rates) | ||
83 | { | ||
84 | int i, j, count; | ||
85 | *rates = 0; | ||
86 | count = 0; | ||
87 | for (i = 0; i < supp_rates_len; i++) { | ||
88 | int rate = (supp_rates[i] & 0x7F) * 5; | ||
89 | |||
90 | for (j = 0; j < sband->n_bitrates; j++) | ||
91 | if (sband->bitrates[j].bitrate == rate) { | ||
92 | *rates |= BIT(j); | ||
93 | count++; | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | return count; | ||
99 | } | ||
100 | |||
101 | /* frame sending functions */ | ||
102 | |||
103 | static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie, | ||
104 | struct ieee80211_supported_band *sband, | ||
105 | struct ieee80211_channel *channel, | ||
106 | enum ieee80211_smps_mode smps) | ||
107 | { | ||
108 | struct ieee80211_ht_info *ht_info; | ||
109 | u8 *pos; | ||
110 | u32 flags = channel->flags; | ||
111 | u16 cap = sband->ht_cap.cap; | ||
112 | __le16 tmp; | ||
113 | |||
114 | if (!sband->ht_cap.ht_supported) | ||
115 | return; | ||
116 | |||
117 | if (!ht_info_ie) | ||
118 | return; | ||
119 | |||
120 | if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info)) | ||
121 | return; | ||
122 | |||
123 | ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2); | ||
124 | |||
125 | /* determine capability flags */ | ||
126 | |||
127 | if (ieee80211_disable_40mhz_24ghz && | ||
128 | sband->band == IEEE80211_BAND_2GHZ) { | ||
129 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
130 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
131 | } | ||
132 | |||
133 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
134 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
135 | if (flags & IEEE80211_CHAN_NO_HT40PLUS) { | ||
136 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
137 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
138 | } | ||
139 | break; | ||
140 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
141 | if (flags & IEEE80211_CHAN_NO_HT40MINUS) { | ||
142 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
143 | cap &= ~IEEE80211_HT_CAP_SGI_40; | ||
144 | } | ||
145 | break; | ||
146 | } | ||
147 | |||
148 | /* set SM PS mode properly */ | ||
149 | cap &= ~IEEE80211_HT_CAP_SM_PS; | ||
150 | switch (smps) { | ||
151 | case IEEE80211_SMPS_AUTOMATIC: | ||
152 | case IEEE80211_SMPS_NUM_MODES: | ||
153 | WARN_ON(1); | ||
154 | case IEEE80211_SMPS_OFF: | ||
155 | cap |= WLAN_HT_CAP_SM_PS_DISABLED << | ||
156 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
157 | break; | ||
158 | case IEEE80211_SMPS_STATIC: | ||
159 | cap |= WLAN_HT_CAP_SM_PS_STATIC << | ||
160 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
161 | break; | ||
162 | case IEEE80211_SMPS_DYNAMIC: | ||
163 | cap |= WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
164 | IEEE80211_HT_CAP_SM_PS_SHIFT; | ||
165 | break; | ||
166 | } | ||
167 | |||
168 | /* reserve and fill IE */ | ||
169 | |||
170 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
171 | *pos++ = WLAN_EID_HT_CAPABILITY; | ||
172 | *pos++ = sizeof(struct ieee80211_ht_cap); | ||
173 | memset(pos, 0, sizeof(struct ieee80211_ht_cap)); | ||
174 | |||
175 | /* capability flags */ | ||
176 | tmp = cpu_to_le16(cap); | ||
177 | memcpy(pos, &tmp, sizeof(u16)); | ||
178 | pos += sizeof(u16); | ||
179 | |||
180 | /* AMPDU parameters */ | ||
181 | *pos++ = sband->ht_cap.ampdu_factor | | ||
182 | (sband->ht_cap.ampdu_density << | ||
183 | IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); | ||
184 | |||
185 | /* MCS set */ | ||
186 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | ||
187 | pos += sizeof(sband->ht_cap.mcs); | ||
188 | |||
189 | /* extended capabilities */ | ||
190 | pos += sizeof(__le16); | ||
191 | |||
192 | /* BF capabilities */ | ||
193 | pos += sizeof(__le32); | ||
194 | |||
195 | /* antenna selection */ | ||
196 | pos += sizeof(u8); | ||
197 | } | ||
198 | |||
199 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | ||
200 | struct ieee80211_work *wk) | ||
201 | { | ||
202 | struct ieee80211_local *local = sdata->local; | ||
203 | struct sk_buff *skb; | ||
204 | struct ieee80211_mgmt *mgmt; | ||
205 | u8 *pos; | ||
206 | const u8 *ies; | ||
207 | size_t offset = 0, noffset; | ||
208 | int i, len, count, rates_len, supp_rates_len; | ||
209 | u16 capab; | ||
210 | struct ieee80211_supported_band *sband; | ||
211 | u32 rates = 0; | ||
212 | |||
213 | sband = local->hw.wiphy->bands[wk->chan->band]; | ||
214 | |||
215 | /* | ||
216 | * Get all rates supported by the device and the AP as | ||
217 | * some APs don't like getting a superset of their rates | ||
218 | * in the association request (e.g. D-Link DAP 1353 in | ||
219 | * b-only mode)... | ||
220 | */ | ||
221 | rates_len = ieee80211_compatible_rates(wk->assoc.supp_rates, | ||
222 | wk->assoc.supp_rates_len, | ||
223 | sband, &rates); | ||
224 | |||
225 | skb = alloc_skb(local->hw.extra_tx_headroom + | ||
226 | sizeof(*mgmt) + /* bit too much but doesn't matter */ | ||
227 | 2 + wk->assoc.ssid_len + /* SSID */ | ||
228 | 4 + rates_len + /* (extended) rates */ | ||
229 | 4 + /* power capability */ | ||
230 | 2 + 2 * sband->n_channels + /* supported channels */ | ||
231 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | ||
232 | wk->ie_len + /* extra IEs */ | ||
233 | 9, /* WMM */ | ||
234 | GFP_KERNEL); | ||
235 | if (!skb) { | ||
236 | printk(KERN_DEBUG "%s: failed to allocate buffer for assoc " | ||
237 | "frame\n", sdata->name); | ||
238 | return; | ||
239 | } | ||
240 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
241 | |||
242 | capab = WLAN_CAPABILITY_ESS; | ||
243 | |||
244 | if (sband->band == IEEE80211_BAND_2GHZ) { | ||
245 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) | ||
246 | capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; | ||
247 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)) | ||
248 | capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; | ||
249 | } | ||
250 | |||
251 | if (wk->assoc.capability & WLAN_CAPABILITY_PRIVACY) | ||
252 | capab |= WLAN_CAPABILITY_PRIVACY; | ||
253 | |||
254 | if ((wk->assoc.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) && | ||
255 | (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT)) | ||
256 | capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; | ||
257 | |||
258 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | ||
259 | memset(mgmt, 0, 24); | ||
260 | memcpy(mgmt->da, wk->filter_ta, ETH_ALEN); | ||
261 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | ||
262 | memcpy(mgmt->bssid, wk->filter_ta, ETH_ALEN); | ||
263 | |||
264 | if (!is_zero_ether_addr(wk->assoc.prev_bssid)) { | ||
265 | skb_put(skb, 10); | ||
266 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
267 | IEEE80211_STYPE_REASSOC_REQ); | ||
268 | mgmt->u.reassoc_req.capab_info = cpu_to_le16(capab); | ||
269 | mgmt->u.reassoc_req.listen_interval = | ||
270 | cpu_to_le16(local->hw.conf.listen_interval); | ||
271 | memcpy(mgmt->u.reassoc_req.current_ap, wk->assoc.prev_bssid, | ||
272 | ETH_ALEN); | ||
273 | } else { | ||
274 | skb_put(skb, 4); | ||
275 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
276 | IEEE80211_STYPE_ASSOC_REQ); | ||
277 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | ||
278 | mgmt->u.assoc_req.listen_interval = | ||
279 | cpu_to_le16(local->hw.conf.listen_interval); | ||
280 | } | ||
281 | |||
282 | /* SSID */ | ||
283 | ies = pos = skb_put(skb, 2 + wk->assoc.ssid_len); | ||
284 | *pos++ = WLAN_EID_SSID; | ||
285 | *pos++ = wk->assoc.ssid_len; | ||
286 | memcpy(pos, wk->assoc.ssid, wk->assoc.ssid_len); | ||
287 | |||
288 | /* add all rates which were marked to be used above */ | ||
289 | supp_rates_len = rates_len; | ||
290 | if (supp_rates_len > 8) | ||
291 | supp_rates_len = 8; | ||
292 | |||
293 | len = sband->n_bitrates; | ||
294 | pos = skb_put(skb, supp_rates_len + 2); | ||
295 | *pos++ = WLAN_EID_SUPP_RATES; | ||
296 | *pos++ = supp_rates_len; | ||
297 | |||
298 | count = 0; | ||
299 | for (i = 0; i < sband->n_bitrates; i++) { | ||
300 | if (BIT(i) & rates) { | ||
301 | int rate = sband->bitrates[i].bitrate; | ||
302 | *pos++ = (u8) (rate / 5); | ||
303 | if (++count == 8) | ||
304 | break; | ||
305 | } | ||
306 | } | ||
307 | |||
308 | if (rates_len > count) { | ||
309 | pos = skb_put(skb, rates_len - count + 2); | ||
310 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
311 | *pos++ = rates_len - count; | ||
312 | |||
313 | for (i++; i < sband->n_bitrates; i++) { | ||
314 | if (BIT(i) & rates) { | ||
315 | int rate = sband->bitrates[i].bitrate; | ||
316 | *pos++ = (u8) (rate / 5); | ||
317 | } | ||
318 | } | ||
319 | } | ||
320 | |||
321 | if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) { | ||
322 | /* 1. power capabilities */ | ||
323 | pos = skb_put(skb, 4); | ||
324 | *pos++ = WLAN_EID_PWR_CAPABILITY; | ||
325 | *pos++ = 2; | ||
326 | *pos++ = 0; /* min tx power */ | ||
327 | *pos++ = wk->chan->max_power; /* max tx power */ | ||
328 | |||
329 | /* 2. supported channels */ | ||
330 | /* TODO: get this in reg domain format */ | ||
331 | pos = skb_put(skb, 2 * sband->n_channels + 2); | ||
332 | *pos++ = WLAN_EID_SUPPORTED_CHANNELS; | ||
333 | *pos++ = 2 * sband->n_channels; | ||
334 | for (i = 0; i < sband->n_channels; i++) { | ||
335 | *pos++ = ieee80211_frequency_to_channel( | ||
336 | sband->channels[i].center_freq); | ||
337 | *pos++ = 1; /* one channel in the subband*/ | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* if present, add any custom IEs that go before HT */ | ||
342 | if (wk->ie_len && wk->ie) { | ||
343 | static const u8 before_ht[] = { | ||
344 | WLAN_EID_SSID, | ||
345 | WLAN_EID_SUPP_RATES, | ||
346 | WLAN_EID_EXT_SUPP_RATES, | ||
347 | WLAN_EID_PWR_CAPABILITY, | ||
348 | WLAN_EID_SUPPORTED_CHANNELS, | ||
349 | WLAN_EID_RSN, | ||
350 | WLAN_EID_QOS_CAPA, | ||
351 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
352 | WLAN_EID_MOBILITY_DOMAIN, | ||
353 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
354 | }; | ||
355 | noffset = ieee80211_ie_split(wk->ie, wk->ie_len, | ||
356 | before_ht, ARRAY_SIZE(before_ht), | ||
357 | offset); | ||
358 | pos = skb_put(skb, noffset - offset); | ||
359 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
360 | offset = noffset; | ||
361 | } | ||
362 | |||
363 | if (wk->assoc.use_11n && wk->assoc.wmm_used && | ||
364 | local->hw.queues >= 4) | ||
365 | ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie, | ||
366 | sband, wk->chan, wk->assoc.smps); | ||
367 | |||
368 | /* if present, add any custom non-vendor IEs that go after HT */ | ||
369 | if (wk->ie_len && wk->ie) { | ||
370 | noffset = ieee80211_ie_split_vendor(wk->ie, wk->ie_len, | ||
371 | offset); | ||
372 | pos = skb_put(skb, noffset - offset); | ||
373 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
374 | offset = noffset; | ||
375 | } | ||
376 | |||
377 | if (wk->assoc.wmm_used && local->hw.queues >= 4) { | ||
378 | pos = skb_put(skb, 9); | ||
379 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
380 | *pos++ = 7; /* len */ | ||
381 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
382 | *pos++ = 0x50; | ||
383 | *pos++ = 0xf2; | ||
384 | *pos++ = 2; /* WME */ | ||
385 | *pos++ = 0; /* WME info */ | ||
386 | *pos++ = 1; /* WME ver */ | ||
387 | *pos++ = 0; | ||
388 | } | ||
389 | |||
390 | /* add any remaining custom (i.e. vendor specific here) IEs */ | ||
391 | if (wk->ie_len && wk->ie) { | ||
392 | noffset = wk->ie_len; | ||
393 | pos = skb_put(skb, noffset - offset); | ||
394 | memcpy(pos, wk->ie + offset, noffset - offset); | ||
395 | } | ||
396 | |||
397 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
398 | ieee80211_tx_skb(sdata, skb); | ||
399 | } | ||
400 | |||
401 | static void ieee80211_remove_auth_bss(struct ieee80211_local *local, | ||
402 | struct ieee80211_work *wk) | ||
403 | { | ||
404 | struct cfg80211_bss *cbss; | ||
405 | u16 capa_val = WLAN_CAPABILITY_ESS; | ||
406 | |||
407 | if (wk->probe_auth.privacy) | ||
408 | capa_val |= WLAN_CAPABILITY_PRIVACY; | ||
409 | |||
410 | cbss = cfg80211_get_bss(local->hw.wiphy, wk->chan, wk->filter_ta, | ||
411 | wk->probe_auth.ssid, wk->probe_auth.ssid_len, | ||
412 | WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, | ||
413 | capa_val); | ||
414 | if (!cbss) | ||
415 | return; | ||
416 | |||
417 | cfg80211_unlink_bss(local->hw.wiphy, cbss); | ||
418 | cfg80211_put_bss(cbss); | ||
419 | } | ||
420 | |||
421 | static enum work_action __must_check | ||
422 | ieee80211_direct_probe(struct ieee80211_work *wk) | ||
423 | { | ||
424 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
425 | struct ieee80211_local *local = sdata->local; | ||
426 | |||
427 | wk->probe_auth.tries++; | ||
428 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | ||
429 | printk(KERN_DEBUG "%s: direct probe to %pM timed out\n", | ||
430 | sdata->name, wk->filter_ta); | ||
431 | |||
432 | /* | ||
433 | * Most likely AP is not in the range so remove the | ||
434 | * bss struct for that AP. | ||
435 | */ | ||
436 | ieee80211_remove_auth_bss(local, wk); | ||
437 | |||
438 | return WORK_ACT_TIMEOUT; | ||
439 | } | ||
440 | |||
441 | printk(KERN_DEBUG "%s: direct probe to %pM (try %d)\n", | ||
442 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | ||
443 | |||
444 | /* | ||
445 | * Direct probe is sent to broadcast address as some APs | ||
446 | * will not answer to direct packet in unassociated state. | ||
447 | */ | ||
448 | ieee80211_send_probe_req(sdata, NULL, wk->probe_auth.ssid, | ||
449 | wk->probe_auth.ssid_len, NULL, 0); | ||
450 | |||
451 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
452 | run_again(local, wk->timeout); | ||
453 | |||
454 | return WORK_ACT_NONE; | ||
455 | } | ||
456 | |||
457 | |||
458 | static enum work_action __must_check | ||
459 | ieee80211_authenticate(struct ieee80211_work *wk) | ||
460 | { | ||
461 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
462 | struct ieee80211_local *local = sdata->local; | ||
463 | |||
464 | wk->probe_auth.tries++; | ||
465 | if (wk->probe_auth.tries > IEEE80211_AUTH_MAX_TRIES) { | ||
466 | printk(KERN_DEBUG "%s: authentication with %pM" | ||
467 | " timed out\n", sdata->name, wk->filter_ta); | ||
468 | |||
469 | /* | ||
470 | * Most likely AP is not in the range so remove the | ||
471 | * bss struct for that AP. | ||
472 | */ | ||
473 | ieee80211_remove_auth_bss(local, wk); | ||
474 | |||
475 | return WORK_ACT_TIMEOUT; | ||
476 | } | ||
477 | |||
478 | printk(KERN_DEBUG "%s: authenticate with %pM (try %d)\n", | ||
479 | sdata->name, wk->filter_ta, wk->probe_auth.tries); | ||
480 | |||
481 | ieee80211_send_auth(sdata, 1, wk->probe_auth.algorithm, wk->ie, | ||
482 | wk->ie_len, wk->filter_ta, NULL, 0, 0); | ||
483 | wk->probe_auth.transaction = 2; | ||
484 | |||
485 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | ||
486 | run_again(local, wk->timeout); | ||
487 | |||
488 | return WORK_ACT_NONE; | ||
489 | } | ||
490 | |||
491 | static enum work_action __must_check | ||
492 | ieee80211_associate(struct ieee80211_work *wk) | ||
493 | { | ||
494 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
495 | struct ieee80211_local *local = sdata->local; | ||
496 | |||
497 | wk->assoc.tries++; | ||
498 | if (wk->assoc.tries > IEEE80211_ASSOC_MAX_TRIES) { | ||
499 | printk(KERN_DEBUG "%s: association with %pM" | ||
500 | " timed out\n", | ||
501 | sdata->name, wk->filter_ta); | ||
502 | |||
503 | /* | ||
504 | * Most likely AP is not in the range so remove the | ||
505 | * bss struct for that AP. | ||
506 | */ | ||
507 | if (wk->assoc.bss) | ||
508 | cfg80211_unlink_bss(local->hw.wiphy, wk->assoc.bss); | ||
509 | |||
510 | return WORK_ACT_TIMEOUT; | ||
511 | } | ||
512 | |||
513 | printk(KERN_DEBUG "%s: associate with %pM (try %d)\n", | ||
514 | sdata->name, wk->filter_ta, wk->assoc.tries); | ||
515 | ieee80211_send_assoc(sdata, wk); | ||
516 | |||
517 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | ||
518 | run_again(local, wk->timeout); | ||
519 | |||
520 | return WORK_ACT_NONE; | ||
521 | } | ||
522 | |||
523 | static enum work_action __must_check | ||
524 | ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | ||
525 | { | ||
526 | /* | ||
527 | * First time we run, do nothing -- the generic code will | ||
528 | * have switched to the right channel etc. | ||
529 | */ | ||
530 | if (!wk->remain.started) { | ||
531 | wk->remain.started = true; | ||
532 | wk->timeout = jiffies + msecs_to_jiffies(wk->remain.duration); | ||
533 | |||
534 | cfg80211_ready_on_channel(wk->sdata->dev, (u64)wk, wk->chan, | ||
535 | wk->chan_type, wk->remain.duration, | ||
536 | GFP_KERNEL); | ||
537 | |||
538 | return WORK_ACT_NONE; | ||
539 | } | ||
540 | |||
541 | return WORK_ACT_TIMEOUT; | ||
542 | } | ||
543 | |||
544 | static void ieee80211_auth_challenge(struct ieee80211_work *wk, | ||
545 | struct ieee80211_mgmt *mgmt, | ||
546 | size_t len) | ||
547 | { | ||
548 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
549 | u8 *pos; | ||
550 | struct ieee802_11_elems elems; | ||
551 | |||
552 | pos = mgmt->u.auth.variable; | ||
553 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
554 | if (!elems.challenge) | ||
555 | return; | ||
556 | ieee80211_send_auth(sdata, 3, wk->probe_auth.algorithm, | ||
557 | elems.challenge - 2, elems.challenge_len + 2, | ||
558 | wk->filter_ta, wk->probe_auth.key, | ||
559 | wk->probe_auth.key_len, wk->probe_auth.key_idx); | ||
560 | wk->probe_auth.transaction = 4; | ||
561 | } | ||
562 | |||
563 | static enum work_action __must_check | ||
564 | ieee80211_rx_mgmt_auth(struct ieee80211_work *wk, | ||
565 | struct ieee80211_mgmt *mgmt, size_t len) | ||
566 | { | ||
567 | u16 auth_alg, auth_transaction, status_code; | ||
568 | |||
569 | if (wk->type != IEEE80211_WORK_AUTH) | ||
570 | return WORK_ACT_NONE; | ||
571 | |||
572 | if (len < 24 + 6) | ||
573 | return WORK_ACT_NONE; | ||
574 | |||
575 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | ||
576 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | ||
577 | status_code = le16_to_cpu(mgmt->u.auth.status_code); | ||
578 | |||
579 | if (auth_alg != wk->probe_auth.algorithm || | ||
580 | auth_transaction != wk->probe_auth.transaction) | ||
581 | return WORK_ACT_NONE; | ||
582 | |||
583 | if (status_code != WLAN_STATUS_SUCCESS) { | ||
584 | printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", | ||
585 | wk->sdata->name, mgmt->sa, status_code); | ||
586 | return WORK_ACT_DONE; | ||
587 | } | ||
588 | |||
589 | switch (wk->probe_auth.algorithm) { | ||
590 | case WLAN_AUTH_OPEN: | ||
591 | case WLAN_AUTH_LEAP: | ||
592 | case WLAN_AUTH_FT: | ||
593 | break; | ||
594 | case WLAN_AUTH_SHARED_KEY: | ||
595 | if (wk->probe_auth.transaction != 4) { | ||
596 | ieee80211_auth_challenge(wk, mgmt, len); | ||
597 | /* need another frame */ | ||
598 | return WORK_ACT_NONE; | ||
599 | } | ||
600 | break; | ||
601 | default: | ||
602 | WARN_ON(1); | ||
603 | return WORK_ACT_NONE; | ||
604 | } | ||
605 | |||
606 | printk(KERN_DEBUG "%s: authenticated\n", wk->sdata->name); | ||
607 | return WORK_ACT_DONE; | ||
608 | } | ||
609 | |||
610 | static enum work_action __must_check | ||
611 | ieee80211_rx_mgmt_assoc_resp(struct ieee80211_work *wk, | ||
612 | struct ieee80211_mgmt *mgmt, size_t len, | ||
613 | bool reassoc) | ||
614 | { | ||
615 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
616 | struct ieee80211_local *local = sdata->local; | ||
617 | u16 capab_info, status_code, aid; | ||
618 | struct ieee802_11_elems elems; | ||
619 | u8 *pos; | ||
620 | |||
621 | /* | ||
622 | * AssocResp and ReassocResp have identical structure, so process both | ||
623 | * of them in this function. | ||
624 | */ | ||
625 | |||
626 | if (len < 24 + 6) | ||
627 | return WORK_ACT_NONE; | ||
628 | |||
629 | capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); | ||
630 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | ||
631 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | ||
632 | |||
633 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " | ||
634 | "status=%d aid=%d)\n", | ||
635 | sdata->name, reassoc ? "Rea" : "A", mgmt->sa, | ||
636 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | ||
637 | |||
638 | pos = mgmt->u.assoc_resp.variable; | ||
639 | ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems); | ||
640 | |||
641 | if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && | ||
642 | elems.timeout_int && elems.timeout_int_len == 5 && | ||
643 | elems.timeout_int[0] == WLAN_TIMEOUT_ASSOC_COMEBACK) { | ||
644 | u32 tu, ms; | ||
645 | tu = get_unaligned_le32(elems.timeout_int + 1); | ||
646 | ms = tu * 1024 / 1000; | ||
647 | printk(KERN_DEBUG "%s: %pM rejected association temporarily; " | ||
648 | "comeback duration %u TU (%u ms)\n", | ||
649 | sdata->name, mgmt->sa, tu, ms); | ||
650 | wk->timeout = jiffies + msecs_to_jiffies(ms); | ||
651 | if (ms > IEEE80211_ASSOC_TIMEOUT) | ||
652 | run_again(local, wk->timeout); | ||
653 | return WORK_ACT_NONE; | ||
654 | } | ||
655 | |||
656 | if (status_code != WLAN_STATUS_SUCCESS) | ||
657 | printk(KERN_DEBUG "%s: %pM denied association (code=%d)\n", | ||
658 | sdata->name, mgmt->sa, status_code); | ||
659 | else | ||
660 | printk(KERN_DEBUG "%s: associated\n", sdata->name); | ||
661 | |||
662 | return WORK_ACT_DONE; | ||
663 | } | ||
664 | |||
665 | static enum work_action __must_check | ||
666 | ieee80211_rx_mgmt_probe_resp(struct ieee80211_work *wk, | ||
667 | struct ieee80211_mgmt *mgmt, size_t len, | ||
668 | struct ieee80211_rx_status *rx_status) | ||
669 | { | ||
670 | struct ieee80211_sub_if_data *sdata = wk->sdata; | ||
671 | struct ieee80211_local *local = sdata->local; | ||
672 | size_t baselen; | ||
673 | |||
674 | ASSERT_WORK_MTX(local); | ||
675 | |||
676 | baselen = (u8 *) mgmt->u.probe_resp.variable - (u8 *) mgmt; | ||
677 | if (baselen > len) | ||
678 | return WORK_ACT_NONE; | ||
679 | |||
680 | printk(KERN_DEBUG "%s: direct probe responded\n", sdata->name); | ||
681 | return WORK_ACT_DONE; | ||
682 | } | ||
683 | |||
684 | static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local, | ||
685 | struct sk_buff *skb) | ||
686 | { | ||
687 | struct ieee80211_rx_status *rx_status; | ||
688 | struct ieee80211_mgmt *mgmt; | ||
689 | struct ieee80211_work *wk; | ||
690 | enum work_action rma = WORK_ACT_NONE; | ||
691 | u16 fc; | ||
692 | |||
693 | rx_status = (struct ieee80211_rx_status *) skb->cb; | ||
694 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
695 | fc = le16_to_cpu(mgmt->frame_control); | ||
696 | |||
697 | mutex_lock(&local->work_mtx); | ||
698 | |||
699 | list_for_each_entry(wk, &local->work_list, list) { | ||
700 | const u8 *bssid = NULL; | ||
701 | |||
702 | switch (wk->type) { | ||
703 | case IEEE80211_WORK_DIRECT_PROBE: | ||
704 | case IEEE80211_WORK_AUTH: | ||
705 | case IEEE80211_WORK_ASSOC: | ||
706 | bssid = wk->filter_ta; | ||
707 | break; | ||
708 | default: | ||
709 | continue; | ||
710 | } | ||
711 | |||
712 | /* | ||
713 | * Before queuing, we already verified mgmt->sa, | ||
714 | * so this is needed just for matching. | ||
715 | */ | ||
716 | if (compare_ether_addr(bssid, mgmt->bssid)) | ||
717 | continue; | ||
718 | |||
719 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
720 | case IEEE80211_STYPE_PROBE_RESP: | ||
721 | rma = ieee80211_rx_mgmt_probe_resp(wk, mgmt, skb->len, | ||
722 | rx_status); | ||
723 | break; | ||
724 | case IEEE80211_STYPE_AUTH: | ||
725 | rma = ieee80211_rx_mgmt_auth(wk, mgmt, skb->len); | ||
726 | break; | ||
727 | case IEEE80211_STYPE_ASSOC_RESP: | ||
728 | rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, | ||
729 | skb->len, false); | ||
730 | break; | ||
731 | case IEEE80211_STYPE_REASSOC_RESP: | ||
732 | rma = ieee80211_rx_mgmt_assoc_resp(wk, mgmt, | ||
733 | skb->len, true); | ||
734 | break; | ||
735 | default: | ||
736 | WARN_ON(1); | ||
737 | } | ||
738 | /* | ||
739 | * We've processed this frame for that work, so it can't | ||
740 | * belong to another work struct. | ||
741 | * NB: this is also required for correctness for 'rma'! | ||
742 | */ | ||
743 | break; | ||
744 | } | ||
745 | |||
746 | switch (rma) { | ||
747 | case WORK_ACT_NONE: | ||
748 | break; | ||
749 | case WORK_ACT_DONE: | ||
750 | list_del_rcu(&wk->list); | ||
751 | break; | ||
752 | default: | ||
753 | WARN(1, "unexpected: %d", rma); | ||
754 | } | ||
755 | |||
756 | mutex_unlock(&local->work_mtx); | ||
757 | |||
758 | if (rma != WORK_ACT_DONE) | ||
759 | goto out; | ||
760 | |||
761 | switch (wk->done(wk, skb)) { | ||
762 | case WORK_DONE_DESTROY: | ||
763 | free_work(wk); | ||
764 | break; | ||
765 | case WORK_DONE_REQUEUE: | ||
766 | synchronize_rcu(); | ||
767 | wk->started = false; /* restart */ | ||
768 | mutex_lock(&local->work_mtx); | ||
769 | list_add_tail(&wk->list, &local->work_list); | ||
770 | mutex_unlock(&local->work_mtx); | ||
771 | } | ||
772 | |||
773 | out: | ||
774 | kfree_skb(skb); | ||
775 | } | ||
776 | |||
777 | static void ieee80211_work_timer(unsigned long data) | ||
778 | { | ||
779 | struct ieee80211_local *local = (void *) data; | ||
780 | |||
781 | if (local->quiescing) | ||
782 | return; | ||
783 | |||
784 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
785 | } | ||
786 | |||
787 | static void ieee80211_work_work(struct work_struct *work) | ||
788 | { | ||
789 | struct ieee80211_local *local = | ||
790 | container_of(work, struct ieee80211_local, work_work); | ||
791 | struct sk_buff *skb; | ||
792 | struct ieee80211_work *wk, *tmp; | ||
793 | LIST_HEAD(free_work); | ||
794 | enum work_action rma; | ||
795 | bool remain_off_channel = false; | ||
796 | |||
797 | if (local->scanning) | ||
798 | return; | ||
799 | |||
800 | /* | ||
801 | * ieee80211_queue_work() should have picked up most cases, | ||
802 | * here we'll pick the the rest. | ||
803 | */ | ||
804 | if (WARN(local->suspended, "work scheduled while going to suspend\n")) | ||
805 | return; | ||
806 | |||
807 | /* first process frames to avoid timing out while a frame is pending */ | ||
808 | while ((skb = skb_dequeue(&local->work_skb_queue))) | ||
809 | ieee80211_work_rx_queued_mgmt(local, skb); | ||
810 | |||
811 | ieee80211_recalc_idle(local); | ||
812 | |||
813 | mutex_lock(&local->work_mtx); | ||
814 | |||
815 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
816 | /* mark work as started if it's on the current off-channel */ | ||
817 | if (!wk->started && local->tmp_channel && | ||
818 | wk->chan == local->tmp_channel && | ||
819 | wk->chan_type == local->tmp_channel_type) { | ||
820 | wk->started = true; | ||
821 | } | ||
822 | |||
823 | if (!wk->started && !local->tmp_channel) { | ||
824 | /* | ||
825 | * TODO: could optimize this by leaving the | ||
826 | * station vifs in awake mode if they | ||
827 | * happen to be on the same channel as | ||
828 | * the requested channel | ||
829 | */ | ||
830 | ieee80211_offchannel_stop_beaconing(local); | ||
831 | ieee80211_offchannel_stop_station(local); | ||
832 | |||
833 | local->tmp_channel = wk->chan; | ||
834 | local->tmp_channel_type = wk->chan_type; | ||
835 | ieee80211_hw_config(local, 0); | ||
836 | wk->started = true; | ||
837 | wk->timeout = jiffies; | ||
838 | } | ||
839 | |||
840 | /* don't try to work with items that aren't started */ | ||
841 | if (!wk->started) | ||
842 | continue; | ||
843 | |||
844 | if (time_is_after_jiffies(wk->timeout)) { | ||
845 | /* | ||
846 | * This work item isn't supposed to be worked on | ||
847 | * right now, but take care to adjust the timer | ||
848 | * properly. | ||
849 | */ | ||
850 | run_again(local, wk->timeout); | ||
851 | continue; | ||
852 | } | ||
853 | |||
854 | switch (wk->type) { | ||
855 | default: | ||
856 | WARN_ON(1); | ||
857 | /* nothing */ | ||
858 | rma = WORK_ACT_NONE; | ||
859 | break; | ||
860 | case IEEE80211_WORK_ABORT: | ||
861 | rma = WORK_ACT_TIMEOUT; | ||
862 | case IEEE80211_WORK_DIRECT_PROBE: | ||
863 | rma = ieee80211_direct_probe(wk); | ||
864 | break; | ||
865 | case IEEE80211_WORK_AUTH: | ||
866 | rma = ieee80211_authenticate(wk); | ||
867 | break; | ||
868 | case IEEE80211_WORK_ASSOC: | ||
869 | rma = ieee80211_associate(wk); | ||
870 | break; | ||
871 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | ||
872 | rma = ieee80211_remain_on_channel_timeout(wk); | ||
873 | break; | ||
874 | } | ||
875 | |||
876 | switch (rma) { | ||
877 | case WORK_ACT_NONE: | ||
878 | /* might have changed the timeout */ | ||
879 | run_again(local, wk->timeout); | ||
880 | break; | ||
881 | case WORK_ACT_TIMEOUT: | ||
882 | list_del_rcu(&wk->list); | ||
883 | synchronize_rcu(); | ||
884 | list_add(&wk->list, &free_work); | ||
885 | break; | ||
886 | default: | ||
887 | WARN(1, "unexpected: %d", rma); | ||
888 | } | ||
889 | } | ||
890 | |||
891 | list_for_each_entry(wk, &local->work_list, list) { | ||
892 | if (!wk->started) | ||
893 | continue; | ||
894 | if (wk->chan != local->tmp_channel) | ||
895 | continue; | ||
896 | if (wk->chan_type != local->tmp_channel_type) | ||
897 | continue; | ||
898 | remain_off_channel = true; | ||
899 | } | ||
900 | |||
901 | if (!remain_off_channel && local->tmp_channel) { | ||
902 | local->tmp_channel = NULL; | ||
903 | ieee80211_hw_config(local, 0); | ||
904 | ieee80211_offchannel_return(local, true); | ||
905 | /* give connection some time to breathe */ | ||
906 | run_again(local, jiffies + HZ/2); | ||
907 | } | ||
908 | |||
909 | if (list_empty(&local->work_list) && local->scan_req) | ||
910 | ieee80211_queue_delayed_work(&local->hw, | ||
911 | &local->scan_work, | ||
912 | round_jiffies_relative(0)); | ||
913 | |||
914 | mutex_unlock(&local->work_mtx); | ||
915 | |||
916 | ieee80211_recalc_idle(local); | ||
917 | |||
918 | list_for_each_entry_safe(wk, tmp, &free_work, list) { | ||
919 | wk->done(wk, NULL); | ||
920 | list_del(&wk->list); | ||
921 | kfree(wk); | ||
922 | } | ||
923 | } | ||
924 | |||
925 | void ieee80211_add_work(struct ieee80211_work *wk) | ||
926 | { | ||
927 | struct ieee80211_local *local; | ||
928 | |||
929 | if (WARN_ON(!wk->chan)) | ||
930 | return; | ||
931 | |||
932 | if (WARN_ON(!wk->sdata)) | ||
933 | return; | ||
934 | |||
935 | if (WARN_ON(!wk->done)) | ||
936 | return; | ||
937 | |||
938 | wk->started = false; | ||
939 | |||
940 | local = wk->sdata->local; | ||
941 | mutex_lock(&local->work_mtx); | ||
942 | list_add_tail(&wk->list, &local->work_list); | ||
943 | mutex_unlock(&local->work_mtx); | ||
944 | |||
945 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
946 | } | ||
947 | |||
948 | void ieee80211_work_init(struct ieee80211_local *local) | ||
949 | { | ||
950 | mutex_init(&local->work_mtx); | ||
951 | INIT_LIST_HEAD(&local->work_list); | ||
952 | setup_timer(&local->work_timer, ieee80211_work_timer, | ||
953 | (unsigned long)local); | ||
954 | INIT_WORK(&local->work_work, ieee80211_work_work); | ||
955 | skb_queue_head_init(&local->work_skb_queue); | ||
956 | } | ||
957 | |||
958 | void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata) | ||
959 | { | ||
960 | struct ieee80211_local *local = sdata->local; | ||
961 | struct ieee80211_work *wk; | ||
962 | |||
963 | mutex_lock(&local->work_mtx); | ||
964 | list_for_each_entry(wk, &local->work_list, list) { | ||
965 | if (wk->sdata != sdata) | ||
966 | continue; | ||
967 | wk->type = IEEE80211_WORK_ABORT; | ||
968 | wk->started = true; | ||
969 | wk->timeout = jiffies; | ||
970 | } | ||
971 | mutex_unlock(&local->work_mtx); | ||
972 | |||
973 | /* run cleanups etc. */ | ||
974 | ieee80211_work_work(&local->work_work); | ||
975 | |||
976 | mutex_lock(&local->work_mtx); | ||
977 | list_for_each_entry(wk, &local->work_list, list) { | ||
978 | if (wk->sdata != sdata) | ||
979 | continue; | ||
980 | WARN_ON(1); | ||
981 | break; | ||
982 | } | ||
983 | mutex_unlock(&local->work_mtx); | ||
984 | } | ||
985 | |||
986 | ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata, | ||
987 | struct sk_buff *skb) | ||
988 | { | ||
989 | struct ieee80211_local *local = sdata->local; | ||
990 | struct ieee80211_mgmt *mgmt; | ||
991 | struct ieee80211_work *wk; | ||
992 | u16 fc; | ||
993 | |||
994 | if (skb->len < 24) | ||
995 | return RX_DROP_MONITOR; | ||
996 | |||
997 | mgmt = (struct ieee80211_mgmt *) skb->data; | ||
998 | fc = le16_to_cpu(mgmt->frame_control); | ||
999 | |||
1000 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
1001 | if (sdata != wk->sdata) | ||
1002 | continue; | ||
1003 | if (compare_ether_addr(wk->filter_ta, mgmt->sa)) | ||
1004 | continue; | ||
1005 | if (compare_ether_addr(wk->filter_ta, mgmt->bssid)) | ||
1006 | continue; | ||
1007 | |||
1008 | switch (fc & IEEE80211_FCTL_STYPE) { | ||
1009 | case IEEE80211_STYPE_AUTH: | ||
1010 | case IEEE80211_STYPE_PROBE_RESP: | ||
1011 | case IEEE80211_STYPE_ASSOC_RESP: | ||
1012 | case IEEE80211_STYPE_REASSOC_RESP: | ||
1013 | case IEEE80211_STYPE_DEAUTH: | ||
1014 | case IEEE80211_STYPE_DISASSOC: | ||
1015 | skb_queue_tail(&local->work_skb_queue, skb); | ||
1016 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1017 | return RX_QUEUED; | ||
1018 | } | ||
1019 | } | ||
1020 | |||
1021 | return RX_CONTINUE; | ||
1022 | } | ||
1023 | |||
1024 | static enum work_done_result ieee80211_remain_done(struct ieee80211_work *wk, | ||
1025 | struct sk_buff *skb) | ||
1026 | { | ||
1027 | /* | ||
1028 | * We are done serving the remain-on-channel command. | ||
1029 | */ | ||
1030 | cfg80211_remain_on_channel_expired(wk->sdata->dev, (u64)wk, | ||
1031 | wk->chan, wk->chan_type, | ||
1032 | GFP_KERNEL); | ||
1033 | |||
1034 | return WORK_DONE_DESTROY; | ||
1035 | } | ||
1036 | |||
1037 | int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1038 | struct ieee80211_channel *chan, | ||
1039 | enum nl80211_channel_type channel_type, | ||
1040 | unsigned int duration, u64 *cookie) | ||
1041 | { | ||
1042 | struct ieee80211_work *wk; | ||
1043 | |||
1044 | wk = kzalloc(sizeof(*wk), GFP_KERNEL); | ||
1045 | if (!wk) | ||
1046 | return -ENOMEM; | ||
1047 | |||
1048 | wk->type = IEEE80211_WORK_REMAIN_ON_CHANNEL; | ||
1049 | wk->chan = chan; | ||
1050 | wk->chan_type = channel_type; | ||
1051 | wk->sdata = sdata; | ||
1052 | wk->done = ieee80211_remain_done; | ||
1053 | |||
1054 | wk->remain.duration = duration; | ||
1055 | |||
1056 | *cookie = (u64)wk; | ||
1057 | |||
1058 | ieee80211_add_work(wk); | ||
1059 | |||
1060 | return 0; | ||
1061 | } | ||
1062 | |||
1063 | int ieee80211_wk_cancel_remain_on_channel(struct ieee80211_sub_if_data *sdata, | ||
1064 | u64 cookie) | ||
1065 | { | ||
1066 | struct ieee80211_local *local = sdata->local; | ||
1067 | struct ieee80211_work *wk, *tmp; | ||
1068 | bool found = false; | ||
1069 | |||
1070 | mutex_lock(&local->work_mtx); | ||
1071 | list_for_each_entry_safe(wk, tmp, &local->work_list, list) { | ||
1072 | if ((u64)wk == cookie) { | ||
1073 | wk->timeout = jiffies; | ||
1074 | found = true; | ||
1075 | break; | ||
1076 | } | ||
1077 | } | ||
1078 | mutex_unlock(&local->work_mtx); | ||
1079 | |||
1080 | if (!found) | ||
1081 | return -ENOENT; | ||
1082 | |||
1083 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 8419971f07c5..d0ee29063e5d 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -94,21 +94,6 @@ config CFG80211_DEBUGFS | |||
94 | 94 | ||
95 | If unsure, say N. | 95 | If unsure, say N. |
96 | 96 | ||
97 | config WIRELESS_OLD_REGULATORY | ||
98 | bool "Old wireless static regulatory definitions" | ||
99 | default n | ||
100 | depends on CFG80211 | ||
101 | ---help--- | ||
102 | This option enables the old static regulatory information | ||
103 | and uses it within the new framework. This option is available | ||
104 | for historical reasons and it is advised to leave it off. | ||
105 | |||
106 | For details see: | ||
107 | |||
108 | http://wireless.kernel.org/en/developers/Regulatory | ||
109 | |||
110 | Say N and if you say Y, please tell us why. The default is N. | ||
111 | |||
112 | config CFG80211_INTERNAL_REGDB | 97 | config CFG80211_INTERNAL_REGDB |
113 | bool "use statically compiled regulatory rules database" if EMBEDDED | 98 | bool "use statically compiled regulatory rules database" if EMBEDDED |
114 | default n | 99 | default n |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index a46ac6c9b365..bf1737fc9a7e 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -41,44 +41,57 @@ rdev_fixed_channel(struct cfg80211_registered_device *rdev, | |||
41 | return result; | 41 | return result; |
42 | } | 42 | } |
43 | 43 | ||
44 | int rdev_set_freq(struct cfg80211_registered_device *rdev, | 44 | struct ieee80211_channel * |
45 | struct wireless_dev *for_wdev, | 45 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, |
46 | int freq, enum nl80211_channel_type channel_type) | 46 | int freq, enum nl80211_channel_type channel_type) |
47 | { | 47 | { |
48 | struct ieee80211_channel *chan; | 48 | struct ieee80211_channel *chan; |
49 | struct ieee80211_sta_ht_cap *ht_cap; | 49 | struct ieee80211_sta_ht_cap *ht_cap; |
50 | int result; | ||
51 | |||
52 | if (rdev_fixed_channel(rdev, for_wdev)) | ||
53 | return -EBUSY; | ||
54 | |||
55 | if (!rdev->ops->set_channel) | ||
56 | return -EOPNOTSUPP; | ||
57 | 50 | ||
58 | chan = ieee80211_get_channel(&rdev->wiphy, freq); | 51 | chan = ieee80211_get_channel(&rdev->wiphy, freq); |
59 | 52 | ||
60 | /* Primary channel not allowed */ | 53 | /* Primary channel not allowed */ |
61 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 54 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) |
62 | return -EINVAL; | 55 | return NULL; |
63 | 56 | ||
64 | if (channel_type == NL80211_CHAN_HT40MINUS && | 57 | if (channel_type == NL80211_CHAN_HT40MINUS && |
65 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | 58 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) |
66 | return -EINVAL; | 59 | return NULL; |
67 | else if (channel_type == NL80211_CHAN_HT40PLUS && | 60 | else if (channel_type == NL80211_CHAN_HT40PLUS && |
68 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | 61 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) |
69 | return -EINVAL; | 62 | return NULL; |
70 | 63 | ||
71 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | 64 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; |
72 | 65 | ||
73 | if (channel_type != NL80211_CHAN_NO_HT) { | 66 | if (channel_type != NL80211_CHAN_NO_HT) { |
74 | if (!ht_cap->ht_supported) | 67 | if (!ht_cap->ht_supported) |
75 | return -EINVAL; | 68 | return NULL; |
76 | 69 | ||
77 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | 70 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || |
78 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) | 71 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) |
79 | return -EINVAL; | 72 | return NULL; |
80 | } | 73 | } |
81 | 74 | ||
75 | return chan; | ||
76 | } | ||
77 | |||
78 | int rdev_set_freq(struct cfg80211_registered_device *rdev, | ||
79 | struct wireless_dev *for_wdev, | ||
80 | int freq, enum nl80211_channel_type channel_type) | ||
81 | { | ||
82 | struct ieee80211_channel *chan; | ||
83 | int result; | ||
84 | |||
85 | if (rdev_fixed_channel(rdev, for_wdev)) | ||
86 | return -EBUSY; | ||
87 | |||
88 | if (!rdev->ops->set_channel) | ||
89 | return -EOPNOTSUPP; | ||
90 | |||
91 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | ||
92 | if (!chan) | ||
93 | return -EINVAL; | ||
94 | |||
82 | result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type); | 95 | result = rdev->ops->set_channel(&rdev->wiphy, chan, channel_type); |
83 | if (result) | 96 | if (result) |
84 | return result; | 97 | return result; |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 35b712127143..30ec95f05b52 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -374,6 +374,9 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | |||
374 | struct ieee80211_channel * | 374 | struct ieee80211_channel * |
375 | rdev_fixed_channel(struct cfg80211_registered_device *rdev, | 375 | rdev_fixed_channel(struct cfg80211_registered_device *rdev, |
376 | struct wireless_dev *for_wdev); | 376 | struct wireless_dev *for_wdev); |
377 | struct ieee80211_channel * | ||
378 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | ||
379 | int freq, enum nl80211_channel_type channel_type); | ||
377 | int rdev_set_freq(struct cfg80211_registered_device *rdev, | 380 | int rdev_set_freq(struct cfg80211_registered_device *rdev, |
378 | struct wireless_dev *for_wdev, | 381 | struct wireless_dev *for_wdev, |
379 | int freq, enum nl80211_channel_type channel_type); | 382 | int freq, enum nl80211_channel_type channel_type); |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index acaeaa784d68..94d151f6f73e 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -93,7 +93,18 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
93 | } | 93 | } |
94 | } | 94 | } |
95 | 95 | ||
96 | WARN_ON(!bss); | 96 | /* |
97 | * We might be coming here because the driver reported | ||
98 | * a successful association at the same time as the | ||
99 | * user requested a deauth. In that case, we will have | ||
100 | * removed the BSS from the auth_bsses list due to the | ||
101 | * deauth request when the assoc response makes it. If | ||
102 | * the two code paths acquire the lock the other way | ||
103 | * around, that's just the standard situation of a | ||
104 | * deauth being requested while connected. | ||
105 | */ | ||
106 | if (!bss) | ||
107 | goto out; | ||
97 | } else if (wdev->conn) { | 108 | } else if (wdev->conn) { |
98 | cfg80211_sme_failed_assoc(wdev); | 109 | cfg80211_sme_failed_assoc(wdev); |
99 | /* | 110 | /* |
@@ -680,3 +691,40 @@ void cfg80211_mlme_down(struct cfg80211_registered_device *rdev, | |||
680 | } | 691 | } |
681 | } | 692 | } |
682 | } | 693 | } |
694 | |||
695 | void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie, | ||
696 | struct ieee80211_channel *chan, | ||
697 | enum nl80211_channel_type channel_type, | ||
698 | unsigned int duration, gfp_t gfp) | ||
699 | { | ||
700 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
701 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
702 | |||
703 | nl80211_send_remain_on_channel(rdev, dev, cookie, chan, channel_type, | ||
704 | duration, gfp); | ||
705 | } | ||
706 | EXPORT_SYMBOL(cfg80211_ready_on_channel); | ||
707 | |||
708 | void cfg80211_remain_on_channel_expired(struct net_device *dev, | ||
709 | u64 cookie, | ||
710 | struct ieee80211_channel *chan, | ||
711 | enum nl80211_channel_type channel_type, | ||
712 | gfp_t gfp) | ||
713 | { | ||
714 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
715 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
716 | |||
717 | nl80211_send_remain_on_channel_cancel(rdev, dev, cookie, chan, | ||
718 | channel_type, gfp); | ||
719 | } | ||
720 | EXPORT_SYMBOL(cfg80211_remain_on_channel_expired); | ||
721 | |||
722 | void cfg80211_new_sta(struct net_device *dev, const u8 *mac_addr, | ||
723 | struct station_info *sinfo, gfp_t gfp) | ||
724 | { | ||
725 | struct wiphy *wiphy = dev->ieee80211_ptr->wiphy; | ||
726 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
727 | |||
728 | nl80211_send_sta_event(rdev, dev, mac_addr, sinfo, gfp); | ||
729 | } | ||
730 | EXPORT_SYMBOL(cfg80211_new_sta); | ||
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7cb0d647fc34..e3bee3cecdfa 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -141,6 +141,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
141 | [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, | 141 | [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, |
142 | [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, | 142 | [NL80211_ATTR_PMKID] = { .type = NLA_BINARY, |
143 | .len = WLAN_PMKID_LEN }, | 143 | .len = WLAN_PMKID_LEN }, |
144 | [NL80211_ATTR_DURATION] = { .type = NLA_U32 }, | ||
145 | [NL80211_ATTR_COOKIE] = { .type = NLA_U64 }, | ||
144 | }; | 146 | }; |
145 | 147 | ||
146 | /* policy for the attributes */ | 148 | /* policy for the attributes */ |
@@ -569,6 +571,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
569 | CMD(set_pmksa, SET_PMKSA); | 571 | CMD(set_pmksa, SET_PMKSA); |
570 | CMD(del_pmksa, DEL_PMKSA); | 572 | CMD(del_pmksa, DEL_PMKSA); |
571 | CMD(flush_pmksa, FLUSH_PMKSA); | 573 | CMD(flush_pmksa, FLUSH_PMKSA); |
574 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | ||
572 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 575 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
573 | i++; | 576 | i++; |
574 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 577 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -1639,7 +1642,7 @@ static int parse_station_flags(struct genl_info *info, | |||
1639 | 1642 | ||
1640 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | 1643 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, |
1641 | int flags, struct net_device *dev, | 1644 | int flags, struct net_device *dev, |
1642 | u8 *mac_addr, struct station_info *sinfo) | 1645 | const u8 *mac_addr, struct station_info *sinfo) |
1643 | { | 1646 | { |
1644 | void *hdr; | 1647 | void *hdr; |
1645 | struct nlattr *sinfoattr, *txrate; | 1648 | struct nlattr *sinfoattr, *txrate; |
@@ -2550,12 +2553,6 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2550 | 2553 | ||
2551 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); | 2554 | data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]); |
2552 | 2555 | ||
2553 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
2554 | /* We ignore world regdom requests with the old regdom setup */ | ||
2555 | if (is_world_regdom(data)) | ||
2556 | return -EINVAL; | ||
2557 | #endif | ||
2558 | |||
2559 | r = regulatory_hint_user(data); | 2556 | r = regulatory_hint_user(data); |
2560 | 2557 | ||
2561 | return r; | 2558 | return r; |
@@ -4289,6 +4286,143 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info) | |||
4289 | 4286 | ||
4290 | } | 4287 | } |
4291 | 4288 | ||
4289 | static int nl80211_remain_on_channel(struct sk_buff *skb, | ||
4290 | struct genl_info *info) | ||
4291 | { | ||
4292 | struct cfg80211_registered_device *rdev; | ||
4293 | struct net_device *dev; | ||
4294 | struct ieee80211_channel *chan; | ||
4295 | struct sk_buff *msg; | ||
4296 | void *hdr; | ||
4297 | u64 cookie; | ||
4298 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
4299 | u32 freq, duration; | ||
4300 | int err; | ||
4301 | |||
4302 | if (!info->attrs[NL80211_ATTR_WIPHY_FREQ] || | ||
4303 | !info->attrs[NL80211_ATTR_DURATION]) | ||
4304 | return -EINVAL; | ||
4305 | |||
4306 | duration = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | ||
4307 | |||
4308 | /* | ||
4309 | * We should be on that channel for at least one jiffie, | ||
4310 | * and more than 5 seconds seems excessive. | ||
4311 | */ | ||
4312 | if (!duration || !msecs_to_jiffies(duration) || duration > 5000) | ||
4313 | return -EINVAL; | ||
4314 | |||
4315 | rtnl_lock(); | ||
4316 | |||
4317 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4318 | if (err) | ||
4319 | goto unlock_rtnl; | ||
4320 | |||
4321 | if (!rdev->ops->remain_on_channel) { | ||
4322 | err = -EOPNOTSUPP; | ||
4323 | goto out; | ||
4324 | } | ||
4325 | |||
4326 | if (!netif_running(dev)) { | ||
4327 | err = -ENETDOWN; | ||
4328 | goto out; | ||
4329 | } | ||
4330 | |||
4331 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | ||
4332 | channel_type = nla_get_u32( | ||
4333 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | ||
4334 | if (channel_type != NL80211_CHAN_NO_HT && | ||
4335 | channel_type != NL80211_CHAN_HT20 && | ||
4336 | channel_type != NL80211_CHAN_HT40PLUS && | ||
4337 | channel_type != NL80211_CHAN_HT40MINUS) | ||
4338 | err = -EINVAL; | ||
4339 | goto out; | ||
4340 | } | ||
4341 | |||
4342 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | ||
4343 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | ||
4344 | if (chan == NULL) { | ||
4345 | err = -EINVAL; | ||
4346 | goto out; | ||
4347 | } | ||
4348 | |||
4349 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
4350 | if (!msg) { | ||
4351 | err = -ENOMEM; | ||
4352 | goto out; | ||
4353 | } | ||
4354 | |||
4355 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
4356 | NL80211_CMD_REMAIN_ON_CHANNEL); | ||
4357 | |||
4358 | if (IS_ERR(hdr)) { | ||
4359 | err = PTR_ERR(hdr); | ||
4360 | goto free_msg; | ||
4361 | } | ||
4362 | |||
4363 | err = rdev->ops->remain_on_channel(&rdev->wiphy, dev, chan, | ||
4364 | channel_type, duration, &cookie); | ||
4365 | |||
4366 | if (err) | ||
4367 | goto free_msg; | ||
4368 | |||
4369 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); | ||
4370 | |||
4371 | genlmsg_end(msg, hdr); | ||
4372 | err = genlmsg_reply(msg, info); | ||
4373 | goto out; | ||
4374 | |||
4375 | nla_put_failure: | ||
4376 | err = -ENOBUFS; | ||
4377 | free_msg: | ||
4378 | nlmsg_free(msg); | ||
4379 | out: | ||
4380 | cfg80211_unlock_rdev(rdev); | ||
4381 | dev_put(dev); | ||
4382 | unlock_rtnl: | ||
4383 | rtnl_unlock(); | ||
4384 | return err; | ||
4385 | } | ||
4386 | |||
4387 | static int nl80211_cancel_remain_on_channel(struct sk_buff *skb, | ||
4388 | struct genl_info *info) | ||
4389 | { | ||
4390 | struct cfg80211_registered_device *rdev; | ||
4391 | struct net_device *dev; | ||
4392 | u64 cookie; | ||
4393 | int err; | ||
4394 | |||
4395 | if (!info->attrs[NL80211_ATTR_COOKIE]) | ||
4396 | return -EINVAL; | ||
4397 | |||
4398 | rtnl_lock(); | ||
4399 | |||
4400 | err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); | ||
4401 | if (err) | ||
4402 | goto unlock_rtnl; | ||
4403 | |||
4404 | if (!rdev->ops->cancel_remain_on_channel) { | ||
4405 | err = -EOPNOTSUPP; | ||
4406 | goto out; | ||
4407 | } | ||
4408 | |||
4409 | if (!netif_running(dev)) { | ||
4410 | err = -ENETDOWN; | ||
4411 | goto out; | ||
4412 | } | ||
4413 | |||
4414 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); | ||
4415 | |||
4416 | err = rdev->ops->cancel_remain_on_channel(&rdev->wiphy, dev, cookie); | ||
4417 | |||
4418 | out: | ||
4419 | cfg80211_unlock_rdev(rdev); | ||
4420 | dev_put(dev); | ||
4421 | unlock_rtnl: | ||
4422 | rtnl_unlock(); | ||
4423 | return err; | ||
4424 | } | ||
4425 | |||
4292 | static struct genl_ops nl80211_ops[] = { | 4426 | static struct genl_ops nl80211_ops[] = { |
4293 | { | 4427 | { |
4294 | .cmd = NL80211_CMD_GET_WIPHY, | 4428 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -4551,8 +4685,20 @@ static struct genl_ops nl80211_ops[] = { | |||
4551 | .policy = nl80211_policy, | 4685 | .policy = nl80211_policy, |
4552 | .flags = GENL_ADMIN_PERM, | 4686 | .flags = GENL_ADMIN_PERM, |
4553 | }, | 4687 | }, |
4554 | 4688 | { | |
4689 | .cmd = NL80211_CMD_REMAIN_ON_CHANNEL, | ||
4690 | .doit = nl80211_remain_on_channel, | ||
4691 | .policy = nl80211_policy, | ||
4692 | .flags = GENL_ADMIN_PERM, | ||
4693 | }, | ||
4694 | { | ||
4695 | .cmd = NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | ||
4696 | .doit = nl80211_cancel_remain_on_channel, | ||
4697 | .policy = nl80211_policy, | ||
4698 | .flags = GENL_ADMIN_PERM, | ||
4699 | }, | ||
4555 | }; | 4700 | }; |
4701 | |||
4556 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 4702 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
4557 | .name = "mlme", | 4703 | .name = "mlme", |
4558 | }; | 4704 | }; |
@@ -5140,6 +5286,89 @@ nla_put_failure: | |||
5140 | nlmsg_free(msg); | 5286 | nlmsg_free(msg); |
5141 | } | 5287 | } |
5142 | 5288 | ||
5289 | static void nl80211_send_remain_on_chan_event( | ||
5290 | int cmd, struct cfg80211_registered_device *rdev, | ||
5291 | struct net_device *netdev, u64 cookie, | ||
5292 | struct ieee80211_channel *chan, | ||
5293 | enum nl80211_channel_type channel_type, | ||
5294 | unsigned int duration, gfp_t gfp) | ||
5295 | { | ||
5296 | struct sk_buff *msg; | ||
5297 | void *hdr; | ||
5298 | |||
5299 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp); | ||
5300 | if (!msg) | ||
5301 | return; | ||
5302 | |||
5303 | hdr = nl80211hdr_put(msg, 0, 0, 0, cmd); | ||
5304 | if (!hdr) { | ||
5305 | nlmsg_free(msg); | ||
5306 | return; | ||
5307 | } | ||
5308 | |||
5309 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5310 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5311 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, chan->center_freq); | ||
5312 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_CHANNEL_TYPE, channel_type); | ||
5313 | NLA_PUT_U64(msg, NL80211_ATTR_COOKIE, cookie); | ||
5314 | |||
5315 | if (cmd == NL80211_CMD_REMAIN_ON_CHANNEL) | ||
5316 | NLA_PUT_U32(msg, NL80211_ATTR_DURATION, duration); | ||
5317 | |||
5318 | if (genlmsg_end(msg, hdr) < 0) { | ||
5319 | nlmsg_free(msg); | ||
5320 | return; | ||
5321 | } | ||
5322 | |||
5323 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
5324 | nl80211_mlme_mcgrp.id, gfp); | ||
5325 | return; | ||
5326 | |||
5327 | nla_put_failure: | ||
5328 | genlmsg_cancel(msg, hdr); | ||
5329 | nlmsg_free(msg); | ||
5330 | } | ||
5331 | |||
5332 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | ||
5333 | struct net_device *netdev, u64 cookie, | ||
5334 | struct ieee80211_channel *chan, | ||
5335 | enum nl80211_channel_type channel_type, | ||
5336 | unsigned int duration, gfp_t gfp) | ||
5337 | { | ||
5338 | nl80211_send_remain_on_chan_event(NL80211_CMD_REMAIN_ON_CHANNEL, | ||
5339 | rdev, netdev, cookie, chan, | ||
5340 | channel_type, duration, gfp); | ||
5341 | } | ||
5342 | |||
5343 | void nl80211_send_remain_on_channel_cancel( | ||
5344 | struct cfg80211_registered_device *rdev, struct net_device *netdev, | ||
5345 | u64 cookie, struct ieee80211_channel *chan, | ||
5346 | enum nl80211_channel_type channel_type, gfp_t gfp) | ||
5347 | { | ||
5348 | nl80211_send_remain_on_chan_event(NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, | ||
5349 | rdev, netdev, cookie, chan, | ||
5350 | channel_type, 0, gfp); | ||
5351 | } | ||
5352 | |||
5353 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | ||
5354 | struct net_device *dev, const u8 *mac_addr, | ||
5355 | struct station_info *sinfo, gfp_t gfp) | ||
5356 | { | ||
5357 | struct sk_buff *msg; | ||
5358 | |||
5359 | msg = nlmsg_new(NLMSG_GOODSIZE, gfp); | ||
5360 | if (!msg) | ||
5361 | return; | ||
5362 | |||
5363 | if (nl80211_send_station(msg, 0, 0, 0, dev, mac_addr, sinfo) < 0) { | ||
5364 | nlmsg_free(msg); | ||
5365 | return; | ||
5366 | } | ||
5367 | |||
5368 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
5369 | nl80211_mlme_mcgrp.id, gfp); | ||
5370 | } | ||
5371 | |||
5143 | /* initialisation/exit functions */ | 5372 | /* initialisation/exit functions */ |
5144 | 5373 | ||
5145 | int nl80211_init(void) | 5374 | int nl80211_init(void) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 44cc2a76a1b0..14855b8fb430 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -59,4 +59,19 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev, | |||
59 | struct net_device *netdev, const u8 *bssid, | 59 | struct net_device *netdev, const u8 *bssid, |
60 | gfp_t gfp); | 60 | gfp_t gfp); |
61 | 61 | ||
62 | void nl80211_send_remain_on_channel(struct cfg80211_registered_device *rdev, | ||
63 | struct net_device *netdev, | ||
64 | u64 cookie, | ||
65 | struct ieee80211_channel *chan, | ||
66 | enum nl80211_channel_type channel_type, | ||
67 | unsigned int duration, gfp_t gfp); | ||
68 | void nl80211_send_remain_on_channel_cancel( | ||
69 | struct cfg80211_registered_device *rdev, struct net_device *netdev, | ||
70 | u64 cookie, struct ieee80211_channel *chan, | ||
71 | enum nl80211_channel_type channel_type, gfp_t gfp); | ||
72 | |||
73 | void nl80211_send_sta_event(struct cfg80211_registered_device *rdev, | ||
74 | struct net_device *dev, const u8 *mac_addr, | ||
75 | struct station_info *sinfo, gfp_t gfp); | ||
76 | |||
62 | #endif /* __NET_WIRELESS_NL80211_H */ | 77 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index dc13c3ffeca6..87ea60d84c3c 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -129,78 +129,6 @@ static char *ieee80211_regdom = "00"; | |||
129 | module_param(ieee80211_regdom, charp, 0444); | 129 | module_param(ieee80211_regdom, charp, 0444); |
130 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 130 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
131 | 131 | ||
132 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
133 | /* | ||
134 | * We assume 40 MHz bandwidth for the old regulatory work. | ||
135 | * We make emphasis we are using the exact same frequencies | ||
136 | * as before | ||
137 | */ | ||
138 | |||
139 | static const struct ieee80211_regdomain us_regdom = { | ||
140 | .n_reg_rules = 6, | ||
141 | .alpha2 = "US", | ||
142 | .reg_rules = { | ||
143 | /* IEEE 802.11b/g, channels 1..11 */ | ||
144 | REG_RULE(2412-10, 2462+10, 40, 6, 27, 0), | ||
145 | /* IEEE 802.11a, channel 36..48 */ | ||
146 | REG_RULE(5180-10, 5240+10, 40, 6, 17, 0), | ||
147 | /* IEEE 802.11a, channels 48..64 */ | ||
148 | REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS), | ||
149 | /* IEEE 802.11a, channels 100..124 */ | ||
150 | REG_RULE(5500-10, 5590+10, 40, 6, 20, NL80211_RRF_DFS), | ||
151 | /* IEEE 802.11a, channels 132..144 */ | ||
152 | REG_RULE(5660-10, 5700+10, 40, 6, 20, NL80211_RRF_DFS), | ||
153 | /* IEEE 802.11a, channels 149..165, outdoor */ | ||
154 | REG_RULE(5745-10, 5825+10, 40, 6, 30, 0), | ||
155 | } | ||
156 | }; | ||
157 | |||
158 | static const struct ieee80211_regdomain jp_regdom = { | ||
159 | .n_reg_rules = 6, | ||
160 | .alpha2 = "JP", | ||
161 | .reg_rules = { | ||
162 | /* IEEE 802.11b/g, channels 1..11 */ | ||
163 | REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), | ||
164 | /* IEEE 802.11b/g, channels 12..13 */ | ||
165 | REG_RULE(2467-10, 2472+10, 20, 6, 20, 0), | ||
166 | /* IEEE 802.11b/g, channel 14 */ | ||
167 | REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_NO_OFDM), | ||
168 | /* IEEE 802.11a, channels 36..48 */ | ||
169 | REG_RULE(5180-10, 5240+10, 40, 6, 20, 0), | ||
170 | /* IEEE 802.11a, channels 52..64 */ | ||
171 | REG_RULE(5260-10, 5320+10, 40, 6, 20, NL80211_RRF_DFS), | ||
172 | /* IEEE 802.11a, channels 100..144 */ | ||
173 | REG_RULE(5500-10, 5700+10, 40, 6, 23, NL80211_RRF_DFS), | ||
174 | } | ||
175 | }; | ||
176 | |||
177 | static const struct ieee80211_regdomain *static_regdom(char *alpha2) | ||
178 | { | ||
179 | if (alpha2[0] == 'U' && alpha2[1] == 'S') | ||
180 | return &us_regdom; | ||
181 | if (alpha2[0] == 'J' && alpha2[1] == 'P') | ||
182 | return &jp_regdom; | ||
183 | /* Use world roaming rules for "EU", since it was a pseudo | ||
184 | domain anyway... */ | ||
185 | if (alpha2[0] == 'E' && alpha2[1] == 'U') | ||
186 | return &world_regdom; | ||
187 | /* Default, world roaming rules */ | ||
188 | return &world_regdom; | ||
189 | } | ||
190 | |||
191 | static bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
192 | { | ||
193 | if (rd == &us_regdom || rd == &jp_regdom || rd == &world_regdom) | ||
194 | return true; | ||
195 | return false; | ||
196 | } | ||
197 | #else | ||
198 | static inline bool is_old_static_regdom(const struct ieee80211_regdomain *rd) | ||
199 | { | ||
200 | return false; | ||
201 | } | ||
202 | #endif | ||
203 | |||
204 | static void reset_regdomains(void) | 132 | static void reset_regdomains(void) |
205 | { | 133 | { |
206 | /* avoid freeing static information or freeing something twice */ | 134 | /* avoid freeing static information or freeing something twice */ |
@@ -210,8 +138,6 @@ static void reset_regdomains(void) | |||
210 | cfg80211_world_regdom = NULL; | 138 | cfg80211_world_regdom = NULL; |
211 | if (cfg80211_regdomain == &world_regdom) | 139 | if (cfg80211_regdomain == &world_regdom) |
212 | cfg80211_regdomain = NULL; | 140 | cfg80211_regdomain = NULL; |
213 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
214 | cfg80211_regdomain = NULL; | ||
215 | 141 | ||
216 | kfree(cfg80211_regdomain); | 142 | kfree(cfg80211_regdomain); |
217 | kfree(cfg80211_world_regdom); | 143 | kfree(cfg80211_world_regdom); |
@@ -1490,8 +1416,6 @@ static int ignore_request(struct wiphy *wiphy, | |||
1490 | return REG_INTERSECT; | 1416 | return REG_INTERSECT; |
1491 | case NL80211_REGDOM_SET_BY_DRIVER: | 1417 | case NL80211_REGDOM_SET_BY_DRIVER: |
1492 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { | 1418 | if (last_request->initiator == NL80211_REGDOM_SET_BY_CORE) { |
1493 | if (is_old_static_regdom(cfg80211_regdomain)) | ||
1494 | return 0; | ||
1495 | if (regdom_changes(pending_request->alpha2)) | 1419 | if (regdom_changes(pending_request->alpha2)) |
1496 | return 0; | 1420 | return 0; |
1497 | return -EALREADY; | 1421 | return -EALREADY; |
@@ -1528,8 +1452,7 @@ static int ignore_request(struct wiphy *wiphy, | |||
1528 | return -EAGAIN; | 1452 | return -EAGAIN; |
1529 | } | 1453 | } |
1530 | 1454 | ||
1531 | if (!is_old_static_regdom(cfg80211_regdomain) && | 1455 | if (!regdom_changes(pending_request->alpha2)) |
1532 | !regdom_changes(pending_request->alpha2)) | ||
1533 | return -EALREADY; | 1456 | return -EALREADY; |
1534 | 1457 | ||
1535 | return 0; | 1458 | return 0; |
@@ -2111,8 +2034,7 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) | |||
2111 | * If someone else asked us to change the rd lets only bother | 2034 | * If someone else asked us to change the rd lets only bother |
2112 | * checking if the alpha2 changes if CRDA was already called | 2035 | * checking if the alpha2 changes if CRDA was already called |
2113 | */ | 2036 | */ |
2114 | if (!is_old_static_regdom(cfg80211_regdomain) && | 2037 | if (!regdom_changes(rd->alpha2)) |
2115 | !regdom_changes(rd->alpha2)) | ||
2116 | return -EINVAL; | 2038 | return -EINVAL; |
2117 | } | 2039 | } |
2118 | 2040 | ||
@@ -2311,15 +2233,8 @@ int regulatory_init(void) | |||
2311 | spin_lock_init(®_requests_lock); | 2233 | spin_lock_init(®_requests_lock); |
2312 | spin_lock_init(®_pending_beacons_lock); | 2234 | spin_lock_init(®_pending_beacons_lock); |
2313 | 2235 | ||
2314 | #ifdef CONFIG_WIRELESS_OLD_REGULATORY | ||
2315 | cfg80211_regdomain = static_regdom(ieee80211_regdom); | ||
2316 | |||
2317 | printk(KERN_INFO "cfg80211: Using static regulatory domain info\n"); | ||
2318 | print_regdomain_info(cfg80211_regdomain); | ||
2319 | #else | ||
2320 | cfg80211_regdomain = cfg80211_world_regdom; | 2236 | cfg80211_regdomain = cfg80211_world_regdom; |
2321 | 2237 | ||
2322 | #endif | ||
2323 | /* We always try to get an update for the static regdomain */ | 2238 | /* We always try to get an update for the static regdomain */ |
2324 | err = regulatory_hint_core(cfg80211_regdomain->alpha2); | 2239 | err = regulatory_hint_core(cfg80211_regdomain->alpha2); |
2325 | if (err) { | 2240 | if (err) { |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 12dfa62aad18..0c2cbbebca95 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -601,7 +601,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
601 | struct cfg80211_registered_device *rdev; | 601 | struct cfg80211_registered_device *rdev; |
602 | struct wiphy *wiphy; | 602 | struct wiphy *wiphy; |
603 | struct iw_scan_req *wreq = NULL; | 603 | struct iw_scan_req *wreq = NULL; |
604 | struct cfg80211_scan_request *creq; | 604 | struct cfg80211_scan_request *creq = NULL; |
605 | int i, err, n_channels = 0; | 605 | int i, err, n_channels = 0; |
606 | enum ieee80211_band band; | 606 | enum ieee80211_band band; |
607 | 607 | ||
@@ -694,8 +694,10 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
694 | /* translate "Scan for SSID" request */ | 694 | /* translate "Scan for SSID" request */ |
695 | if (wreq) { | 695 | if (wreq) { |
696 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { | 696 | if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { |
697 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) | 697 | if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) { |
698 | return -EINVAL; | 698 | err = -EINVAL; |
699 | goto out; | ||
700 | } | ||
699 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); | 701 | memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len); |
700 | creq->ssids[0].ssid_len = wreq->essid_len; | 702 | creq->ssids[0].ssid_len = wreq->essid_len; |
701 | } | 703 | } |
@@ -707,12 +709,15 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
707 | err = rdev->ops->scan(wiphy, dev, creq); | 709 | err = rdev->ops->scan(wiphy, dev, creq); |
708 | if (err) { | 710 | if (err) { |
709 | rdev->scan_req = NULL; | 711 | rdev->scan_req = NULL; |
710 | kfree(creq); | 712 | /* creq will be freed below */ |
711 | } else { | 713 | } else { |
712 | nl80211_send_scan_start(rdev, dev); | 714 | nl80211_send_scan_start(rdev, dev); |
715 | /* creq now owned by driver */ | ||
716 | creq = NULL; | ||
713 | dev_hold(dev); | 717 | dev_hold(dev); |
714 | } | 718 | } |
715 | out: | 719 | out: |
720 | kfree(creq); | ||
716 | cfg80211_unlock_rdev(rdev); | 721 | cfg80211_unlock_rdev(rdev); |
717 | return err; | 722 | return err; |
718 | } | 723 | } |