diff options
Diffstat (limited to 'drivers/net')
117 files changed, 2873 insertions, 1917 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 1128fa8c9ed5..91c5f73b5ba3 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -2061,11 +2061,12 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2061 | 2061 | ||
2062 | int i; | 2062 | int i; |
2063 | 2063 | ||
2064 | at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d " | 2064 | at76_dbg(DBG_MAC80211, "%s(): cmd %d key->cipher %d key->keyidx %d " |
2065 | "key->keylen %d", | 2065 | "key->keylen %d", |
2066 | __func__, cmd, key->alg, key->keyidx, key->keylen); | 2066 | __func__, cmd, key->cipher, key->keyidx, key->keylen); |
2067 | 2067 | ||
2068 | if (key->alg != ALG_WEP) | 2068 | if ((key->cipher != WLAN_CIPHER_SUITE_WEP40) && |
2069 | (key->cipher != WLAN_CIPHER_SUITE_WEP104)) | ||
2069 | return -EOPNOTSUPP; | 2070 | return -EOPNOTSUPP; |
2070 | 2071 | ||
2071 | key->hw_key_idx = key->keyidx; | 2072 | key->hw_key_idx = key->keyidx; |
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index debfb0fbc7c5..32bf79e6a320 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1190,14 +1190,13 @@ static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) | |||
1190 | if (info->control.hw_key) { | 1190 | if (info->control.hw_key) { |
1191 | icv = info->control.hw_key->icv_len; | 1191 | icv = info->control.hw_key->icv_len; |
1192 | 1192 | ||
1193 | switch (info->control.hw_key->alg) { | 1193 | switch (info->control.hw_key->cipher) { |
1194 | case ALG_WEP: | 1194 | case WLAN_CIPHER_SUITE_WEP40: |
1195 | case WLAN_CIPHER_SUITE_WEP104: | ||
1196 | case WLAN_CIPHER_SUITE_TKIP: | ||
1195 | keytype = AR9170_TX_MAC_ENCR_RC4; | 1197 | keytype = AR9170_TX_MAC_ENCR_RC4; |
1196 | break; | 1198 | break; |
1197 | case ALG_TKIP: | 1199 | case WLAN_CIPHER_SUITE_CCMP: |
1198 | keytype = AR9170_TX_MAC_ENCR_RC4; | ||
1199 | break; | ||
1200 | case ALG_CCMP: | ||
1201 | keytype = AR9170_TX_MAC_ENCR_AES; | 1200 | keytype = AR9170_TX_MAC_ENCR_AES; |
1202 | break; | 1201 | break; |
1203 | default: | 1202 | default: |
@@ -1778,17 +1777,17 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1778 | if ((!ar->vif) || (ar->disable_offload)) | 1777 | if ((!ar->vif) || (ar->disable_offload)) |
1779 | return -EOPNOTSUPP; | 1778 | return -EOPNOTSUPP; |
1780 | 1779 | ||
1781 | switch (key->alg) { | 1780 | switch (key->cipher) { |
1782 | case ALG_WEP: | 1781 | case WLAN_CIPHER_SUITE_WEP40: |
1783 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 1782 | ktype = AR9170_ENC_ALG_WEP64; |
1784 | ktype = AR9170_ENC_ALG_WEP64; | 1783 | break; |
1785 | else | 1784 | case WLAN_CIPHER_SUITE_WEP104: |
1786 | ktype = AR9170_ENC_ALG_WEP128; | 1785 | ktype = AR9170_ENC_ALG_WEP128; |
1787 | break; | 1786 | break; |
1788 | case ALG_TKIP: | 1787 | case WLAN_CIPHER_SUITE_TKIP: |
1789 | ktype = AR9170_ENC_ALG_TKIP; | 1788 | ktype = AR9170_ENC_ALG_TKIP; |
1790 | break; | 1789 | break; |
1791 | case ALG_CCMP: | 1790 | case WLAN_CIPHER_SUITE_CCMP: |
1792 | ktype = AR9170_ENC_ALG_AESCCMP; | 1791 | ktype = AR9170_ENC_ALG_AESCCMP; |
1793 | break; | 1792 | break; |
1794 | default: | 1793 | default: |
@@ -1827,7 +1826,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1827 | if (err) | 1826 | if (err) |
1828 | goto out; | 1827 | goto out; |
1829 | 1828 | ||
1830 | if (key->alg == ALG_TKIP) { | 1829 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
1831 | err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, | 1830 | err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, |
1832 | ktype, 1, key->key + 16, 16); | 1831 | ktype, 1, key->key + 16, 16); |
1833 | if (err) | 1832 | if (err) |
@@ -1864,7 +1863,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1864 | if (err) | 1863 | if (err) |
1865 | goto out; | 1864 | goto out; |
1866 | 1865 | ||
1867 | if (key->alg == ALG_TKIP) { | 1866 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
1868 | err = ar9170_upload_key(ar, key->hw_key_idx, | 1867 | err = ar9170_upload_key(ar, key->hw_key_idx, |
1869 | NULL, | 1868 | NULL, |
1870 | AR9170_ENC_ALG_NONE, 1, | 1869 | AR9170_ENC_ALG_NONE, 1, |
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c index 26dbe65fedb0..e4a5f046bba4 100644 --- a/drivers/net/wireless/ath/ath5k/ani.c +++ b/drivers/net/wireless/ath/ath5k/ani.c | |||
@@ -552,9 +552,9 @@ ath5k_ani_mib_intr(struct ath5k_hw *ah) | |||
552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) | 552 | if (ah->ah_sc->ani_state.ani_mode != ATH5K_ANI_MODE_AUTO) |
553 | return; | 553 | return; |
554 | 554 | ||
555 | /* if one of the errors triggered, we can get a superfluous second | 555 | /* If one of the errors triggered, we can get a superfluous second |
556 | * interrupt, even though we have already reset the register. the | 556 | * interrupt, even though we have already reset the register. The |
557 | * function detects that so we can return early */ | 557 | * function detects that so we can return early. */ |
558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) | 558 | if (ath5k_ani_save_and_clear_phy_errors(ah, as) == 0) |
559 | return; | 559 | return; |
560 | 560 | ||
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index ea6362a8988d..f399c4dd8e69 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -175,7 +175,7 @@ | |||
175 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 | 175 | #define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 |
176 | #define AR5K_TUNE_RADAR_ALERT false | 176 | #define AR5K_TUNE_RADAR_ALERT false |
177 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 | 177 | #define AR5K_TUNE_MIN_TX_FIFO_THRES 1 |
178 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) | 178 | #define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1) |
179 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 | 179 | #define AR5K_TUNE_REGISTER_TIMEOUT 20000 |
180 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to | 180 | /* Register for RSSI threshold has a mask of 0xff, so 255 seems to |
181 | * be the max value. */ | 181 | * be the max value. */ |
@@ -343,9 +343,6 @@ struct ath5k_srev_name { | |||
343 | #define AR5K_SREV_PHY_5413 0x61 | 343 | #define AR5K_SREV_PHY_5413 0x61 |
344 | #define AR5K_SREV_PHY_2425 0x70 | 344 | #define AR5K_SREV_PHY_2425 0x70 |
345 | 345 | ||
346 | /* IEEE defs */ | ||
347 | #define IEEE80211_MAX_LEN 2500 | ||
348 | |||
349 | /* TODO add support to mac80211 for vendor-specific rates and modes */ | 346 | /* TODO add support to mac80211 for vendor-specific rates and modes */ |
350 | 347 | ||
351 | /* | 348 | /* |
@@ -1190,7 +1187,7 @@ extern int ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype opmode); | |||
1190 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); | 1187 | void ath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class); |
1191 | /* BSSID Functions */ | 1188 | /* BSSID Functions */ |
1192 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); | 1189 | int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); |
1193 | void ath5k_hw_set_associd(struct ath5k_hw *ah); | 1190 | void ath5k_hw_set_bssid(struct ath5k_hw *ah); |
1194 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); | 1191 | void ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); |
1195 | /* Receive start/stop functions */ | 1192 | /* Receive start/stop functions */ |
1196 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); | 1193 | void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c index b32e28caeee2..aabad4f13e2a 100644 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ b/drivers/net/wireless/ath/ath5k/attach.c | |||
@@ -139,12 +139,12 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
139 | else | 139 | else |
140 | ah->ah_version = AR5K_AR5212; | 140 | ah->ah_version = AR5K_AR5212; |
141 | 141 | ||
142 | /*Fill the ath5k_hw struct with the needed functions*/ | 142 | /* Fill the ath5k_hw struct with the needed functions */ |
143 | ret = ath5k_hw_init_desc_functions(ah); | 143 | ret = ath5k_hw_init_desc_functions(ah); |
144 | if (ret) | 144 | if (ret) |
145 | goto err_free; | 145 | goto err_free; |
146 | 146 | ||
147 | /* Bring device out of sleep and reset it's units */ | 147 | /* Bring device out of sleep and reset its units */ |
148 | ret = ath5k_hw_nic_wakeup(ah, 0, true); | 148 | ret = ath5k_hw_nic_wakeup(ah, 0, true); |
149 | if (ret) | 149 | if (ret) |
150 | goto err_free; | 150 | goto err_free; |
@@ -158,7 +158,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
158 | CHANNEL_5GHZ); | 158 | CHANNEL_5GHZ); |
159 | ah->ah_phy = AR5K_PHY(0); | 159 | ah->ah_phy = AR5K_PHY(0); |
160 | 160 | ||
161 | /* Try to identify radio chip based on it's srev */ | 161 | /* Try to identify radio chip based on its srev */ |
162 | switch (ah->ah_radio_5ghz_revision & 0xf0) { | 162 | switch (ah->ah_radio_5ghz_revision & 0xf0) { |
163 | case AR5K_SREV_RAD_5111: | 163 | case AR5K_SREV_RAD_5111: |
164 | ah->ah_radio = AR5K_RF5111; | 164 | ah->ah_radio = AR5K_RF5111; |
@@ -329,7 +329,7 @@ int ath5k_hw_attach(struct ath5k_softc *sc) | |||
329 | 329 | ||
330 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ | 330 | /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ |
331 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); | 331 | memcpy(common->curbssid, ath_bcast_mac, ETH_ALEN); |
332 | ath5k_hw_set_associd(ah); | 332 | ath5k_hw_set_bssid(ah); |
333 | ath5k_hw_set_opmode(ah, sc->opmode); | 333 | ath5k_hw_set_opmode(ah, sc->opmode); |
334 | 334 | ||
335 | ath5k_hw_rfgain_opt_init(ah); | 335 | ath5k_hw_rfgain_opt_init(ah); |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 373dcfec689c..f2fceb10c9fc 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -612,7 +612,7 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
612 | goto err_free; | 612 | goto err_free; |
613 | } | 613 | } |
614 | 614 | ||
615 | /*If we passed the test malloc a ath5k_hw struct*/ | 615 | /* If we passed the test, malloc an ath5k_hw struct */ |
616 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); | 616 | sc->ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); |
617 | if (!sc->ah) { | 617 | if (!sc->ah) { |
618 | ret = -ENOMEM; | 618 | ret = -ENOMEM; |
@@ -786,8 +786,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
786 | /* | 786 | /* |
787 | * Check if the MAC has multi-rate retry support. | 787 | * Check if the MAC has multi-rate retry support. |
788 | * We do this by trying to setup a fake extended | 788 | * We do this by trying to setup a fake extended |
789 | * descriptor. MAC's that don't have support will | 789 | * descriptor. MACs that don't have support will |
790 | * return false w/o doing anything. MAC's that do | 790 | * return false w/o doing anything. MACs that do |
791 | * support it will return true w/o doing anything. | 791 | * support it will return true w/o doing anything. |
792 | */ | 792 | */ |
793 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); | 793 | ret = ath5k_hw_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); |
@@ -827,7 +827,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
827 | /* | 827 | /* |
828 | * Allocate hardware transmit queues: one queue for | 828 | * Allocate hardware transmit queues: one queue for |
829 | * beacon frames and one data queue for each QoS | 829 | * beacon frames and one data queue for each QoS |
830 | * priority. Note that hw functions handle reseting | 830 | * priority. Note that hw functions handle resetting |
831 | * these queues at the needed time. | 831 | * these queues at the needed time. |
832 | */ | 832 | */ |
833 | ret = ath5k_beaconq_setup(ah); | 833 | ret = ath5k_beaconq_setup(ah); |
@@ -909,7 +909,7 @@ ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
909 | /* | 909 | /* |
910 | * NB: the order of these is important: | 910 | * NB: the order of these is important: |
911 | * o call the 802.11 layer before detaching ath5k_hw to | 911 | * o call the 802.11 layer before detaching ath5k_hw to |
912 | * insure callbacks into the driver to delete global | 912 | * ensure callbacks into the driver to delete global |
913 | * key cache entries can be handled | 913 | * key cache entries can be handled |
914 | * o reclaim the tx queue data structures after calling | 914 | * o reclaim the tx queue data structures after calling |
915 | * the 802.11 layer as we'll get called back to reclaim | 915 | * the 802.11 layer as we'll get called back to reclaim |
@@ -1514,7 +1514,7 @@ ath5k_txq_setup(struct ath5k_softc *sc, | |||
1514 | /* | 1514 | /* |
1515 | * Enable interrupts only for EOL and DESC conditions. | 1515 | * Enable interrupts only for EOL and DESC conditions. |
1516 | * We mark tx descriptors to receive a DESC interrupt | 1516 | * We mark tx descriptors to receive a DESC interrupt |
1517 | * when a tx queue gets deep; otherwise waiting for the | 1517 | * when a tx queue gets deep; otherwise we wait for the |
1518 | * EOL to reap descriptors. Note that this is done to | 1518 | * EOL to reap descriptors. Note that this is done to |
1519 | * reduce interrupt load and this only defers reaping | 1519 | * reduce interrupt load and this only defers reaping |
1520 | * descriptors, never transmitting frames. Aside from | 1520 | * descriptors, never transmitting frames. Aside from |
@@ -1709,7 +1709,7 @@ ath5k_rx_start(struct ath5k_softc *sc) | |||
1709 | struct ath5k_buf *bf; | 1709 | struct ath5k_buf *bf; |
1710 | int ret; | 1710 | int ret; |
1711 | 1711 | ||
1712 | common->rx_bufsize = roundup(IEEE80211_MAX_LEN, common->cachelsz); | 1712 | common->rx_bufsize = roundup(IEEE80211_MAX_FRAME_LEN, common->cachelsz); |
1713 | 1713 | ||
1714 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", | 1714 | ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rx_bufsize %u\n", |
1715 | common->cachelsz, common->rx_bufsize); | 1715 | common->cachelsz, common->rx_bufsize); |
@@ -1859,7 +1859,7 @@ ath5k_update_beacon_rssi(struct ath5k_softc *sc, struct sk_buff *skb, int rssi) | |||
1859 | } | 1859 | } |
1860 | 1860 | ||
1861 | /* | 1861 | /* |
1862 | * Compute padding position. skb must contains an IEEE 802.11 frame | 1862 | * Compute padding position. skb must contain an IEEE 802.11 frame |
1863 | */ | 1863 | */ |
1864 | static int ath5k_common_padpos(struct sk_buff *skb) | 1864 | static int ath5k_common_padpos(struct sk_buff *skb) |
1865 | { | 1865 | { |
@@ -1878,10 +1878,9 @@ static int ath5k_common_padpos(struct sk_buff *skb) | |||
1878 | } | 1878 | } |
1879 | 1879 | ||
1880 | /* | 1880 | /* |
1881 | * This function expects a 802.11 frame and returns the number of | 1881 | * This function expects an 802.11 frame and returns the number of |
1882 | * bytes added, or -1 if we don't have enought header room. | 1882 | * bytes added, or -1 if we don't have enough header room. |
1883 | */ | 1883 | */ |
1884 | |||
1885 | static int ath5k_add_padding(struct sk_buff *skb) | 1884 | static int ath5k_add_padding(struct sk_buff *skb) |
1886 | { | 1885 | { |
1887 | int padpos = ath5k_common_padpos(skb); | 1886 | int padpos = ath5k_common_padpos(skb); |
@@ -1901,10 +1900,18 @@ static int ath5k_add_padding(struct sk_buff *skb) | |||
1901 | } | 1900 | } |
1902 | 1901 | ||
1903 | /* | 1902 | /* |
1904 | * This function expects a 802.11 frame and returns the number of | 1903 | * The MAC header is padded to have 32-bit boundary if the |
1905 | * bytes removed | 1904 | * packet payload is non-zero. The general calculation for |
1905 | * padsize would take into account odd header lengths: | ||
1906 | * padsize = 4 - (hdrlen & 3); however, since only | ||
1907 | * even-length headers are used, padding can only be 0 or 2 | ||
1908 | * bytes and we can optimize this a bit. We must not try to | ||
1909 | * remove padding from short control frames that do not have a | ||
1910 | * payload. | ||
1911 | * | ||
1912 | * This function expects an 802.11 frame and returns the number of | ||
1913 | * bytes removed. | ||
1906 | */ | 1914 | */ |
1907 | |||
1908 | static int ath5k_remove_padding(struct sk_buff *skb) | 1915 | static int ath5k_remove_padding(struct sk_buff *skb) |
1909 | { | 1916 | { |
1910 | int padpos = ath5k_common_padpos(skb); | 1917 | int padpos = ath5k_common_padpos(skb); |
@@ -1925,14 +1932,6 @@ ath5k_receive_frame(struct ath5k_softc *sc, struct sk_buff *skb, | |||
1925 | { | 1932 | { |
1926 | struct ieee80211_rx_status *rxs; | 1933 | struct ieee80211_rx_status *rxs; |
1927 | 1934 | ||
1928 | /* The MAC header is padded to have 32-bit boundary if the | ||
1929 | * packet payload is non-zero. The general calculation for | ||
1930 | * padsize would take into account odd header lengths: | ||
1931 | * padsize = (4 - hdrlen % 4) % 4; However, since only | ||
1932 | * even-length headers are used, padding can only be 0 or 2 | ||
1933 | * bytes and we can optimize this a bit. In addition, we must | ||
1934 | * not try to remove padding from short control frames that do | ||
1935 | * not have payload. */ | ||
1936 | ath5k_remove_padding(skb); | 1935 | ath5k_remove_padding(skb); |
1937 | 1936 | ||
1938 | rxs = IEEE80211_SKB_RXCB(skb); | 1937 | rxs = IEEE80211_SKB_RXCB(skb); |
@@ -2036,9 +2035,8 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs) | |||
2036 | return true; | 2035 | return true; |
2037 | } | 2036 | } |
2038 | 2037 | ||
2039 | /* let crypto-error packets fall through in MNTR */ | 2038 | /* reject any frames with non-crypto errors */ |
2040 | if ((rs->rs_status & ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || | 2039 | if (rs->rs_status & ~(AR5K_RXERR_DECRYPT)) |
2041 | sc->opmode != NL80211_IFTYPE_MONITOR) | ||
2042 | return false; | 2040 | return false; |
2043 | } | 2041 | } |
2044 | 2042 | ||
@@ -2281,10 +2279,11 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
2281 | * default antenna which is supposed to be an omni. | 2279 | * default antenna which is supposed to be an omni. |
2282 | * | 2280 | * |
2283 | * Note2: On sectored scenarios it's possible to have | 2281 | * Note2: On sectored scenarios it's possible to have |
2284 | * multiple antennas (1omni -the default- and 14 sectors) | 2282 | * multiple antennas (1 omni -- the default -- and 14 |
2285 | * so if we choose to actually support this mode we need | 2283 | * sectors), so if we choose to actually support this |
2286 | * to allow user to set how many antennas we have and tweak | 2284 | * mode, we need to allow the user to set how many antennas |
2287 | * the code below to send beacons on all of them. | 2285 | * we have and tweak the code below to send beacons |
2286 | * on all of them. | ||
2288 | */ | 2287 | */ |
2289 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) | 2288 | if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) |
2290 | antenna = sc->bsent & 4 ? 2 : 1; | 2289 | antenna = sc->bsent & 4 ? 2 : 1; |
@@ -2326,14 +2325,13 @@ ath5k_beacon_send(struct ath5k_softc *sc) | |||
2326 | 2325 | ||
2327 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); | 2326 | ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); |
2328 | 2327 | ||
2329 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || | 2328 | if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION)) { |
2330 | sc->opmode == NL80211_IFTYPE_MONITOR)) { | ||
2331 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); | 2329 | ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); |
2332 | return; | 2330 | return; |
2333 | } | 2331 | } |
2334 | /* | 2332 | /* |
2335 | * Check if the previous beacon has gone out. If | 2333 | * Check if the previous beacon has gone out. If |
2336 | * not don't don't try to post another, skip this | 2334 | * not, don't don't try to post another: skip this |
2337 | * period and wait for the next. Missed beacons | 2335 | * period and wait for the next. Missed beacons |
2338 | * indicate a problem and should not occur. If we | 2336 | * indicate a problem and should not occur. If we |
2339 | * miss too many consecutive beacons reset the device. | 2337 | * miss too many consecutive beacons reset the device. |
@@ -2901,12 +2899,9 @@ static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2901 | 2899 | ||
2902 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2900 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
2903 | 2901 | ||
2904 | if (sc->opmode == NL80211_IFTYPE_MONITOR) | ||
2905 | ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); | ||
2906 | |||
2907 | /* | 2902 | /* |
2908 | * the hardware expects the header padded to 4 byte boundaries | 2903 | * The hardware expects the header padded to 4 byte boundaries. |
2909 | * if this is not the case we add the padding after the header | 2904 | * If this is not the case, we add the padding after the header. |
2910 | */ | 2905 | */ |
2911 | padsize = ath5k_add_padding(skb); | 2906 | padsize = ath5k_add_padding(skb); |
2912 | if (padsize < 0) { | 2907 | if (padsize < 0) { |
@@ -3049,7 +3044,6 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
3049 | case NL80211_IFTYPE_STATION: | 3044 | case NL80211_IFTYPE_STATION: |
3050 | case NL80211_IFTYPE_ADHOC: | 3045 | case NL80211_IFTYPE_ADHOC: |
3051 | case NL80211_IFTYPE_MESH_POINT: | 3046 | case NL80211_IFTYPE_MESH_POINT: |
3052 | case NL80211_IFTYPE_MONITOR: | ||
3053 | sc->opmode = vif->type; | 3047 | sc->opmode = vif->type; |
3054 | break; | 3048 | break; |
3055 | default: | 3049 | default: |
@@ -3233,9 +3227,9 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
3233 | rfilt |= AR5K_RX_FILTER_PHYERR; | 3227 | rfilt |= AR5K_RX_FILTER_PHYERR; |
3234 | 3228 | ||
3235 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons | 3229 | /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons |
3236 | * and probes for any BSSID, this needs testing */ | 3230 | * and probes for any BSSID */ |
3237 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) | 3231 | if (*new_flags & FIF_BCN_PRBRESP_PROMISC) |
3238 | rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; | 3232 | rfilt |= AR5K_RX_FILTER_BEACON; |
3239 | 3233 | ||
3240 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not | 3234 | /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not |
3241 | * set we should only pass on control frames for this | 3235 | * set we should only pass on control frames for this |
@@ -3251,7 +3245,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
3251 | 3245 | ||
3252 | switch (sc->opmode) { | 3246 | switch (sc->opmode) { |
3253 | case NL80211_IFTYPE_MESH_POINT: | 3247 | case NL80211_IFTYPE_MESH_POINT: |
3254 | case NL80211_IFTYPE_MONITOR: | ||
3255 | rfilt |= AR5K_RX_FILTER_CONTROL | | 3248 | rfilt |= AR5K_RX_FILTER_CONTROL | |
3256 | AR5K_RX_FILTER_BEACON | | 3249 | AR5K_RX_FILTER_BEACON | |
3257 | AR5K_RX_FILTER_PROBEREQ | | 3250 | AR5K_RX_FILTER_PROBEREQ | |
@@ -3274,7 +3267,7 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
3274 | 3267 | ||
3275 | /* Set multicast bits */ | 3268 | /* Set multicast bits */ |
3276 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); | 3269 | ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); |
3277 | /* Set the cached hw filter flags, this will alter actually | 3270 | /* Set the cached hw filter flags, this will later actually |
3278 | * be set in HW */ | 3271 | * be set in HW */ |
3279 | sc->filter_flags = rfilt; | 3272 | sc->filter_flags = rfilt; |
3280 | 3273 | ||
@@ -3297,11 +3290,12 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3297 | if (sc->opmode == NL80211_IFTYPE_AP) | 3290 | if (sc->opmode == NL80211_IFTYPE_AP) |
3298 | return -EOPNOTSUPP; | 3291 | return -EOPNOTSUPP; |
3299 | 3292 | ||
3300 | switch (key->alg) { | 3293 | switch (key->cipher) { |
3301 | case ALG_WEP: | 3294 | case WLAN_CIPHER_SUITE_WEP40: |
3302 | case ALG_TKIP: | 3295 | case WLAN_CIPHER_SUITE_WEP104: |
3296 | case WLAN_CIPHER_SUITE_TKIP: | ||
3303 | break; | 3297 | break; |
3304 | case ALG_CCMP: | 3298 | case WLAN_CIPHER_SUITE_CCMP: |
3305 | if (sc->ah->ah_aes_support) | 3299 | if (sc->ah->ah_aes_support) |
3306 | break; | 3300 | break; |
3307 | 3301 | ||
@@ -3475,7 +3469,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3475 | /* Cache for later use during resets */ | 3469 | /* Cache for later use during resets */ |
3476 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | 3470 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
3477 | common->curaid = 0; | 3471 | common->curaid = 0; |
3478 | ath5k_hw_set_associd(ah); | 3472 | ath5k_hw_set_bssid(ah); |
3479 | mmiowb(); | 3473 | mmiowb(); |
3480 | } | 3474 | } |
3481 | 3475 | ||
@@ -3493,7 +3487,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw, | |||
3493 | "Bss Info ASSOC %d, bssid: %pM\n", | 3487 | "Bss Info ASSOC %d, bssid: %pM\n", |
3494 | bss_conf->aid, common->curbssid); | 3488 | bss_conf->aid, common->curbssid); |
3495 | common->curaid = bss_conf->aid; | 3489 | common->curaid = bss_conf->aid; |
3496 | ath5k_hw_set_associd(ah); | 3490 | ath5k_hw_set_bssid(ah); |
3497 | /* Once ANI is available you would start it here */ | 3491 | /* Once ANI is available you would start it here */ |
3498 | } | 3492 | } |
3499 | } | 3493 | } |
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c index 484f31870ba8..58bb6c5dda7b 100644 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ b/drivers/net/wireless/ath/ath5k/dma.c | |||
@@ -377,11 +377,11 @@ int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) | |||
377 | * | 377 | * |
378 | * This function increases/decreases the tx trigger level for the tx fifo | 378 | * This function increases/decreases the tx trigger level for the tx fifo |
379 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes | 379 | * buffer (aka FIFO threshold) that is used to indicate when PCU flushes |
380 | * the buffer and transmits it's data. Lowering this results sending small | 380 | * the buffer and transmits its data. Lowering this results sending small |
381 | * frames more quickly but can lead to tx underruns, raising it a lot can | 381 | * frames more quickly but can lead to tx underruns, raising it a lot can |
382 | * result other problems (i think bmiss is related). Right now we start with | 382 | * result other problems (i think bmiss is related). Right now we start with |
383 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using | 383 | * the lowest possible (64Bytes) and if we get tx underrun we increase it using |
384 | * the increase flag. Returns -EIO if we have have reached maximum/minimum. | 384 | * the increase flag. Returns -EIO if we have reached maximum/minimum. |
385 | * | 385 | * |
386 | * XXX: Link this with tx DMA size ? | 386 | * XXX: Link this with tx DMA size ? |
387 | * XXX: Use it to save interrupts ? | 387 | * XXX: Use it to save interrupts ? |
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index ae316fec4a6a..39722dd73e43 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c | |||
@@ -661,7 +661,7 @@ ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) | |||
661 | * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC | 661 | * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC |
662 | * steps that match with the power values we read from eeprom. On | 662 | * steps that match with the power values we read from eeprom. On |
663 | * older eeprom versions (< 3.2) these steps are equaly spaced at | 663 | * older eeprom versions (< 3.2) these steps are equaly spaced at |
664 | * 10% of the pcdac curve -until the curve reaches it's maximum- | 664 | * 10% of the pcdac curve -until the curve reaches its maximum- |
665 | * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) | 665 | * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) |
666 | * these 11 steps are spaced in a different way. This function returns | 666 | * these 11 steps are spaced in a different way. This function returns |
667 | * the pcdac steps based on eeprom version and curve min/max so that we | 667 | * the pcdac steps based on eeprom version and curve min/max so that we |
@@ -1113,7 +1113,7 @@ ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) | |||
1113 | */ | 1113 | */ |
1114 | 1114 | ||
1115 | /* For RF2413 power calibration data doesn't start on a fixed location and | 1115 | /* For RF2413 power calibration data doesn't start on a fixed location and |
1116 | * if a mode is not supported, it's section is missing -not zeroed-. | 1116 | * if a mode is not supported, its section is missing -not zeroed-. |
1117 | * So we need to calculate the starting offset for each section by using | 1117 | * So we need to calculate the starting offset for each section by using |
1118 | * these two functions */ | 1118 | * these two functions */ |
1119 | 1119 | ||
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c index 86fdb6ddfaaa..3fef5931ec3a 100644 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ b/drivers/net/wireless/ath/ath5k/pcu.c | |||
@@ -308,27 +308,26 @@ int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) | |||
308 | } | 308 | } |
309 | 309 | ||
310 | /** | 310 | /** |
311 | * ath5k_hw_set_associd - Set BSSID for association | 311 | * ath5k_hw_set_bssid - Set current BSSID on hw |
312 | * | 312 | * |
313 | * @ah: The &struct ath5k_hw | 313 | * @ah: The &struct ath5k_hw |
314 | * @bssid: BSSID | ||
315 | * @assoc_id: Assoc id | ||
316 | * | 314 | * |
317 | * Sets the BSSID which trigers the "SME Join" operation | 315 | * Sets the current BSSID and BSSID mask we have from the |
316 | * common struct into the hardware | ||
318 | */ | 317 | */ |
319 | void ath5k_hw_set_associd(struct ath5k_hw *ah) | 318 | void ath5k_hw_set_bssid(struct ath5k_hw *ah) |
320 | { | 319 | { |
321 | struct ath_common *common = ath5k_hw_common(ah); | 320 | struct ath_common *common = ath5k_hw_common(ah); |
322 | u16 tim_offset = 0; | 321 | u16 tim_offset = 0; |
323 | 322 | ||
324 | /* | 323 | /* |
325 | * Set simple BSSID mask on 5212 | 324 | * Set BSSID mask on 5212 |
326 | */ | 325 | */ |
327 | if (ah->ah_version == AR5K_AR5212) | 326 | if (ah->ah_version == AR5K_AR5212) |
328 | ath_hw_setbssidmask(common); | 327 | ath_hw_setbssidmask(common); |
329 | 328 | ||
330 | /* | 329 | /* |
331 | * Set BSSID which triggers the "SME Join" operation | 330 | * Set BSSID |
332 | */ | 331 | */ |
333 | ath5k_hw_reg_write(ah, | 332 | ath5k_hw_reg_write(ah, |
334 | get_unaligned_le32(common->curbssid), | 333 | get_unaligned_le32(common->curbssid), |
@@ -695,21 +694,18 @@ int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) | |||
695 | static | 694 | static |
696 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) | 695 | int ath5k_keycache_type(const struct ieee80211_key_conf *key) |
697 | { | 696 | { |
698 | switch (key->alg) { | 697 | switch (key->cipher) { |
699 | case ALG_TKIP: | 698 | case WLAN_CIPHER_SUITE_TKIP: |
700 | return AR5K_KEYTABLE_TYPE_TKIP; | 699 | return AR5K_KEYTABLE_TYPE_TKIP; |
701 | case ALG_CCMP: | 700 | case WLAN_CIPHER_SUITE_CCMP: |
702 | return AR5K_KEYTABLE_TYPE_CCM; | 701 | return AR5K_KEYTABLE_TYPE_CCM; |
703 | case ALG_WEP: | 702 | case WLAN_CIPHER_SUITE_WEP40: |
704 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 703 | return AR5K_KEYTABLE_TYPE_40; |
705 | return AR5K_KEYTABLE_TYPE_40; | 704 | case WLAN_CIPHER_SUITE_WEP104: |
706 | else if (key->keylen == WLAN_KEY_LEN_WEP104) | 705 | return AR5K_KEYTABLE_TYPE_104; |
707 | return AR5K_KEYTABLE_TYPE_104; | ||
708 | return -EINVAL; | ||
709 | default: | 706 | default: |
710 | return -EINVAL; | 707 | return -EINVAL; |
711 | } | 708 | } |
712 | return -EINVAL; | ||
713 | } | 709 | } |
714 | 710 | ||
715 | /* | 711 | /* |
@@ -728,7 +724,7 @@ int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, | |||
728 | bool is_tkip; | 724 | bool is_tkip; |
729 | const u8 *key_ptr; | 725 | const u8 *key_ptr; |
730 | 726 | ||
731 | is_tkip = (key->alg == ALG_TKIP); | 727 | is_tkip = (key->cipher == WLAN_CIPHER_SUITE_TKIP); |
732 | 728 | ||
733 | /* | 729 | /* |
734 | * key->keylen comes in from mac80211 in bytes. | 730 | * key->keylen comes in from mac80211 in bytes. |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 6284c389ba18..c7c446592374 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -115,7 +115,7 @@ static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, | |||
115 | \**********************/ | 115 | \**********************/ |
116 | 116 | ||
117 | /* | 117 | /* |
118 | * This code is used to optimize rf gain on different environments | 118 | * This code is used to optimize RF gain on different environments |
119 | * (temperature mostly) based on feedback from a power detector. | 119 | * (temperature mostly) based on feedback from a power detector. |
120 | * | 120 | * |
121 | * It's only used on RF5111 and RF5112, later RF chips seem to have | 121 | * It's only used on RF5111 and RF5112, later RF chips seem to have |
@@ -302,7 +302,7 @@ static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) | |||
302 | } | 302 | } |
303 | 303 | ||
304 | /* Perform gain_F adjustment by choosing the right set | 304 | /* Perform gain_F adjustment by choosing the right set |
305 | * of parameters from rf gain optimization ladder */ | 305 | * of parameters from RF gain optimization ladder */ |
306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) | 306 | static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) |
307 | { | 307 | { |
308 | const struct ath5k_gain_opt *go; | 308 | const struct ath5k_gain_opt *go; |
@@ -367,7 +367,7 @@ done: | |||
367 | return ret; | 367 | return ret; |
368 | } | 368 | } |
369 | 369 | ||
370 | /* Main callback for thermal rf gain calibration engine | 370 | /* Main callback for thermal RF gain calibration engine |
371 | * Check for a new gain reading and schedule an adjustment | 371 | * Check for a new gain reading and schedule an adjustment |
372 | * if needed. | 372 | * if needed. |
373 | * | 373 | * |
@@ -433,7 +433,7 @@ done: | |||
433 | return ah->ah_gain.g_state; | 433 | return ah->ah_gain.g_state; |
434 | } | 434 | } |
435 | 435 | ||
436 | /* Write initial rf gain table to set the RF sensitivity | 436 | /* Write initial RF gain table to set the RF sensitivity |
437 | * this one works on all RF chips and has nothing to do | 437 | * this one works on all RF chips and has nothing to do |
438 | * with gain_F calibration */ | 438 | * with gain_F calibration */ |
439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | 439 | int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) |
@@ -496,7 +496,7 @@ int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) | |||
496 | 496 | ||
497 | 497 | ||
498 | /* | 498 | /* |
499 | * Setup RF registers by writing rf buffer on hw | 499 | * Setup RF registers by writing RF buffer on hw |
500 | */ | 500 | */ |
501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | 501 | int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, |
502 | unsigned int mode) | 502 | unsigned int mode) |
@@ -571,7 +571,7 @@ int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
571 | return -EINVAL; | 571 | return -EINVAL; |
572 | } | 572 | } |
573 | 573 | ||
574 | /* If it's the first time we set rf buffer, allocate | 574 | /* If it's the first time we set RF buffer, allocate |
575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size | 575 | * ah->ah_rf_banks based on ah->ah_rf_banks_size |
576 | * we set above */ | 576 | * we set above */ |
577 | if (ah->ah_rf_banks == NULL) { | 577 | if (ah->ah_rf_banks == NULL) { |
@@ -3035,9 +3035,6 @@ ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, | |||
3035 | /* Limit max power if we have a CTL available */ | 3035 | /* Limit max power if we have a CTL available */ |
3036 | ath5k_get_max_ctl_power(ah, channel); | 3036 | ath5k_get_max_ctl_power(ah, channel); |
3037 | 3037 | ||
3038 | /* FIXME: Tx power limit for this regdomain | ||
3039 | * XXX: Mac80211/CRDA will do that anyway ? */ | ||
3040 | |||
3041 | /* FIXME: Antenna reduction stuff */ | 3038 | /* FIXME: Antenna reduction stuff */ |
3042 | 3039 | ||
3043 | /* FIXME: Limit power on turbo modes */ | 3040 | /* FIXME: Limit power on turbo modes */ |
diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 55b4ac6d236f..05ef587ad2b4 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h | |||
@@ -1911,7 +1911,7 @@ | |||
1911 | #define AR5K_PHY_TURBO 0x9804 /* Register Address */ | 1911 | #define AR5K_PHY_TURBO 0x9804 /* Register Address */ |
1912 | #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ | 1912 | #define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ |
1913 | #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ | 1913 | #define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ |
1914 | #define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ | 1914 | #define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo */ |
1915 | 1915 | ||
1916 | /* | 1916 | /* |
1917 | * PHY agility command register | 1917 | * PHY agility command register |
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index 498aa28ea9e6..4154959125b6 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c | |||
@@ -959,7 +959,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
959 | AR5K_QUEUE_DCU_SEQNUM(0)); | 959 | AR5K_QUEUE_DCU_SEQNUM(0)); |
960 | } | 960 | } |
961 | 961 | ||
962 | /* TSF accelerates on AR5211 durring reset | 962 | /* TSF accelerates on AR5211 during reset |
963 | * As a workaround save it here and restore | 963 | * As a workaround save it here and restore |
964 | * it later so that it's back in time after | 964 | * it later so that it's back in time after |
965 | * reset. This way it'll get re-synced on the | 965 | * reset. This way it'll get re-synced on the |
@@ -1080,7 +1080,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1080 | return ret; | 1080 | return ret; |
1081 | 1081 | ||
1082 | /* Spur info is available only from EEPROM versions | 1082 | /* Spur info is available only from EEPROM versions |
1083 | * bigger than 5.3 but but the EEPOM routines will use | 1083 | * greater than 5.3, but the EEPROM routines will use |
1084 | * static values for older versions */ | 1084 | * static values for older versions */ |
1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) | 1085 | if (ah->ah_mac_srev >= AR5K_SREV_AR5424) |
1086 | ath5k_hw_set_spur_mitigation_filter(ah, | 1086 | ath5k_hw_set_spur_mitigation_filter(ah, |
@@ -1160,7 +1160,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1160 | */ | 1160 | */ |
1161 | 1161 | ||
1162 | /* Restore bssid and bssid mask */ | 1162 | /* Restore bssid and bssid mask */ |
1163 | ath5k_hw_set_associd(ah); | 1163 | ath5k_hw_set_bssid(ah); |
1164 | 1164 | ||
1165 | /* Set PCU config */ | 1165 | /* Set PCU config */ |
1166 | ath5k_hw_set_opmode(ah, op_mode); | 1166 | ath5k_hw_set_opmode(ah, op_mode); |
@@ -1173,11 +1173,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1173 | /* Set RSSI/BRSSI thresholds | 1173 | /* Set RSSI/BRSSI thresholds |
1174 | * | 1174 | * |
1175 | * Note: If we decide to set this value | 1175 | * Note: If we decide to set this value |
1176 | * dynamicaly, have in mind that when AR5K_RSSI_THR | 1176 | * dynamically, keep in mind that when AR5K_RSSI_THR |
1177 | * register is read it might return 0x40 if we haven't | 1177 | * register is read, it might return 0x40 if we haven't |
1178 | * wrote anything to it plus BMISS RSSI threshold is zeroed. | 1178 | * written anything to it. Also, BMISS RSSI threshold is zeroed. |
1179 | * So doing a save/restore procedure here isn't the right | 1179 | * So doing a save/restore procedure here isn't the right |
1180 | * choice. Instead store it on ath5k_hw */ | 1180 | * choice. Instead, store it in ath5k_hw */ |
1181 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | | 1181 | ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | |
1182 | AR5K_TUNE_BMISS_THRES << | 1182 | AR5K_TUNE_BMISS_THRES << |
1183 | AR5K_RSSI_THR_BMISS_S), | 1183 | AR5K_RSSI_THR_BMISS_S), |
@@ -1235,7 +1235,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1235 | 1235 | ||
1236 | /* | 1236 | /* |
1237 | * Perform ADC test to see if baseband is ready | 1237 | * Perform ADC test to see if baseband is ready |
1238 | * Set tx hold and check adc test register | 1238 | * Set TX hold and check ADC test register |
1239 | */ | 1239 | */ |
1240 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); | 1240 | phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); |
1241 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); | 1241 | ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); |
@@ -1254,15 +1254,15 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, | |||
1254 | * | 1254 | * |
1255 | * This method is used to calibrate some static offsets | 1255 | * This method is used to calibrate some static offsets |
1256 | * used together with on-the fly I/Q calibration (the | 1256 | * used together with on-the fly I/Q calibration (the |
1257 | * one performed via ath5k_hw_phy_calibrate), that doesn't | 1257 | * one performed via ath5k_hw_phy_calibrate), which doesn't |
1258 | * interrupt rx path. | 1258 | * interrupt rx path. |
1259 | * | 1259 | * |
1260 | * While rx path is re-routed to the power detector we also | 1260 | * While rx path is re-routed to the power detector we also |
1261 | * start a noise floor calibration, to measure the | 1261 | * start a noise floor calibration to measure the |
1262 | * card's noise floor (the noise we measure when we are not | 1262 | * card's noise floor (the noise we measure when we are not |
1263 | * transmiting or receiving anything). | 1263 | * transmitting or receiving anything). |
1264 | * | 1264 | * |
1265 | * If we are in a noisy environment AGC calibration may time | 1265 | * If we are in a noisy environment, AGC calibration may time |
1266 | * out and/or noise floor calibration might timeout. | 1266 | * out and/or noise floor calibration might timeout. |
1267 | */ | 1267 | */ |
1268 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, | 1268 | AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, |
diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h index e50baff66175..3ac4cff4239d 100644 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ b/drivers/net/wireless/ath/ath5k/rfbuffer.h | |||
@@ -25,10 +25,10 @@ | |||
25 | * | 25 | * |
26 | * We don't write on those registers directly but | 26 | * We don't write on those registers directly but |
27 | * we send a data packet on the chip, using a special register, | 27 | * we send a data packet on the chip, using a special register, |
28 | * that holds all the settings we need. After we 've sent the | 28 | * that holds all the settings we need. After we've sent the |
29 | * data packet, we write on another special register to notify hw | 29 | * data packet, we write on another special register to notify hw |
30 | * to apply the settings. This is done so that control registers | 30 | * to apply the settings. This is done so that control registers |
31 | * can be dynamicaly programmed during operation and the settings | 31 | * can be dynamically programmed during operation and the settings |
32 | * are applied faster on the hw. | 32 | * are applied faster on the hw. |
33 | * | 33 | * |
34 | * We call each data packet an "RF Bank" and all the data we write | 34 | * We call each data packet an "RF Bank" and all the data we write |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 973ae4f49f35..4555e9983903 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -46,6 +46,7 @@ ath9k_htc-y += htc_hst.o \ | |||
46 | htc_drv_txrx.o \ | 46 | htc_drv_txrx.o \ |
47 | htc_drv_main.o \ | 47 | htc_drv_main.o \ |
48 | htc_drv_beacon.o \ | 48 | htc_drv_beacon.o \ |
49 | htc_drv_init.o | 49 | htc_drv_init.o \ |
50 | htc_drv_gpio.o | ||
50 | 51 | ||
51 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o | 52 | obj-$(CONFIG_ATH9K_HTC) += ath9k_htc.o |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 5b995bee70ae..a462da23e87e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -185,7 +185,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) | |||
185 | ath_print(common, ATH_DBG_INTERRUPT, | 185 | ath_print(common, ATH_DBG_INTERRUPT, |
186 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); | 186 | "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); |
187 | 187 | ||
188 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); | 188 | REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); |
189 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); | 189 | (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); |
190 | 190 | ||
191 | } | 191 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 07f26ee7a723..f0197a6046ab 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -423,6 +423,7 @@ int ath_beaconq_config(struct ath_softc *sc); | |||
423 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ | 423 | #define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ |
424 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ | 424 | #define ATH_ANI_POLLINTERVAL_OLD 100 /* 100 ms */ |
425 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ | 425 | #define ATH_ANI_POLLINTERVAL_NEW 1000 /* 1000 ms */ |
426 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ | ||
426 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 427 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
427 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 428 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
428 | 429 | ||
@@ -436,14 +437,6 @@ void ath_ani_calibrate(unsigned long data); | |||
436 | /* BTCOEX */ | 437 | /* BTCOEX */ |
437 | /**********/ | 438 | /**********/ |
438 | 439 | ||
439 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
440 | enum ath_stomp_type { | ||
441 | ATH_BTCOEX_NO_STOMP, | ||
442 | ATH_BTCOEX_STOMP_ALL, | ||
443 | ATH_BTCOEX_STOMP_LOW, | ||
444 | ATH_BTCOEX_STOMP_NONE | ||
445 | }; | ||
446 | |||
447 | struct ath_btcoex { | 440 | struct ath_btcoex { |
448 | bool hw_timer_enabled; | 441 | bool hw_timer_enabled; |
449 | spinlock_t btcoex_lock; | 442 | spinlock_t btcoex_lock; |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 4d4b22d52dfd..081192e78a46 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -359,11 +359,12 @@ void ath_beacon_tasklet(unsigned long data) | |||
359 | sc->beacon.bmisscnt++; | 359 | sc->beacon.bmisscnt++; |
360 | 360 | ||
361 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { | 361 | if (sc->beacon.bmisscnt < BSTUCK_THRESH) { |
362 | ath_print(common, ATH_DBG_BEACON, | 362 | ath_print(common, ATH_DBG_BSTUCK, |
363 | "missed %u consecutive beacons\n", | 363 | "missed %u consecutive beacons\n", |
364 | sc->beacon.bmisscnt); | 364 | sc->beacon.bmisscnt); |
365 | ath9k_hw_bstuck_nfcal(ah); | ||
365 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { | 366 | } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { |
366 | ath_print(common, ATH_DBG_BEACON, | 367 | ath_print(common, ATH_DBG_BSTUCK, |
367 | "beacon is officially stuck\n"); | 368 | "beacon is officially stuck\n"); |
368 | sc->sc_flags |= SC_OP_TSF_RESET; | 369 | sc->sc_flags |= SC_OP_TSF_RESET; |
369 | ath_reset(sc, false); | 370 | ath_reset(sc, false); |
@@ -373,7 +374,7 @@ void ath_beacon_tasklet(unsigned long data) | |||
373 | } | 374 | } |
374 | 375 | ||
375 | if (sc->beacon.bmisscnt != 0) { | 376 | if (sc->beacon.bmisscnt != 0) { |
376 | ath_print(common, ATH_DBG_BEACON, | 377 | ath_print(common, ATH_DBG_BSTUCK, |
377 | "resume beacon xmit after %u misses\n", | 378 | "resume beacon xmit after %u misses\n", |
378 | sc->beacon.bmisscnt); | 379 | sc->beacon.bmisscnt); |
379 | sc->beacon.bmisscnt = 0; | 380 | sc->beacon.bmisscnt = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index fb4ac15f3b93..6a92e57fddf0 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -168,6 +168,7 @@ EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); | |||
168 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) | 168 | static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) |
169 | { | 169 | { |
170 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 170 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
171 | u32 val; | ||
171 | 172 | ||
172 | /* | 173 | /* |
173 | * Program coex mode and weight registers to | 174 | * Program coex mode and weight registers to |
@@ -177,6 +178,12 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) | |||
177 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); | 178 | REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_hw->bt_coex_weights); |
178 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); | 179 | REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_hw->bt_coex_mode2); |
179 | 180 | ||
181 | if (AR_SREV_9271(ah)) { | ||
182 | val = REG_READ(ah, 0x50040); | ||
183 | val &= 0xFFFFFEFF; | ||
184 | REG_WRITE(ah, 0x50040, val); | ||
185 | } | ||
186 | |||
180 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); | 187 | REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); |
181 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); | 188 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); |
182 | 189 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 45208690c0ec..67ee5d735cc1 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -19,8 +19,7 @@ | |||
19 | 19 | ||
20 | /* Common calibration code */ | 20 | /* Common calibration code */ |
21 | 21 | ||
22 | /* We can tune this as we go by monitoring really low values */ | 22 | #define ATH9K_NF_TOO_HIGH -60 |
23 | #define ATH9K_NF_TOO_LOW -60 | ||
24 | 23 | ||
25 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | 24 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) |
26 | { | 25 | { |
@@ -45,11 +44,39 @@ static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) | |||
45 | return nfval; | 44 | return nfval; |
46 | } | 45 | } |
47 | 46 | ||
48 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | 47 | static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, |
48 | struct ath9k_channel *chan) | ||
49 | { | ||
50 | struct ath_nf_limits *limit; | ||
51 | |||
52 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
53 | limit = &ah->nf_2g; | ||
54 | else | ||
55 | limit = &ah->nf_5g; | ||
56 | |||
57 | return limit; | ||
58 | } | ||
59 | |||
60 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
61 | struct ath9k_channel *chan) | ||
62 | { | ||
63 | return ath9k_hw_get_nf_limits(ah, chan)->nominal; | ||
64 | } | ||
65 | |||
66 | |||
67 | static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | ||
68 | struct ath9k_hw_cal_data *cal, | ||
49 | int16_t *nfarray) | 69 | int16_t *nfarray) |
50 | { | 70 | { |
71 | struct ath_common *common = ath9k_hw_common(ah); | ||
72 | struct ath_nf_limits *limit; | ||
73 | struct ath9k_nfcal_hist *h; | ||
74 | bool high_nf_mid = false; | ||
51 | int i; | 75 | int i; |
52 | 76 | ||
77 | h = cal->nfCalHist; | ||
78 | limit = ath9k_hw_get_nf_limits(ah, ah->curchan); | ||
79 | |||
53 | for (i = 0; i < NUM_NF_READINGS; i++) { | 80 | for (i = 0; i < NUM_NF_READINGS; i++) { |
54 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; | 81 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; |
55 | 82 | ||
@@ -63,7 +90,39 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, | |||
63 | h[i].privNF = | 90 | h[i].privNF = |
64 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); | 91 | ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); |
65 | } | 92 | } |
93 | |||
94 | if (!h[i].privNF) | ||
95 | continue; | ||
96 | |||
97 | if (h[i].privNF > limit->max) { | ||
98 | high_nf_mid = true; | ||
99 | |||
100 | ath_print(common, ATH_DBG_CALIBRATE, | ||
101 | "NFmid[%d] (%d) > MAX (%d), %s\n", | ||
102 | i, h[i].privNF, limit->max, | ||
103 | (cal->nfcal_interference ? | ||
104 | "not corrected (due to interference)" : | ||
105 | "correcting to MAX")); | ||
106 | |||
107 | /* | ||
108 | * Normally we limit the average noise floor by the | ||
109 | * hardware specific maximum here. However if we have | ||
110 | * encountered stuck beacons because of interference, | ||
111 | * we bypass this limit here in order to better deal | ||
112 | * with our environment. | ||
113 | */ | ||
114 | if (!cal->nfcal_interference) | ||
115 | h[i].privNF = limit->max; | ||
116 | } | ||
66 | } | 117 | } |
118 | |||
119 | /* | ||
120 | * If the noise floor seems normal for all chains, assume that | ||
121 | * there is no significant interference in the environment anymore. | ||
122 | * Re-enable the enforcement of the NF maximum again. | ||
123 | */ | ||
124 | if (!high_nf_mid) | ||
125 | cal->nfcal_interference = false; | ||
67 | } | 126 | } |
68 | 127 | ||
69 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, | 128 | static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah, |
@@ -104,19 +163,6 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah, | |||
104 | ah->cal_samples = 0; | 163 | ah->cal_samples = 0; |
105 | } | 164 | } |
106 | 165 | ||
107 | static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, | ||
108 | struct ath9k_channel *chan) | ||
109 | { | ||
110 | struct ath_nf_limits *limit; | ||
111 | |||
112 | if (!chan || IS_CHAN_2GHZ(chan)) | ||
113 | limit = &ah->nf_2g; | ||
114 | else | ||
115 | limit = &ah->nf_5g; | ||
116 | |||
117 | return limit->nominal; | ||
118 | } | ||
119 | |||
120 | /* This is done for the currently configured channel */ | 166 | /* This is done for the currently configured channel */ |
121 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) | 167 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
122 | { | 168 | { |
@@ -277,10 +323,10 @@ static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf) | |||
277 | "NF calibrated [%s] [chain %d] is %d\n", | 323 | "NF calibrated [%s] [chain %d] is %d\n", |
278 | (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); | 324 | (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]); |
279 | 325 | ||
280 | if (nf[i] > limit->max) { | 326 | if (nf[i] > ATH9K_NF_TOO_HIGH) { |
281 | ath_print(common, ATH_DBG_CALIBRATE, | 327 | ath_print(common, ATH_DBG_CALIBRATE, |
282 | "NF[%d] (%d) > MAX (%d), correcting to MAX", | 328 | "NF[%d] (%d) > MAX (%d), correcting to MAX", |
283 | i, nf[i], limit->max); | 329 | i, nf[i], ATH9K_NF_TOO_HIGH); |
284 | nf[i] = limit->max; | 330 | nf[i] = limit->max; |
285 | } else if (nf[i] < limit->min) { | 331 | } else if (nf[i] < limit->min) { |
286 | ath_print(common, ATH_DBG_CALIBRATE, | 332 | ath_print(common, ATH_DBG_CALIBRATE, |
@@ -326,7 +372,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
326 | 372 | ||
327 | h = caldata->nfCalHist; | 373 | h = caldata->nfCalHist; |
328 | caldata->nfcal_pending = false; | 374 | caldata->nfcal_pending = false; |
329 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); | 375 | ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); |
330 | caldata->rawNoiseFloor = h[0].privNF; | 376 | caldata->rawNoiseFloor = h[0].privNF; |
331 | return true; | 377 | return true; |
332 | } | 378 | } |
@@ -361,3 +407,28 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | |||
361 | return ah->caldata->rawNoiseFloor; | 407 | return ah->caldata->rawNoiseFloor; |
362 | } | 408 | } |
363 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | 409 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
410 | |||
411 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) | ||
412 | { | ||
413 | struct ath9k_hw_cal_data *caldata = ah->caldata; | ||
414 | |||
415 | if (unlikely(!caldata)) | ||
416 | return; | ||
417 | |||
418 | /* | ||
419 | * If beacons are stuck, the most likely cause is interference. | ||
420 | * Triggering a noise floor calibration at this point helps the | ||
421 | * hardware adapt to a noisy environment much faster. | ||
422 | * To ensure that we recover from stuck beacons quickly, let | ||
423 | * the baseband update the internal NF value itself, similar to | ||
424 | * what is being done after a full reset. | ||
425 | */ | ||
426 | if (!caldata->nfcal_pending) | ||
427 | ath9k_hw_start_nfcal(ah, true); | ||
428 | else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF)) | ||
429 | ath9k_hw_getnf(ah, ah->curchan); | ||
430 | |||
431 | caldata->nfcal_interference = true; | ||
432 | } | ||
433 | EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal); | ||
434 | |||
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 0a304b3eeeb6..5b053a6260b2 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -113,6 +113,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); | |||
113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); | 113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | 114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
115 | struct ath9k_channel *chan); | 115 | struct ath9k_channel *chan); |
116 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); | ||
116 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | 117 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); |
117 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 118 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
118 | struct ath9k_cal_list *currCal); | 119 | struct ath9k_cal_list *currCal); |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index c86f7d3593ab..31cfe468e3fc 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -46,12 +46,17 @@ int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) | |||
46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 46 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
47 | 47 | ||
48 | if (tx_info->control.hw_key) { | 48 | if (tx_info->control.hw_key) { |
49 | if (tx_info->control.hw_key->alg == ALG_WEP) | 49 | switch (tx_info->control.hw_key->cipher) { |
50 | case WLAN_CIPHER_SUITE_WEP40: | ||
51 | case WLAN_CIPHER_SUITE_WEP104: | ||
50 | return ATH9K_KEY_TYPE_WEP; | 52 | return ATH9K_KEY_TYPE_WEP; |
51 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | 53 | case WLAN_CIPHER_SUITE_TKIP: |
52 | return ATH9K_KEY_TYPE_TKIP; | 54 | return ATH9K_KEY_TYPE_TKIP; |
53 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | 55 | case WLAN_CIPHER_SUITE_CCMP: |
54 | return ATH9K_KEY_TYPE_AES; | 56 | return ATH9K_KEY_TYPE_AES; |
57 | default: | ||
58 | break; | ||
59 | } | ||
55 | } | 60 | } |
56 | 61 | ||
57 | return ATH9K_KEY_TYPE_CLEAR; | 62 | return ATH9K_KEY_TYPE_CLEAR; |
@@ -212,11 +217,11 @@ static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) | |||
212 | } | 217 | } |
213 | 218 | ||
214 | static int ath_reserve_key_cache_slot(struct ath_common *common, | 219 | static int ath_reserve_key_cache_slot(struct ath_common *common, |
215 | enum ieee80211_key_alg alg) | 220 | u32 cipher) |
216 | { | 221 | { |
217 | int i; | 222 | int i; |
218 | 223 | ||
219 | if (alg == ALG_TKIP) | 224 | if (cipher == WLAN_CIPHER_SUITE_TKIP) |
220 | return ath_reserve_key_cache_slot_tkip(common); | 225 | return ath_reserve_key_cache_slot_tkip(common); |
221 | 226 | ||
222 | /* First, try to find slots that would not be available for TKIP. */ | 227 | /* First, try to find slots that would not be available for TKIP. */ |
@@ -293,14 +298,15 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
293 | 298 | ||
294 | memset(&hk, 0, sizeof(hk)); | 299 | memset(&hk, 0, sizeof(hk)); |
295 | 300 | ||
296 | switch (key->alg) { | 301 | switch (key->cipher) { |
297 | case ALG_WEP: | 302 | case WLAN_CIPHER_SUITE_WEP40: |
303 | case WLAN_CIPHER_SUITE_WEP104: | ||
298 | hk.kv_type = ATH9K_CIPHER_WEP; | 304 | hk.kv_type = ATH9K_CIPHER_WEP; |
299 | break; | 305 | break; |
300 | case ALG_TKIP: | 306 | case WLAN_CIPHER_SUITE_TKIP: |
301 | hk.kv_type = ATH9K_CIPHER_TKIP; | 307 | hk.kv_type = ATH9K_CIPHER_TKIP; |
302 | break; | 308 | break; |
303 | case ALG_CCMP: | 309 | case WLAN_CIPHER_SUITE_CCMP: |
304 | hk.kv_type = ATH9K_CIPHER_AES_CCM; | 310 | hk.kv_type = ATH9K_CIPHER_AES_CCM; |
305 | break; | 311 | break; |
306 | default: | 312 | default: |
@@ -316,7 +322,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
316 | memcpy(gmac, vif->addr, ETH_ALEN); | 322 | memcpy(gmac, vif->addr, ETH_ALEN); |
317 | gmac[0] |= 0x01; | 323 | gmac[0] |= 0x01; |
318 | mac = gmac; | 324 | mac = gmac; |
319 | idx = ath_reserve_key_cache_slot(common, key->alg); | 325 | idx = ath_reserve_key_cache_slot(common, key->cipher); |
320 | break; | 326 | break; |
321 | case NL80211_IFTYPE_ADHOC: | 327 | case NL80211_IFTYPE_ADHOC: |
322 | if (!sta) { | 328 | if (!sta) { |
@@ -326,7 +332,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
326 | memcpy(gmac, sta->addr, ETH_ALEN); | 332 | memcpy(gmac, sta->addr, ETH_ALEN); |
327 | gmac[0] |= 0x01; | 333 | gmac[0] |= 0x01; |
328 | mac = gmac; | 334 | mac = gmac; |
329 | idx = ath_reserve_key_cache_slot(common, key->alg); | 335 | idx = ath_reserve_key_cache_slot(common, key->cipher); |
330 | break; | 336 | break; |
331 | default: | 337 | default: |
332 | idx = key->keyidx; | 338 | idx = key->keyidx; |
@@ -348,13 +354,13 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
348 | return -EOPNOTSUPP; | 354 | return -EOPNOTSUPP; |
349 | mac = sta->addr; | 355 | mac = sta->addr; |
350 | 356 | ||
351 | idx = ath_reserve_key_cache_slot(common, key->alg); | 357 | idx = ath_reserve_key_cache_slot(common, key->cipher); |
352 | } | 358 | } |
353 | 359 | ||
354 | if (idx < 0) | 360 | if (idx < 0) |
355 | return -ENOSPC; /* no free key cache entries */ | 361 | return -ENOSPC; /* no free key cache entries */ |
356 | 362 | ||
357 | if (key->alg == ALG_TKIP) | 363 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
358 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, | 364 | ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, |
359 | vif->type == NL80211_IFTYPE_AP); | 365 | vif->type == NL80211_IFTYPE_AP); |
360 | else | 366 | else |
@@ -364,7 +370,7 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
364 | return -EIO; | 370 | return -EIO; |
365 | 371 | ||
366 | set_bit(idx, common->keymap); | 372 | set_bit(idx, common->keymap); |
367 | if (key->alg == ALG_TKIP) { | 373 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
368 | set_bit(idx + 64, common->keymap); | 374 | set_bit(idx + 64, common->keymap); |
369 | if (common->splitmic) { | 375 | if (common->splitmic) { |
370 | set_bit(idx + 32, common->keymap); | 376 | set_bit(idx + 32, common->keymap); |
@@ -389,7 +395,7 @@ void ath9k_cmn_key_delete(struct ath_common *common, | |||
389 | return; | 395 | return; |
390 | 396 | ||
391 | clear_bit(key->hw_key_idx, common->keymap); | 397 | clear_bit(key->hw_key_idx, common->keymap); |
392 | if (key->alg != ALG_TKIP) | 398 | if (key->cipher != WLAN_CIPHER_SUITE_TKIP) |
393 | return; | 399 | return; |
394 | 400 | ||
395 | clear_bit(key->hw_key_idx + 64, common->keymap); | 401 | clear_bit(key->hw_key_idx + 64, common->keymap); |
@@ -414,6 +420,37 @@ int ath9k_cmn_count_streams(unsigned int chainmask, int max) | |||
414 | } | 420 | } |
415 | EXPORT_SYMBOL(ath9k_cmn_count_streams); | 421 | EXPORT_SYMBOL(ath9k_cmn_count_streams); |
416 | 422 | ||
423 | /* | ||
424 | * Configures appropriate weight based on stomp type. | ||
425 | */ | ||
426 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | ||
427 | enum ath_stomp_type stomp_type) | ||
428 | { | ||
429 | struct ath_hw *ah = common->ah; | ||
430 | |||
431 | switch (stomp_type) { | ||
432 | case ATH_BTCOEX_STOMP_ALL: | ||
433 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
434 | AR_STOMP_ALL_WLAN_WGHT); | ||
435 | break; | ||
436 | case ATH_BTCOEX_STOMP_LOW: | ||
437 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
438 | AR_STOMP_LOW_WLAN_WGHT); | ||
439 | break; | ||
440 | case ATH_BTCOEX_STOMP_NONE: | ||
441 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
442 | AR_STOMP_NONE_WLAN_WGHT); | ||
443 | break; | ||
444 | default: | ||
445 | ath_print(common, ATH_DBG_BTCOEX, | ||
446 | "Invalid Stomptype\n"); | ||
447 | break; | ||
448 | } | ||
449 | |||
450 | ath9k_hw_btcoex_enable(ah); | ||
451 | } | ||
452 | EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp); | ||
453 | |||
417 | static int __init ath9k_cmn_init(void) | 454 | static int __init ath9k_cmn_init(void) |
418 | { | 455 | { |
419 | return 0; | 456 | return 0; |
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 97809d39c73f..4aa4e7dbe4d2 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -52,6 +52,14 @@ | |||
52 | #define ATH_EP_RND(x, mul) \ | 52 | #define ATH_EP_RND(x, mul) \ |
53 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | 53 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) |
54 | 54 | ||
55 | /* Defines the BT AR_BT_COEX_WGHT used */ | ||
56 | enum ath_stomp_type { | ||
57 | ATH_BTCOEX_NO_STOMP, | ||
58 | ATH_BTCOEX_STOMP_ALL, | ||
59 | ATH_BTCOEX_STOMP_LOW, | ||
60 | ATH_BTCOEX_STOMP_NONE | ||
61 | }; | ||
62 | |||
55 | int ath9k_cmn_padpos(__le16 frame_control); | 63 | int ath9k_cmn_padpos(__le16 frame_control); |
56 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); | 64 | int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb); |
57 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, | 65 | void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, |
@@ -65,3 +73,5 @@ int ath9k_cmn_key_config(struct ath_common *common, | |||
65 | void ath9k_cmn_key_delete(struct ath_common *common, | 73 | void ath9k_cmn_key_delete(struct ath_common *common, |
66 | struct ieee80211_key_conf *key); | 74 | struct ieee80211_key_conf *key); |
67 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); | 75 | int ath9k_cmn_count_streams(unsigned int chainmask, int max); |
76 | void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common, | ||
77 | enum ath_stomp_type stomp_type); | ||
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 3a8ee999da5d..4a9a68bba324 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -251,36 +251,6 @@ static void ath_detect_bt_priority(struct ath_softc *sc) | |||
251 | } | 251 | } |
252 | } | 252 | } |
253 | 253 | ||
254 | /* | ||
255 | * Configures appropriate weight based on stomp type. | ||
256 | */ | ||
257 | static void ath9k_btcoex_bt_stomp(struct ath_softc *sc, | ||
258 | enum ath_stomp_type stomp_type) | ||
259 | { | ||
260 | struct ath_hw *ah = sc->sc_ah; | ||
261 | |||
262 | switch (stomp_type) { | ||
263 | case ATH_BTCOEX_STOMP_ALL: | ||
264 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
265 | AR_STOMP_ALL_WLAN_WGHT); | ||
266 | break; | ||
267 | case ATH_BTCOEX_STOMP_LOW: | ||
268 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
269 | AR_STOMP_LOW_WLAN_WGHT); | ||
270 | break; | ||
271 | case ATH_BTCOEX_STOMP_NONE: | ||
272 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
273 | AR_STOMP_NONE_WLAN_WGHT); | ||
274 | break; | ||
275 | default: | ||
276 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
277 | "Invalid Stomptype\n"); | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | ath9k_hw_btcoex_enable(ah); | ||
282 | } | ||
283 | |||
284 | static void ath9k_gen_timer_start(struct ath_hw *ah, | 254 | static void ath9k_gen_timer_start(struct ath_hw *ah, |
285 | struct ath_gen_timer *timer, | 255 | struct ath_gen_timer *timer, |
286 | u32 timer_next, | 256 | u32 timer_next, |
@@ -319,6 +289,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
319 | struct ath_softc *sc = (struct ath_softc *) data; | 289 | struct ath_softc *sc = (struct ath_softc *) data; |
320 | struct ath_hw *ah = sc->sc_ah; | 290 | struct ath_hw *ah = sc->sc_ah; |
321 | struct ath_btcoex *btcoex = &sc->btcoex; | 291 | struct ath_btcoex *btcoex = &sc->btcoex; |
292 | struct ath_common *common = ath9k_hw_common(ah); | ||
322 | u32 timer_period; | 293 | u32 timer_period; |
323 | bool is_btscan; | 294 | bool is_btscan; |
324 | 295 | ||
@@ -328,7 +299,7 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
328 | 299 | ||
329 | spin_lock_bh(&btcoex->btcoex_lock); | 300 | spin_lock_bh(&btcoex->btcoex_lock); |
330 | 301 | ||
331 | ath9k_btcoex_bt_stomp(sc, is_btscan ? ATH_BTCOEX_STOMP_ALL : | 302 | ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : |
332 | btcoex->bt_stomp_type); | 303 | btcoex->bt_stomp_type); |
333 | 304 | ||
334 | spin_unlock_bh(&btcoex->btcoex_lock); | 305 | spin_unlock_bh(&btcoex->btcoex_lock); |
@@ -359,17 +330,18 @@ static void ath_btcoex_no_stomp_timer(void *arg) | |||
359 | struct ath_softc *sc = (struct ath_softc *)arg; | 330 | struct ath_softc *sc = (struct ath_softc *)arg; |
360 | struct ath_hw *ah = sc->sc_ah; | 331 | struct ath_hw *ah = sc->sc_ah; |
361 | struct ath_btcoex *btcoex = &sc->btcoex; | 332 | struct ath_btcoex *btcoex = &sc->btcoex; |
333 | struct ath_common *common = ath9k_hw_common(ah); | ||
362 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; | 334 | bool is_btscan = sc->sc_flags & SC_OP_BT_SCAN; |
363 | 335 | ||
364 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | 336 | ath_print(common, ATH_DBG_BTCOEX, |
365 | "no stomp timer running\n"); | 337 | "no stomp timer running\n"); |
366 | 338 | ||
367 | spin_lock_bh(&btcoex->btcoex_lock); | 339 | spin_lock_bh(&btcoex->btcoex_lock); |
368 | 340 | ||
369 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | 341 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) |
370 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE); | 342 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); |
371 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | 343 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
372 | ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW); | 344 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); |
373 | 345 | ||
374 | spin_unlock_bh(&btcoex->btcoex_lock); | 346 | spin_unlock_bh(&btcoex->btcoex_lock); |
375 | } | 347 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 17e7a9a367e7..495f18950ac9 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -920,7 +920,8 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface, | |||
920 | } | 920 | } |
921 | 921 | ||
922 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, | 922 | ret = ath9k_htc_hw_init(hif_dev->htc_handle, |
923 | &hif_dev->udev->dev, hif_dev->device_id); | 923 | &hif_dev->udev->dev, hif_dev->device_id, |
924 | hif_dev->udev->product); | ||
924 | if (ret) { | 925 | if (ret) { |
925 | ret = -EINVAL; | 926 | ret = -EINVAL; |
926 | goto err_htc_hw_init; | 927 | goto err_htc_hw_init; |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 43b9e21bc562..75ecf6a30d25 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -316,17 +316,32 @@ struct htc_beacon_config { | |||
316 | u8 dtim_count; | 316 | u8 dtim_count; |
317 | }; | 317 | }; |
318 | 318 | ||
319 | #define OP_INVALID BIT(0) | 319 | struct ath_btcoex { |
320 | #define OP_SCANNING BIT(1) | 320 | u32 bt_priority_cnt; |
321 | #define OP_FULL_RESET BIT(2) | 321 | unsigned long bt_priority_time; |
322 | #define OP_LED_ASSOCIATED BIT(3) | 322 | int bt_stomp_type; /* Types of BT stomping */ |
323 | #define OP_LED_ON BIT(4) | 323 | u32 btcoex_no_stomp; |
324 | #define OP_PREAMBLE_SHORT BIT(5) | 324 | u32 btcoex_period; |
325 | #define OP_PROTECT_ENABLE BIT(6) | 325 | u32 btscan_no_stomp; |
326 | #define OP_ASSOCIATED BIT(7) | 326 | }; |
327 | #define OP_ENABLE_BEACON BIT(8) | 327 | |
328 | #define OP_LED_DEINIT BIT(9) | 328 | void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv); |
329 | #define OP_UNPLUGGED BIT(10) | 329 | void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv); |
330 | void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv); | ||
331 | |||
332 | #define OP_INVALID BIT(0) | ||
333 | #define OP_SCANNING BIT(1) | ||
334 | #define OP_FULL_RESET BIT(2) | ||
335 | #define OP_LED_ASSOCIATED BIT(3) | ||
336 | #define OP_LED_ON BIT(4) | ||
337 | #define OP_PREAMBLE_SHORT BIT(5) | ||
338 | #define OP_PROTECT_ENABLE BIT(6) | ||
339 | #define OP_ASSOCIATED BIT(7) | ||
340 | #define OP_ENABLE_BEACON BIT(8) | ||
341 | #define OP_LED_DEINIT BIT(9) | ||
342 | #define OP_UNPLUGGED BIT(10) | ||
343 | #define OP_BT_PRIORITY_DETECTED BIT(11) | ||
344 | #define OP_BT_SCAN BIT(12) | ||
330 | 345 | ||
331 | struct ath9k_htc_priv { | 346 | struct ath9k_htc_priv { |
332 | struct device *dev; | 347 | struct device *dev; |
@@ -391,6 +406,9 @@ struct ath9k_htc_priv { | |||
391 | int cabq; | 406 | int cabq; |
392 | int hwq_map[WME_NUM_AC]; | 407 | int hwq_map[WME_NUM_AC]; |
393 | 408 | ||
409 | struct ath_btcoex btcoex; | ||
410 | struct delayed_work coex_period_work; | ||
411 | struct delayed_work duty_cycle_work; | ||
394 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 412 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
395 | struct ath9k_debug debug; | 413 | struct ath9k_debug debug; |
396 | #endif | 414 | #endif |
@@ -443,7 +461,7 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv); | |||
443 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); | 461 | void ath9k_deinit_leds(struct ath9k_htc_priv *priv); |
444 | 462 | ||
445 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 463 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
446 | u16 devid); | 464 | u16 devid, char *product); |
447 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); | 465 | void ath9k_htc_disconnect_device(struct htc_target *htc_handle, bool hotunplug); |
448 | #ifdef CONFIG_PM | 466 | #ifdef CONFIG_PM |
449 | int ath9k_htc_resume(struct htc_target *htc_handle); | 467 | int ath9k_htc_resume(struct htc_target *htc_handle); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c new file mode 100644 index 000000000000..50eec9a3b88c --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | |||
@@ -0,0 +1,134 @@ | |||
1 | #include "htc.h" | ||
2 | |||
3 | /******************/ | ||
4 | /* BTCOEX */ | ||
5 | /******************/ | ||
6 | |||
7 | /* | ||
8 | * Detects if there is any priority bt traffic | ||
9 | */ | ||
10 | static void ath_detect_bt_priority(struct ath9k_htc_priv *priv) | ||
11 | { | ||
12 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
13 | struct ath_hw *ah = priv->ah; | ||
14 | |||
15 | if (ath9k_hw_gpio_get(ah, ah->btcoex_hw.btpriority_gpio)) | ||
16 | btcoex->bt_priority_cnt++; | ||
17 | |||
18 | if (time_after(jiffies, btcoex->bt_priority_time + | ||
19 | msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { | ||
20 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | ||
21 | /* Detect if colocated bt started scanning */ | ||
22 | if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) { | ||
23 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
24 | "BT scan detected"); | ||
25 | priv->op_flags |= (OP_BT_SCAN | | ||
26 | OP_BT_PRIORITY_DETECTED); | ||
27 | } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { | ||
28 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
29 | "BT priority traffic detected"); | ||
30 | priv->op_flags |= OP_BT_PRIORITY_DETECTED; | ||
31 | } | ||
32 | |||
33 | btcoex->bt_priority_cnt = 0; | ||
34 | btcoex->bt_priority_time = jiffies; | ||
35 | } | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * This is the master bt coex work which runs for every | ||
40 | * 45ms, bt traffic will be given priority during 55% of this | ||
41 | * period while wlan gets remaining 45% | ||
42 | */ | ||
43 | static void ath_btcoex_period_work(struct work_struct *work) | ||
44 | { | ||
45 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
46 | coex_period_work.work); | ||
47 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
48 | struct ath_common *common = ath9k_hw_common(priv->ah); | ||
49 | u32 timer_period; | ||
50 | bool is_btscan; | ||
51 | int ret; | ||
52 | u8 cmd_rsp, aggr; | ||
53 | |||
54 | ath_detect_bt_priority(priv); | ||
55 | |||
56 | is_btscan = !!(priv->op_flags & OP_BT_SCAN); | ||
57 | |||
58 | aggr = priv->op_flags & OP_BT_PRIORITY_DETECTED; | ||
59 | |||
60 | WMI_CMD_BUF(WMI_AGGR_LIMIT_CMD, &aggr); | ||
61 | |||
62 | ath9k_cmn_btcoex_bt_stomp(common, is_btscan ? ATH_BTCOEX_STOMP_ALL : | ||
63 | btcoex->bt_stomp_type); | ||
64 | |||
65 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | ||
66 | btcoex->btcoex_no_stomp; | ||
67 | ieee80211_queue_delayed_work(priv->hw, &priv->duty_cycle_work, | ||
68 | msecs_to_jiffies(timer_period)); | ||
69 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, | ||
70 | msecs_to_jiffies(btcoex->btcoex_period)); | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | * Work to time slice between wlan and bt traffic and | ||
75 | * configure weight registers | ||
76 | */ | ||
77 | static void ath_btcoex_duty_cycle_work(struct work_struct *work) | ||
78 | { | ||
79 | struct ath9k_htc_priv *priv = container_of(work, struct ath9k_htc_priv, | ||
80 | duty_cycle_work.work); | ||
81 | struct ath_hw *ah = priv->ah; | ||
82 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
83 | struct ath_common *common = ath9k_hw_common(ah); | ||
84 | bool is_btscan = priv->op_flags & OP_BT_SCAN; | ||
85 | |||
86 | ath_print(common, ATH_DBG_BTCOEX, | ||
87 | "time slice work for bt and wlan\n"); | ||
88 | |||
89 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || is_btscan) | ||
90 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_NONE); | ||
91 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | ||
92 | ath9k_cmn_btcoex_bt_stomp(common, ATH_BTCOEX_STOMP_LOW); | ||
93 | } | ||
94 | |||
95 | void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv) | ||
96 | { | ||
97 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
98 | |||
99 | btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD; | ||
100 | btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * | ||
101 | btcoex->btcoex_period / 100; | ||
102 | btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) * | ||
103 | btcoex->btcoex_period / 100; | ||
104 | INIT_DELAYED_WORK(&priv->coex_period_work, ath_btcoex_period_work); | ||
105 | INIT_DELAYED_WORK(&priv->duty_cycle_work, ath_btcoex_duty_cycle_work); | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | * (Re)start btcoex work | ||
110 | */ | ||
111 | |||
112 | void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv) | ||
113 | { | ||
114 | struct ath_btcoex *btcoex = &priv->btcoex; | ||
115 | struct ath_hw *ah = priv->ah; | ||
116 | |||
117 | ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX, | ||
118 | "Starting btcoex work"); | ||
119 | |||
120 | btcoex->bt_priority_cnt = 0; | ||
121 | btcoex->bt_priority_time = jiffies; | ||
122 | priv->op_flags &= ~(OP_BT_PRIORITY_DETECTED | OP_BT_SCAN); | ||
123 | ieee80211_queue_delayed_work(priv->hw, &priv->coex_period_work, 0); | ||
124 | } | ||
125 | |||
126 | |||
127 | /* | ||
128 | * Cancel btcoex and bt duty cycle work. | ||
129 | */ | ||
130 | void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv) | ||
131 | { | ||
132 | cancel_delayed_work_sync(&priv->coex_period_work); | ||
133 | cancel_delayed_work_sync(&priv->duty_cycle_work); | ||
134 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index 2d4279191d7a..695e2b088d10 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -41,6 +41,8 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); | |||
41 | .max_power = 20, \ | 41 | .max_power = 20, \ |
42 | } | 42 | } |
43 | 43 | ||
44 | #define ATH_HTC_BTCOEX_PRODUCT_ID "wb193" | ||
45 | |||
44 | static struct ieee80211_channel ath9k_2ghz_channels[] = { | 46 | static struct ieee80211_channel ath9k_2ghz_channels[] = { |
45 | CHAN2G(2412, 0), /* Channel 1 */ | 47 | CHAN2G(2412, 0), /* Channel 1 */ |
46 | CHAN2G(2417, 1), /* Channel 2 */ | 48 | CHAN2G(2417, 1), /* Channel 2 */ |
@@ -605,7 +607,31 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
605 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 607 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
606 | } | 608 | } |
607 | 609 | ||
608 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | 610 | static void ath9k_init_btcoex(struct ath9k_htc_priv *priv) |
611 | { | ||
612 | int qnum; | ||
613 | |||
614 | switch (priv->ah->btcoex_hw.scheme) { | ||
615 | case ATH_BTCOEX_CFG_NONE: | ||
616 | break; | ||
617 | case ATH_BTCOEX_CFG_3WIRE: | ||
618 | priv->ah->btcoex_hw.btactive_gpio = 7; | ||
619 | priv->ah->btcoex_hw.btpriority_gpio = 6; | ||
620 | priv->ah->btcoex_hw.wlanactive_gpio = 8; | ||
621 | priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; | ||
622 | ath9k_hw_btcoex_init_3wire(priv->ah); | ||
623 | ath_htc_init_btcoex_work(priv); | ||
624 | qnum = priv->hwq_map[WME_AC_BE]; | ||
625 | ath9k_hw_init_btcoex_hw(priv->ah, qnum); | ||
626 | break; | ||
627 | default: | ||
628 | WARN_ON(1); | ||
629 | break; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, | ||
634 | u16 devid, char *product) | ||
609 | { | 635 | { |
610 | struct ath_hw *ah = NULL; | 636 | struct ath_hw *ah = NULL; |
611 | struct ath_common *common; | 637 | struct ath_common *common; |
@@ -672,6 +698,11 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, u16 devid) | |||
672 | ath9k_init_channels_rates(priv); | 698 | ath9k_init_channels_rates(priv); |
673 | ath9k_init_misc(priv); | 699 | ath9k_init_misc(priv); |
674 | 700 | ||
701 | if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) { | ||
702 | ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE; | ||
703 | ath9k_init_btcoex(priv); | ||
704 | } | ||
705 | |||
675 | return 0; | 706 | return 0; |
676 | 707 | ||
677 | err_queues: | 708 | err_queues: |
@@ -734,7 +765,8 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
734 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); | 765 | SET_IEEE80211_PERM_ADDR(hw, common->macaddr); |
735 | } | 766 | } |
736 | 767 | ||
737 | static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | 768 | static int ath9k_init_device(struct ath9k_htc_priv *priv, |
769 | u16 devid, char *product) | ||
738 | { | 770 | { |
739 | struct ieee80211_hw *hw = priv->hw; | 771 | struct ieee80211_hw *hw = priv->hw; |
740 | struct ath_common *common; | 772 | struct ath_common *common; |
@@ -743,7 +775,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, u16 devid) | |||
743 | struct ath_regulatory *reg; | 775 | struct ath_regulatory *reg; |
744 | 776 | ||
745 | /* Bring up device */ | 777 | /* Bring up device */ |
746 | error = ath9k_init_priv(priv, devid); | 778 | error = ath9k_init_priv(priv, devid, product); |
747 | if (error != 0) | 779 | if (error != 0) |
748 | goto err_init; | 780 | goto err_init; |
749 | 781 | ||
@@ -801,7 +833,7 @@ err_init: | |||
801 | } | 833 | } |
802 | 834 | ||
803 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | 835 | int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, |
804 | u16 devid) | 836 | u16 devid, char *product) |
805 | { | 837 | { |
806 | struct ieee80211_hw *hw; | 838 | struct ieee80211_hw *hw; |
807 | struct ath9k_htc_priv *priv; | 839 | struct ath9k_htc_priv *priv; |
@@ -835,7 +867,7 @@ int ath9k_htc_probe_device(struct htc_target *htc_handle, struct device *dev, | |||
835 | /* The device may have been unplugged earlier. */ | 867 | /* The device may have been unplugged earlier. */ |
836 | priv->op_flags &= ~OP_UNPLUGGED; | 868 | priv->op_flags &= ~OP_UNPLUGGED; |
837 | 869 | ||
838 | ret = ath9k_init_device(priv, devid); | 870 | ret = ath9k_init_device(priv, devid, product); |
839 | if (ret) | 871 | if (ret) |
840 | goto err_init; | 872 | goto err_init; |
841 | 873 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 7d09b4b17bbd..5e318cb662c6 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1210,6 +1210,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw) | |||
1210 | 1210 | ||
1211 | ieee80211_wake_queues(hw); | 1211 | ieee80211_wake_queues(hw); |
1212 | 1212 | ||
1213 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) { | ||
1214 | ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, | ||
1215 | AR_STOMP_LOW_WLAN_WGHT); | ||
1216 | ath9k_hw_btcoex_enable(ah); | ||
1217 | ath_htc_resume_btcoex_work(priv); | ||
1218 | } | ||
1213 | mutex_unlock(&priv->mutex); | 1219 | mutex_unlock(&priv->mutex); |
1214 | 1220 | ||
1215 | return ret; | 1221 | return ret; |
@@ -1254,6 +1260,12 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw) | |||
1254 | "Monitor interface removed\n"); | 1260 | "Monitor interface removed\n"); |
1255 | } | 1261 | } |
1256 | 1262 | ||
1263 | if (ah->btcoex_hw.enabled) { | ||
1264 | ath9k_hw_btcoex_disable(ah); | ||
1265 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | ||
1266 | ath_htc_cancel_btcoex_work(priv); | ||
1267 | } | ||
1268 | |||
1257 | ath9k_hw_phy_disable(ah); | 1269 | ath9k_hw_phy_disable(ah); |
1258 | ath9k_hw_disable(ah); | 1270 | ath9k_hw_disable(ah); |
1259 | ath9k_hw_configpcipowersave(ah, 1, 1); | 1271 | ath9k_hw_configpcipowersave(ah, 1, 1); |
@@ -1585,9 +1597,10 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1585 | key->hw_key_idx = ret; | 1597 | key->hw_key_idx = ret; |
1586 | /* push IV and Michael MIC generation to stack */ | 1598 | /* push IV and Michael MIC generation to stack */ |
1587 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1599 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1588 | if (key->alg == ALG_TKIP) | 1600 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1589 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1601 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1590 | if (priv->ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | 1602 | if (priv->ah->sw_mgmt_crypto && |
1603 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
1591 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1604 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; |
1592 | ret = 0; | 1605 | ret = 0; |
1593 | } | 1606 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 705c0f342e1c..861ec9269309 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -462,9 +462,9 @@ void ath9k_htc_hw_free(struct htc_target *htc) | |||
462 | } | 462 | } |
463 | 463 | ||
464 | int ath9k_htc_hw_init(struct htc_target *target, | 464 | int ath9k_htc_hw_init(struct htc_target *target, |
465 | struct device *dev, u16 devid) | 465 | struct device *dev, u16 devid, char *product) |
466 | { | 466 | { |
467 | if (ath9k_htc_probe_device(target, dev, devid)) { | 467 | if (ath9k_htc_probe_device(target, dev, devid, product)) { |
468 | printk(KERN_ERR "Failed to initialize the device\n"); | 468 | printk(KERN_ERR "Failed to initialize the device\n"); |
469 | return -ENODEV; | 469 | return -ENODEV; |
470 | } | 470 | } |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.h b/drivers/net/wireless/ath/ath9k/htc_hst.h index faba6790328b..07b6509d5896 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.h +++ b/drivers/net/wireless/ath/ath9k/htc_hst.h | |||
@@ -239,7 +239,7 @@ struct htc_target *ath9k_htc_hw_alloc(void *hif_handle, | |||
239 | struct device *dev); | 239 | struct device *dev); |
240 | void ath9k_htc_hw_free(struct htc_target *htc); | 240 | void ath9k_htc_hw_free(struct htc_target *htc); |
241 | int ath9k_htc_hw_init(struct htc_target *target, | 241 | int ath9k_htc_hw_init(struct htc_target *target, |
242 | struct device *dev, u16 devid); | 242 | struct device *dev, u16 devid, char *product); |
243 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); | 243 | void ath9k_htc_hw_deinit(struct htc_target *target, bool hot_unplug); |
244 | 244 | ||
245 | #endif /* HTC_HST_H */ | 245 | #endif /* HTC_HST_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 399f7c1283cd..1601dd439890 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -355,6 +355,7 @@ struct ath9k_hw_cal_data { | |||
355 | int16_t rawNoiseFloor; | 355 | int16_t rawNoiseFloor; |
356 | bool paprd_done; | 356 | bool paprd_done; |
357 | bool nfcal_pending; | 357 | bool nfcal_pending; |
358 | bool nfcal_interference; | ||
358 | u16 small_signal_gain[AR9300_MAX_CHAINS]; | 359 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
359 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; | 360 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
360 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 361 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3caa32316e7b..1165f909ef04 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -226,9 +226,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
226 | caldata = &aphy->caldata; | 226 | caldata = &aphy->caldata; |
227 | 227 | ||
228 | ath_print(common, ATH_DBG_CONFIG, | 228 | ath_print(common, ATH_DBG_CONFIG, |
229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", | 229 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", |
230 | sc->sc_ah->curchan->channel, | 230 | sc->sc_ah->curchan->channel, |
231 | channel->center_freq, conf_is_ht40(conf)); | 231 | channel->center_freq, conf_is_ht40(conf), |
232 | fastcc); | ||
232 | 233 | ||
233 | spin_lock_bh(&sc->sc_resetlock); | 234 | spin_lock_bh(&sc->sc_resetlock); |
234 | 235 | ||
@@ -395,7 +396,12 @@ void ath_ani_calibrate(unsigned long data) | |||
395 | bool shortcal = false; | 396 | bool shortcal = false; |
396 | bool aniflag = false; | 397 | bool aniflag = false; |
397 | unsigned int timestamp = jiffies_to_msecs(jiffies); | 398 | unsigned int timestamp = jiffies_to_msecs(jiffies); |
398 | u32 cal_interval, short_cal_interval; | 399 | u32 cal_interval, short_cal_interval, long_cal_interval; |
400 | |||
401 | if (ah->caldata && ah->caldata->nfcal_interference) | ||
402 | long_cal_interval = ATH_LONG_CALINTERVAL_INT; | ||
403 | else | ||
404 | long_cal_interval = ATH_LONG_CALINTERVAL; | ||
399 | 405 | ||
400 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? | 406 | short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? |
401 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | 407 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
@@ -407,7 +413,7 @@ void ath_ani_calibrate(unsigned long data) | |||
407 | ath9k_ps_wakeup(sc); | 413 | ath9k_ps_wakeup(sc); |
408 | 414 | ||
409 | /* Long calibration runs independently of short calibration. */ | 415 | /* Long calibration runs independently of short calibration. */ |
410 | if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { | 416 | if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) { |
411 | longcal = true; | 417 | longcal = true; |
412 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); | 418 | ath_print(common, ATH_DBG_ANI, "longcal @%lu\n", jiffies); |
413 | common->ani.longcal_timer = timestamp; | 419 | common->ani.longcal_timer = timestamp; |
@@ -1776,9 +1782,10 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1776 | key->hw_key_idx = ret; | 1782 | key->hw_key_idx = ret; |
1777 | /* push IV and Michael MIC generation to stack */ | 1783 | /* push IV and Michael MIC generation to stack */ |
1778 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1784 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1779 | if (key->alg == ALG_TKIP) | 1785 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1780 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1786 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1781 | if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) | 1787 | if (sc->sc_ah->sw_mgmt_crypto && |
1788 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | ||
1782 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; | 1789 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; |
1783 | ret = 0; | 1790 | ret = 0; |
1784 | } | 1791 | } |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 6260faa658a2..45fe9cac7971 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c | |||
@@ -85,6 +85,8 @@ static const char *wmi_cmd_to_name(enum wmi_cmd_id wmi_cmd) | |||
85 | return "WMI_TGT_DETACH_CMDID"; | 85 | return "WMI_TGT_DETACH_CMDID"; |
86 | case WMI_TGT_TXQ_ENABLE_CMDID: | 86 | case WMI_TGT_TXQ_ENABLE_CMDID: |
87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; | 87 | return "WMI_TGT_TXQ_ENABLE_CMDID"; |
88 | case WMI_AGGR_LIMIT_CMD: | ||
89 | return "WMI_AGGR_LIMIT_CMD"; | ||
88 | } | 90 | } |
89 | 91 | ||
90 | return "Bogus"; | 92 | return "Bogus"; |
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h index 765db5faa2d3..a0bf857625df 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.h +++ b/drivers/net/wireless/ath/ath9k/wmi.h | |||
@@ -71,6 +71,7 @@ enum wmi_cmd_id { | |||
71 | WMI_TX_AGGR_ENABLE_CMDID, | 71 | WMI_TX_AGGR_ENABLE_CMDID, |
72 | WMI_TGT_DETACH_CMDID, | 72 | WMI_TGT_DETACH_CMDID, |
73 | WMI_TGT_TXQ_ENABLE_CMDID, | 73 | WMI_TGT_TXQ_ENABLE_CMDID, |
74 | WMI_AGGR_LIMIT_CMD = 0x0026, | ||
74 | }; | 75 | }; |
75 | 76 | ||
76 | enum wmi_event_id { | 77 | enum wmi_event_id { |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4dda14e36227..457f07692ac7 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1407,22 +1407,6 @@ static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) | |||
1407 | return htype; | 1407 | return htype; |
1408 | } | 1408 | } |
1409 | 1409 | ||
1410 | static int get_hw_crypto_keytype(struct sk_buff *skb) | ||
1411 | { | ||
1412 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | ||
1413 | |||
1414 | if (tx_info->control.hw_key) { | ||
1415 | if (tx_info->control.hw_key->alg == ALG_WEP) | ||
1416 | return ATH9K_KEY_TYPE_WEP; | ||
1417 | else if (tx_info->control.hw_key->alg == ALG_TKIP) | ||
1418 | return ATH9K_KEY_TYPE_TKIP; | ||
1419 | else if (tx_info->control.hw_key->alg == ALG_CCMP) | ||
1420 | return ATH9K_KEY_TYPE_AES; | ||
1421 | } | ||
1422 | |||
1423 | return ATH9K_KEY_TYPE_CLEAR; | ||
1424 | } | ||
1425 | |||
1426 | static void assign_aggr_tid_seqno(struct sk_buff *skb, | 1410 | static void assign_aggr_tid_seqno(struct sk_buff *skb, |
1427 | struct ath_buf *bf) | 1411 | struct ath_buf *bf) |
1428 | { | 1412 | { |
@@ -1661,7 +1645,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1661 | bf->bf_state.bfs_paprd_timestamp = jiffies; | 1645 | bf->bf_state.bfs_paprd_timestamp = jiffies; |
1662 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); | 1646 | bf->bf_flags = setup_tx_flags(skb, use_ldpc); |
1663 | 1647 | ||
1664 | bf->bf_keytype = get_hw_crypto_keytype(skb); | 1648 | bf->bf_keytype = ath9k_cmn_get_hw_crypto_keytype(skb); |
1665 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { | 1649 | if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { |
1666 | bf->bf_frmlen += tx_info->control.hw_key->icv_len; | 1650 | bf->bf_frmlen += tx_info->control.hw_key->icv_len; |
1667 | bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; | 1651 | bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; |
diff --git a/drivers/net/wireless/ath/debug.h b/drivers/net/wireless/ath/debug.h index 873bf526e11f..fd3a020682dc 100644 --- a/drivers/net/wireless/ath/debug.h +++ b/drivers/net/wireless/ath/debug.h | |||
@@ -36,6 +36,7 @@ | |||
36 | * @ATH_DBG_PS: power save processing | 36 | * @ATH_DBG_PS: power save processing |
37 | * @ATH_DBG_HWTIMER: hardware timer handling | 37 | * @ATH_DBG_HWTIMER: hardware timer handling |
38 | * @ATH_DBG_BTCOEX: bluetooth coexistance | 38 | * @ATH_DBG_BTCOEX: bluetooth coexistance |
39 | * @ATH_DBG_BSTUCK: stuck beacons | ||
39 | * @ATH_DBG_ANY: enable all debugging | 40 | * @ATH_DBG_ANY: enable all debugging |
40 | * | 41 | * |
41 | * The debug level is used to control the amount and type of debugging output | 42 | * The debug level is used to control the amount and type of debugging output |
@@ -60,6 +61,7 @@ enum ATH_DEBUG { | |||
60 | ATH_DBG_HWTIMER = 0x00001000, | 61 | ATH_DBG_HWTIMER = 0x00001000, |
61 | ATH_DBG_BTCOEX = 0x00002000, | 62 | ATH_DBG_BTCOEX = 0x00002000, |
62 | ATH_DBG_WMI = 0x00004000, | 63 | ATH_DBG_WMI = 0x00004000, |
64 | ATH_DBG_BSTUCK = 0x00008000, | ||
63 | ATH_DBG_ANY = 0xffffffff | 65 | ATH_DBG_ANY = 0xffffffff |
64 | }; | 66 | }; |
65 | 67 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 20631ae2ddd7..a1186525c70d 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2280,6 +2280,7 @@ out: | |||
2280 | 2280 | ||
2281 | static int b43_upload_microcode(struct b43_wldev *dev) | 2281 | static int b43_upload_microcode(struct b43_wldev *dev) |
2282 | { | 2282 | { |
2283 | struct wiphy *wiphy = dev->wl->hw->wiphy; | ||
2283 | const size_t hdr_len = sizeof(struct b43_fw_header); | 2284 | const size_t hdr_len = sizeof(struct b43_fw_header); |
2284 | const __be32 *data; | 2285 | const __be32 *data; |
2285 | unsigned int i, len; | 2286 | unsigned int i, len; |
@@ -2405,6 +2406,10 @@ static int b43_upload_microcode(struct b43_wldev *dev) | |||
2405 | } | 2406 | } |
2406 | } | 2407 | } |
2407 | 2408 | ||
2409 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", | ||
2410 | dev->fw.rev, dev->fw.patch); | ||
2411 | wiphy->hw_version = dev->dev->id.coreid; | ||
2412 | |||
2408 | if (b43_is_old_txhdr_format(dev)) { | 2413 | if (b43_is_old_txhdr_format(dev)) { |
2409 | /* We're over the deadline, but we keep support for old fw | 2414 | /* We're over the deadline, but we keep support for old fw |
2410 | * until it turns out to be in major conflict with something new. */ | 2415 | * until it turns out to be in major conflict with something new. */ |
@@ -3754,17 +3759,17 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3754 | } | 3759 | } |
3755 | 3760 | ||
3756 | err = -EINVAL; | 3761 | err = -EINVAL; |
3757 | switch (key->alg) { | 3762 | switch (key->cipher) { |
3758 | case ALG_WEP: | 3763 | case WLAN_CIPHER_SUITE_WEP40: |
3759 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 3764 | algorithm = B43_SEC_ALGO_WEP40; |
3760 | algorithm = B43_SEC_ALGO_WEP40; | 3765 | break; |
3761 | else | 3766 | case WLAN_CIPHER_SUITE_WEP104: |
3762 | algorithm = B43_SEC_ALGO_WEP104; | 3767 | algorithm = B43_SEC_ALGO_WEP104; |
3763 | break; | 3768 | break; |
3764 | case ALG_TKIP: | 3769 | case WLAN_CIPHER_SUITE_TKIP: |
3765 | algorithm = B43_SEC_ALGO_TKIP; | 3770 | algorithm = B43_SEC_ALGO_TKIP; |
3766 | break; | 3771 | break; |
3767 | case ALG_CCMP: | 3772 | case WLAN_CIPHER_SUITE_CCMP: |
3768 | algorithm = B43_SEC_ALGO_AES; | 3773 | algorithm = B43_SEC_ALGO_AES; |
3769 | break; | 3774 | break; |
3770 | default: | 3775 | default: |
@@ -4250,6 +4255,10 @@ static void b43_wireless_core_exit(struct b43_wldev *dev) | |||
4250 | B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); | 4255 | B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); |
4251 | if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) | 4256 | if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) |
4252 | return; | 4257 | return; |
4258 | |||
4259 | /* Unregister HW RNG driver */ | ||
4260 | b43_rng_exit(dev->wl); | ||
4261 | |||
4253 | b43_set_status(dev, B43_STAT_UNINIT); | 4262 | b43_set_status(dev, B43_STAT_UNINIT); |
4254 | 4263 | ||
4255 | /* Stop the microcode PSM. */ | 4264 | /* Stop the microcode PSM. */ |
@@ -4379,6 +4388,9 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4379 | 4388 | ||
4380 | b43_set_status(dev, B43_STAT_INITIALIZED); | 4389 | b43_set_status(dev, B43_STAT_INITIALIZED); |
4381 | 4390 | ||
4391 | /* Register HW RNG driver */ | ||
4392 | b43_rng_init(dev->wl); | ||
4393 | |||
4382 | out: | 4394 | out: |
4383 | return err; | 4395 | return err; |
4384 | 4396 | ||
@@ -4984,7 +4996,6 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) | |||
4984 | if (err) | 4996 | if (err) |
4985 | goto err_one_core_detach; | 4997 | goto err_one_core_detach; |
4986 | b43_leds_register(wl->current_dev); | 4998 | b43_leds_register(wl->current_dev); |
4987 | b43_rng_init(wl); | ||
4988 | } | 4999 | } |
4989 | 5000 | ||
4990 | out: | 5001 | out: |
@@ -5020,7 +5031,6 @@ static void b43_remove(struct ssb_device *dev) | |||
5020 | b43_one_core_detach(dev); | 5031 | b43_one_core_detach(dev); |
5021 | 5032 | ||
5022 | if (list_empty(&wl->devlist)) { | 5033 | if (list_empty(&wl->devlist)) { |
5023 | b43_rng_exit(wl); | ||
5024 | b43_leds_unregister(wl); | 5034 | b43_leds_unregister(wl); |
5025 | /* Last core on the chip unregistered. | 5035 | /* Last core on the chip unregistered. |
5026 | * We can destroy common struct b43_wl. | 5036 | * We can destroy common struct b43_wl. |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index e288c559481d..d116229c3347 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -893,7 +893,7 @@ static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev) | |||
893 | } | 893 | } |
894 | 894 | ||
895 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ | 895 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */ |
896 | static void b43_nphy_gain_crtl_workarounds(struct b43_wldev *dev) | 896 | static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev) |
897 | { | 897 | { |
898 | struct b43_phy_n *nphy = dev->phy.n; | 898 | struct b43_phy_n *nphy = dev->phy.n; |
899 | u8 i, j; | 899 | u8 i, j; |
@@ -1094,11 +1094,12 @@ static void b43_nphy_workarounds(struct b43_wldev *dev) | |||
1094 | b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); | 1094 | b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7); |
1095 | b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); | 1095 | b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7); |
1096 | 1096 | ||
1097 | b43_nphy_gain_crtl_workarounds(dev); | 1097 | b43_nphy_gain_ctrl_workarounds(dev); |
1098 | 1098 | ||
1099 | if (dev->phy.rev < 2) { | 1099 | if (dev->phy.rev < 2) { |
1100 | if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) | 1100 | if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2) |
1101 | ; /*TODO: b43_mhf(dev, 2, 0x0010, 0x0010, 3);*/ | 1101 | b43_hf_write(dev, b43_hf_read(dev) | |
1102 | B43_HF_MLADVW); | ||
1102 | } else if (dev->phy.rev == 2) { | 1103 | } else if (dev->phy.rev == 2) { |
1103 | b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); | 1104 | b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0); |
1104 | b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); | 1105 | b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0); |
@@ -3073,6 +3074,55 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, | |||
3073 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); | 3074 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); |
3074 | } | 3075 | } |
3075 | 3076 | ||
3077 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ | ||
3078 | static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) | ||
3079 | { | ||
3080 | u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); | ||
3081 | if (on) | ||
3082 | tmslow |= SSB_TMSLOW_PHYCLK; | ||
3083 | else | ||
3084 | tmslow &= ~SSB_TMSLOW_PHYCLK; | ||
3085 | ssb_write32(dev->dev, SSB_TMSLOW, tmslow); | ||
3086 | } | ||
3087 | |||
3088 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ | ||
3089 | static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) | ||
3090 | { | ||
3091 | struct b43_phy *phy = &dev->phy; | ||
3092 | struct b43_phy_n *nphy = phy->n; | ||
3093 | u16 buf[16]; | ||
3094 | |||
3095 | if (0 /* FIXME clk */) | ||
3096 | return; | ||
3097 | |||
3098 | b43_mac_suspend(dev); | ||
3099 | |||
3100 | if (nphy->hang_avoid) | ||
3101 | b43_nphy_stay_in_carrier_search(dev, true); | ||
3102 | |||
3103 | b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN, | ||
3104 | (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT); | ||
3105 | |||
3106 | if (mask & 0x3 != 0x3) { | ||
3107 | b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1); | ||
3108 | if (dev->phy.rev >= 3) { | ||
3109 | /* TODO */ | ||
3110 | } | ||
3111 | } else { | ||
3112 | b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E); | ||
3113 | if (dev->phy.rev >= 3) { | ||
3114 | /* TODO */ | ||
3115 | } | ||
3116 | } | ||
3117 | |||
3118 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); | ||
3119 | |||
3120 | if (nphy->hang_avoid) | ||
3121 | b43_nphy_stay_in_carrier_search(dev, false); | ||
3122 | |||
3123 | b43_mac_enable(dev); | ||
3124 | } | ||
3125 | |||
3076 | /* | 3126 | /* |
3077 | * Init N-PHY | 3127 | * Init N-PHY |
3078 | * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N | 3128 | * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N |
@@ -3173,7 +3223,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3173 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); | 3223 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); |
3174 | b43_nphy_bmac_clock_fgc(dev, 0); | 3224 | b43_nphy_bmac_clock_fgc(dev, 0); |
3175 | 3225 | ||
3176 | /* TODO N PHY MAC PHY Clock Set with argument 1 */ | 3226 | b43_nphy_mac_phy_clock_set(dev, true); |
3177 | 3227 | ||
3178 | b43_nphy_pa_override(dev, false); | 3228 | b43_nphy_pa_override(dev, false); |
3179 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | 3229 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); |
@@ -3199,7 +3249,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3199 | } | 3249 | } |
3200 | 3250 | ||
3201 | if (nphy->phyrxchain != 3) | 3251 | if (nphy->phyrxchain != 3) |
3202 | ;/* TODO N PHY RX Core Set State with phyrxchain as argument */ | 3252 | b43_nphy_set_rx_core_state(dev, nphy->phyrxchain); |
3203 | if (nphy->mphase_cal_phase_id > 0) | 3253 | if (nphy->mphase_cal_phase_id > 0) |
3204 | ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ | 3254 | ;/* TODO PHY Periodic Calibration Multi-Phase Restart */ |
3205 | 3255 | ||
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1713f5f7a58b..67f18ecdb3bf 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -1623,6 +1623,7 @@ error: | |||
1623 | 1623 | ||
1624 | static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) | 1624 | static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) |
1625 | { | 1625 | { |
1626 | struct wiphy *wiphy = dev->wl->hw->wiphy; | ||
1626 | const size_t hdr_len = sizeof(struct b43legacy_fw_header); | 1627 | const size_t hdr_len = sizeof(struct b43legacy_fw_header); |
1627 | const __be32 *data; | 1628 | const __be32 *data; |
1628 | unsigned int i; | 1629 | unsigned int i; |
@@ -1732,6 +1733,10 @@ static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) | |||
1732 | dev->fw.rev = fwrev; | 1733 | dev->fw.rev = fwrev; |
1733 | dev->fw.patch = fwpatch; | 1734 | dev->fw.patch = fwpatch; |
1734 | 1735 | ||
1736 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "%u.%u", | ||
1737 | dev->fw.rev, dev->fw.patch); | ||
1738 | wiphy->hw_version = dev->dev->id.coreid; | ||
1739 | |||
1735 | return 0; | 1740 | return 0; |
1736 | 1741 | ||
1737 | error: | 1742 | error: |
diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index a85e43a8d758..6038633ef361 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c | |||
@@ -1696,7 +1696,7 @@ static int prism2_request_scan(struct net_device *dev) | |||
1696 | hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, | 1696 | hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, |
1697 | HFA384X_ROAMING_FIRMWARE); | 1697 | HFA384X_ROAMING_FIRMWARE); |
1698 | 1698 | ||
1699 | return 0; | 1699 | return ret; |
1700 | } | 1700 | } |
1701 | 1701 | ||
1702 | #else /* !PRISM2_NO_STATION_MODES */ | 1702 | #else /* !PRISM2_NO_STATION_MODES */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 2ba57340083c..61915f371416 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -3056,9 +3056,9 @@ static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) | |||
3056 | 3056 | ||
3057 | packet = list_entry(element, struct ipw2100_tx_packet, list); | 3057 | packet = list_entry(element, struct ipw2100_tx_packet, list); |
3058 | 3058 | ||
3059 | IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n", | 3059 | IPW_DEBUG_TX("using TBD at virt=%p, phys=%04X\n", |
3060 | &txq->drv[txq->next], | 3060 | &txq->drv[txq->next], |
3061 | (void *)(txq->nic + txq->next * | 3061 | (u32) (txq->nic + txq->next * |
3062 | sizeof(struct ipw2100_bd))); | 3062 | sizeof(struct ipw2100_bd))); |
3063 | 3063 | ||
3064 | packet->index = txq->next; | 3064 | packet->index = txq->next; |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index a51e4da1bdfc..b82364258dc5 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -3,6 +3,9 @@ config IWLWIFI | |||
3 | depends on PCI && MAC80211 | 3 | depends on PCI && MAC80211 |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | 5 | ||
6 | menu "Debugging Options" | ||
7 | depends on IWLWIFI | ||
8 | |||
6 | config IWLWIFI_DEBUG | 9 | config IWLWIFI_DEBUG |
7 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" | 10 | bool "Enable full debugging output in iwlagn and iwl3945 drivers" |
8 | depends on IWLWIFI | 11 | depends on IWLWIFI |
@@ -36,6 +39,12 @@ config IWLWIFI_DEBUGFS | |||
36 | is a low-impact option that allows getting insight into the | 39 | is a low-impact option that allows getting insight into the |
37 | driver's state at runtime. | 40 | driver's state at runtime. |
38 | 41 | ||
42 | config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | ||
43 | bool "Experimental uCode support" | ||
44 | depends on IWLWIFI && IWLWIFI_DEBUG | ||
45 | ---help--- | ||
46 | Enable use of experimental ucode for testing and debugging. | ||
47 | |||
39 | config IWLWIFI_DEVICE_TRACING | 48 | config IWLWIFI_DEVICE_TRACING |
40 | bool "iwlwifi device access tracing" | 49 | bool "iwlwifi device access tracing" |
41 | depends on IWLWIFI | 50 | depends on IWLWIFI |
@@ -53,6 +62,7 @@ config IWLWIFI_DEVICE_TRACING | |||
53 | 62 | ||
54 | If unsure, say Y so we can help you better when problems | 63 | If unsure, say Y so we can help you better when problems |
55 | occur. | 64 | occur. |
65 | endmenu | ||
56 | 66 | ||
57 | config IWLAGN | 67 | config IWLAGN |
58 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" | 68 | tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 728bb858ba97..493163925a45 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -12,6 +12,7 @@ obj-$(CONFIG_IWLAGN) += iwlagn.o | |||
12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o | 12 | iwlagn-objs := iwl-agn.o iwl-agn-rs.o iwl-agn-led.o iwl-agn-ict.o |
13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o | 13 | iwlagn-objs += iwl-agn-ucode.o iwl-agn-hcmd.o iwl-agn-tx.o |
14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o | 14 | iwlagn-objs += iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o |
15 | iwlagn-objs += iwl-agn-tt.o | ||
15 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o | 16 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o |
16 | 17 | ||
17 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o | 18 | iwlagn-$(CONFIG_IWL4965) += iwl-4965.o |
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 0b779a41a142..3bf5a30828be 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -229,6 +229,11 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
229 | .check_ack_health = iwl_good_ack_health, | 229 | .check_ack_health = iwl_good_ack_health, |
230 | .txfifo_flush = iwlagn_txfifo_flush, | 230 | .txfifo_flush = iwlagn_txfifo_flush, |
231 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 231 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
232 | .tt_ops = { | ||
233 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
234 | .tt_power_mode = iwl_tt_current_power_mode, | ||
235 | .ct_kill_check = iwl_check_for_ct_kill, | ||
236 | } | ||
232 | }; | 237 | }; |
233 | 238 | ||
234 | static const struct iwl_ops iwl1000_ops = { | 239 | static const struct iwl_ops iwl1000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d92b72909233..f0a47f42d4b8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1470,7 +1470,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, | |||
1470 | 1470 | ||
1471 | cmd.band = band; | 1471 | cmd.band = band; |
1472 | cmd.expect_beacon = 0; | 1472 | cmd.expect_beacon = 0; |
1473 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); | 1473 | ch = ch_switch->channel->hw_value; |
1474 | cmd.channel = cpu_to_le16(ch); | 1474 | cmd.channel = cpu_to_le16(ch); |
1475 | cmd.rxon_flags = priv->staging_rxon.flags; | 1475 | cmd.rxon_flags = priv->staging_rxon.flags; |
1476 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; | 1476 | cmd.rxon_filter_flags = priv->staging_rxon.filter_flags; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 48bdcd8d2e94..013f3dae69f1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -291,7 +291,7 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
291 | }; | 291 | }; |
292 | 292 | ||
293 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 293 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
294 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); | 294 | ch = ch_switch->channel->hw_value; |
295 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", | 295 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", |
296 | priv->active_rxon.channel, ch); | 296 | priv->active_rxon.channel, ch); |
297 | cmd.channel = cpu_to_le16(ch); | 297 | cmd.channel = cpu_to_le16(ch); |
@@ -405,6 +405,11 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
405 | .check_ack_health = iwl_good_ack_health, | 405 | .check_ack_health = iwl_good_ack_health, |
406 | .txfifo_flush = iwlagn_txfifo_flush, | 406 | .txfifo_flush = iwlagn_txfifo_flush, |
407 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 407 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
408 | .tt_ops = { | ||
409 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
410 | .tt_power_mode = iwl_tt_current_power_mode, | ||
411 | .ct_kill_check = iwl_check_for_ct_kill, | ||
412 | } | ||
408 | }; | 413 | }; |
409 | 414 | ||
410 | static struct iwl_lib_ops iwl5150_lib = { | 415 | static struct iwl_lib_ops iwl5150_lib = { |
@@ -470,6 +475,11 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
470 | .check_ack_health = iwl_good_ack_health, | 475 | .check_ack_health = iwl_good_ack_health, |
471 | .txfifo_flush = iwlagn_txfifo_flush, | 476 | .txfifo_flush = iwlagn_txfifo_flush, |
472 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 477 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
478 | .tt_ops = { | ||
479 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
480 | .tt_power_mode = iwl_tt_current_power_mode, | ||
481 | .ct_kill_check = iwl_check_for_ct_kill, | ||
482 | } | ||
473 | }; | 483 | }; |
474 | 484 | ||
475 | static const struct iwl_ops iwl5000_ops = { | 485 | static const struct iwl_ops iwl5000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index cee06b968de8..9e390f698641 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -214,7 +214,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
214 | }; | 214 | }; |
215 | 215 | ||
216 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 216 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; |
217 | ch = ieee80211_frequency_to_channel(ch_switch->channel->center_freq); | 217 | ch = ch_switch->channel->hw_value; |
218 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | 218 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", |
219 | priv->active_rxon.channel, ch); | 219 | priv->active_rxon.channel, ch); |
220 | cmd.channel = cpu_to_le16(ch); | 220 | cmd.channel = cpu_to_le16(ch); |
@@ -330,6 +330,11 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
330 | .check_ack_health = iwl_good_ack_health, | 330 | .check_ack_health = iwl_good_ack_health, |
331 | .txfifo_flush = iwlagn_txfifo_flush, | 331 | .txfifo_flush = iwlagn_txfifo_flush, |
332 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, | 332 | .dev_txfifo_flush = iwlagn_dev_txfifo_flush, |
333 | .tt_ops = { | ||
334 | .lower_power_detection = iwl_tt_is_low_power_state, | ||
335 | .tt_power_mode = iwl_tt_current_power_mode, | ||
336 | .ct_kill_check = iwl_check_for_ct_kill, | ||
337 | } | ||
333 | }; | 338 | }; |
334 | 339 | ||
335 | static const struct iwl_ops iwl6000_ops = { | 340 | static const struct iwl_ops iwl6000_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 75b901b3eb1e..84939763d178 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -235,13 +235,13 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
235 | /* data from PHY/DSP regarding signal strength, etc., | 235 | /* data from PHY/DSP regarding signal strength, etc., |
236 | * contents are always there, not configurable by host | 236 | * contents are always there, not configurable by host |
237 | */ | 237 | */ |
238 | struct iwl5000_non_cfg_phy *ncphy = | 238 | struct iwlagn_non_cfg_phy *ncphy = |
239 | (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; | 239 | (struct iwlagn_non_cfg_phy *)rx_resp->non_cfg_phy_buf; |
240 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; | 240 | u32 val, rssi_a, rssi_b, rssi_c, max_rssi; |
241 | u8 agc; | 241 | u8 agc; |
242 | 242 | ||
243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); | 243 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_AGC_IDX]); |
244 | agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; | 244 | agc = (val & IWLAGN_OFDM_AGC_MSK) >> IWLAGN_OFDM_AGC_BIT_POS; |
245 | 245 | ||
246 | /* Find max rssi among 3 possible receivers. | 246 | /* Find max rssi among 3 possible receivers. |
247 | * These values are measured by the digital signal processor (DSP). | 247 | * These values are measured by the digital signal processor (DSP). |
@@ -249,11 +249,14 @@ static int iwlagn_calc_rssi(struct iwl_priv *priv, | |||
249 | * if the radio's automatic gain control (AGC) is working right. | 249 | * if the radio's automatic gain control (AGC) is working right. |
250 | * AGC value (see below) will provide the "interesting" info. | 250 | * AGC value (see below) will provide the "interesting" info. |
251 | */ | 251 | */ |
252 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); | 252 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_AB_IDX]); |
253 | rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; | 253 | rssi_a = (val & IWLAGN_OFDM_RSSI_INBAND_A_BITMSK) >> |
254 | rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; | 254 | IWLAGN_OFDM_RSSI_A_BIT_POS; |
255 | val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); | 255 | rssi_b = (val & IWLAGN_OFDM_RSSI_INBAND_B_BITMSK) >> |
256 | rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; | 256 | IWLAGN_OFDM_RSSI_B_BIT_POS; |
257 | val = le32_to_cpu(ncphy->non_cfg_phy[IWLAGN_RX_RES_RSSI_C_IDX]); | ||
258 | rssi_c = (val & IWLAGN_OFDM_RSSI_INBAND_C_BITMSK) >> | ||
259 | IWLAGN_OFDM_RSSI_C_BIT_POS; | ||
257 | 260 | ||
258 | max_rssi = max_t(u32, rssi_a, rssi_b); | 261 | max_rssi = max_t(u32, rssi_a, rssi_b); |
259 | max_rssi = max_t(u32, max_rssi, rssi_c); | 262 | max_rssi = max_t(u32, max_rssi, rssi_c); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 9dd9e64c2b0b..eedd71f5506b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -1098,7 +1098,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
1098 | if (chan->band != band) | 1098 | if (chan->band != band) |
1099 | continue; | 1099 | continue; |
1100 | 1100 | ||
1101 | channel = ieee80211_frequency_to_channel(chan->center_freq); | 1101 | channel = chan->hw_value; |
1102 | scan_ch->channel = cpu_to_le16(channel); | 1102 | scan_ch->channel = cpu_to_le16(channel); |
1103 | 1103 | ||
1104 | ch_info = iwl_get_channel_info(priv, band, channel); | 1104 | ch_info = iwl_get_channel_info(priv, band, channel); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 23e5c42e7d7e..a4563389bad0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -82,6 +82,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
82 | struct iwl_lq_sta *lq_sta); | 82 | struct iwl_lq_sta *lq_sta); |
83 | static void rs_fill_link_cmd(struct iwl_priv *priv, | 83 | static void rs_fill_link_cmd(struct iwl_priv *priv, |
84 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); | 84 | struct iwl_lq_sta *lq_sta, u32 rate_n_flags); |
85 | static void rs_stay_in_table(struct iwl_lq_sta *lq_sta); | ||
85 | 86 | ||
86 | 87 | ||
87 | #ifdef CONFIG_MAC80211_DEBUGFS | 88 | #ifdef CONFIG_MAC80211_DEBUGFS |
@@ -502,6 +503,7 @@ static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, | |||
502 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); | 503 | u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); |
503 | u8 mcs; | 504 | u8 mcs; |
504 | 505 | ||
506 | memset(tbl, 0, sizeof(struct iwl_scale_tbl_info)); | ||
505 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); | 507 | *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); |
506 | 508 | ||
507 | if (*rate_idx == IWL_RATE_INVALID) { | 509 | if (*rate_idx == IWL_RATE_INVALID) { |
@@ -848,7 +850,20 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
848 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); | 850 | other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
849 | } else { | 851 | } else { |
850 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); | 852 | IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); |
851 | return; | 853 | tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); |
854 | IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n", | ||
855 | tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI); | ||
856 | tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]); | ||
857 | IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n", | ||
858 | tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI); | ||
859 | IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n", | ||
860 | tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI); | ||
861 | /* | ||
862 | * no matching table found, let's by-pass the data collection | ||
863 | * and continue to perform rate scale to find the rate table | ||
864 | */ | ||
865 | rs_stay_in_table(lq_sta); | ||
866 | goto done; | ||
852 | } | 867 | } |
853 | 868 | ||
854 | /* | 869 | /* |
@@ -909,7 +924,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
909 | } | 924 | } |
910 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ | 925 | /* The last TX rate is cached in lq_sta; it's set in if/else above */ |
911 | lq_sta->last_rate_n_flags = tx_rate; | 926 | lq_sta->last_rate_n_flags = tx_rate; |
912 | 927 | done: | |
913 | /* See if there's a better rate or modulation mode to try. */ | 928 | /* See if there's a better rate or modulation mode to try. */ |
914 | if (sta && sta->supp_rates[sband->band]) | 929 | if (sta && sta->supp_rates[sband->band]) |
915 | rs_rate_scale_perform(priv, skb, sta, lq_sta); | 930 | rs_rate_scale_perform(priv, skb, sta, lq_sta); |
@@ -1265,7 +1280,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1265 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1280 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1266 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1281 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1267 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1282 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1268 | u8 start_action = tbl->action; | 1283 | u8 start_action; |
1269 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1284 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1270 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1285 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1271 | int ret = 0; | 1286 | int ret = 0; |
@@ -1277,6 +1292,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv, | |||
1277 | else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && | 1292 | else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && |
1278 | tbl->action > IWL_LEGACY_SWITCH_SISO) | 1293 | tbl->action > IWL_LEGACY_SWITCH_SISO) |
1279 | tbl->action = IWL_LEGACY_SWITCH_SISO; | 1294 | tbl->action = IWL_LEGACY_SWITCH_SISO; |
1295 | start_action = tbl->action; | ||
1280 | for (; ;) { | 1296 | for (; ;) { |
1281 | lq_sta->action_counter++; | 1297 | lq_sta->action_counter++; |
1282 | switch (tbl->action) { | 1298 | switch (tbl->action) { |
@@ -1403,7 +1419,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1403 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1419 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
1404 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1420 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1405 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1421 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1406 | u8 start_action = tbl->action; | 1422 | u8 start_action; |
1407 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1423 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1408 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1424 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1409 | u8 update_search_tbl_counter = 0; | 1425 | u8 update_search_tbl_counter = 0; |
@@ -1414,6 +1430,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1414 | /* stay in SISO */ | 1430 | /* stay in SISO */ |
1415 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; | 1431 | tbl->action = IWL_SISO_SWITCH_ANTENNA1; |
1416 | } | 1432 | } |
1433 | start_action = tbl->action; | ||
1417 | for (;;) { | 1434 | for (;;) { |
1418 | lq_sta->action_counter++; | 1435 | lq_sta->action_counter++; |
1419 | switch (tbl->action) { | 1436 | switch (tbl->action) { |
@@ -1541,7 +1558,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1541 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1558 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
1542 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1559 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1543 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1560 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1544 | u8 start_action = tbl->action; | 1561 | u8 start_action; |
1545 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1562 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1546 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1563 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1547 | u8 update_search_tbl_counter = 0; | 1564 | u8 update_search_tbl_counter = 0; |
@@ -1553,6 +1570,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1553 | /* switch in SISO */ | 1570 | /* switch in SISO */ |
1554 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; | 1571 | tbl->action = IWL_MIMO2_SWITCH_SISO_A; |
1555 | } | 1572 | } |
1573 | start_action = tbl->action; | ||
1556 | for (;;) { | 1574 | for (;;) { |
1557 | lq_sta->action_counter++; | 1575 | lq_sta->action_counter++; |
1558 | switch (tbl->action) { | 1576 | switch (tbl->action) { |
@@ -1682,7 +1700,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1682 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | 1700 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; |
1683 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1701 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1684 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1702 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1685 | u8 start_action = tbl->action; | 1703 | u8 start_action; |
1686 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; | 1704 | u8 valid_tx_ant = priv->hw_params.valid_tx_ant; |
1687 | u8 tx_chains_num = priv->hw_params.tx_chains_num; | 1705 | u8 tx_chains_num = priv->hw_params.tx_chains_num; |
1688 | int ret; | 1706 | int ret; |
@@ -1694,6 +1712,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1694 | /* switch in SISO */ | 1712 | /* switch in SISO */ |
1695 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; | 1713 | tbl->action = IWL_MIMO3_SWITCH_SISO_A; |
1696 | } | 1714 | } |
1715 | start_action = tbl->action; | ||
1697 | for (;;) { | 1716 | for (;;) { |
1698 | lq_sta->action_counter++; | 1717 | lq_sta->action_counter++; |
1699 | switch (tbl->action) { | 1718 | switch (tbl->action) { |
@@ -2594,7 +2613,6 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2594 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); | 2613 | rs_dbgfs_set_mcs(lq_sta, &new_rate, index); |
2595 | 2614 | ||
2596 | /* Interpret new_rate (rate_n_flags) */ | 2615 | /* Interpret new_rate (rate_n_flags) */ |
2597 | memset(&tbl_type, 0, sizeof(tbl_type)); | ||
2598 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, | 2616 | rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, |
2599 | &tbl_type, &rate_idx); | 2617 | &tbl_type, &rate_idx); |
2600 | 2618 | ||
@@ -2694,8 +2712,18 @@ static void rs_fill_link_cmd(struct iwl_priv *priv, | |||
2694 | 2712 | ||
2695 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; | 2713 | lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; |
2696 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 2714 | lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
2715 | |||
2697 | lq_cmd->agg_params.agg_time_limit = | 2716 | lq_cmd->agg_params.agg_time_limit = |
2698 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 2717 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
2718 | /* | ||
2719 | * overwrite if needed, pass aggregation time limit | ||
2720 | * to uCode in uSec | ||
2721 | */ | ||
2722 | if (priv && priv->cfg->agg_time_limit && | ||
2723 | priv->cfg->agg_time_limit >= LINK_QUAL_AGG_TIME_LIMIT_MIN && | ||
2724 | priv->cfg->agg_time_limit <= LINK_QUAL_AGG_TIME_LIMIT_MAX) | ||
2725 | lq_cmd->agg_params.agg_time_limit = | ||
2726 | cpu_to_le16(priv->cfg->agg_time_limit); | ||
2699 | } | 2727 | } |
2700 | 2728 | ||
2701 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | 2729 | static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.c b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c new file mode 100644 index 000000000000..30298ea56a24 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.c | |||
@@ -0,0 +1,696 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | |||
29 | |||
30 | #include <linux/kernel.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/init.h> | ||
34 | |||
35 | #include <net/mac80211.h> | ||
36 | |||
37 | #include "iwl-eeprom.h" | ||
38 | #include "iwl-dev.h" | ||
39 | #include "iwl-core.h" | ||
40 | #include "iwl-io.h" | ||
41 | #include "iwl-commands.h" | ||
42 | #include "iwl-debug.h" | ||
43 | #include "iwl-agn-tt.h" | ||
44 | |||
45 | /* default Thermal Throttling transaction table | ||
46 | * Current state | Throttling Down | Throttling Up | ||
47 | *============================================================================= | ||
48 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
49 | *----------------------------------------------------------------------------- | ||
50 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
51 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
52 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
53 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
54 | *============================================================================= | ||
55 | */ | ||
56 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | ||
57 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, | ||
58 | {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, | ||
59 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
60 | }; | ||
61 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | ||
62 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, | ||
63 | {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, | ||
64 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
65 | }; | ||
66 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | ||
67 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, | ||
68 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, | ||
69 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
70 | }; | ||
71 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | ||
72 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, | ||
73 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, | ||
74 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | ||
75 | }; | ||
76 | |||
77 | /* Advance Thermal Throttling default restriction table */ | ||
78 | static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { | ||
79 | {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, | ||
80 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, | ||
81 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, | ||
82 | {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } | ||
83 | }; | ||
84 | |||
85 | bool iwl_tt_is_low_power_state(struct iwl_priv *priv) | ||
86 | { | ||
87 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
88 | |||
89 | if (tt->state >= IWL_TI_1) | ||
90 | return true; | ||
91 | return false; | ||
92 | } | ||
93 | |||
94 | u8 iwl_tt_current_power_mode(struct iwl_priv *priv) | ||
95 | { | ||
96 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
97 | |||
98 | return tt->tt_power_mode; | ||
99 | } | ||
100 | |||
101 | bool iwl_ht_enabled(struct iwl_priv *priv) | ||
102 | { | ||
103 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
104 | struct iwl_tt_restriction *restriction; | ||
105 | |||
106 | if (!priv->thermal_throttle.advanced_tt) | ||
107 | return true; | ||
108 | restriction = tt->restriction + tt->state; | ||
109 | return restriction->is_ht; | ||
110 | } | ||
111 | |||
112 | static bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | ||
113 | { | ||
114 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
115 | bool within_margin = false; | ||
116 | |||
117 | if (priv->cfg->temperature_kelvin) | ||
118 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
119 | |||
120 | if (!priv->thermal_throttle.advanced_tt) | ||
121 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
122 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | ||
123 | else | ||
124 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
125 | CT_KILL_THRESHOLD) ? true : false; | ||
126 | return within_margin; | ||
127 | } | ||
128 | |||
129 | bool iwl_check_for_ct_kill(struct iwl_priv *priv) | ||
130 | { | ||
131 | bool is_ct_kill = false; | ||
132 | |||
133 | if (iwl_within_ct_kill_margin(priv)) { | ||
134 | iwl_tt_enter_ct_kill(priv); | ||
135 | is_ct_kill = true; | ||
136 | } | ||
137 | return is_ct_kill; | ||
138 | } | ||
139 | |||
140 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | ||
141 | { | ||
142 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
143 | struct iwl_tt_restriction *restriction; | ||
144 | |||
145 | if (!priv->thermal_throttle.advanced_tt) | ||
146 | return IWL_ANT_OK_MULTI; | ||
147 | restriction = tt->restriction + tt->state; | ||
148 | return restriction->tx_stream; | ||
149 | } | ||
150 | |||
151 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) | ||
152 | { | ||
153 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
154 | struct iwl_tt_restriction *restriction; | ||
155 | |||
156 | if (!priv->thermal_throttle.advanced_tt) | ||
157 | return IWL_ANT_OK_MULTI; | ||
158 | restriction = tt->restriction + tt->state; | ||
159 | return restriction->rx_stream; | ||
160 | } | ||
161 | |||
162 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ | ||
163 | #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ | ||
164 | |||
165 | /* | ||
166 | * toggle the bit to wake up uCode and check the temperature | ||
167 | * if the temperature is below CT, uCode will stay awake and send card | ||
168 | * state notification with CT_KILL bit clear to inform Thermal Throttling | ||
169 | * Management to change state. Otherwise, uCode will go back to sleep | ||
170 | * without doing anything, driver should continue the 5 seconds timer | ||
171 | * to wake up uCode for temperature check until temperature drop below CT | ||
172 | */ | ||
173 | static void iwl_tt_check_exit_ct_kill(unsigned long data) | ||
174 | { | ||
175 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
176 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
177 | unsigned long flags; | ||
178 | |||
179 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
180 | return; | ||
181 | |||
182 | if (tt->state == IWL_TI_CT_KILL) { | ||
183 | if (priv->thermal_throttle.ct_kill_toggle) { | ||
184 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
185 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
186 | priv->thermal_throttle.ct_kill_toggle = false; | ||
187 | } else { | ||
188 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
189 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
190 | priv->thermal_throttle.ct_kill_toggle = true; | ||
191 | } | ||
192 | iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
193 | spin_lock_irqsave(&priv->reg_lock, flags); | ||
194 | if (!iwl_grab_nic_access(priv)) | ||
195 | iwl_release_nic_access(priv); | ||
196 | spin_unlock_irqrestore(&priv->reg_lock, flags); | ||
197 | |||
198 | /* Reschedule the ct_kill timer to occur in | ||
199 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | ||
200 | * thermal update */ | ||
201 | IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); | ||
202 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, | ||
203 | jiffies + CT_KILL_EXIT_DURATION * HZ); | ||
204 | } | ||
205 | } | ||
206 | |||
207 | static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | ||
208 | bool stop) | ||
209 | { | ||
210 | if (stop) { | ||
211 | IWL_DEBUG_POWER(priv, "Stop all queues\n"); | ||
212 | if (priv->mac80211_registered) | ||
213 | ieee80211_stop_queues(priv->hw); | ||
214 | IWL_DEBUG_POWER(priv, | ||
215 | "Schedule 5 seconds CT_KILL Timer\n"); | ||
216 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, | ||
217 | jiffies + CT_KILL_EXIT_DURATION * HZ); | ||
218 | } else { | ||
219 | IWL_DEBUG_POWER(priv, "Wake all queues\n"); | ||
220 | if (priv->mac80211_registered) | ||
221 | ieee80211_wake_queues(priv->hw); | ||
222 | } | ||
223 | } | ||
224 | |||
225 | static void iwl_tt_ready_for_ct_kill(unsigned long data) | ||
226 | { | ||
227 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
228 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
229 | |||
230 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
231 | return; | ||
232 | |||
233 | /* temperature timer expired, ready to go into CT_KILL state */ | ||
234 | if (tt->state != IWL_TI_CT_KILL) { | ||
235 | IWL_DEBUG_POWER(priv, "entering CT_KILL state when " | ||
236 | "temperature timer expired\n"); | ||
237 | tt->state = IWL_TI_CT_KILL; | ||
238 | set_bit(STATUS_CT_KILL, &priv->status); | ||
239 | iwl_perform_ct_kill_task(priv, true); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | ||
244 | { | ||
245 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | ||
246 | /* make request to retrieve statistics information */ | ||
247 | iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
248 | /* Reschedule the ct_kill wait timer */ | ||
249 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | ||
250 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | ||
251 | } | ||
252 | |||
253 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) | ||
254 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) | ||
255 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) | ||
256 | |||
257 | /* | ||
258 | * Legacy thermal throttling | ||
259 | * 1) Avoid NIC destruction due to high temperatures | ||
260 | * Chip will identify dangerously high temperatures that can | ||
261 | * harm the device and will power down | ||
262 | * 2) Avoid the NIC power down due to high temperature | ||
263 | * Throttle early enough to lower the power consumption before | ||
264 | * drastic steps are needed | ||
265 | */ | ||
266 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
267 | { | ||
268 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
269 | enum iwl_tt_state old_state; | ||
270 | |||
271 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
272 | if ((tt->tt_previous_temp) && | ||
273 | (temp > tt->tt_previous_temp) && | ||
274 | ((temp - tt->tt_previous_temp) > | ||
275 | IWL_TT_INCREASE_MARGIN)) { | ||
276 | IWL_DEBUG_POWER(priv, | ||
277 | "Temperature increase %d degree Celsius\n", | ||
278 | (temp - tt->tt_previous_temp)); | ||
279 | } | ||
280 | #endif | ||
281 | old_state = tt->state; | ||
282 | /* in Celsius */ | ||
283 | if (temp >= IWL_MINIMAL_POWER_THRESHOLD) | ||
284 | tt->state = IWL_TI_CT_KILL; | ||
285 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) | ||
286 | tt->state = IWL_TI_2; | ||
287 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) | ||
288 | tt->state = IWL_TI_1; | ||
289 | else | ||
290 | tt->state = IWL_TI_0; | ||
291 | |||
292 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
293 | tt->tt_previous_temp = temp; | ||
294 | #endif | ||
295 | /* stop ct_kill_waiting_tm timer */ | ||
296 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
297 | if (tt->state != old_state) { | ||
298 | switch (tt->state) { | ||
299 | case IWL_TI_0: | ||
300 | /* | ||
301 | * When the system is ready to go back to IWL_TI_0 | ||
302 | * we only have to call iwl_power_update_mode() to | ||
303 | * do so. | ||
304 | */ | ||
305 | break; | ||
306 | case IWL_TI_1: | ||
307 | tt->tt_power_mode = IWL_POWER_INDEX_3; | ||
308 | break; | ||
309 | case IWL_TI_2: | ||
310 | tt->tt_power_mode = IWL_POWER_INDEX_4; | ||
311 | break; | ||
312 | default: | ||
313 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
314 | break; | ||
315 | } | ||
316 | mutex_lock(&priv->mutex); | ||
317 | if (old_state == IWL_TI_CT_KILL) | ||
318 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
319 | if (tt->state != IWL_TI_CT_KILL && | ||
320 | iwl_power_update_mode(priv, true)) { | ||
321 | /* TT state not updated | ||
322 | * try again during next temperature read | ||
323 | */ | ||
324 | if (old_state == IWL_TI_CT_KILL) | ||
325 | set_bit(STATUS_CT_KILL, &priv->status); | ||
326 | tt->state = old_state; | ||
327 | IWL_ERR(priv, "Cannot update power mode, " | ||
328 | "TT state not updated\n"); | ||
329 | } else { | ||
330 | if (tt->state == IWL_TI_CT_KILL) { | ||
331 | if (force) { | ||
332 | set_bit(STATUS_CT_KILL, &priv->status); | ||
333 | iwl_perform_ct_kill_task(priv, true); | ||
334 | } else { | ||
335 | iwl_prepare_ct_kill_task(priv); | ||
336 | tt->state = old_state; | ||
337 | } | ||
338 | } else if (old_state == IWL_TI_CT_KILL && | ||
339 | tt->state != IWL_TI_CT_KILL) | ||
340 | iwl_perform_ct_kill_task(priv, false); | ||
341 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", | ||
342 | tt->state); | ||
343 | IWL_DEBUG_POWER(priv, "Power Index change to %u\n", | ||
344 | tt->tt_power_mode); | ||
345 | } | ||
346 | mutex_unlock(&priv->mutex); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | /* | ||
351 | * Advance thermal throttling | ||
352 | * 1) Avoid NIC destruction due to high temperatures | ||
353 | * Chip will identify dangerously high temperatures that can | ||
354 | * harm the device and will power down | ||
355 | * 2) Avoid the NIC power down due to high temperature | ||
356 | * Throttle early enough to lower the power consumption before | ||
357 | * drastic steps are needed | ||
358 | * Actions include relaxing the power down sleep thresholds and | ||
359 | * decreasing the number of TX streams | ||
360 | * 3) Avoid throughput performance impact as much as possible | ||
361 | * | ||
362 | *============================================================================= | ||
363 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
364 | *----------------------------------------------------------------------------- | ||
365 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
366 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
367 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
368 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
369 | *============================================================================= | ||
370 | */ | ||
371 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
372 | { | ||
373 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
374 | int i; | ||
375 | bool changed = false; | ||
376 | enum iwl_tt_state old_state; | ||
377 | struct iwl_tt_trans *transaction; | ||
378 | |||
379 | old_state = tt->state; | ||
380 | for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { | ||
381 | /* based on the current TT state, | ||
382 | * find the curresponding transaction table | ||
383 | * each table has (IWL_TI_STATE_MAX - 1) entries | ||
384 | * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) | ||
385 | * will advance to the correct table. | ||
386 | * then based on the current temperature | ||
387 | * find the next state need to transaction to | ||
388 | * go through all the possible (IWL_TI_STATE_MAX - 1) entries | ||
389 | * in the current table to see if transaction is needed | ||
390 | */ | ||
391 | transaction = tt->transaction + | ||
392 | ((old_state * (IWL_TI_STATE_MAX - 1)) + i); | ||
393 | if (temp >= transaction->tt_low && | ||
394 | temp <= transaction->tt_high) { | ||
395 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
396 | if ((tt->tt_previous_temp) && | ||
397 | (temp > tt->tt_previous_temp) && | ||
398 | ((temp - tt->tt_previous_temp) > | ||
399 | IWL_TT_INCREASE_MARGIN)) { | ||
400 | IWL_DEBUG_POWER(priv, | ||
401 | "Temperature increase %d " | ||
402 | "degree Celsius\n", | ||
403 | (temp - tt->tt_previous_temp)); | ||
404 | } | ||
405 | tt->tt_previous_temp = temp; | ||
406 | #endif | ||
407 | if (old_state != | ||
408 | transaction->next_state) { | ||
409 | changed = true; | ||
410 | tt->state = | ||
411 | transaction->next_state; | ||
412 | } | ||
413 | break; | ||
414 | } | ||
415 | } | ||
416 | /* stop ct_kill_waiting_tm timer */ | ||
417 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
418 | if (changed) { | ||
419 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | ||
420 | |||
421 | if (tt->state >= IWL_TI_1) { | ||
422 | /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ | ||
423 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
424 | if (!iwl_ht_enabled(priv)) | ||
425 | /* disable HT */ | ||
426 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
427 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
428 | RXON_FLG_HT40_PROT_MSK | | ||
429 | RXON_FLG_HT_PROT_MSK); | ||
430 | else { | ||
431 | /* check HT capability and set | ||
432 | * according to the system HT capability | ||
433 | * in case get disabled before */ | ||
434 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
435 | } | ||
436 | |||
437 | } else { | ||
438 | /* | ||
439 | * restore system power setting -- it will be | ||
440 | * recalculated automatically. | ||
441 | */ | ||
442 | |||
443 | /* check HT capability and set | ||
444 | * according to the system HT capability | ||
445 | * in case get disabled before */ | ||
446 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
447 | } | ||
448 | mutex_lock(&priv->mutex); | ||
449 | if (old_state == IWL_TI_CT_KILL) | ||
450 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
451 | if (tt->state != IWL_TI_CT_KILL && | ||
452 | iwl_power_update_mode(priv, true)) { | ||
453 | /* TT state not updated | ||
454 | * try again during next temperature read | ||
455 | */ | ||
456 | IWL_ERR(priv, "Cannot update power mode, " | ||
457 | "TT state not updated\n"); | ||
458 | if (old_state == IWL_TI_CT_KILL) | ||
459 | set_bit(STATUS_CT_KILL, &priv->status); | ||
460 | tt->state = old_state; | ||
461 | } else { | ||
462 | IWL_DEBUG_POWER(priv, | ||
463 | "Thermal Throttling to new state: %u\n", | ||
464 | tt->state); | ||
465 | if (old_state != IWL_TI_CT_KILL && | ||
466 | tt->state == IWL_TI_CT_KILL) { | ||
467 | if (force) { | ||
468 | IWL_DEBUG_POWER(priv, | ||
469 | "Enter IWL_TI_CT_KILL\n"); | ||
470 | set_bit(STATUS_CT_KILL, &priv->status); | ||
471 | iwl_perform_ct_kill_task(priv, true); | ||
472 | } else { | ||
473 | iwl_prepare_ct_kill_task(priv); | ||
474 | tt->state = old_state; | ||
475 | } | ||
476 | } else if (old_state == IWL_TI_CT_KILL && | ||
477 | tt->state != IWL_TI_CT_KILL) { | ||
478 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); | ||
479 | iwl_perform_ct_kill_task(priv, false); | ||
480 | } | ||
481 | } | ||
482 | mutex_unlock(&priv->mutex); | ||
483 | } | ||
484 | } | ||
485 | |||
486 | /* Card State Notification indicated reach critical temperature | ||
487 | * if PSP not enable, no Thermal Throttling function will be performed | ||
488 | * just set the GP1 bit to acknowledge the event | ||
489 | * otherwise, go into IWL_TI_CT_KILL state | ||
490 | * since Card State Notification will not provide any temperature reading | ||
491 | * for Legacy mode | ||
492 | * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() | ||
493 | * for advance mode | ||
494 | * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state | ||
495 | */ | ||
496 | static void iwl_bg_ct_enter(struct work_struct *work) | ||
497 | { | ||
498 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); | ||
499 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
500 | |||
501 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
502 | return; | ||
503 | |||
504 | if (!iwl_is_ready(priv)) | ||
505 | return; | ||
506 | |||
507 | if (tt->state != IWL_TI_CT_KILL) { | ||
508 | IWL_ERR(priv, "Device reached critical temperature " | ||
509 | "- ucode going to sleep!\n"); | ||
510 | if (!priv->thermal_throttle.advanced_tt) | ||
511 | iwl_legacy_tt_handler(priv, | ||
512 | IWL_MINIMAL_POWER_THRESHOLD, | ||
513 | true); | ||
514 | else | ||
515 | iwl_advance_tt_handler(priv, | ||
516 | CT_KILL_THRESHOLD + 1, true); | ||
517 | } | ||
518 | } | ||
519 | |||
520 | /* Card State Notification indicated out of critical temperature | ||
521 | * since Card State Notification will not provide any temperature reading | ||
522 | * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature | ||
523 | * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state | ||
524 | */ | ||
525 | static void iwl_bg_ct_exit(struct work_struct *work) | ||
526 | { | ||
527 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); | ||
528 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
529 | |||
530 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
531 | return; | ||
532 | |||
533 | if (!iwl_is_ready(priv)) | ||
534 | return; | ||
535 | |||
536 | /* stop ct_kill_exit_tm timer */ | ||
537 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
538 | |||
539 | if (tt->state == IWL_TI_CT_KILL) { | ||
540 | IWL_ERR(priv, | ||
541 | "Device temperature below critical" | ||
542 | "- ucode awake!\n"); | ||
543 | /* | ||
544 | * exit from CT_KILL state | ||
545 | * reset the current temperature reading | ||
546 | */ | ||
547 | priv->temperature = 0; | ||
548 | if (!priv->thermal_throttle.advanced_tt) | ||
549 | iwl_legacy_tt_handler(priv, | ||
550 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2, | ||
551 | true); | ||
552 | else | ||
553 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, | ||
554 | true); | ||
555 | } | ||
556 | } | ||
557 | |||
558 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv) | ||
559 | { | ||
560 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
561 | return; | ||
562 | |||
563 | IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); | ||
564 | queue_work(priv->workqueue, &priv->ct_enter); | ||
565 | } | ||
566 | EXPORT_SYMBOL(iwl_tt_enter_ct_kill); | ||
567 | |||
568 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv) | ||
569 | { | ||
570 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
571 | return; | ||
572 | |||
573 | IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); | ||
574 | queue_work(priv->workqueue, &priv->ct_exit); | ||
575 | } | ||
576 | EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | ||
577 | |||
578 | static void iwl_bg_tt_work(struct work_struct *work) | ||
579 | { | ||
580 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | ||
581 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
582 | |||
583 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
584 | return; | ||
585 | |||
586 | if (priv->cfg->temperature_kelvin) | ||
587 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
588 | |||
589 | if (!priv->thermal_throttle.advanced_tt) | ||
590 | iwl_legacy_tt_handler(priv, temp, false); | ||
591 | else | ||
592 | iwl_advance_tt_handler(priv, temp, false); | ||
593 | } | ||
594 | |||
595 | void iwl_tt_handler(struct iwl_priv *priv) | ||
596 | { | ||
597 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
598 | return; | ||
599 | |||
600 | IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); | ||
601 | queue_work(priv->workqueue, &priv->tt_work); | ||
602 | } | ||
603 | EXPORT_SYMBOL(iwl_tt_handler); | ||
604 | |||
605 | /* Thermal throttling initialization | ||
606 | * For advance thermal throttling: | ||
607 | * Initialize Thermal Index and temperature threshold table | ||
608 | * Initialize thermal throttling restriction table | ||
609 | */ | ||
610 | void iwl_tt_initialize(struct iwl_priv *priv) | ||
611 | { | ||
612 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
613 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | ||
614 | struct iwl_tt_trans *transaction; | ||
615 | |||
616 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); | ||
617 | |||
618 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | ||
619 | |||
620 | tt->state = IWL_TI_0; | ||
621 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); | ||
622 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; | ||
623 | priv->thermal_throttle.ct_kill_exit_tm.function = | ||
624 | iwl_tt_check_exit_ct_kill; | ||
625 | init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
626 | priv->thermal_throttle.ct_kill_waiting_tm.data = | ||
627 | (unsigned long)priv; | ||
628 | priv->thermal_throttle.ct_kill_waiting_tm.function = | ||
629 | iwl_tt_ready_for_ct_kill; | ||
630 | /* setup deferred ct kill work */ | ||
631 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); | ||
632 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | ||
633 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | ||
634 | |||
635 | if (priv->cfg->adv_thermal_throttle) { | ||
636 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | ||
637 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | ||
638 | IWL_TI_STATE_MAX, GFP_KERNEL); | ||
639 | tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * | ||
640 | IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), | ||
641 | GFP_KERNEL); | ||
642 | if (!tt->restriction || !tt->transaction) { | ||
643 | IWL_ERR(priv, "Fallback to Legacy Throttling\n"); | ||
644 | priv->thermal_throttle.advanced_tt = false; | ||
645 | kfree(tt->restriction); | ||
646 | tt->restriction = NULL; | ||
647 | kfree(tt->transaction); | ||
648 | tt->transaction = NULL; | ||
649 | } else { | ||
650 | transaction = tt->transaction + | ||
651 | (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); | ||
652 | memcpy(transaction, &tt_range_0[0], size); | ||
653 | transaction = tt->transaction + | ||
654 | (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); | ||
655 | memcpy(transaction, &tt_range_1[0], size); | ||
656 | transaction = tt->transaction + | ||
657 | (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); | ||
658 | memcpy(transaction, &tt_range_2[0], size); | ||
659 | transaction = tt->transaction + | ||
660 | (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); | ||
661 | memcpy(transaction, &tt_range_3[0], size); | ||
662 | size = sizeof(struct iwl_tt_restriction) * | ||
663 | IWL_TI_STATE_MAX; | ||
664 | memcpy(tt->restriction, | ||
665 | &restriction_range[0], size); | ||
666 | priv->thermal_throttle.advanced_tt = true; | ||
667 | } | ||
668 | } else { | ||
669 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); | ||
670 | priv->thermal_throttle.advanced_tt = false; | ||
671 | } | ||
672 | } | ||
673 | EXPORT_SYMBOL(iwl_tt_initialize); | ||
674 | |||
675 | /* cleanup thermal throttling management related memory and timer */ | ||
676 | void iwl_tt_exit(struct iwl_priv *priv) | ||
677 | { | ||
678 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
679 | |||
680 | /* stop ct_kill_exit_tm timer if activated */ | ||
681 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
682 | /* stop ct_kill_waiting_tm timer if activated */ | ||
683 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
684 | cancel_work_sync(&priv->tt_work); | ||
685 | cancel_work_sync(&priv->ct_enter); | ||
686 | cancel_work_sync(&priv->ct_exit); | ||
687 | |||
688 | if (priv->thermal_throttle.advanced_tt) { | ||
689 | /* free advance thermal throttling memory */ | ||
690 | kfree(tt->restriction); | ||
691 | tt->restriction = NULL; | ||
692 | kfree(tt->transaction); | ||
693 | tt->transaction = NULL; | ||
694 | } | ||
695 | } | ||
696 | EXPORT_SYMBOL(iwl_tt_exit); | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tt.h b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h new file mode 100644 index 000000000000..d55060427cac --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tt.h | |||
@@ -0,0 +1,129 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2007 - 2010 Intel Corporation. All rights reserved. | ||
4 | * | ||
5 | * Portions of this file are derived from the ipw3945 project, as well | ||
6 | * as portions of the ieee80211 subsystem header files. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of version 2 of the GNU General Public License as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
13 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
14 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
15 | * more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License along with | ||
18 | * this program; if not, write to the Free Software Foundation, Inc., | ||
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
20 | * | ||
21 | * The full GNU General Public License is included in this distribution in the | ||
22 | * file called LICENSE. | ||
23 | * | ||
24 | * Contact Information: | ||
25 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
26 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
27 | *****************************************************************************/ | ||
28 | #ifndef __iwl_tt_setting_h__ | ||
29 | #define __iwl_tt_setting_h__ | ||
30 | |||
31 | #include "iwl-commands.h" | ||
32 | |||
33 | #define IWL_ABSOLUTE_ZERO 0 | ||
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | ||
35 | #define IWL_TT_INCREASE_MARGIN 5 | ||
36 | #define IWL_TT_CT_KILL_MARGIN 3 | ||
37 | |||
38 | enum iwl_antenna_ok { | ||
39 | IWL_ANT_OK_NONE, | ||
40 | IWL_ANT_OK_SINGLE, | ||
41 | IWL_ANT_OK_MULTI, | ||
42 | }; | ||
43 | |||
44 | /* Thermal Throttling State Machine states */ | ||
45 | enum iwl_tt_state { | ||
46 | IWL_TI_0, /* normal temperature, system power state */ | ||
47 | IWL_TI_1, /* high temperature detect, low power state */ | ||
48 | IWL_TI_2, /* higher temperature detected, lower power state */ | ||
49 | IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ | ||
50 | IWL_TI_STATE_MAX | ||
51 | }; | ||
52 | |||
53 | /** | ||
54 | * struct iwl_tt_restriction - Thermal Throttling restriction table | ||
55 | * @tx_stream: number of tx stream allowed | ||
56 | * @is_ht: ht enable/disable | ||
57 | * @rx_stream: number of rx stream allowed | ||
58 | * | ||
59 | * This table is used by advance thermal throttling management | ||
60 | * based on the current thermal throttling state, and determines | ||
61 | * the number of tx/rx streams and the status of HT operation. | ||
62 | */ | ||
63 | struct iwl_tt_restriction { | ||
64 | enum iwl_antenna_ok tx_stream; | ||
65 | enum iwl_antenna_ok rx_stream; | ||
66 | bool is_ht; | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * struct iwl_tt_trans - Thermal Throttling transaction table | ||
71 | * @next_state: next thermal throttling mode | ||
72 | * @tt_low: low temperature threshold to change state | ||
73 | * @tt_high: high temperature threshold to change state | ||
74 | * | ||
75 | * This is used by the advanced thermal throttling algorithm | ||
76 | * to determine the next thermal state to go based on the | ||
77 | * current temperature. | ||
78 | */ | ||
79 | struct iwl_tt_trans { | ||
80 | enum iwl_tt_state next_state; | ||
81 | u32 tt_low; | ||
82 | u32 tt_high; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * struct iwl_tt_mgnt - Thermal Throttling Management structure | ||
87 | * @advanced_tt: advanced thermal throttle required | ||
88 | * @state: current Thermal Throttling state | ||
89 | * @tt_power_mode: Thermal Throttling power mode index | ||
90 | * being used to set power level when | ||
91 | * when thermal throttling state != IWL_TI_0 | ||
92 | * the tt_power_mode should set to different | ||
93 | * power mode based on the current tt state | ||
94 | * @tt_previous_temperature: last measured temperature | ||
95 | * @iwl_tt_restriction: ptr to restriction tbl, used by advance | ||
96 | * thermal throttling to determine how many tx/rx streams | ||
97 | * should be used in tt state; and can HT be enabled or not | ||
98 | * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling | ||
99 | * state transaction | ||
100 | * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature | ||
101 | * @ct_kill_exit_tm: timer to exit thermal kill | ||
102 | */ | ||
103 | struct iwl_tt_mgmt { | ||
104 | enum iwl_tt_state state; | ||
105 | bool advanced_tt; | ||
106 | u8 tt_power_mode; | ||
107 | bool ct_kill_toggle; | ||
108 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
109 | s32 tt_previous_temp; | ||
110 | #endif | ||
111 | struct iwl_tt_restriction *restriction; | ||
112 | struct iwl_tt_trans *transaction; | ||
113 | struct timer_list ct_kill_exit_tm; | ||
114 | struct timer_list ct_kill_waiting_tm; | ||
115 | }; | ||
116 | |||
117 | u8 iwl_tt_current_power_mode(struct iwl_priv *priv); | ||
118 | bool iwl_tt_is_low_power_state(struct iwl_priv *priv); | ||
119 | bool iwl_ht_enabled(struct iwl_priv *priv); | ||
120 | bool iwl_check_for_ct_kill(struct iwl_priv *priv); | ||
121 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | ||
122 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | ||
123 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | ||
124 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv); | ||
125 | void iwl_tt_handler(struct iwl_priv *priv); | ||
126 | void iwl_tt_initialize(struct iwl_priv *priv); | ||
127 | void iwl_tt_exit(struct iwl_priv *priv); | ||
128 | |||
129 | #endif /* __iwl_tt_setting_h__ */ | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 69155aa448fb..3fc982e87921 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -470,8 +470,8 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
470 | { | 470 | { |
471 | struct ieee80211_key_conf *keyconf = info->control.hw_key; | 471 | struct ieee80211_key_conf *keyconf = info->control.hw_key; |
472 | 472 | ||
473 | switch (keyconf->alg) { | 473 | switch (keyconf->cipher) { |
474 | case ALG_CCMP: | 474 | case WLAN_CIPHER_SUITE_CCMP: |
475 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | 475 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; |
476 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); | 476 | memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); |
477 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 477 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
@@ -479,20 +479,20 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
479 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | 479 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); |
480 | break; | 480 | break; |
481 | 481 | ||
482 | case ALG_TKIP: | 482 | case WLAN_CIPHER_SUITE_TKIP: |
483 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; | 483 | tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; |
484 | ieee80211_get_tkip_key(keyconf, skb_frag, | 484 | ieee80211_get_tkip_key(keyconf, skb_frag, |
485 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); | 485 | IEEE80211_TKIP_P2_KEY, tx_cmd->key); |
486 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); | 486 | IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); |
487 | break; | 487 | break; |
488 | 488 | ||
489 | case ALG_WEP: | 489 | case WLAN_CIPHER_SUITE_WEP104: |
490 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
491 | /* fall through */ | ||
492 | case WLAN_CIPHER_SUITE_WEP40: | ||
490 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | | 493 | tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | |
491 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); | 494 | (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); |
492 | 495 | ||
493 | if (keyconf->keylen == WEP_KEY_LEN_128) | ||
494 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
495 | |||
496 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); | 496 | memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); |
497 | 497 | ||
498 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | 498 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " |
@@ -500,7 +500,7 @@ static void iwlagn_tx_cmd_build_hwcrypto(struct iwl_priv *priv, | |||
500 | break; | 500 | break; |
501 | 501 | ||
502 | default: | 502 | default: |
503 | IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); | 503 | IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher); |
504 | break; | 504 | break; |
505 | } | 505 | } |
506 | } | 506 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 10d7b9b7f064..3ced9ea9c5fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci-aspm.h> | ||
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
@@ -763,10 +764,10 @@ static void iwl_bg_ucode_trace(unsigned long data) | |||
763 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 764 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
764 | struct iwl_rx_mem_buffer *rxb) | 765 | struct iwl_rx_mem_buffer *rxb) |
765 | { | 766 | { |
766 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
767 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 767 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
768 | struct iwl4965_beacon_notif *beacon = | 768 | struct iwl4965_beacon_notif *beacon = |
769 | (struct iwl4965_beacon_notif *)pkt->u.raw; | 769 | (struct iwl4965_beacon_notif *)pkt->u.raw; |
770 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
770 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); | 771 | u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); |
771 | 772 | ||
772 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " | 773 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " |
@@ -778,6 +779,8 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv, | |||
778 | le32_to_cpu(beacon->low_tsf), rate); | 779 | le32_to_cpu(beacon->low_tsf), rate); |
779 | #endif | 780 | #endif |
780 | 781 | ||
782 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
783 | |||
781 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && | 784 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && |
782 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) | 785 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) |
783 | queue_work(priv->workqueue, &priv->beacon_update); | 786 | queue_work(priv->workqueue, &priv->beacon_update); |
@@ -1656,24 +1659,37 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); | |||
1656 | static int iwl_mac_setup_register(struct iwl_priv *priv, | 1659 | static int iwl_mac_setup_register(struct iwl_priv *priv, |
1657 | struct iwlagn_ucode_capabilities *capa); | 1660 | struct iwlagn_ucode_capabilities *capa); |
1658 | 1661 | ||
1662 | #define UCODE_EXPERIMENTAL_INDEX 100 | ||
1663 | #define UCODE_EXPERIMENTAL_TAG "exp" | ||
1664 | |||
1659 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) | 1665 | static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) |
1660 | { | 1666 | { |
1661 | const char *name_pre = priv->cfg->fw_name_pre; | 1667 | const char *name_pre = priv->cfg->fw_name_pre; |
1668 | char tag[8]; | ||
1662 | 1669 | ||
1663 | if (first) | 1670 | if (first) { |
1671 | #ifdef CONFIG_IWLWIFI_DEBUG_EXPERIMENTAL_UCODE | ||
1672 | priv->fw_index = UCODE_EXPERIMENTAL_INDEX; | ||
1673 | strcpy(tag, UCODE_EXPERIMENTAL_TAG); | ||
1674 | } else if (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) { | ||
1675 | #endif | ||
1664 | priv->fw_index = priv->cfg->ucode_api_max; | 1676 | priv->fw_index = priv->cfg->ucode_api_max; |
1665 | else | 1677 | sprintf(tag, "%d", priv->fw_index); |
1678 | } else { | ||
1666 | priv->fw_index--; | 1679 | priv->fw_index--; |
1680 | sprintf(tag, "%d", priv->fw_index); | ||
1681 | } | ||
1667 | 1682 | ||
1668 | if (priv->fw_index < priv->cfg->ucode_api_min) { | 1683 | if (priv->fw_index < priv->cfg->ucode_api_min) { |
1669 | IWL_ERR(priv, "no suitable firmware found!\n"); | 1684 | IWL_ERR(priv, "no suitable firmware found!\n"); |
1670 | return -ENOENT; | 1685 | return -ENOENT; |
1671 | } | 1686 | } |
1672 | 1687 | ||
1673 | sprintf(priv->firmware_name, "%s%d%s", | 1688 | sprintf(priv->firmware_name, "%s%s%s", name_pre, tag, ".ucode"); |
1674 | name_pre, priv->fw_index, ".ucode"); | ||
1675 | 1689 | ||
1676 | IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", | 1690 | IWL_DEBUG_INFO(priv, "attempting to load firmware %s'%s'\n", |
1691 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
1692 | ? "EXPERIMENTAL " : "", | ||
1677 | priv->firmware_name); | 1693 | priv->firmware_name); |
1678 | 1694 | ||
1679 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, | 1695 | return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, |
@@ -1968,8 +1984,10 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
1968 | memset(&pieces, 0, sizeof(pieces)); | 1984 | memset(&pieces, 0, sizeof(pieces)); |
1969 | 1985 | ||
1970 | if (!ucode_raw) { | 1986 | if (!ucode_raw) { |
1971 | IWL_ERR(priv, "request for firmware file '%s' failed.\n", | 1987 | if (priv->fw_index <= priv->cfg->ucode_api_max) |
1972 | priv->firmware_name); | 1988 | IWL_ERR(priv, |
1989 | "request for firmware file '%s' failed.\n", | ||
1990 | priv->firmware_name); | ||
1973 | goto try_again; | 1991 | goto try_again; |
1974 | } | 1992 | } |
1975 | 1993 | ||
@@ -2016,7 +2034,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) | |||
2016 | api_max, api_ver); | 2034 | api_max, api_ver); |
2017 | 2035 | ||
2018 | if (build) | 2036 | if (build) |
2019 | sprintf(buildstr, " build %u", build); | 2037 | sprintf(buildstr, " build %u%s", build, |
2038 | (priv->fw_index == UCODE_EXPERIMENTAL_INDEX) | ||
2039 | ? " (EXP)" : ""); | ||
2020 | else | 2040 | else |
2021 | buildstr[0] = '\0'; | 2041 | buildstr[0] = '\0'; |
2022 | 2042 | ||
@@ -2589,6 +2609,52 @@ int iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log, | |||
2589 | return pos; | 2609 | return pos; |
2590 | } | 2610 | } |
2591 | 2611 | ||
2612 | static void iwl_rf_kill_ct_config(struct iwl_priv *priv) | ||
2613 | { | ||
2614 | struct iwl_ct_kill_config cmd; | ||
2615 | struct iwl_ct_kill_throttling_config adv_cmd; | ||
2616 | unsigned long flags; | ||
2617 | int ret = 0; | ||
2618 | |||
2619 | spin_lock_irqsave(&priv->lock, flags); | ||
2620 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
2621 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
2622 | spin_unlock_irqrestore(&priv->lock, flags); | ||
2623 | priv->thermal_throttle.ct_kill_toggle = false; | ||
2624 | |||
2625 | if (priv->cfg->support_ct_kill_exit) { | ||
2626 | adv_cmd.critical_temperature_enter = | ||
2627 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
2628 | adv_cmd.critical_temperature_exit = | ||
2629 | cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); | ||
2630 | |||
2631 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
2632 | sizeof(adv_cmd), &adv_cmd); | ||
2633 | if (ret) | ||
2634 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
2635 | else | ||
2636 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
2637 | "succeeded, " | ||
2638 | "critical temperature enter is %d," | ||
2639 | "exit is %d\n", | ||
2640 | priv->hw_params.ct_kill_threshold, | ||
2641 | priv->hw_params.ct_kill_exit_threshold); | ||
2642 | } else { | ||
2643 | cmd.critical_temperature_R = | ||
2644 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
2645 | |||
2646 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
2647 | sizeof(cmd), &cmd); | ||
2648 | if (ret) | ||
2649 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
2650 | else | ||
2651 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
2652 | "succeeded, " | ||
2653 | "critical temperature is %d\n", | ||
2654 | priv->hw_params.ct_kill_threshold); | ||
2655 | } | ||
2656 | } | ||
2657 | |||
2592 | /** | 2658 | /** |
2593 | * iwl_alive_start - called after REPLY_ALIVE notification received | 2659 | * iwl_alive_start - called after REPLY_ALIVE notification received |
2594 | * from protocol/runtime uCode (initialization uCode's | 2660 | * from protocol/runtime uCode (initialization uCode's |
@@ -3060,9 +3126,7 @@ void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3060 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3126 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3061 | iwlcore_commit_rxon(priv); | 3127 | iwlcore_commit_rxon(priv); |
3062 | 3128 | ||
3063 | iwl_setup_rxon_timing(priv, vif); | 3129 | ret = iwl_send_rxon_timing(priv, vif); |
3064 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3065 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
3066 | if (ret) | 3130 | if (ret) |
3067 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3131 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3068 | "Attempting to continue.\n"); | 3132 | "Attempting to continue.\n"); |
@@ -3298,9 +3362,7 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3298 | iwlcore_commit_rxon(priv); | 3362 | iwlcore_commit_rxon(priv); |
3299 | 3363 | ||
3300 | /* RXON Timing */ | 3364 | /* RXON Timing */ |
3301 | iwl_setup_rxon_timing(priv, vif); | 3365 | ret = iwl_send_rxon_timing(priv, vif); |
3302 | ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3303 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
3304 | if (ret) | 3366 | if (ret) |
3305 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3367 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3306 | "Attempting to continue.\n"); | 3368 | "Attempting to continue.\n"); |
@@ -3386,7 +3448,9 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3386 | * in 1X mode. | 3448 | * in 1X mode. |
3387 | * In legacy wep mode, we use another host command to the uCode. | 3449 | * In legacy wep mode, we use another host command to the uCode. |
3388 | */ | 3450 | */ |
3389 | if (key->alg == ALG_WEP && !sta && vif->type != NL80211_IFTYPE_AP) { | 3451 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
3452 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
3453 | !sta) { | ||
3390 | if (cmd == SET_KEY) | 3454 | if (cmd == SET_KEY) |
3391 | is_default_wep_key = !priv->key_mapping_key; | 3455 | is_default_wep_key = !priv->key_mapping_key; |
3392 | else | 3456 | else |
@@ -3581,6 +3645,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3581 | struct iwl_priv *priv = hw->priv; | 3645 | struct iwl_priv *priv = hw->priv; |
3582 | const struct iwl_channel_info *ch_info; | 3646 | const struct iwl_channel_info *ch_info; |
3583 | struct ieee80211_conf *conf = &hw->conf; | 3647 | struct ieee80211_conf *conf = &hw->conf; |
3648 | struct ieee80211_channel *channel = ch_switch->channel; | ||
3584 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 3649 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
3585 | u16 ch; | 3650 | u16 ch; |
3586 | unsigned long flags = 0; | 3651 | unsigned long flags = 0; |
@@ -3604,11 +3669,10 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3604 | mutex_lock(&priv->mutex); | 3669 | mutex_lock(&priv->mutex); |
3605 | if (priv->cfg->ops->lib->set_channel_switch) { | 3670 | if (priv->cfg->ops->lib->set_channel_switch) { |
3606 | 3671 | ||
3607 | ch = ieee80211_frequency_to_channel( | 3672 | ch = channel->hw_value; |
3608 | ch_switch->channel->center_freq); | ||
3609 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { | 3673 | if (le16_to_cpu(priv->active_rxon.channel) != ch) { |
3610 | ch_info = iwl_get_channel_info(priv, | 3674 | ch_info = iwl_get_channel_info(priv, |
3611 | conf->channel->band, | 3675 | channel->band, |
3612 | ch); | 3676 | ch); |
3613 | if (!is_channel_valid(ch_info)) { | 3677 | if (!is_channel_valid(ch_info)) { |
3614 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); | 3678 | IWL_DEBUG_MAC80211(priv, "invalid channel\n"); |
@@ -3637,15 +3701,12 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw, | |||
3637 | } else | 3701 | } else |
3638 | ht_conf->is_40mhz = false; | 3702 | ht_conf->is_40mhz = false; |
3639 | 3703 | ||
3640 | /* if we are switching from ht to 2.4 clear flags | 3704 | if (le16_to_cpu(priv->staging_rxon.channel) != ch) |
3641 | * from any ht related info since 2.4 does not | ||
3642 | * support ht */ | ||
3643 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | ||
3644 | priv->staging_rxon.flags = 0; | 3705 | priv->staging_rxon.flags = 0; |
3645 | 3706 | ||
3646 | iwl_set_rxon_channel(priv, conf->channel); | 3707 | iwl_set_rxon_channel(priv, channel); |
3647 | iwl_set_rxon_ht(priv, ht_conf); | 3708 | iwl_set_rxon_ht(priv, ht_conf); |
3648 | iwl_set_flags_for_band(priv, conf->channel->band, | 3709 | iwl_set_flags_for_band(priv, channel->band, |
3649 | priv->vif); | 3710 | priv->vif); |
3650 | spin_unlock_irqrestore(&priv->lock, flags); | 3711 | spin_unlock_irqrestore(&priv->lock, flags); |
3651 | 3712 | ||
@@ -3923,8 +3984,35 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3923 | .sta_remove = iwl_mac_sta_remove, | 3984 | .sta_remove = iwl_mac_sta_remove, |
3924 | .channel_switch = iwl_mac_channel_switch, | 3985 | .channel_switch = iwl_mac_channel_switch, |
3925 | .flush = iwl_mac_flush, | 3986 | .flush = iwl_mac_flush, |
3987 | .tx_last_beacon = iwl_mac_tx_last_beacon, | ||
3926 | }; | 3988 | }; |
3927 | 3989 | ||
3990 | static void iwl_hw_detect(struct iwl_priv *priv) | ||
3991 | { | ||
3992 | priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); | ||
3993 | priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); | ||
3994 | pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); | ||
3995 | IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id); | ||
3996 | } | ||
3997 | |||
3998 | static int iwl_set_hw_params(struct iwl_priv *priv) | ||
3999 | { | ||
4000 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
4001 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
4002 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
4003 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); | ||
4004 | else | ||
4005 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); | ||
4006 | |||
4007 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; | ||
4008 | |||
4009 | if (priv->cfg->mod_params->disable_11n) | ||
4010 | priv->cfg->sku &= ~IWL_SKU_N; | ||
4011 | |||
4012 | /* Device-specific setup */ | ||
4013 | return priv->cfg->ops->lib->set_hw_params(priv); | ||
4014 | } | ||
4015 | |||
3928 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 4016 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
3929 | { | 4017 | { |
3930 | int err = 0; | 4018 | int err = 0; |
@@ -3968,6 +4056,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3968 | /************************** | 4056 | /************************** |
3969 | * 2. Initializing PCI bus | 4057 | * 2. Initializing PCI bus |
3970 | **************************/ | 4058 | **************************/ |
4059 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
4060 | PCIE_LINK_STATE_CLKPM); | ||
4061 | |||
3971 | if (pci_enable_device(pdev)) { | 4062 | if (pci_enable_device(pdev)) { |
3972 | err = -ENODEV; | 4063 | err = -ENODEV; |
3973 | goto out_ieee80211_free_hw; | 4064 | goto out_ieee80211_free_hw; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 60725a5c1b69..4083e4430827 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1367,21 +1367,24 @@ struct iwl4965_rx_non_cfg_phy { | |||
1367 | } __packed; | 1367 | } __packed; |
1368 | 1368 | ||
1369 | 1369 | ||
1370 | #define IWL50_RX_RES_PHY_CNT 8 | 1370 | #define IWLAGN_RX_RES_PHY_CNT 8 |
1371 | #define IWL50_RX_RES_AGC_IDX 1 | 1371 | #define IWLAGN_RX_RES_AGC_IDX 1 |
1372 | #define IWL50_RX_RES_RSSI_AB_IDX 2 | 1372 | #define IWLAGN_RX_RES_RSSI_AB_IDX 2 |
1373 | #define IWL50_RX_RES_RSSI_C_IDX 3 | 1373 | #define IWLAGN_RX_RES_RSSI_C_IDX 3 |
1374 | #define IWL50_OFDM_AGC_MSK 0xfe00 | 1374 | #define IWLAGN_OFDM_AGC_MSK 0xfe00 |
1375 | #define IWL50_OFDM_AGC_BIT_POS 9 | 1375 | #define IWLAGN_OFDM_AGC_BIT_POS 9 |
1376 | #define IWL50_OFDM_RSSI_A_MSK 0x00ff | 1376 | #define IWLAGN_OFDM_RSSI_INBAND_A_BITMSK 0x00ff |
1377 | #define IWL50_OFDM_RSSI_A_BIT_POS 0 | 1377 | #define IWLAGN_OFDM_RSSI_ALLBAND_A_BITMSK 0xff00 |
1378 | #define IWL50_OFDM_RSSI_B_MSK 0xff0000 | 1378 | #define IWLAGN_OFDM_RSSI_A_BIT_POS 0 |
1379 | #define IWL50_OFDM_RSSI_B_BIT_POS 16 | 1379 | #define IWLAGN_OFDM_RSSI_INBAND_B_BITMSK 0xff0000 |
1380 | #define IWL50_OFDM_RSSI_C_MSK 0x00ff | 1380 | #define IWLAGN_OFDM_RSSI_ALLBAND_B_BITMSK 0xff000000 |
1381 | #define IWL50_OFDM_RSSI_C_BIT_POS 0 | 1381 | #define IWLAGN_OFDM_RSSI_B_BIT_POS 16 |
1382 | #define IWLAGN_OFDM_RSSI_INBAND_C_BITMSK 0x00ff | ||
1383 | #define IWLAGN_OFDM_RSSI_ALLBAND_C_BITMSK 0xff00 | ||
1384 | #define IWLAGN_OFDM_RSSI_C_BIT_POS 0 | ||
1382 | 1385 | ||
1383 | struct iwl5000_non_cfg_phy { | 1386 | struct iwlagn_non_cfg_phy { |
1384 | __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */ | 1387 | __le32 non_cfg_phy[IWLAGN_RX_RES_PHY_CNT]; /* up to 8 phy entries */ |
1385 | } __packed; | 1388 | } __packed; |
1386 | 1389 | ||
1387 | 1390 | ||
@@ -1401,7 +1404,7 @@ struct iwl_rx_phy_res { | |||
1401 | u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ | 1404 | u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ |
1402 | __le32 rate_n_flags; /* RATE_MCS_* */ | 1405 | __le32 rate_n_flags; /* RATE_MCS_* */ |
1403 | __le16 byte_count; /* frame's byte-count */ | 1406 | __le16 byte_count; /* frame's byte-count */ |
1404 | __le16 reserved3; | 1407 | __le16 frame_time; /* frame's time on the air */ |
1405 | } __packed; | 1408 | } __packed; |
1406 | 1409 | ||
1407 | struct iwl_rx_mpdu_res_start { | 1410 | struct iwl_rx_mpdu_res_start { |
@@ -2092,8 +2095,8 @@ struct iwl_link_qual_general_params { | |||
2092 | } __packed; | 2095 | } __packed; |
2093 | 2096 | ||
2094 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ | 2097 | #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ |
2095 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535) | 2098 | #define LINK_QUAL_AGG_TIME_LIMIT_MAX (8000) |
2096 | #define LINK_QUAL_AGG_TIME_LIMIT_MIN (0) | 2099 | #define LINK_QUAL_AGG_TIME_LIMIT_MIN (100) |
2097 | 2100 | ||
2098 | #define LINK_QUAL_AGG_DISABLE_START_DEF (3) | 2101 | #define LINK_QUAL_AGG_DISABLE_START_DEF (3) |
2099 | #define LINK_QUAL_AGG_DISABLE_START_MAX (255) | 2102 | #define LINK_QUAL_AGG_DISABLE_START_MAX (255) |
@@ -2110,8 +2113,10 @@ struct iwl_link_qual_general_params { | |||
2110 | */ | 2113 | */ |
2111 | struct iwl_link_qual_agg_params { | 2114 | struct iwl_link_qual_agg_params { |
2112 | 2115 | ||
2113 | /* Maximum number of uSec in aggregation. | 2116 | /* |
2114 | * Driver should set this to 4000 (4 milliseconds). */ | 2117 | *Maximum number of uSec in aggregation. |
2118 | * default set to 4000 (4 milliseconds) if not configured in .cfg | ||
2119 | */ | ||
2115 | __le16 agg_time_limit; | 2120 | __le16 agg_time_limit; |
2116 | 2121 | ||
2117 | /* | 2122 | /* |
@@ -2919,6 +2924,11 @@ struct iwl_scancomplete_notification { | |||
2919 | * | 2924 | * |
2920 | *****************************************************************************/ | 2925 | *****************************************************************************/ |
2921 | 2926 | ||
2927 | enum iwl_ibss_manager { | ||
2928 | IWL_NOT_IBSS_MANAGER = 0, | ||
2929 | IWL_IBSS_MANAGER = 1, | ||
2930 | }; | ||
2931 | |||
2922 | /* | 2932 | /* |
2923 | * BEACON_NOTIFICATION = 0x90 (notification only, not a command) | 2933 | * BEACON_NOTIFICATION = 0x90 (notification only, not a command) |
2924 | */ | 2934 | */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 07dbc2796448..3d9443b9bec1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -183,14 +183,6 @@ out: | |||
183 | } | 183 | } |
184 | EXPORT_SYMBOL(iwl_alloc_all); | 184 | EXPORT_SYMBOL(iwl_alloc_all); |
185 | 185 | ||
186 | void iwl_hw_detect(struct iwl_priv *priv) | ||
187 | { | ||
188 | priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); | ||
189 | priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); | ||
190 | pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); | ||
191 | } | ||
192 | EXPORT_SYMBOL(iwl_hw_detect); | ||
193 | |||
194 | /* | 186 | /* |
195 | * QoS support | 187 | * QoS support |
196 | */ | 188 | */ |
@@ -247,7 +239,11 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
247 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; | 239 | ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; |
248 | 240 | ||
249 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; | 241 | ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; |
242 | if (priv->cfg->ampdu_factor) | ||
243 | ht_info->ampdu_factor = priv->cfg->ampdu_factor; | ||
250 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; | 244 | ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; |
245 | if (priv->cfg->ampdu_density) | ||
246 | ht_info->ampdu_density = priv->cfg->ampdu_density; | ||
251 | 247 | ||
252 | ht_info->mcs.rx_mask[0] = 0xFF; | 248 | ht_info->mcs.rx_mask[0] = 0xFF; |
253 | if (rx_chains_num >= 2) | 249 | if (rx_chains_num >= 2) |
@@ -499,17 +495,19 @@ static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) | |||
499 | return new_val; | 495 | return new_val; |
500 | } | 496 | } |
501 | 497 | ||
502 | void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | 498 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) |
503 | { | 499 | { |
504 | u64 tsf; | 500 | u64 tsf; |
505 | s32 interval_tm, rem; | 501 | s32 interval_tm, rem; |
506 | unsigned long flags; | ||
507 | struct ieee80211_conf *conf = NULL; | 502 | struct ieee80211_conf *conf = NULL; |
508 | u16 beacon_int; | 503 | u16 beacon_int; |
509 | 504 | ||
510 | conf = ieee80211_get_hw_conf(priv->hw); | 505 | conf = ieee80211_get_hw_conf(priv->hw); |
511 | 506 | ||
512 | spin_lock_irqsave(&priv->lock, flags); | 507 | lockdep_assert_held(&priv->mutex); |
508 | |||
509 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | ||
510 | |||
513 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); | 511 | priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); |
514 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); | 512 | priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); |
515 | 513 | ||
@@ -532,14 +530,16 @@ void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
532 | rem = do_div(tsf, interval_tm); | 530 | rem = do_div(tsf, interval_tm); |
533 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); | 531 | priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); |
534 | 532 | ||
535 | spin_unlock_irqrestore(&priv->lock, flags); | ||
536 | IWL_DEBUG_ASSOC(priv, | 533 | IWL_DEBUG_ASSOC(priv, |
537 | "beacon interval %d beacon timer %d beacon tim %d\n", | 534 | "beacon interval %d beacon timer %d beacon tim %d\n", |
538 | le16_to_cpu(priv->rxon_timing.beacon_interval), | 535 | le16_to_cpu(priv->rxon_timing.beacon_interval), |
539 | le32_to_cpu(priv->rxon_timing.beacon_init_val), | 536 | le32_to_cpu(priv->rxon_timing.beacon_init_val), |
540 | le16_to_cpu(priv->rxon_timing.atim_window)); | 537 | le16_to_cpu(priv->rxon_timing.atim_window)); |
538 | |||
539 | return iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
540 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
541 | } | 541 | } |
542 | EXPORT_SYMBOL(iwl_setup_rxon_timing); | 542 | EXPORT_SYMBOL(iwl_send_rxon_timing); |
543 | 543 | ||
544 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) | 544 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) |
545 | { | 545 | { |
@@ -912,25 +912,18 @@ u8 iwl_get_single_channel_number(struct iwl_priv *priv, | |||
912 | EXPORT_SYMBOL(iwl_get_single_channel_number); | 912 | EXPORT_SYMBOL(iwl_get_single_channel_number); |
913 | 913 | ||
914 | /** | 914 | /** |
915 | * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON | 915 | * iwl_set_rxon_channel - Set the band and channel values in staging RXON |
916 | * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz | 916 | * @ch: requested channel as a pointer to struct ieee80211_channel |
917 | * @channel: Any channel valid for the requested phymode | ||
918 | 917 | ||
919 | * In addition to setting the staging RXON, priv->phymode is also set. | 918 | * In addition to setting the staging RXON, priv->band is also set. |
920 | * | 919 | * |
921 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields | 920 | * NOTE: Does not commit to the hardware; it sets appropriate bit fields |
922 | * in the staging RXON flag structure based on the phymode | 921 | * in the staging RXON flag structure based on the ch->band |
923 | */ | 922 | */ |
924 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) | 923 | int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) |
925 | { | 924 | { |
926 | enum ieee80211_band band = ch->band; | 925 | enum ieee80211_band band = ch->band; |
927 | u16 channel = ieee80211_frequency_to_channel(ch->center_freq); | 926 | u16 channel = ch->hw_value; |
928 | |||
929 | if (!iwl_get_channel_info(priv, band, channel)) { | ||
930 | IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n", | ||
931 | channel, band); | ||
932 | return -EINVAL; | ||
933 | } | ||
934 | 927 | ||
935 | if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && | 928 | if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && |
936 | (priv->band == band)) | 929 | (priv->band == band)) |
@@ -1328,25 +1321,6 @@ out: | |||
1328 | EXPORT_SYMBOL(iwl_apm_init); | 1321 | EXPORT_SYMBOL(iwl_apm_init); |
1329 | 1322 | ||
1330 | 1323 | ||
1331 | int iwl_set_hw_params(struct iwl_priv *priv) | ||
1332 | { | ||
1333 | priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; | ||
1334 | priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; | ||
1335 | if (priv->cfg->mod_params->amsdu_size_8K) | ||
1336 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K); | ||
1337 | else | ||
1338 | priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K); | ||
1339 | |||
1340 | priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; | ||
1341 | |||
1342 | if (priv->cfg->mod_params->disable_11n) | ||
1343 | priv->cfg->sku &= ~IWL_SKU_N; | ||
1344 | |||
1345 | /* Device-specific setup */ | ||
1346 | return priv->cfg->ops->lib->set_hw_params(priv); | ||
1347 | } | ||
1348 | EXPORT_SYMBOL(iwl_set_hw_params); | ||
1349 | |||
1350 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | 1324 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) |
1351 | { | 1325 | { |
1352 | int ret = 0; | 1326 | int ret = 0; |
@@ -1496,76 +1470,6 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) | |||
1496 | } | 1470 | } |
1497 | EXPORT_SYMBOL(iwl_send_statistics_request); | 1471 | EXPORT_SYMBOL(iwl_send_statistics_request); |
1498 | 1472 | ||
1499 | void iwl_rf_kill_ct_config(struct iwl_priv *priv) | ||
1500 | { | ||
1501 | struct iwl_ct_kill_config cmd; | ||
1502 | struct iwl_ct_kill_throttling_config adv_cmd; | ||
1503 | unsigned long flags; | ||
1504 | int ret = 0; | ||
1505 | |||
1506 | spin_lock_irqsave(&priv->lock, flags); | ||
1507 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
1508 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
1509 | spin_unlock_irqrestore(&priv->lock, flags); | ||
1510 | priv->thermal_throttle.ct_kill_toggle = false; | ||
1511 | |||
1512 | if (priv->cfg->support_ct_kill_exit) { | ||
1513 | adv_cmd.critical_temperature_enter = | ||
1514 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
1515 | adv_cmd.critical_temperature_exit = | ||
1516 | cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); | ||
1517 | |||
1518 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
1519 | sizeof(adv_cmd), &adv_cmd); | ||
1520 | if (ret) | ||
1521 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
1522 | else | ||
1523 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
1524 | "succeeded, " | ||
1525 | "critical temperature enter is %d," | ||
1526 | "exit is %d\n", | ||
1527 | priv->hw_params.ct_kill_threshold, | ||
1528 | priv->hw_params.ct_kill_exit_threshold); | ||
1529 | } else { | ||
1530 | cmd.critical_temperature_R = | ||
1531 | cpu_to_le32(priv->hw_params.ct_kill_threshold); | ||
1532 | |||
1533 | ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, | ||
1534 | sizeof(cmd), &cmd); | ||
1535 | if (ret) | ||
1536 | IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); | ||
1537 | else | ||
1538 | IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " | ||
1539 | "succeeded, " | ||
1540 | "critical temperature is %d\n", | ||
1541 | priv->hw_params.ct_kill_threshold); | ||
1542 | } | ||
1543 | } | ||
1544 | EXPORT_SYMBOL(iwl_rf_kill_ct_config); | ||
1545 | |||
1546 | |||
1547 | /* | ||
1548 | * CARD_STATE_CMD | ||
1549 | * | ||
1550 | * Use: Sets the device's internal card state to enable, disable, or halt | ||
1551 | * | ||
1552 | * When in the 'enable' state the card operates as normal. | ||
1553 | * When in the 'disable' state, the card enters into a low power mode. | ||
1554 | * When in the 'halt' state, the card is shut down and must be fully | ||
1555 | * restarted to come back on. | ||
1556 | */ | ||
1557 | int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) | ||
1558 | { | ||
1559 | struct iwl_host_cmd cmd = { | ||
1560 | .id = REPLY_CARD_STATE_CMD, | ||
1561 | .len = sizeof(u32), | ||
1562 | .data = &flags, | ||
1563 | .flags = meta_flag, | ||
1564 | }; | ||
1565 | |||
1566 | return iwl_send_cmd(priv, &cmd); | ||
1567 | } | ||
1568 | |||
1569 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, | 1473 | void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, |
1570 | struct iwl_rx_mem_buffer *rxb) | 1474 | struct iwl_rx_mem_buffer *rxb) |
1571 | { | 1475 | { |
@@ -1648,6 +1552,14 @@ int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
1648 | } | 1552 | } |
1649 | EXPORT_SYMBOL(iwl_mac_conf_tx); | 1553 | EXPORT_SYMBOL(iwl_mac_conf_tx); |
1650 | 1554 | ||
1555 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw) | ||
1556 | { | ||
1557 | struct iwl_priv *priv = hw->priv; | ||
1558 | |||
1559 | return priv->ibss_manager == IWL_IBSS_MANAGER; | ||
1560 | } | ||
1561 | EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon); | ||
1562 | |||
1651 | static void iwl_ht_conf(struct iwl_priv *priv, | 1563 | static void iwl_ht_conf(struct iwl_priv *priv, |
1652 | struct ieee80211_vif *vif) | 1564 | struct ieee80211_vif *vif) |
1653 | { | 1565 | { |
@@ -2014,6 +1926,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2014 | struct iwl_priv *priv = hw->priv; | 1926 | struct iwl_priv *priv = hw->priv; |
2015 | const struct iwl_channel_info *ch_info; | 1927 | const struct iwl_channel_info *ch_info; |
2016 | struct ieee80211_conf *conf = &hw->conf; | 1928 | struct ieee80211_conf *conf = &hw->conf; |
1929 | struct ieee80211_channel *channel = conf->channel; | ||
2017 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | 1930 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; |
2018 | unsigned long flags = 0; | 1931 | unsigned long flags = 0; |
2019 | int ret = 0; | 1932 | int ret = 0; |
@@ -2023,7 +1936,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2023 | mutex_lock(&priv->mutex); | 1936 | mutex_lock(&priv->mutex); |
2024 | 1937 | ||
2025 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", | 1938 | IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", |
2026 | conf->channel->hw_value, changed); | 1939 | channel->hw_value, changed); |
2027 | 1940 | ||
2028 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && | 1941 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && |
2029 | test_bit(STATUS_SCANNING, &priv->status))) { | 1942 | test_bit(STATUS_SCANNING, &priv->status))) { |
@@ -2054,8 +1967,8 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2054 | if (scan_active) | 1967 | if (scan_active) |
2055 | goto set_ch_out; | 1968 | goto set_ch_out; |
2056 | 1969 | ||
2057 | ch = ieee80211_frequency_to_channel(conf->channel->center_freq); | 1970 | ch = channel->hw_value; |
2058 | ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); | 1971 | ch_info = iwl_get_channel_info(priv, channel->band, ch); |
2059 | if (!is_channel_valid(ch_info)) { | 1972 | if (!is_channel_valid(ch_info)) { |
2060 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); | 1973 | IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); |
2061 | ret = -EINVAL; | 1974 | ret = -EINVAL; |
@@ -2086,16 +1999,13 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2086 | * from BSS config in iwl_ht_conf */ | 1999 | * from BSS config in iwl_ht_conf */ |
2087 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 2000 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
2088 | 2001 | ||
2089 | /* if we are switching from ht to 2.4 clear flags | ||
2090 | * from any ht related info since 2.4 does not | ||
2091 | * support ht */ | ||
2092 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) | 2002 | if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) |
2093 | priv->staging_rxon.flags = 0; | 2003 | priv->staging_rxon.flags = 0; |
2094 | 2004 | ||
2095 | iwl_set_rxon_channel(priv, conf->channel); | 2005 | iwl_set_rxon_channel(priv, channel); |
2096 | iwl_set_rxon_ht(priv, ht_conf); | 2006 | iwl_set_rxon_ht(priv, ht_conf); |
2097 | 2007 | ||
2098 | iwl_set_flags_for_band(priv, conf->channel->band, priv->vif); | 2008 | iwl_set_flags_for_band(priv, channel->band, priv->vif); |
2099 | spin_unlock_irqrestore(&priv->lock, flags); | 2009 | spin_unlock_irqrestore(&priv->lock, flags); |
2100 | 2010 | ||
2101 | if (priv->cfg->ops->lib->update_bcast_station) | 2011 | if (priv->cfg->ops->lib->update_bcast_station) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5e6ee3da6bbf..7b1e832bae56 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -136,6 +136,12 @@ struct iwl_temp_ops { | |||
136 | void (*set_calib_version)(struct iwl_priv *priv); | 136 | void (*set_calib_version)(struct iwl_priv *priv); |
137 | }; | 137 | }; |
138 | 138 | ||
139 | struct iwl_tt_ops { | ||
140 | bool (*lower_power_detection)(struct iwl_priv *priv); | ||
141 | u8 (*tt_power_mode)(struct iwl_priv *priv); | ||
142 | bool (*ct_kill_check)(struct iwl_priv *priv); | ||
143 | }; | ||
144 | |||
139 | struct iwl_lib_ops { | 145 | struct iwl_lib_ops { |
140 | /* set hw dependent parameters */ | 146 | /* set hw dependent parameters */ |
141 | int (*set_hw_params)(struct iwl_priv *priv); | 147 | int (*set_hw_params)(struct iwl_priv *priv); |
@@ -212,6 +218,9 @@ struct iwl_lib_ops { | |||
212 | void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); | 218 | void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control); |
213 | 219 | ||
214 | struct iwl_debugfs_ops debugfs_ops; | 220 | struct iwl_debugfs_ops debugfs_ops; |
221 | |||
222 | /* thermal throttling */ | ||
223 | struct iwl_tt_ops tt_ops; | ||
215 | }; | 224 | }; |
216 | 225 | ||
217 | struct iwl_led_ops { | 226 | struct iwl_led_ops { |
@@ -269,6 +278,11 @@ struct iwl_mod_params { | |||
269 | * @chain_noise_calib_by_driver: driver has the capability to perform | 278 | * @chain_noise_calib_by_driver: driver has the capability to perform |
270 | * chain noise calibration operation | 279 | * chain noise calibration operation |
271 | * @scan_antennas: available antenna for scan operation | 280 | * @scan_antennas: available antenna for scan operation |
281 | * @need_dc_calib: need to perform init dc calibration | ||
282 | * @bt_statistics: use BT version of statistics notification | ||
283 | * @agg_time_limit: maximum number of uSec in aggregation | ||
284 | * @ampdu_factor: Maximum A-MPDU length factor | ||
285 | * @ampdu_density: Minimum A-MPDU spacing | ||
272 | * | 286 | * |
273 | * We enable the driver to be backward compatible wrt API version. The | 287 | * We enable the driver to be backward compatible wrt API version. The |
274 | * driver specifies which APIs it supports (with @ucode_api_max being the | 288 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -339,6 +353,9 @@ struct iwl_cfg { | |||
339 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; | 353 | u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; |
340 | const bool need_dc_calib; | 354 | const bool need_dc_calib; |
341 | const bool bt_statistics; | 355 | const bool bt_statistics; |
356 | u16 agg_time_limit; | ||
357 | u8 ampdu_factor; | ||
358 | u8 ampdu_density; | ||
342 | }; | 359 | }; |
343 | 360 | ||
344 | /*************************** | 361 | /*************************** |
@@ -347,10 +364,10 @@ struct iwl_cfg { | |||
347 | 364 | ||
348 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, | 365 | struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, |
349 | struct ieee80211_ops *hw_ops); | 366 | struct ieee80211_ops *hw_ops); |
350 | void iwl_hw_detect(struct iwl_priv *priv); | ||
351 | void iwl_activate_qos(struct iwl_priv *priv); | 367 | void iwl_activate_qos(struct iwl_priv *priv); |
352 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, | 368 | int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, |
353 | const struct ieee80211_tx_queue_params *params); | 369 | const struct ieee80211_tx_queue_params *params); |
370 | int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw); | ||
354 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); | 371 | void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); |
355 | int iwl_check_rxon_cmd(struct iwl_priv *priv); | 372 | int iwl_check_rxon_cmd(struct iwl_priv *priv); |
356 | int iwl_full_rxon_required(struct iwl_priv *priv); | 373 | int iwl_full_rxon_required(struct iwl_priv *priv); |
@@ -372,7 +389,6 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
372 | u32 decrypt_res, | 389 | u32 decrypt_res, |
373 | struct ieee80211_rx_status *stats); | 390 | struct ieee80211_rx_status *stats); |
374 | void iwl_irq_handle_error(struct iwl_priv *priv); | 391 | void iwl_irq_handle_error(struct iwl_priv *priv); |
375 | int iwl_set_hw_params(struct iwl_priv *priv); | ||
376 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); | 392 | void iwl_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif); |
377 | void iwl_bss_info_changed(struct ieee80211_hw *hw, | 393 | void iwl_bss_info_changed(struct ieee80211_hw *hw, |
378 | struct ieee80211_vif *vif, | 394 | struct ieee80211_vif *vif, |
@@ -527,7 +543,6 @@ int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); | |||
527 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, | 543 | int iwl_mac_hw_scan(struct ieee80211_hw *hw, |
528 | struct ieee80211_vif *vif, | 544 | struct ieee80211_vif *vif, |
529 | struct cfg80211_scan_request *req); | 545 | struct cfg80211_scan_request *req); |
530 | void iwl_bg_start_internal_scan(struct work_struct *work); | ||
531 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); | 546 | void iwl_internal_short_hw_scan(struct iwl_priv *priv); |
532 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); | 547 | int iwl_force_reset(struct iwl_priv *priv, int mode, bool external); |
533 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | 548 | u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, |
@@ -539,9 +554,6 @@ u16 iwl_get_active_dwell_time(struct iwl_priv *priv, | |||
539 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, | 554 | u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, |
540 | enum ieee80211_band band, | 555 | enum ieee80211_band band, |
541 | struct ieee80211_vif *vif); | 556 | struct ieee80211_vif *vif); |
542 | void iwl_bg_scan_check(struct work_struct *data); | ||
543 | void iwl_bg_abort_scan(struct work_struct *work); | ||
544 | void iwl_bg_scan_completed(struct work_struct *work); | ||
545 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); | 557 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv); |
546 | 558 | ||
547 | /* For faster active scanning, scan will move to the next channel if fewer than | 559 | /* For faster active scanning, scan will move to the next channel if fewer than |
@@ -580,8 +592,6 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, | |||
580 | 592 | ||
581 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); | 593 | int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); |
582 | 594 | ||
583 | int iwl_send_card_state(struct iwl_priv *priv, u32 flags, | ||
584 | u8 meta_flag); | ||
585 | 595 | ||
586 | /***************************************************** | 596 | /***************************************************** |
587 | * PCI * | 597 | * PCI * |
@@ -695,7 +705,6 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) | |||
695 | return iwl_is_ready(priv); | 705 | return iwl_is_ready(priv); |
696 | } | 706 | } |
697 | 707 | ||
698 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | ||
699 | extern void iwl_send_bt_config(struct iwl_priv *priv); | 708 | extern void iwl_send_bt_config(struct iwl_priv *priv); |
700 | extern int iwl_send_statistics_request(struct iwl_priv *priv, | 709 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
701 | u8 flags, bool clear); | 710 | u8 flags, bool clear); |
@@ -704,7 +713,7 @@ extern int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
704 | void iwl_apm_stop(struct iwl_priv *priv); | 713 | void iwl_apm_stop(struct iwl_priv *priv); |
705 | int iwl_apm_init(struct iwl_priv *priv); | 714 | int iwl_apm_init(struct iwl_priv *priv); |
706 | 715 | ||
707 | void iwl_setup_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); | 716 | int iwl_send_rxon_timing(struct iwl_priv *priv, struct ieee80211_vif *vif); |
708 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) | 717 | static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) |
709 | { | 718 | { |
710 | return priv->cfg->ops->hcmd->rxon_assoc(priv); | 719 | return priv->cfg->ops->hcmd->rxon_assoc(priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index e96a1bb12783..d3acdae72381 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -467,8 +467,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
467 | for (i = 0; i < supp_band->n_channels; i++) | 467 | for (i = 0; i < supp_band->n_channels; i++) |
468 | pos += scnprintf(buf + pos, bufsz - pos, | 468 | pos += scnprintf(buf + pos, bufsz - pos, |
469 | "%d: %ddBm: BSS%s%s, %s.\n", | 469 | "%d: %ddBm: BSS%s%s, %s.\n", |
470 | ieee80211_frequency_to_channel( | 470 | channels[i].hw_value, |
471 | channels[i].center_freq), | ||
472 | channels[i].max_power, | 471 | channels[i].max_power, |
473 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 472 | channels[i].flags & IEEE80211_CHAN_RADAR ? |
474 | " (IEEE 802.11h required)" : "", | 473 | " (IEEE 802.11h required)" : "", |
@@ -491,8 +490,7 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, | |||
491 | for (i = 0; i < supp_band->n_channels; i++) | 490 | for (i = 0; i < supp_band->n_channels; i++) |
492 | pos += scnprintf(buf + pos, bufsz - pos, | 491 | pos += scnprintf(buf + pos, bufsz - pos, |
493 | "%d: %ddBm: BSS%s%s, %s.\n", | 492 | "%d: %ddBm: BSS%s%s, %s.\n", |
494 | ieee80211_frequency_to_channel( | 493 | channels[i].hw_value, |
495 | channels[i].center_freq), | ||
496 | channels[i].max_power, | 494 | channels[i].max_power, |
497 | channels[i].flags & IEEE80211_CHAN_RADAR ? | 495 | channels[i].flags & IEEE80211_CHAN_RADAR ? |
498 | " (IEEE 802.11h required)" : "", | 496 | " (IEEE 802.11h required)" : "", |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 2e97cd2fa98a..1ad330342ffc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -47,6 +47,7 @@ | |||
47 | #include "iwl-led.h" | 47 | #include "iwl-led.h" |
48 | #include "iwl-power.h" | 48 | #include "iwl-power.h" |
49 | #include "iwl-agn-rs.h" | 49 | #include "iwl-agn-rs.h" |
50 | #include "iwl-agn-tt.h" | ||
50 | 51 | ||
51 | struct iwl_tx_queue; | 52 | struct iwl_tx_queue; |
52 | 53 | ||
@@ -420,7 +421,7 @@ struct iwl_tid_data { | |||
420 | }; | 421 | }; |
421 | 422 | ||
422 | struct iwl_hw_key { | 423 | struct iwl_hw_key { |
423 | enum ieee80211_key_alg alg; | 424 | u32 cipher; |
424 | int keylen; | 425 | int keylen; |
425 | u8 keyidx; | 426 | u8 keyidx; |
426 | u8 key[32]; | 427 | u8 key[32]; |
@@ -434,7 +435,13 @@ union iwl_ht_rate_supp { | |||
434 | }; | 435 | }; |
435 | }; | 436 | }; |
436 | 437 | ||
437 | #define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3) | 438 | #define CFG_HT_RX_AMPDU_FACTOR_8K (0x0) |
439 | #define CFG_HT_RX_AMPDU_FACTOR_16K (0x1) | ||
440 | #define CFG_HT_RX_AMPDU_FACTOR_32K (0x2) | ||
441 | #define CFG_HT_RX_AMPDU_FACTOR_64K (0x3) | ||
442 | #define CFG_HT_RX_AMPDU_FACTOR_DEF CFG_HT_RX_AMPDU_FACTOR_64K | ||
443 | #define CFG_HT_RX_AMPDU_FACTOR_MAX CFG_HT_RX_AMPDU_FACTOR_64K | ||
444 | #define CFG_HT_RX_AMPDU_FACTOR_MIN CFG_HT_RX_AMPDU_FACTOR_8K | ||
438 | 445 | ||
439 | /* | 446 | /* |
440 | * Maximal MPDU density for TX aggregation | 447 | * Maximal MPDU density for TX aggregation |
@@ -443,8 +450,13 @@ union iwl_ht_rate_supp { | |||
443 | * 6 - 8us density | 450 | * 6 - 8us density |
444 | * 7 - 16us density | 451 | * 7 - 16us density |
445 | */ | 452 | */ |
453 | #define CFG_HT_MPDU_DENSITY_2USEC (0x4) | ||
446 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) | 454 | #define CFG_HT_MPDU_DENSITY_4USEC (0x5) |
455 | #define CFG_HT_MPDU_DENSITY_8USEC (0x6) | ||
456 | #define CFG_HT_MPDU_DENSITY_16USEC (0x7) | ||
447 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC | 457 | #define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC |
458 | #define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC | ||
459 | #define CFG_HT_MPDU_DENSITY_MIN (0x1) | ||
448 | 460 | ||
449 | struct iwl_ht_config { | 461 | struct iwl_ht_config { |
450 | /* self configuration data */ | 462 | /* self configuration data */ |
@@ -1052,7 +1064,6 @@ struct iwl_event_log { | |||
1052 | #define IWL_DEF_MONITORING_PERIOD (1000) | 1064 | #define IWL_DEF_MONITORING_PERIOD (1000) |
1053 | #define IWL_LONG_MONITORING_PERIOD (5000) | 1065 | #define IWL_LONG_MONITORING_PERIOD (5000) |
1054 | #define IWL_ONE_HUNDRED_MSECS (100) | 1066 | #define IWL_ONE_HUNDRED_MSECS (100) |
1055 | #define IWL_SIXTY_SECS (60000) | ||
1056 | 1067 | ||
1057 | enum iwl_reset { | 1068 | enum iwl_reset { |
1058 | IWL_RF_RESET = 0, | 1069 | IWL_RF_RESET = 0, |
@@ -1110,6 +1121,9 @@ struct iwl_priv { | |||
1110 | u32 ucode_beacon_time; | 1121 | u32 ucode_beacon_time; |
1111 | int missed_beacon_threshold; | 1122 | int missed_beacon_threshold; |
1112 | 1123 | ||
1124 | /* track IBSS manager (last beacon) status */ | ||
1125 | u32 ibss_manager; | ||
1126 | |||
1113 | /* storing the jiffies when the plcp error rate is received */ | 1127 | /* storing the jiffies when the plcp error rate is received */ |
1114 | unsigned long plcp_jiffies; | 1128 | unsigned long plcp_jiffies; |
1115 | 1129 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index cda6a94d6cc9..63c0ab46261f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -192,47 +192,6 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
192 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); | 192 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); |
193 | } | 193 | } |
194 | 194 | ||
195 | /* default Thermal Throttling transaction table | ||
196 | * Current state | Throttling Down | Throttling Up | ||
197 | *============================================================================= | ||
198 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
199 | *----------------------------------------------------------------------------- | ||
200 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
201 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
202 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
203 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
204 | *============================================================================= | ||
205 | */ | ||
206 | static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { | ||
207 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, | ||
208 | {IWL_TI_1, 105, CT_KILL_THRESHOLD - 1}, | ||
209 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
210 | }; | ||
211 | static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { | ||
212 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, | ||
213 | {IWL_TI_2, 110, CT_KILL_THRESHOLD - 1}, | ||
214 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
215 | }; | ||
216 | static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { | ||
217 | {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, | ||
218 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX}, | ||
219 | {IWL_TI_CT_KILL, CT_KILL_THRESHOLD, IWL_ABSOLUTE_MAX} | ||
220 | }; | ||
221 | static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { | ||
222 | {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, | ||
223 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, | ||
224 | {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} | ||
225 | }; | ||
226 | |||
227 | /* Advance Thermal Throttling default restriction table */ | ||
228 | static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { | ||
229 | {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, | ||
230 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, | ||
231 | {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, | ||
232 | {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } | ||
233 | }; | ||
234 | |||
235 | |||
236 | static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, | 195 | static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, |
237 | struct iwl_powertable_cmd *cmd) | 196 | struct iwl_powertable_cmd *cmd) |
238 | { | 197 | { |
@@ -308,7 +267,6 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) | |||
308 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) | 267 | int iwl_power_update_mode(struct iwl_priv *priv, bool force) |
309 | { | 268 | { |
310 | int ret = 0; | 269 | int ret = 0; |
311 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
312 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; | 270 | bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS; |
313 | bool update_chains; | 271 | bool update_chains; |
314 | struct iwl_powertable_cmd cmd; | 272 | struct iwl_powertable_cmd cmd; |
@@ -325,9 +283,13 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
325 | else if (priv->cfg->supports_idle && | 283 | else if (priv->cfg->supports_idle && |
326 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) | 284 | priv->hw->conf.flags & IEEE80211_CONF_IDLE) |
327 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); | 285 | iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_5, 20); |
328 | else if (tt->state >= IWL_TI_1) | 286 | else if (priv->cfg->ops->lib->tt_ops.lower_power_detection && |
329 | iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); | 287 | priv->cfg->ops->lib->tt_ops.tt_power_mode && |
330 | else if (!enabled) | 288 | priv->cfg->ops->lib->tt_ops.lower_power_detection(priv)) { |
289 | /* in thermal throttling low power state */ | ||
290 | iwl_static_sleep_cmd(priv, &cmd, | ||
291 | priv->cfg->ops->lib->tt_ops.tt_power_mode(priv), dtimper); | ||
292 | } else if (!enabled) | ||
331 | iwl_power_sleep_cam_cmd(priv, &cmd); | 293 | iwl_power_sleep_cam_cmd(priv, &cmd); |
332 | else if (priv->power_data.debug_sleep_level_override >= 0) | 294 | else if (priv->power_data.debug_sleep_level_override >= 0) |
333 | iwl_static_sleep_cmd(priv, &cmd, | 295 | iwl_static_sleep_cmd(priv, &cmd, |
@@ -367,592 +329,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force) | |||
367 | } | 329 | } |
368 | EXPORT_SYMBOL(iwl_power_update_mode); | 330 | EXPORT_SYMBOL(iwl_power_update_mode); |
369 | 331 | ||
370 | bool iwl_ht_enabled(struct iwl_priv *priv) | ||
371 | { | ||
372 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
373 | struct iwl_tt_restriction *restriction; | ||
374 | |||
375 | if (!priv->thermal_throttle.advanced_tt) | ||
376 | return true; | ||
377 | restriction = tt->restriction + tt->state; | ||
378 | return restriction->is_ht; | ||
379 | } | ||
380 | EXPORT_SYMBOL(iwl_ht_enabled); | ||
381 | |||
382 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv) | ||
383 | { | ||
384 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
385 | bool within_margin = false; | ||
386 | |||
387 | if (priv->cfg->temperature_kelvin) | ||
388 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
389 | |||
390 | if (!priv->thermal_throttle.advanced_tt) | ||
391 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
392 | CT_KILL_THRESHOLD_LEGACY) ? true : false; | ||
393 | else | ||
394 | within_margin = ((temp + IWL_TT_CT_KILL_MARGIN) >= | ||
395 | CT_KILL_THRESHOLD) ? true : false; | ||
396 | return within_margin; | ||
397 | } | ||
398 | |||
399 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) | ||
400 | { | ||
401 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
402 | struct iwl_tt_restriction *restriction; | ||
403 | |||
404 | if (!priv->thermal_throttle.advanced_tt) | ||
405 | return IWL_ANT_OK_MULTI; | ||
406 | restriction = tt->restriction + tt->state; | ||
407 | return restriction->tx_stream; | ||
408 | } | ||
409 | EXPORT_SYMBOL(iwl_tx_ant_restriction); | ||
410 | |||
411 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) | ||
412 | { | ||
413 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
414 | struct iwl_tt_restriction *restriction; | ||
415 | |||
416 | if (!priv->thermal_throttle.advanced_tt) | ||
417 | return IWL_ANT_OK_MULTI; | ||
418 | restriction = tt->restriction + tt->state; | ||
419 | return restriction->rx_stream; | ||
420 | } | ||
421 | |||
422 | #define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ | ||
423 | #define CT_KILL_WAITING_DURATION (300) /* 300ms duration */ | ||
424 | |||
425 | /* | ||
426 | * toggle the bit to wake up uCode and check the temperature | ||
427 | * if the temperature is below CT, uCode will stay awake and send card | ||
428 | * state notification with CT_KILL bit clear to inform Thermal Throttling | ||
429 | * Management to change state. Otherwise, uCode will go back to sleep | ||
430 | * without doing anything, driver should continue the 5 seconds timer | ||
431 | * to wake up uCode for temperature check until temperature drop below CT | ||
432 | */ | ||
433 | static void iwl_tt_check_exit_ct_kill(unsigned long data) | ||
434 | { | ||
435 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
436 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
437 | unsigned long flags; | ||
438 | |||
439 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
440 | return; | ||
441 | |||
442 | if (tt->state == IWL_TI_CT_KILL) { | ||
443 | if (priv->thermal_throttle.ct_kill_toggle) { | ||
444 | iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, | ||
445 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
446 | priv->thermal_throttle.ct_kill_toggle = false; | ||
447 | } else { | ||
448 | iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, | ||
449 | CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); | ||
450 | priv->thermal_throttle.ct_kill_toggle = true; | ||
451 | } | ||
452 | iwl_read32(priv, CSR_UCODE_DRV_GP1); | ||
453 | spin_lock_irqsave(&priv->reg_lock, flags); | ||
454 | if (!iwl_grab_nic_access(priv)) | ||
455 | iwl_release_nic_access(priv); | ||
456 | spin_unlock_irqrestore(&priv->reg_lock, flags); | ||
457 | |||
458 | /* Reschedule the ct_kill timer to occur in | ||
459 | * CT_KILL_EXIT_DURATION seconds to ensure we get a | ||
460 | * thermal update */ | ||
461 | IWL_DEBUG_POWER(priv, "schedule ct_kill exit timer\n"); | ||
462 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + | ||
463 | CT_KILL_EXIT_DURATION * HZ); | ||
464 | } | ||
465 | } | ||
466 | |||
467 | static void iwl_perform_ct_kill_task(struct iwl_priv *priv, | ||
468 | bool stop) | ||
469 | { | ||
470 | if (stop) { | ||
471 | IWL_DEBUG_POWER(priv, "Stop all queues\n"); | ||
472 | if (priv->mac80211_registered) | ||
473 | ieee80211_stop_queues(priv->hw); | ||
474 | IWL_DEBUG_POWER(priv, | ||
475 | "Schedule 5 seconds CT_KILL Timer\n"); | ||
476 | mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + | ||
477 | CT_KILL_EXIT_DURATION * HZ); | ||
478 | } else { | ||
479 | IWL_DEBUG_POWER(priv, "Wake all queues\n"); | ||
480 | if (priv->mac80211_registered) | ||
481 | ieee80211_wake_queues(priv->hw); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | static void iwl_tt_ready_for_ct_kill(unsigned long data) | ||
486 | { | ||
487 | struct iwl_priv *priv = (struct iwl_priv *)data; | ||
488 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
489 | |||
490 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
491 | return; | ||
492 | |||
493 | /* temperature timer expired, ready to go into CT_KILL state */ | ||
494 | if (tt->state != IWL_TI_CT_KILL) { | ||
495 | IWL_DEBUG_POWER(priv, "entering CT_KILL state when temperature timer expired\n"); | ||
496 | tt->state = IWL_TI_CT_KILL; | ||
497 | set_bit(STATUS_CT_KILL, &priv->status); | ||
498 | iwl_perform_ct_kill_task(priv, true); | ||
499 | } | ||
500 | } | ||
501 | |||
502 | static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | ||
503 | { | ||
504 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | ||
505 | /* make request to retrieve statistics information */ | ||
506 | iwl_send_statistics_request(priv, CMD_SYNC, false); | ||
507 | /* Reschedule the ct_kill wait timer */ | ||
508 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | ||
509 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | ||
510 | } | ||
511 | |||
512 | #define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) | ||
513 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) | ||
514 | #define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) | ||
515 | |||
516 | /* | ||
517 | * Legacy thermal throttling | ||
518 | * 1) Avoid NIC destruction due to high temperatures | ||
519 | * Chip will identify dangerously high temperatures that can | ||
520 | * harm the device and will power down | ||
521 | * 2) Avoid the NIC power down due to high temperature | ||
522 | * Throttle early enough to lower the power consumption before | ||
523 | * drastic steps are needed | ||
524 | */ | ||
525 | static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
526 | { | ||
527 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
528 | enum iwl_tt_state old_state; | ||
529 | |||
530 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
531 | if ((tt->tt_previous_temp) && | ||
532 | (temp > tt->tt_previous_temp) && | ||
533 | ((temp - tt->tt_previous_temp) > | ||
534 | IWL_TT_INCREASE_MARGIN)) { | ||
535 | IWL_DEBUG_POWER(priv, | ||
536 | "Temperature increase %d degree Celsius\n", | ||
537 | (temp - tt->tt_previous_temp)); | ||
538 | } | ||
539 | #endif | ||
540 | old_state = tt->state; | ||
541 | /* in Celsius */ | ||
542 | if (temp >= IWL_MINIMAL_POWER_THRESHOLD) | ||
543 | tt->state = IWL_TI_CT_KILL; | ||
544 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) | ||
545 | tt->state = IWL_TI_2; | ||
546 | else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) | ||
547 | tt->state = IWL_TI_1; | ||
548 | else | ||
549 | tt->state = IWL_TI_0; | ||
550 | |||
551 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
552 | tt->tt_previous_temp = temp; | ||
553 | #endif | ||
554 | /* stop ct_kill_waiting_tm timer */ | ||
555 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
556 | if (tt->state != old_state) { | ||
557 | switch (tt->state) { | ||
558 | case IWL_TI_0: | ||
559 | /* | ||
560 | * When the system is ready to go back to IWL_TI_0 | ||
561 | * we only have to call iwl_power_update_mode() to | ||
562 | * do so. | ||
563 | */ | ||
564 | break; | ||
565 | case IWL_TI_1: | ||
566 | tt->tt_power_mode = IWL_POWER_INDEX_3; | ||
567 | break; | ||
568 | case IWL_TI_2: | ||
569 | tt->tt_power_mode = IWL_POWER_INDEX_4; | ||
570 | break; | ||
571 | default: | ||
572 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
573 | break; | ||
574 | } | ||
575 | mutex_lock(&priv->mutex); | ||
576 | if (old_state == IWL_TI_CT_KILL) | ||
577 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
578 | if (tt->state != IWL_TI_CT_KILL && | ||
579 | iwl_power_update_mode(priv, true)) { | ||
580 | /* TT state not updated | ||
581 | * try again during next temperature read | ||
582 | */ | ||
583 | if (old_state == IWL_TI_CT_KILL) | ||
584 | set_bit(STATUS_CT_KILL, &priv->status); | ||
585 | tt->state = old_state; | ||
586 | IWL_ERR(priv, "Cannot update power mode, " | ||
587 | "TT state not updated\n"); | ||
588 | } else { | ||
589 | if (tt->state == IWL_TI_CT_KILL) { | ||
590 | if (force) { | ||
591 | set_bit(STATUS_CT_KILL, &priv->status); | ||
592 | iwl_perform_ct_kill_task(priv, true); | ||
593 | } else { | ||
594 | iwl_prepare_ct_kill_task(priv); | ||
595 | tt->state = old_state; | ||
596 | } | ||
597 | } else if (old_state == IWL_TI_CT_KILL && | ||
598 | tt->state != IWL_TI_CT_KILL) | ||
599 | iwl_perform_ct_kill_task(priv, false); | ||
600 | IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", | ||
601 | tt->state); | ||
602 | IWL_DEBUG_POWER(priv, "Power Index change to %u\n", | ||
603 | tt->tt_power_mode); | ||
604 | } | ||
605 | mutex_unlock(&priv->mutex); | ||
606 | } | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * Advance thermal throttling | ||
611 | * 1) Avoid NIC destruction due to high temperatures | ||
612 | * Chip will identify dangerously high temperatures that can | ||
613 | * harm the device and will power down | ||
614 | * 2) Avoid the NIC power down due to high temperature | ||
615 | * Throttle early enough to lower the power consumption before | ||
616 | * drastic steps are needed | ||
617 | * Actions include relaxing the power down sleep thresholds and | ||
618 | * decreasing the number of TX streams | ||
619 | * 3) Avoid throughput performance impact as much as possible | ||
620 | * | ||
621 | *============================================================================= | ||
622 | * Condition Nxt State Condition Nxt State Condition Nxt State | ||
623 | *----------------------------------------------------------------------------- | ||
624 | * IWL_TI_0 T >= 114 CT_KILL 114>T>=105 TI_1 N/A N/A | ||
625 | * IWL_TI_1 T >= 114 CT_KILL 114>T>=110 TI_2 T<=95 TI_0 | ||
626 | * IWL_TI_2 T >= 114 CT_KILL T<=100 TI_1 | ||
627 | * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 | ||
628 | *============================================================================= | ||
629 | */ | ||
630 | static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp, bool force) | ||
631 | { | ||
632 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
633 | int i; | ||
634 | bool changed = false; | ||
635 | enum iwl_tt_state old_state; | ||
636 | struct iwl_tt_trans *transaction; | ||
637 | |||
638 | old_state = tt->state; | ||
639 | for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { | ||
640 | /* based on the current TT state, | ||
641 | * find the curresponding transaction table | ||
642 | * each table has (IWL_TI_STATE_MAX - 1) entries | ||
643 | * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) | ||
644 | * will advance to the correct table. | ||
645 | * then based on the current temperature | ||
646 | * find the next state need to transaction to | ||
647 | * go through all the possible (IWL_TI_STATE_MAX - 1) entries | ||
648 | * in the current table to see if transaction is needed | ||
649 | */ | ||
650 | transaction = tt->transaction + | ||
651 | ((old_state * (IWL_TI_STATE_MAX - 1)) + i); | ||
652 | if (temp >= transaction->tt_low && | ||
653 | temp <= transaction->tt_high) { | ||
654 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
655 | if ((tt->tt_previous_temp) && | ||
656 | (temp > tt->tt_previous_temp) && | ||
657 | ((temp - tt->tt_previous_temp) > | ||
658 | IWL_TT_INCREASE_MARGIN)) { | ||
659 | IWL_DEBUG_POWER(priv, | ||
660 | "Temperature increase %d " | ||
661 | "degree Celsius\n", | ||
662 | (temp - tt->tt_previous_temp)); | ||
663 | } | ||
664 | tt->tt_previous_temp = temp; | ||
665 | #endif | ||
666 | if (old_state != | ||
667 | transaction->next_state) { | ||
668 | changed = true; | ||
669 | tt->state = | ||
670 | transaction->next_state; | ||
671 | } | ||
672 | break; | ||
673 | } | ||
674 | } | ||
675 | /* stop ct_kill_waiting_tm timer */ | ||
676 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
677 | if (changed) { | ||
678 | struct iwl_rxon_cmd *rxon = &priv->staging_rxon; | ||
679 | |||
680 | if (tt->state >= IWL_TI_1) { | ||
681 | /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ | ||
682 | tt->tt_power_mode = IWL_POWER_INDEX_5; | ||
683 | if (!iwl_ht_enabled(priv)) | ||
684 | /* disable HT */ | ||
685 | rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | | ||
686 | RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | | ||
687 | RXON_FLG_HT40_PROT_MSK | | ||
688 | RXON_FLG_HT_PROT_MSK); | ||
689 | else { | ||
690 | /* check HT capability and set | ||
691 | * according to the system HT capability | ||
692 | * in case get disabled before */ | ||
693 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
694 | } | ||
695 | |||
696 | } else { | ||
697 | /* | ||
698 | * restore system power setting -- it will be | ||
699 | * recalculated automatically. | ||
700 | */ | ||
701 | |||
702 | /* check HT capability and set | ||
703 | * according to the system HT capability | ||
704 | * in case get disabled before */ | ||
705 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
706 | } | ||
707 | mutex_lock(&priv->mutex); | ||
708 | if (old_state == IWL_TI_CT_KILL) | ||
709 | clear_bit(STATUS_CT_KILL, &priv->status); | ||
710 | if (tt->state != IWL_TI_CT_KILL && | ||
711 | iwl_power_update_mode(priv, true)) { | ||
712 | /* TT state not updated | ||
713 | * try again during next temperature read | ||
714 | */ | ||
715 | IWL_ERR(priv, "Cannot update power mode, " | ||
716 | "TT state not updated\n"); | ||
717 | if (old_state == IWL_TI_CT_KILL) | ||
718 | set_bit(STATUS_CT_KILL, &priv->status); | ||
719 | tt->state = old_state; | ||
720 | } else { | ||
721 | IWL_DEBUG_POWER(priv, | ||
722 | "Thermal Throttling to new state: %u\n", | ||
723 | tt->state); | ||
724 | if (old_state != IWL_TI_CT_KILL && | ||
725 | tt->state == IWL_TI_CT_KILL) { | ||
726 | if (force) { | ||
727 | IWL_DEBUG_POWER(priv, | ||
728 | "Enter IWL_TI_CT_KILL\n"); | ||
729 | set_bit(STATUS_CT_KILL, &priv->status); | ||
730 | iwl_perform_ct_kill_task(priv, true); | ||
731 | } else { | ||
732 | iwl_prepare_ct_kill_task(priv); | ||
733 | tt->state = old_state; | ||
734 | } | ||
735 | } else if (old_state == IWL_TI_CT_KILL && | ||
736 | tt->state != IWL_TI_CT_KILL) { | ||
737 | IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); | ||
738 | iwl_perform_ct_kill_task(priv, false); | ||
739 | } | ||
740 | } | ||
741 | mutex_unlock(&priv->mutex); | ||
742 | } | ||
743 | } | ||
744 | |||
745 | /* Card State Notification indicated reach critical temperature | ||
746 | * if PSP not enable, no Thermal Throttling function will be performed | ||
747 | * just set the GP1 bit to acknowledge the event | ||
748 | * otherwise, go into IWL_TI_CT_KILL state | ||
749 | * since Card State Notification will not provide any temperature reading | ||
750 | * for Legacy mode | ||
751 | * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() | ||
752 | * for advance mode | ||
753 | * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state | ||
754 | */ | ||
755 | static void iwl_bg_ct_enter(struct work_struct *work) | ||
756 | { | ||
757 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); | ||
758 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
759 | |||
760 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
761 | return; | ||
762 | |||
763 | if (!iwl_is_ready(priv)) | ||
764 | return; | ||
765 | |||
766 | if (tt->state != IWL_TI_CT_KILL) { | ||
767 | IWL_ERR(priv, "Device reached critical temperature " | ||
768 | "- ucode going to sleep!\n"); | ||
769 | if (!priv->thermal_throttle.advanced_tt) | ||
770 | iwl_legacy_tt_handler(priv, | ||
771 | IWL_MINIMAL_POWER_THRESHOLD, | ||
772 | true); | ||
773 | else | ||
774 | iwl_advance_tt_handler(priv, | ||
775 | CT_KILL_THRESHOLD + 1, true); | ||
776 | } | ||
777 | } | ||
778 | |||
779 | /* Card State Notification indicated out of critical temperature | ||
780 | * since Card State Notification will not provide any temperature reading | ||
781 | * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature | ||
782 | * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state | ||
783 | */ | ||
784 | static void iwl_bg_ct_exit(struct work_struct *work) | ||
785 | { | ||
786 | struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); | ||
787 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
788 | |||
789 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
790 | return; | ||
791 | |||
792 | if (!iwl_is_ready(priv)) | ||
793 | return; | ||
794 | |||
795 | /* stop ct_kill_exit_tm timer */ | ||
796 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
797 | |||
798 | if (tt->state == IWL_TI_CT_KILL) { | ||
799 | IWL_ERR(priv, | ||
800 | "Device temperature below critical" | ||
801 | "- ucode awake!\n"); | ||
802 | /* | ||
803 | * exit from CT_KILL state | ||
804 | * reset the current temperature reading | ||
805 | */ | ||
806 | priv->temperature = 0; | ||
807 | if (!priv->thermal_throttle.advanced_tt) | ||
808 | iwl_legacy_tt_handler(priv, | ||
809 | IWL_REDUCED_PERFORMANCE_THRESHOLD_2, | ||
810 | true); | ||
811 | else | ||
812 | iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD, | ||
813 | true); | ||
814 | } | ||
815 | } | ||
816 | |||
817 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv) | ||
818 | { | ||
819 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
820 | return; | ||
821 | |||
822 | IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); | ||
823 | queue_work(priv->workqueue, &priv->ct_enter); | ||
824 | } | ||
825 | EXPORT_SYMBOL(iwl_tt_enter_ct_kill); | ||
826 | |||
827 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv) | ||
828 | { | ||
829 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
830 | return; | ||
831 | |||
832 | IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); | ||
833 | queue_work(priv->workqueue, &priv->ct_exit); | ||
834 | } | ||
835 | EXPORT_SYMBOL(iwl_tt_exit_ct_kill); | ||
836 | |||
837 | static void iwl_bg_tt_work(struct work_struct *work) | ||
838 | { | ||
839 | struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); | ||
840 | s32 temp = priv->temperature; /* degrees CELSIUS except specified */ | ||
841 | |||
842 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
843 | return; | ||
844 | |||
845 | if (priv->cfg->temperature_kelvin) | ||
846 | temp = KELVIN_TO_CELSIUS(priv->temperature); | ||
847 | |||
848 | if (!priv->thermal_throttle.advanced_tt) | ||
849 | iwl_legacy_tt_handler(priv, temp, false); | ||
850 | else | ||
851 | iwl_advance_tt_handler(priv, temp, false); | ||
852 | } | ||
853 | |||
854 | void iwl_tt_handler(struct iwl_priv *priv) | ||
855 | { | ||
856 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
857 | return; | ||
858 | |||
859 | IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); | ||
860 | queue_work(priv->workqueue, &priv->tt_work); | ||
861 | } | ||
862 | EXPORT_SYMBOL(iwl_tt_handler); | ||
863 | |||
864 | /* Thermal throttling initialization | ||
865 | * For advance thermal throttling: | ||
866 | * Initialize Thermal Index and temperature threshold table | ||
867 | * Initialize thermal throttling restriction table | ||
868 | */ | ||
869 | void iwl_tt_initialize(struct iwl_priv *priv) | ||
870 | { | ||
871 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
872 | int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); | ||
873 | struct iwl_tt_trans *transaction; | ||
874 | |||
875 | IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling\n"); | ||
876 | |||
877 | memset(tt, 0, sizeof(struct iwl_tt_mgmt)); | ||
878 | |||
879 | tt->state = IWL_TI_0; | ||
880 | init_timer(&priv->thermal_throttle.ct_kill_exit_tm); | ||
881 | priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; | ||
882 | priv->thermal_throttle.ct_kill_exit_tm.function = | ||
883 | iwl_tt_check_exit_ct_kill; | ||
884 | init_timer(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
885 | priv->thermal_throttle.ct_kill_waiting_tm.data = (unsigned long)priv; | ||
886 | priv->thermal_throttle.ct_kill_waiting_tm.function = | ||
887 | iwl_tt_ready_for_ct_kill; | ||
888 | /* setup deferred ct kill work */ | ||
889 | INIT_WORK(&priv->tt_work, iwl_bg_tt_work); | ||
890 | INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); | ||
891 | INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); | ||
892 | |||
893 | if (priv->cfg->adv_thermal_throttle) { | ||
894 | IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); | ||
895 | tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * | ||
896 | IWL_TI_STATE_MAX, GFP_KERNEL); | ||
897 | tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * | ||
898 | IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), | ||
899 | GFP_KERNEL); | ||
900 | if (!tt->restriction || !tt->transaction) { | ||
901 | IWL_ERR(priv, "Fallback to Legacy Throttling\n"); | ||
902 | priv->thermal_throttle.advanced_tt = false; | ||
903 | kfree(tt->restriction); | ||
904 | tt->restriction = NULL; | ||
905 | kfree(tt->transaction); | ||
906 | tt->transaction = NULL; | ||
907 | } else { | ||
908 | transaction = tt->transaction + | ||
909 | (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); | ||
910 | memcpy(transaction, &tt_range_0[0], size); | ||
911 | transaction = tt->transaction + | ||
912 | (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); | ||
913 | memcpy(transaction, &tt_range_1[0], size); | ||
914 | transaction = tt->transaction + | ||
915 | (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); | ||
916 | memcpy(transaction, &tt_range_2[0], size); | ||
917 | transaction = tt->transaction + | ||
918 | (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); | ||
919 | memcpy(transaction, &tt_range_3[0], size); | ||
920 | size = sizeof(struct iwl_tt_restriction) * | ||
921 | IWL_TI_STATE_MAX; | ||
922 | memcpy(tt->restriction, | ||
923 | &restriction_range[0], size); | ||
924 | priv->thermal_throttle.advanced_tt = true; | ||
925 | } | ||
926 | } else { | ||
927 | IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); | ||
928 | priv->thermal_throttle.advanced_tt = false; | ||
929 | } | ||
930 | } | ||
931 | EXPORT_SYMBOL(iwl_tt_initialize); | ||
932 | |||
933 | /* cleanup thermal throttling management related memory and timer */ | ||
934 | void iwl_tt_exit(struct iwl_priv *priv) | ||
935 | { | ||
936 | struct iwl_tt_mgmt *tt = &priv->thermal_throttle; | ||
937 | |||
938 | /* stop ct_kill_exit_tm timer if activated */ | ||
939 | del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); | ||
940 | /* stop ct_kill_waiting_tm timer if activated */ | ||
941 | del_timer_sync(&priv->thermal_throttle.ct_kill_waiting_tm); | ||
942 | cancel_work_sync(&priv->tt_work); | ||
943 | cancel_work_sync(&priv->ct_enter); | ||
944 | cancel_work_sync(&priv->ct_exit); | ||
945 | |||
946 | if (priv->thermal_throttle.advanced_tt) { | ||
947 | /* free advance thermal throttling memory */ | ||
948 | kfree(tt->restriction); | ||
949 | tt->restriction = NULL; | ||
950 | kfree(tt->transaction); | ||
951 | tt->transaction = NULL; | ||
952 | } | ||
953 | } | ||
954 | EXPORT_SYMBOL(iwl_tt_exit); | ||
955 | |||
956 | /* initialize to default */ | 332 | /* initialize to default */ |
957 | void iwl_power_initialize(struct iwl_priv *priv) | 333 | void iwl_power_initialize(struct iwl_priv *priv) |
958 | { | 334 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h index 5db91c10dcc8..df81565a7cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ b/drivers/net/wireless/iwlwifi/iwl-power.h | |||
@@ -30,90 +30,6 @@ | |||
30 | 30 | ||
31 | #include "iwl-commands.h" | 31 | #include "iwl-commands.h" |
32 | 32 | ||
33 | #define IWL_ABSOLUTE_ZERO 0 | ||
34 | #define IWL_ABSOLUTE_MAX 0xFFFFFFFF | ||
35 | #define IWL_TT_INCREASE_MARGIN 5 | ||
36 | #define IWL_TT_CT_KILL_MARGIN 3 | ||
37 | |||
38 | enum iwl_antenna_ok { | ||
39 | IWL_ANT_OK_NONE, | ||
40 | IWL_ANT_OK_SINGLE, | ||
41 | IWL_ANT_OK_MULTI, | ||
42 | }; | ||
43 | |||
44 | /* Thermal Throttling State Machine states */ | ||
45 | enum iwl_tt_state { | ||
46 | IWL_TI_0, /* normal temperature, system power state */ | ||
47 | IWL_TI_1, /* high temperature detect, low power state */ | ||
48 | IWL_TI_2, /* higher temperature detected, lower power state */ | ||
49 | IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ | ||
50 | IWL_TI_STATE_MAX | ||
51 | }; | ||
52 | |||
53 | /** | ||
54 | * struct iwl_tt_restriction - Thermal Throttling restriction table | ||
55 | * @tx_stream: number of tx stream allowed | ||
56 | * @is_ht: ht enable/disable | ||
57 | * @rx_stream: number of rx stream allowed | ||
58 | * | ||
59 | * This table is used by advance thermal throttling management | ||
60 | * based on the current thermal throttling state, and determines | ||
61 | * the number of tx/rx streams and the status of HT operation. | ||
62 | */ | ||
63 | struct iwl_tt_restriction { | ||
64 | enum iwl_antenna_ok tx_stream; | ||
65 | enum iwl_antenna_ok rx_stream; | ||
66 | bool is_ht; | ||
67 | }; | ||
68 | |||
69 | /** | ||
70 | * struct iwl_tt_trans - Thermal Throttling transaction table | ||
71 | * @next_state: next thermal throttling mode | ||
72 | * @tt_low: low temperature threshold to change state | ||
73 | * @tt_high: high temperature threshold to change state | ||
74 | * | ||
75 | * This is used by the advanced thermal throttling algorithm | ||
76 | * to determine the next thermal state to go based on the | ||
77 | * current temperature. | ||
78 | */ | ||
79 | struct iwl_tt_trans { | ||
80 | enum iwl_tt_state next_state; | ||
81 | u32 tt_low; | ||
82 | u32 tt_high; | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * struct iwl_tt_mgnt - Thermal Throttling Management structure | ||
87 | * @advanced_tt: advanced thermal throttle required | ||
88 | * @state: current Thermal Throttling state | ||
89 | * @tt_power_mode: Thermal Throttling power mode index | ||
90 | * being used to set power level when | ||
91 | * when thermal throttling state != IWL_TI_0 | ||
92 | * the tt_power_mode should set to different | ||
93 | * power mode based on the current tt state | ||
94 | * @tt_previous_temperature: last measured temperature | ||
95 | * @iwl_tt_restriction: ptr to restriction tbl, used by advance | ||
96 | * thermal throttling to determine how many tx/rx streams | ||
97 | * should be used in tt state; and can HT be enabled or not | ||
98 | * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling | ||
99 | * state transaction | ||
100 | * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature | ||
101 | * @ct_kill_exit_tm: timer to exit thermal kill | ||
102 | */ | ||
103 | struct iwl_tt_mgmt { | ||
104 | enum iwl_tt_state state; | ||
105 | bool advanced_tt; | ||
106 | u8 tt_power_mode; | ||
107 | bool ct_kill_toggle; | ||
108 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
109 | s32 tt_previous_temp; | ||
110 | #endif | ||
111 | struct iwl_tt_restriction *restriction; | ||
112 | struct iwl_tt_trans *transaction; | ||
113 | struct timer_list ct_kill_exit_tm; | ||
114 | struct timer_list ct_kill_waiting_tm; | ||
115 | }; | ||
116 | |||
117 | enum iwl_power_level { | 33 | enum iwl_power_level { |
118 | IWL_POWER_INDEX_1, | 34 | IWL_POWER_INDEX_1, |
119 | IWL_POWER_INDEX_2, | 35 | IWL_POWER_INDEX_2, |
@@ -130,15 +46,6 @@ struct iwl_power_mgr { | |||
130 | }; | 46 | }; |
131 | 47 | ||
132 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); | 48 | int iwl_power_update_mode(struct iwl_priv *priv, bool force); |
133 | bool iwl_ht_enabled(struct iwl_priv *priv); | ||
134 | bool iwl_within_ct_kill_margin(struct iwl_priv *priv); | ||
135 | enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); | ||
136 | enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); | ||
137 | void iwl_tt_enter_ct_kill(struct iwl_priv *priv); | ||
138 | void iwl_tt_exit_ct_kill(struct iwl_priv *priv); | ||
139 | void iwl_tt_handler(struct iwl_priv *priv); | ||
140 | void iwl_tt_initialize(struct iwl_priv *priv); | ||
141 | void iwl_tt_exit(struct iwl_priv *priv); | ||
142 | void iwl_power_initialize(struct iwl_priv *priv); | 49 | void iwl_power_initialize(struct iwl_priv *priv); |
143 | 50 | ||
144 | extern bool no_sleep_autoadjust; | 51 | extern bool no_sleep_autoadjust; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a4b3663a262f..8d7fa59364fe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -378,7 +378,7 @@ void iwl_internal_short_hw_scan(struct iwl_priv *priv) | |||
378 | queue_work(priv->workqueue, &priv->start_internal_scan); | 378 | queue_work(priv->workqueue, &priv->start_internal_scan); |
379 | } | 379 | } |
380 | 380 | ||
381 | void iwl_bg_start_internal_scan(struct work_struct *work) | 381 | static void iwl_bg_start_internal_scan(struct work_struct *work) |
382 | { | 382 | { |
383 | struct iwl_priv *priv = | 383 | struct iwl_priv *priv = |
384 | container_of(work, struct iwl_priv, start_internal_scan); | 384 | container_of(work, struct iwl_priv, start_internal_scan); |
@@ -418,9 +418,8 @@ void iwl_bg_start_internal_scan(struct work_struct *work) | |||
418 | unlock: | 418 | unlock: |
419 | mutex_unlock(&priv->mutex); | 419 | mutex_unlock(&priv->mutex); |
420 | } | 420 | } |
421 | EXPORT_SYMBOL(iwl_bg_start_internal_scan); | ||
422 | 421 | ||
423 | void iwl_bg_scan_check(struct work_struct *data) | 422 | static void iwl_bg_scan_check(struct work_struct *data) |
424 | { | 423 | { |
425 | struct iwl_priv *priv = | 424 | struct iwl_priv *priv = |
426 | container_of(data, struct iwl_priv, scan_check.work); | 425 | container_of(data, struct iwl_priv, scan_check.work); |
@@ -439,7 +438,6 @@ void iwl_bg_scan_check(struct work_struct *data) | |||
439 | } | 438 | } |
440 | mutex_unlock(&priv->mutex); | 439 | mutex_unlock(&priv->mutex); |
441 | } | 440 | } |
442 | EXPORT_SYMBOL(iwl_bg_scan_check); | ||
443 | 441 | ||
444 | /** | 442 | /** |
445 | * iwl_fill_probe_req - fill in all required fields and IE for probe request | 443 | * iwl_fill_probe_req - fill in all required fields and IE for probe request |
@@ -489,7 +487,7 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, | |||
489 | } | 487 | } |
490 | EXPORT_SYMBOL(iwl_fill_probe_req); | 488 | EXPORT_SYMBOL(iwl_fill_probe_req); |
491 | 489 | ||
492 | void iwl_bg_abort_scan(struct work_struct *work) | 490 | static void iwl_bg_abort_scan(struct work_struct *work) |
493 | { | 491 | { |
494 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); | 492 | struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); |
495 | 493 | ||
@@ -504,13 +502,13 @@ void iwl_bg_abort_scan(struct work_struct *work) | |||
504 | iwl_send_scan_abort(priv); | 502 | iwl_send_scan_abort(priv); |
505 | mutex_unlock(&priv->mutex); | 503 | mutex_unlock(&priv->mutex); |
506 | } | 504 | } |
507 | EXPORT_SYMBOL(iwl_bg_abort_scan); | ||
508 | 505 | ||
509 | void iwl_bg_scan_completed(struct work_struct *work) | 506 | static void iwl_bg_scan_completed(struct work_struct *work) |
510 | { | 507 | { |
511 | struct iwl_priv *priv = | 508 | struct iwl_priv *priv = |
512 | container_of(work, struct iwl_priv, scan_completed); | 509 | container_of(work, struct iwl_priv, scan_completed); |
513 | bool internal = false; | 510 | bool internal = false; |
511 | bool scan_completed = false; | ||
514 | 512 | ||
515 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); | 513 | IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); |
516 | 514 | ||
@@ -521,7 +519,8 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
521 | priv->is_internal_short_scan = false; | 519 | priv->is_internal_short_scan = false; |
522 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); | 520 | IWL_DEBUG_SCAN(priv, "internal short scan completed\n"); |
523 | internal = true; | 521 | internal = true; |
524 | } else { | 522 | } else if (priv->scan_request) { |
523 | scan_completed = true; | ||
525 | priv->scan_request = NULL; | 524 | priv->scan_request = NULL; |
526 | priv->scan_vif = NULL; | 525 | priv->scan_vif = NULL; |
527 | } | 526 | } |
@@ -552,10 +551,9 @@ void iwl_bg_scan_completed(struct work_struct *work) | |||
552 | * into driver again into functions that will attempt to take | 551 | * into driver again into functions that will attempt to take |
553 | * mutex. | 552 | * mutex. |
554 | */ | 553 | */ |
555 | if (!internal) | 554 | if (scan_completed) |
556 | ieee80211_scan_completed(priv->hw, false); | 555 | ieee80211_scan_completed(priv->hw, false); |
557 | } | 556 | } |
558 | EXPORT_SYMBOL(iwl_bg_scan_completed); | ||
559 | 557 | ||
560 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 558 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |
561 | { | 559 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 7e0829be5e78..d5e8db37b86e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -818,7 +818,7 @@ int iwl_set_default_wep_key(struct iwl_priv *priv, | |||
818 | 818 | ||
819 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; | 819 | keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; |
820 | keyconf->hw_key_idx = HW_KEY_DEFAULT; | 820 | keyconf->hw_key_idx = HW_KEY_DEFAULT; |
821 | priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; | 821 | priv->stations[IWL_AP_ID].keyinfo.cipher = keyconf->cipher; |
822 | 822 | ||
823 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; | 823 | priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; |
824 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, | 824 | memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, |
@@ -856,7 +856,7 @@ static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, | |||
856 | 856 | ||
857 | spin_lock_irqsave(&priv->sta_lock, flags); | 857 | spin_lock_irqsave(&priv->sta_lock, flags); |
858 | 858 | ||
859 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 859 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
860 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 860 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
861 | priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; | 861 | priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; |
862 | 862 | ||
@@ -906,7 +906,7 @@ static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
906 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 906 | keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
907 | 907 | ||
908 | spin_lock_irqsave(&priv->sta_lock, flags); | 908 | spin_lock_irqsave(&priv->sta_lock, flags); |
909 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 909 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
910 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 910 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
911 | 911 | ||
912 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | 912 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, |
@@ -955,7 +955,7 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
955 | 955 | ||
956 | spin_lock_irqsave(&priv->sta_lock, flags); | 956 | spin_lock_irqsave(&priv->sta_lock, flags); |
957 | 957 | ||
958 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 958 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
959 | priv->stations[sta_id].keyinfo.keylen = 16; | 959 | priv->stations[sta_id].keyinfo.keylen = 16; |
960 | 960 | ||
961 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) | 961 | if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) |
@@ -1090,24 +1090,26 @@ int iwl_set_dynamic_key(struct iwl_priv *priv, | |||
1090 | priv->key_mapping_key++; | 1090 | priv->key_mapping_key++; |
1091 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 1091 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
1092 | 1092 | ||
1093 | switch (keyconf->alg) { | 1093 | switch (keyconf->cipher) { |
1094 | case ALG_CCMP: | 1094 | case WLAN_CIPHER_SUITE_CCMP: |
1095 | ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | 1095 | ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); |
1096 | break; | 1096 | break; |
1097 | case ALG_TKIP: | 1097 | case WLAN_CIPHER_SUITE_TKIP: |
1098 | ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | 1098 | ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); |
1099 | break; | 1099 | break; |
1100 | case ALG_WEP: | 1100 | case WLAN_CIPHER_SUITE_WEP40: |
1101 | case WLAN_CIPHER_SUITE_WEP104: | ||
1101 | ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); | 1102 | ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); |
1102 | break; | 1103 | break; |
1103 | default: | 1104 | default: |
1104 | IWL_ERR(priv, | 1105 | IWL_ERR(priv, |
1105 | "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); | 1106 | "Unknown alg: %s cipher = %x\n", __func__, |
1107 | keyconf->cipher); | ||
1106 | ret = -EINVAL; | 1108 | ret = -EINVAL; |
1107 | } | 1109 | } |
1108 | 1110 | ||
1109 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", | 1111 | IWL_DEBUG_WEP(priv, "Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n", |
1110 | keyconf->alg, keyconf->keylen, keyconf->keyidx, | 1112 | keyconf->cipher, keyconf->keylen, keyconf->keyidx, |
1111 | sta_id, ret); | 1113 | sta_id, ret); |
1112 | 1114 | ||
1113 | return ret; | 1115 | return ret; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index a81989c06983..c308dab14673 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -422,6 +422,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
422 | int len; | 422 | int len; |
423 | u32 idx; | 423 | u32 idx; |
424 | u16 fix_size; | 424 | u16 fix_size; |
425 | bool is_ct_kill = false; | ||
425 | 426 | ||
426 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); | 427 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); |
427 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); | 428 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); |
@@ -443,9 +444,11 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
443 | 444 | ||
444 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { | 445 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { |
445 | IWL_ERR(priv, "No space in command queue\n"); | 446 | IWL_ERR(priv, "No space in command queue\n"); |
446 | if (iwl_within_ct_kill_margin(priv)) | 447 | if (priv->cfg->ops->lib->tt_ops.ct_kill_check) { |
447 | iwl_tt_enter_ct_kill(priv); | 448 | is_ct_kill = |
448 | else { | 449 | priv->cfg->ops->lib->tt_ops.ct_kill_check(priv); |
450 | } | ||
451 | if (!is_ct_kill) { | ||
449 | IWL_ERR(priv, "Restarting adapter due to queue full\n"); | 452 | IWL_ERR(priv, "Restarting adapter due to queue full\n"); |
450 | queue_work(priv->workqueue, &priv->restart); | 453 | queue_work(priv->workqueue, &priv->restart); |
451 | } | 454 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 59a308b02f95..94d7e6e1323d 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/pci.h> | 35 | #include <linux/pci.h> |
36 | #include <linux/pci-aspm.h> | ||
36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
37 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
38 | #include <linux/delay.h> | 39 | #include <linux/delay.h> |
@@ -151,7 +152,7 @@ static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, | |||
151 | key_flags &= ~STA_KEY_FLG_INVALID; | 152 | key_flags &= ~STA_KEY_FLG_INVALID; |
152 | 153 | ||
153 | spin_lock_irqsave(&priv->sta_lock, flags); | 154 | spin_lock_irqsave(&priv->sta_lock, flags); |
154 | priv->stations[sta_id].keyinfo.alg = keyconf->alg; | 155 | priv->stations[sta_id].keyinfo.cipher = keyconf->cipher; |
155 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; | 156 | priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; |
156 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, | 157 | memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, |
157 | keyconf->keylen); | 158 | keyconf->keylen); |
@@ -222,23 +223,25 @@ static int iwl3945_set_dynamic_key(struct iwl_priv *priv, | |||
222 | 223 | ||
223 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; | 224 | keyconf->hw_key_idx = HW_KEY_DYNAMIC; |
224 | 225 | ||
225 | switch (keyconf->alg) { | 226 | switch (keyconf->cipher) { |
226 | case ALG_CCMP: | 227 | case WLAN_CIPHER_SUITE_CCMP: |
227 | ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); | 228 | ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); |
228 | break; | 229 | break; |
229 | case ALG_TKIP: | 230 | case WLAN_CIPHER_SUITE_TKIP: |
230 | ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); | 231 | ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); |
231 | break; | 232 | break; |
232 | case ALG_WEP: | 233 | case WLAN_CIPHER_SUITE_WEP40: |
234 | case WLAN_CIPHER_SUITE_WEP104: | ||
233 | ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); | 235 | ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); |
234 | break; | 236 | break; |
235 | default: | 237 | default: |
236 | IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); | 238 | IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__, |
239 | keyconf->cipher); | ||
237 | ret = -EINVAL; | 240 | ret = -EINVAL; |
238 | } | 241 | } |
239 | 242 | ||
240 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", | 243 | IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n", |
241 | keyconf->alg, keyconf->keylen, keyconf->keyidx, | 244 | keyconf->cipher, keyconf->keylen, keyconf->keyidx, |
242 | sta_id, ret); | 245 | sta_id, ret); |
243 | 246 | ||
244 | return ret; | 247 | return ret; |
@@ -254,10 +257,11 @@ static int iwl3945_remove_static_key(struct iwl_priv *priv) | |||
254 | static int iwl3945_set_static_key(struct iwl_priv *priv, | 257 | static int iwl3945_set_static_key(struct iwl_priv *priv, |
255 | struct ieee80211_key_conf *key) | 258 | struct ieee80211_key_conf *key) |
256 | { | 259 | { |
257 | if (key->alg == ALG_WEP) | 260 | if (key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
261 | key->cipher == WLAN_CIPHER_SUITE_WEP104) | ||
258 | return -EOPNOTSUPP; | 262 | return -EOPNOTSUPP; |
259 | 263 | ||
260 | IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg); | 264 | IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher); |
261 | return -EINVAL; | 265 | return -EINVAL; |
262 | } | 266 | } |
263 | 267 | ||
@@ -369,23 +373,25 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
369 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; | 373 | struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload; |
370 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; | 374 | struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; |
371 | 375 | ||
372 | switch (keyinfo->alg) { | 376 | tx_cmd->sec_ctl = 0; |
373 | case ALG_CCMP: | 377 | |
378 | switch (keyinfo->cipher) { | ||
379 | case WLAN_CIPHER_SUITE_CCMP: | ||
374 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; | 380 | tx_cmd->sec_ctl = TX_CMD_SEC_CCM; |
375 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); | 381 | memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen); |
376 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); | 382 | IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); |
377 | break; | 383 | break; |
378 | 384 | ||
379 | case ALG_TKIP: | 385 | case WLAN_CIPHER_SUITE_TKIP: |
380 | break; | 386 | break; |
381 | 387 | ||
382 | case ALG_WEP: | 388 | case WLAN_CIPHER_SUITE_WEP104: |
383 | tx_cmd->sec_ctl = TX_CMD_SEC_WEP | | 389 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; |
390 | /* fall through */ | ||
391 | case WLAN_CIPHER_SUITE_WEP40: | ||
392 | tx_cmd->sec_ctl |= TX_CMD_SEC_WEP | | ||
384 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; | 393 | (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; |
385 | 394 | ||
386 | if (keyinfo->keylen == 13) | ||
387 | tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; | ||
388 | |||
389 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); | 395 | memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen); |
390 | 396 | ||
391 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " | 397 | IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " |
@@ -393,7 +399,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, | |||
393 | break; | 399 | break; |
394 | 400 | ||
395 | default: | 401 | default: |
396 | IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg); | 402 | IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher); |
397 | break; | 403 | break; |
398 | } | 404 | } |
399 | } | 405 | } |
@@ -813,9 +819,9 @@ static void iwl3945_bg_beacon_update(struct work_struct *work) | |||
813 | static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | 819 | static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, |
814 | struct iwl_rx_mem_buffer *rxb) | 820 | struct iwl_rx_mem_buffer *rxb) |
815 | { | 821 | { |
816 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
817 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | 822 | struct iwl_rx_packet *pkt = rxb_addr(rxb); |
818 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); | 823 | struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); |
824 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
819 | u8 rate = beacon->beacon_notify_hdr.rate; | 825 | u8 rate = beacon->beacon_notify_hdr.rate; |
820 | 826 | ||
821 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " | 827 | IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " |
@@ -827,6 +833,8 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, | |||
827 | le32_to_cpu(beacon->low_tsf), rate); | 833 | le32_to_cpu(beacon->low_tsf), rate); |
828 | #endif | 834 | #endif |
829 | 835 | ||
836 | priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status); | ||
837 | |||
830 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && | 838 | if ((priv->iw_mode == NL80211_IFTYPE_AP) && |
831 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) | 839 | (!test_bit(STATUS_EXIT_PENDING, &priv->status))) |
832 | queue_work(priv->workqueue, &priv->beacon_update); | 840 | queue_work(priv->workqueue, &priv->beacon_update); |
@@ -3086,10 +3094,7 @@ void iwl3945_post_associate(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3086 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 3094 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
3087 | iwlcore_commit_rxon(priv); | 3095 | iwlcore_commit_rxon(priv); |
3088 | 3096 | ||
3089 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 3097 | rc = iwl_send_rxon_timing(priv, vif); |
3090 | iwl_setup_rxon_timing(priv, vif); | ||
3091 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3092 | sizeof(priv->rxon_timing), &priv->rxon_timing); | ||
3093 | if (rc) | 3098 | if (rc) |
3094 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3099 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3095 | "Attempting to continue.\n"); | 3100 | "Attempting to continue.\n"); |
@@ -3263,11 +3268,7 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3263 | iwlcore_commit_rxon(priv); | 3268 | iwlcore_commit_rxon(priv); |
3264 | 3269 | ||
3265 | /* RXON Timing */ | 3270 | /* RXON Timing */ |
3266 | memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); | 3271 | rc = iwl_send_rxon_timing(priv, vif); |
3267 | iwl_setup_rxon_timing(priv, vif); | ||
3268 | rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, | ||
3269 | sizeof(priv->rxon_timing), | ||
3270 | &priv->rxon_timing); | ||
3271 | if (rc) | 3272 | if (rc) |
3272 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 3273 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
3273 | "Attempting to continue.\n"); | 3274 | "Attempting to continue.\n"); |
@@ -3785,10 +3786,8 @@ static void iwl3945_setup_deferred_work(struct iwl_priv *priv) | |||
3785 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); | 3786 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); |
3786 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); | 3787 | INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); |
3787 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); | 3788 | INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll); |
3788 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 3789 | |
3789 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 3790 | iwl_setup_scan_deferred_work(priv); |
3790 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | ||
3791 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | ||
3792 | 3791 | ||
3793 | iwl3945_hw_setup_deferred_work(priv); | 3792 | iwl3945_hw_setup_deferred_work(priv); |
3794 | 3793 | ||
@@ -3853,6 +3852,7 @@ static struct ieee80211_ops iwl3945_hw_ops = { | |||
3853 | .hw_scan = iwl_mac_hw_scan, | 3852 | .hw_scan = iwl_mac_hw_scan, |
3854 | .sta_add = iwl3945_mac_sta_add, | 3853 | .sta_add = iwl3945_mac_sta_add, |
3855 | .sta_remove = iwl_mac_sta_remove, | 3854 | .sta_remove = iwl_mac_sta_remove, |
3855 | .tx_last_beacon = iwl_mac_tx_last_beacon, | ||
3856 | }; | 3856 | }; |
3857 | 3857 | ||
3858 | static int iwl3945_init_drv(struct iwl_priv *priv) | 3858 | static int iwl3945_init_drv(struct iwl_priv *priv) |
@@ -4009,6 +4009,9 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e | |||
4009 | /*************************** | 4009 | /*************************** |
4010 | * 2. Initializing PCI bus | 4010 | * 2. Initializing PCI bus |
4011 | * *************************/ | 4011 | * *************************/ |
4012 | pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | | ||
4013 | PCIE_LINK_STATE_CLKPM); | ||
4014 | |||
4012 | if (pci_enable_device(pdev)) { | 4015 | if (pci_enable_device(pdev)) { |
4013 | err = -ENODEV; | 4016 | err = -ENODEV; |
4014 | goto out_ieee80211_free_hw; | 4017 | goto out_ieee80211_free_hw; |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index c02fcedea9fa..a944893ae3ca 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -1195,11 +1195,8 @@ static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, | |||
1195 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " | 1195 | IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " |
1196 | "oid is 0x%x\n", hdr->oid); | 1196 | "oid is 0x%x\n", hdr->oid); |
1197 | 1197 | ||
1198 | if (hdr->oid <= WIFI_IF_NTFY_MAX) { | 1198 | set_bit(hdr->oid, &iwm->wifi_ntfy[0]); |
1199 | set_bit(hdr->oid, &iwm->wifi_ntfy[0]); | 1199 | wake_up_interruptible(&iwm->wifi_ntfy_queue); |
1200 | wake_up_interruptible(&iwm->wifi_ntfy_queue); | ||
1201 | } else | ||
1202 | return -EINVAL; | ||
1203 | 1200 | ||
1204 | switch (hdr->oid) { | 1201 | switch (hdr->oid) { |
1205 | case UMAC_WIFI_IF_CMD_SET_PROFILE: | 1202 | case UMAC_WIFI_IF_CMD_SET_PROFILE: |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 3e82f1627209..317f086ced0a 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/wait.h> | 10 | #include <linux/wait.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
13 | #include <linux/wait.h> | ||
13 | #include <linux/ieee80211.h> | 14 | #include <linux/ieee80211.h> |
14 | #include <net/cfg80211.h> | 15 | #include <net/cfg80211.h> |
15 | #include <asm/unaligned.h> | 16 | #include <asm/unaligned.h> |
@@ -526,20 +527,31 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
526 | 527 | ||
527 | pos = scanresp->bssdesc_and_tlvbuffer; | 528 | pos = scanresp->bssdesc_and_tlvbuffer; |
528 | 529 | ||
530 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_RSP", scanresp->bssdesc_and_tlvbuffer, | ||
531 | scanresp->bssdescriptsize); | ||
532 | |||
529 | tsfdesc = pos + bsssize; | 533 | tsfdesc = pos + bsssize; |
530 | tsfsize = 4 + 8 * scanresp->nr_sets; | 534 | tsfsize = 4 + 8 * scanresp->nr_sets; |
535 | lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TSF", (u8 *) tsfdesc, tsfsize); | ||
531 | 536 | ||
532 | /* Validity check: we expect a Marvell-Local TLV */ | 537 | /* Validity check: we expect a Marvell-Local TLV */ |
533 | i = get_unaligned_le16(tsfdesc); | 538 | i = get_unaligned_le16(tsfdesc); |
534 | tsfdesc += 2; | 539 | tsfdesc += 2; |
535 | if (i != TLV_TYPE_TSFTIMESTAMP) | 540 | if (i != TLV_TYPE_TSFTIMESTAMP) { |
541 | lbs_deb_scan("scan response: invalid TSF Timestamp %d\n", i); | ||
536 | goto done; | 542 | goto done; |
543 | } | ||
544 | |||
537 | /* Validity check: the TLV holds TSF values with 8 bytes each, so | 545 | /* Validity check: the TLV holds TSF values with 8 bytes each, so |
538 | * the size in the TLV must match the nr_sets value */ | 546 | * the size in the TLV must match the nr_sets value */ |
539 | i = get_unaligned_le16(tsfdesc); | 547 | i = get_unaligned_le16(tsfdesc); |
540 | tsfdesc += 2; | 548 | tsfdesc += 2; |
541 | if (i / 8 != scanresp->nr_sets) | 549 | if (i / 8 != scanresp->nr_sets) { |
550 | lbs_deb_scan("scan response: invalid number of TSF timestamp " | ||
551 | "sets (expected %d got %d)\n", scanresp->nr_sets, | ||
552 | i / 8); | ||
542 | goto done; | 553 | goto done; |
554 | } | ||
543 | 555 | ||
544 | for (i = 0; i < scanresp->nr_sets; i++) { | 556 | for (i = 0; i < scanresp->nr_sets; i++) { |
545 | const u8 *bssid; | 557 | const u8 *bssid; |
@@ -581,8 +593,11 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
581 | id = *pos++; | 593 | id = *pos++; |
582 | elen = *pos++; | 594 | elen = *pos++; |
583 | left -= 2; | 595 | left -= 2; |
584 | if (elen > left || elen == 0) | 596 | if (elen > left || elen == 0) { |
597 | lbs_deb_scan("scan response: invalid IE fmt\n"); | ||
585 | goto done; | 598 | goto done; |
599 | } | ||
600 | |||
586 | if (id == WLAN_EID_DS_PARAMS) | 601 | if (id == WLAN_EID_DS_PARAMS) |
587 | chan_no = *pos; | 602 | chan_no = *pos; |
588 | if (id == WLAN_EID_SSID) { | 603 | if (id == WLAN_EID_SSID) { |
@@ -613,7 +628,9 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
613 | capa, intvl, ie, ielen, | 628 | capa, intvl, ie, ielen, |
614 | LBS_SCAN_RSSI_TO_MBM(rssi), | 629 | LBS_SCAN_RSSI_TO_MBM(rssi), |
615 | GFP_KERNEL); | 630 | GFP_KERNEL); |
616 | } | 631 | } else |
632 | lbs_deb_scan("scan response: missing BSS channel IE\n"); | ||
633 | |||
617 | tsfdesc += 8; | 634 | tsfdesc += 8; |
618 | } | 635 | } |
619 | ret = 0; | 636 | ret = 0; |
@@ -1103,7 +1120,7 @@ static int lbs_associate(struct lbs_private *priv, | |||
1103 | lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); | 1120 | lbs_deb_hex(LBS_DEB_ASSOC, "Common Rates", tmp, pos - tmp); |
1104 | 1121 | ||
1105 | /* add auth type TLV */ | 1122 | /* add auth type TLV */ |
1106 | if (priv->fwrelease >= 0x09000000) | 1123 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) >= 9) |
1107 | pos += lbs_add_auth_type_tlv(pos, sme->auth_type); | 1124 | pos += lbs_add_auth_type_tlv(pos, sme->auth_type); |
1108 | 1125 | ||
1109 | /* add WPA/WPA2 TLV */ | 1126 | /* add WPA/WPA2 TLV */ |
@@ -1114,6 +1131,9 @@ static int lbs_associate(struct lbs_private *priv, | |||
1114 | (u16)(pos - (u8 *) &cmd->iebuf); | 1131 | (u16)(pos - (u8 *) &cmd->iebuf); |
1115 | cmd->hdr.size = cpu_to_le16(len); | 1132 | cmd->hdr.size = cpu_to_le16(len); |
1116 | 1133 | ||
1134 | lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_CMD", (u8 *) cmd, | ||
1135 | le16_to_cpu(cmd->hdr.size)); | ||
1136 | |||
1117 | /* store for later use */ | 1137 | /* store for later use */ |
1118 | memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); | 1138 | memcpy(priv->assoc_bss, bss->bssid, ETH_ALEN); |
1119 | 1139 | ||
@@ -1121,14 +1141,28 @@ static int lbs_associate(struct lbs_private *priv, | |||
1121 | if (ret) | 1141 | if (ret) |
1122 | goto done; | 1142 | goto done; |
1123 | 1143 | ||
1124 | |||
1125 | /* generate connect message to cfg80211 */ | 1144 | /* generate connect message to cfg80211 */ |
1126 | 1145 | ||
1127 | resp = (void *) cmd; /* recast for easier field access */ | 1146 | resp = (void *) cmd; /* recast for easier field access */ |
1128 | status = le16_to_cpu(resp->statuscode); | 1147 | status = le16_to_cpu(resp->statuscode); |
1129 | 1148 | ||
1130 | /* Convert statis code of old firmware */ | 1149 | /* Older FW versions map the IEEE 802.11 Status Code in the association |
1131 | if (priv->fwrelease < 0x09000000) | 1150 | * response to the following values returned in resp->statuscode: |
1151 | * | ||
1152 | * IEEE Status Code Marvell Status Code | ||
1153 | * 0 -> 0x0000 ASSOC_RESULT_SUCCESS | ||
1154 | * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1155 | * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1156 | * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1157 | * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED | ||
1158 | * others -> 0x0003 ASSOC_RESULT_REFUSED | ||
1159 | * | ||
1160 | * Other response codes: | ||
1161 | * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) | ||
1162 | * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for | ||
1163 | * association response from the AP) | ||
1164 | */ | ||
1165 | if (MRVL_FW_MAJOR_REV(priv->fwrelease) <= 8) { | ||
1132 | switch (status) { | 1166 | switch (status) { |
1133 | case 0: | 1167 | case 0: |
1134 | break; | 1168 | break; |
@@ -1150,11 +1184,16 @@ static int lbs_associate(struct lbs_private *priv, | |||
1150 | break; | 1184 | break; |
1151 | default: | 1185 | default: |
1152 | lbs_deb_assoc("association failure %d\n", status); | 1186 | lbs_deb_assoc("association failure %d\n", status); |
1153 | status = WLAN_STATUS_UNSPECIFIED_FAILURE; | 1187 | /* v5 OLPC firmware does return the AP status code if |
1188 | * it's not one of the values above. Let that through. | ||
1189 | */ | ||
1190 | break; | ||
1191 | } | ||
1154 | } | 1192 | } |
1155 | 1193 | ||
1156 | lbs_deb_assoc("status %d, capability 0x%04x\n", status, | 1194 | lbs_deb_assoc("status %d, statuscode 0x%04x, capability 0x%04x, " |
1157 | le16_to_cpu(resp->capability)); | 1195 | "aid 0x%04x\n", status, le16_to_cpu(resp->statuscode), |
1196 | le16_to_cpu(resp->capability), le16_to_cpu(resp->aid)); | ||
1158 | 1197 | ||
1159 | resp_ie_len = le16_to_cpu(resp->hdr.size) | 1198 | resp_ie_len = le16_to_cpu(resp->hdr.size) |
1160 | - sizeof(resp->hdr) | 1199 | - sizeof(resp->hdr) |
@@ -1174,7 +1213,6 @@ static int lbs_associate(struct lbs_private *priv, | |||
1174 | netif_tx_wake_all_queues(priv->dev); | 1213 | netif_tx_wake_all_queues(priv->dev); |
1175 | } | 1214 | } |
1176 | 1215 | ||
1177 | |||
1178 | done: | 1216 | done: |
1179 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); | 1217 | lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); |
1180 | return ret; | 1218 | return ret; |
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 1d141fefd767..2ae752d10065 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -8,7 +8,14 @@ | |||
8 | #define _LBS_DECL_H_ | 8 | #define _LBS_DECL_H_ |
9 | 9 | ||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/firmware.h> | ||
11 | 12 | ||
13 | /* Should be terminated by a NULL entry */ | ||
14 | struct lbs_fw_table { | ||
15 | int model; | ||
16 | const char *helper; | ||
17 | const char *fwname; | ||
18 | }; | ||
12 | 19 | ||
13 | struct lbs_private; | 20 | struct lbs_private; |
14 | struct sk_buff; | 21 | struct sk_buff; |
@@ -53,4 +60,10 @@ int lbs_exit_auto_deep_sleep(struct lbs_private *priv); | |||
53 | u32 lbs_fw_index_to_data_rate(u8 index); | 60 | u32 lbs_fw_index_to_data_rate(u8 index); |
54 | u8 lbs_data_rate_to_fw_index(u32 rate); | 61 | u8 lbs_data_rate_to_fw_index(u32 rate); |
55 | 62 | ||
63 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
64 | const char *user_mainfw, u32 card_model, | ||
65 | const struct lbs_fw_table *fw_table, | ||
66 | const struct firmware **helper, | ||
67 | const struct firmware **mainfw); | ||
68 | |||
56 | #endif | 69 | #endif |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 9c298396be50..e213a5dc049d 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -48,7 +48,6 @@ | |||
48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); | 48 | MODULE_AUTHOR("Holger Schurig <hs4233@mail.mn-solutions.de>"); |
49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); | 49 | MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); |
50 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
51 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
52 | 51 | ||
53 | 52 | ||
54 | 53 | ||
@@ -61,9 +60,34 @@ struct if_cs_card { | |||
61 | struct lbs_private *priv; | 60 | struct lbs_private *priv; |
62 | void __iomem *iobase; | 61 | void __iomem *iobase; |
63 | bool align_regs; | 62 | bool align_regs; |
63 | u32 model; | ||
64 | }; | 64 | }; |
65 | 65 | ||
66 | 66 | ||
67 | enum { | ||
68 | MODEL_UNKNOWN = 0x00, | ||
69 | MODEL_8305 = 0x01, | ||
70 | MODEL_8381 = 0x02, | ||
71 | MODEL_8385 = 0x03 | ||
72 | }; | ||
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8305, "libertas/cf8305.bin", NULL }, | ||
76 | { MODEL_8305, "libertas_cs_helper.fw", NULL }, | ||
77 | { MODEL_8381, "libertas/cf8381_helper.bin", "libertas/cf8381.bin" }, | ||
78 | { MODEL_8381, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
79 | { MODEL_8385, "libertas/cf8385_helper.bin", "libertas/cf8385.bin" }, | ||
80 | { MODEL_8385, "libertas_cs_helper.fw", "libertas_cs.fw" }, | ||
81 | { 0, NULL, NULL } | ||
82 | }; | ||
83 | MODULE_FIRMWARE("libertas/cf8305.bin"); | ||
84 | MODULE_FIRMWARE("libertas/cf8381_helper.bin"); | ||
85 | MODULE_FIRMWARE("libertas/cf8381.bin"); | ||
86 | MODULE_FIRMWARE("libertas/cf8385_helper.bin"); | ||
87 | MODULE_FIRMWARE("libertas/cf8385.bin"); | ||
88 | MODULE_FIRMWARE("libertas_cs_helper.fw"); | ||
89 | MODULE_FIRMWARE("libertas_cs.fw"); | ||
90 | |||
67 | 91 | ||
68 | /********************************************************************/ | 92 | /********************************************************************/ |
69 | /* Hardware access */ | 93 | /* Hardware access */ |
@@ -289,22 +313,19 @@ static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 r | |||
289 | #define CF8385_MANFID 0x02df | 313 | #define CF8385_MANFID 0x02df |
290 | #define CF8385_CARDID 0x8103 | 314 | #define CF8385_CARDID 0x8103 |
291 | 315 | ||
292 | static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) | 316 | /* FIXME: just use the 'driver_info' field of 'struct pcmcia_device_id' when |
293 | { | 317 | * that gets fixed. Currently there's no way to access it from the probe hook. |
294 | return (p_dev->manf_id == CF8305_MANFID && | 318 | */ |
295 | p_dev->card_id == CF8305_CARDID); | 319 | static inline u32 get_model(u16 manf_id, u16 card_id) |
296 | } | ||
297 | |||
298 | static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) | ||
299 | { | ||
300 | return (p_dev->manf_id == CF8381_MANFID && | ||
301 | p_dev->card_id == CF8381_CARDID); | ||
302 | } | ||
303 | |||
304 | static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) | ||
305 | { | 320 | { |
306 | return (p_dev->manf_id == CF8385_MANFID && | 321 | /* NOTE: keep in sync with if_cs_ids */ |
307 | p_dev->card_id == CF8385_CARDID); | 322 | if (manf_id == CF8305_MANFID && card_id == CF8305_CARDID) |
323 | return MODEL_8305; | ||
324 | else if (manf_id == CF8381_MANFID && card_id == CF8381_CARDID) | ||
325 | return MODEL_8381; | ||
326 | else if (manf_id == CF8385_MANFID && card_id == CF8385_CARDID) | ||
327 | return MODEL_8385; | ||
328 | return MODEL_UNKNOWN; | ||
308 | } | 329 | } |
309 | 330 | ||
310 | /********************************************************************/ | 331 | /********************************************************************/ |
@@ -558,12 +579,11 @@ static irqreturn_t if_cs_interrupt(int irq, void *data) | |||
558 | * | 579 | * |
559 | * Return 0 on success | 580 | * Return 0 on success |
560 | */ | 581 | */ |
561 | static int if_cs_prog_helper(struct if_cs_card *card) | 582 | static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) |
562 | { | 583 | { |
563 | int ret = 0; | 584 | int ret = 0; |
564 | int sent = 0; | 585 | int sent = 0; |
565 | u8 scratch; | 586 | u8 scratch; |
566 | const struct firmware *fw; | ||
567 | 587 | ||
568 | lbs_deb_enter(LBS_DEB_CS); | 588 | lbs_deb_enter(LBS_DEB_CS); |
569 | 589 | ||
@@ -589,14 +609,6 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
589 | goto done; | 609 | goto done; |
590 | } | 610 | } |
591 | 611 | ||
592 | /* TODO: make firmware file configurable */ | ||
593 | ret = request_firmware(&fw, "libertas_cs_helper.fw", | ||
594 | &card->p_dev->dev); | ||
595 | if (ret) { | ||
596 | lbs_pr_err("can't load helper firmware\n"); | ||
597 | ret = -ENODEV; | ||
598 | goto done; | ||
599 | } | ||
600 | lbs_deb_cs("helper size %td\n", fw->size); | 612 | lbs_deb_cs("helper size %td\n", fw->size); |
601 | 613 | ||
602 | /* "Set the 5 bytes of the helper image to 0" */ | 614 | /* "Set the 5 bytes of the helper image to 0" */ |
@@ -635,7 +647,7 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
635 | if (ret < 0) { | 647 | if (ret < 0) { |
636 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", | 648 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", |
637 | sent, ret); | 649 | sent, ret); |
638 | goto err_release; | 650 | goto done; |
639 | } | 651 | } |
640 | 652 | ||
641 | if (count == 0) | 653 | if (count == 0) |
@@ -644,17 +656,14 @@ static int if_cs_prog_helper(struct if_cs_card *card) | |||
644 | sent += count; | 656 | sent += count; |
645 | } | 657 | } |
646 | 658 | ||
647 | err_release: | ||
648 | release_firmware(fw); | ||
649 | done: | 659 | done: |
650 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 660 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
651 | return ret; | 661 | return ret; |
652 | } | 662 | } |
653 | 663 | ||
654 | 664 | ||
655 | static int if_cs_prog_real(struct if_cs_card *card) | 665 | static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) |
656 | { | 666 | { |
657 | const struct firmware *fw; | ||
658 | int ret = 0; | 667 | int ret = 0; |
659 | int retry = 0; | 668 | int retry = 0; |
660 | int len = 0; | 669 | int len = 0; |
@@ -662,21 +671,13 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
662 | 671 | ||
663 | lbs_deb_enter(LBS_DEB_CS); | 672 | lbs_deb_enter(LBS_DEB_CS); |
664 | 673 | ||
665 | /* TODO: make firmware file configurable */ | ||
666 | ret = request_firmware(&fw, "libertas_cs.fw", | ||
667 | &card->p_dev->dev); | ||
668 | if (ret) { | ||
669 | lbs_pr_err("can't load firmware\n"); | ||
670 | ret = -ENODEV; | ||
671 | goto done; | ||
672 | } | ||
673 | lbs_deb_cs("fw size %td\n", fw->size); | 674 | lbs_deb_cs("fw size %td\n", fw->size); |
674 | 675 | ||
675 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, | 676 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, |
676 | IF_CS_SQ_HELPER_OK); | 677 | IF_CS_SQ_HELPER_OK); |
677 | if (ret < 0) { | 678 | if (ret < 0) { |
678 | lbs_pr_err("helper firmware doesn't answer\n"); | 679 | lbs_pr_err("helper firmware doesn't answer\n"); |
679 | goto err_release; | 680 | goto done; |
680 | } | 681 | } |
681 | 682 | ||
682 | for (sent = 0; sent < fw->size; sent += len) { | 683 | for (sent = 0; sent < fw->size; sent += len) { |
@@ -691,7 +692,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
691 | if (retry > 20) { | 692 | if (retry > 20) { |
692 | lbs_pr_err("could not download firmware\n"); | 693 | lbs_pr_err("could not download firmware\n"); |
693 | ret = -ENODEV; | 694 | ret = -ENODEV; |
694 | goto err_release; | 695 | goto done; |
695 | } | 696 | } |
696 | if (retry) { | 697 | if (retry) { |
697 | sent -= len; | 698 | sent -= len; |
@@ -710,7 +711,7 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
710 | IF_CS_BIT_COMMAND); | 711 | IF_CS_BIT_COMMAND); |
711 | if (ret < 0) { | 712 | if (ret < 0) { |
712 | lbs_pr_err("can't download firmware at 0x%x\n", sent); | 713 | lbs_pr_err("can't download firmware at 0x%x\n", sent); |
713 | goto err_release; | 714 | goto done; |
714 | } | 715 | } |
715 | } | 716 | } |
716 | 717 | ||
@@ -718,9 +719,6 @@ static int if_cs_prog_real(struct if_cs_card *card) | |||
718 | if (ret < 0) | 719 | if (ret < 0) |
719 | lbs_pr_err("firmware download failed\n"); | 720 | lbs_pr_err("firmware download failed\n"); |
720 | 721 | ||
721 | err_release: | ||
722 | release_firmware(fw); | ||
723 | |||
724 | done: | 722 | done: |
725 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 723 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
726 | return ret; | 724 | return ret; |
@@ -824,6 +822,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
824 | unsigned int prod_id; | 822 | unsigned int prod_id; |
825 | struct lbs_private *priv; | 823 | struct lbs_private *priv; |
826 | struct if_cs_card *card; | 824 | struct if_cs_card *card; |
825 | const struct firmware *helper = NULL; | ||
826 | const struct firmware *mainfw = NULL; | ||
827 | 827 | ||
828 | lbs_deb_enter(LBS_DEB_CS); | 828 | lbs_deb_enter(LBS_DEB_CS); |
829 | 829 | ||
@@ -843,7 +843,6 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
843 | goto out1; | 843 | goto out1; |
844 | } | 844 | } |
845 | 845 | ||
846 | |||
847 | /* | 846 | /* |
848 | * Allocate an interrupt line. Note that this does not assign | 847 | * Allocate an interrupt line. Note that this does not assign |
849 | * a handler to the interrupt, unless the 'Handler' member of | 848 | * a handler to the interrupt, unless the 'Handler' member of |
@@ -881,34 +880,47 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
881 | */ | 880 | */ |
882 | card->align_regs = 0; | 881 | card->align_regs = 0; |
883 | 882 | ||
883 | card->model = get_model(p_dev->manf_id, p_dev->card_id); | ||
884 | if (card->model == MODEL_UNKNOWN) { | ||
885 | lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", | ||
886 | p_dev->manf_id, p_dev->card_id); | ||
887 | goto out2; | ||
888 | } | ||
889 | |||
884 | /* Check if we have a current silicon */ | 890 | /* Check if we have a current silicon */ |
885 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); | 891 | prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); |
886 | if (if_cs_hw_is_cf8305(p_dev)) { | 892 | if (card->model == MODEL_8305) { |
887 | card->align_regs = 1; | 893 | card->align_regs = 1; |
888 | if (prod_id < IF_CS_CF8305_B1_REV) { | 894 | if (prod_id < IF_CS_CF8305_B1_REV) { |
889 | lbs_pr_err("old chips like 8305 rev B3 " | 895 | lbs_pr_err("8305 rev B0 and older are not supported\n"); |
890 | "aren't supported\n"); | ||
891 | ret = -ENODEV; | 896 | ret = -ENODEV; |
892 | goto out2; | 897 | goto out2; |
893 | } | 898 | } |
894 | } | 899 | } |
895 | 900 | ||
896 | if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { | 901 | if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { |
897 | lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); | 902 | lbs_pr_err("8381 rev B2 and older are not supported\n"); |
898 | ret = -ENODEV; | 903 | ret = -ENODEV; |
899 | goto out2; | 904 | goto out2; |
900 | } | 905 | } |
901 | 906 | ||
902 | if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { | 907 | if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { |
903 | lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); | 908 | lbs_pr_err("8385 rev B0 and older are not supported\n"); |
904 | ret = -ENODEV; | 909 | ret = -ENODEV; |
905 | goto out2; | 910 | goto out2; |
906 | } | 911 | } |
907 | 912 | ||
913 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | ||
914 | &fw_table[0], &helper, &mainfw); | ||
915 | if (ret) { | ||
916 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
917 | goto out2; | ||
918 | } | ||
919 | |||
908 | /* Load the firmware early, before calling into libertas.ko */ | 920 | /* Load the firmware early, before calling into libertas.ko */ |
909 | ret = if_cs_prog_helper(card); | 921 | ret = if_cs_prog_helper(card, helper); |
910 | if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) | 922 | if (ret == 0 && (card->model != MODEL_8305)) |
911 | ret = if_cs_prog_real(card); | 923 | ret = if_cs_prog_real(card, mainfw); |
912 | if (ret) | 924 | if (ret) |
913 | goto out2; | 925 | goto out2; |
914 | 926 | ||
@@ -957,6 +969,11 @@ out2: | |||
957 | out1: | 969 | out1: |
958 | pcmcia_disable_device(p_dev); | 970 | pcmcia_disable_device(p_dev); |
959 | out: | 971 | out: |
972 | if (helper) | ||
973 | release_firmware(helper); | ||
974 | if (mainfw) | ||
975 | release_firmware(mainfw); | ||
976 | |||
960 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 977 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
961 | return ret; | 978 | return ret; |
962 | } | 979 | } |
@@ -993,6 +1010,7 @@ static struct pcmcia_device_id if_cs_ids[] = { | |||
993 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), | 1010 | PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), |
994 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), | 1011 | PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), |
995 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), | 1012 | PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), |
1013 | /* NOTE: keep in sync with get_model() */ | ||
996 | PCMCIA_DEVICE_NULL, | 1014 | PCMCIA_DEVICE_NULL, |
997 | }; | 1015 | }; |
998 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); | 1016 | MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index ba854c70ab94..1bbaaa44d981 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -76,36 +76,32 @@ static const struct sdio_device_id if_sdio_ids[] = { | |||
76 | 76 | ||
77 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); | 77 | MODULE_DEVICE_TABLE(sdio, if_sdio_ids); |
78 | 78 | ||
79 | struct if_sdio_model { | 79 | #define MODEL_8385 0x04 |
80 | int model; | 80 | #define MODEL_8686 0x0b |
81 | const char *helper; | 81 | #define MODEL_8688 0x10 |
82 | const char *firmware; | 82 | |
83 | }; | 83 | static const struct lbs_fw_table fw_table[] = { |
84 | 84 | { MODEL_8385, "libertas/sd8385_helper.bin", "libertas/sd8385.bin" }, | |
85 | static struct if_sdio_model if_sdio_models[] = { | 85 | { MODEL_8385, "sd8385_helper.bin", "sd8385.bin" }, |
86 | { | 86 | { MODEL_8686, "libertas/sd8686_v9_helper.bin", "libertas/sd8686_v9.bin" }, |
87 | /* 8385 */ | 87 | { MODEL_8686, "libertas/sd8686_v8_helper.bin", "libertas/sd8686_v8.bin" }, |
88 | .model = IF_SDIO_MODEL_8385, | 88 | { MODEL_8686, "sd8686_helper.bin", "sd8686.bin" }, |
89 | .helper = "sd8385_helper.bin", | 89 | { MODEL_8688, "libertas/sd8688_helper.bin", "libertas/sd8688.bin" }, |
90 | .firmware = "sd8385.bin", | 90 | { MODEL_8688, "sd8688_helper.bin", "sd8688.bin" }, |
91 | }, | 91 | { 0, NULL, NULL } |
92 | { | ||
93 | /* 8686 */ | ||
94 | .model = IF_SDIO_MODEL_8686, | ||
95 | .helper = "sd8686_helper.bin", | ||
96 | .firmware = "sd8686.bin", | ||
97 | }, | ||
98 | { | ||
99 | /* 8688 */ | ||
100 | .model = IF_SDIO_MODEL_8688, | ||
101 | .helper = "sd8688_helper.bin", | ||
102 | .firmware = "sd8688.bin", | ||
103 | }, | ||
104 | }; | 92 | }; |
93 | MODULE_FIRMWARE("libertas/sd8385_helper.bin"); | ||
94 | MODULE_FIRMWARE("libertas/sd8385.bin"); | ||
105 | MODULE_FIRMWARE("sd8385_helper.bin"); | 95 | MODULE_FIRMWARE("sd8385_helper.bin"); |
106 | MODULE_FIRMWARE("sd8385.bin"); | 96 | MODULE_FIRMWARE("sd8385.bin"); |
97 | MODULE_FIRMWARE("libertas/sd8686_v9_helper.bin"); | ||
98 | MODULE_FIRMWARE("libertas/sd8686_v9.bin"); | ||
99 | MODULE_FIRMWARE("libertas/sd8686_v8_helper.bin"); | ||
100 | MODULE_FIRMWARE("libertas/sd8686_v8.bin"); | ||
107 | MODULE_FIRMWARE("sd8686_helper.bin"); | 101 | MODULE_FIRMWARE("sd8686_helper.bin"); |
108 | MODULE_FIRMWARE("sd8686.bin"); | 102 | MODULE_FIRMWARE("sd8686.bin"); |
103 | MODULE_FIRMWARE("libertas/sd8688_helper.bin"); | ||
104 | MODULE_FIRMWARE("libertas/sd8688.bin"); | ||
109 | MODULE_FIRMWARE("sd8688_helper.bin"); | 105 | MODULE_FIRMWARE("sd8688_helper.bin"); |
110 | MODULE_FIRMWARE("sd8688.bin"); | 106 | MODULE_FIRMWARE("sd8688.bin"); |
111 | 107 | ||
@@ -187,11 +183,11 @@ static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err) | |||
187 | u16 rx_len; | 183 | u16 rx_len; |
188 | 184 | ||
189 | switch (card->model) { | 185 | switch (card->model) { |
190 | case IF_SDIO_MODEL_8385: | 186 | case MODEL_8385: |
191 | case IF_SDIO_MODEL_8686: | 187 | case MODEL_8686: |
192 | rx_len = if_sdio_read_scratch(card, &ret); | 188 | rx_len = if_sdio_read_scratch(card, &ret); |
193 | break; | 189 | break; |
194 | case IF_SDIO_MODEL_8688: | 190 | case MODEL_8688: |
195 | default: /* for newer chipsets */ | 191 | default: /* for newer chipsets */ |
196 | rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); | 192 | rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); |
197 | if (!ret) | 193 | if (!ret) |
@@ -288,7 +284,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card, | |||
288 | 284 | ||
289 | lbs_deb_enter(LBS_DEB_SDIO); | 285 | lbs_deb_enter(LBS_DEB_SDIO); |
290 | 286 | ||
291 | if (card->model == IF_SDIO_MODEL_8385) { | 287 | if (card->model == MODEL_8385) { |
292 | event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); | 288 | event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); |
293 | if (ret) | 289 | if (ret) |
294 | goto out; | 290 | goto out; |
@@ -466,10 +462,10 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) | |||
466 | 462 | ||
467 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) | 463 | #define FW_DL_READY_STATUS (IF_SDIO_IO_RDY | IF_SDIO_DL_RDY) |
468 | 464 | ||
469 | static int if_sdio_prog_helper(struct if_sdio_card *card) | 465 | static int if_sdio_prog_helper(struct if_sdio_card *card, |
466 | const struct firmware *fw) | ||
470 | { | 467 | { |
471 | int ret; | 468 | int ret; |
472 | const struct firmware *fw; | ||
473 | unsigned long timeout; | 469 | unsigned long timeout; |
474 | u8 *chunk_buffer; | 470 | u8 *chunk_buffer; |
475 | u32 chunk_size; | 471 | u32 chunk_size; |
@@ -478,16 +474,10 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
478 | 474 | ||
479 | lbs_deb_enter(LBS_DEB_SDIO); | 475 | lbs_deb_enter(LBS_DEB_SDIO); |
480 | 476 | ||
481 | ret = request_firmware(&fw, card->helper, &card->func->dev); | ||
482 | if (ret) { | ||
483 | lbs_pr_err("can't load helper firmware\n"); | ||
484 | goto out; | ||
485 | } | ||
486 | |||
487 | chunk_buffer = kzalloc(64, GFP_KERNEL); | 477 | chunk_buffer = kzalloc(64, GFP_KERNEL); |
488 | if (!chunk_buffer) { | 478 | if (!chunk_buffer) { |
489 | ret = -ENOMEM; | 479 | ret = -ENOMEM; |
490 | goto release_fw; | 480 | goto out; |
491 | } | 481 | } |
492 | 482 | ||
493 | sdio_claim_host(card->func); | 483 | sdio_claim_host(card->func); |
@@ -562,22 +552,19 @@ static int if_sdio_prog_helper(struct if_sdio_card *card) | |||
562 | release: | 552 | release: |
563 | sdio_release_host(card->func); | 553 | sdio_release_host(card->func); |
564 | kfree(chunk_buffer); | 554 | kfree(chunk_buffer); |
565 | release_fw: | ||
566 | release_firmware(fw); | ||
567 | 555 | ||
568 | out: | 556 | out: |
569 | if (ret) | 557 | if (ret) |
570 | lbs_pr_err("failed to load helper firmware\n"); | 558 | lbs_pr_err("failed to load helper firmware\n"); |
571 | 559 | ||
572 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 560 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
573 | |||
574 | return ret; | 561 | return ret; |
575 | } | 562 | } |
576 | 563 | ||
577 | static int if_sdio_prog_real(struct if_sdio_card *card) | 564 | static int if_sdio_prog_real(struct if_sdio_card *card, |
565 | const struct firmware *fw) | ||
578 | { | 566 | { |
579 | int ret; | 567 | int ret; |
580 | const struct firmware *fw; | ||
581 | unsigned long timeout; | 568 | unsigned long timeout; |
582 | u8 *chunk_buffer; | 569 | u8 *chunk_buffer; |
583 | u32 chunk_size; | 570 | u32 chunk_size; |
@@ -586,16 +573,10 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
586 | 573 | ||
587 | lbs_deb_enter(LBS_DEB_SDIO); | 574 | lbs_deb_enter(LBS_DEB_SDIO); |
588 | 575 | ||
589 | ret = request_firmware(&fw, card->firmware, &card->func->dev); | ||
590 | if (ret) { | ||
591 | lbs_pr_err("can't load firmware\n"); | ||
592 | goto out; | ||
593 | } | ||
594 | |||
595 | chunk_buffer = kzalloc(512, GFP_KERNEL); | 576 | chunk_buffer = kzalloc(512, GFP_KERNEL); |
596 | if (!chunk_buffer) { | 577 | if (!chunk_buffer) { |
597 | ret = -ENOMEM; | 578 | ret = -ENOMEM; |
598 | goto release_fw; | 579 | goto out; |
599 | } | 580 | } |
600 | 581 | ||
601 | sdio_claim_host(card->func); | 582 | sdio_claim_host(card->func); |
@@ -685,15 +666,12 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
685 | release: | 666 | release: |
686 | sdio_release_host(card->func); | 667 | sdio_release_host(card->func); |
687 | kfree(chunk_buffer); | 668 | kfree(chunk_buffer); |
688 | release_fw: | ||
689 | release_firmware(fw); | ||
690 | 669 | ||
691 | out: | 670 | out: |
692 | if (ret) | 671 | if (ret) |
693 | lbs_pr_err("failed to load firmware\n"); | 672 | lbs_pr_err("failed to load firmware\n"); |
694 | 673 | ||
695 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 674 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
696 | |||
697 | return ret; | 675 | return ret; |
698 | } | 676 | } |
699 | 677 | ||
@@ -701,6 +679,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
701 | { | 679 | { |
702 | int ret; | 680 | int ret; |
703 | u16 scratch; | 681 | u16 scratch; |
682 | const struct firmware *helper = NULL; | ||
683 | const struct firmware *mainfw = NULL; | ||
704 | 684 | ||
705 | lbs_deb_enter(LBS_DEB_SDIO); | 685 | lbs_deb_enter(LBS_DEB_SDIO); |
706 | 686 | ||
@@ -718,11 +698,18 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
718 | goto success; | 698 | goto success; |
719 | } | 699 | } |
720 | 700 | ||
721 | ret = if_sdio_prog_helper(card); | 701 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, |
702 | card->model, &fw_table[0], &helper, &mainfw); | ||
703 | if (ret) { | ||
704 | lbs_pr_err("failed to find firmware (%d)\n", ret); | ||
705 | goto out; | ||
706 | } | ||
707 | |||
708 | ret = if_sdio_prog_helper(card, helper); | ||
722 | if (ret) | 709 | if (ret) |
723 | goto out; | 710 | goto out; |
724 | 711 | ||
725 | ret = if_sdio_prog_real(card); | 712 | ret = if_sdio_prog_real(card, mainfw); |
726 | if (ret) | 713 | if (ret) |
727 | goto out; | 714 | goto out; |
728 | 715 | ||
@@ -733,8 +720,12 @@ success: | |||
733 | ret = 0; | 720 | ret = 0; |
734 | 721 | ||
735 | out: | 722 | out: |
736 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 723 | if (helper) |
724 | release_firmware(helper); | ||
725 | if (mainfw) | ||
726 | release_firmware(mainfw); | ||
737 | 727 | ||
728 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | ||
738 | return ret; | 729 | return ret; |
739 | } | 730 | } |
740 | 731 | ||
@@ -938,7 +929,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
938 | "ID: %x", &model) == 1) | 929 | "ID: %x", &model) == 1) |
939 | break; | 930 | break; |
940 | if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { | 931 | if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { |
941 | model = IF_SDIO_MODEL_8385; | 932 | model = MODEL_8385; |
942 | break; | 933 | break; |
943 | } | 934 | } |
944 | } | 935 | } |
@@ -956,13 +947,13 @@ static int if_sdio_probe(struct sdio_func *func, | |||
956 | card->model = model; | 947 | card->model = model; |
957 | 948 | ||
958 | switch (card->model) { | 949 | switch (card->model) { |
959 | case IF_SDIO_MODEL_8385: | 950 | case MODEL_8385: |
960 | card->scratch_reg = IF_SDIO_SCRATCH_OLD; | 951 | card->scratch_reg = IF_SDIO_SCRATCH_OLD; |
961 | break; | 952 | break; |
962 | case IF_SDIO_MODEL_8686: | 953 | case MODEL_8686: |
963 | card->scratch_reg = IF_SDIO_SCRATCH; | 954 | card->scratch_reg = IF_SDIO_SCRATCH; |
964 | break; | 955 | break; |
965 | case IF_SDIO_MODEL_8688: | 956 | case MODEL_8688: |
966 | default: /* for newer chipsets */ | 957 | default: /* for newer chipsets */ |
967 | card->scratch_reg = IF_SDIO_FW_STATUS; | 958 | card->scratch_reg = IF_SDIO_FW_STATUS; |
968 | break; | 959 | break; |
@@ -972,49 +963,17 @@ static int if_sdio_probe(struct sdio_func *func, | |||
972 | card->workqueue = create_workqueue("libertas_sdio"); | 963 | card->workqueue = create_workqueue("libertas_sdio"); |
973 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); | 964 | INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); |
974 | 965 | ||
975 | for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { | 966 | /* Check if we support this card */ |
976 | if (card->model == if_sdio_models[i].model) | 967 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
968 | if (card->model == fw_table[i].model) | ||
977 | break; | 969 | break; |
978 | } | 970 | } |
979 | 971 | if (i == ARRAY_SIZE(fw_table)) { | |
980 | if (i == ARRAY_SIZE(if_sdio_models)) { | ||
981 | lbs_pr_err("unknown card model 0x%x\n", card->model); | 972 | lbs_pr_err("unknown card model 0x%x\n", card->model); |
982 | ret = -ENODEV; | 973 | ret = -ENODEV; |
983 | goto free; | 974 | goto free; |
984 | } | 975 | } |
985 | 976 | ||
986 | card->helper = if_sdio_models[i].helper; | ||
987 | card->firmware = if_sdio_models[i].firmware; | ||
988 | |||
989 | kparam_block_sysfs_write(helper_name); | ||
990 | if (lbs_helper_name) { | ||
991 | char *helper = kstrdup(lbs_helper_name, GFP_KERNEL); | ||
992 | if (!helper) { | ||
993 | kparam_unblock_sysfs_write(helper_name); | ||
994 | ret = -ENOMEM; | ||
995 | goto free; | ||
996 | } | ||
997 | lbs_deb_sdio("overriding helper firmware: %s\n", | ||
998 | lbs_helper_name); | ||
999 | card->helper = helper; | ||
1000 | card->helper_allocated = true; | ||
1001 | } | ||
1002 | kparam_unblock_sysfs_write(helper_name); | ||
1003 | |||
1004 | kparam_block_sysfs_write(fw_name); | ||
1005 | if (lbs_fw_name) { | ||
1006 | char *fw_name = kstrdup(lbs_fw_name, GFP_KERNEL); | ||
1007 | if (!fw_name) { | ||
1008 | kparam_unblock_sysfs_write(fw_name); | ||
1009 | ret = -ENOMEM; | ||
1010 | goto free; | ||
1011 | } | ||
1012 | lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); | ||
1013 | card->firmware = fw_name; | ||
1014 | card->firmware_allocated = true; | ||
1015 | } | ||
1016 | kparam_unblock_sysfs_write(fw_name); | ||
1017 | |||
1018 | sdio_claim_host(func); | 977 | sdio_claim_host(func); |
1019 | 978 | ||
1020 | ret = sdio_enable_func(func); | 979 | ret = sdio_enable_func(func); |
@@ -1028,7 +987,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1028 | /* For 1-bit transfers to the 8686 model, we need to enable the | 987 | /* For 1-bit transfers to the 8686 model, we need to enable the |
1029 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 | 988 | * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 |
1030 | * bit to allow access to non-vendor registers. */ | 989 | * bit to allow access to non-vendor registers. */ |
1031 | if ((card->model == IF_SDIO_MODEL_8686) && | 990 | if ((card->model == MODEL_8686) && |
1032 | (host->caps & MMC_CAP_SDIO_IRQ) && | 991 | (host->caps & MMC_CAP_SDIO_IRQ) && |
1033 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { | 992 | (host->ios.bus_width == MMC_BUS_WIDTH_1)) { |
1034 | u8 reg; | 993 | u8 reg; |
@@ -1091,8 +1050,8 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1091 | * Get rx_unit if the chip is SD8688 or newer. | 1050 | * Get rx_unit if the chip is SD8688 or newer. |
1092 | * SD8385 & SD8686 do not have rx_unit. | 1051 | * SD8385 & SD8686 do not have rx_unit. |
1093 | */ | 1052 | */ |
1094 | if ((card->model != IF_SDIO_MODEL_8385) | 1053 | if ((card->model != MODEL_8385) |
1095 | && (card->model != IF_SDIO_MODEL_8686)) | 1054 | && (card->model != MODEL_8686)) |
1096 | card->rx_unit = if_sdio_read_rx_unit(card); | 1055 | card->rx_unit = if_sdio_read_rx_unit(card); |
1097 | else | 1056 | else |
1098 | card->rx_unit = 0; | 1057 | card->rx_unit = 0; |
@@ -1108,7 +1067,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1108 | /* | 1067 | /* |
1109 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 1068 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
1110 | */ | 1069 | */ |
1111 | if (card->model == IF_SDIO_MODEL_8688) { | 1070 | if (card->model == MODEL_8688) { |
1112 | struct cmd_header cmd; | 1071 | struct cmd_header cmd; |
1113 | 1072 | ||
1114 | memset(&cmd, 0, sizeof(cmd)); | 1073 | memset(&cmd, 0, sizeof(cmd)); |
@@ -1165,7 +1124,7 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1165 | 1124 | ||
1166 | card = sdio_get_drvdata(func); | 1125 | card = sdio_get_drvdata(func); |
1167 | 1126 | ||
1168 | if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { | 1127 | if (user_rmmod && (card->model == MODEL_8688)) { |
1169 | /* | 1128 | /* |
1170 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT | 1129 | * FUNC_SHUTDOWN is required for SD8688 WLAN/BT |
1171 | * multiple functions | 1130 | * multiple functions |
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h index 12179c1dc9c9..62fda3592f67 100644 --- a/drivers/net/wireless/libertas/if_sdio.h +++ b/drivers/net/wireless/libertas/if_sdio.h | |||
@@ -12,10 +12,6 @@ | |||
12 | #ifndef _LBS_IF_SDIO_H | 12 | #ifndef _LBS_IF_SDIO_H |
13 | #define _LBS_IF_SDIO_H | 13 | #define _LBS_IF_SDIO_H |
14 | 14 | ||
15 | #define IF_SDIO_MODEL_8385 0x04 | ||
16 | #define IF_SDIO_MODEL_8686 0x0b | ||
17 | #define IF_SDIO_MODEL_8688 0x10 | ||
18 | |||
19 | #define IF_SDIO_IOPORT 0x00 | 15 | #define IF_SDIO_IOPORT 0x00 |
20 | 16 | ||
21 | #define IF_SDIO_H_INT_MASK 0x04 | 17 | #define IF_SDIO_H_INT_MASK 0x04 |
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index fe3f08028eb3..79bcb4e5d2ca 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -39,9 +39,6 @@ struct if_spi_card { | |||
39 | struct lbs_private *priv; | 39 | struct lbs_private *priv; |
40 | struct libertas_spi_platform_data *pdata; | 40 | struct libertas_spi_platform_data *pdata; |
41 | 41 | ||
42 | char helper_fw_name[IF_SPI_FW_NAME_MAX]; | ||
43 | char main_fw_name[IF_SPI_FW_NAME_MAX]; | ||
44 | |||
45 | /* The card ID and card revision, as reported by the hardware. */ | 42 | /* The card ID and card revision, as reported by the hardware. */ |
46 | u16 card_id; | 43 | u16 card_id; |
47 | u8 card_rev; | 44 | u8 card_rev; |
@@ -70,10 +67,28 @@ static void free_if_spi_card(struct if_spi_card *card) | |||
70 | kfree(card); | 67 | kfree(card); |
71 | } | 68 | } |
72 | 69 | ||
73 | static struct chip_ident chip_id_to_device_name[] = { | 70 | #define MODEL_8385 0x04 |
74 | { .chip_id = 0x04, .name = 8385 }, | 71 | #define MODEL_8686 0x0b |
75 | { .chip_id = 0x0b, .name = 8686 }, | 72 | #define MODEL_8688 0x10 |
73 | |||
74 | static const struct lbs_fw_table fw_table[] = { | ||
75 | { MODEL_8385, "libertas/gspi8385_helper.bin", "libertas/gspi8385.bin" }, | ||
76 | { MODEL_8385, "libertas/gspi8385_hlp.bin", "libertas/gspi8385.bin" }, | ||
77 | { MODEL_8686, "libertas/gspi8686_v9_helper.bin", "libertas/gspi8686_v9.bin" }, | ||
78 | { MODEL_8686, "libertas/gspi8686_hlp.bin", "libertas/gspi8686.bin" }, | ||
79 | { MODEL_8688, "libertas/gspi8688_helper.bin", "libertas/gspi8688.bin" }, | ||
80 | { 0, NULL, NULL } | ||
76 | }; | 81 | }; |
82 | MODULE_FIRMWARE("libertas/gspi8385_helper.bin"); | ||
83 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
84 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
85 | MODULE_FIRMWARE("libertas/gspi8686_v9_helper.bin"); | ||
86 | MODULE_FIRMWARE("libertas/gspi8686_v9.bin"); | ||
87 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
88 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
89 | MODULE_FIRMWARE("libertas/gspi8688_helper.bin"); | ||
90 | MODULE_FIRMWARE("libertas/gspi8688.bin"); | ||
91 | |||
77 | 92 | ||
78 | /* | 93 | /* |
79 | * SPI Interface Unit Routines | 94 | * SPI Interface Unit Routines |
@@ -399,26 +414,20 @@ static int spu_init(struct if_spi_card *card, int use_dummy_writes) | |||
399 | * Firmware Loading | 414 | * Firmware Loading |
400 | */ | 415 | */ |
401 | 416 | ||
402 | static int if_spi_prog_helper_firmware(struct if_spi_card *card) | 417 | static int if_spi_prog_helper_firmware(struct if_spi_card *card, |
418 | const struct firmware *firmware) | ||
403 | { | 419 | { |
404 | int err = 0; | 420 | int err = 0; |
405 | const struct firmware *firmware = NULL; | ||
406 | int bytes_remaining; | 421 | int bytes_remaining; |
407 | const u8 *fw; | 422 | const u8 *fw; |
408 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; | 423 | u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; |
409 | struct spi_device *spi = card->spi; | ||
410 | 424 | ||
411 | lbs_deb_enter(LBS_DEB_SPI); | 425 | lbs_deb_enter(LBS_DEB_SPI); |
412 | 426 | ||
413 | err = spu_set_interrupt_mode(card, 1, 0); | 427 | err = spu_set_interrupt_mode(card, 1, 0); |
414 | if (err) | 428 | if (err) |
415 | goto out; | 429 | goto out; |
416 | /* Get helper firmware image */ | 430 | |
417 | err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); | ||
418 | if (err) { | ||
419 | lbs_pr_err("request_firmware failed with err = %d\n", err); | ||
420 | goto out; | ||
421 | } | ||
422 | bytes_remaining = firmware->size; | 431 | bytes_remaining = firmware->size; |
423 | fw = firmware->data; | 432 | fw = firmware->data; |
424 | 433 | ||
@@ -429,13 +438,13 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
429 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, | 438 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, |
430 | HELPER_FW_LOAD_CHUNK_SZ); | 439 | HELPER_FW_LOAD_CHUNK_SZ); |
431 | if (err) | 440 | if (err) |
432 | goto release_firmware; | 441 | goto out; |
433 | 442 | ||
434 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, | 443 | err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, |
435 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | 444 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, |
436 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | 445 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); |
437 | if (err) | 446 | if (err) |
438 | goto release_firmware; | 447 | goto out; |
439 | 448 | ||
440 | /* Feed the data into the command read/write port reg | 449 | /* Feed the data into the command read/write port reg |
441 | * in chunks of 64 bytes */ | 450 | * in chunks of 64 bytes */ |
@@ -446,16 +455,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
446 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 455 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
447 | temp, HELPER_FW_LOAD_CHUNK_SZ); | 456 | temp, HELPER_FW_LOAD_CHUNK_SZ); |
448 | if (err) | 457 | if (err) |
449 | goto release_firmware; | 458 | goto out; |
450 | 459 | ||
451 | /* Interrupt the boot code */ | 460 | /* Interrupt the boot code */ |
452 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 461 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
453 | if (err) | 462 | if (err) |
454 | goto release_firmware; | 463 | goto out; |
455 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 464 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
456 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 465 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
457 | if (err) | 466 | if (err) |
458 | goto release_firmware; | 467 | goto out; |
459 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; | 468 | bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; |
460 | fw += HELPER_FW_LOAD_CHUNK_SZ; | 469 | fw += HELPER_FW_LOAD_CHUNK_SZ; |
461 | } | 470 | } |
@@ -465,18 +474,16 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card) | |||
465 | * bootloader. This completes the helper download. */ | 474 | * bootloader. This completes the helper download. */ |
466 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); | 475 | err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); |
467 | if (err) | 476 | if (err) |
468 | goto release_firmware; | 477 | goto out; |
469 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 478 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
470 | if (err) | 479 | if (err) |
471 | goto release_firmware; | 480 | goto out; |
472 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, | 481 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, |
473 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 482 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
474 | goto release_firmware; | 483 | goto out; |
475 | 484 | ||
476 | lbs_deb_spi("waiting for helper to boot...\n"); | 485 | lbs_deb_spi("waiting for helper to boot...\n"); |
477 | 486 | ||
478 | release_firmware: | ||
479 | release_firmware(firmware); | ||
480 | out: | 487 | out: |
481 | if (err) | 488 | if (err) |
482 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); | 489 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); |
@@ -523,13 +530,12 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | |||
523 | return len; | 530 | return len; |
524 | } | 531 | } |
525 | 532 | ||
526 | static int if_spi_prog_main_firmware(struct if_spi_card *card) | 533 | static int if_spi_prog_main_firmware(struct if_spi_card *card, |
534 | const struct firmware *firmware) | ||
527 | { | 535 | { |
528 | int len, prev_len; | 536 | int len, prev_len; |
529 | int bytes, crc_err = 0, err = 0; | 537 | int bytes, crc_err = 0, err = 0; |
530 | const struct firmware *firmware = NULL; | ||
531 | const u8 *fw; | 538 | const u8 *fw; |
532 | struct spi_device *spi = card->spi; | ||
533 | u16 num_crc_errs; | 539 | u16 num_crc_errs; |
534 | 540 | ||
535 | lbs_deb_enter(LBS_DEB_SPI); | 541 | lbs_deb_enter(LBS_DEB_SPI); |
@@ -538,19 +544,11 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
538 | if (err) | 544 | if (err) |
539 | goto out; | 545 | goto out; |
540 | 546 | ||
541 | /* Get firmware image */ | ||
542 | err = request_firmware(&firmware, card->main_fw_name, &spi->dev); | ||
543 | if (err) { | ||
544 | lbs_pr_err("%s: can't get firmware '%s' from kernel. " | ||
545 | "err = %d\n", __func__, card->main_fw_name, err); | ||
546 | goto out; | ||
547 | } | ||
548 | |||
549 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); | 547 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); |
550 | if (err) { | 548 | if (err) { |
551 | lbs_pr_err("%s: timed out waiting for initial " | 549 | lbs_pr_err("%s: timed out waiting for initial " |
552 | "scratch reg = 0\n", __func__); | 550 | "scratch reg = 0\n", __func__); |
553 | goto release_firmware; | 551 | goto out; |
554 | } | 552 | } |
555 | 553 | ||
556 | num_crc_errs = 0; | 554 | num_crc_errs = 0; |
@@ -560,7 +558,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
560 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { | 558 | while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { |
561 | if (len < 0) { | 559 | if (len < 0) { |
562 | err = len; | 560 | err = len; |
563 | goto release_firmware; | 561 | goto out; |
564 | } | 562 | } |
565 | if (bytes < 0) { | 563 | if (bytes < 0) { |
566 | /* If there are no more bytes left, we would normally | 564 | /* If there are no more bytes left, we would normally |
@@ -575,7 +573,7 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
575 | lbs_pr_err("Too many CRC errors encountered " | 573 | lbs_pr_err("Too many CRC errors encountered " |
576 | "in firmware load.\n"); | 574 | "in firmware load.\n"); |
577 | err = -EIO; | 575 | err = -EIO; |
578 | goto release_firmware; | 576 | goto out; |
579 | } | 577 | } |
580 | } else { | 578 | } else { |
581 | /* Previous transfer succeeded. Advance counters. */ | 579 | /* Previous transfer succeeded. Advance counters. */ |
@@ -590,15 +588,15 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
590 | 588 | ||
591 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); | 589 | err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); |
592 | if (err) | 590 | if (err) |
593 | goto release_firmware; | 591 | goto out; |
594 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, | 592 | err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, |
595 | card->cmd_buffer, len); | 593 | card->cmd_buffer, len); |
596 | if (err) | 594 | if (err) |
597 | goto release_firmware; | 595 | goto out; |
598 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , | 596 | err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , |
599 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); | 597 | IF_SPI_CIC_CMD_DOWNLOAD_OVER); |
600 | if (err) | 598 | if (err) |
601 | goto release_firmware; | 599 | goto out; |
602 | prev_len = len; | 600 | prev_len = len; |
603 | } | 601 | } |
604 | if (bytes > prev_len) { | 602 | if (bytes > prev_len) { |
@@ -611,12 +609,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card) | |||
611 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); | 609 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); |
612 | if (err) { | 610 | if (err) { |
613 | lbs_pr_err("failed to confirm the firmware download\n"); | 611 | lbs_pr_err("failed to confirm the firmware download\n"); |
614 | goto release_firmware; | 612 | goto out; |
615 | } | 613 | } |
616 | 614 | ||
617 | release_firmware: | ||
618 | release_firmware(firmware); | ||
619 | |||
620 | out: | 615 | out: |
621 | if (err) | 616 | if (err) |
622 | lbs_pr_err("failed to load firmware (err=%d)\n", err); | 617 | lbs_pr_err("failed to load firmware (err=%d)\n", err); |
@@ -800,14 +795,16 @@ static int lbs_spi_thread(void *data) | |||
800 | goto err; | 795 | goto err; |
801 | } | 796 | } |
802 | 797 | ||
803 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) | 798 | if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) { |
804 | err = if_spi_c2h_cmd(card); | 799 | err = if_spi_c2h_cmd(card); |
805 | if (err) | 800 | if (err) |
806 | goto err; | 801 | goto err; |
807 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) | 802 | } |
803 | if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) { | ||
808 | err = if_spi_c2h_data(card); | 804 | err = if_spi_c2h_data(card); |
809 | if (err) | 805 | if (err) |
810 | goto err; | 806 | goto err; |
807 | } | ||
811 | 808 | ||
812 | /* workaround: in PS mode, the card does not set the Command | 809 | /* workaround: in PS mode, the card does not set the Command |
813 | * Download Ready bit, but it sets TX Download Ready. */ | 810 | * Download Ready bit, but it sets TX Download Ready. */ |
@@ -886,37 +883,16 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | |||
886 | * SPI callbacks | 883 | * SPI callbacks |
887 | */ | 884 | */ |
888 | 885 | ||
889 | static int if_spi_calculate_fw_names(u16 card_id, | ||
890 | char *helper_fw, char *main_fw) | ||
891 | { | ||
892 | int i; | ||
893 | for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { | ||
894 | if (card_id == chip_id_to_device_name[i].chip_id) | ||
895 | break; | ||
896 | } | ||
897 | if (i == ARRAY_SIZE(chip_id_to_device_name)) { | ||
898 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); | ||
899 | return -EAFNOSUPPORT; | ||
900 | } | ||
901 | snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", | ||
902 | chip_id_to_device_name[i].name); | ||
903 | snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", | ||
904 | chip_id_to_device_name[i].name); | ||
905 | return 0; | ||
906 | } | ||
907 | MODULE_FIRMWARE("libertas/gspi8385_hlp.bin"); | ||
908 | MODULE_FIRMWARE("libertas/gspi8385.bin"); | ||
909 | MODULE_FIRMWARE("libertas/gspi8686_hlp.bin"); | ||
910 | MODULE_FIRMWARE("libertas/gspi8686.bin"); | ||
911 | |||
912 | static int __devinit if_spi_probe(struct spi_device *spi) | 886 | static int __devinit if_spi_probe(struct spi_device *spi) |
913 | { | 887 | { |
914 | struct if_spi_card *card; | 888 | struct if_spi_card *card; |
915 | struct lbs_private *priv = NULL; | 889 | struct lbs_private *priv = NULL; |
916 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; | 890 | struct libertas_spi_platform_data *pdata = spi->dev.platform_data; |
917 | int err = 0; | 891 | int err = 0, i; |
918 | u32 scratch; | 892 | u32 scratch; |
919 | struct sched_param param = { .sched_priority = 1 }; | 893 | struct sched_param param = { .sched_priority = 1 }; |
894 | const struct firmware *helper = NULL; | ||
895 | const struct firmware *mainfw = NULL; | ||
920 | 896 | ||
921 | lbs_deb_enter(LBS_DEB_SPI); | 897 | lbs_deb_enter(LBS_DEB_SPI); |
922 | 898 | ||
@@ -961,10 +937,25 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
961 | lbs_deb_spi("Firmware is already loaded for " | 937 | lbs_deb_spi("Firmware is already loaded for " |
962 | "Marvell WLAN 802.11 adapter\n"); | 938 | "Marvell WLAN 802.11 adapter\n"); |
963 | else { | 939 | else { |
964 | err = if_spi_calculate_fw_names(card->card_id, | 940 | /* Check if we support this card */ |
965 | card->helper_fw_name, card->main_fw_name); | 941 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { |
966 | if (err) | 942 | if (card->card_id == fw_table[i].model) |
943 | break; | ||
944 | } | ||
945 | if (i == ARRAY_SIZE(fw_table)) { | ||
946 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", | ||
947 | card->card_id); | ||
948 | err = -ENODEV; | ||
967 | goto free_card; | 949 | goto free_card; |
950 | } | ||
951 | |||
952 | err = lbs_get_firmware(&card->spi->dev, NULL, NULL, | ||
953 | card->card_id, &fw_table[0], &helper, | ||
954 | &mainfw); | ||
955 | if (err) { | ||
956 | lbs_pr_err("failed to find firmware (%d)\n", err); | ||
957 | goto free_card; | ||
958 | } | ||
968 | 959 | ||
969 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " | 960 | lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " |
970 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " | 961 | "(chip_id = 0x%04x, chip_rev = 0x%02x) " |
@@ -973,10 +964,10 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
973 | card->card_id, card->card_rev, | 964 | card->card_id, card->card_rev, |
974 | spi->master->bus_num, spi->chip_select, | 965 | spi->master->bus_num, spi->chip_select, |
975 | spi->max_speed_hz); | 966 | spi->max_speed_hz); |
976 | err = if_spi_prog_helper_firmware(card); | 967 | err = if_spi_prog_helper_firmware(card, helper); |
977 | if (err) | 968 | if (err) |
978 | goto free_card; | 969 | goto free_card; |
979 | err = if_spi_prog_main_firmware(card); | 970 | err = if_spi_prog_main_firmware(card, mainfw); |
980 | if (err) | 971 | if (err) |
981 | goto free_card; | 972 | goto free_card; |
982 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); | 973 | lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); |
@@ -1044,6 +1035,11 @@ remove_card: | |||
1044 | free_card: | 1035 | free_card: |
1045 | free_if_spi_card(card); | 1036 | free_if_spi_card(card); |
1046 | out: | 1037 | out: |
1038 | if (helper) | ||
1039 | release_firmware(helper); | ||
1040 | if (mainfw) | ||
1041 | release_firmware(mainfw); | ||
1042 | |||
1047 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); | 1043 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); |
1048 | return err; | 1044 | return err; |
1049 | } | 1045 | } |
diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h index f87eec410848..8b1417d3b71b 100644 --- a/drivers/net/wireless/libertas/if_spi.h +++ b/drivers/net/wireless/libertas/if_spi.h | |||
@@ -25,11 +25,6 @@ | |||
25 | 25 | ||
26 | #define IF_SPI_FW_NAME_MAX 30 | 26 | #define IF_SPI_FW_NAME_MAX 30 |
27 | 27 | ||
28 | struct chip_ident { | ||
29 | u16 chip_id; | ||
30 | u16 name; | ||
31 | }; | ||
32 | |||
33 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 | 28 | #define MAX_MAIN_FW_LOAD_CRC_ERR 10 |
34 | 29 | ||
35 | /* Chunk size when loading the helper firmware */ | 30 | /* Chunk size when loading the helper firmware */ |
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 3ff61063671a..e906616232a2 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -26,15 +26,25 @@ | |||
26 | 26 | ||
27 | #define MESSAGE_HEADER_LEN 4 | 27 | #define MESSAGE_HEADER_LEN 4 |
28 | 28 | ||
29 | static char *lbs_fw_name = "usb8388.bin"; | 29 | static char *lbs_fw_name = NULL; |
30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); | 30 | module_param_named(fw_name, lbs_fw_name, charp, 0644); |
31 | 31 | ||
32 | MODULE_FIRMWARE("libertas/usb8388_v9.bin"); | ||
33 | MODULE_FIRMWARE("libertas/usb8388_v5.bin"); | ||
34 | MODULE_FIRMWARE("libertas/usb8388.bin"); | ||
35 | MODULE_FIRMWARE("libertas/usb8682.bin"); | ||
32 | MODULE_FIRMWARE("usb8388.bin"); | 36 | MODULE_FIRMWARE("usb8388.bin"); |
33 | 37 | ||
38 | enum { | ||
39 | MODEL_UNKNOWN = 0x0, | ||
40 | MODEL_8388 = 0x1, | ||
41 | MODEL_8682 = 0x2 | ||
42 | }; | ||
43 | |||
34 | static struct usb_device_id if_usb_table[] = { | 44 | static struct usb_device_id if_usb_table[] = { |
35 | /* Enter the device signature inside */ | 45 | /* Enter the device signature inside */ |
36 | { USB_DEVICE(0x1286, 0x2001) }, | 46 | { USB_DEVICE(0x1286, 0x2001), .driver_info = MODEL_8388 }, |
37 | { USB_DEVICE(0x05a3, 0x8388) }, | 47 | { USB_DEVICE(0x05a3, 0x8388), .driver_info = MODEL_8388 }, |
38 | {} /* Terminating entry */ | 48 | {} /* Terminating entry */ |
39 | }; | 49 | }; |
40 | 50 | ||
@@ -66,6 +76,8 @@ static ssize_t if_usb_firmware_set(struct device *dev, | |||
66 | struct if_usb_card *cardp = priv->card; | 76 | struct if_usb_card *cardp = priv->card; |
67 | int ret; | 77 | int ret; |
68 | 78 | ||
79 | BUG_ON(buf == NULL); | ||
80 | |||
69 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); | 81 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); |
70 | if (ret == 0) | 82 | if (ret == 0) |
71 | return count; | 83 | return count; |
@@ -91,6 +103,8 @@ static ssize_t if_usb_boot2_set(struct device *dev, | |||
91 | struct if_usb_card *cardp = priv->card; | 103 | struct if_usb_card *cardp = priv->card; |
92 | int ret; | 104 | int ret; |
93 | 105 | ||
106 | BUG_ON(buf == NULL); | ||
107 | |||
94 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); | 108 | ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); |
95 | if (ret == 0) | 109 | if (ret == 0) |
96 | return count; | 110 | return count; |
@@ -244,6 +258,7 @@ static int if_usb_probe(struct usb_interface *intf, | |||
244 | init_waitqueue_head(&cardp->fw_wq); | 258 | init_waitqueue_head(&cardp->fw_wq); |
245 | 259 | ||
246 | cardp->udev = udev; | 260 | cardp->udev = udev; |
261 | cardp->model = (uint32_t) id->driver_info; | ||
247 | iface_desc = intf->cur_altsetting; | 262 | iface_desc = intf->cur_altsetting; |
248 | 263 | ||
249 | lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" | 264 | lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" |
@@ -924,6 +939,38 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp, | |||
924 | return ret; | 939 | return ret; |
925 | } | 940 | } |
926 | 941 | ||
942 | /* table of firmware file names */ | ||
943 | static const struct { | ||
944 | u32 model; | ||
945 | const char *fwname; | ||
946 | } fw_table[] = { | ||
947 | { MODEL_8388, "libertas/usb8388_v9.bin" }, | ||
948 | { MODEL_8388, "libertas/usb8388_v5.bin" }, | ||
949 | { MODEL_8388, "libertas/usb8388.bin" }, | ||
950 | { MODEL_8388, "usb8388.bin" }, | ||
951 | { MODEL_8682, "libertas/usb8682.bin" } | ||
952 | }; | ||
953 | |||
954 | static int get_fw(struct if_usb_card *cardp, const char *fwname) | ||
955 | { | ||
956 | int i; | ||
957 | |||
958 | /* Try user-specified firmware first */ | ||
959 | if (fwname) | ||
960 | return request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | ||
961 | |||
962 | /* Otherwise search for firmware to use */ | ||
963 | for (i = 0; i < ARRAY_SIZE(fw_table); i++) { | ||
964 | if (fw_table[i].model != cardp->model) | ||
965 | continue; | ||
966 | if (request_firmware(&cardp->fw, fw_table[i].fwname, | ||
967 | &cardp->udev->dev) == 0) | ||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | return -ENOENT; | ||
972 | } | ||
973 | |||
927 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, | 974 | static int __if_usb_prog_firmware(struct if_usb_card *cardp, |
928 | const char *fwname, int cmd) | 975 | const char *fwname, int cmd) |
929 | { | 976 | { |
@@ -933,10 +980,9 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, | |||
933 | 980 | ||
934 | lbs_deb_enter(LBS_DEB_USB); | 981 | lbs_deb_enter(LBS_DEB_USB); |
935 | 982 | ||
936 | ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev); | 983 | ret = get_fw(cardp, fwname); |
937 | if (ret < 0) { | 984 | if (ret) { |
938 | lbs_pr_err("request_firmware() failed with %#x\n", ret); | 985 | lbs_pr_err("failed to find firmware (%d)\n", ret); |
939 | lbs_pr_err("firmware %s not found\n", fwname); | ||
940 | goto done; | 986 | goto done; |
941 | } | 987 | } |
942 | 988 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h index 5ba0aee0eb2f..d819e7e3c9aa 100644 --- a/drivers/net/wireless/libertas/if_usb.h +++ b/drivers/net/wireless/libertas/if_usb.h | |||
@@ -43,6 +43,7 @@ struct bootcmdresp | |||
43 | /** USB card description structure*/ | 43 | /** USB card description structure*/ |
44 | struct if_usb_card { | 44 | struct if_usb_card { |
45 | struct usb_device *udev; | 45 | struct usb_device *udev; |
46 | uint32_t model; /* MODEL_* */ | ||
46 | struct urb *rx_urb, *tx_urb; | 47 | struct urb *rx_urb, *tx_urb; |
47 | struct lbs_private *priv; | 48 | struct lbs_private *priv; |
48 | 49 | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 24958a86747b..47ce5a6ba120 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -1047,6 +1047,111 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) | |||
1047 | } | 1047 | } |
1048 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); | 1048 | EXPORT_SYMBOL_GPL(lbs_notify_command_response); |
1049 | 1049 | ||
1050 | /** | ||
1051 | * @brief Retrieves two-stage firmware | ||
1052 | * | ||
1053 | * @param dev A pointer to device structure | ||
1054 | * @param user_helper User-defined helper firmware file | ||
1055 | * @param user_mainfw User-defined main firmware file | ||
1056 | * @param card_model Bus-specific card model ID used to filter firmware table | ||
1057 | * elements | ||
1058 | * @param fw_table Table of firmware file names and device model numbers | ||
1059 | * terminated by an entry with a NULL helper name | ||
1060 | * @param helper On success, the helper firmware; caller must free | ||
1061 | * @param mainfw On success, the main firmware; caller must free | ||
1062 | * | ||
1063 | * @return 0 on success, non-zero on failure | ||
1064 | */ | ||
1065 | int lbs_get_firmware(struct device *dev, const char *user_helper, | ||
1066 | const char *user_mainfw, u32 card_model, | ||
1067 | const struct lbs_fw_table *fw_table, | ||
1068 | const struct firmware **helper, | ||
1069 | const struct firmware **mainfw) | ||
1070 | { | ||
1071 | const struct lbs_fw_table *iter; | ||
1072 | int ret; | ||
1073 | |||
1074 | BUG_ON(helper == NULL); | ||
1075 | BUG_ON(mainfw == NULL); | ||
1076 | |||
1077 | /* Try user-specified firmware first */ | ||
1078 | if (user_helper) { | ||
1079 | ret = request_firmware(helper, user_helper, dev); | ||
1080 | if (ret) { | ||
1081 | lbs_pr_err("couldn't find helper firmware %s", | ||
1082 | user_helper); | ||
1083 | goto fail; | ||
1084 | } | ||
1085 | } | ||
1086 | if (user_mainfw) { | ||
1087 | ret = request_firmware(mainfw, user_mainfw, dev); | ||
1088 | if (ret) { | ||
1089 | lbs_pr_err("couldn't find main firmware %s", | ||
1090 | user_mainfw); | ||
1091 | goto fail; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | if (*helper && *mainfw) | ||
1096 | return 0; | ||
1097 | |||
1098 | /* Otherwise search for firmware to use. If neither the helper or | ||
1099 | * the main firmware were specified by the user, then we need to | ||
1100 | * make sure that found helper & main are from the same entry in | ||
1101 | * fw_table. | ||
1102 | */ | ||
1103 | iter = fw_table; | ||
1104 | while (iter && iter->helper) { | ||
1105 | if (iter->model != card_model) | ||
1106 | goto next; | ||
1107 | |||
1108 | if (*helper == NULL) { | ||
1109 | ret = request_firmware(helper, iter->helper, dev); | ||
1110 | if (ret) | ||
1111 | goto next; | ||
1112 | |||
1113 | /* If the device has one-stage firmware (ie cf8305) and | ||
1114 | * we've got it then we don't need to bother with the | ||
1115 | * main firmware. | ||
1116 | */ | ||
1117 | if (iter->fwname == NULL) | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | if (*mainfw == NULL) { | ||
1122 | ret = request_firmware(mainfw, iter->fwname, dev); | ||
1123 | if (ret && !user_helper) { | ||
1124 | /* Clear the helper if it wasn't user-specified | ||
1125 | * and the main firmware load failed, to ensure | ||
1126 | * we don't have mismatched firmware pairs. | ||
1127 | */ | ||
1128 | release_firmware(*helper); | ||
1129 | *helper = NULL; | ||
1130 | } | ||
1131 | } | ||
1132 | |||
1133 | if (*helper && *mainfw) | ||
1134 | return 0; | ||
1135 | |||
1136 | next: | ||
1137 | iter++; | ||
1138 | } | ||
1139 | |||
1140 | fail: | ||
1141 | /* Failed */ | ||
1142 | if (*helper) { | ||
1143 | release_firmware(*helper); | ||
1144 | *helper = NULL; | ||
1145 | } | ||
1146 | if (*mainfw) { | ||
1147 | release_firmware(*mainfw); | ||
1148 | *mainfw = NULL; | ||
1149 | } | ||
1150 | |||
1151 | return -ENOENT; | ||
1152 | } | ||
1153 | EXPORT_SYMBOL_GPL(lbs_get_firmware); | ||
1154 | |||
1050 | static int __init lbs_init_module(void) | 1155 | static int __init lbs_init_module(void) |
1051 | { | 1156 | { |
1052 | lbs_deb_enter(LBS_DEB_MAIN); | 1157 | lbs_deb_enter(LBS_DEB_MAIN); |
diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c index 41a4f214ade1..ba7d96584cb6 100644 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ b/drivers/net/wireless/libertas_tf/if_usb.c | |||
@@ -54,7 +54,7 @@ static int if_usb_reset_device(struct if_usb_card *cardp); | |||
54 | /** | 54 | /** |
55 | * if_usb_wrike_bulk_callback - call back to handle URB status | 55 | * if_usb_wrike_bulk_callback - call back to handle URB status |
56 | * | 56 | * |
57 | * @param urb pointer to urb structure | 57 | * @param urb pointer to urb structure |
58 | */ | 58 | */ |
59 | static void if_usb_write_bulk_callback(struct urb *urb) | 59 | static void if_usb_write_bulk_callback(struct urb *urb) |
60 | { | 60 | { |
@@ -178,16 +178,19 @@ static int if_usb_probe(struct usb_interface *intf, | |||
178 | le16_to_cpu(endpoint->wMaxPacketSize); | 178 | le16_to_cpu(endpoint->wMaxPacketSize); |
179 | cardp->ep_in = usb_endpoint_num(endpoint); | 179 | cardp->ep_in = usb_endpoint_num(endpoint); |
180 | 180 | ||
181 | lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); | 181 | lbtf_deb_usbd(&udev->dev, "in_endpoint = %d\n", |
182 | lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); | 182 | cardp->ep_in); |
183 | lbtf_deb_usbd(&udev->dev, "Bulk in size is %d\n", | ||
184 | cardp->ep_in_size); | ||
183 | } else if (usb_endpoint_is_bulk_out(endpoint)) { | 185 | } else if (usb_endpoint_is_bulk_out(endpoint)) { |
184 | cardp->ep_out_size = | 186 | cardp->ep_out_size = |
185 | le16_to_cpu(endpoint->wMaxPacketSize); | 187 | le16_to_cpu(endpoint->wMaxPacketSize); |
186 | cardp->ep_out = usb_endpoint_num(endpoint); | 188 | cardp->ep_out = usb_endpoint_num(endpoint); |
187 | 189 | ||
188 | lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); | 190 | lbtf_deb_usbd(&udev->dev, "out_endpoint = %d\n", |
191 | cardp->ep_out); | ||
189 | lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", | 192 | lbtf_deb_usbd(&udev->dev, "Bulk out size is %d\n", |
190 | cardp->ep_out_size); | 193 | cardp->ep_out_size); |
191 | } | 194 | } |
192 | } | 195 | } |
193 | if (!cardp->ep_out_size || !cardp->ep_in_size) { | 196 | if (!cardp->ep_out_size || !cardp->ep_in_size) { |
@@ -318,10 +321,12 @@ static int if_usb_send_fw_pkt(struct if_usb_card *cardp) | |||
318 | 321 | ||
319 | if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { | 322 | if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { |
320 | lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); | 323 | lbtf_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); |
321 | lbtf_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", | 324 | lbtf_deb_usb2(&cardp->udev->dev, |
322 | cardp->fwseqnum, cardp->totalbytes); | 325 | "seqnum = %d totalbytes = %d\n", |
326 | cardp->fwseqnum, cardp->totalbytes); | ||
323 | } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { | 327 | } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { |
324 | lbtf_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); | 328 | lbtf_deb_usb2(&cardp->udev->dev, |
329 | "Host has finished FW downloading\n"); | ||
325 | lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); | 330 | lbtf_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); |
326 | 331 | ||
327 | /* Host has finished FW downloading | 332 | /* Host has finished FW downloading |
@@ -367,7 +372,7 @@ EXPORT_SYMBOL_GPL(if_usb_reset_device); | |||
367 | /** | 372 | /** |
368 | * usb_tx_block - transfer data to the device | 373 | * usb_tx_block - transfer data to the device |
369 | * | 374 | * |
370 | * @priv pointer to struct lbtf_private | 375 | * @priv pointer to struct lbtf_private |
371 | * @payload pointer to payload data | 376 | * @payload pointer to payload data |
372 | * @nb data length | 377 | * @nb data length |
373 | * @data non-zero for data, zero for commands | 378 | * @data non-zero for data, zero for commands |
@@ -400,7 +405,8 @@ static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, | |||
400 | urb->transfer_flags |= URB_ZERO_PACKET; | 405 | urb->transfer_flags |= URB_ZERO_PACKET; |
401 | 406 | ||
402 | if (usb_submit_urb(urb, GFP_ATOMIC)) { | 407 | if (usb_submit_urb(urb, GFP_ATOMIC)) { |
403 | lbtf_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); | 408 | lbtf_deb_usbd(&cardp->udev->dev, |
409 | "usb_submit_urb failed: %d\n", ret); | ||
404 | goto tx_ret; | 410 | goto tx_ret; |
405 | } | 411 | } |
406 | 412 | ||
@@ -438,10 +444,12 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, | |||
438 | 444 | ||
439 | cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; | 445 | cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; |
440 | 446 | ||
441 | lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); | 447 | lbtf_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", |
448 | cardp->rx_urb); | ||
442 | ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); | 449 | ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC); |
443 | if (ret) { | 450 | if (ret) { |
444 | lbtf_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); | 451 | lbtf_deb_usbd(&cardp->udev->dev, |
452 | "Submit Rx URB failed: %d\n", ret); | ||
445 | kfree_skb(skb); | 453 | kfree_skb(skb); |
446 | cardp->rx_skb = NULL; | 454 | cardp->rx_skb = NULL; |
447 | lbtf_deb_leave(LBTF_DEB_USB); | 455 | lbtf_deb_leave(LBTF_DEB_USB); |
@@ -522,14 +530,14 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
522 | } | 530 | } |
523 | } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { | 531 | } else if (bcmdresp.cmd != BOOT_CMD_FW_BY_USB) { |
524 | pr_info("boot cmd response cmd_tag error (%d)\n", | 532 | pr_info("boot cmd response cmd_tag error (%d)\n", |
525 | bcmdresp.cmd); | 533 | bcmdresp.cmd); |
526 | } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { | 534 | } else if (bcmdresp.result != BOOT_CMD_RESP_OK) { |
527 | pr_info("boot cmd response result error (%d)\n", | 535 | pr_info("boot cmd response result error (%d)\n", |
528 | bcmdresp.result); | 536 | bcmdresp.result); |
529 | } else { | 537 | } else { |
530 | cardp->bootcmdresp = 1; | 538 | cardp->bootcmdresp = 1; |
531 | lbtf_deb_usbd(&cardp->udev->dev, | 539 | lbtf_deb_usbd(&cardp->udev->dev, |
532 | "Received valid boot command response\n"); | 540 | "Received valid boot command response\n"); |
533 | } | 541 | } |
534 | 542 | ||
535 | kfree_skb(skb); | 543 | kfree_skb(skb); |
@@ -541,19 +549,23 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
541 | syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), | 549 | syncfwheader = kmemdup(skb->data, sizeof(struct fwsyncheader), |
542 | GFP_ATOMIC); | 550 | GFP_ATOMIC); |
543 | if (!syncfwheader) { | 551 | if (!syncfwheader) { |
544 | lbtf_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); | 552 | lbtf_deb_usbd(&cardp->udev->dev, |
553 | "Failure to allocate syncfwheader\n"); | ||
545 | kfree_skb(skb); | 554 | kfree_skb(skb); |
546 | lbtf_deb_leave(LBTF_DEB_USB); | 555 | lbtf_deb_leave(LBTF_DEB_USB); |
547 | return; | 556 | return; |
548 | } | 557 | } |
549 | 558 | ||
550 | if (!syncfwheader->cmd) { | 559 | if (!syncfwheader->cmd) { |
551 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); | 560 | lbtf_deb_usb2(&cardp->udev->dev, |
552 | lbtf_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", | 561 | "FW received Blk with correct CRC\n"); |
553 | le32_to_cpu(syncfwheader->seqnum)); | 562 | lbtf_deb_usb2(&cardp->udev->dev, |
563 | "FW received Blk seqnum = %d\n", | ||
564 | le32_to_cpu(syncfwheader->seqnum)); | ||
554 | cardp->CRC_OK = 1; | 565 | cardp->CRC_OK = 1; |
555 | } else { | 566 | } else { |
556 | lbtf_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); | 567 | lbtf_deb_usbd(&cardp->udev->dev, |
568 | "FW received Blk with CRC error\n"); | ||
557 | cardp->CRC_OK = 0; | 569 | cardp->CRC_OK = 0; |
558 | } | 570 | } |
559 | 571 | ||
@@ -666,7 +678,8 @@ static void if_usb_receive(struct urb *urb) | |||
666 | { | 678 | { |
667 | /* Event cause handling */ | 679 | /* Event cause handling */ |
668 | u32 event_cause = le32_to_cpu(pkt[1]); | 680 | u32 event_cause = le32_to_cpu(pkt[1]); |
669 | lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event_cause); | 681 | lbtf_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", |
682 | event_cause); | ||
670 | 683 | ||
671 | /* Icky undocumented magic special case */ | 684 | /* Icky undocumented magic special case */ |
672 | if (event_cause & 0xffff0000) { | 685 | if (event_cause & 0xffff0000) { |
@@ -689,7 +702,7 @@ static void if_usb_receive(struct urb *urb) | |||
689 | } | 702 | } |
690 | default: | 703 | default: |
691 | lbtf_deb_usbd(&cardp->udev->dev, | 704 | lbtf_deb_usbd(&cardp->udev->dev, |
692 | "libertastf: unknown command type 0x%X\n", recvtype); | 705 | "libertastf: unknown command type 0x%X\n", recvtype); |
693 | kfree_skb(skb); | 706 | kfree_skb(skb); |
694 | break; | 707 | break; |
695 | } | 708 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 86fa8abdd66f..298ba79fc51b 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -9,7 +9,8 @@ | |||
9 | 9 | ||
10 | /* | 10 | /* |
11 | * TODO: | 11 | * TODO: |
12 | * - IBSS mode simulation (Beacon transmission with competition for "air time") | 12 | * - Add TSF sync and fix IBSS beacon transmission by adding |
13 | * competition for "air time" at TBTT | ||
13 | * - RX filtering based on filter configuration (data->rx_filter) | 14 | * - RX filtering based on filter configuration (data->rx_filter) |
14 | */ | 15 | */ |
15 | 16 | ||
@@ -620,7 +621,8 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, | |||
620 | hwsim_check_magic(vif); | 621 | hwsim_check_magic(vif); |
621 | 622 | ||
622 | if (vif->type != NL80211_IFTYPE_AP && | 623 | if (vif->type != NL80211_IFTYPE_AP && |
623 | vif->type != NL80211_IFTYPE_MESH_POINT) | 624 | vif->type != NL80211_IFTYPE_MESH_POINT && |
625 | vif->type != NL80211_IFTYPE_ADHOC) | ||
624 | return; | 626 | return; |
625 | 627 | ||
626 | skb = ieee80211_beacon_get(hw, vif); | 628 | skb = ieee80211_beacon_get(hw, vif); |
@@ -1295,6 +1297,7 @@ static int __init init_mac80211_hwsim(void) | |||
1295 | hw->wiphy->interface_modes = | 1297 | hw->wiphy->interface_modes = |
1296 | BIT(NL80211_IFTYPE_STATION) | | 1298 | BIT(NL80211_IFTYPE_STATION) | |
1297 | BIT(NL80211_IFTYPE_AP) | | 1299 | BIT(NL80211_IFTYPE_AP) | |
1300 | BIT(NL80211_IFTYPE_ADHOC) | | ||
1298 | BIT(NL80211_IFTYPE_MESH_POINT); | 1301 | BIT(NL80211_IFTYPE_MESH_POINT); |
1299 | 1302 | ||
1300 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1303 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig index b0342a520bf1..60a930e45a8b 100644 --- a/drivers/net/wireless/p54/Kconfig +++ b/drivers/net/wireless/p54/Kconfig | |||
@@ -2,6 +2,7 @@ config P54_COMMON | |||
2 | tristate "Softmac Prism54 support" | 2 | tristate "Softmac Prism54 support" |
3 | depends on MAC80211 && EXPERIMENTAL | 3 | depends on MAC80211 && EXPERIMENTAL |
4 | select FW_LOADER | 4 | select FW_LOADER |
5 | select CRC_CCITT | ||
5 | ---help--- | 6 | ---help--- |
6 | This is common code for isl38xx/stlc45xx based modules. | 7 | This is common code for isl38xx/stlc45xx based modules. |
7 | This module does nothing by itself - the USB/PCI/SPI front-ends | 8 | This module does nothing by itself - the USB/PCI/SPI front-ends |
diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c index 78347041ec40..8c05266d37f4 100644 --- a/drivers/net/wireless/p54/eeprom.c +++ b/drivers/net/wireless/p54/eeprom.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | 24 | ||
25 | #include <net/mac80211.h> | 25 | #include <net/mac80211.h> |
26 | #include <linux/crc-ccitt.h> | ||
26 | 27 | ||
27 | #include "p54.h" | 28 | #include "p54.h" |
28 | #include "eeprom.h" | 29 | #include "eeprom.h" |
@@ -540,6 +541,7 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
540 | int err; | 541 | int err; |
541 | u8 *end = (u8 *)eeprom + len; | 542 | u8 *end = (u8 *)eeprom + len; |
542 | u16 synth = 0; | 543 | u16 synth = 0; |
544 | u16 crc16 = ~0; | ||
543 | 545 | ||
544 | wrap = (struct eeprom_pda_wrap *) eeprom; | 546 | wrap = (struct eeprom_pda_wrap *) eeprom; |
545 | entry = (void *)wrap->data + le16_to_cpu(wrap->len); | 547 | entry = (void *)wrap->data + le16_to_cpu(wrap->len); |
@@ -655,16 +657,29 @@ int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
655 | } | 657 | } |
656 | break; | 658 | break; |
657 | case PDR_END: | 659 | case PDR_END: |
658 | /* make it overrun */ | 660 | crc16 = ~crc_ccitt(crc16, (u8 *) entry, sizeof(*entry)); |
659 | entry_len = len; | 661 | if (crc16 != le16_to_cpup((__le16 *)entry->data)) { |
662 | wiphy_err(dev->wiphy, "eeprom failed checksum " | ||
663 | "test!\n"); | ||
664 | err = -ENOMSG; | ||
665 | goto err; | ||
666 | } else { | ||
667 | goto good_eeprom; | ||
668 | } | ||
660 | break; | 669 | break; |
661 | default: | 670 | default: |
662 | break; | 671 | break; |
663 | } | 672 | } |
664 | 673 | ||
665 | entry = (void *)entry + (entry_len + 1)*2; | 674 | crc16 = crc_ccitt(crc16, (u8 *)entry, (entry_len + 1) * 2); |
675 | entry = (void *)entry + (entry_len + 1) * 2; | ||
666 | } | 676 | } |
667 | 677 | ||
678 | wiphy_err(dev->wiphy, "unexpected end of eeprom data.\n"); | ||
679 | err = -ENODATA; | ||
680 | goto err; | ||
681 | |||
682 | good_eeprom: | ||
668 | if (!synth || !priv->iq_autocal || !priv->output_limit || | 683 | if (!synth || !priv->iq_autocal || !priv->output_limit || |
669 | !priv->curve_data) { | 684 | !priv->curve_data) { |
670 | wiphy_err(dev->wiphy, | 685 | wiphy_err(dev->wiphy, |
diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c index 15b20c29a604..92b9b1f05fd5 100644 --- a/drivers/net/wireless/p54/fwio.c +++ b/drivers/net/wireless/p54/fwio.c | |||
@@ -123,10 +123,14 @@ int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) | |||
123 | bootrec = (struct bootrec *)&bootrec->data[len]; | 123 | bootrec = (struct bootrec *)&bootrec->data[len]; |
124 | } | 124 | } |
125 | 125 | ||
126 | if (fw_version) | 126 | if (fw_version) { |
127 | wiphy_info(priv->hw->wiphy, | 127 | wiphy_info(priv->hw->wiphy, |
128 | "FW rev %s - Softmac protocol %x.%x\n", | 128 | "FW rev %s - Softmac protocol %x.%x\n", |
129 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); | 129 | fw_version, priv->fw_var >> 8, priv->fw_var & 0xff); |
130 | snprintf(dev->wiphy->fw_version, sizeof(dev->wiphy->fw_version), | ||
131 | "%s - %x.%x", fw_version, | ||
132 | priv->fw_var >> 8, priv->fw_var & 0xff); | ||
133 | } | ||
130 | 134 | ||
131 | if (priv->fw_var < 0x500) | 135 | if (priv->fw_var < 0x500) |
132 | wiphy_info(priv->hw->wiphy, | 136 | wiphy_info(priv->hw->wiphy, |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 47db439b63bf..622d27b6d8f2 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -429,8 +429,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
429 | 429 | ||
430 | mutex_lock(&priv->conf_mutex); | 430 | mutex_lock(&priv->conf_mutex); |
431 | if (cmd == SET_KEY) { | 431 | if (cmd == SET_KEY) { |
432 | switch (key->alg) { | 432 | switch (key->cipher) { |
433 | case ALG_TKIP: | 433 | case WLAN_CIPHER_SUITE_TKIP: |
434 | if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | | 434 | if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | |
435 | BR_DESC_PRIV_CAP_TKIP))) { | 435 | BR_DESC_PRIV_CAP_TKIP))) { |
436 | ret = -EOPNOTSUPP; | 436 | ret = -EOPNOTSUPP; |
@@ -439,7 +439,8 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
439 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 439 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
440 | algo = P54_CRYPTO_TKIPMICHAEL; | 440 | algo = P54_CRYPTO_TKIPMICHAEL; |
441 | break; | 441 | break; |
442 | case ALG_WEP: | 442 | case WLAN_CIPHER_SUITE_WEP40: |
443 | case WLAN_CIPHER_SUITE_WEP104: | ||
443 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { | 444 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { |
444 | ret = -EOPNOTSUPP; | 445 | ret = -EOPNOTSUPP; |
445 | goto out_unlock; | 446 | goto out_unlock; |
@@ -447,7 +448,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
447 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 448 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
448 | algo = P54_CRYPTO_WEP; | 449 | algo = P54_CRYPTO_WEP; |
449 | break; | 450 | break; |
450 | case ALG_CCMP: | 451 | case WLAN_CIPHER_SUITE_CCMP: |
451 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { | 452 | if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { |
452 | ret = -EOPNOTSUPP; | 453 | ret = -EOPNOTSUPP; |
453 | goto out_unlock; | 454 | goto out_unlock; |
diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h index 1ea1050911d9..d592cbd34d78 100644 --- a/drivers/net/wireless/p54/p54spi_eeprom.h +++ b/drivers/net/wireless/p54/p54spi_eeprom.h | |||
@@ -671,7 +671,7 @@ static unsigned char p54spi_eeprom[] = { | |||
671 | 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, | 671 | 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, |
672 | 672 | ||
673 | 0x02, 0x00, 0x00, 0x00, /* PDR_END */ | 673 | 0x02, 0x00, 0x00, 0x00, /* PDR_END */ |
674 | 0xa8, 0xf5 /* bogus data */ | 674 | 0x67, 0x99, |
675 | }; | 675 | }; |
676 | 676 | ||
677 | #endif /* P54SPI_EEPROM_H */ | 677 | #endif /* P54SPI_EEPROM_H */ |
diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c index 173aec3d6e7e..34447d1ad80d 100644 --- a/drivers/net/wireless/p54/txrx.c +++ b/drivers/net/wireless/p54/txrx.c | |||
@@ -683,14 +683,15 @@ static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, | |||
683 | } | 683 | } |
684 | } | 684 | } |
685 | 685 | ||
686 | static u8 p54_convert_algo(enum ieee80211_key_alg alg) | 686 | static u8 p54_convert_algo(u32 cipher) |
687 | { | 687 | { |
688 | switch (alg) { | 688 | switch (cipher) { |
689 | case ALG_WEP: | 689 | case WLAN_CIPHER_SUITE_WEP40: |
690 | case WLAN_CIPHER_SUITE_WEP104: | ||
690 | return P54_CRYPTO_WEP; | 691 | return P54_CRYPTO_WEP; |
691 | case ALG_TKIP: | 692 | case WLAN_CIPHER_SUITE_TKIP: |
692 | return P54_CRYPTO_TKIPMICHAEL; | 693 | return P54_CRYPTO_TKIPMICHAEL; |
693 | case ALG_CCMP: | 694 | case WLAN_CIPHER_SUITE_CCMP: |
694 | return P54_CRYPTO_AESCCMP; | 695 | return P54_CRYPTO_AESCCMP; |
695 | default: | 696 | default: |
696 | return 0; | 697 | return 0; |
@@ -731,7 +732,7 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
731 | 732 | ||
732 | if (info->control.hw_key) { | 733 | if (info->control.hw_key) { |
733 | crypt_offset = ieee80211_get_hdrlen_from_skb(skb); | 734 | crypt_offset = ieee80211_get_hdrlen_from_skb(skb); |
734 | if (info->control.hw_key->alg == ALG_TKIP) { | 735 | if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
735 | u8 *iv = (u8 *)(skb->data + crypt_offset); | 736 | u8 *iv = (u8 *)(skb->data + crypt_offset); |
736 | /* | 737 | /* |
737 | * The firmware excepts that the IV has to have | 738 | * The firmware excepts that the IV has to have |
@@ -827,10 +828,10 @@ int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
827 | hdr->tries = ridx; | 828 | hdr->tries = ridx; |
828 | txhdr->rts_rate_idx = 0; | 829 | txhdr->rts_rate_idx = 0; |
829 | if (info->control.hw_key) { | 830 | if (info->control.hw_key) { |
830 | txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); | 831 | txhdr->key_type = p54_convert_algo(info->control.hw_key->cipher); |
831 | txhdr->key_len = min((u8)16, info->control.hw_key->keylen); | 832 | txhdr->key_len = min((u8)16, info->control.hw_key->keylen); |
832 | memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); | 833 | memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); |
833 | if (info->control.hw_key->alg == ALG_TKIP) { | 834 | if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
834 | /* reserve space for the MIC key */ | 835 | /* reserve space for the MIC key */ |
835 | len += 8; | 836 | len += 8; |
836 | memcpy(skb_put(skb, 8), &(info->control.hw_key->key | 837 | memcpy(skb_put(skb, 8), &(info->control.hw_key->key |
diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 77cd65db8500..d97a2caf582b 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c | |||
@@ -3234,7 +3234,7 @@ prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) | |||
3234 | switch (cmd) { | 3234 | switch (cmd) { |
3235 | case PRISM54_HOSTAPD: | 3235 | case PRISM54_HOSTAPD: |
3236 | if (!capable(CAP_NET_ADMIN)) | 3236 | if (!capable(CAP_NET_ADMIN)) |
3237 | return -EPERM; | 3237 | return -EPERM; |
3238 | ret = prism54_hostapd(ndev, &wrq->u.data); | 3238 | ret = prism54_hostapd(ndev, &wrq->u.data); |
3239 | return ret; | 3239 | return ret; |
3240 | } | 3240 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 8ddaae44d7fb..baadf03a800e 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -355,7 +355,9 @@ static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, | |||
355 | * it is known that not work at least on some hardware. | 355 | * it is known that not work at least on some hardware. |
356 | * SW crypto will be used in that case. | 356 | * SW crypto will be used in that case. |
357 | */ | 357 | */ |
358 | if (key->alg == ALG_WEP && key->keyidx != 0) | 358 | if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 || |
359 | key->cipher == WLAN_CIPHER_SUITE_WEP104) && | ||
360 | key->keyidx != 0) | ||
359 | return -EOPNOTSUPP; | 361 | return -EOPNOTSUPP; |
360 | 362 | ||
361 | /* | 363 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ed4ebcdde7c9..cf1f16bfcd5e 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -1318,7 +1318,25 @@ | |||
1318 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) | 1318 | #define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) |
1319 | 1319 | ||
1320 | /* | 1320 | /* |
1321 | * TX_STA_FIFO: TX Result for specific PID status fifo register | 1321 | * TX_STA_FIFO: TX Result for specific PID status fifo register. |
1322 | * | ||
1323 | * This register is implemented as FIFO with 16 entries in the HW. Each | ||
1324 | * register read fetches the next tx result. If the FIFO is full because | ||
1325 | * it wasn't read fast enough after the according interrupt (TX_FIFO_STATUS) | ||
1326 | * triggered, the hw seems to simply drop further tx results. | ||
1327 | * | ||
1328 | * VALID: 1: this tx result is valid | ||
1329 | * 0: no valid tx result -> driver should stop reading | ||
1330 | * PID_TYPE: The PID latched from the PID field in the TXWI, can be used | ||
1331 | * to match a frame with its tx result (even though the PID is | ||
1332 | * only 4 bits wide). | ||
1333 | * TX_SUCCESS: Indicates tx success (1) or failure (0) | ||
1334 | * TX_AGGRE: Indicates if the frame was part of an aggregate (1) or not (0) | ||
1335 | * TX_ACK_REQUIRED: Indicates if the frame needed to get ack'ed (1) or not (0) | ||
1336 | * WCID: The wireless client ID. | ||
1337 | * MCS: The tx rate used during the last transmission of this frame, be it | ||
1338 | * successful or not. | ||
1339 | * PHYMODE: The phymode used for the transmission. | ||
1322 | */ | 1340 | */ |
1323 | #define TX_STA_FIFO 0x1718 | 1341 | #define TX_STA_FIFO 0x1718 |
1324 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) | 1342 | #define TX_STA_FIFO_VALID FIELD32(0x00000001) |
@@ -1945,6 +1963,13 @@ struct mac_iveiv_entry { | |||
1945 | 1963 | ||
1946 | /* | 1964 | /* |
1947 | * Word1 | 1965 | * Word1 |
1966 | * ACK: 0: No Ack needed, 1: Ack needed | ||
1967 | * NSEQ: 0: Don't assign hw sequence number, 1: Assign hw sequence number | ||
1968 | * BW_WIN_SIZE: BA windows size of the recipient | ||
1969 | * WIRELESS_CLI_ID: Client ID for WCID table access | ||
1970 | * MPDU_TOTAL_BYTE_COUNT: Length of 802.11 frame | ||
1971 | * PACKETID: Will be latched into the TX_STA_FIFO register once the according | ||
1972 | * frame was processed. 0: Don't report tx status for this frame. | ||
1948 | */ | 1973 | */ |
1949 | #define TXWI_W1_ACK FIELD32(0x00000001) | 1974 | #define TXWI_W1_ACK FIELD32(0x00000001) |
1950 | #define TXWI_W1_NSEQ FIELD32(0x00000002) | 1975 | #define TXWI_W1_NSEQ FIELD32(0x00000002) |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 8c00fbda8664..6a0cb2d924d8 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
2 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | 3 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 4 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> |
4 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 5 | Copyright (C) 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
@@ -427,8 +428,10 @@ int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | |||
427 | } | 428 | } |
428 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); | 429 | EXPORT_SYMBOL_GPL(rt2800_load_firmware); |
429 | 430 | ||
430 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | 431 | void rt2800_write_tx_data(struct queue_entry *entry, |
432 | struct txentry_desc *txdesc) | ||
431 | { | 433 | { |
434 | __le32 *txwi = rt2800_drv_get_txwi(entry); | ||
432 | u32 word; | 435 | u32 word; |
433 | 436 | ||
434 | /* | 437 | /* |
@@ -437,7 +440,8 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
437 | rt2x00_desc_read(txwi, 0, &word); | 440 | rt2x00_desc_read(txwi, 0, &word); |
438 | rt2x00_set_field32(&word, TXWI_W0_FRAG, | 441 | rt2x00_set_field32(&word, TXWI_W0_FRAG, |
439 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); | 442 | test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); |
440 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); | 443 | rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, |
444 | test_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags)); | ||
441 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); | 445 | rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); |
442 | rt2x00_set_field32(&word, TXWI_W0_TS, | 446 | rt2x00_set_field32(&word, TXWI_W0_TS, |
443 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); | 447 | test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); |
@@ -478,7 +482,7 @@ void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc) | |||
478 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); | 482 | _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); |
479 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); | 483 | _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); |
480 | } | 484 | } |
481 | EXPORT_SYMBOL_GPL(rt2800_write_txwi); | 485 | EXPORT_SYMBOL_GPL(rt2800_write_tx_data); |
482 | 486 | ||
483 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) | 487 | static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) |
484 | { | 488 | { |
@@ -490,7 +494,7 @@ static int rt2800_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxwi_w2) | |||
490 | u8 offset1; | 494 | u8 offset1; |
491 | u8 offset2; | 495 | u8 offset2; |
492 | 496 | ||
493 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_2GHZ) { | 497 | if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { |
494 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); | 498 | rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &eeprom); |
495 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); | 499 | offset0 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET0); |
496 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); | 500 | offset1 = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG_OFFSET1); |
@@ -569,6 +573,122 @@ void rt2800_process_rxwi(struct queue_entry *entry, | |||
569 | } | 573 | } |
570 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); | 574 | EXPORT_SYMBOL_GPL(rt2800_process_rxwi); |
571 | 575 | ||
576 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev) | ||
577 | { | ||
578 | struct data_queue *queue; | ||
579 | struct queue_entry *entry; | ||
580 | __le32 *txwi; | ||
581 | struct txdone_entry_desc txdesc; | ||
582 | u32 word; | ||
583 | u32 reg; | ||
584 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | ||
585 | u16 mcs, real_mcs; | ||
586 | int i; | ||
587 | |||
588 | /* | ||
589 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO | ||
590 | * at most X times and also stop processing once the TX_STA_FIFO_VALID | ||
591 | * flag is not set anymore. | ||
592 | * | ||
593 | * The legacy drivers use X=TX_RING_SIZE but state in a comment | ||
594 | * that the TX_STA_FIFO stack has a size of 16. We stick to our | ||
595 | * tx ring size for now. | ||
596 | */ | ||
597 | for (i = 0; i < TX_ENTRIES; i++) { | ||
598 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
599 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
600 | break; | ||
601 | |||
602 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
603 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
604 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
605 | |||
606 | /* | ||
607 | * Skip this entry when it contains an invalid | ||
608 | * queue identication number. | ||
609 | */ | ||
610 | if (pid <= 0 || pid > QID_RX) | ||
611 | continue; | ||
612 | |||
613 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); | ||
614 | if (unlikely(!queue)) | ||
615 | continue; | ||
616 | |||
617 | /* | ||
618 | * Inside each queue, we process each entry in a chronological | ||
619 | * order. We first check that the queue is not empty. | ||
620 | */ | ||
621 | entry = NULL; | ||
622 | while (!rt2x00queue_empty(queue)) { | ||
623 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
624 | if (!test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
625 | break; | ||
626 | |||
627 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
628 | } | ||
629 | |||
630 | if (!entry || rt2x00queue_empty(queue)) | ||
631 | break; | ||
632 | |||
633 | /* | ||
634 | * Check if we got a match by looking at WCID/ACK/PID | ||
635 | * fields | ||
636 | */ | ||
637 | txwi = rt2800_drv_get_txwi(entry); | ||
638 | |||
639 | rt2x00_desc_read(txwi, 1, &word); | ||
640 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
641 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
642 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
643 | |||
644 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) | ||
645 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content"); | ||
646 | |||
647 | /* | ||
648 | * Obtain the status about this packet. | ||
649 | */ | ||
650 | txdesc.flags = 0; | ||
651 | rt2x00_desc_read(txwi, 0, &word); | ||
652 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
653 | mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
654 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
655 | |||
656 | /* | ||
657 | * Ralink has a retry mechanism using a global fallback | ||
658 | * table. We setup this fallback table to try the immediate | ||
659 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
660 | * always contains the MCS used for the last transmission, be | ||
661 | * it successful or not. | ||
662 | */ | ||
663 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
664 | /* | ||
665 | * Transmission succeeded. The number of retries is | ||
666 | * mcs - real_mcs | ||
667 | */ | ||
668 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
669 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
670 | } else { | ||
671 | /* | ||
672 | * Transmission failed. The number of retries is | ||
673 | * always 7 in this case (for a total number of 8 | ||
674 | * frames sent). | ||
675 | */ | ||
676 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
677 | txdesc.retry = rt2x00dev->long_retry; | ||
678 | } | ||
679 | |||
680 | /* | ||
681 | * the frame was retried at least once | ||
682 | * -> hw used fallback rates | ||
683 | */ | ||
684 | if (txdesc.retry) | ||
685 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
686 | |||
687 | rt2x00lib_txdone(entry, &txdesc); | ||
688 | } | ||
689 | } | ||
690 | EXPORT_SYMBOL_GPL(rt2800_txdone); | ||
691 | |||
572 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | 692 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) |
573 | { | 693 | { |
574 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 694 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
@@ -600,7 +720,7 @@ void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc) | |||
600 | /* | 720 | /* |
601 | * Add the TXWI for the beacon to the skb. | 721 | * Add the TXWI for the beacon to the skb. |
602 | */ | 722 | */ |
603 | rt2800_write_txwi((__le32 *)entry->skb->data, txdesc); | 723 | rt2800_write_tx_data(entry, txdesc); |
604 | 724 | ||
605 | /* | 725 | /* |
606 | * Dump beacon to userspace through debugfs. | 726 | * Dump beacon to userspace through debugfs. |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h index 091641e3c5e2..3b572c63382d 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.h +++ b/drivers/net/wireless/rt2x00/rt2800lib.h | |||
@@ -1,4 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> | ||
3 | Copyright (C) 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
2 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz | 4 | Copyright (C) 2009 Bartlomiej Zolnierkiewicz |
3 | 5 | ||
4 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
@@ -44,6 +46,7 @@ struct rt2800_ops { | |||
44 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, | 46 | int (*drv_write_firmware)(struct rt2x00_dev *rt2x00dev, |
45 | const u8 *data, const size_t len); | 47 | const u8 *data, const size_t len); |
46 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); | 48 | int (*drv_init_registers)(struct rt2x00_dev *rt2x00dev); |
49 | __le32 *(*drv_get_txwi)(struct queue_entry *entry); | ||
47 | }; | 50 | }; |
48 | 51 | ||
49 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, | 52 | static inline void rt2800_register_read(struct rt2x00_dev *rt2x00dev, |
@@ -126,6 +129,13 @@ static inline int rt2800_drv_init_registers(struct rt2x00_dev *rt2x00dev) | |||
126 | return rt2800ops->drv_init_registers(rt2x00dev); | 129 | return rt2800ops->drv_init_registers(rt2x00dev); |
127 | } | 130 | } |
128 | 131 | ||
132 | static inline __le32 *rt2800_drv_get_txwi(struct queue_entry *entry) | ||
133 | { | ||
134 | const struct rt2800_ops *rt2800ops = entry->queue->rt2x00dev->ops->drv; | ||
135 | |||
136 | return rt2800ops->drv_get_txwi(entry); | ||
137 | } | ||
138 | |||
129 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, | 139 | void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev, |
130 | const u8 command, const u8 token, | 140 | const u8 command, const u8 token, |
131 | const u8 arg0, const u8 arg1); | 141 | const u8 arg0, const u8 arg1); |
@@ -135,9 +145,12 @@ int rt2800_check_firmware(struct rt2x00_dev *rt2x00dev, | |||
135 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, | 145 | int rt2800_load_firmware(struct rt2x00_dev *rt2x00dev, |
136 | const u8 *data, const size_t len); | 146 | const u8 *data, const size_t len); |
137 | 147 | ||
138 | void rt2800_write_txwi(__le32 *txwi, struct txentry_desc *txdesc); | 148 | void rt2800_write_tx_data(struct queue_entry *entry, |
149 | struct txentry_desc *txdesc); | ||
139 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); | 150 | void rt2800_process_rxwi(struct queue_entry *entry, struct rxdone_entry_desc *txdesc); |
140 | 151 | ||
152 | void rt2800_txdone(struct rt2x00_dev *rt2x00dev); | ||
153 | |||
141 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); | 154 | void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc); |
142 | 155 | ||
143 | extern const struct rt2x00debug rt2800_rt2x00debug; | 156 | extern const struct rt2x00debug rt2800_rt2x00debug; |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 39b3846fa340..4390f2b74b2e 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> | 3 | Copyright (C) 2009 Alban Browaeys <prahal@yahoo.com> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> | 5 | Copyright (C) 2009 Luis Correia <luis.f.correia@gmail.com> |
@@ -566,15 +566,11 @@ static int rt2800pci_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
566 | /* | 566 | /* |
567 | * TX descriptor initialization | 567 | * TX descriptor initialization |
568 | */ | 568 | */ |
569 | static void rt2800pci_write_tx_data(struct queue_entry* entry, | 569 | static __le32 *rt2800pci_get_txwi(struct queue_entry *entry) |
570 | struct txentry_desc *txdesc) | ||
571 | { | 570 | { |
572 | __le32 *txwi = (__le32 *) entry->skb->data; | 571 | return (__le32 *) entry->skb->data; |
573 | |||
574 | rt2800_write_txwi(txwi, txdesc); | ||
575 | } | 572 | } |
576 | 573 | ||
577 | |||
578 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 574 | static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
579 | struct sk_buff *skb, | 575 | struct sk_buff *skb, |
580 | struct txentry_desc *txdesc) | 576 | struct txentry_desc *txdesc) |
@@ -728,110 +724,6 @@ static void rt2800pci_fill_rxdone(struct queue_entry *entry, | |||
728 | /* | 724 | /* |
729 | * Interrupt functions. | 725 | * Interrupt functions. |
730 | */ | 726 | */ |
731 | static void rt2800pci_txdone(struct rt2x00_dev *rt2x00dev) | ||
732 | { | ||
733 | struct data_queue *queue; | ||
734 | struct queue_entry *entry; | ||
735 | __le32 *txwi; | ||
736 | struct txdone_entry_desc txdesc; | ||
737 | u32 word; | ||
738 | u32 reg; | ||
739 | int wcid, ack, pid, tx_wcid, tx_ack, tx_pid; | ||
740 | u16 mcs, real_mcs; | ||
741 | int i; | ||
742 | |||
743 | /* | ||
744 | * TX_STA_FIFO is a stack of X entries, hence read TX_STA_FIFO | ||
745 | * at most X times and also stop processing once the TX_STA_FIFO_VALID | ||
746 | * flag is not set anymore. | ||
747 | * | ||
748 | * The legacy drivers use X=TX_RING_SIZE but state in a comment | ||
749 | * that the TX_STA_FIFO stack has a size of 16. We stick to our | ||
750 | * tx ring size for now. | ||
751 | */ | ||
752 | for (i = 0; i < TX_ENTRIES; i++) { | ||
753 | rt2800_register_read(rt2x00dev, TX_STA_FIFO, ®); | ||
754 | if (!rt2x00_get_field32(reg, TX_STA_FIFO_VALID)) | ||
755 | break; | ||
756 | |||
757 | wcid = rt2x00_get_field32(reg, TX_STA_FIFO_WCID); | ||
758 | ack = rt2x00_get_field32(reg, TX_STA_FIFO_TX_ACK_REQUIRED); | ||
759 | pid = rt2x00_get_field32(reg, TX_STA_FIFO_PID_TYPE); | ||
760 | |||
761 | /* | ||
762 | * Skip this entry when it contains an invalid | ||
763 | * queue identication number. | ||
764 | */ | ||
765 | if (pid <= 0 || pid > QID_RX) | ||
766 | continue; | ||
767 | |||
768 | queue = rt2x00queue_get_queue(rt2x00dev, pid - 1); | ||
769 | if (unlikely(!queue)) | ||
770 | continue; | ||
771 | |||
772 | /* | ||
773 | * Inside each queue, we process each entry in a chronological | ||
774 | * order. We first check that the queue is not empty. | ||
775 | */ | ||
776 | if (rt2x00queue_empty(queue)) | ||
777 | continue; | ||
778 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
779 | |||
780 | /* Check if we got a match by looking at WCID/ACK/PID | ||
781 | * fields */ | ||
782 | txwi = (__le32 *) entry->skb->data; | ||
783 | |||
784 | rt2x00_desc_read(txwi, 1, &word); | ||
785 | tx_wcid = rt2x00_get_field32(word, TXWI_W1_WIRELESS_CLI_ID); | ||
786 | tx_ack = rt2x00_get_field32(word, TXWI_W1_ACK); | ||
787 | tx_pid = rt2x00_get_field32(word, TXWI_W1_PACKETID); | ||
788 | |||
789 | if ((wcid != tx_wcid) || (ack != tx_ack) || (pid != tx_pid)) | ||
790 | WARNING(rt2x00dev, "invalid TX_STA_FIFO content\n"); | ||
791 | |||
792 | /* | ||
793 | * Obtain the status about this packet. | ||
794 | */ | ||
795 | txdesc.flags = 0; | ||
796 | rt2x00_desc_read(txwi, 0, &word); | ||
797 | mcs = rt2x00_get_field32(word, TXWI_W0_MCS); | ||
798 | real_mcs = rt2x00_get_field32(reg, TX_STA_FIFO_MCS); | ||
799 | |||
800 | /* | ||
801 | * Ralink has a retry mechanism using a global fallback | ||
802 | * table. We setup this fallback table to try the immediate | ||
803 | * lower rate for all rates. In the TX_STA_FIFO, the MCS field | ||
804 | * always contains the MCS used for the last transmission, be | ||
805 | * it successful or not. | ||
806 | */ | ||
807 | if (rt2x00_get_field32(reg, TX_STA_FIFO_TX_SUCCESS)) { | ||
808 | /* | ||
809 | * Transmission succeeded. The number of retries is | ||
810 | * mcs - real_mcs | ||
811 | */ | ||
812 | __set_bit(TXDONE_SUCCESS, &txdesc.flags); | ||
813 | txdesc.retry = ((mcs > real_mcs) ? mcs - real_mcs : 0); | ||
814 | } else { | ||
815 | /* | ||
816 | * Transmission failed. The number of retries is | ||
817 | * always 7 in this case (for a total number of 8 | ||
818 | * frames sent). | ||
819 | */ | ||
820 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
821 | txdesc.retry = 7; | ||
822 | } | ||
823 | |||
824 | /* | ||
825 | * the frame was retried at least once | ||
826 | * -> hw used fallback rates | ||
827 | */ | ||
828 | if (txdesc.retry) | ||
829 | __set_bit(TXDONE_FALLBACK, &txdesc.flags); | ||
830 | |||
831 | rt2x00lib_txdone(entry, &txdesc); | ||
832 | } | ||
833 | } | ||
834 | |||
835 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) | 727 | static void rt2800pci_wakeup(struct rt2x00_dev *rt2x00dev) |
836 | { | 728 | { |
837 | struct ieee80211_conf conf = { .flags = 0 }; | 729 | struct ieee80211_conf conf = { .flags = 0 }; |
@@ -867,7 +759,7 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance) | |||
867 | * 4 - Tx done interrupt. | 759 | * 4 - Tx done interrupt. |
868 | */ | 760 | */ |
869 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) | 761 | if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) |
870 | rt2800pci_txdone(rt2x00dev); | 762 | rt2800_txdone(rt2x00dev); |
871 | 763 | ||
872 | /* | 764 | /* |
873 | * 5 - Auto wakeup interrupt. | 765 | * 5 - Auto wakeup interrupt. |
@@ -1011,6 +903,7 @@ static const struct rt2800_ops rt2800pci_rt2800_ops = { | |||
1011 | .regbusy_read = rt2x00pci_regbusy_read, | 903 | .regbusy_read = rt2x00pci_regbusy_read, |
1012 | .drv_write_firmware = rt2800pci_write_firmware, | 904 | .drv_write_firmware = rt2800pci_write_firmware, |
1013 | .drv_init_registers = rt2800pci_init_registers, | 905 | .drv_init_registers = rt2800pci_init_registers, |
906 | .drv_get_txwi = rt2800pci_get_txwi, | ||
1014 | }; | 907 | }; |
1015 | 908 | ||
1016 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | 909 | static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { |
@@ -1030,7 +923,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = { | |||
1030 | .reset_tuner = rt2800_reset_tuner, | 923 | .reset_tuner = rt2800_reset_tuner, |
1031 | .link_tuner = rt2800_link_tuner, | 924 | .link_tuner = rt2800_link_tuner, |
1032 | .write_tx_desc = rt2800pci_write_tx_desc, | 925 | .write_tx_desc = rt2800pci_write_tx_desc, |
1033 | .write_tx_data = rt2800pci_write_tx_data, | 926 | .write_tx_data = rt2800_write_tx_data, |
1034 | .write_beacon = rt2800_write_beacon, | 927 | .write_beacon = rt2800_write_beacon, |
1035 | .kick_tx_queue = rt2800pci_kick_tx_queue, | 928 | .kick_tx_queue = rt2800pci_kick_tx_queue, |
1036 | .kill_tx_queue = rt2800pci_kill_tx_queue, | 929 | .kill_tx_queue = rt2800pci_kill_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5a2dfe87c6b6..9ad28be294eb 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2009 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> | 4 | Copyright (C) 2009 Mattias Nissler <mattias.nissler@gmx.de> |
4 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> | 5 | Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
5 | Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> | 6 | Copyright (C) 2009 Xose Vazquez Perez <xose.vazquez@gmail.com> |
@@ -320,15 +321,14 @@ static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, | |||
320 | /* | 321 | /* |
321 | * TX descriptor initialization | 322 | * TX descriptor initialization |
322 | */ | 323 | */ |
323 | static void rt2800usb_write_tx_data(struct queue_entry* entry, | 324 | static __le32 *rt2800usb_get_txwi(struct queue_entry *entry) |
324 | struct txentry_desc *txdesc) | ||
325 | { | 325 | { |
326 | __le32 *txwi = (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); | 326 | if (entry->queue->qid == QID_BEACON) |
327 | 327 | return (__le32 *) (entry->skb->data); | |
328 | rt2800_write_txwi(txwi, txdesc); | 328 | else |
329 | return (__le32 *) (entry->skb->data + TXINFO_DESC_SIZE); | ||
329 | } | 330 | } |
330 | 331 | ||
331 | |||
332 | static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | 332 | static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, |
333 | struct sk_buff *skb, | 333 | struct sk_buff *skb, |
334 | struct txentry_desc *txdesc) | 334 | struct txentry_desc *txdesc) |
@@ -379,6 +379,38 @@ static int rt2800usb_get_tx_data_len(struct queue_entry *entry) | |||
379 | } | 379 | } |
380 | 380 | ||
381 | /* | 381 | /* |
382 | * TX control handlers | ||
383 | */ | ||
384 | static void rt2800usb_work_txdone(struct work_struct *work) | ||
385 | { | ||
386 | struct rt2x00_dev *rt2x00dev = | ||
387 | container_of(work, struct rt2x00_dev, txdone_work); | ||
388 | struct data_queue *queue; | ||
389 | struct queue_entry *entry; | ||
390 | |||
391 | rt2800_txdone(rt2x00dev); | ||
392 | |||
393 | /* | ||
394 | * Process any trailing TX status reports for IO failures, | ||
395 | * we loop until we find the first non-IO error entry. This | ||
396 | * can either be a frame which is free, is being uploaded, | ||
397 | * or has completed the upload but didn't have an entry | ||
398 | * in the TX_STAT_FIFO register yet. | ||
399 | */ | ||
400 | tx_queue_for_each(rt2x00dev, queue) { | ||
401 | while (!rt2x00queue_empty(queue)) { | ||
402 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
403 | |||
404 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || | ||
405 | !test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
406 | break; | ||
407 | |||
408 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | /* | ||
382 | * RX control handlers | 414 | * RX control handlers |
383 | */ | 415 | */ |
384 | static void rt2800usb_fill_rxdone(struct queue_entry *entry, | 416 | static void rt2800usb_fill_rxdone(struct queue_entry *entry, |
@@ -514,6 +546,11 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
514 | */ | 546 | */ |
515 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; | 547 | rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; |
516 | 548 | ||
549 | /* | ||
550 | * Overwrite TX done handler | ||
551 | */ | ||
552 | PREPARE_WORK(&rt2x00dev->txdone_work, rt2800usb_work_txdone); | ||
553 | |||
517 | return 0; | 554 | return 0; |
518 | } | 555 | } |
519 | 556 | ||
@@ -549,6 +586,7 @@ static const struct rt2800_ops rt2800usb_rt2800_ops = { | |||
549 | .regbusy_read = rt2x00usb_regbusy_read, | 586 | .regbusy_read = rt2x00usb_regbusy_read, |
550 | .drv_write_firmware = rt2800usb_write_firmware, | 587 | .drv_write_firmware = rt2800usb_write_firmware, |
551 | .drv_init_registers = rt2800usb_init_registers, | 588 | .drv_init_registers = rt2800usb_init_registers, |
589 | .drv_get_txwi = rt2800usb_get_txwi, | ||
552 | }; | 590 | }; |
553 | 591 | ||
554 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | 592 | static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { |
@@ -566,7 +604,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { | |||
566 | .link_tuner = rt2800_link_tuner, | 604 | .link_tuner = rt2800_link_tuner, |
567 | .watchdog = rt2x00usb_watchdog, | 605 | .watchdog = rt2x00usb_watchdog, |
568 | .write_tx_desc = rt2800usb_write_tx_desc, | 606 | .write_tx_desc = rt2800usb_write_tx_desc, |
569 | .write_tx_data = rt2800usb_write_tx_data, | 607 | .write_tx_data = rt2800_write_tx_data, |
570 | .write_beacon = rt2800_write_beacon, | 608 | .write_beacon = rt2800_write_beacon, |
571 | .get_tx_data_len = rt2800usb_get_tx_data_len, | 609 | .get_tx_data_len = rt2800usb_get_tx_data_len, |
572 | .kick_tx_queue = rt2x00usb_kick_tx_queue, | 610 | .kick_tx_queue = rt2x00usb_kick_tx_queue, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index c21af38cc5af..8c65244a847a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | <http://rt2x00.serialmonkey.com> | 5 | <http://rt2x00.serialmonkey.com> |
5 | 6 | ||
@@ -698,6 +699,7 @@ struct rt2x00_dev { | |||
698 | struct ieee80211_hw *hw; | 699 | struct ieee80211_hw *hw; |
699 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; | 700 | struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; |
700 | enum ieee80211_band curr_band; | 701 | enum ieee80211_band curr_band; |
702 | int curr_freq; | ||
701 | 703 | ||
702 | /* | 704 | /* |
703 | * If enabled, the debugfs interface structures | 705 | * If enabled, the debugfs interface structures |
@@ -850,11 +852,6 @@ struct rt2x00_dev { | |||
850 | struct ieee80211_low_level_stats low_level_stats; | 852 | struct ieee80211_low_level_stats low_level_stats; |
851 | 853 | ||
852 | /* | 854 | /* |
853 | * RX configuration information. | ||
854 | */ | ||
855 | struct ieee80211_rx_status rx_status; | ||
856 | |||
857 | /* | ||
858 | * Scheduled work. | 855 | * Scheduled work. |
859 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() | 856 | * NOTE: intf_work will use ieee80211_iterate_active_interfaces() |
860 | * which means it cannot be placed on the hw->workqueue | 857 | * which means it cannot be placed on the hw->workqueue |
@@ -862,6 +859,12 @@ struct rt2x00_dev { | |||
862 | */ | 859 | */ |
863 | struct work_struct intf_work; | 860 | struct work_struct intf_work; |
864 | 861 | ||
862 | /** | ||
863 | * Scheduled work for TX/RX done handling (USB devices) | ||
864 | */ | ||
865 | struct work_struct rxdone_work; | ||
866 | struct work_struct txdone_work; | ||
867 | |||
865 | /* | 868 | /* |
866 | * Data queue arrays for RX, TX and Beacon. | 869 | * Data queue arrays for RX, TX and Beacon. |
867 | * The Beacon array also contains the Atim queue | 870 | * The Beacon array also contains the Atim queue |
@@ -1071,6 +1074,7 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | |||
1071 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); | 1074 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); |
1072 | void rt2x00lib_txdone(struct queue_entry *entry, | 1075 | void rt2x00lib_txdone(struct queue_entry *entry, |
1073 | struct txdone_entry_desc *txdesc); | 1076 | struct txdone_entry_desc *txdesc); |
1077 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status); | ||
1074 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | 1078 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
1075 | struct queue_entry *entry); | 1079 | struct queue_entry *entry); |
1076 | 1080 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c index 953dc4f2c6af..34f34fa7f53a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ b/drivers/net/wireless/rt2x00/rt2x00config.c | |||
@@ -126,11 +126,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
126 | * ANTENNA_SW_DIVERSITY state to the driver. | 126 | * ANTENNA_SW_DIVERSITY state to the driver. |
127 | * If that happens, fallback to hardware defaults, | 127 | * If that happens, fallback to hardware defaults, |
128 | * or our own default. | 128 | * or our own default. |
129 | * If diversity handling is active for a particular antenna, | ||
130 | * we shouldn't overwrite that antenna. | ||
131 | * The calls to rt2x00lib_config_antenna_check() | ||
132 | * might have caused that we restore back to the already | ||
133 | * active setting. If that has happened we can quit. | ||
134 | */ | 129 | */ |
135 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) | 130 | if (!(ant->flags & ANTENNA_RX_DIVERSITY)) |
136 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); | 131 | config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); |
@@ -142,9 +137,6 @@ void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, | |||
142 | else | 137 | else |
143 | config.tx = active->tx; | 138 | config.tx = active->tx; |
144 | 139 | ||
145 | if (config.rx == active->rx && config.tx == active->tx) | ||
146 | return; | ||
147 | |||
148 | /* | 140 | /* |
149 | * Antenna setup changes require the RX to be disabled, | 141 | * Antenna setup changes require the RX to be disabled, |
150 | * else the changes will be ignored by the device. | 142 | * else the changes will be ignored by the device. |
@@ -209,10 +201,8 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, | |||
209 | rt2x00link_reset_tuner(rt2x00dev, false); | 201 | rt2x00link_reset_tuner(rt2x00dev, false); |
210 | 202 | ||
211 | rt2x00dev->curr_band = conf->channel->band; | 203 | rt2x00dev->curr_band = conf->channel->band; |
204 | rt2x00dev->curr_freq = conf->channel->center_freq; | ||
212 | rt2x00dev->tx_power = conf->power_level; | 205 | rt2x00dev->tx_power = conf->power_level; |
213 | rt2x00dev->short_retry = conf->short_frame_max_tx_count; | 206 | rt2x00dev->short_retry = conf->short_frame_max_tx_count; |
214 | rt2x00dev->long_retry = conf->long_frame_max_tx_count; | 207 | rt2x00dev->long_retry = conf->long_frame_max_tx_count; |
215 | |||
216 | rt2x00dev->rx_status.band = conf->channel->band; | ||
217 | rt2x00dev->rx_status.freq = conf->channel->center_freq; | ||
218 | } | 208 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index 583dacd8d241..5e9074bf2b8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -31,15 +31,14 @@ | |||
31 | 31 | ||
32 | enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) | 32 | enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) |
33 | { | 33 | { |
34 | switch (key->alg) { | 34 | switch (key->cipher) { |
35 | case ALG_WEP: | 35 | case WLAN_CIPHER_SUITE_WEP40: |
36 | if (key->keylen == WLAN_KEY_LEN_WEP40) | 36 | return CIPHER_WEP64; |
37 | return CIPHER_WEP64; | 37 | case WLAN_CIPHER_SUITE_WEP104: |
38 | else | 38 | return CIPHER_WEP128; |
39 | return CIPHER_WEP128; | 39 | case WLAN_CIPHER_SUITE_TKIP: |
40 | case ALG_TKIP: | ||
41 | return CIPHER_TKIP; | 40 | return CIPHER_TKIP; |
42 | case ALG_CCMP: | 41 | case WLAN_CIPHER_SUITE_CCMP: |
43 | return CIPHER_AES; | 42 | return CIPHER_AES; |
44 | default: | 43 | default: |
45 | return CIPHER_NONE; | 44 | return CIPHER_NONE; |
@@ -95,7 +94,7 @@ unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, | |||
95 | overhead += key->iv_len; | 94 | overhead += key->iv_len; |
96 | 95 | ||
97 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 96 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
98 | if (key->alg == ALG_TKIP) | 97 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
99 | overhead += 8; | 98 | overhead += 8; |
100 | } | 99 | } |
101 | 100 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 585e8166f22a..e692608bee8b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | 4 | <http://rt2x00.serialmonkey.com> |
4 | 5 | ||
5 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
@@ -383,15 +384,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
383 | * send the status report back. | 384 | * send the status report back. |
384 | */ | 385 | */ |
385 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) | 386 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) |
386 | /* | 387 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); |
387 | * Only PCI and SOC devices process the tx status in process | ||
388 | * context. Hence use ieee80211_tx_status for PCI and SOC | ||
389 | * devices and stick to ieee80211_tx_status_irqsafe for USB. | ||
390 | */ | ||
391 | if (rt2x00_is_usb(rt2x00dev)) | ||
392 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | ||
393 | else | ||
394 | ieee80211_tx_status(rt2x00dev->hw, entry->skb); | ||
395 | else | 388 | else |
396 | dev_kfree_skb_any(entry->skb); | 389 | dev_kfree_skb_any(entry->skb); |
397 | 390 | ||
@@ -403,7 +396,6 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
403 | 396 | ||
404 | rt2x00dev->ops->lib->clear_entry(entry); | 397 | rt2x00dev->ops->lib->clear_entry(entry); |
405 | 398 | ||
406 | clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
407 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | 399 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); |
408 | 400 | ||
409 | /* | 401 | /* |
@@ -416,6 +408,18 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
416 | } | 408 | } |
417 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 409 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
418 | 410 | ||
411 | void rt2x00lib_txdone_noinfo(struct queue_entry *entry, u32 status) | ||
412 | { | ||
413 | struct txdone_entry_desc txdesc; | ||
414 | |||
415 | txdesc.flags = 0; | ||
416 | __set_bit(status, &txdesc.flags); | ||
417 | txdesc.retry = 0; | ||
418 | |||
419 | rt2x00lib_txdone(entry, &txdesc); | ||
420 | } | ||
421 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone_noinfo); | ||
422 | |||
419 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, | 423 | static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, |
420 | struct rxdone_entry_desc *rxdesc) | 424 | struct rxdone_entry_desc *rxdesc) |
421 | { | 425 | { |
@@ -460,9 +464,13 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
460 | { | 464 | { |
461 | struct rxdone_entry_desc rxdesc; | 465 | struct rxdone_entry_desc rxdesc; |
462 | struct sk_buff *skb; | 466 | struct sk_buff *skb; |
463 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 467 | struct ieee80211_rx_status *rx_status; |
464 | unsigned int header_length; | 468 | unsigned int header_length; |
465 | int rate_idx; | 469 | int rate_idx; |
470 | |||
471 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
472 | goto submit_entry; | ||
473 | |||
466 | /* | 474 | /* |
467 | * Allocate a new sk_buffer. If no new buffer available, drop the | 475 | * Allocate a new sk_buffer. If no new buffer available, drop the |
468 | * received frame and reuse the existing buffer. | 476 | * received frame and reuse the existing buffer. |
@@ -527,39 +535,32 @@ void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | |||
527 | */ | 535 | */ |
528 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); | 536 | rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); |
529 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); | 537 | rt2x00debug_update_crypto(rt2x00dev, &rxdesc); |
538 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | ||
530 | 539 | ||
540 | /* | ||
541 | * Initialize RX status information, and send frame | ||
542 | * to mac80211. | ||
543 | */ | ||
544 | rx_status = IEEE80211_SKB_RXCB(entry->skb); | ||
531 | rx_status->mactime = rxdesc.timestamp; | 545 | rx_status->mactime = rxdesc.timestamp; |
546 | rx_status->band = rt2x00dev->curr_band; | ||
547 | rx_status->freq = rt2x00dev->curr_freq; | ||
532 | rx_status->rate_idx = rate_idx; | 548 | rx_status->rate_idx = rate_idx; |
533 | rx_status->signal = rxdesc.rssi; | 549 | rx_status->signal = rxdesc.rssi; |
534 | rx_status->flag = rxdesc.flags; | 550 | rx_status->flag = rxdesc.flags; |
535 | rx_status->antenna = rt2x00dev->link.ant.active.rx; | 551 | rx_status->antenna = rt2x00dev->link.ant.active.rx; |
536 | 552 | ||
537 | /* | 553 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); |
538 | * Send frame to mac80211 & debugfs. | ||
539 | * mac80211 will clean up the skb structure. | ||
540 | */ | ||
541 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | ||
542 | memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); | ||
543 | |||
544 | /* | ||
545 | * Currently only PCI and SOC devices handle rx interrupts in process | ||
546 | * context. Hence, use ieee80211_rx_irqsafe for USB and ieee80211_rx_ni | ||
547 | * for PCI and SOC devices. | ||
548 | */ | ||
549 | if (rt2x00_is_usb(rt2x00dev)) | ||
550 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); | ||
551 | else | ||
552 | ieee80211_rx_ni(rt2x00dev->hw, entry->skb); | ||
553 | 554 | ||
554 | /* | 555 | /* |
555 | * Replace the skb with the freshly allocated one. | 556 | * Replace the skb with the freshly allocated one. |
556 | */ | 557 | */ |
557 | entry->skb = skb; | 558 | entry->skb = skb; |
558 | entry->flags = 0; | ||
559 | 559 | ||
560 | submit_entry: | ||
560 | rt2x00dev->ops->lib->clear_entry(entry); | 561 | rt2x00dev->ops->lib->clear_entry(entry); |
561 | |||
562 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | 562 | rt2x00queue_index_inc(entry->queue, Q_INDEX); |
563 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
563 | } | 564 | } |
564 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | 565 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); |
565 | 566 | ||
@@ -1017,6 +1018,8 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1017 | * Stop all work. | 1018 | * Stop all work. |
1018 | */ | 1019 | */ |
1019 | cancel_work_sync(&rt2x00dev->intf_work); | 1020 | cancel_work_sync(&rt2x00dev->intf_work); |
1021 | cancel_work_sync(&rt2x00dev->rxdone_work); | ||
1022 | cancel_work_sync(&rt2x00dev->txdone_work); | ||
1020 | 1023 | ||
1021 | /* | 1024 | /* |
1022 | * Uninitialize device. | 1025 | * Uninitialize device. |
diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c index b818a43c4672..f0e1eb72befc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ b/drivers/net/wireless/rt2x00/rt2x00firmware.c | |||
@@ -63,6 +63,9 @@ static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) | |||
63 | 63 | ||
64 | INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", | 64 | INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", |
65 | fw->data[fw->size - 4], fw->data[fw->size - 3]); | 65 | fw->data[fw->size - 4], fw->data[fw->size - 3]); |
66 | snprintf(rt2x00dev->hw->wiphy->fw_version, | ||
67 | sizeof(rt2x00dev->hw->wiphy->fw_version), "%d.%d", | ||
68 | fw->data[fw->size - 4], fw->data[fw->size - 3]); | ||
66 | 69 | ||
67 | retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); | 70 | retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); |
68 | switch (retval) { | 71 | switch (retval) { |
diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c index c004cd3a8847..ad3c7ff4837b 100644 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ b/drivers/net/wireless/rt2x00/rt2x00ht.c | |||
@@ -54,6 +54,16 @@ void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, | |||
54 | */ | 54 | */ |
55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { | 55 | if (txrate->flags & IEEE80211_TX_RC_MCS) { |
56 | txdesc->mcs = txrate->idx; | 56 | txdesc->mcs = txrate->idx; |
57 | |||
58 | /* | ||
59 | * MIMO PS should be set to 1 for STA's using dynamic SM PS | ||
60 | * when using more then one tx stream (>MCS7). | ||
61 | */ | ||
62 | if (tx_info->control.sta && txdesc->mcs > 7 && | ||
63 | (tx_info->control.sta->ht_cap.cap & | ||
64 | (WLAN_HT_CAP_SM_PS_DYNAMIC << | ||
65 | IEEE80211_HT_CAP_SM_PS_SHIFT))) | ||
66 | __set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags); | ||
57 | } else { | 67 | } else { |
58 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); | 68 | txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); |
59 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) | 69 | if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9c609be95083..480d33a3ce42 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> | 4 | Copyright (C) 2004 - 2009 Gertjan van Wingerde <gwingerde@gmail.com> |
4 | <http://rt2x00.serialmonkey.com> | 5 | <http://rt2x00.serialmonkey.com> |
5 | 6 | ||
@@ -730,9 +731,9 @@ void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) | |||
730 | rt2x00queue_reset(queue); | 731 | rt2x00queue_reset(queue); |
731 | 732 | ||
732 | for (i = 0; i < queue->limit; i++) { | 733 | for (i = 0; i < queue->limit; i++) { |
733 | queue->entries[i].flags = 0; | ||
734 | |||
735 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); | 734 | rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); |
735 | if (queue->qid == QID_RX) | ||
736 | rt2x00queue_index_inc(queue, Q_INDEX); | ||
736 | } | 737 | } |
737 | } | 738 | } |
738 | } | 739 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 191e7775a9c0..2d3bf843735f 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> |
3 | <http://rt2x00.serialmonkey.com> | 3 | <http://rt2x00.serialmonkey.com> |
4 | 4 | ||
5 | This program is free software; you can redistribute it and/or modify | 5 | This program is free software; you can redistribute it and/or modify |
@@ -268,6 +268,7 @@ struct txdone_entry_desc { | |||
268 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. | 268 | * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. |
269 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. | 269 | * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. |
270 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. | 270 | * @ENTRY_TXD_HT_SHORT_GI: Use short GI. |
271 | * @ENTRY_TXD_HT_MIMO_PS: The receiving STA is in dynamic SM PS mode. | ||
271 | */ | 272 | */ |
272 | enum txentry_desc_flags { | 273 | enum txentry_desc_flags { |
273 | ENTRY_TXD_RTS_FRAME, | 274 | ENTRY_TXD_RTS_FRAME, |
@@ -286,6 +287,7 @@ enum txentry_desc_flags { | |||
286 | ENTRY_TXD_HT_AMPDU, | 287 | ENTRY_TXD_HT_AMPDU, |
287 | ENTRY_TXD_HT_BW_40, | 288 | ENTRY_TXD_HT_BW_40, |
288 | ENTRY_TXD_HT_SHORT_GI, | 289 | ENTRY_TXD_HT_SHORT_GI, |
290 | ENTRY_TXD_HT_MIMO_PS, | ||
289 | }; | 291 | }; |
290 | 292 | ||
291 | /** | 293 | /** |
@@ -363,12 +365,16 @@ struct txentry_desc { | |||
363 | * the device has signaled it is done with it. | 365 | * the device has signaled it is done with it. |
364 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting | 366 | * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting |
365 | * for the signal to start sending. | 367 | * for the signal to start sending. |
368 | * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured | ||
369 | * while transfering the data to the hardware. No TX status report will | ||
370 | * be expected from the hardware. | ||
366 | */ | 371 | */ |
367 | enum queue_entry_flags { | 372 | enum queue_entry_flags { |
368 | ENTRY_BCN_ASSIGNED, | 373 | ENTRY_BCN_ASSIGNED, |
369 | ENTRY_OWNER_DEVICE_DATA, | 374 | ENTRY_OWNER_DEVICE_DATA, |
370 | ENTRY_OWNER_DEVICE_CRYPTO, | 375 | ENTRY_OWNER_DEVICE_CRYPTO, |
371 | ENTRY_DATA_PENDING, | 376 | ENTRY_DATA_PENDING, |
377 | ENTRY_DATA_IO_FAILED | ||
372 | }; | 378 | }; |
373 | 379 | ||
374 | /** | 380 | /** |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index ff3a36622d1b..f76014f732ce 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (C) 2004 - 2009 Ivo van Doorn <IvDoorn@gmail.com> | 2 | Copyright (C) 2010 Willow Garage <http://www.willowgarage.com> |
3 | Copyright (C) 2004 - 2010 Ivo van Doorn <IvDoorn@gmail.com> | ||
3 | <http://rt2x00.serialmonkey.com> | 4 | <http://rt2x00.serialmonkey.com> |
4 | 5 | ||
5 | This program is free software; you can redistribute it and/or modify | 6 | This program is free software; you can redistribute it and/or modify |
@@ -167,33 +168,61 @@ EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); | |||
167 | /* | 168 | /* |
168 | * TX data handlers. | 169 | * TX data handlers. |
169 | */ | 170 | */ |
171 | static void rt2x00usb_work_txdone_entry(struct queue_entry *entry) | ||
172 | { | ||
173 | /* | ||
174 | * If the transfer to hardware succeeded, it does not mean the | ||
175 | * frame was send out correctly. It only means the frame | ||
176 | * was succesfully pushed to the hardware, we have no | ||
177 | * way to determine the transmission status right now. | ||
178 | * (Only indirectly by looking at the failed TX counters | ||
179 | * in the register). | ||
180 | */ | ||
181 | if (test_bit(ENTRY_DATA_IO_FAILED, &entry->flags)) | ||
182 | rt2x00lib_txdone_noinfo(entry, TXDONE_FAILURE); | ||
183 | else | ||
184 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); | ||
185 | } | ||
186 | |||
187 | static void rt2x00usb_work_txdone(struct work_struct *work) | ||
188 | { | ||
189 | struct rt2x00_dev *rt2x00dev = | ||
190 | container_of(work, struct rt2x00_dev, txdone_work); | ||
191 | struct data_queue *queue; | ||
192 | struct queue_entry *entry; | ||
193 | |||
194 | tx_queue_for_each(rt2x00dev, queue) { | ||
195 | while (!rt2x00queue_empty(queue)) { | ||
196 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | ||
197 | |||
198 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
199 | break; | ||
200 | |||
201 | rt2x00usb_work_txdone_entry(entry); | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
170 | static void rt2x00usb_interrupt_txdone(struct urb *urb) | 206 | static void rt2x00usb_interrupt_txdone(struct urb *urb) |
171 | { | 207 | { |
172 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 208 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
173 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 209 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
174 | struct txdone_entry_desc txdesc; | ||
175 | 210 | ||
176 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 211 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
177 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 212 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
178 | return; | 213 | return; |
179 | 214 | ||
180 | /* | 215 | /* |
181 | * Obtain the status about this packet. | 216 | * Check if the frame was correctly uploaded |
182 | * Note that when the status is 0 it does not mean the | ||
183 | * frame was send out correctly. It only means the frame | ||
184 | * was succesfully pushed to the hardware, we have no | ||
185 | * way to determine the transmission status right now. | ||
186 | * (Only indirectly by looking at the failed TX counters | ||
187 | * in the register). | ||
188 | */ | 217 | */ |
189 | txdesc.flags = 0; | 218 | if (urb->status) |
190 | if (!urb->status) | 219 | __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
191 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
192 | else | ||
193 | __set_bit(TXDONE_FAILURE, &txdesc.flags); | ||
194 | txdesc.retry = 0; | ||
195 | 220 | ||
196 | rt2x00lib_txdone(entry, &txdesc); | 221 | /* |
222 | * Schedule the delayed work for reading the TX status | ||
223 | * from the device. | ||
224 | */ | ||
225 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work); | ||
197 | } | 226 | } |
198 | 227 | ||
199 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) | 228 | static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) |
@@ -294,6 +323,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); | |||
294 | 323 | ||
295 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | 324 | static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) |
296 | { | 325 | { |
326 | struct queue_entry *entry; | ||
297 | struct queue_entry_priv_usb *entry_priv; | 327 | struct queue_entry_priv_usb *entry_priv; |
298 | unsigned short threshold = queue->threshold; | 328 | unsigned short threshold = queue->threshold; |
299 | 329 | ||
@@ -313,14 +343,22 @@ static void rt2x00usb_watchdog_reset_tx(struct data_queue *queue) | |||
313 | * Reset all currently uploaded TX frames. | 343 | * Reset all currently uploaded TX frames. |
314 | */ | 344 | */ |
315 | while (!rt2x00queue_empty(queue)) { | 345 | while (!rt2x00queue_empty(queue)) { |
316 | entry_priv = rt2x00queue_get_entry(queue, Q_INDEX_DONE)->priv_data; | 346 | entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
347 | entry_priv = entry->priv_data; | ||
317 | usb_kill_urb(entry_priv->urb); | 348 | usb_kill_urb(entry_priv->urb); |
318 | 349 | ||
319 | /* | 350 | /* |
320 | * We need a short delay here to wait for | 351 | * We need a short delay here to wait for |
321 | * the URB to be canceled and invoked the tx_done handler. | 352 | * the URB to be canceled |
353 | */ | ||
354 | do { | ||
355 | udelay(100); | ||
356 | } while (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)); | ||
357 | |||
358 | /* | ||
359 | * Invoke the TX done handler | ||
322 | */ | 360 | */ |
323 | udelay(200); | 361 | rt2x00usb_work_txdone_entry(entry); |
324 | } | 362 | } |
325 | 363 | ||
326 | /* | 364 | /* |
@@ -345,15 +383,41 @@ EXPORT_SYMBOL_GPL(rt2x00usb_watchdog); | |||
345 | /* | 383 | /* |
346 | * RX data handlers. | 384 | * RX data handlers. |
347 | */ | 385 | */ |
386 | static void rt2x00usb_work_rxdone(struct work_struct *work) | ||
387 | { | ||
388 | struct rt2x00_dev *rt2x00dev = | ||
389 | container_of(work, struct rt2x00_dev, rxdone_work); | ||
390 | struct queue_entry *entry; | ||
391 | struct skb_frame_desc *skbdesc; | ||
392 | u8 rxd[32]; | ||
393 | |||
394 | while (!rt2x00queue_empty(rt2x00dev->rx)) { | ||
395 | entry = rt2x00queue_get_entry(rt2x00dev->rx, Q_INDEX_DONE); | ||
396 | |||
397 | if (test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | ||
398 | break; | ||
399 | |||
400 | /* | ||
401 | * Fill in desc fields of the skb descriptor | ||
402 | */ | ||
403 | skbdesc = get_skb_frame_desc(entry->skb); | ||
404 | skbdesc->desc = rxd; | ||
405 | skbdesc->desc_len = entry->queue->desc_size; | ||
406 | |||
407 | /* | ||
408 | * Send the frame to rt2x00lib for further processing. | ||
409 | */ | ||
410 | rt2x00lib_rxdone(rt2x00dev, entry); | ||
411 | } | ||
412 | } | ||
413 | |||
348 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) | 414 | static void rt2x00usb_interrupt_rxdone(struct urb *urb) |
349 | { | 415 | { |
350 | struct queue_entry *entry = (struct queue_entry *)urb->context; | 416 | struct queue_entry *entry = (struct queue_entry *)urb->context; |
351 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 417 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
352 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | ||
353 | u8 rxd[32]; | ||
354 | 418 | ||
355 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || | 419 | if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || |
356 | !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 420 | !__test_and_clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
357 | return; | 421 | return; |
358 | 422 | ||
359 | /* | 423 | /* |
@@ -361,22 +425,14 @@ static void rt2x00usb_interrupt_rxdone(struct urb *urb) | |||
361 | * to be actually valid, or if the urb is signaling | 425 | * to be actually valid, or if the urb is signaling |
362 | * a problem. | 426 | * a problem. |
363 | */ | 427 | */ |
364 | if (urb->actual_length < entry->queue->desc_size || urb->status) { | 428 | if (urb->actual_length < entry->queue->desc_size || urb->status) |
365 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 429 | __set_bit(ENTRY_DATA_IO_FAILED, &entry->flags); |
366 | usb_submit_urb(urb, GFP_ATOMIC); | ||
367 | return; | ||
368 | } | ||
369 | |||
370 | /* | ||
371 | * Fill in desc fields of the skb descriptor | ||
372 | */ | ||
373 | skbdesc->desc = rxd; | ||
374 | skbdesc->desc_len = entry->queue->desc_size; | ||
375 | 430 | ||
376 | /* | 431 | /* |
377 | * Send the frame to rt2x00lib for further processing. | 432 | * Schedule the delayed work for reading the RX status |
433 | * from the device. | ||
378 | */ | 434 | */ |
379 | rt2x00lib_rxdone(rt2x00dev, entry); | 435 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work); |
380 | } | 436 | } |
381 | 437 | ||
382 | /* | 438 | /* |
@@ -405,6 +461,8 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
405 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; | 461 | struct queue_entry_priv_usb *entry_priv = entry->priv_data; |
406 | int pipe; | 462 | int pipe; |
407 | 463 | ||
464 | entry->flags = 0; | ||
465 | |||
408 | if (entry->queue->qid == QID_RX) { | 466 | if (entry->queue->qid == QID_RX) { |
409 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); | 467 | pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); |
410 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, | 468 | usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, |
@@ -413,8 +471,6 @@ void rt2x00usb_clear_entry(struct queue_entry *entry) | |||
413 | 471 | ||
414 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | 472 | set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); |
415 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); | 473 | usb_submit_urb(entry_priv->urb, GFP_ATOMIC); |
416 | } else { | ||
417 | entry->flags = 0; | ||
418 | } | 474 | } |
419 | } | 475 | } |
420 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); | 476 | EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); |
@@ -659,6 +715,9 @@ int rt2x00usb_probe(struct usb_interface *usb_intf, | |||
659 | 715 | ||
660 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); | 716 | rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_USB); |
661 | 717 | ||
718 | INIT_WORK(&rt2x00dev->rxdone_work, rt2x00usb_work_rxdone); | ||
719 | INIT_WORK(&rt2x00dev->txdone_work, rt2x00usb_work_txdone); | ||
720 | |||
662 | retval = rt2x00usb_alloc_reg(rt2x00dev); | 721 | retval = rt2x00usb_alloc_reg(rt2x00dev); |
663 | if (retval) | 722 | if (retval) |
664 | goto exit_free_device; | 723 | goto exit_free_device; |
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index f226582dbc87..3f8d10b76fee 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c | |||
@@ -1050,7 +1050,7 @@ static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
1050 | /* | 1050 | /* |
1051 | * Determine r17 bounds. | 1051 | * Determine r17 bounds. |
1052 | */ | 1052 | */ |
1053 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1053 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1054 | low_bound = 0x28; | 1054 | low_bound = 0x28; |
1055 | up_bound = 0x48; | 1055 | up_bound = 0x48; |
1056 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { | 1056 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { |
@@ -1972,7 +1972,7 @@ static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1972 | return 0; | 1972 | return 0; |
1973 | } | 1973 | } |
1974 | 1974 | ||
1975 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1975 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1976 | if (lna == 3 || lna == 2) | 1976 | if (lna == 3 || lna == 2) |
1977 | offset += 10; | 1977 | offset += 10; |
1978 | } | 1978 | } |
@@ -2107,11 +2107,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) | |||
2107 | "TX status report missed for entry %d\n", | 2107 | "TX status report missed for entry %d\n", |
2108 | entry_done->entry_idx); | 2108 | entry_done->entry_idx); |
2109 | 2109 | ||
2110 | txdesc.flags = 0; | 2110 | rt2x00lib_txdone_noinfo(entry, TXDONE_UNKNOWN); |
2111 | __set_bit(TXDONE_UNKNOWN, &txdesc.flags); | ||
2112 | txdesc.retry = 0; | ||
2113 | |||
2114 | rt2x00lib_txdone(entry_done, &txdesc); | ||
2115 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); | 2111 | entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); |
2116 | } | 2112 | } |
2117 | 2113 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 99985a218653..8ca19f70aea7 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -929,7 +929,7 @@ static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, | |||
929 | /* | 929 | /* |
930 | * Determine r17 bounds. | 930 | * Determine r17 bounds. |
931 | */ | 931 | */ |
932 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 932 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
933 | low_bound = 0x28; | 933 | low_bound = 0x28; |
934 | up_bound = 0x48; | 934 | up_bound = 0x48; |
935 | 935 | ||
@@ -1597,7 +1597,7 @@ static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) | |||
1597 | return 0; | 1597 | return 0; |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { | 1600 | if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { |
1601 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { | 1601 | if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { |
1602 | if (lna == 3 || lna == 2) | 1602 | if (lna == 3 || lna == 2) |
1603 | offset += 10; | 1603 | offset += 10; |
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 30107ce78dfb..05c6badbe201 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -99,19 +99,66 @@ void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) | |||
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
102 | static void rtl8180_handle_rx(struct ieee80211_hw *dev) | 102 | static void rtl8180_handle_tx(struct ieee80211_hw *dev) |
103 | { | 103 | { |
104 | struct rtl8180_priv *priv = dev->priv; | 104 | struct rtl8180_priv *priv = dev->priv; |
105 | unsigned int count = 32; | 105 | struct rtl8180_tx_ring *ring; |
106 | int prio; | ||
107 | |||
108 | spin_lock(&priv->lock); | ||
109 | |||
110 | for (prio = 3; prio >= 0; prio--) { | ||
111 | ring = &priv->tx_ring[prio]; | ||
112 | |||
113 | while (skb_queue_len(&ring->queue)) { | ||
114 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | ||
115 | struct sk_buff *skb; | ||
116 | struct ieee80211_tx_info *info; | ||
117 | u32 flags = le32_to_cpu(entry->flags); | ||
118 | |||
119 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
120 | break; | ||
121 | |||
122 | ring->idx = (ring->idx + 1) % ring->entries; | ||
123 | skb = __skb_dequeue(&ring->queue); | ||
124 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
125 | skb->len, PCI_DMA_TODEVICE); | ||
126 | |||
127 | info = IEEE80211_SKB_CB(skb); | ||
128 | ieee80211_tx_info_clear_status(info); | ||
129 | |||
130 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
131 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
132 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
133 | |||
134 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
135 | info->status.rates[1].idx = -1; | ||
136 | |||
137 | ieee80211_tx_status(dev, skb); | ||
138 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
139 | ieee80211_wake_queue(dev, prio); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | spin_unlock(&priv->lock); | ||
144 | } | ||
145 | |||
146 | static int rtl8180_poll(struct ieee80211_hw *dev, int budget) | ||
147 | { | ||
148 | struct rtl8180_priv *priv = dev->priv; | ||
149 | unsigned int count = 0; | ||
106 | u8 signal, agc, sq; | 150 | u8 signal, agc, sq; |
107 | 151 | ||
108 | while (count--) { | 152 | /* handle pending Tx queue cleanup */ |
153 | rtl8180_handle_tx(dev); | ||
154 | |||
155 | while (count++ < budget) { | ||
109 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; | 156 | struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; |
110 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; | 157 | struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; |
111 | u32 flags = le32_to_cpu(entry->flags); | 158 | u32 flags = le32_to_cpu(entry->flags); |
112 | 159 | ||
113 | if (flags & RTL818X_RX_DESC_FLAG_OWN) | 160 | if (flags & RTL818X_RX_DESC_FLAG_OWN) |
114 | return; | 161 | break; |
115 | 162 | ||
116 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | | 163 | if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | |
117 | RTL818X_RX_DESC_FLAG_FOF | | 164 | RTL818X_RX_DESC_FLAG_FOF | |
@@ -151,7 +198,7 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
151 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; | 198 | rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; |
152 | 199 | ||
153 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 200 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
154 | ieee80211_rx_irqsafe(dev, skb); | 201 | ieee80211_rx(dev, skb); |
155 | 202 | ||
156 | skb = new_skb; | 203 | skb = new_skb; |
157 | priv->rx_buf[priv->rx_idx] = skb; | 204 | priv->rx_buf[priv->rx_idx] = skb; |
@@ -168,41 +215,16 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev) | |||
168 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); | 215 | entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); |
169 | priv->rx_idx = (priv->rx_idx + 1) % 32; | 216 | priv->rx_idx = (priv->rx_idx + 1) % 32; |
170 | } | 217 | } |
171 | } | ||
172 | 218 | ||
173 | static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) | 219 | if (count < budget) { |
174 | { | 220 | /* disable polling */ |
175 | struct rtl8180_priv *priv = dev->priv; | 221 | ieee80211_napi_complete(dev); |
176 | struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; | ||
177 | 222 | ||
178 | while (skb_queue_len(&ring->queue)) { | 223 | /* enable interrupts */ |
179 | struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; | 224 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); |
180 | struct sk_buff *skb; | ||
181 | struct ieee80211_tx_info *info; | ||
182 | u32 flags = le32_to_cpu(entry->flags); | ||
183 | |||
184 | if (flags & RTL818X_TX_DESC_FLAG_OWN) | ||
185 | return; | ||
186 | |||
187 | ring->idx = (ring->idx + 1) % ring->entries; | ||
188 | skb = __skb_dequeue(&ring->queue); | ||
189 | pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), | ||
190 | skb->len, PCI_DMA_TODEVICE); | ||
191 | |||
192 | info = IEEE80211_SKB_CB(skb); | ||
193 | ieee80211_tx_info_clear_status(info); | ||
194 | |||
195 | if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && | ||
196 | (flags & RTL818X_TX_DESC_FLAG_TX_OK)) | ||
197 | info->flags |= IEEE80211_TX_STAT_ACK; | ||
198 | |||
199 | info->status.rates[0].count = (flags & 0xFF) + 1; | ||
200 | info->status.rates[1].idx = -1; | ||
201 | |||
202 | ieee80211_tx_status_irqsafe(dev, skb); | ||
203 | if (ring->entries - skb_queue_len(&ring->queue) == 2) | ||
204 | ieee80211_wake_queue(dev, prio); | ||
205 | } | 225 | } |
226 | |||
227 | return count; | ||
206 | } | 228 | } |
207 | 229 | ||
208 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | 230 | static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) |
@@ -211,31 +233,17 @@ static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) | |||
211 | struct rtl8180_priv *priv = dev->priv; | 233 | struct rtl8180_priv *priv = dev->priv; |
212 | u16 reg; | 234 | u16 reg; |
213 | 235 | ||
214 | spin_lock(&priv->lock); | ||
215 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); | 236 | reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); |
216 | if (unlikely(reg == 0xFFFF)) { | 237 | if (unlikely(reg == 0xFFFF)) |
217 | spin_unlock(&priv->lock); | ||
218 | return IRQ_HANDLED; | 238 | return IRQ_HANDLED; |
219 | } | ||
220 | 239 | ||
221 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); | 240 | rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); |
222 | 241 | ||
223 | if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) | 242 | /* disable interrupts */ |
224 | rtl8180_handle_tx(dev, 3); | 243 | rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); |
225 | |||
226 | if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) | ||
227 | rtl8180_handle_tx(dev, 2); | ||
228 | |||
229 | if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) | ||
230 | rtl8180_handle_tx(dev, 1); | ||
231 | |||
232 | if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) | ||
233 | rtl8180_handle_tx(dev, 0); | ||
234 | |||
235 | if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) | ||
236 | rtl8180_handle_rx(dev); | ||
237 | 244 | ||
238 | spin_unlock(&priv->lock); | 245 | /* enable polling */ |
246 | ieee80211_napi_schedule(dev); | ||
239 | 247 | ||
240 | return IRQ_HANDLED; | 248 | return IRQ_HANDLED; |
241 | } | 249 | } |
@@ -247,7 +255,6 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
247 | struct rtl8180_priv *priv = dev->priv; | 255 | struct rtl8180_priv *priv = dev->priv; |
248 | struct rtl8180_tx_ring *ring; | 256 | struct rtl8180_tx_ring *ring; |
249 | struct rtl8180_tx_desc *entry; | 257 | struct rtl8180_tx_desc *entry; |
250 | unsigned long flags; | ||
251 | unsigned int idx, prio; | 258 | unsigned int idx, prio; |
252 | dma_addr_t mapping; | 259 | dma_addr_t mapping; |
253 | u32 tx_flags; | 260 | u32 tx_flags; |
@@ -294,7 +301,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
294 | plcp_len |= 1 << 15; | 301 | plcp_len |= 1 << 15; |
295 | } | 302 | } |
296 | 303 | ||
297 | spin_lock_irqsave(&priv->lock, flags); | 304 | spin_lock(&priv->lock); |
298 | 305 | ||
299 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 306 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
300 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 307 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
@@ -318,7 +325,7 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
318 | if (ring->entries - skb_queue_len(&ring->queue) < 2) | 325 | if (ring->entries - skb_queue_len(&ring->queue) < 2) |
319 | ieee80211_stop_queue(dev, prio); | 326 | ieee80211_stop_queue(dev, prio); |
320 | 327 | ||
321 | spin_unlock_irqrestore(&priv->lock, flags); | 328 | spin_unlock(&priv->lock); |
322 | 329 | ||
323 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); | 330 | rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); |
324 | 331 | ||
@@ -783,6 +790,7 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
783 | struct rtl8180_priv *priv = dev->priv; | 790 | struct rtl8180_priv *priv = dev->priv; |
784 | struct rtl8180_vif *vif_priv; | 791 | struct rtl8180_vif *vif_priv; |
785 | int i; | 792 | int i; |
793 | u8 reg; | ||
786 | 794 | ||
787 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; | 795 | vif_priv = (struct rtl8180_vif *)&vif->drv_priv; |
788 | 796 | ||
@@ -791,12 +799,14 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
791 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], | 799 | rtl818x_iowrite8(priv, &priv->map->BSSID[i], |
792 | info->bssid[i]); | 800 | info->bssid[i]); |
793 | 801 | ||
794 | if (is_valid_ether_addr(info->bssid)) | 802 | if (is_valid_ether_addr(info->bssid)) { |
795 | rtl818x_iowrite8(priv, &priv->map->MSR, | 803 | if (vif->type == NL80211_IFTYPE_ADHOC) |
796 | RTL818X_MSR_INFRA); | 804 | reg = RTL818X_MSR_ADHOC; |
797 | else | 805 | else |
798 | rtl818x_iowrite8(priv, &priv->map->MSR, | 806 | reg = RTL818X_MSR_INFRA; |
799 | RTL818X_MSR_NO_LINK); | 807 | } else |
808 | reg = RTL818X_MSR_NO_LINK; | ||
809 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | ||
800 | } | 810 | } |
801 | 811 | ||
802 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) | 812 | if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) |
@@ -861,6 +871,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
861 | .prepare_multicast = rtl8180_prepare_multicast, | 871 | .prepare_multicast = rtl8180_prepare_multicast, |
862 | .configure_filter = rtl8180_configure_filter, | 872 | .configure_filter = rtl8180_configure_filter, |
863 | .get_tsf = rtl8180_get_tsf, | 873 | .get_tsf = rtl8180_get_tsf, |
874 | .napi_poll = rtl8180_poll, | ||
864 | }; | 875 | }; |
865 | 876 | ||
866 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) | 877 | static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) |
@@ -992,6 +1003,8 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
992 | dev->queues = 1; | 1003 | dev->queues = 1; |
993 | dev->max_signal = 65; | 1004 | dev->max_signal = 65; |
994 | 1005 | ||
1006 | dev->napi_weight = 64; | ||
1007 | |||
995 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); | 1008 | reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); |
996 | reg &= RTL818X_TX_CONF_HWVER_MASK; | 1009 | reg &= RTL818X_TX_CONF_HWVER_MASK; |
997 | switch (reg) { | 1010 | switch (reg) { |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 98e0351c1dd6..38fa8244cc96 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1176,13 +1176,12 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, | |||
1176 | else | 1176 | else |
1177 | reg = 0; | 1177 | reg = 0; |
1178 | 1178 | ||
1179 | if (is_valid_ether_addr(info->bssid)) { | 1179 | if (is_valid_ether_addr(info->bssid)) |
1180 | reg |= RTL818X_MSR_INFRA; | 1180 | reg |= RTL818X_MSR_INFRA; |
1181 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | 1181 | else |
1182 | } else { | ||
1183 | reg |= RTL818X_MSR_NO_LINK; | 1182 | reg |= RTL818X_MSR_NO_LINK; |
1184 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); | 1183 | |
1185 | } | 1184 | rtl818x_iowrite8(priv, &priv->map->MSR, reg); |
1186 | 1185 | ||
1187 | mutex_unlock(&priv->conf_mutex); | 1186 | mutex_unlock(&priv->conf_mutex); |
1188 | } | 1187 | } |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index 91891f928070..2f8a2ba744dc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -380,7 +380,7 @@ int wl1251_acx_pd_threshold(struct wl1251 *wl) | |||
380 | 380 | ||
381 | out: | 381 | out: |
382 | kfree(pd); | 382 | kfree(pd); |
383 | return 0; | 383 | return ret; |
384 | } | 384 | } |
385 | 385 | ||
386 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) | 386 | int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index 842df310d92a..a8845b8f2451 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h | |||
@@ -37,7 +37,7 @@ struct acx_header { | |||
37 | 37 | ||
38 | /* payload length (not including headers */ | 38 | /* payload length (not including headers */ |
39 | u16 len; | 39 | u16 len; |
40 | }; | 40 | } __packed; |
41 | 41 | ||
42 | struct acx_error_counter { | 42 | struct acx_error_counter { |
43 | struct acx_header header; | 43 | struct acx_header header; |
@@ -459,8 +459,8 @@ struct acx_beacon_filter_ie_table { | |||
459 | struct acx_header header; | 459 | struct acx_header header; |
460 | 460 | ||
461 | u8 num_ie; | 461 | u8 num_ie; |
462 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
463 | u8 pad[3]; | 462 | u8 pad[3]; |
463 | u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; | ||
464 | } __packed; | 464 | } __packed; |
465 | 465 | ||
466 | #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ | 466 | #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ |
@@ -471,7 +471,7 @@ struct acx_conn_monit_params { | |||
471 | 471 | ||
472 | u32 synch_fail_thold; /* number of beacons missed */ | 472 | u32 synch_fail_thold; /* number of beacons missed */ |
473 | u32 bss_lose_timeout; /* number of TU's from synch fail */ | 473 | u32 bss_lose_timeout; /* number of TU's from synch fail */ |
474 | }; | 474 | } __packed; |
475 | 475 | ||
476 | enum { | 476 | enum { |
477 | SG_ENABLE = 0, | 477 | SG_ENABLE = 0, |
@@ -1056,7 +1056,7 @@ struct acx_rate_class { | |||
1056 | u8 long_retry_limit; | 1056 | u8 long_retry_limit; |
1057 | u8 aflags; | 1057 | u8 aflags; |
1058 | u8 reserved; | 1058 | u8 reserved; |
1059 | }; | 1059 | } __packed; |
1060 | 1060 | ||
1061 | struct acx_rate_policy { | 1061 | struct acx_rate_policy { |
1062 | struct acx_header header; | 1062 | struct acx_header header; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 65e0416be5b6..5e65f47fda8a 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -302,7 +302,7 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
302 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | | 302 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | |
303 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | | 303 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | |
304 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | | 304 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | |
305 | BT_PTA_PREDICTION_EVENT_ID; | 305 | BT_PTA_PREDICTION_EVENT_ID | JOIN_EVENT_COMPLETE_ID; |
306 | 306 | ||
307 | ret = wl1251_event_unmask(wl); | 307 | ret = wl1251_event_unmask(wl); |
308 | if (ret < 0) { | 308 | if (ret < 0) { |
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c index ce3722f4c3e3..15fb68c6b542 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.c | |||
@@ -200,7 +200,7 @@ int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, | |||
200 | 200 | ||
201 | out: | 201 | out: |
202 | kfree(vbm); | 202 | kfree(vbm); |
203 | return 0; | 203 | return ret; |
204 | } | 204 | } |
205 | 205 | ||
206 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) | 206 | int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h index a9e4991369be..60d7e522486c 100644 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ b/drivers/net/wireless/wl12xx/wl1251_cmd.h | |||
@@ -111,7 +111,7 @@ struct wl1251_cmd_header { | |||
111 | struct wl1251_command { | 111 | struct wl1251_command { |
112 | struct wl1251_cmd_header header; | 112 | struct wl1251_cmd_header header; |
113 | u8 parameters[MAX_CMD_PARAMS]; | 113 | u8 parameters[MAX_CMD_PARAMS]; |
114 | }; | 114 | } __packed; |
115 | 115 | ||
116 | enum { | 116 | enum { |
117 | CMD_MAILBOX_IDLE = 0, | 117 | CMD_MAILBOX_IDLE = 0, |
@@ -164,7 +164,7 @@ struct cmd_read_write_memory { | |||
164 | of this field is the Host in WRITE command or the Wilink in READ | 164 | of this field is the Host in WRITE command or the Wilink in READ |
165 | command. */ | 165 | command. */ |
166 | u8 value[MAX_READ_SIZE]; | 166 | u8 value[MAX_READ_SIZE]; |
167 | }; | 167 | } __packed; |
168 | 168 | ||
169 | #define CMDMBOX_HEADER_LEN 4 | 169 | #define CMDMBOX_HEADER_LEN 4 |
170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 | 170 | #define CMDMBOX_INFO_ELEM_HEADER_LEN 4 |
@@ -339,7 +339,7 @@ struct wl1251_cmd_trigger_scan_to { | |||
339 | struct wl1251_cmd_header header; | 339 | struct wl1251_cmd_header header; |
340 | 340 | ||
341 | u32 timeout; | 341 | u32 timeout; |
342 | }; | 342 | } __packed; |
343 | 343 | ||
344 | /* HW encryption keys */ | 344 | /* HW encryption keys */ |
345 | #define NUM_ACCESS_CATEGORIES_COPY 4 | 345 | #define NUM_ACCESS_CATEGORIES_COPY 4 |
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c index 020d764f9c13..e093a1c5a205 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl12xx/wl1251_event.c | |||
@@ -97,6 +97,35 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | |||
97 | return 0; | 97 | return 0; |
98 | } | 98 | } |
99 | 99 | ||
100 | /* | ||
101 | * Poll the mailbox event field until any of the bits in the mask is set or a | ||
102 | * timeout occurs (WL1251_EVENT_TIMEOUT in msecs) | ||
103 | */ | ||
104 | int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms) | ||
105 | { | ||
106 | u32 events_vector, event; | ||
107 | unsigned long timeout; | ||
108 | |||
109 | timeout = jiffies + msecs_to_jiffies(timeout_ms); | ||
110 | |||
111 | do { | ||
112 | if (time_after(jiffies, timeout)) | ||
113 | return -ETIMEDOUT; | ||
114 | |||
115 | msleep(1); | ||
116 | |||
117 | /* read from both event fields */ | ||
118 | wl1251_mem_read(wl, wl->mbox_ptr[0], &events_vector, | ||
119 | sizeof(events_vector)); | ||
120 | event = events_vector & mask; | ||
121 | wl1251_mem_read(wl, wl->mbox_ptr[1], &events_vector, | ||
122 | sizeof(events_vector)); | ||
123 | event |= events_vector & mask; | ||
124 | } while (!event); | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
100 | int wl1251_event_unmask(struct wl1251 *wl) | 129 | int wl1251_event_unmask(struct wl1251 *wl) |
101 | { | 130 | { |
102 | int ret; | 131 | int ret; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h index f48a2b66bc5a..ec456474a842 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ b/drivers/net/wireless/wl12xx/wl1251_event.h | |||
@@ -117,5 +117,6 @@ struct event_mailbox { | |||
117 | int wl1251_event_unmask(struct wl1251 *wl); | 117 | int wl1251_event_unmask(struct wl1251 *wl); |
118 | void wl1251_event_mbox_config(struct wl1251 *wl); | 118 | void wl1251_event_mbox_config(struct wl1251 *wl); |
119 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); | 119 | int wl1251_event_handle(struct wl1251 *wl, u8 mbox); |
120 | int wl1251_event_wait(struct wl1251 *wl, u32 mask, int timeout_ms); | ||
120 | 121 | ||
121 | #endif | 122 | #endif |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 861a5f33761e..c81e95b45c14 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -293,14 +293,14 @@ static void wl1251_irq_work(struct work_struct *work) | |||
293 | wl1251_tx_complete(wl); | 293 | wl1251_tx_complete(wl); |
294 | } | 294 | } |
295 | 295 | ||
296 | if (intr & (WL1251_ACX_INTR_EVENT_A | | 296 | if (intr & WL1251_ACX_INTR_EVENT_A) { |
297 | WL1251_ACX_INTR_EVENT_B)) { | 297 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_A"); |
298 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", | 298 | wl1251_event_handle(wl, 0); |
299 | intr); | 299 | } |
300 | if (intr & WL1251_ACX_INTR_EVENT_A) | 300 | |
301 | wl1251_event_handle(wl, 0); | 301 | if (intr & WL1251_ACX_INTR_EVENT_B) { |
302 | else | 302 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT_B"); |
303 | wl1251_event_handle(wl, 1); | 303 | wl1251_event_handle(wl, 1); |
304 | } | 304 | } |
305 | 305 | ||
306 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) | 306 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) |
@@ -339,11 +339,9 @@ static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, | |||
339 | if (ret < 0) | 339 | if (ret < 0) |
340 | goto out; | 340 | goto out; |
341 | 341 | ||
342 | /* | 342 | ret = wl1251_event_wait(wl, JOIN_EVENT_COMPLETE_ID, 100); |
343 | * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify | 343 | if (ret < 0) |
344 | * locking we just sleep instead, for now | 344 | wl1251_warning("join timeout"); |
345 | */ | ||
346 | msleep(10); | ||
347 | 345 | ||
348 | out: | 346 | out: |
349 | return ret; | 347 | return ret; |
@@ -725,8 +723,9 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
725 | struct ieee80211_key_conf *mac80211_key, | 723 | struct ieee80211_key_conf *mac80211_key, |
726 | const u8 *addr) | 724 | const u8 *addr) |
727 | { | 725 | { |
728 | switch (mac80211_key->alg) { | 726 | switch (mac80211_key->cipher) { |
729 | case ALG_WEP: | 727 | case WLAN_CIPHER_SUITE_WEP40: |
728 | case WLAN_CIPHER_SUITE_WEP104: | ||
730 | if (is_broadcast_ether_addr(addr)) | 729 | if (is_broadcast_ether_addr(addr)) |
731 | key->key_type = KEY_WEP_DEFAULT; | 730 | key->key_type = KEY_WEP_DEFAULT; |
732 | else | 731 | else |
@@ -734,7 +733,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
734 | 733 | ||
735 | mac80211_key->hw_key_idx = mac80211_key->keyidx; | 734 | mac80211_key->hw_key_idx = mac80211_key->keyidx; |
736 | break; | 735 | break; |
737 | case ALG_TKIP: | 736 | case WLAN_CIPHER_SUITE_TKIP: |
738 | if (is_broadcast_ether_addr(addr)) | 737 | if (is_broadcast_ether_addr(addr)) |
739 | key->key_type = KEY_TKIP_MIC_GROUP; | 738 | key->key_type = KEY_TKIP_MIC_GROUP; |
740 | else | 739 | else |
@@ -742,7 +741,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
742 | 741 | ||
743 | mac80211_key->hw_key_idx = mac80211_key->keyidx; | 742 | mac80211_key->hw_key_idx = mac80211_key->keyidx; |
744 | break; | 743 | break; |
745 | case ALG_CCMP: | 744 | case WLAN_CIPHER_SUITE_CCMP: |
746 | if (is_broadcast_ether_addr(addr)) | 745 | if (is_broadcast_ether_addr(addr)) |
747 | key->key_type = KEY_AES_GROUP; | 746 | key->key_type = KEY_AES_GROUP; |
748 | else | 747 | else |
@@ -750,7 +749,7 @@ static int wl1251_set_key_type(struct wl1251 *wl, | |||
750 | mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 749 | mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
751 | break; | 750 | break; |
752 | default: | 751 | default: |
753 | wl1251_error("Unknown key algo 0x%x", mac80211_key->alg); | 752 | wl1251_error("Unknown key cipher 0x%x", mac80211_key->cipher); |
754 | return -EOPNOTSUPP; | 753 | return -EOPNOTSUPP; |
755 | } | 754 | } |
756 | 755 | ||
@@ -783,7 +782,7 @@ static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
783 | wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | 782 | wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); |
784 | wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | 783 | wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); |
785 | wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 784 | wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
786 | key->alg, key->keyidx, key->keylen, key->flags); | 785 | key->cipher, key->keyidx, key->keylen, key->flags); |
787 | wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); | 786 | wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); |
788 | 787 | ||
789 | if (is_zero_ether_addr(addr)) { | 788 | if (is_zero_ether_addr(addr)) { |
diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c index a38ec199187a..6634b3e27cfc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ b/drivers/net/wireless/wl12xx/wl1251_tx.c | |||
@@ -189,7 +189,7 @@ static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, | |||
189 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; | 189 | tx_hdr = (struct tx_double_buffer_desc *) skb->data; |
190 | 190 | ||
191 | if (control->control.hw_key && | 191 | if (control->control.hw_key && |
192 | control->control.hw_key->alg == ALG_TKIP) { | 192 | control->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
193 | int hdrlen; | 193 | int hdrlen; |
194 | __le16 fc; | 194 | __le16 fc; |
195 | u16 length; | 195 | u16 length; |
@@ -399,7 +399,7 @@ static void wl1251_tx_packet_cb(struct wl1251 *wl, | |||
399 | */ | 399 | */ |
400 | frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); | 400 | frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); |
401 | if (info->control.hw_key && | 401 | if (info->control.hw_key && |
402 | info->control.hw_key->alg == ALG_TKIP) { | 402 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
403 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 403 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
404 | memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); | 404 | memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); |
405 | skb_pull(skb, WL1251_TKIP_IV_SPACE); | 405 | skb_pull(skb, WL1251_TKIP_IV_SPACE); |
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c index bb245f05af49..f03ad088db8b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ b/drivers/net/wireless/wl12xx/wl1271_acx.c | |||
@@ -269,7 +269,7 @@ int wl1271_acx_pd_threshold(struct wl1271 *wl) | |||
269 | 269 | ||
270 | out: | 270 | out: |
271 | kfree(pd); | 271 | kfree(pd); |
272 | return 0; | 272 | return ret; |
273 | } | 273 | } |
274 | 274 | ||
275 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) | 275 | int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 9d68f0012f05..30194c0f36a9 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -1439,7 +1439,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1439 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); | 1439 | wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); |
1440 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); | 1440 | wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); |
1441 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", | 1441 | wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", |
1442 | key_conf->alg, key_conf->keyidx, | 1442 | key_conf->cipher, key_conf->keyidx, |
1443 | key_conf->keylen, key_conf->flags); | 1443 | key_conf->keylen, key_conf->flags); |
1444 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); | 1444 | wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); |
1445 | 1445 | ||
@@ -1455,20 +1455,21 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1455 | if (ret < 0) | 1455 | if (ret < 0) |
1456 | goto out_unlock; | 1456 | goto out_unlock; |
1457 | 1457 | ||
1458 | switch (key_conf->alg) { | 1458 | switch (key_conf->cipher) { |
1459 | case ALG_WEP: | 1459 | case WLAN_CIPHER_SUITE_WEP40: |
1460 | case WLAN_CIPHER_SUITE_WEP104: | ||
1460 | key_type = KEY_WEP; | 1461 | key_type = KEY_WEP; |
1461 | 1462 | ||
1462 | key_conf->hw_key_idx = key_conf->keyidx; | 1463 | key_conf->hw_key_idx = key_conf->keyidx; |
1463 | break; | 1464 | break; |
1464 | case ALG_TKIP: | 1465 | case WLAN_CIPHER_SUITE_TKIP: |
1465 | key_type = KEY_TKIP; | 1466 | key_type = KEY_TKIP; |
1466 | 1467 | ||
1467 | key_conf->hw_key_idx = key_conf->keyidx; | 1468 | key_conf->hw_key_idx = key_conf->keyidx; |
1468 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); | 1469 | tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq); |
1469 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1470 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1470 | break; | 1471 | break; |
1471 | case ALG_CCMP: | 1472 | case WLAN_CIPHER_SUITE_CCMP: |
1472 | key_type = KEY_AES; | 1473 | key_type = KEY_AES; |
1473 | 1474 | ||
1474 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1475 | key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
@@ -1476,7 +1477,7 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
1476 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); | 1477 | tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq); |
1477 | break; | 1478 | break; |
1478 | default: | 1479 | default: |
1479 | wl1271_error("Unknown key algo 0x%x", key_conf->alg); | 1480 | wl1271_error("Unknown key algo 0x%x", key_conf->cipher); |
1480 | 1481 | ||
1481 | ret = -EOPNOTSUPP; | 1482 | ret = -EOPNOTSUPP; |
1482 | goto out_sleep; | 1483 | goto out_sleep; |
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index c592cc2e9fe8..dc0b46c93c4b 100644 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ b/drivers/net/wireless/wl12xx/wl1271_tx.c | |||
@@ -193,7 +193,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) | |||
193 | info = IEEE80211_SKB_CB(skb); | 193 | info = IEEE80211_SKB_CB(skb); |
194 | 194 | ||
195 | if (info->control.hw_key && | 195 | if (info->control.hw_key && |
196 | info->control.hw_key->alg == ALG_TKIP) | 196 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) |
197 | extra = WL1271_TKIP_IV_SPACE; | 197 | extra = WL1271_TKIP_IV_SPACE; |
198 | 198 | ||
199 | if (info->control.hw_key) { | 199 | if (info->control.hw_key) { |
@@ -347,7 +347,7 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
347 | 347 | ||
348 | /* remove TKIP header space if present */ | 348 | /* remove TKIP header space if present */ |
349 | if (info->control.hw_key && | 349 | if (info->control.hw_key && |
350 | info->control.hw_key->alg == ALG_TKIP) { | 350 | info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) { |
351 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 351 | int hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
352 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); | 352 | memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data, hdrlen); |
353 | skb_pull(skb, WL1271_TKIP_IV_SPACE); | 353 | skb_pull(skb, WL1271_TKIP_IV_SPACE); |
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c index b2af3c549bb3..87a95bcfee57 100644 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ b/drivers/net/wireless/zd1211rw/zd_chip.c | |||
@@ -973,6 +973,7 @@ static void dump_fw_registers(struct zd_chip *chip) | |||
973 | 973 | ||
974 | static int print_fw_version(struct zd_chip *chip) | 974 | static int print_fw_version(struct zd_chip *chip) |
975 | { | 975 | { |
976 | struct wiphy *wiphy = zd_chip_to_mac(chip)->hw->wiphy; | ||
976 | int r; | 977 | int r; |
977 | u16 version; | 978 | u16 version; |
978 | 979 | ||
@@ -982,6 +983,10 @@ static int print_fw_version(struct zd_chip *chip) | |||
982 | return r; | 983 | return r; |
983 | 984 | ||
984 | dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); | 985 | dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); |
986 | |||
987 | snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), | ||
988 | "%04hx", version); | ||
989 | |||
985 | return 0; | 990 | return 0; |
986 | } | 991 | } |
987 | 992 | ||