aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-05-25 03:38:24 -0400
committerDavid S. Miller <davem@davemloft.net>2009-05-25 03:38:24 -0400
commit45ea4ea2af358fe316c918381c7868f9418cad09 (patch)
tree4deb3d87b26e884b06929fe33740d45e78fbdcab
parentdddc045e2fdd4eb8d7dfac29bff191d639fff8c3 (diff)
parenta2e2322d83df82a57ba456cfa604c8b8f7b04670 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
-rw-r--r--Documentation/DocBook/mac80211.tmpl1
-rw-r--r--drivers/net/wireless/Kconfig1
-rw-r--r--drivers/net/wireless/Makefile2
-rw-r--r--drivers/net/wireless/ath/ar9170/main.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c54
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c98
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c119
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c194
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c12
-rw-r--r--drivers/net/wireless/ath/regd.c10
-rw-r--r--drivers/net/wireless/b43/main.c26
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h4
-rw-r--r--drivers/net/wireless/b43legacy/main.c99
-rw-r--r--drivers/net/wireless/b43legacy/pio.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945-led.c70
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c151
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c88
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000-hw.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c164
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c65
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c355
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h14
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c392
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-csr.h22
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c97
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h32
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.c153
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h253
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c63
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c87
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Kconfig23
-rw-r--r--drivers/net/wireless/iwmc3200wifi/Makefile5
-rw-r--r--drivers/net/wireless/iwmc3200wifi/bus.h57
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c409
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.h31
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c920
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h419
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debug.h124
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c453
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.c187
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.h114
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c388
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.h100
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.c464
-rw-r--r--drivers/net/wireless/iwmc3200wifi/hal.h236
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h350
-rw-r--r--drivers/net/wireless/iwmc3200wifi/lmac.h457
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c680
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c172
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rfkill.c88
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c1431
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.h60
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.c516
-rw-r--r--drivers/net/wireless/iwmc3200wifi/sdio.h67
-rw-r--r--drivers/net/wireless/iwmc3200wifi/tx.c492
-rw-r--r--drivers/net/wireless/iwmc3200wifi/umac.h744
-rw-r--r--drivers/net/wireless/iwmc3200wifi/wext.c723
-rw-r--r--drivers/net/wireless/libertas/dev.h2
-rw-r--r--drivers/net/wireless/libertas/host.h2
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c149
-rw-r--r--drivers/net/wireless/libertas/if_sdio.h8
-rw-r--r--drivers/net/wireless/libertas/if_spi.c7
-rw-r--r--drivers/net/wireless/libertas/main.c20
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c35
-rw-r--r--drivers/net/wireless/p54/p54spi.c64
-rw-r--r--drivers/net/wireless/rndis_wlan.c216
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c30
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c30
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c17
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c25
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00crypto.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c9
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c28
-rw-r--r--drivers/net/wireless/strip.c2
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.c6
-rw-r--r--drivers/net/wireless/zd1211rw/zd_mac.h2
-rw-r--r--drivers/staging/agnx/pci.c15
-rw-r--r--include/linux/ieee80211.h9
-rw-r--r--include/net/cfg80211.h78
-rw-r--r--include/net/mac80211.h29
-rw-r--r--net/mac80211/debugfs.c16
-rw-r--r--net/mac80211/ibss.c33
-rw-r--r--net/mac80211/ieee80211_i.h43
-rw-r--r--net/mac80211/key.c6
-rw-r--r--net/mac80211/main.c16
-rw-r--r--net/mac80211/mesh.c40
-rw-r--r--net/mac80211/mesh.h16
-rw-r--r--net/mac80211/mesh_hwmp.c8
-rw-r--r--net/mac80211/mesh_plink.c21
-rw-r--r--net/mac80211/mlme.c227
-rw-r--r--net/mac80211/pm.c80
-rw-r--r--net/mac80211/rx.c94
-rw-r--r--net/mac80211/scan.c18
-rw-r--r--net/mac80211/spectmgmt.c101
-rw-r--r--net/mac80211/sta_info.c6
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/mac80211/tx.c2
-rw-r--r--net/mac80211/util.c116
-rw-r--r--net/mac80211/wext.c5
-rw-r--r--net/mac80211/wme.c30
-rw-r--r--net/wireless/Kconfig8
-rw-r--r--net/wireless/Makefile1
-rw-r--r--net/wireless/core.c7
-rw-r--r--net/wireless/core.h14
-rw-r--r--net/wireless/debugfs.c131
-rw-r--r--net/wireless/debugfs.h14
-rw-r--r--net/wireless/nl80211.c66
-rw-r--r--net/wireless/reg.c216
-rw-r--r--net/wireless/util.c320
-rw-r--r--net/wireless/wext-compat.c7
-rw-r--r--net/wireless/wext.c32
124 files changed, 13213 insertions, 1745 deletions
diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl
index fbeaffc1dcc3..e36986663570 100644
--- a/Documentation/DocBook/mac80211.tmpl
+++ b/Documentation/DocBook/mac80211.tmpl
@@ -145,7 +145,6 @@ usage should require reading the full document.
145 interface in STA mode at first! 145 interface in STA mode at first!
146 </para> 146 </para>
147!Finclude/net/mac80211.h ieee80211_if_init_conf 147!Finclude/net/mac80211.h ieee80211_if_init_conf
148!Finclude/net/mac80211.h ieee80211_if_conf
149 </chapter> 148 </chapter>
150 149
151 <chapter id="rx-tx"> 150 <chapter id="rx-tx">
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index 91be3e7bf133..a67d29290ba0 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -501,5 +501,6 @@ source "drivers/net/wireless/zd1211rw/Kconfig"
501source "drivers/net/wireless/rt2x00/Kconfig" 501source "drivers/net/wireless/rt2x00/Kconfig"
502source "drivers/net/wireless/orinoco/Kconfig" 502source "drivers/net/wireless/orinoco/Kconfig"
503source "drivers/net/wireless/wl12xx/Kconfig" 503source "drivers/net/wireless/wl12xx/Kconfig"
504source "drivers/net/wireless/iwmc3200wifi/Kconfig"
504 505
505endmenu 506endmenu
diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile
index f2b1861e6bcb..7a4647e78fd3 100644
--- a/drivers/net/wireless/Makefile
+++ b/drivers/net/wireless/Makefile
@@ -60,3 +60,5 @@ obj-$(CONFIG_ATH_COMMON) += ath/
60obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o 60obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o
61 61
62obj-$(CONFIG_WL12XX) += wl12xx/ 62obj-$(CONFIG_WL12XX) += wl12xx/
63
64obj-$(CONFIG_IWM) += iwmc3200wifi/
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c
index 4ef1d2fc859c..99df9ddae9cb 100644
--- a/drivers/net/wireless/ath/ar9170/main.c
+++ b/drivers/net/wireless/ath/ar9170/main.c
@@ -1555,7 +1555,7 @@ static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1555 1555
1556 switch (key->alg) { 1556 switch (key->alg) {
1557 case ALG_WEP: 1557 case ALG_WEP:
1558 if (key->keylen == LEN_WEP40) 1558 if (key->keylen == WLAN_KEY_LEN_WEP40)
1559 ktype = AR9170_ENC_ALG_WEP64; 1559 ktype = AR9170_ENC_ALG_WEP64;
1560 else 1560 else
1561 ktype = AR9170_ENC_ALG_WEP128; 1561 ktype = AR9170_ENC_ALG_WEP128;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index dbfe9f45050e..fb5193764afa 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -242,8 +242,8 @@ static int ath5k_get_tx_stats(struct ieee80211_hw *hw,
242static u64 ath5k_get_tsf(struct ieee80211_hw *hw); 242static u64 ath5k_get_tsf(struct ieee80211_hw *hw);
243static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); 243static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf);
244static void ath5k_reset_tsf(struct ieee80211_hw *hw); 244static void ath5k_reset_tsf(struct ieee80211_hw *hw);
245static int ath5k_beacon_update(struct ath5k_softc *sc, 245static int ath5k_beacon_update(struct ieee80211_hw *hw,
246 struct sk_buff *skb); 246 struct ieee80211_vif *vif);
247static void ath5k_bss_info_changed(struct ieee80211_hw *hw, 247static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
248 struct ieee80211_vif *vif, 248 struct ieee80211_vif *vif,
249 struct ieee80211_bss_conf *bss_conf, 249 struct ieee80211_bss_conf *bss_conf,
@@ -2127,8 +2127,10 @@ ath5k_beacon_send(struct ath5k_softc *sc)
2127 /* NB: hw still stops DMA, so proceed */ 2127 /* NB: hw still stops DMA, so proceed */
2128 } 2128 }
2129 2129
2130 /* Note: Beacon buffer is updated on beacon_update when mac80211 2130 /* refresh the beacon for AP mode */
2131 * calls config_interface */ 2131 if (sc->opmode == NL80211_IFTYPE_AP)
2132 ath5k_beacon_update(sc->hw, sc->vif);
2133
2132 ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); 2134 ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr);
2133 ath5k_hw_start_tx_dma(ah, sc->bhalq); 2135 ath5k_hw_start_tx_dma(ah, sc->bhalq);
2134 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", 2136 ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n",
@@ -3047,28 +3049,55 @@ ath5k_reset_tsf(struct ieee80211_hw *hw)
3047 ath5k_hw_reset_tsf(sc->ah); 3049 ath5k_hw_reset_tsf(sc->ah);
3048} 3050}
3049 3051
3052/*
3053 * Updates the beacon that is sent by ath5k_beacon_send. For adhoc,
3054 * this is called only once at config_bss time, for AP we do it every
3055 * SWBA interrupt so that the TIM will reflect buffered frames.
3056 *
3057 * Called with the beacon lock.
3058 */
3050static int 3059static int
3051ath5k_beacon_update(struct ath5k_softc *sc, struct sk_buff *skb) 3060ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
3052{ 3061{
3053 unsigned long flags;
3054 int ret; 3062 int ret;
3063 struct ath5k_softc *sc = hw->priv;
3064 struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
3065
3066 if (!skb) {
3067 ret = -ENOMEM;
3068 goto out;
3069 }
3055 3070
3056 ath5k_debug_dump_skb(sc, skb, "BC ", 1); 3071 ath5k_debug_dump_skb(sc, skb, "BC ", 1);
3057 3072
3058 spin_lock_irqsave(&sc->block, flags);
3059 ath5k_txbuf_free(sc, sc->bbuf); 3073 ath5k_txbuf_free(sc, sc->bbuf);
3060 sc->bbuf->skb = skb; 3074 sc->bbuf->skb = skb;
3061 ret = ath5k_beacon_setup(sc, sc->bbuf); 3075 ret = ath5k_beacon_setup(sc, sc->bbuf);
3062 if (ret) 3076 if (ret)
3063 sc->bbuf->skb = NULL; 3077 sc->bbuf->skb = NULL;
3078out:
3079 return ret;
3080}
3081
3082/*
3083 * Update the beacon and reconfigure the beacon queues.
3084 */
3085static void
3086ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
3087{
3088 int ret;
3089 unsigned long flags;
3090 struct ath5k_softc *sc = hw->priv;
3091
3092 spin_lock_irqsave(&sc->block, flags);
3093 ret = ath5k_beacon_update(hw, vif);
3064 spin_unlock_irqrestore(&sc->block, flags); 3094 spin_unlock_irqrestore(&sc->block, flags);
3065 if (!ret) { 3095 if (ret == 0) {
3066 ath5k_beacon_config(sc); 3096 ath5k_beacon_config(sc);
3067 mmiowb(); 3097 mmiowb();
3068 } 3098 }
3069
3070 return ret;
3071} 3099}
3100
3072static void 3101static void
3073set_beacon_filter(struct ieee80211_hw *hw, bool enable) 3102set_beacon_filter(struct ieee80211_hw *hw, bool enable)
3074{ 3103{
@@ -3118,10 +3147,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
3118 (vif->type == NL80211_IFTYPE_ADHOC || 3147 (vif->type == NL80211_IFTYPE_ADHOC ||
3119 vif->type == NL80211_IFTYPE_MESH_POINT || 3148 vif->type == NL80211_IFTYPE_MESH_POINT ||
3120 vif->type == NL80211_IFTYPE_AP)) { 3149 vif->type == NL80211_IFTYPE_AP)) {
3121 struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); 3150 ath5k_beacon_reconfig(hw, vif);
3122
3123 if (beacon)
3124 ath5k_beacon_update(sc, beacon);
3125 } 3151 }
3126 3152
3127 unlock: 3153 unlock:
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 579aa0a96ab8..ec35503f6a40 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -1038,9 +1038,9 @@ int ath5k_keycache_type(const struct ieee80211_key_conf *key)
1038 case ALG_CCMP: 1038 case ALG_CCMP:
1039 return AR5K_KEYTABLE_TYPE_CCM; 1039 return AR5K_KEYTABLE_TYPE_CCM;
1040 case ALG_WEP: 1040 case ALG_WEP:
1041 if (key->keylen == LEN_WEP40) 1041 if (key->keylen == WLAN_KEY_LEN_WEP40)
1042 return AR5K_KEYTABLE_TYPE_40; 1042 return AR5K_KEYTABLE_TYPE_40;
1043 else if (key->keylen == LEN_WEP104) 1043 else if (key->keylen == WLAN_KEY_LEN_WEP104)
1044 return AR5K_KEYTABLE_TYPE_104; 1044 return AR5K_KEYTABLE_TYPE_104;
1045 return -EINVAL; 1045 return -EINVAL;
1046 default: 1046 default:
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index d0d1c350025a..a876ca8d69ef 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -1897,6 +1897,9 @@ ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR,
1897 s16 min_pwrL, min_pwrR; 1897 s16 min_pwrL, min_pwrR;
1898 s16 pwr_i; 1898 s16 pwr_i;
1899 1899
1900 if (WARN_ON(stepL[0] == stepL[1] || stepR[0] == stepR[1]))
1901 return 0;
1902
1900 if (pwrL[0] == pwrL[1]) 1903 if (pwrL[0] == pwrL[1])
1901 min_pwrL = pwrL[0]; 1904 min_pwrL = pwrL[0];
1902 else { 1905 else {
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 10ffc9442859..796a3adffea0 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -515,6 +515,10 @@ struct ath_rfkill {
515#define SC_OP_LED_ON BIT(13) 515#define SC_OP_LED_ON BIT(13)
516#define SC_OP_SCANNING BIT(14) 516#define SC_OP_SCANNING BIT(14)
517#define SC_OP_TSF_RESET BIT(15) 517#define SC_OP_TSF_RESET BIT(15)
518#define SC_OP_WAIT_FOR_CAB BIT(16)
519#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
520#define SC_OP_WAIT_FOR_TX_ACK BIT(18)
521#define SC_OP_BEACON_SYNC BIT(19)
518 522
519struct ath_bus_ops { 523struct ath_bus_ops {
520 void (*read_cachesize)(struct ath_softc *sc, int *csz); 524 void (*read_cachesize)(struct ath_softc *sc, int *csz);
@@ -599,6 +603,7 @@ struct ath_softc {
599 struct ath9k_debug debug; 603 struct ath9k_debug debug;
600#endif 604#endif
601 struct ath_bus_ops *bus_ops; 605 struct ath_bus_ops *bus_ops;
606 struct ath_beacon_config cur_beacon_conf;
602}; 607};
603 608
604struct ath_wiphy { 609struct ath_wiphy {
@@ -676,7 +681,9 @@ static inline void ath9k_ps_restore(struct ath_softc *sc)
676{ 681{
677 if (atomic_dec_and_test(&sc->ps_usecount)) 682 if (atomic_dec_and_test(&sc->ps_usecount))
678 if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && 683 if ((sc->hw->conf.flags & IEEE80211_CONF_PS) &&
679 !(sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) 684 !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
685 SC_OP_WAIT_FOR_PSPOLL_DATA |
686 SC_OP_WAIT_FOR_TX_ACK)))
680 ath9k_hw_setpower(sc->sc_ah, 687 ath9k_hw_setpower(sc->sc_ah,
681 sc->sc_ah->restore_mode); 688 sc->sc_ah->restore_mode);
682} 689}
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 3a7154beeae1..a21b21339fbc 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -507,8 +507,7 @@ void ath_beacon_tasklet(unsigned long data)
507 * slot. Slots that are not occupied will generate nothing. 507 * slot. Slots that are not occupied will generate nothing.
508 */ 508 */
509static void ath_beacon_config_ap(struct ath_softc *sc, 509static void ath_beacon_config_ap(struct ath_softc *sc,
510 struct ath_beacon_config *conf, 510 struct ath_beacon_config *conf)
511 struct ath_vif *avp)
512{ 511{
513 u32 nexttbtt, intval; 512 u32 nexttbtt, intval;
514 513
@@ -553,14 +552,14 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
553 * we've associated with. 552 * we've associated with.
554 */ 553 */
555static void ath_beacon_config_sta(struct ath_softc *sc, 554static void ath_beacon_config_sta(struct ath_softc *sc,
556 struct ath_beacon_config *conf, 555 struct ath_beacon_config *conf)
557 struct ath_vif *avp)
558{ 556{
559 struct ath9k_beacon_state bs; 557 struct ath9k_beacon_state bs;
560 int dtimperiod, dtimcount, sleepduration; 558 int dtimperiod, dtimcount, sleepduration;
561 int cfpperiod, cfpcount; 559 int cfpperiod, cfpcount;
562 u32 nexttbtt = 0, intval, tsftu; 560 u32 nexttbtt = 0, intval, tsftu;
563 u64 tsf; 561 u64 tsf;
562 int num_beacons, offset, dtim_dec_count, cfp_dec_count;
564 563
565 memset(&bs, 0, sizeof(bs)); 564 memset(&bs, 0, sizeof(bs));
566 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; 565 intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
@@ -588,14 +587,27 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
588 */ 587 */
589 tsf = ath9k_hw_gettsf64(sc->sc_ah); 588 tsf = ath9k_hw_gettsf64(sc->sc_ah);
590 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; 589 tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
591 do { 590
591 num_beacons = tsftu / intval + 1;
592 offset = tsftu % intval;
593 nexttbtt = tsftu - offset;
594 if (offset)
592 nexttbtt += intval; 595 nexttbtt += intval;
593 if (--dtimcount < 0) { 596
594 dtimcount = dtimperiod - 1; 597 /* DTIM Beacon every dtimperiod Beacon */
595 if (--cfpcount < 0) 598 dtim_dec_count = num_beacons % dtimperiod;
596 cfpcount = cfpperiod - 1; 599 /* CFP every cfpperiod DTIM Beacon */
597 } 600 cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
598 } while (nexttbtt < tsftu); 601 if (dtim_dec_count)
602 cfp_dec_count++;
603
604 dtimcount -= dtim_dec_count;
605 if (dtimcount < 0)
606 dtimcount += dtimperiod;
607
608 cfpcount -= cfp_dec_count;
609 if (cfpcount < 0)
610 cfpcount += cfpperiod;
599 611
600 bs.bs_intval = intval; 612 bs.bs_intval = intval;
601 bs.bs_nexttbtt = nexttbtt; 613 bs.bs_nexttbtt = nexttbtt;
@@ -654,7 +666,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
654 666
655static void ath_beacon_config_adhoc(struct ath_softc *sc, 667static void ath_beacon_config_adhoc(struct ath_softc *sc,
656 struct ath_beacon_config *conf, 668 struct ath_beacon_config *conf,
657 struct ath_vif *avp,
658 struct ieee80211_vif *vif) 669 struct ieee80211_vif *vif)
659{ 670{
660 u64 tsf; 671 u64 tsf;
@@ -698,43 +709,50 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
698 sc->beacon.bmisscnt = 0; 709 sc->beacon.bmisscnt = 0;
699 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); 710 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
700 711
701 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) 712 /* FIXME: Handle properly when vif is NULL */
713 if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
702 ath_beacon_start_adhoc(sc, vif); 714 ath_beacon_start_adhoc(sc, vif);
703} 715}
704 716
705void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) 717void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
706{ 718{
707 struct ath_beacon_config conf; 719 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
720 enum nl80211_iftype iftype;
708 721
709 /* Setup the beacon configuration parameters */ 722 /* Setup the beacon configuration parameters */
710 723
711 memset(&conf, 0, sizeof(struct ath_beacon_config));
712 conf.beacon_interval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
713 conf.listen_interval = 1;
714 conf.dtim_period = conf.beacon_interval;
715 conf.dtim_count = 1;
716 conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
717
718 if (vif) { 724 if (vif) {
719 struct ath_vif *avp = (struct ath_vif *)vif->drv_priv; 725 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
720 726
721 switch(avp->av_opmode) { 727 iftype = vif->type;
722 case NL80211_IFTYPE_AP: 728
723 ath_beacon_config_ap(sc, &conf, avp); 729 cur_conf->beacon_interval = bss_conf->beacon_int;
724 break; 730 cur_conf->dtim_period = bss_conf->dtim_period;
725 case NL80211_IFTYPE_ADHOC: 731 cur_conf->listen_interval = 1;
726 case NL80211_IFTYPE_MESH_POINT: 732 cur_conf->dtim_count = 1;
727 ath_beacon_config_adhoc(sc, &conf, avp, vif); 733 cur_conf->bmiss_timeout =
728 break; 734 ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
729 case NL80211_IFTYPE_STATION: 735 } else {
730 ath_beacon_config_sta(sc, &conf, avp); 736 iftype = sc->sc_ah->opmode;
731 break; 737 }
732 default: 738
733 DPRINTF(sc, ATH_DBG_CONFIG,
734 "Unsupported beaconing mode\n");
735 return;
736 }
737 739
738 sc->sc_flags |= SC_OP_BEACONS; 740 switch (iftype) {
741 case NL80211_IFTYPE_AP:
742 ath_beacon_config_ap(sc, cur_conf);
743 break;
744 case NL80211_IFTYPE_ADHOC:
745 case NL80211_IFTYPE_MESH_POINT:
746 ath_beacon_config_adhoc(sc, cur_conf, vif);
747 break;
748 case NL80211_IFTYPE_STATION:
749 ath_beacon_config_sta(sc, cur_conf);
750 break;
751 default:
752 DPRINTF(sc, ATH_DBG_CONFIG,
753 "Unsupported beaconing mode\n");
754 return;
739 } 755 }
756
757 sc->sc_flags |= SC_OP_BEACONS;
740} 758}
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 23298b90b52b..db845cf960c9 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -29,6 +29,7 @@ enum ATH_DEBUG {
29 ATH_DBG_BEACON = 0x00000100, 29 ATH_DBG_BEACON = 0x00000100,
30 ATH_DBG_CONFIG = 0x00000200, 30 ATH_DBG_CONFIG = 0x00000200,
31 ATH_DBG_FATAL = 0x00000400, 31 ATH_DBG_FATAL = 0x00000400,
32 ATH_DBG_PS = 0x00000800,
32 ATH_DBG_ANY = 0xffffffff 33 ATH_DBG_ANY = 0xffffffff
33}; 34};
34 35
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 4acfab514916..1579c9407ed5 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2472,14 +2472,14 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
2472 } 2472 }
2473 break; 2473 break;
2474 case ATH9K_CIPHER_WEP: 2474 case ATH9K_CIPHER_WEP:
2475 if (k->kv_len < LEN_WEP40) { 2475 if (k->kv_len < WLAN_KEY_LEN_WEP40) {
2476 DPRINTF(ah->ah_sc, ATH_DBG_ANY, 2476 DPRINTF(ah->ah_sc, ATH_DBG_ANY,
2477 "WEP key length %u too small\n", k->kv_len); 2477 "WEP key length %u too small\n", k->kv_len);
2478 return false; 2478 return false;
2479 } 2479 }
2480 if (k->kv_len <= LEN_WEP40) 2480 if (k->kv_len <= WLAN_KEY_LEN_WEP40)
2481 keyType = AR_KEYTABLE_TYPE_40; 2481 keyType = AR_KEYTABLE_TYPE_40;
2482 else if (k->kv_len <= LEN_WEP104) 2482 else if (k->kv_len <= WLAN_KEY_LEN_WEP104)
2483 keyType = AR_KEYTABLE_TYPE_104; 2483 keyType = AR_KEYTABLE_TYPE_104;
2484 else 2484 else
2485 keyType = AR_KEYTABLE_TYPE_128; 2485 keyType = AR_KEYTABLE_TYPE_128;
@@ -2498,7 +2498,7 @@ bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry,
2498 key2 = get_unaligned_le32(k->kv_val + 6); 2498 key2 = get_unaligned_le32(k->kv_val + 6);
2499 key3 = get_unaligned_le16(k->kv_val + 10); 2499 key3 = get_unaligned_le16(k->kv_val + 10);
2500 key4 = get_unaligned_le32(k->kv_val + 12); 2500 key4 = get_unaligned_le32(k->kv_val + 12);
2501 if (k->kv_len <= LEN_WEP104) 2501 if (k->kv_len <= WLAN_KEY_LEN_WEP104)
2502 key4 &= 0xff; 2502 key4 &= 0xff;
2503 2503
2504 /* 2504 /*
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index bbbfdcde2727..61da08a1648c 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -35,14 +35,14 @@ MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption");
35#define CHAN2G(_freq, _idx) { \ 35#define CHAN2G(_freq, _idx) { \
36 .center_freq = (_freq), \ 36 .center_freq = (_freq), \
37 .hw_value = (_idx), \ 37 .hw_value = (_idx), \
38 .max_power = 30, \ 38 .max_power = 20, \
39} 39}
40 40
41#define CHAN5G(_freq, _idx) { \ 41#define CHAN5G(_freq, _idx) { \
42 .band = IEEE80211_BAND_5GHZ, \ 42 .band = IEEE80211_BAND_5GHZ, \
43 .center_freq = (_freq), \ 43 .center_freq = (_freq), \
44 .hw_value = (_idx), \ 44 .hw_value = (_idx), \
45 .max_power = 30, \ 45 .max_power = 20, \
46} 46}
47 47
48/* Some 2 GHz radios are actually tunable on 2312-2732 48/* Some 2 GHz radios are actually tunable on 2312-2732
@@ -280,7 +280,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
280 if (r) { 280 if (r) {
281 DPRINTF(sc, ATH_DBG_FATAL, 281 DPRINTF(sc, ATH_DBG_FATAL,
282 "Unable to reset channel (%u Mhz) " 282 "Unable to reset channel (%u Mhz) "
283 "reset status %u\n", 283 "reset status %d\n",
284 channel->center_freq, r); 284 channel->center_freq, r);
285 spin_unlock_bh(&sc->sc_resetlock); 285 spin_unlock_bh(&sc->sc_resetlock);
286 return r; 286 return r;
@@ -329,6 +329,12 @@ static void ath_ani_calibrate(unsigned long data)
329 if (sc->sc_flags & SC_OP_SCANNING) 329 if (sc->sc_flags & SC_OP_SCANNING)
330 goto set_timer; 330 goto set_timer;
331 331
332 /* Only calibrate if awake */
333 if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
334 goto set_timer;
335
336 ath9k_ps_wakeup(sc);
337
332 /* Long calibration runs independently of short calibration. */ 338 /* Long calibration runs independently of short calibration. */
333 if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { 339 if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
334 longcal = true; 340 longcal = true;
@@ -380,6 +386,8 @@ static void ath_ani_calibrate(unsigned long data)
380 } 386 }
381 } 387 }
382 388
389 ath9k_ps_restore(sc);
390
383set_timer: 391set_timer:
384 /* 392 /*
385 * Set timer interval based on previous results. 393 * Set timer interval based on previous results.
@@ -455,8 +463,11 @@ static void ath9k_tasklet(unsigned long data)
455 struct ath_softc *sc = (struct ath_softc *)data; 463 struct ath_softc *sc = (struct ath_softc *)data;
456 u32 status = sc->intrstatus; 464 u32 status = sc->intrstatus;
457 465
466 ath9k_ps_wakeup(sc);
467
458 if (status & ATH9K_INT_FATAL) { 468 if (status & ATH9K_INT_FATAL) {
459 ath_reset(sc, false); 469 ath_reset(sc, false);
470 ath9k_ps_restore(sc);
460 return; 471 return;
461 } 472 }
462 473
@@ -469,8 +480,19 @@ static void ath9k_tasklet(unsigned long data)
469 if (status & ATH9K_INT_TX) 480 if (status & ATH9K_INT_TX)
470 ath_tx_tasklet(sc); 481 ath_tx_tasklet(sc);
471 482
483 if ((status & ATH9K_INT_TSFOOR) &&
484 (sc->hw->conf.flags & IEEE80211_CONF_PS)) {
485 /*
486 * TSF sync does not look correct; remain awake to sync with
487 * the next Beacon.
488 */
489 DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n");
490 sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC;
491 }
492
472 /* re-enable hardware interrupt */ 493 /* re-enable hardware interrupt */
473 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); 494 ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
495 ath9k_ps_restore(sc);
474} 496}
475 497
476irqreturn_t ath_isr(int irq, void *dev) 498irqreturn_t ath_isr(int irq, void *dev)
@@ -498,14 +520,11 @@ irqreturn_t ath_isr(int irq, void *dev)
498 if (sc->sc_flags & SC_OP_INVALID) 520 if (sc->sc_flags & SC_OP_INVALID)
499 return IRQ_NONE; 521 return IRQ_NONE;
500 522
501 ath9k_ps_wakeup(sc);
502 523
503 /* shared irq, not for us */ 524 /* shared irq, not for us */
504 525
505 if (!ath9k_hw_intrpend(ah)) { 526 if (!ath9k_hw_intrpend(ah))
506 ath9k_ps_restore(sc);
507 return IRQ_NONE; 527 return IRQ_NONE;
508 }
509 528
510 /* 529 /*
511 * Figure out the reason(s) for the interrupt. Note 530 * Figure out the reason(s) for the interrupt. Note
@@ -520,10 +539,8 @@ irqreturn_t ath_isr(int irq, void *dev)
520 * If there are no status bits set, then this interrupt was not 539 * If there are no status bits set, then this interrupt was not
521 * for me (should have been caught above). 540 * for me (should have been caught above).
522 */ 541 */
523 if (!status) { 542 if (!status)
524 ath9k_ps_restore(sc);
525 return IRQ_NONE; 543 return IRQ_NONE;
526 }
527 544
528 /* Cache the status */ 545 /* Cache the status */
529 sc->intrstatus = status; 546 sc->intrstatus = status;
@@ -560,20 +577,17 @@ irqreturn_t ath_isr(int irq, void *dev)
560 ath9k_hw_set_interrupts(ah, sc->imask); 577 ath9k_hw_set_interrupts(ah, sc->imask);
561 } 578 }
562 579
563 if (status & ATH9K_INT_TIM_TIMER) { 580 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP))
564 if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { 581 if (status & ATH9K_INT_TIM_TIMER) {
565 /* Clear RxAbort bit so that we can 582 /* Clear RxAbort bit so that we can
566 * receive frames */ 583 * receive frames */
567 ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); 584 ath9k_hw_setpower(ah, ATH9K_PM_AWAKE);
568 ath9k_hw_setrxabort(ah, 0); 585 ath9k_hw_setrxabort(sc->sc_ah, 0);
569 sched = true;
570 sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; 586 sc->sc_flags |= SC_OP_WAIT_FOR_BEACON;
571 } 587 }
572 }
573 588
574chip_reset: 589chip_reset:
575 590
576 ath9k_ps_restore(sc);
577 ath_debug_stat_interrupt(sc, status); 591 ath_debug_stat_interrupt(sc, status);
578 592
579 if (sched) { 593 if (sched) {
@@ -900,6 +914,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
900 if (avp->av_opmode == NL80211_IFTYPE_STATION) { 914 if (avp->av_opmode == NL80211_IFTYPE_STATION) {
901 sc->curaid = bss_conf->aid; 915 sc->curaid = bss_conf->aid;
902 ath9k_hw_write_associd(sc); 916 ath9k_hw_write_associd(sc);
917
918 /*
919 * Request a re-configuration of Beacon related timers
920 * on the receipt of the first Beacon frame (i.e.,
921 * after time sync with the AP).
922 */
923 sc->sc_flags |= SC_OP_BEACON_SYNC;
903 } 924 }
904 925
905 /* Configure the beacon */ 926 /* Configure the beacon */
@@ -1094,7 +1115,7 @@ void ath_radio_enable(struct ath_softc *sc)
1094 if (r) { 1115 if (r) {
1095 DPRINTF(sc, ATH_DBG_FATAL, 1116 DPRINTF(sc, ATH_DBG_FATAL,
1096 "Unable to reset channel %u (%uMhz) ", 1117 "Unable to reset channel %u (%uMhz) ",
1097 "reset status %u\n", 1118 "reset status %d\n",
1098 channel->center_freq, r); 1119 channel->center_freq, r);
1099 } 1120 }
1100 spin_unlock_bh(&sc->sc_resetlock); 1121 spin_unlock_bh(&sc->sc_resetlock);
@@ -1146,7 +1167,7 @@ void ath_radio_disable(struct ath_softc *sc)
1146 if (r) { 1167 if (r) {
1147 DPRINTF(sc, ATH_DBG_FATAL, 1168 DPRINTF(sc, ATH_DBG_FATAL,
1148 "Unable to reset channel %u (%uMhz) " 1169 "Unable to reset channel %u (%uMhz) "
1149 "reset status %u\n", 1170 "reset status %d\n",
1150 channel->center_freq, r); 1171 channel->center_freq, r);
1151 } 1172 }
1152 spin_unlock_bh(&sc->sc_resetlock); 1173 spin_unlock_bh(&sc->sc_resetlock);
@@ -1416,8 +1437,6 @@ static int ath_init(u16 devid, struct ath_softc *sc)
1416 for (i = 0; i < sc->keymax; i++) 1437 for (i = 0; i < sc->keymax; i++)
1417 ath9k_hw_keyreset(ah, (u16) i); 1438 ath9k_hw_keyreset(ah, (u16) i);
1418 1439
1419 error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
1420 ath9k_reg_notifier);
1421 if (error) 1440 if (error)
1422 goto bad; 1441 goto bad;
1423 1442
@@ -1630,14 +1649,19 @@ int ath_attach(u16 devid, struct ath_softc *sc)
1630 if (error != 0) 1649 if (error != 0)
1631 return error; 1650 return error;
1632 1651
1633 reg = &sc->sc_ah->regulatory;
1634
1635 /* get mac address from hardware and set in mac80211 */ 1652 /* get mac address from hardware and set in mac80211 */
1636 1653
1637 SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); 1654 SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr);
1638 1655
1639 ath_set_hw_capab(sc, hw); 1656 ath_set_hw_capab(sc, hw);
1640 1657
1658 error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy,
1659 ath9k_reg_notifier);
1660 if (error)
1661 return error;
1662
1663 reg = &sc->sc_ah->regulatory;
1664
1641 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { 1665 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
1642 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); 1666 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
1643 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) 1667 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
@@ -1709,7 +1733,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
1709 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); 1733 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
1710 if (r) 1734 if (r)
1711 DPRINTF(sc, ATH_DBG_FATAL, 1735 DPRINTF(sc, ATH_DBG_FATAL,
1712 "Unable to reset hardware; reset status %u\n", r); 1736 "Unable to reset hardware; reset status %d\n", r);
1713 spin_unlock_bh(&sc->sc_resetlock); 1737 spin_unlock_bh(&sc->sc_resetlock);
1714 1738
1715 if (ath_startrecv(sc) != 0) 1739 if (ath_startrecv(sc) != 0)
@@ -2001,7 +2025,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
2001 r = ath9k_hw_reset(sc->sc_ah, init_channel, false); 2025 r = ath9k_hw_reset(sc->sc_ah, init_channel, false);
2002 if (r) { 2026 if (r) {
2003 DPRINTF(sc, ATH_DBG_FATAL, 2027 DPRINTF(sc, ATH_DBG_FATAL,
2004 "Unable to reset hardware; reset status %u " 2028 "Unable to reset hardware; reset status %d "
2005 "(freq %u MHz)\n", r, 2029 "(freq %u MHz)\n", r,
2006 curchan->center_freq); 2030 curchan->center_freq);
2007 spin_unlock_bh(&sc->sc_resetlock); 2031 spin_unlock_bh(&sc->sc_resetlock);
@@ -2074,6 +2098,46 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2074 goto exit; 2098 goto exit;
2075 } 2099 }
2076 2100
2101 if (sc->hw->conf.flags & IEEE80211_CONF_PS) {
2102 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2103 /*
2104 * mac80211 does not set PM field for normal data frames, so we
2105 * need to update that based on the current PS mode.
2106 */
2107 if (ieee80211_is_data(hdr->frame_control) &&
2108 !ieee80211_is_nullfunc(hdr->frame_control) &&
2109 !ieee80211_has_pm(hdr->frame_control)) {
2110 DPRINTF(sc, ATH_DBG_PS, "Add PM=1 for a TX frame "
2111 "while in PS mode\n");
2112 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM);
2113 }
2114 }
2115
2116 if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) {
2117 /*
2118 * We are using PS-Poll and mac80211 can request TX while in
2119 * power save mode. Need to wake up hardware for the TX to be
2120 * completed and if needed, also for RX of buffered frames.
2121 */
2122 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2123 ath9k_ps_wakeup(sc);
2124 ath9k_hw_setrxabort(sc->sc_ah, 0);
2125 if (ieee80211_is_pspoll(hdr->frame_control)) {
2126 DPRINTF(sc, ATH_DBG_PS, "Sending PS-Poll to pick a "
2127 "buffered frame\n");
2128 sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA;
2129 } else {
2130 DPRINTF(sc, ATH_DBG_PS, "Wake up to complete TX\n");
2131 sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK;
2132 }
2133 /*
2134 * The actual restore operation will happen only after
2135 * the sc_flags bit is cleared. We are just dropping
2136 * the ps_usecount here.
2137 */
2138 ath9k_ps_restore(sc);
2139 }
2140
2077 memset(&txctl, 0, sizeof(struct ath_tx_control)); 2141 memset(&txctl, 0, sizeof(struct ath_tx_control));
2078 2142
2079 /* 2143 /*
@@ -2311,7 +2375,10 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
2311 if (!(ah->caps.hw_caps & 2375 if (!(ah->caps.hw_caps &
2312 ATH9K_HW_CAP_AUTOSLEEP)) { 2376 ATH9K_HW_CAP_AUTOSLEEP)) {
2313 ath9k_hw_setrxabort(sc->sc_ah, 0); 2377 ath9k_hw_setrxabort(sc->sc_ah, 0);
2314 sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; 2378 sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON |
2379 SC_OP_WAIT_FOR_CAB |
2380 SC_OP_WAIT_FOR_PSPOLL_DATA |
2381 SC_OP_WAIT_FOR_TX_ACK);
2315 if (sc->imask & ATH9K_INT_TIM_TIMER) { 2382 if (sc->imask & ATH9K_INT_TIM_TIMER) {
2316 sc->imask &= ~ATH9K_INT_TIM_TIMER; 2383 sc->imask &= ~ATH9K_INT_TIM_TIMER;
2317 ath9k_hw_set_interrupts(sc->sc_ah, 2384 ath9k_hw_set_interrupts(sc->sc_ah,
@@ -2386,8 +2453,10 @@ static void ath9k_configure_filter(struct ieee80211_hw *hw,
2386 *total_flags &= SUPPORTED_FILTERS; 2453 *total_flags &= SUPPORTED_FILTERS;
2387 2454
2388 sc->rx.rxfilter = *total_flags; 2455 sc->rx.rxfilter = *total_flags;
2456 ath9k_ps_wakeup(sc);
2389 rfilt = ath_calcrxfilter(sc); 2457 rfilt = ath_calcrxfilter(sc);
2390 ath9k_hw_setrxfilter(sc->sc_ah, rfilt); 2458 ath9k_hw_setrxfilter(sc->sc_ah, rfilt);
2459 ath9k_ps_restore(sc);
2391 2460
2392 DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter); 2461 DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", sc->rx.rxfilter);
2393} 2462}
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index b46badd21f73..5014a19b0f75 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -473,6 +473,159 @@ void ath_flushrecv(struct ath_softc *sc)
473 spin_unlock_bh(&sc->rx.rxflushlock); 473 spin_unlock_bh(&sc->rx.rxflushlock);
474} 474}
475 475
476static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
477{
478 /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
479 struct ieee80211_mgmt *mgmt;
480 u8 *pos, *end, id, elen;
481 struct ieee80211_tim_ie *tim;
482
483 mgmt = (struct ieee80211_mgmt *)skb->data;
484 pos = mgmt->u.beacon.variable;
485 end = skb->data + skb->len;
486
487 while (pos + 2 < end) {
488 id = *pos++;
489 elen = *pos++;
490 if (pos + elen > end)
491 break;
492
493 if (id == WLAN_EID_TIM) {
494 if (elen < sizeof(*tim))
495 break;
496 tim = (struct ieee80211_tim_ie *) pos;
497 if (tim->dtim_count != 0)
498 break;
499 return tim->bitmap_ctrl & 0x01;
500 }
501
502 pos += elen;
503 }
504
505 return false;
506}
507
508static void ath_rx_ps_back_to_sleep(struct ath_softc *sc)
509{
510 sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
511}
512
513static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
514{
515 struct ieee80211_mgmt *mgmt;
516
517 if (skb->len < 24 + 8 + 2 + 2)
518 return;
519
520 mgmt = (struct ieee80211_mgmt *)skb->data;
521 if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0)
522 return; /* not from our current AP */
523
524 if (sc->sc_flags & SC_OP_BEACON_SYNC) {
525 sc->sc_flags &= ~SC_OP_BEACON_SYNC;
526 DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on "
527 "timestamp from the AP\n");
528 ath_beacon_config(sc, NULL);
529 }
530
531 if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) {
532 /* We are not in PS mode anymore; remain awake */
533 DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain "
534 "awake\n");
535 sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB);
536 return;
537 }
538
539 if (ath_beacon_dtim_pending_cab(skb)) {
540 /*
541 * Remain awake waiting for buffered broadcast/multicast
542 * frames.
543 */
544 DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating "
545 "buffered broadcast/multicast frame(s)\n");
546 sc->sc_flags |= SC_OP_WAIT_FOR_CAB;
547 return;
548 }
549
550 if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) {
551 /*
552 * This can happen if a broadcast frame is dropped or the AP
553 * fails to send a frame indicating that all CAB frames have
554 * been delivered.
555 */
556 DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n");
557 }
558
559 /* No more broadcast/multicast frames to be received at this point. */
560 ath_rx_ps_back_to_sleep(sc);
561}
562
563static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
564{
565 struct ieee80211_hdr *hdr;
566
567 hdr = (struct ieee80211_hdr *)skb->data;
568
569 /* Process Beacon and CAB receive in PS state */
570 if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) &&
571 ieee80211_is_beacon(hdr->frame_control))
572 ath_rx_ps_beacon(sc, skb);
573 else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) &&
574 (ieee80211_is_data(hdr->frame_control) ||
575 ieee80211_is_action(hdr->frame_control)) &&
576 is_multicast_ether_addr(hdr->addr1) &&
577 !ieee80211_has_moredata(hdr->frame_control)) {
578 DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to "
579 "sleep\n");
580 /*
581 * No more broadcast/multicast frames to be received at this
582 * point.
583 */
584 ath_rx_ps_back_to_sleep(sc);
585 } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) &&
586 !is_multicast_ether_addr(hdr->addr1) &&
587 !ieee80211_has_morefrags(hdr->frame_control)) {
588 sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA;
589 DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
590 "received PS-Poll data (0x%x)\n",
591 sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
592 SC_OP_WAIT_FOR_CAB |
593 SC_OP_WAIT_FOR_PSPOLL_DATA |
594 SC_OP_WAIT_FOR_TX_ACK));
595 }
596}
597
598static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb,
599 struct ieee80211_rx_status *rx_status)
600{
601 struct ieee80211_hdr *hdr;
602
603 hdr = (struct ieee80211_hdr *)skb->data;
604
605 /* Send the frame to mac80211 */
606 if (is_multicast_ether_addr(hdr->addr1)) {
607 int i;
608 /*
609 * Deliver broadcast/multicast frames to all suitable
610 * virtual wiphys.
611 */
612 /* TODO: filter based on channel configuration */
613 for (i = 0; i < sc->num_sec_wiphy; i++) {
614 struct ath_wiphy *aphy = sc->sec_wiphy[i];
615 struct sk_buff *nskb;
616 if (aphy == NULL)
617 continue;
618 nskb = skb_copy(skb, GFP_ATOMIC);
619 if (nskb)
620 __ieee80211_rx(aphy->hw, nskb, rx_status);
621 }
622 __ieee80211_rx(sc->hw, skb, rx_status);
623 } else {
624 /* Deliver unicast frames based on receiver address */
625 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, rx_status);
626 }
627}
628
476int ath_rx_tasklet(struct ath_softc *sc, int flush) 629int ath_rx_tasklet(struct ath_softc *sc, int flush)
477{ 630{
478#define PA2DESC(_sc, _pa) \ 631#define PA2DESC(_sc, _pa) \
@@ -622,7 +775,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
622 775
623 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { 776 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
624 rx_status.flag |= RX_FLAG_DECRYPTED; 777 rx_status.flag |= RX_FLAG_DECRYPTED;
625 } else if ((le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_PROTECTED) 778 } else if (ieee80211_has_protected(fc)
626 && !decrypt_error && skb->len >= hdrlen + 4) { 779 && !decrypt_error && skb->len >= hdrlen + 4) {
627 keyix = skb->data[hdrlen + 3] >> 6; 780 keyix = skb->data[hdrlen + 3] >> 6;
628 781
@@ -631,36 +784,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
631 } 784 }
632 if (ah->sw_mgmt_crypto && 785 if (ah->sw_mgmt_crypto &&
633 (rx_status.flag & RX_FLAG_DECRYPTED) && 786 (rx_status.flag & RX_FLAG_DECRYPTED) &&
634 ieee80211_is_mgmt(hdr->frame_control)) { 787 ieee80211_is_mgmt(fc)) {
635 /* Use software decrypt for management frames. */ 788 /* Use software decrypt for management frames. */
636 rx_status.flag &= ~RX_FLAG_DECRYPTED; 789 rx_status.flag &= ~RX_FLAG_DECRYPTED;
637 } 790 }
638 791
639 /* Send the frame to mac80211 */
640 if (hdr->addr1[5] & 0x01) {
641 int i;
642 /*
643 * Deliver broadcast/multicast frames to all suitable
644 * virtual wiphys.
645 */
646 /* TODO: filter based on channel configuration */
647 for (i = 0; i < sc->num_sec_wiphy; i++) {
648 struct ath_wiphy *aphy = sc->sec_wiphy[i];
649 struct sk_buff *nskb;
650 if (aphy == NULL)
651 continue;
652 nskb = skb_copy(skb, GFP_ATOMIC);
653 if (nskb)
654 __ieee80211_rx(aphy->hw, nskb,
655 &rx_status);
656 }
657 __ieee80211_rx(sc->hw, skb, &rx_status);
658 } else {
659 /* Deliver unicast frames based on receiver address */
660 __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb,
661 &rx_status);
662 }
663
664 /* We will now give hardware our shiny new allocated skb */ 792 /* We will now give hardware our shiny new allocated skb */
665 bf->bf_mpdu = requeue_skb; 793 bf->bf_mpdu = requeue_skb;
666 bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, 794 bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data,
@@ -672,6 +800,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
672 bf->bf_mpdu = NULL; 800 bf->bf_mpdu = NULL;
673 DPRINTF(sc, ATH_DBG_FATAL, 801 DPRINTF(sc, ATH_DBG_FATAL,
674 "dma_mapping_error() on RX\n"); 802 "dma_mapping_error() on RX\n");
803 ath_rx_send_to_mac80211(sc, skb, &rx_status);
675 break; 804 break;
676 } 805 }
677 bf->bf_dmacontext = bf->bf_buf_addr; 806 bf->bf_dmacontext = bf->bf_buf_addr;
@@ -687,11 +816,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
687 sc->rx.rxotherant = 0; 816 sc->rx.rxotherant = 0;
688 } 817 }
689 818
690 if (ieee80211_is_beacon(fc) && 819 if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
691 (sc->sc_flags & SC_OP_WAIT_FOR_BEACON)) { 820 SC_OP_WAIT_FOR_PSPOLL_DATA)))
692 sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; 821 ath_rx_ps(sc, skb);
693 ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); 822
694 } 823 ath_rx_send_to_mac80211(sc, skb, &rx_status);
824
695requeue: 825requeue:
696 list_move_tail(&bf->list, &sc->rx.rxbuf); 826 list_move_tail(&bf->list, &sc->rx.rxbuf);
697 ath_rx_buf_link(sc, bf); 827 ath_rx_buf_link(sc, bf);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 41c42824a5ca..a8def4fa449c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1070,7 +1070,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1070 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true); 1070 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, true);
1071 if (r) 1071 if (r)
1072 DPRINTF(sc, ATH_DBG_FATAL, 1072 DPRINTF(sc, ATH_DBG_FATAL,
1073 "Unable to reset hardware; reset status %u\n", 1073 "Unable to reset hardware; reset status %d\n",
1074 r); 1074 r);
1075 spin_unlock_bh(&sc->sc_resetlock); 1075 spin_unlock_bh(&sc->sc_resetlock);
1076 } 1076 }
@@ -1790,6 +1790,16 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1790 skb_pull(skb, padsize); 1790 skb_pull(skb, padsize);
1791 } 1791 }
1792 1792
1793 if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) {
1794 sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK;
1795 DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having "
1796 "received TX status (0x%x)\n",
1797 sc->sc_flags & (SC_OP_WAIT_FOR_BEACON |
1798 SC_OP_WAIT_FOR_CAB |
1799 SC_OP_WAIT_FOR_PSPOLL_DATA |
1800 SC_OP_WAIT_FOR_TX_ACK));
1801 }
1802
1793 if (frame_type == ATH9K_NOT_INTERNAL) 1803 if (frame_type == ATH9K_NOT_INTERNAL)
1794 ieee80211_tx_status(hw, skb); 1804 ieee80211_tx_status(hw, skb);
1795 else 1805 else
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index fdf07c822081..7a89f9fac7d4 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -200,8 +200,10 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy,
200 continue; 200 continue;
201 201
202 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { 202 if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) {
203 r = freq_reg_info(wiphy, ch->center_freq, 203 r = freq_reg_info(wiphy,
204 &bandwidth, &reg_rule); 204 ch->center_freq,
205 bandwidth,
206 &reg_rule);
205 if (r) 207 if (r)
206 continue; 208 continue;
207 /* 209 /*
@@ -265,7 +267,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
265 */ 267 */
266 268
267 ch = &sband->channels[11]; /* CH 12 */ 269 ch = &sband->channels[11]; /* CH 12 */
268 r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule); 270 r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
269 if (!r) { 271 if (!r) {
270 if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) 272 if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
271 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) 273 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
@@ -273,7 +275,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy,
273 } 275 }
274 276
275 ch = &sband->channels[12]; /* CH 13 */ 277 ch = &sband->channels[12]; /* CH 13 */
276 r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, &reg_rule); 278 r = freq_reg_info(wiphy, ch->center_freq, bandwidth, &reg_rule);
277 if (!r) { 279 if (!r) {
278 if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) 280 if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
279 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) 281 if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 2615aaf7df6a..cb4a8712946a 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -3553,27 +3553,25 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw,
3553 3553
3554 B43_WARN_ON(wl->vif != vif); 3554 B43_WARN_ON(wl->vif != vif);
3555 3555
3556 spin_lock_irqsave(&wl->irq_lock, flags);
3556 if (changed & BSS_CHANGED_BSSID) { 3557 if (changed & BSS_CHANGED_BSSID) {
3557 spin_lock_irqsave(&wl->irq_lock, flags);
3558 if (conf->bssid) 3558 if (conf->bssid)
3559 memcpy(wl->bssid, conf->bssid, ETH_ALEN); 3559 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
3560 else 3560 else
3561 memset(wl->bssid, 0, ETH_ALEN); 3561 memset(wl->bssid, 0, ETH_ALEN);
3562 }
3562 3563
3563 if (b43_status(dev) >= B43_STAT_INITIALIZED) { 3564 if (b43_status(dev) >= B43_STAT_INITIALIZED) {
3564 if (b43_is_mode(wl, NL80211_IFTYPE_AP) || 3565 if (changed & BSS_CHANGED_BEACON &&
3565 b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) { 3566 (b43_is_mode(wl, NL80211_IFTYPE_AP) ||
3566 B43_WARN_ON(vif->type != wl->if_type); 3567 b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) ||
3567 if (changed & BSS_CHANGED_BEACON) 3568 b43_is_mode(wl, NL80211_IFTYPE_ADHOC)))
3568 b43_update_templates(wl); 3569 b43_update_templates(wl);
3569 } else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) { 3570
3570 if (changed & BSS_CHANGED_BEACON) 3571 if (changed & BSS_CHANGED_BSSID)
3571 b43_update_templates(wl);
3572 }
3573 b43_write_mac_bssid_templates(dev); 3572 b43_write_mac_bssid_templates(dev);
3574 }
3575 spin_unlock_irqrestore(&wl->irq_lock, flags);
3576 } 3573 }
3574 spin_unlock_irqrestore(&wl->irq_lock, flags);
3577 3575
3578 b43_mac_suspend(dev); 3576 b43_mac_suspend(dev);
3579 3577
@@ -3639,7 +3637,7 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
3639 err = -EINVAL; 3637 err = -EINVAL;
3640 switch (key->alg) { 3638 switch (key->alg) {
3641 case ALG_WEP: 3639 case ALG_WEP:
3642 if (key->keylen == LEN_WEP40) 3640 if (key->keylen == WLAN_KEY_LEN_WEP40)
3643 algorithm = B43_SEC_ALGO_WEP40; 3641 algorithm = B43_SEC_ALGO_WEP40;
3644 else 3642 else
3645 algorithm = B43_SEC_ALGO_WEP104; 3643 algorithm = B43_SEC_ALGO_WEP104;
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index da59ef02b6ef..19a4b0bc0d87 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -694,8 +694,8 @@ struct b43legacy_wldev {
694 /* Reason code of the last interrupt. */ 694 /* Reason code of the last interrupt. */
695 u32 irq_reason; 695 u32 irq_reason;
696 u32 dma_reason[6]; 696 u32 dma_reason[6];
697 /* saved irq enable/disable state bitfield. */ 697 /* The currently active generic-interrupt mask. */
698 u32 irq_savedstate; 698 u32 irq_mask;
699 /* Link Quality calculation context. */ 699 /* Link Quality calculation context. */
700 struct b43legacy_noise_calculation noisecalc; 700 struct b43legacy_noise_calculation noisecalc;
701 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ 701 /* if > 0 MAC is suspended. if == 0 MAC is enabled. */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 07c7898c87ac..f6f3fbf0a2f4 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -583,35 +583,6 @@ static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev)
583 b43legacy_set_slot_time(dev, 20); 583 b43legacy_set_slot_time(dev, 20);
584} 584}
585 585
586/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable.
587 * Returns the _previously_ enabled IRQ mask.
588 */
589static inline u32 b43legacy_interrupt_enable(struct b43legacy_wldev *dev,
590 u32 mask)
591{
592 u32 old_mask;
593
594 old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
595 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask |
596 mask);
597
598 return old_mask;
599}
600
601/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable.
602 * Returns the _previously_ enabled IRQ mask.
603 */
604static inline u32 b43legacy_interrupt_disable(struct b43legacy_wldev *dev,
605 u32 mask)
606{
607 u32 old_mask;
608
609 old_mask = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
610 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, old_mask & ~mask);
611
612 return old_mask;
613}
614
615/* Synchronize IRQ top- and bottom-half. 586/* Synchronize IRQ top- and bottom-half.
616 * IRQs must be masked before calling this. 587 * IRQs must be masked before calling this.
617 * This must not be called with the irq_lock held. 588 * This must not be called with the irq_lock held.
@@ -1200,7 +1171,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
1200 /* This is the bottom half of the asynchronous beacon update. */ 1171 /* This is the bottom half of the asynchronous beacon update. */
1201 1172
1202 /* Ignore interrupt in the future. */ 1173 /* Ignore interrupt in the future. */
1203 dev->irq_savedstate &= ~B43legacy_IRQ_BEACON; 1174 dev->irq_mask &= ~B43legacy_IRQ_BEACON;
1204 1175
1205 cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); 1176 cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD);
1206 beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); 1177 beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID);
@@ -1209,7 +1180,7 @@ static void handle_irq_beacon(struct b43legacy_wldev *dev)
1209 /* Schedule interrupt manually, if busy. */ 1180 /* Schedule interrupt manually, if busy. */
1210 if (beacon0_valid && beacon1_valid) { 1181 if (beacon0_valid && beacon1_valid) {
1211 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON); 1182 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON);
1212 dev->irq_savedstate |= B43legacy_IRQ_BEACON; 1183 dev->irq_mask |= B43legacy_IRQ_BEACON;
1213 return; 1184 return;
1214 } 1185 }
1215 1186
@@ -1247,12 +1218,11 @@ static void b43legacy_beacon_update_trigger_work(struct work_struct *work)
1247 dev = wl->current_dev; 1218 dev = wl->current_dev;
1248 if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) { 1219 if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) {
1249 spin_lock_irq(&wl->irq_lock); 1220 spin_lock_irq(&wl->irq_lock);
1250 /* update beacon right away or defer to irq */ 1221 /* Update beacon right away or defer to IRQ. */
1251 dev->irq_savedstate = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK);
1252 handle_irq_beacon(dev); 1222 handle_irq_beacon(dev);
1253 /* The handler might have updated the IRQ mask. */ 1223 /* The handler might have updated the IRQ mask. */
1254 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 1224 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
1255 dev->irq_savedstate); 1225 dev->irq_mask);
1256 mmiowb(); 1226 mmiowb();
1257 spin_unlock_irq(&wl->irq_lock); 1227 spin_unlock_irq(&wl->irq_lock);
1258 } 1228 }
@@ -1398,7 +1368,7 @@ static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev)
1398 if (reason & B43legacy_IRQ_TX_OK) 1368 if (reason & B43legacy_IRQ_TX_OK)
1399 handle_irq_transmit_status(dev); 1369 handle_irq_transmit_status(dev);
1400 1370
1401 b43legacy_interrupt_enable(dev, dev->irq_savedstate); 1371 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
1402 mmiowb(); 1372 mmiowb();
1403 spin_unlock_irqrestore(&dev->wl->irq_lock, flags); 1373 spin_unlock_irqrestore(&dev->wl->irq_lock, flags);
1404} 1374}
@@ -1450,18 +1420,18 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
1450 struct b43legacy_wldev *dev = dev_id; 1420 struct b43legacy_wldev *dev = dev_id;
1451 u32 reason; 1421 u32 reason;
1452 1422
1453 if (!dev) 1423 B43legacy_WARN_ON(!dev);
1454 return IRQ_NONE;
1455 1424
1456 spin_lock(&dev->wl->irq_lock); 1425 spin_lock(&dev->wl->irq_lock);
1457 1426
1458 if (b43legacy_status(dev) < B43legacy_STAT_STARTED) 1427 if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED))
1428 /* This can only happen on shared IRQ lines. */
1459 goto out; 1429 goto out;
1460 reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); 1430 reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);
1461 if (reason == 0xffffffff) /* shared IRQ */ 1431 if (reason == 0xffffffff) /* shared IRQ */
1462 goto out; 1432 goto out;
1463 ret = IRQ_HANDLED; 1433 ret = IRQ_HANDLED;
1464 reason &= b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); 1434 reason &= dev->irq_mask;
1465 if (!reason) 1435 if (!reason)
1466 goto out; 1436 goto out;
1467 1437
@@ -1485,10 +1455,9 @@ static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id)
1485 & 0x0000DC00; 1455 & 0x0000DC00;
1486 1456
1487 b43legacy_interrupt_ack(dev, reason); 1457 b43legacy_interrupt_ack(dev, reason);
1488 /* disable all IRQs. They are enabled again in the bottom half. */ 1458 /* Disable all IRQs. They are enabled again in the bottom half. */
1489 dev->irq_savedstate = b43legacy_interrupt_disable(dev, 1459 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
1490 B43legacy_IRQ_ALL); 1460 /* Save the reason code and call our bottom half. */
1491 /* save the reason code and call our bottom half. */
1492 dev->irq_reason = reason; 1461 dev->irq_reason = reason;
1493 tasklet_schedule(&dev->isr_tasklet); 1462 tasklet_schedule(&dev->isr_tasklet);
1494out: 1463out:
@@ -1948,7 +1917,8 @@ void b43legacy_mac_enable(struct b43legacy_wldev *dev)
1948 1917
1949 /* Re-enable IRQs. */ 1918 /* Re-enable IRQs. */
1950 spin_lock_irq(&dev->wl->irq_lock); 1919 spin_lock_irq(&dev->wl->irq_lock);
1951 b43legacy_interrupt_enable(dev, dev->irq_savedstate); 1920 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK,
1921 dev->irq_mask);
1952 spin_unlock_irq(&dev->wl->irq_lock); 1922 spin_unlock_irq(&dev->wl->irq_lock);
1953 } 1923 }
1954} 1924}
@@ -1967,10 +1937,9 @@ void b43legacy_mac_suspend(struct b43legacy_wldev *dev)
1967 /* Mask IRQs before suspending MAC. Otherwise 1937 /* Mask IRQs before suspending MAC. Otherwise
1968 * the MAC stays busy and won't suspend. */ 1938 * the MAC stays busy and won't suspend. */
1969 spin_lock_irq(&dev->wl->irq_lock); 1939 spin_lock_irq(&dev->wl->irq_lock);
1970 tmp = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); 1940 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
1971 spin_unlock_irq(&dev->wl->irq_lock); 1941 spin_unlock_irq(&dev->wl->irq_lock);
1972 b43legacy_synchronize_irq(dev); 1942 b43legacy_synchronize_irq(dev);
1973 dev->irq_savedstate = tmp;
1974 1943
1975 b43legacy_power_saving_ctl_bits(dev, -1, 1); 1944 b43legacy_power_saving_ctl_bits(dev, -1, 1);
1976 b43legacy_write32(dev, B43legacy_MMIO_MACCTL, 1945 b43legacy_write32(dev, B43legacy_MMIO_MACCTL,
@@ -2659,7 +2628,6 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
2659 int antenna_tx; 2628 int antenna_tx;
2660 int antenna_rx; 2629 int antenna_rx;
2661 int err = 0; 2630 int err = 0;
2662 u32 savedirqs;
2663 2631
2664 antenna_tx = B43legacy_ANTENNA_DEFAULT; 2632 antenna_tx = B43legacy_ANTENNA_DEFAULT;
2665 antenna_rx = B43legacy_ANTENNA_DEFAULT; 2633 antenna_rx = B43legacy_ANTENNA_DEFAULT;
@@ -2699,7 +2667,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
2699 spin_unlock_irqrestore(&wl->irq_lock, flags); 2667 spin_unlock_irqrestore(&wl->irq_lock, flags);
2700 goto out_unlock_mutex; 2668 goto out_unlock_mutex;
2701 } 2669 }
2702 savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); 2670 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
2703 spin_unlock_irqrestore(&wl->irq_lock, flags); 2671 spin_unlock_irqrestore(&wl->irq_lock, flags);
2704 b43legacy_synchronize_irq(dev); 2672 b43legacy_synchronize_irq(dev);
2705 2673
@@ -2738,7 +2706,7 @@ static int b43legacy_op_dev_config(struct ieee80211_hw *hw,
2738 } 2706 }
2739 2707
2740 spin_lock_irqsave(&wl->irq_lock, flags); 2708 spin_lock_irqsave(&wl->irq_lock, flags);
2741 b43legacy_interrupt_enable(dev, savedirqs); 2709 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
2742 mmiowb(); 2710 mmiowb();
2743 spin_unlock_irqrestore(&wl->irq_lock, flags); 2711 spin_unlock_irqrestore(&wl->irq_lock, flags);
2744out_unlock_mutex: 2712out_unlock_mutex:
@@ -2801,7 +2769,6 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
2801 struct b43legacy_wldev *dev; 2769 struct b43legacy_wldev *dev;
2802 struct b43legacy_phy *phy; 2770 struct b43legacy_phy *phy;
2803 unsigned long flags; 2771 unsigned long flags;
2804 u32 savedirqs;
2805 2772
2806 mutex_lock(&wl->mutex); 2773 mutex_lock(&wl->mutex);
2807 B43legacy_WARN_ON(wl->vif != vif); 2774 B43legacy_WARN_ON(wl->vif != vif);
@@ -2817,30 +2784,27 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
2817 spin_unlock_irqrestore(&wl->irq_lock, flags); 2784 spin_unlock_irqrestore(&wl->irq_lock, flags);
2818 goto out_unlock_mutex; 2785 goto out_unlock_mutex;
2819 } 2786 }
2820 savedirqs = b43legacy_interrupt_disable(dev, B43legacy_IRQ_ALL); 2787 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
2821 2788
2822 if (changed & BSS_CHANGED_BSSID) { 2789 if (changed & BSS_CHANGED_BSSID) {
2823 spin_unlock_irqrestore(&wl->irq_lock, flags);
2824 b43legacy_synchronize_irq(dev); 2790 b43legacy_synchronize_irq(dev);
2825 2791
2826 if (conf->bssid) 2792 if (conf->bssid)
2827 memcpy(wl->bssid, conf->bssid, ETH_ALEN); 2793 memcpy(wl->bssid, conf->bssid, ETH_ALEN);
2828 else 2794 else
2829 memset(wl->bssid, 0, ETH_ALEN); 2795 memset(wl->bssid, 0, ETH_ALEN);
2796 }
2797
2798 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
2799 if (changed & BSS_CHANGED_BEACON &&
2800 (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) ||
2801 b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)))
2802 b43legacy_update_templates(wl);
2830 2803
2831 if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { 2804 if (changed & BSS_CHANGED_BSSID)
2832 if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) {
2833 B43legacy_WARN_ON(vif->type != NL80211_IFTYPE_AP);
2834 if (changed & BSS_CHANGED_BEACON)
2835 b43legacy_update_templates(wl);
2836 } else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) {
2837 if (changed & BSS_CHANGED_BEACON)
2838 b43legacy_update_templates(wl);
2839 }
2840 b43legacy_write_mac_bssid_templates(dev); 2805 b43legacy_write_mac_bssid_templates(dev);
2841 }
2842 spin_unlock_irqrestore(&wl->irq_lock, flags);
2843 } 2806 }
2807 spin_unlock_irqrestore(&wl->irq_lock, flags);
2844 2808
2845 b43legacy_mac_suspend(dev); 2809 b43legacy_mac_suspend(dev);
2846 2810
@@ -2862,7 +2826,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw,
2862 b43legacy_mac_enable(dev); 2826 b43legacy_mac_enable(dev);
2863 2827
2864 spin_lock_irqsave(&wl->irq_lock, flags); 2828 spin_lock_irqsave(&wl->irq_lock, flags);
2865 b43legacy_interrupt_enable(dev, savedirqs); 2829 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
2866 /* XXX: why? */ 2830 /* XXX: why? */
2867 mmiowb(); 2831 mmiowb();
2868 spin_unlock_irqrestore(&wl->irq_lock, flags); 2832 spin_unlock_irqrestore(&wl->irq_lock, flags);
@@ -2922,8 +2886,7 @@ static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev)
2922 * setting the status to INITIALIZED, as the interrupt handler 2886 * setting the status to INITIALIZED, as the interrupt handler
2923 * won't care about IRQs then. */ 2887 * won't care about IRQs then. */
2924 spin_lock_irqsave(&wl->irq_lock, flags); 2888 spin_lock_irqsave(&wl->irq_lock, flags);
2925 dev->irq_savedstate = b43legacy_interrupt_disable(dev, 2889 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0);
2926 B43legacy_IRQ_ALL);
2927 b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ 2890 b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */
2928 spin_unlock_irqrestore(&wl->irq_lock, flags); 2891 spin_unlock_irqrestore(&wl->irq_lock, flags);
2929 b43legacy_synchronize_irq(dev); 2892 b43legacy_synchronize_irq(dev);
@@ -2963,7 +2926,7 @@ static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev)
2963 2926
2964 /* Start data flow (TX/RX) */ 2927 /* Start data flow (TX/RX) */
2965 b43legacy_mac_enable(dev); 2928 b43legacy_mac_enable(dev);
2966 b43legacy_interrupt_enable(dev, dev->irq_savedstate); 2929 b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask);
2967 2930
2968 /* Start maintenance work */ 2931 /* Start maintenance work */
2969 b43legacy_periodic_tasks_setup(dev); 2932 b43legacy_periodic_tasks_setup(dev);
@@ -3126,7 +3089,7 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev)
3126 /* IRQ related flags */ 3089 /* IRQ related flags */
3127 dev->irq_reason = 0; 3090 dev->irq_reason = 0;
3128 memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); 3091 memset(dev->dma_reason, 0, sizeof(dev->dma_reason));
3129 dev->irq_savedstate = B43legacy_IRQ_MASKTEMPLATE; 3092 dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE;
3130 3093
3131 dev->mac_suspended = 1; 3094 dev->mac_suspended = 1;
3132 3095
diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c
index 746d5361bba0..51866c9a2769 100644
--- a/drivers/net/wireless/b43legacy/pio.c
+++ b/drivers/net/wireless/b43legacy/pio.c
@@ -443,7 +443,7 @@ int b43legacy_pio_init(struct b43legacy_wldev *dev)
443 pio->queue3 = queue; 443 pio->queue3 = queue;
444 444
445 if (dev->dev->id.revision < 3) 445 if (dev->dev->id.revision < 3)
446 dev->irq_savedstate |= B43legacy_IRQ_PIO_WORKAROUND; 446 dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND;
447 447
448 b43legacydbg(dev->wl, "PIO initialized\n"); 448 b43legacydbg(dev->wl, "PIO initialized\n");
449 err = 0; 449 err = 0;
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
index ac22f59be9ef..bd7e520d98c2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c
@@ -44,6 +44,15 @@
44#include "iwl-core.h" 44#include "iwl-core.h"
45#include "iwl-dev.h" 45#include "iwl-dev.h"
46 46
47#ifdef CONFIG_IWLWIFI_DEBUG
48static const char *led_type_str[] = {
49 __stringify(IWL_LED_TRG_TX),
50 __stringify(IWL_LED_TRG_RX),
51 __stringify(IWL_LED_TRG_ASSOC),
52 __stringify(IWL_LED_TRG_RADIO),
53 NULL
54};
55#endif /* CONFIG_IWLWIFI_DEBUG */
47 56
48static const struct { 57static const struct {
49 u16 brightness; 58 u16 brightness;
@@ -61,7 +70,7 @@ static const struct {
61 {10, 110, 110}, 70 {10, 110, 110},
62 {5, 130, 130}, 71 {5, 130, 130},
63 {0, 167, 167}, 72 {0, 167, 167},
64 /*SOLID_ON*/ 73 /* SOLID_ON */
65 {-1, IWL_LED_SOLID, 0} 74 {-1, IWL_LED_SOLID, 0}
66}; 75};
67 76
@@ -143,6 +152,30 @@ static int iwl3945_led_off(struct iwl_priv *priv, int led_id)
143} 152}
144 153
145/* 154/*
155 * Set led on in case of association
156 * */
157static int iwl3945_led_associate(struct iwl_priv *priv, int led_id)
158{
159 IWL_DEBUG_LED(priv, "Associated\n");
160
161 priv->allow_blinking = 1;
162 return iwl3945_led_on(priv, led_id);
163}
164/* Set Led off in case of disassociation */
165static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id)
166{
167 IWL_DEBUG_LED(priv, "Disassociated\n");
168
169 priv->allow_blinking = 0;
170 if (iwl_is_rfkill(priv))
171 iwl3945_led_off(priv, led_id);
172 else
173 iwl3945_led_on(priv, led_id);
174
175 return 0;
176}
177
178/*
146 * brightness call back function for Tx/Rx LED 179 * brightness call back function for Tx/Rx LED
147 */ 180 */
148static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) 181static int iwl3945_led_associated(struct iwl_priv *priv, int led_id)
@@ -165,26 +198,21 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
165 enum led_brightness brightness) 198 enum led_brightness brightness)
166{ 199{
167 struct iwl_led *led = container_of(led_cdev, 200 struct iwl_led *led = container_of(led_cdev,
168 struct iwl_led, led_dev); 201 struct iwl_led, led_dev);
169 struct iwl_priv *priv = led->priv; 202 struct iwl_priv *priv = led->priv;
170 203
171 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 204 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
172 return; 205 return;
173 206
207 IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n",
208 led_type_str[led->type], brightness);
209
174 switch (brightness) { 210 switch (brightness) {
175 case LED_FULL: 211 case LED_FULL:
176 if (led->type == IWL_LED_TRG_ASSOC) {
177 priv->allow_blinking = 1;
178 IWL_DEBUG_LED(priv, "MAC is associated\n");
179 }
180 if (led->led_on) 212 if (led->led_on)
181 led->led_on(priv, IWL_LED_LINK); 213 led->led_on(priv, IWL_LED_LINK);
182 break; 214 break;
183 case LED_OFF: 215 case LED_OFF:
184 if (led->type == IWL_LED_TRG_ASSOC) {
185 priv->allow_blinking = 0;
186 IWL_DEBUG_LED(priv, "MAC is disassociated\n");
187 }
188 if (led->led_off) 216 if (led->led_off)
189 led->led_off(priv, IWL_LED_LINK); 217 led->led_off(priv, IWL_LED_LINK);
190 break; 218 break;
@@ -197,8 +225,6 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
197 } 225 }
198} 226}
199 227
200
201
202/* 228/*
203 * Register led class with the system 229 * Register led class with the system
204 */ 230 */
@@ -237,12 +263,12 @@ static int iwl3945_led_register_led(struct iwl_priv *priv,
237static inline u8 get_blink_rate(struct iwl_priv *priv) 263static inline u8 get_blink_rate(struct iwl_priv *priv)
238{ 264{
239 int index; 265 int index;
240 u64 current_tpt = priv->rxtxpackets; 266 s64 tpt = priv->rxtxpackets;
241 s64 tpt = current_tpt - priv->led_tpt;
242 267
243 if (tpt < 0) 268 if (tpt < 0)
244 tpt = -tpt; 269 tpt = -tpt;
245 priv->led_tpt = current_tpt; 270
271 IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt);
246 272
247 if (!priv->allow_blinking) 273 if (!priv->allow_blinking)
248 index = IWL_MAX_BLINK_TBL; 274 index = IWL_MAX_BLINK_TBL;
@@ -250,13 +276,9 @@ static inline u8 get_blink_rate(struct iwl_priv *priv)
250 for (index = 0; index < IWL_MAX_BLINK_TBL; index++) 276 for (index = 0; index < IWL_MAX_BLINK_TBL; index++)
251 if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) 277 if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE))
252 break; 278 break;
253 return index;
254}
255 279
256static inline int is_rf_kill(struct iwl_priv *priv) 280 IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index);
257{ 281 return index;
258 return test_bit(STATUS_RF_KILL_HW, &priv->status) ||
259 test_bit(STATUS_RF_KILL_SW, &priv->status);
260} 282}
261 283
262/* 284/*
@@ -272,7 +294,7 @@ void iwl3945_led_background(struct iwl_priv *priv)
272 priv->last_blink_time = 0; 294 priv->last_blink_time = 0;
273 return; 295 return;
274 } 296 }
275 if (is_rf_kill(priv)) { 297 if (iwl_is_rfkill(priv)) {
276 priv->last_blink_time = 0; 298 priv->last_blink_time = 0;
277 return; 299 return;
278 } 300 }
@@ -341,8 +363,8 @@ int iwl3945_led_register(struct iwl_priv *priv)
341 IWL_LED_TRG_ASSOC, 0, trigger); 363 IWL_LED_TRG_ASSOC, 0, trigger);
342 364
343 /* for assoc always turn led on */ 365 /* for assoc always turn led on */
344 priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on; 366 priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate;
345 priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on; 367 priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate;
346 priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; 368 priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
347 369
348 if (ret) 370 if (ret)
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 5b0c6e5bda92..fd65e1c3e055 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -98,7 +98,6 @@ const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
98 * ... and set IWL_EVT_DISABLE to 1. */ 98 * ... and set IWL_EVT_DISABLE to 1. */
99void iwl3945_disable_events(struct iwl_priv *priv) 99void iwl3945_disable_events(struct iwl_priv *priv)
100{ 100{
101 int ret;
102 int i; 101 int i;
103 u32 base; /* SRAM address of event log header */ 102 u32 base; /* SRAM address of event log header */
104 u32 disable_ptr; /* SRAM address of event-disable bitmap array */ 103 u32 disable_ptr; /* SRAM address of event-disable bitmap array */
@@ -159,26 +158,17 @@ void iwl3945_disable_events(struct iwl_priv *priv)
159 return; 158 return;
160 } 159 }
161 160
162 ret = iwl_grab_nic_access(priv);
163 if (ret) {
164 IWL_WARN(priv, "Can not read from adapter at this time.\n");
165 return;
166 }
167
168 disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32))); 161 disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32)));
169 array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32))); 162 array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32)));
170 iwl_release_nic_access(priv);
171 163
172 if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) { 164 if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) {
173 IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n", 165 IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n",
174 disable_ptr); 166 disable_ptr);
175 ret = iwl_grab_nic_access(priv);
176 for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++) 167 for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
177 iwl_write_targ_mem(priv, 168 iwl_write_targ_mem(priv,
178 disable_ptr + (i * sizeof(u32)), 169 disable_ptr + (i * sizeof(u32)),
179 evt_disable[i]); 170 evt_disable[i]);
180 171
181 iwl_release_nic_access(priv);
182 } else { 172 } else {
183 IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n"); 173 IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n");
184 IWL_DEBUG_INFO(priv, " by writing \"1\"s into disable bitmap\n"); 174 IWL_DEBUG_INFO(priv, " by writing \"1\"s into disable bitmap\n");
@@ -908,55 +898,30 @@ u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags)
908 898
909static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) 899static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
910{ 900{
911 int ret;
912 unsigned long flags;
913
914 spin_lock_irqsave(&priv->lock, flags);
915 ret = iwl_grab_nic_access(priv);
916 if (ret) {
917 spin_unlock_irqrestore(&priv->lock, flags);
918 return ret;
919 }
920
921 if (src == IWL_PWR_SRC_VAUX) { 901 if (src == IWL_PWR_SRC_VAUX) {
922 if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) { 902 if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
923 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, 903 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
924 APMG_PS_CTRL_VAL_PWR_SRC_VAUX, 904 APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
925 ~APMG_PS_CTRL_MSK_PWR_SRC); 905 ~APMG_PS_CTRL_MSK_PWR_SRC);
926 iwl_release_nic_access(priv);
927 906
928 iwl_poll_bit(priv, CSR_GPIO_IN, 907 iwl_poll_bit(priv, CSR_GPIO_IN,
929 CSR_GPIO_IN_VAL_VAUX_PWR_SRC, 908 CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
930 CSR_GPIO_IN_BIT_AUX_POWER, 5000); 909 CSR_GPIO_IN_BIT_AUX_POWER, 5000);
931 } else {
932 iwl_release_nic_access(priv);
933 } 910 }
934 } else { 911 } else {
935 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, 912 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
936 APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, 913 APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
937 ~APMG_PS_CTRL_MSK_PWR_SRC); 914 ~APMG_PS_CTRL_MSK_PWR_SRC);
938 915
939 iwl_release_nic_access(priv);
940 iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, 916 iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
941 CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ 917 CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */
942 } 918 }
943 spin_unlock_irqrestore(&priv->lock, flags);
944 919
945 return ret; 920 return 0;
946} 921}
947 922
948static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) 923static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
949{ 924{
950 int rc;
951 unsigned long flags;
952
953 spin_lock_irqsave(&priv->lock, flags);
954 rc = iwl_grab_nic_access(priv);
955 if (rc) {
956 spin_unlock_irqrestore(&priv->lock, flags);
957 return rc;
958 }
959
960 iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); 925 iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr);
961 iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); 926 iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
962 iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); 927 iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
@@ -973,23 +938,11 @@ static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
973 /* fake read to flush all prev I/O */ 938 /* fake read to flush all prev I/O */
974 iwl_read_direct32(priv, FH39_RSSR_CTRL); 939 iwl_read_direct32(priv, FH39_RSSR_CTRL);
975 940
976 iwl_release_nic_access(priv);
977 spin_unlock_irqrestore(&priv->lock, flags);
978
979 return 0; 941 return 0;
980} 942}
981 943
982static int iwl3945_tx_reset(struct iwl_priv *priv) 944static int iwl3945_tx_reset(struct iwl_priv *priv)
983{ 945{
984 int rc;
985 unsigned long flags;
986
987 spin_lock_irqsave(&priv->lock, flags);
988 rc = iwl_grab_nic_access(priv);
989 if (rc) {
990 spin_unlock_irqrestore(&priv->lock, flags);
991 return rc;
992 }
993 946
994 /* bypass mode */ 947 /* bypass mode */
995 iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2); 948 iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
@@ -1017,8 +970,6 @@ static int iwl3945_tx_reset(struct iwl_priv *priv)
1017 FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | 970 FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
1018 FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); 971 FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
1019 972
1020 iwl_release_nic_access(priv);
1021 spin_unlock_irqrestore(&priv->lock, flags);
1022 973
1023 return 0; 974 return 0;
1024} 975}
@@ -1061,7 +1012,7 @@ static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
1061 1012
1062static int iwl3945_apm_init(struct iwl_priv *priv) 1013static int iwl3945_apm_init(struct iwl_priv *priv)
1063{ 1014{
1064 int ret = 0; 1015 int ret;
1065 1016
1066 iwl_power_initialize(priv); 1017 iwl_power_initialize(priv);
1067 1018
@@ -1083,10 +1034,6 @@ static int iwl3945_apm_init(struct iwl_priv *priv)
1083 goto out; 1034 goto out;
1084 } 1035 }
1085 1036
1086 ret = iwl_grab_nic_access(priv);
1087 if (ret)
1088 goto out;
1089
1090 /* enable DMA */ 1037 /* enable DMA */
1091 iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | 1038 iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
1092 APMG_CLK_VAL_BSM_CLK_RQT); 1039 APMG_CLK_VAL_BSM_CLK_RQT);
@@ -1097,7 +1044,6 @@ static int iwl3945_apm_init(struct iwl_priv *priv)
1097 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, 1044 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
1098 APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 1045 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
1099 1046
1100 iwl_release_nic_access(priv);
1101out: 1047out:
1102 return ret; 1048 return ret;
1103} 1049}
@@ -1196,22 +1142,13 @@ int iwl3945_hw_nic_init(struct iwl_priv *priv)
1196 1142
1197 iwl3945_rx_init(priv, rxq); 1143 iwl3945_rx_init(priv, rxq);
1198 1144
1199 spin_lock_irqsave(&priv->lock, flags);
1200 1145
1201 /* Look at using this instead: 1146 /* Look at using this instead:
1202 rxq->need_update = 1; 1147 rxq->need_update = 1;
1203 iwl_rx_queue_update_write_ptr(priv, rxq); 1148 iwl_rx_queue_update_write_ptr(priv, rxq);
1204 */ 1149 */
1205 1150
1206 rc = iwl_grab_nic_access(priv);
1207 if (rc) {
1208 spin_unlock_irqrestore(&priv->lock, flags);
1209 return rc;
1210 }
1211 iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); 1151 iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
1212 iwl_release_nic_access(priv);
1213
1214 spin_unlock_irqrestore(&priv->lock, flags);
1215 1152
1216 rc = iwl3945_txq_ctx_reset(priv); 1153 rc = iwl3945_txq_ctx_reset(priv);
1217 if (rc) 1154 if (rc)
@@ -1243,14 +1180,6 @@ void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
1243void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) 1180void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
1244{ 1181{
1245 int txq_id; 1182 int txq_id;
1246 unsigned long flags;
1247
1248 spin_lock_irqsave(&priv->lock, flags);
1249 if (iwl_grab_nic_access(priv)) {
1250 spin_unlock_irqrestore(&priv->lock, flags);
1251 iwl3945_hw_txq_ctx_free(priv);
1252 return;
1253 }
1254 1183
1255 /* stop SCD */ 1184 /* stop SCD */
1256 iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); 1185 iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
@@ -1263,9 +1192,6 @@ void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
1263 1000); 1192 1000);
1264 } 1193 }
1265 1194
1266 iwl_release_nic_access(priv);
1267 spin_unlock_irqrestore(&priv->lock, flags);
1268
1269 iwl3945_hw_txq_ctx_free(priv); 1195 iwl3945_hw_txq_ctx_free(priv);
1270} 1196}
1271 1197
@@ -1310,12 +1236,8 @@ static void iwl3945_apm_stop(struct iwl_priv *priv)
1310 1236
1311static int iwl3945_apm_reset(struct iwl_priv *priv) 1237static int iwl3945_apm_reset(struct iwl_priv *priv)
1312{ 1238{
1313 int rc;
1314 unsigned long flags;
1315
1316 iwl3945_apm_stop_master(priv); 1239 iwl3945_apm_stop_master(priv);
1317 1240
1318 spin_lock_irqsave(&priv->lock, flags);
1319 1241
1320 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); 1242 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
1321 udelay(10); 1243 udelay(10);
@@ -1325,36 +1247,31 @@ static int iwl3945_apm_reset(struct iwl_priv *priv)
1325 iwl_poll_direct_bit(priv, CSR_GP_CNTRL, 1247 iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
1326 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); 1248 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
1327 1249
1328 rc = iwl_grab_nic_access(priv); 1250 iwl_write_prph(priv, APMG_CLK_CTRL_REG,
1329 if (!rc) { 1251 APMG_CLK_VAL_BSM_CLK_RQT);
1330 iwl_write_prph(priv, APMG_CLK_CTRL_REG,
1331 APMG_CLK_VAL_BSM_CLK_RQT);
1332 1252
1333 iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); 1253 iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
1334 iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 1254 iwl_write_prph(priv, APMG_RTC_INT_STT_REG,
1335 0xFFFFFFFF); 1255 0xFFFFFFFF);
1336 1256
1337 /* enable DMA */ 1257 /* enable DMA */
1338 iwl_write_prph(priv, APMG_CLK_EN_REG, 1258 iwl_write_prph(priv, APMG_CLK_EN_REG,
1339 APMG_CLK_VAL_DMA_CLK_RQT | 1259 APMG_CLK_VAL_DMA_CLK_RQT |
1340 APMG_CLK_VAL_BSM_CLK_RQT); 1260 APMG_CLK_VAL_BSM_CLK_RQT);
1341 udelay(10); 1261 udelay(10);
1342 1262
1343 iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, 1263 iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
1344 APMG_PS_CTRL_VAL_RESET_REQ); 1264 APMG_PS_CTRL_VAL_RESET_REQ);
1345 udelay(5); 1265 udelay(5);
1346 iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, 1266 iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
1347 APMG_PS_CTRL_VAL_RESET_REQ); 1267 APMG_PS_CTRL_VAL_RESET_REQ);
1348 iwl_release_nic_access(priv);
1349 }
1350 1268
1351 /* Clear the 'host command active' bit... */ 1269 /* Clear the 'host command active' bit... */
1352 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 1270 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
1353 1271
1354 wake_up_interruptible(&priv->wait_command_queue); 1272 wake_up_interruptible(&priv->wait_command_queue);
1355 spin_unlock_irqrestore(&priv->lock, flags);
1356 1273
1357 return rc; 1274 return 0;
1358} 1275}
1359 1276
1360/** 1277/**
@@ -2500,14 +2417,6 @@ int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
2500int iwl3945_hw_rxq_stop(struct iwl_priv *priv) 2417int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
2501{ 2418{
2502 int rc; 2419 int rc;
2503 unsigned long flags;
2504
2505 spin_lock_irqsave(&priv->lock, flags);
2506 rc = iwl_grab_nic_access(priv);
2507 if (rc) {
2508 spin_unlock_irqrestore(&priv->lock, flags);
2509 return rc;
2510 }
2511 2420
2512 iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); 2421 iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
2513 rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS, 2422 rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
@@ -2515,28 +2424,17 @@ int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
2515 if (rc < 0) 2424 if (rc < 0)
2516 IWL_ERR(priv, "Can't stop Rx DMA.\n"); 2425 IWL_ERR(priv, "Can't stop Rx DMA.\n");
2517 2426
2518 iwl_release_nic_access(priv);
2519 spin_unlock_irqrestore(&priv->lock, flags);
2520
2521 return 0; 2427 return 0;
2522} 2428}
2523 2429
2524int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) 2430int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
2525{ 2431{
2526 int rc;
2527 unsigned long flags;
2528 int txq_id = txq->q.id; 2432 int txq_id = txq->q.id;
2529 2433
2530 struct iwl3945_shared *shared_data = priv->shared_virt; 2434 struct iwl3945_shared *shared_data = priv->shared_virt;
2531 2435
2532 shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); 2436 shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
2533 2437
2534 spin_lock_irqsave(&priv->lock, flags);
2535 rc = iwl_grab_nic_access(priv);
2536 if (rc) {
2537 spin_unlock_irqrestore(&priv->lock, flags);
2538 return rc;
2539 }
2540 iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); 2438 iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
2541 iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); 2439 iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
2542 2440
@@ -2546,11 +2444,9 @@ int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
2546 FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | 2444 FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD |
2547 FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | 2445 FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL |
2548 FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); 2446 FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE);
2549 iwl_release_nic_access(priv);
2550 2447
2551 /* fake read to flush all prev. writes */ 2448 /* fake read to flush all prev. writes */
2552 iwl_read32(priv, FH39_TSSR_CBB_BASE); 2449 iwl_read32(priv, FH39_TSSR_CBB_BASE);
2553 spin_unlock_irqrestore(&priv->lock, flags);
2554 2450
2555 return 0; 2451 return 0;
2556} 2452}
@@ -2858,10 +2754,6 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
2858 inst_len = priv->ucode_init.len; 2754 inst_len = priv->ucode_init.len;
2859 data_len = priv->ucode_init_data.len; 2755 data_len = priv->ucode_init_data.len;
2860 2756
2861 rc = iwl_grab_nic_access(priv);
2862 if (rc)
2863 return rc;
2864
2865 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); 2757 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
2866 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); 2758 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
2867 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); 2759 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
@@ -2875,10 +2767,8 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
2875 le32_to_cpu(*image)); 2767 le32_to_cpu(*image));
2876 2768
2877 rc = iwl3945_verify_bsm(priv); 2769 rc = iwl3945_verify_bsm(priv);
2878 if (rc) { 2770 if (rc)
2879 iwl_release_nic_access(priv);
2880 return rc; 2771 return rc;
2881 }
2882 2772
2883 /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ 2773 /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
2884 iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); 2774 iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
@@ -2910,8 +2800,6 @@ static int iwl3945_load_bsm(struct iwl_priv *priv)
2910 iwl_write_prph(priv, BSM_WR_CTRL_REG, 2800 iwl_write_prph(priv, BSM_WR_CTRL_REG,
2911 BSM_WR_CTRL_REG_BIT_START_EN); 2801 BSM_WR_CTRL_REG_BIT_START_EN);
2912 2802
2913 iwl_release_nic_access(priv);
2914
2915 return 0; 2803 return 0;
2916} 2804}
2917 2805
@@ -2950,6 +2838,7 @@ static struct iwl_lib_ops iwl3945_lib = {
2950 .send_tx_power = iwl3945_send_tx_power, 2838 .send_tx_power = iwl3945_send_tx_power,
2951 .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, 2839 .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
2952 .post_associate = iwl3945_post_associate, 2840 .post_associate = iwl3945_post_associate,
2841 .isr = iwl_isr_legacy,
2953 .config_ap = iwl3945_config_ap, 2842 .config_ap = iwl3945_config_ap,
2954}; 2843};
2955 2844
@@ -2983,7 +2872,8 @@ static struct iwl_cfg iwl3945_bg_cfg = {
2983 .eeprom_size = IWL3945_EEPROM_IMG_SIZE, 2872 .eeprom_size = IWL3945_EEPROM_IMG_SIZE,
2984 .eeprom_ver = EEPROM_3945_EEPROM_VERSION, 2873 .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
2985 .ops = &iwl3945_ops, 2874 .ops = &iwl3945_ops,
2986 .mod_params = &iwl3945_mod_params 2875 .mod_params = &iwl3945_mod_params,
2876 .use_isr_legacy = true
2987}; 2877};
2988 2878
2989static struct iwl_cfg iwl3945_abg_cfg = { 2879static struct iwl_cfg iwl3945_abg_cfg = {
@@ -2995,7 +2885,8 @@ static struct iwl_cfg iwl3945_abg_cfg = {
2995 .eeprom_size = IWL3945_EEPROM_IMG_SIZE, 2885 .eeprom_size = IWL3945_EEPROM_IMG_SIZE,
2996 .eeprom_ver = EEPROM_3945_EEPROM_VERSION, 2886 .eeprom_ver = EEPROM_3945_EEPROM_VERSION,
2997 .ops = &iwl3945_ops, 2887 .ops = &iwl3945_ops,
2998 .mod_params = &iwl3945_mod_params 2888 .mod_params = &iwl3945_mod_params,
2889 .use_isr_legacy = true
2999}; 2890};
3000 2891
3001struct pci_device_id iwl3945_hw_card_ids[] = { 2892struct pci_device_id iwl3945_hw_card_ids[] = {
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index a98ff4ead720..a0b29411a4b3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -163,10 +163,6 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
163 inst_len = priv->ucode_init.len; 163 inst_len = priv->ucode_init.len;
164 data_len = priv->ucode_init_data.len; 164 data_len = priv->ucode_init_data.len;
165 165
166 ret = iwl_grab_nic_access(priv);
167 if (ret)
168 return ret;
169
170 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); 166 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
171 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); 167 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
172 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); 168 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
@@ -179,10 +175,8 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
179 _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); 175 _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
180 176
181 ret = iwl4965_verify_bsm(priv); 177 ret = iwl4965_verify_bsm(priv);
182 if (ret) { 178 if (ret)
183 iwl_release_nic_access(priv);
184 return ret; 179 return ret;
185 }
186 180
187 /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ 181 /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
188 iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); 182 iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
@@ -211,7 +205,6 @@ static int iwl4965_load_bsm(struct iwl_priv *priv)
211 * (e.g. when powering back up after power-save shutdown) */ 205 * (e.g. when powering back up after power-save shutdown) */
212 iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); 206 iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
213 207
214 iwl_release_nic_access(priv);
215 208
216 return 0; 209 return 0;
217} 210}
@@ -229,20 +222,12 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
229{ 222{
230 dma_addr_t pinst; 223 dma_addr_t pinst;
231 dma_addr_t pdata; 224 dma_addr_t pdata;
232 unsigned long flags;
233 int ret = 0; 225 int ret = 0;
234 226
235 /* bits 35:4 for 4965 */ 227 /* bits 35:4 for 4965 */
236 pinst = priv->ucode_code.p_addr >> 4; 228 pinst = priv->ucode_code.p_addr >> 4;
237 pdata = priv->ucode_data_backup.p_addr >> 4; 229 pdata = priv->ucode_data_backup.p_addr >> 4;
238 230
239 spin_lock_irqsave(&priv->lock, flags);
240 ret = iwl_grab_nic_access(priv);
241 if (ret) {
242 spin_unlock_irqrestore(&priv->lock, flags);
243 return ret;
244 }
245
246 /* Tell bootstrap uCode where to find image to load */ 231 /* Tell bootstrap uCode where to find image to load */
247 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); 232 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
248 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); 233 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
@@ -253,10 +238,6 @@ static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
253 * that all new ptr/size info is in place */ 238 * that all new ptr/size info is in place */
254 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, 239 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
255 priv->ucode_code.len | BSM_DRAM_INST_LOAD); 240 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
256 iwl_release_nic_access(priv);
257
258 spin_unlock_irqrestore(&priv->lock, flags);
259
260 IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); 241 IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
261 242
262 return ret; 243 return ret;
@@ -312,10 +293,12 @@ restart:
312 queue_work(priv->workqueue, &priv->restart); 293 queue_work(priv->workqueue, &priv->restart);
313} 294}
314 295
315static int is_fat_channel(__le32 rxon_flags) 296static bool is_fat_channel(__le32 rxon_flags)
316{ 297{
317 return (rxon_flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) || 298 int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK)
318 (rxon_flags & RXON_FLG_CHANNEL_MODE_MIXED_MSK); 299 >> RXON_FLG_CHANNEL_MODE_POS;
300 return ((chan_mod == CHANNEL_MODE_PURE_40) ||
301 (chan_mod == CHANNEL_MODE_MIXED));
319} 302}
320 303
321/* 304/*
@@ -358,10 +341,6 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
358 goto out; 341 goto out;
359 } 342 }
360 343
361 ret = iwl_grab_nic_access(priv);
362 if (ret)
363 goto out;
364
365 /* enable DMA */ 344 /* enable DMA */
366 iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | 345 iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT |
367 APMG_CLK_VAL_BSM_CLK_RQT); 346 APMG_CLK_VAL_BSM_CLK_RQT);
@@ -372,7 +351,6 @@ static int iwl4965_apm_init(struct iwl_priv *priv)
372 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, 351 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
373 APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 352 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
374 353
375 iwl_release_nic_access(priv);
376out: 354out:
377 return ret; 355 return ret;
378} 356}
@@ -454,11 +432,9 @@ static void iwl4965_apm_stop(struct iwl_priv *priv)
454static int iwl4965_apm_reset(struct iwl_priv *priv) 432static int iwl4965_apm_reset(struct iwl_priv *priv)
455{ 433{
456 int ret = 0; 434 int ret = 0;
457 unsigned long flags;
458 435
459 iwl4965_apm_stop_master(priv); 436 iwl4965_apm_stop_master(priv);
460 437
461 spin_lock_irqsave(&priv->lock, flags);
462 438
463 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); 439 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
464 440
@@ -475,9 +451,6 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
475 451
476 udelay(10); 452 udelay(10);
477 453
478 ret = iwl_grab_nic_access(priv);
479 if (ret)
480 goto out;
481 /* Enable DMA and BSM Clock */ 454 /* Enable DMA and BSM Clock */
482 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | 455 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT |
483 APMG_CLK_VAL_BSM_CLK_RQT); 456 APMG_CLK_VAL_BSM_CLK_RQT);
@@ -488,14 +461,10 @@ static int iwl4965_apm_reset(struct iwl_priv *priv)
488 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, 461 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
489 APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 462 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
490 463
491 iwl_release_nic_access(priv);
492
493 clear_bit(STATUS_HCMD_ACTIVE, &priv->status); 464 clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
494 wake_up_interruptible(&priv->wait_command_queue); 465 wake_up_interruptible(&priv->wait_command_queue);
495 466
496out: 467out:
497 spin_unlock_irqrestore(&priv->lock, flags);
498
499 return ret; 468 return ret;
500} 469}
501 470
@@ -681,18 +650,11 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
681{ 650{
682 u32 a; 651 u32 a;
683 unsigned long flags; 652 unsigned long flags;
684 int ret;
685 int i, chan; 653 int i, chan;
686 u32 reg_val; 654 u32 reg_val;
687 655
688 spin_lock_irqsave(&priv->lock, flags); 656 spin_lock_irqsave(&priv->lock, flags);
689 657
690 ret = iwl_grab_nic_access(priv);
691 if (ret) {
692 spin_unlock_irqrestore(&priv->lock, flags);
693 return ret;
694 }
695
696 /* Clear 4965's internal Tx Scheduler data base */ 658 /* Clear 4965's internal Tx Scheduler data base */
697 priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR); 659 priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR);
698 a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET; 660 a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET;
@@ -759,10 +721,9 @@ static int iwl4965_alive_notify(struct iwl_priv *priv)
759 iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); 721 iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
760 } 722 }
761 723
762 iwl_release_nic_access(priv);
763 spin_unlock_irqrestore(&priv->lock, flags); 724 spin_unlock_irqrestore(&priv->lock, flags);
764 725
765 return ret; 726 return 0;
766} 727}
767 728
768static struct iwl_sensitivity_ranges iwl4965_sensitivity = { 729static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
@@ -788,6 +749,12 @@ static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
788 .nrg_th_ofdm = 100, 749 .nrg_th_ofdm = 100,
789}; 750};
790 751
752static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
753{
754 /* want Kelvin */
755 priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD);
756}
757
791/** 758/**
792 * iwl4965_hw_set_hw_params 759 * iwl4965_hw_set_hw_params
793 * 760 *
@@ -822,7 +789,8 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
822 priv->hw_params.rx_chains_num = 2; 789 priv->hw_params.rx_chains_num = 2;
823 priv->hw_params.valid_tx_ant = ANT_A | ANT_B; 790 priv->hw_params.valid_tx_ant = ANT_A | ANT_B;
824 priv->hw_params.valid_rx_ant = ANT_A | ANT_B; 791 priv->hw_params.valid_rx_ant = ANT_A | ANT_B;
825 priv->hw_params.ct_kill_threshold = CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD); 792 if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
793 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
826 794
827 priv->hw_params.sens = &iwl4965_sensitivity; 795 priv->hw_params.sens = &iwl4965_sensitivity;
828 796
@@ -1524,7 +1492,7 @@ static int iwl4965_send_tx_power(struct iwl_priv *priv)
1524 struct iwl4965_txpowertable_cmd cmd = { 0 }; 1492 struct iwl4965_txpowertable_cmd cmd = { 0 };
1525 int ret; 1493 int ret;
1526 u8 band = 0; 1494 u8 band = 0;
1527 u8 is_fat = 0; 1495 bool is_fat = false;
1528 u8 ctrl_chan_high = 0; 1496 u8 ctrl_chan_high = 0;
1529 1497
1530 if (test_bit(STATUS_SCANNING, &priv->status)) { 1498 if (test_bit(STATUS_SCANNING, &priv->status)) {
@@ -1602,7 +1570,7 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel)
1602{ 1570{
1603 int rc; 1571 int rc;
1604 u8 band = 0; 1572 u8 band = 0;
1605 u8 is_fat = 0; 1573 bool is_fat = false;
1606 u8 ctrl_chan_high = 0; 1574 u8 ctrl_chan_high = 0;
1607 struct iwl4965_channel_switch_cmd cmd = { 0 }; 1575 struct iwl4965_channel_switch_cmd cmd = { 0 };
1608 const struct iwl_channel_info *ch_info; 1576 const struct iwl_channel_info *ch_info;
@@ -1833,8 +1801,6 @@ static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
1833static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, 1801static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1834 u16 ssn_idx, u8 tx_fifo) 1802 u16 ssn_idx, u8 tx_fifo)
1835{ 1803{
1836 int ret = 0;
1837
1838 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1804 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
1839 (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { 1805 (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
1840 IWL_WARN(priv, 1806 IWL_WARN(priv,
@@ -1844,10 +1810,6 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1844 return -EINVAL; 1810 return -EINVAL;
1845 } 1811 }
1846 1812
1847 ret = iwl_grab_nic_access(priv);
1848 if (ret)
1849 return ret;
1850
1851 iwl4965_tx_queue_stop_scheduler(priv, txq_id); 1813 iwl4965_tx_queue_stop_scheduler(priv, txq_id);
1852 1814
1853 iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); 1815 iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
@@ -1861,8 +1823,6 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1861 iwl_txq_ctx_deactivate(priv, txq_id); 1823 iwl_txq_ctx_deactivate(priv, txq_id);
1862 iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); 1824 iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
1863 1825
1864 iwl_release_nic_access(priv);
1865
1866 return 0; 1826 return 0;
1867} 1827}
1868 1828
@@ -1904,7 +1864,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1904 int tx_fifo, int sta_id, int tid, u16 ssn_idx) 1864 int tx_fifo, int sta_id, int tid, u16 ssn_idx)
1905{ 1865{
1906 unsigned long flags; 1866 unsigned long flags;
1907 int ret;
1908 u16 ra_tid; 1867 u16 ra_tid;
1909 1868
1910 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || 1869 if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
@@ -1922,11 +1881,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1922 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 1881 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
1923 1882
1924 spin_lock_irqsave(&priv->lock, flags); 1883 spin_lock_irqsave(&priv->lock, flags);
1925 ret = iwl_grab_nic_access(priv);
1926 if (ret) {
1927 spin_unlock_irqrestore(&priv->lock, flags);
1928 return ret;
1929 }
1930 1884
1931 /* Stop this Tx queue before configuring it */ 1885 /* Stop this Tx queue before configuring it */
1932 iwl4965_tx_queue_stop_scheduler(priv, txq_id); 1886 iwl4965_tx_queue_stop_scheduler(priv, txq_id);
@@ -1959,7 +1913,6 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1959 /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ 1913 /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
1960 iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); 1914 iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
1961 1915
1962 iwl_release_nic_access(priv);
1963 spin_unlock_irqrestore(&priv->lock, flags); 1916 spin_unlock_irqrestore(&priv->lock, flags);
1964 1917
1965 return 0; 1918 return 0;
@@ -2331,9 +2284,13 @@ static struct iwl_lib_ops iwl4965_lib = {
2331 }, 2284 },
2332 .send_tx_power = iwl4965_send_tx_power, 2285 .send_tx_power = iwl4965_send_tx_power,
2333 .update_chain_flags = iwl_update_chain_flags, 2286 .update_chain_flags = iwl_update_chain_flags,
2334 .temperature = iwl4965_temperature_calib,
2335 .post_associate = iwl_post_associate, 2287 .post_associate = iwl_post_associate,
2336 .config_ap = iwl_config_ap, 2288 .config_ap = iwl_config_ap,
2289 .isr = iwl_isr_legacy,
2290 .temp_ops = {
2291 .temperature = iwl4965_temperature_calib,
2292 .set_ct_kill = iwl4965_set_ct_threshold,
2293 },
2337}; 2294};
2338 2295
2339static struct iwl_ops iwl4965_ops = { 2296static struct iwl_ops iwl4965_ops = {
@@ -2354,6 +2311,7 @@ struct iwl_cfg iwl4965_agn_cfg = {
2354 .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, 2311 .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
2355 .ops = &iwl4965_ops, 2312 .ops = &iwl4965_ops,
2356 .mod_params = &iwl4965_mod_params, 2313 .mod_params = &iwl4965_mod_params,
2314 .use_isr_legacy = true
2357}; 2315};
2358 2316
2359/* Module firmware */ 2317/* Module firmware */
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
index 15cac70e36e2..4ef6804a455a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h
@@ -87,6 +87,18 @@
87#define IWL50_NUM_AMPDU_QUEUES 10 87#define IWL50_NUM_AMPDU_QUEUES 10
88#define IWL50_FIRST_AMPDU_QUEUE 10 88#define IWL50_FIRST_AMPDU_QUEUE 10
89 89
90/* 5150 only */
91#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5)
92
93static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv)
94{
95 u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv,
96 EEPROM_5000_TEMPERATURE);
97 /* offset = temperature - voltage / coef */
98 s32 offset = (s32)(temp_calib[0] - temp_calib[1] / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
99 return offset;
100}
101
90/* Fixed (non-configurable) rx data from phy */ 102/* Fixed (non-configurable) rx data from phy */
91 103
92/** 104/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index d731a836e6c8..89e1477b5143 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -124,10 +124,6 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
124 return ret; 124 return ret;
125 } 125 }
126 126
127 ret = iwl_grab_nic_access(priv);
128 if (ret)
129 return ret;
130
131 /* enable DMA */ 127 /* enable DMA */
132 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); 128 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
133 129
@@ -137,8 +133,6 @@ static int iwl5000_apm_init(struct iwl_priv *priv)
137 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, 133 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
138 APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 134 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
139 135
140 iwl_release_nic_access(priv);
141
142 return ret; 136 return ret;
143} 137}
144 138
@@ -165,12 +159,9 @@ static void iwl5000_apm_stop(struct iwl_priv *priv)
165static int iwl5000_apm_reset(struct iwl_priv *priv) 159static int iwl5000_apm_reset(struct iwl_priv *priv)
166{ 160{
167 int ret = 0; 161 int ret = 0;
168 unsigned long flags;
169 162
170 iwl5000_apm_stop_master(priv); 163 iwl5000_apm_stop_master(priv);
171 164
172 spin_lock_irqsave(&priv->lock, flags);
173
174 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); 165 iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
175 166
176 udelay(10); 167 udelay(10);
@@ -193,10 +184,6 @@ static int iwl5000_apm_reset(struct iwl_priv *priv)
193 goto out; 184 goto out;
194 } 185 }
195 186
196 ret = iwl_grab_nic_access(priv);
197 if (ret)
198 goto out;
199
200 /* enable DMA */ 187 /* enable DMA */
201 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); 188 iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT);
202 189
@@ -205,11 +192,7 @@ static int iwl5000_apm_reset(struct iwl_priv *priv)
205 /* disable L1-Active */ 192 /* disable L1-Active */
206 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, 193 iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
207 APMG_PCIDEV_STT_VAL_L1_ACT_DIS); 194 APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
208
209 iwl_release_nic_access(priv);
210
211out: 195out:
212 spin_unlock_irqrestore(&priv->lock, flags);
213 196
214 return ret; 197 return ret;
215} 198}
@@ -252,11 +235,9 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
252 * (PCIe power is lost before PERST# is asserted), 235 * (PCIe power is lost before PERST# is asserted),
253 * causing ME FW to lose ownership and not being able to obtain it back. 236 * causing ME FW to lose ownership and not being able to obtain it back.
254 */ 237 */
255 iwl_grab_nic_access(priv);
256 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, 238 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
257 APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, 239 APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
258 ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); 240 ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
259 iwl_release_nic_access(priv);
260 241
261 spin_unlock_irqrestore(&priv->lock, flags); 242 spin_unlock_irqrestore(&priv->lock, flags);
262} 243}
@@ -434,15 +415,19 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
434 return &priv->eeprom[address]; 415 return &priv->eeprom[address];
435} 416}
436 417
437static s32 iwl5150_get_ct_threshold(struct iwl_priv *priv) 418static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
438{ 419{
439 const s32 volt2temp_coef = -5; 420 const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
440 u16 *temp_calib = (u16 *)iwl_eeprom_query_addr(priv, 421 s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) -
441 EEPROM_5000_TEMPERATURE); 422 iwl_temp_calib_to_offset(priv);
442 /* offset = temperate - voltage / coef */ 423
443 s32 offset = temp_calib[0] - temp_calib[1] / volt2temp_coef; 424 priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
444 s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD) - offset; 425}
445 return threshold * volt2temp_coef; 426
427static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
428{
429 /* want Celsius */
430 priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
446} 431}
447 432
448/* 433/*
@@ -533,19 +518,9 @@ static int iwl5000_load_section(struct iwl_priv *priv,
533 struct fw_desc *image, 518 struct fw_desc *image,
534 u32 dst_addr) 519 u32 dst_addr)
535{ 520{
536 int ret = 0;
537 unsigned long flags;
538
539 dma_addr_t phy_addr = image->p_addr; 521 dma_addr_t phy_addr = image->p_addr;
540 u32 byte_cnt = image->len; 522 u32 byte_cnt = image->len;
541 523
542 spin_lock_irqsave(&priv->lock, flags);
543 ret = iwl_grab_nic_access(priv);
544 if (ret) {
545 spin_unlock_irqrestore(&priv->lock, flags);
546 return ret;
547 }
548
549 iwl_write_direct32(priv, 524 iwl_write_direct32(priv,
550 FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), 525 FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL),
551 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); 526 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE);
@@ -574,8 +549,6 @@ static int iwl5000_load_section(struct iwl_priv *priv,
574 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | 549 FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE |
575 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); 550 FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD);
576 551
577 iwl_release_nic_access(priv);
578 spin_unlock_irqrestore(&priv->lock, flags);
579 return 0; 552 return 0;
580} 553}
581 554
@@ -736,18 +709,11 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
736{ 709{
737 u32 a; 710 u32 a;
738 unsigned long flags; 711 unsigned long flags;
739 int ret;
740 int i, chan; 712 int i, chan;
741 u32 reg_val; 713 u32 reg_val;
742 714
743 spin_lock_irqsave(&priv->lock, flags); 715 spin_lock_irqsave(&priv->lock, flags);
744 716
745 ret = iwl_grab_nic_access(priv);
746 if (ret) {
747 spin_unlock_irqrestore(&priv->lock, flags);
748 return ret;
749 }
750
751 priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); 717 priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR);
752 a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; 718 a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET;
753 for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; 719 for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET;
@@ -815,7 +781,6 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
815 iwl_txq_ctx_activate(priv, 8); 781 iwl_txq_ctx_activate(priv, 8);
816 iwl_txq_ctx_activate(priv, 9); 782 iwl_txq_ctx_activate(priv, 9);
817 783
818 iwl_release_nic_access(priv);
819 spin_unlock_irqrestore(&priv->lock, flags); 784 spin_unlock_irqrestore(&priv->lock, flags);
820 785
821 786
@@ -868,17 +833,8 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
868 priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; 833 priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
869 priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; 834 priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
870 835
871 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { 836 if (priv->cfg->ops->lib->temp_ops.set_ct_kill)
872 case CSR_HW_REV_TYPE_5150: 837 priv->cfg->ops->lib->temp_ops.set_ct_kill(priv);
873 /* 5150 wants in Kelvin */
874 priv->hw_params.ct_kill_threshold =
875 iwl5150_get_ct_threshold(priv);
876 break;
877 default:
878 /* all others want Celsius */
879 priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
880 break;
881 }
882 838
883 /* Set initial calibration set */ 839 /* Set initial calibration set */
884 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { 840 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
@@ -900,7 +856,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
900 break; 856 break;
901 } 857 }
902 858
903
904 return 0; 859 return 0;
905} 860}
906 861
@@ -1006,7 +961,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1006 int tx_fifo, int sta_id, int tid, u16 ssn_idx) 961 int tx_fifo, int sta_id, int tid, u16 ssn_idx)
1007{ 962{
1008 unsigned long flags; 963 unsigned long flags;
1009 int ret;
1010 u16 ra_tid; 964 u16 ra_tid;
1011 965
1012 if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || 966 if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
@@ -1024,11 +978,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1024 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); 978 iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
1025 979
1026 spin_lock_irqsave(&priv->lock, flags); 980 spin_lock_irqsave(&priv->lock, flags);
1027 ret = iwl_grab_nic_access(priv);
1028 if (ret) {
1029 spin_unlock_irqrestore(&priv->lock, flags);
1030 return ret;
1031 }
1032 981
1033 /* Stop this Tx queue before configuring it */ 982 /* Stop this Tx queue before configuring it */
1034 iwl5000_tx_queue_stop_scheduler(priv, txq_id); 983 iwl5000_tx_queue_stop_scheduler(priv, txq_id);
@@ -1064,7 +1013,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1064 /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ 1013 /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */
1065 iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); 1014 iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1);
1066 1015
1067 iwl_release_nic_access(priv);
1068 spin_unlock_irqrestore(&priv->lock, flags); 1016 spin_unlock_irqrestore(&priv->lock, flags);
1069 1017
1070 return 0; 1018 return 0;
@@ -1073,8 +1021,6 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
1073static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, 1021static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1074 u16 ssn_idx, u8 tx_fifo) 1022 u16 ssn_idx, u8 tx_fifo)
1075{ 1023{
1076 int ret;
1077
1078 if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || 1024 if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
1079 (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { 1025 (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
1080 IWL_ERR(priv, 1026 IWL_ERR(priv,
@@ -1084,10 +1030,6 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1084 return -EINVAL; 1030 return -EINVAL;
1085 } 1031 }
1086 1032
1087 ret = iwl_grab_nic_access(priv);
1088 if (ret)
1089 return ret;
1090
1091 iwl5000_tx_queue_stop_scheduler(priv, txq_id); 1033 iwl5000_tx_queue_stop_scheduler(priv, txq_id);
1092 1034
1093 iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); 1035 iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id));
@@ -1101,8 +1043,6 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
1101 iwl_txq_ctx_deactivate(priv, txq_id); 1043 iwl_txq_ctx_deactivate(priv, txq_id);
1102 iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); 1044 iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
1103 1045
1104 iwl_release_nic_access(priv);
1105
1106 return 0; 1046 return 0;
1107} 1047}
1108 1048
@@ -1434,6 +1374,17 @@ static void iwl5000_temperature(struct iwl_priv *priv)
1434 priv->temperature = le32_to_cpu(priv->statistics.general.temperature); 1374 priv->temperature = le32_to_cpu(priv->statistics.general.temperature);
1435} 1375}
1436 1376
1377static void iwl5150_temperature(struct iwl_priv *priv)
1378{
1379 u32 vt = 0;
1380 s32 offset = iwl_temp_calib_to_offset(priv);
1381
1382 vt = le32_to_cpu(priv->statistics.general.temperature);
1383 vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
1384 /* now vt hold the temperature in Kelvin */
1385 priv->temperature = KELVIN_TO_CELSIUS(vt);
1386}
1387
1437/* Calc max signal level (dBm) among 3 possible receivers */ 1388/* Calc max signal level (dBm) among 3 possible receivers */
1438int iwl5000_calc_rssi(struct iwl_priv *priv, 1389int iwl5000_calc_rssi(struct iwl_priv *priv,
1439 struct iwl_rx_phy_res *rx_resp) 1390 struct iwl_rx_phy_res *rx_resp)
@@ -1511,7 +1462,6 @@ struct iwl_lib_ops iwl5000_lib = {
1511 .init_alive_start = iwl5000_init_alive_start, 1462 .init_alive_start = iwl5000_init_alive_start,
1512 .alive_notify = iwl5000_alive_notify, 1463 .alive_notify = iwl5000_alive_notify,
1513 .send_tx_power = iwl5000_send_tx_power, 1464 .send_tx_power = iwl5000_send_tx_power,
1514 .temperature = iwl5000_temperature,
1515 .update_chain_flags = iwl_update_chain_flags, 1465 .update_chain_flags = iwl_update_chain_flags,
1516 .apm_ops = { 1466 .apm_ops = {
1517 .init = iwl5000_apm_init, 1467 .init = iwl5000_apm_init,
@@ -1537,7 +1487,62 @@ struct iwl_lib_ops iwl5000_lib = {
1537 .query_addr = iwl5000_eeprom_query_addr, 1487 .query_addr = iwl5000_eeprom_query_addr,
1538 }, 1488 },
1539 .post_associate = iwl_post_associate, 1489 .post_associate = iwl_post_associate,
1490 .isr = iwl_isr_ict,
1540 .config_ap = iwl_config_ap, 1491 .config_ap = iwl_config_ap,
1492 .temp_ops = {
1493 .temperature = iwl5000_temperature,
1494 .set_ct_kill = iwl5000_set_ct_threshold,
1495 },
1496};
1497
1498static struct iwl_lib_ops iwl5150_lib = {
1499 .set_hw_params = iwl5000_hw_set_hw_params,
1500 .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl,
1501 .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl,
1502 .txq_set_sched = iwl5000_txq_set_sched,
1503 .txq_agg_enable = iwl5000_txq_agg_enable,
1504 .txq_agg_disable = iwl5000_txq_agg_disable,
1505 .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
1506 .txq_free_tfd = iwl_hw_txq_free_tfd,
1507 .txq_init = iwl_hw_tx_queue_init,
1508 .rx_handler_setup = iwl5000_rx_handler_setup,
1509 .setup_deferred_work = iwl5000_setup_deferred_work,
1510 .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr,
1511 .load_ucode = iwl5000_load_ucode,
1512 .init_alive_start = iwl5000_init_alive_start,
1513 .alive_notify = iwl5000_alive_notify,
1514 .send_tx_power = iwl5000_send_tx_power,
1515 .update_chain_flags = iwl_update_chain_flags,
1516 .apm_ops = {
1517 .init = iwl5000_apm_init,
1518 .reset = iwl5000_apm_reset,
1519 .stop = iwl5000_apm_stop,
1520 .config = iwl5000_nic_config,
1521 .set_pwr_src = iwl_set_pwr_src,
1522 },
1523 .eeprom_ops = {
1524 .regulatory_bands = {
1525 EEPROM_5000_REG_BAND_1_CHANNELS,
1526 EEPROM_5000_REG_BAND_2_CHANNELS,
1527 EEPROM_5000_REG_BAND_3_CHANNELS,
1528 EEPROM_5000_REG_BAND_4_CHANNELS,
1529 EEPROM_5000_REG_BAND_5_CHANNELS,
1530 EEPROM_5000_REG_BAND_24_FAT_CHANNELS,
1531 EEPROM_5000_REG_BAND_52_FAT_CHANNELS
1532 },
1533 .verify_signature = iwlcore_eeprom_verify_signature,
1534 .acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
1535 .release_semaphore = iwlcore_eeprom_release_semaphore,
1536 .calib_version = iwl5000_eeprom_calib_version,
1537 .query_addr = iwl5000_eeprom_query_addr,
1538 },
1539 .post_associate = iwl_post_associate,
1540 .isr = iwl_isr_ict,
1541 .config_ap = iwl_config_ap,
1542 .temp_ops = {
1543 .temperature = iwl5150_temperature,
1544 .set_ct_kill = iwl5150_set_ct_threshold,
1545 },
1541}; 1546};
1542 1547
1543struct iwl_ops iwl5000_ops = { 1548struct iwl_ops iwl5000_ops = {
@@ -1547,6 +1552,13 @@ struct iwl_ops iwl5000_ops = {
1547 .smgmt = &iwl5000_station_mgmt, 1552 .smgmt = &iwl5000_station_mgmt,
1548}; 1553};
1549 1554
1555static struct iwl_ops iwl5150_ops = {
1556 .lib = &iwl5150_lib,
1557 .hcmd = &iwl5000_hcmd,
1558 .utils = &iwl5000_hcmd_utils,
1559 .smgmt = &iwl5000_station_mgmt,
1560};
1561
1550struct iwl_mod_params iwl50_mod_params = { 1562struct iwl_mod_params iwl50_mod_params = {
1551 .num_of_queues = IWL50_NUM_QUEUES, 1563 .num_of_queues = IWL50_NUM_QUEUES,
1552 .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, 1564 .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
@@ -1642,7 +1654,7 @@ struct iwl_cfg iwl5150_agn_cfg = {
1642 .ucode_api_max = IWL5150_UCODE_API_MAX, 1654 .ucode_api_max = IWL5150_UCODE_API_MAX,
1643 .ucode_api_min = IWL5150_UCODE_API_MIN, 1655 .ucode_api_min = IWL5150_UCODE_API_MIN,
1644 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, 1656 .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
1645 .ops = &iwl5000_ops, 1657 .ops = &iwl5150_ops,
1646 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, 1658 .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
1647 .eeprom_ver = EEPROM_5050_EEPROM_VERSION, 1659 .eeprom_ver = EEPROM_5050_EEPROM_VERSION,
1648 .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, 1660 .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 4c88e8715df2..23a58b00f180 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -270,6 +270,8 @@ const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
270 {"60", "64QAM 5/6"} 270 {"60", "64QAM 5/6"}
271}; 271};
272 272
273#define MCS_INDEX_PER_STREAM (8)
274
273static inline u8 rs_extract_rate(u32 rate_n_flags) 275static inline u8 rs_extract_rate(u32 rate_n_flags)
274{ 276{
275 return (u8)(rate_n_flags & 0xFF); 277 return (u8)(rate_n_flags & 0xFF);
@@ -652,19 +654,19 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
652 return 1; 654 return 1;
653} 655}
654 656
655/* FIXME:RS: in 4965 we don't use greenfield at all */ 657/* in 4965 we don't use greenfield at all */
656/* FIXME:RS: don't use greenfield for now in TX */ 658static inline u8 rs_use_green(struct iwl_priv *priv,
657#if 0 659 struct ieee80211_conf *conf)
658static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf)
659{
660 return (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) &&
661 priv->current_ht_config.is_green_field &&
662 !priv->current_ht_config.non_GF_STA_present;
663}
664#endif
665static inline u8 rs_use_green(struct iwl_priv *priv, struct ieee80211_conf *conf)
666{ 660{
667 return 0; 661 u8 is_green;
662
663 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
664 is_green = 0;
665 else
666 is_green = (conf_is_ht(conf) &&
667 priv->current_ht_config.is_green_field &&
668 !priv->current_ht_config.non_GF_STA_present);
669 return is_green;
668} 670}
669 671
670/** 672/**
@@ -2061,6 +2063,10 @@ static void rs_rate_scale_perform(struct iwl_priv *priv,
2061 active_tbl = 1 - lq_sta->active_tbl; 2063 active_tbl = 1 - lq_sta->active_tbl;
2062 2064
2063 tbl = &(lq_sta->lq_info[active_tbl]); 2065 tbl = &(lq_sta->lq_info[active_tbl]);
2066 if (is_legacy(tbl->lq_type))
2067 lq_sta->is_green = 0;
2068 else
2069 lq_sta->is_green = rs_use_green(priv, conf);
2064 is_green = lq_sta->is_green; 2070 is_green = lq_sta->is_green;
2065 2071
2066 /* current tx rate */ 2072 /* current tx rate */
@@ -2514,12 +2520,33 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
2514 } 2520 }
2515 } 2521 }
2516 2522
2517 if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT) 2523 if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) {
2518 rate_idx = rate_lowest_index(sband, sta);
2519 else if (sband->band == IEEE80211_BAND_5GHZ)
2520 rate_idx -= IWL_FIRST_OFDM_RATE; 2524 rate_idx -= IWL_FIRST_OFDM_RATE;
2521 2525 /* 6M and 9M shared same MCS index */
2526 rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0;
2527 if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
2528 IWL_RATE_MIMO3_6M_PLCP)
2529 rate_idx = rate_idx + (2 * MCS_INDEX_PER_STREAM);
2530 else if (rs_extract_rate(lq_sta->last_rate_n_flags) >=
2531 IWL_RATE_MIMO2_6M_PLCP)
2532 rate_idx = rate_idx + MCS_INDEX_PER_STREAM;
2533 info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
2534 if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK)
2535 info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI;
2536 if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK)
2537 info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA;
2538 if (lq_sta->last_rate_n_flags & RATE_MCS_FAT_MSK)
2539 info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
2540 if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK)
2541 info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD;
2542 } else {
2543 if (rate_idx < 0 || rate_idx > IWL_RATE_COUNT)
2544 rate_idx = rate_lowest_index(sband, sta);
2545 else if (sband->band == IEEE80211_BAND_5GHZ)
2546 rate_idx -= IWL_FIRST_OFDM_RATE;
2547 }
2522 info->control.rates[0].idx = rate_idx; 2548 info->control.rates[0].idx = rate_idx;
2549
2523} 2550}
2524 2551
2525static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, 2552static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
@@ -2896,7 +2923,8 @@ static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
2896 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); 2923 ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3"));
2897 desc += sprintf(buff+desc, " %s", 2924 desc += sprintf(buff+desc, " %s",
2898 (tbl->is_fat) ? "40MHz" : "20MHz"); 2925 (tbl->is_fat) ? "40MHz" : "20MHz");
2899 desc += sprintf(buff+desc, " %s\n", (tbl->is_SGI) ? "SGI" : ""); 2926 desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "",
2927 (lq_sta->is_green) ? "GF enabled" : "");
2900 } 2928 }
2901 desc += sprintf(buff+desc, "last tx rate=0x%X\n", 2929 desc += sprintf(buff+desc, "last tx rate=0x%X\n",
2902 lq_sta->last_rate_n_flags); 2930 lq_sta->last_rate_n_flags);
@@ -2959,13 +2987,14 @@ static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
2959 return -ENOMEM; 2987 return -ENOMEM;
2960 2988
2961 for (i = 0; i < LQ_SIZE; i++) { 2989 for (i = 0; i < LQ_SIZE; i++) {
2962 desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d\n" 2990 desc += sprintf(buff+desc, "%s type=%d SGI=%d FAT=%d DUP=%d GF=%d\n"
2963 "rate=0x%X\n", 2991 "rate=0x%X\n",
2964 lq_sta->active_tbl == i ? "*" : "x", 2992 lq_sta->active_tbl == i ? "*" : "x",
2965 lq_sta->lq_info[i].lq_type, 2993 lq_sta->lq_info[i].lq_type,
2966 lq_sta->lq_info[i].is_SGI, 2994 lq_sta->lq_info[i].is_SGI,
2967 lq_sta->lq_info[i].is_fat, 2995 lq_sta->lq_info[i].is_fat,
2968 lq_sta->lq_info[i].is_dup, 2996 lq_sta->lq_info[i].is_dup,
2997 lq_sta->is_green,
2969 lq_sta->lq_info[i].current_rate); 2998 lq_sta->lq_info[i].current_rate);
2970 for (j = 0; j < IWL_RATE_COUNT; j++) { 2999 for (j = 0; j < IWL_RATE_COUNT; j++) {
2971 desc += sprintf(buff+desc, 3000 desc += sprintf(buff+desc,
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 596977d71c94..0a5507cbeb3f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -503,24 +503,12 @@ int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
503int iwl_hw_tx_queue_init(struct iwl_priv *priv, 503int iwl_hw_tx_queue_init(struct iwl_priv *priv,
504 struct iwl_tx_queue *txq) 504 struct iwl_tx_queue *txq)
505{ 505{
506 int ret;
507 unsigned long flags;
508 int txq_id = txq->q.id; 506 int txq_id = txq->q.id;
509 507
510 spin_lock_irqsave(&priv->lock, flags);
511 ret = iwl_grab_nic_access(priv);
512 if (ret) {
513 spin_unlock_irqrestore(&priv->lock, flags);
514 return ret;
515 }
516
517 /* Circular buffer (TFD queue in DRAM) physical base address */ 508 /* Circular buffer (TFD queue in DRAM) physical base address */
518 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), 509 iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
519 txq->q.dma_addr >> 8); 510 txq->q.dma_addr >> 8);
520 511
521 iwl_release_nic_access(priv);
522 spin_unlock_irqrestore(&priv->lock, flags);
523
524 return 0; 512 return 0;
525} 513}
526 514
@@ -709,6 +697,7 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
709 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; 697 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
710 u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); 698 u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
711 unsigned long status = priv->status; 699 unsigned long status = priv->status;
700 unsigned long reg_flags;
712 701
713 IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", 702 IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n",
714 (flags & HW_CARD_DISABLED) ? "Kill" : "On", 703 (flags & HW_CARD_DISABLED) ? "Kill" : "On",
@@ -720,32 +709,25 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
720 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, 709 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
721 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); 710 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
722 711
723 if (!iwl_grab_nic_access(priv)) { 712 iwl_write_direct32(priv, HBUS_TARG_MBX_C,
724 iwl_write_direct32( 713 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
725 priv, HBUS_TARG_MBX_C,
726 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
727
728 iwl_release_nic_access(priv);
729 }
730 714
731 if (!(flags & RXON_CARD_DISABLED)) { 715 if (!(flags & RXON_CARD_DISABLED)) {
732 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, 716 iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
733 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); 717 CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
734 if (!iwl_grab_nic_access(priv)) { 718 iwl_write_direct32(priv, HBUS_TARG_MBX_C,
735 iwl_write_direct32(
736 priv, HBUS_TARG_MBX_C,
737 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); 719 HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
738 720
739 iwl_release_nic_access(priv);
740 }
741 } 721 }
742 722
743 if (flags & RF_CARD_DISABLED) { 723 if (flags & RF_CARD_DISABLED) {
744 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, 724 iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
745 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); 725 CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
746 iwl_read32(priv, CSR_UCODE_DRV_GP1); 726 iwl_read32(priv, CSR_UCODE_DRV_GP1);
727 spin_lock_irqsave(&priv->reg_lock, reg_flags);
747 if (!iwl_grab_nic_access(priv)) 728 if (!iwl_grab_nic_access(priv))
748 iwl_release_nic_access(priv); 729 iwl_release_nic_access(priv);
730 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
749 } 731 }
750 } 732 }
751 733
@@ -774,14 +756,6 @@ static void iwl_rx_card_state_notif(struct iwl_priv *priv,
774 756
775int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) 757int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
776{ 758{
777 int ret;
778 unsigned long flags;
779
780 spin_lock_irqsave(&priv->lock, flags);
781 ret = iwl_grab_nic_access(priv);
782 if (ret)
783 goto err;
784
785 if (src == IWL_PWR_SRC_VAUX) { 759 if (src == IWL_PWR_SRC_VAUX) {
786 if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) 760 if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
787 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, 761 iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
@@ -793,10 +767,7 @@ int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src)
793 ~APMG_PS_CTRL_MSK_PWR_SRC); 767 ~APMG_PS_CTRL_MSK_PWR_SRC);
794 } 768 }
795 769
796 iwl_release_nic_access(priv); 770 return 0;
797err:
798 spin_unlock_irqrestore(&priv->lock, flags);
799 return ret;
800} 771}
801 772
802/** 773/**
@@ -860,6 +831,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
860 unsigned long flags; 831 unsigned long flags;
861 u8 fill_rx = 0; 832 u8 fill_rx = 0;
862 u32 count = 8; 833 u32 count = 8;
834 int total_empty;
863 835
864 /* uCode's read index (stored in shared DRAM) indicates the last Rx 836 /* uCode's read index (stored in shared DRAM) indicates the last Rx
865 * buffer that the driver may process (last buffer filled by ucode). */ 837 * buffer that the driver may process (last buffer filled by ucode). */
@@ -870,7 +842,12 @@ void iwl_rx_handle(struct iwl_priv *priv)
870 if (i == r) 842 if (i == r)
871 IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); 843 IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
872 844
873 if (iwl_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2)) 845 /* calculate total frames need to be restock after handling RX */
846 total_empty = r - priv->rxq.write_actual;
847 if (total_empty < 0)
848 total_empty += RX_QUEUE_SIZE;
849
850 if (total_empty > (RX_QUEUE_SIZE / 2))
874 fill_rx = 1; 851 fill_rx = 1;
875 852
876 while (i != r) { 853 while (i != r) {
@@ -947,7 +924,7 @@ void iwl_rx_handle(struct iwl_priv *priv)
947 count++; 924 count++;
948 if (count >= 8) { 925 if (count >= 8) {
949 priv->rxq.read = i; 926 priv->rxq.read = i;
950 iwl_rx_queue_restock(priv); 927 iwl_rx_replenish_now(priv);
951 count = 0; 928 count = 0;
952 } 929 }
953 } 930 }
@@ -955,7 +932,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
955 932
956 /* Backtrack one entry */ 933 /* Backtrack one entry */
957 priv->rxq.read = i; 934 priv->rxq.read = i;
958 iwl_rx_queue_restock(priv); 935 if (fill_rx)
936 iwl_rx_replenish_now(priv);
937 else
938 iwl_rx_queue_restock(priv);
959} 939}
960 940
961/* call this function to flush any scheduled tasklet */ 941/* call this function to flush any scheduled tasklet */
@@ -966,7 +946,7 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv)
966 tasklet_kill(&priv->irq_tasklet); 946 tasklet_kill(&priv->irq_tasklet);
967} 947}
968 948
969static void iwl_irq_tasklet(struct iwl_priv *priv) 949static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
970{ 950{
971 u32 inta, handled = 0; 951 u32 inta, handled = 0;
972 u32 inta_fh; 952 u32 inta_fh;
@@ -1127,9 +1107,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1127 priv->isr_stats.unhandled++; 1107 priv->isr_stats.unhandled++;
1128 } 1108 }
1129 1109
1130 if (inta & ~CSR_INI_SET_MASK) { 1110 if (inta & ~(priv->inta_mask)) {
1131 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", 1111 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1132 inta & ~CSR_INI_SET_MASK); 1112 inta & ~priv->inta_mask);
1133 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); 1113 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh);
1134 } 1114 }
1135 1115
@@ -1150,6 +1130,199 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
1150 spin_unlock_irqrestore(&priv->lock, flags); 1130 spin_unlock_irqrestore(&priv->lock, flags);
1151} 1131}
1152 1132
1133/* tasklet for iwlagn interrupt */
1134static void iwl_irq_tasklet(struct iwl_priv *priv)
1135{
1136 u32 inta = 0;
1137 u32 handled = 0;
1138 unsigned long flags;
1139#ifdef CONFIG_IWLWIFI_DEBUG
1140 u32 inta_mask;
1141#endif
1142
1143 spin_lock_irqsave(&priv->lock, flags);
1144
1145 /* Ack/clear/reset pending uCode interrupts.
1146 * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS,
1147 */
1148 iwl_write32(priv, CSR_INT, priv->inta);
1149
1150 inta = priv->inta;
1151
1152#ifdef CONFIG_IWLWIFI_DEBUG
1153 if (priv->debug_level & IWL_DL_ISR) {
1154 /* just for debug */
1155 inta_mask = iwl_read32(priv, CSR_INT_MASK);
1156 IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ",
1157 inta, inta_mask);
1158 }
1159#endif
1160 /* saved interrupt in inta variable now we can reset priv->inta */
1161 priv->inta = 0;
1162
1163 /* Now service all interrupt bits discovered above. */
1164 if (inta & CSR_INT_BIT_HW_ERR) {
1165 IWL_ERR(priv, "Microcode HW error detected. Restarting.\n");
1166
1167 /* Tell the device to stop sending interrupts */
1168 iwl_disable_interrupts(priv);
1169
1170 priv->isr_stats.hw++;
1171 iwl_irq_handle_error(priv);
1172
1173 handled |= CSR_INT_BIT_HW_ERR;
1174
1175 spin_unlock_irqrestore(&priv->lock, flags);
1176
1177 return;
1178 }
1179
1180#ifdef CONFIG_IWLWIFI_DEBUG
1181 if (priv->debug_level & (IWL_DL_ISR)) {
1182 /* NIC fires this, but we don't use it, redundant with WAKEUP */
1183 if (inta & CSR_INT_BIT_SCD) {
1184 IWL_DEBUG_ISR(priv, "Scheduler finished to transmit "
1185 "the frame/frames.\n");
1186 priv->isr_stats.sch++;
1187 }
1188
1189 /* Alive notification via Rx interrupt will do the real work */
1190 if (inta & CSR_INT_BIT_ALIVE) {
1191 IWL_DEBUG_ISR(priv, "Alive interrupt\n");
1192 priv->isr_stats.alive++;
1193 }
1194 }
1195#endif
1196 /* Safely ignore these bits for debug checks below */
1197 inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE);
1198
1199 /* HW RF KILL switch toggled */
1200 if (inta & CSR_INT_BIT_RF_KILL) {
1201 int hw_rf_kill = 0;
1202 if (!(iwl_read32(priv, CSR_GP_CNTRL) &
1203 CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
1204 hw_rf_kill = 1;
1205
1206 IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
1207 hw_rf_kill ? "disable radio" : "enable radio");
1208
1209 priv->isr_stats.rfkill++;
1210
1211 /* driver only loads ucode once setting the interface up.
1212 * the driver allows loading the ucode even if the radio
1213 * is killed. Hence update the killswitch state here. The
1214 * rfkill handler will care about restarting if needed.
1215 */
1216 if (!test_bit(STATUS_ALIVE, &priv->status)) {
1217 if (hw_rf_kill)
1218 set_bit(STATUS_RF_KILL_HW, &priv->status);
1219 else
1220 clear_bit(STATUS_RF_KILL_HW, &priv->status);
1221 queue_work(priv->workqueue, &priv->rf_kill);
1222 }
1223
1224 handled |= CSR_INT_BIT_RF_KILL;
1225 }
1226
1227 /* Chip got too hot and stopped itself */
1228 if (inta & CSR_INT_BIT_CT_KILL) {
1229 IWL_ERR(priv, "Microcode CT kill error detected.\n");
1230 priv->isr_stats.ctkill++;
1231 handled |= CSR_INT_BIT_CT_KILL;
1232 }
1233
1234 /* Error detected by uCode */
1235 if (inta & CSR_INT_BIT_SW_ERR) {
1236 IWL_ERR(priv, "Microcode SW error detected. "
1237 " Restarting 0x%X.\n", inta);
1238 priv->isr_stats.sw++;
1239 priv->isr_stats.sw_err = inta;
1240 iwl_irq_handle_error(priv);
1241 handled |= CSR_INT_BIT_SW_ERR;
1242 }
1243
1244 /* uCode wakes up after power-down sleep */
1245 if (inta & CSR_INT_BIT_WAKEUP) {
1246 IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
1247 iwl_rx_queue_update_write_ptr(priv, &priv->rxq);
1248 iwl_txq_update_write_ptr(priv, &priv->txq[0]);
1249 iwl_txq_update_write_ptr(priv, &priv->txq[1]);
1250 iwl_txq_update_write_ptr(priv, &priv->txq[2]);
1251 iwl_txq_update_write_ptr(priv, &priv->txq[3]);
1252 iwl_txq_update_write_ptr(priv, &priv->txq[4]);
1253 iwl_txq_update_write_ptr(priv, &priv->txq[5]);
1254
1255 priv->isr_stats.wakeup++;
1256
1257 handled |= CSR_INT_BIT_WAKEUP;
1258 }
1259
1260 /* All uCode command responses, including Tx command responses,
1261 * Rx "responses" (frame-received notification), and other
1262 * notifications from uCode come through here*/
1263 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX |
1264 CSR_INT_BIT_RX_PERIODIC)) {
1265 IWL_DEBUG_ISR(priv, "Rx interrupt\n");
1266 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) {
1267 handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
1268 iwl_write32(priv, CSR_FH_INT_STATUS,
1269 CSR49_FH_INT_RX_MASK);
1270 }
1271 if (inta & CSR_INT_BIT_RX_PERIODIC) {
1272 handled |= CSR_INT_BIT_RX_PERIODIC;
1273 iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC);
1274 }
1275 /* Sending RX interrupt require many steps to be done in the
1276 * the device:
1277 * 1- write interrupt to current index in ICT table.
1278 * 2- dma RX frame.
1279 * 3- update RX shared data to indicate last write index.
1280 * 4- send interrupt.
1281 * This could lead to RX race, driver could receive RX interrupt
1282 * but the shared data changes does not reflect this.
1283 * this could lead to RX race, RX periodic will solve this race
1284 */
1285 iwl_write32(priv, CSR_INT_PERIODIC_REG,
1286 CSR_INT_PERIODIC_DIS);
1287 iwl_rx_handle(priv);
1288 /* Only set RX periodic if real RX is received. */
1289 if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX))
1290 iwl_write32(priv, CSR_INT_PERIODIC_REG,
1291 CSR_INT_PERIODIC_ENA);
1292
1293 priv->isr_stats.rx++;
1294 }
1295
1296 if (inta & CSR_INT_BIT_FH_TX) {
1297 iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK);
1298 IWL_DEBUG_ISR(priv, "Tx interrupt\n");
1299 priv->isr_stats.tx++;
1300 handled |= CSR_INT_BIT_FH_TX;
1301 /* FH finished to write, send event */
1302 priv->ucode_write_complete = 1;
1303 wake_up_interruptible(&priv->wait_command_queue);
1304 }
1305
1306 if (inta & ~handled) {
1307 IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled);
1308 priv->isr_stats.unhandled++;
1309 }
1310
1311 if (inta & ~(priv->inta_mask)) {
1312 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1313 inta & ~priv->inta_mask);
1314 }
1315
1316
1317 /* Re-enable all interrupts */
1318 /* only Re-enable if diabled by irq */
1319 if (test_bit(STATUS_INT_ENABLED, &priv->status))
1320 iwl_enable_interrupts(priv);
1321
1322 spin_unlock_irqrestore(&priv->lock, flags);
1323
1324}
1325
1153 1326
1154/****************************************************************************** 1327/******************************************************************************
1155 * 1328 *
@@ -1579,6 +1752,8 @@ static void __iwl_down(struct iwl_priv *priv)
1579 test_bit(STATUS_EXIT_PENDING, &priv->status) << 1752 test_bit(STATUS_EXIT_PENDING, &priv->status) <<
1580 STATUS_EXIT_PENDING; 1753 STATUS_EXIT_PENDING;
1581 1754
1755 /* device going down, Stop using ICT table */
1756 iwl_disable_ict(priv);
1582 spin_lock_irqsave(&priv->lock, flags); 1757 spin_lock_irqsave(&priv->lock, flags);
1583 iwl_clear_bit(priv, CSR_GP_CNTRL, 1758 iwl_clear_bit(priv, CSR_GP_CNTRL,
1584 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 1759 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
@@ -1587,13 +1762,8 @@ static void __iwl_down(struct iwl_priv *priv)
1587 iwl_txq_ctx_stop(priv); 1762 iwl_txq_ctx_stop(priv);
1588 iwl_rxq_stop(priv); 1763 iwl_rxq_stop(priv);
1589 1764
1590 spin_lock_irqsave(&priv->lock, flags); 1765 iwl_write_prph(priv, APMG_CLK_DIS_REG,
1591 if (!iwl_grab_nic_access(priv)) { 1766 APMG_CLK_VAL_DMA_CLK_RQT);
1592 iwl_write_prph(priv, APMG_CLK_DIS_REG,
1593 APMG_CLK_VAL_DMA_CLK_RQT);
1594 iwl_release_nic_access(priv);
1595 }
1596 spin_unlock_irqrestore(&priv->lock, flags);
1597 1767
1598 udelay(5); 1768 udelay(5);
1599 1769
@@ -1622,6 +1792,49 @@ static void iwl_down(struct iwl_priv *priv)
1622 iwl_cancel_deferred_work(priv); 1792 iwl_cancel_deferred_work(priv);
1623} 1793}
1624 1794
1795#define HW_READY_TIMEOUT (50)
1796
1797static int iwl_set_hw_ready(struct iwl_priv *priv)
1798{
1799 int ret = 0;
1800
1801 iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
1802 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY);
1803
1804 /* See if we got it */
1805 ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
1806 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
1807 CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
1808 HW_READY_TIMEOUT);
1809 if (ret != -ETIMEDOUT)
1810 priv->hw_ready = true;
1811 else
1812 priv->hw_ready = false;
1813
1814 IWL_DEBUG_INFO(priv, "hardware %s\n",
1815 (priv->hw_ready == 1) ? "ready" : "not ready");
1816 return ret;
1817}
1818
1819static int iwl_prepare_card_hw(struct iwl_priv *priv)
1820{
1821 int ret = 0;
1822
1823 IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n");
1824
1825 iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
1826 CSR_HW_IF_CONFIG_REG_PREPARE);
1827
1828 ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
1829 ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE,
1830 CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000);
1831
1832 if (ret != -ETIMEDOUT)
1833 iwl_set_hw_ready(priv);
1834
1835 return ret;
1836}
1837
1625#define MAX_HW_RESTARTS 5 1838#define MAX_HW_RESTARTS 5
1626 1839
1627static int __iwl_up(struct iwl_priv *priv) 1840static int __iwl_up(struct iwl_priv *priv)
@@ -1639,6 +1852,13 @@ static int __iwl_up(struct iwl_priv *priv)
1639 return -EIO; 1852 return -EIO;
1640 } 1853 }
1641 1854
1855 iwl_prepare_card_hw(priv);
1856
1857 if (!priv->hw_ready) {
1858 IWL_WARN(priv, "Exit HW not ready\n");
1859 return -EIO;
1860 }
1861
1642 /* If platform's RF_KILL switch is NOT set to KILL */ 1862 /* If platform's RF_KILL switch is NOT set to KILL */
1643 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) 1863 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
1644 clear_bit(STATUS_RF_KILL_HW, &priv->status); 1864 clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -1667,6 +1887,8 @@ static int __iwl_up(struct iwl_priv *priv)
1667 1887
1668 /* clear (again), then enable host interrupts */ 1888 /* clear (again), then enable host interrupts */
1669 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 1889 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
1890 /* enable dram interrupt */
1891 iwl_reset_ict(priv);
1670 iwl_enable_interrupts(priv); 1892 iwl_enable_interrupts(priv);
1671 1893
1672 /* really make sure rfkill handshake bits are cleared */ 1894 /* really make sure rfkill handshake bits are cleared */
@@ -2298,8 +2520,10 @@ static ssize_t show_version(struct device *d,
2298 2520
2299 if (priv->eeprom) { 2521 if (priv->eeprom) {
2300 eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); 2522 eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION);
2301 pos += sprintf(buf + pos, "EEPROM version: 0x%x\n", 2523 pos += sprintf(buf + pos, "NVM Type: %s, version: 0x%x\n",
2302 eeprom_ver); 2524 (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
2525 ? "OTP" : "EEPROM", eeprom_ver);
2526
2303 } else { 2527 } else {
2304 pos += sprintf(buf + pos, "EEPROM not initialzed\n"); 2528 pos += sprintf(buf + pos, "EEPROM not initialzed\n");
2305 } 2529 }
@@ -2478,7 +2702,7 @@ static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
2478static ssize_t show_qos(struct device *d, 2702static ssize_t show_qos(struct device *d,
2479 struct device_attribute *attr, char *buf) 2703 struct device_attribute *attr, char *buf)
2480{ 2704{
2481 struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; 2705 struct iwl_priv *priv = dev_get_drvdata(d);
2482 char *p = buf; 2706 char *p = buf;
2483 int q; 2707 int q;
2484 2708
@@ -2565,8 +2789,12 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
2565 priv->statistics_periodic.data = (unsigned long)priv; 2789 priv->statistics_periodic.data = (unsigned long)priv;
2566 priv->statistics_periodic.function = iwl_bg_statistics_periodic; 2790 priv->statistics_periodic.function = iwl_bg_statistics_periodic;
2567 2791
2568 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) 2792 if (!priv->cfg->use_isr_legacy)
2569 iwl_irq_tasklet, (unsigned long)priv); 2793 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
2794 iwl_irq_tasklet, (unsigned long)priv);
2795 else
2796 tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
2797 iwl_irq_tasklet_legacy, (unsigned long)priv);
2570} 2798}
2571 2799
2572static void iwl_cancel_deferred_work(struct iwl_priv *priv) 2800static void iwl_cancel_deferred_work(struct iwl_priv *priv)
@@ -2655,6 +2883,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2655 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); 2883 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
2656 priv->cfg = cfg; 2884 priv->cfg = cfg;
2657 priv->pci_dev = pdev; 2885 priv->pci_dev = pdev;
2886 priv->inta_mask = CSR_INI_SET_MASK;
2658 2887
2659#ifdef CONFIG_IWLWIFI_DEBUG 2888#ifdef CONFIG_IWLWIFI_DEBUG
2660 priv->debug_level = priv->cfg->mod_params->debug; 2889 priv->debug_level = priv->cfg->mod_params->debug;
@@ -2705,6 +2934,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2705 (unsigned long long) pci_resource_len(pdev, 0)); 2934 (unsigned long long) pci_resource_len(pdev, 0));
2706 IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); 2935 IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
2707 2936
2937 /* this spin lock will be used in apm_ops.init and EEPROM access
2938 * we should init now
2939 */
2940 spin_lock_init(&priv->reg_lock);
2708 iwl_hw_detect(priv); 2941 iwl_hw_detect(priv);
2709 IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", 2942 IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n",
2710 priv->cfg->name, priv->hw_rev); 2943 priv->cfg->name, priv->hw_rev);
@@ -2713,6 +2946,12 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2713 * PCI Tx retries from interfering with C3 CPU state */ 2946 * PCI Tx retries from interfering with C3 CPU state */
2714 pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); 2947 pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
2715 2948
2949 iwl_prepare_card_hw(priv);
2950 if (!priv->hw_ready) {
2951 IWL_WARN(priv, "Failed, HW not ready\n");
2952 goto out_iounmap;
2953 }
2954
2716 /* amp init */ 2955 /* amp init */
2717 err = priv->cfg->ops->lib->apm_ops.init(priv); 2956 err = priv->cfg->ops->lib->apm_ops.init(priv);
2718 if (err < 0) { 2957 if (err < 0) {
@@ -2763,8 +3002,9 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2763 3002
2764 pci_enable_msi(priv->pci_dev); 3003 pci_enable_msi(priv->pci_dev);
2765 3004
2766 err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, 3005 iwl_alloc_isr_ict(priv);
2767 DRV_NAME, priv); 3006 err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
3007 IRQF_SHARED, DRV_NAME, priv);
2768 if (err) { 3008 if (err) {
2769 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); 3009 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
2770 goto out_disable_msi; 3010 goto out_disable_msi;
@@ -2821,6 +3061,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
2821 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); 3061 sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
2822 out_free_irq: 3062 out_free_irq:
2823 free_irq(priv->pci_dev->irq, priv); 3063 free_irq(priv->pci_dev->irq, priv);
3064 iwl_free_isr_ict(priv);
2824 out_disable_msi: 3065 out_disable_msi:
2825 pci_disable_msi(priv->pci_dev); 3066 pci_disable_msi(priv->pci_dev);
2826 iwl_uninit_drv(priv); 3067 iwl_uninit_drv(priv);
@@ -2902,6 +3143,8 @@ static void __devexit iwl_pci_remove(struct pci_dev *pdev)
2902 3143
2903 iwl_uninit_drv(priv); 3144 iwl_uninit_drv(priv);
2904 3145
3146 iwl_free_isr_ict(priv);
3147
2905 if (priv->ibss_beacon) 3148 if (priv->ibss_beacon)
2906 dev_kfree_skb(priv->ibss_beacon); 3149 dev_kfree_skb(priv->ibss_beacon);
2907 3150
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 7b84d5246b36..e581dc323f0a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -614,8 +614,18 @@ enum {
614 614
615#define RXON_FLG_CHANNEL_MODE_POS (25) 615#define RXON_FLG_CHANNEL_MODE_POS (25)
616#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25) 616#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25)
617#define RXON_FLG_CHANNEL_MODE_PURE_40_MSK cpu_to_le32(0x1 << 25) 617
618#define RXON_FLG_CHANNEL_MODE_MIXED_MSK cpu_to_le32(0x2 << 25) 618/* channel mode */
619enum {
620 CHANNEL_MODE_LEGACY = 0,
621 CHANNEL_MODE_PURE_40 = 1,
622 CHANNEL_MODE_MIXED = 2,
623 CHANNEL_MODE_RESERVED = 3,
624};
625#define RXON_FLG_CHANNEL_MODE_LEGACY cpu_to_le32(CHANNEL_MODE_LEGACY << RXON_FLG_CHANNEL_MODE_POS)
626#define RXON_FLG_CHANNEL_MODE_PURE_40 cpu_to_le32(CHANNEL_MODE_PURE_40 << RXON_FLG_CHANNEL_MODE_POS)
627#define RXON_FLG_CHANNEL_MODE_MIXED cpu_to_le32(CHANNEL_MODE_MIXED << RXON_FLG_CHANNEL_MODE_POS)
628
619/* CTS to self (if spec allows) flag */ 629/* CTS to self (if spec allows) flag */
620#define RXON_FLG_SELF_CTS_EN cpu_to_le32(0x1<<30) 630#define RXON_FLG_SELF_CTS_EN cpu_to_le32(0x1<<30)
621 631
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 5393fb3f452c..e93ddb74457e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -39,6 +39,7 @@
39#include "iwl-rfkill.h" 39#include "iwl-rfkill.h"
40#include "iwl-power.h" 40#include "iwl-power.h"
41#include "iwl-sta.h" 41#include "iwl-sta.h"
42#include "iwl-helpers.h"
42 43
43 44
44MODULE_DESCRIPTION("iwl core"); 45MODULE_DESCRIPTION("iwl core");
@@ -59,6 +60,8 @@ MODULE_LICENSE("GPL");
59 IWL_RATE_##pp##M_INDEX, \ 60 IWL_RATE_##pp##M_INDEX, \
60 IWL_RATE_##np##M_INDEX } 61 IWL_RATE_##np##M_INDEX }
61 62
63static irqreturn_t iwl_isr(int irq, void *data);
64
62/* 65/*
63 * Parameter order: 66 * Parameter order:
64 * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate 67 * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
@@ -603,10 +606,10 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv,
603 606
604 if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) 607 if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
605 return !(ch_info->fat_extension_channel & 608 return !(ch_info->fat_extension_channel &
606 IEEE80211_CHAN_NO_FAT_ABOVE); 609 IEEE80211_CHAN_NO_HT40PLUS);
607 else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) 610 else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
608 return !(ch_info->fat_extension_channel & 611 return !(ch_info->fat_extension_channel &
609 IEEE80211_CHAN_NO_FAT_BELOW); 612 IEEE80211_CHAN_NO_HT40MINUS);
610 613
611 return 0; 614 return 0;
612} 615}
@@ -617,19 +620,23 @@ u8 iwl_is_fat_tx_allowed(struct iwl_priv *priv,
617 struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; 620 struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config;
618 621
619 if ((!iwl_ht_conf->is_ht) || 622 if ((!iwl_ht_conf->is_ht) ||
620 (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ) || 623 (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ))
621 (iwl_ht_conf->extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE))
622 return 0; 624 return 0;
623 625
626 /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
627 * the bit will not set if it is pure 40MHz case
628 */
624 if (sta_ht_inf) { 629 if (sta_ht_inf) {
625 if ((!sta_ht_inf->ht_supported) || 630 if (!sta_ht_inf->ht_supported)
626 (!(sta_ht_inf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)))
627 return 0; 631 return 0;
628 } 632 }
629 633
630 return iwl_is_channel_extension(priv, priv->band, 634 if (iwl_ht_conf->ht_protection & IEEE80211_HT_OP_MODE_PROTECTION_20MHZ)
631 le16_to_cpu(priv->staging_rxon.channel), 635 return 1;
632 iwl_ht_conf->extension_chan_offset); 636 else
637 return iwl_is_channel_extension(priv, priv->band,
638 le16_to_cpu(priv->staging_rxon.channel),
639 iwl_ht_conf->extension_chan_offset);
633} 640}
634EXPORT_SYMBOL(iwl_is_fat_tx_allowed); 641EXPORT_SYMBOL(iwl_is_fat_tx_allowed);
635 642
@@ -799,42 +806,51 @@ EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
799void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) 806void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info)
800{ 807{
801 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 808 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
802 u32 val;
803 809
804 if (!ht_info->is_ht) { 810 if (!ht_info->is_ht) {
805 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 811 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
806 RXON_FLG_CHANNEL_MODE_PURE_40_MSK |
807 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | 812 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
808 RXON_FLG_FAT_PROT_MSK | 813 RXON_FLG_FAT_PROT_MSK |
809 RXON_FLG_HT_PROT_MSK); 814 RXON_FLG_HT_PROT_MSK);
810 return; 815 return;
811 } 816 }
812 817
813 /* Set up channel bandwidth: 20 MHz only, or 20/40 mixed if fat ok */ 818 /* FIXME: if the definition of ht_protection changed, the "translation"
814 if (iwl_is_fat_tx_allowed(priv, NULL)) 819 * will be needed for rxon->flags
815 rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED_MSK; 820 */
816 else 821 rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS);
817 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 822
818 RXON_FLG_CHANNEL_MODE_PURE_40_MSK); 823 /* Set up channel bandwidth:
819 824 * 20 MHz only, 20/40 mixed or pure 40 if fat ok */
820 /* Note: control channel is opposite of extension channel */ 825 /* clear the HT channel mode before set the mode */
821 switch (ht_info->extension_chan_offset) { 826 rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
822 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 827 RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
823 rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); 828 if (iwl_is_fat_tx_allowed(priv, NULL)) {
824 break; 829 /* pure 40 fat */
825 case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 830 if (rxon->flags & RXON_FLG_FAT_PROT_MSK)
826 rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; 831 rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40;
827 break; 832 else {
828 case IEEE80211_HT_PARAM_CHA_SEC_NONE: 833 /* Note: control channel is opposite of extension channel */
829 default: 834 switch (ht_info->extension_chan_offset) {
830 rxon->flags &= ~RXON_FLG_CHANNEL_MODE_MIXED_MSK; 835 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
831 break; 836 rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK);
837 rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
838 break;
839 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
840 rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK;
841 rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED;
842 break;
843 case IEEE80211_HT_PARAM_CHA_SEC_NONE:
844 default:
845 /* channel location only valid if in Mixed mode */
846 IWL_ERR(priv, "invalid extension channel offset\n");
847 break;
848 }
849 }
850 } else {
851 rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY;
832 } 852 }
833 853
834 val = ht_info->ht_protection;
835
836 rxon->flags |= cpu_to_le32(val << RXON_FLG_HT_OPERATING_MODE_POS);
837
838 if (priv->cfg->ops->hcmd->set_rxon_chain) 854 if (priv->cfg->ops->hcmd->set_rxon_chain)
839 priv->cfg->ops->hcmd->set_rxon_chain(priv); 855 priv->cfg->ops->hcmd->set_rxon_chain(priv);
840 856
@@ -1122,8 +1138,9 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode)
1122 priv->staging_rxon.cck_basic_rates = 1138 priv->staging_rxon.cck_basic_rates =
1123 (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; 1139 (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
1124 1140
1125 priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED_MSK | 1141 /* clear both MIX and PURE40 mode flag */
1126 RXON_FLG_CHANNEL_MODE_PURE_40_MSK); 1142 priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
1143 RXON_FLG_CHANNEL_MODE_PURE_40);
1127 memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); 1144 memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN);
1128 memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); 1145 memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN);
1129 priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; 1146 priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff;
@@ -1483,11 +1500,272 @@ void iwl_enable_interrupts(struct iwl_priv *priv)
1483{ 1500{
1484 IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); 1501 IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
1485 set_bit(STATUS_INT_ENABLED, &priv->status); 1502 set_bit(STATUS_INT_ENABLED, &priv->status);
1486 iwl_write32(priv, CSR_INT_MASK, CSR_INI_SET_MASK); 1503 iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
1487} 1504}
1488EXPORT_SYMBOL(iwl_enable_interrupts); 1505EXPORT_SYMBOL(iwl_enable_interrupts);
1489 1506
1490irqreturn_t iwl_isr(int irq, void *data) 1507
1508#define ICT_COUNT (PAGE_SIZE/sizeof(u32))
1509
1510/* Free dram table */
1511void iwl_free_isr_ict(struct iwl_priv *priv)
1512{
1513 if (priv->ict_tbl_vir) {
1514 pci_free_consistent(priv->pci_dev, (sizeof(u32) * ICT_COUNT) +
1515 PAGE_SIZE, priv->ict_tbl_vir,
1516 priv->ict_tbl_dma);
1517 priv->ict_tbl_vir = NULL;
1518 }
1519}
1520EXPORT_SYMBOL(iwl_free_isr_ict);
1521
1522
1523/* allocate dram shared table it is a PAGE_SIZE aligned
1524 * also reset all data related to ICT table interrupt.
1525 */
1526int iwl_alloc_isr_ict(struct iwl_priv *priv)
1527{
1528
1529 if (priv->cfg->use_isr_legacy)
1530 return 0;
1531 /* allocate shrared data table */
1532 priv->ict_tbl_vir = pci_alloc_consistent(priv->pci_dev, (sizeof(u32) *
1533 ICT_COUNT) + PAGE_SIZE,
1534 &priv->ict_tbl_dma);
1535 if (!priv->ict_tbl_vir)
1536 return -ENOMEM;
1537
1538 /* align table to PAGE_SIZE boundry */
1539 priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE);
1540
1541 IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
1542 (unsigned long long)priv->ict_tbl_dma,
1543 (unsigned long long)priv->aligned_ict_tbl_dma,
1544 (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
1545
1546 priv->ict_tbl = priv->ict_tbl_vir +
1547 (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma);
1548
1549 IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n",
1550 priv->ict_tbl, priv->ict_tbl_vir,
1551 (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma));
1552
1553 /* reset table and index to all 0 */
1554 memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE);
1555 priv->ict_index = 0;
1556
1557 /* add periodic RX interrupt */
1558 priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC;
1559 return 0;
1560}
1561EXPORT_SYMBOL(iwl_alloc_isr_ict);
1562
1563/* Device is going up inform it about using ICT interrupt table,
1564 * also we need to tell the driver to start using ICT interrupt.
1565 */
1566int iwl_reset_ict(struct iwl_priv *priv)
1567{
1568 u32 val;
1569 unsigned long flags;
1570
1571 if (!priv->ict_tbl_vir)
1572 return 0;
1573
1574 spin_lock_irqsave(&priv->lock, flags);
1575 iwl_disable_interrupts(priv);
1576
1577 memset(&priv->ict_tbl[0],0, sizeof(u32) * ICT_COUNT);
1578
1579 val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT;
1580
1581 val |= CSR_DRAM_INT_TBL_ENABLE;
1582 val |= CSR_DRAM_INIT_TBL_WRAP_CHECK;
1583
1584 IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X "
1585 "aligned dma address %Lx\n",
1586 val, (unsigned long long)priv->aligned_ict_tbl_dma);
1587
1588 iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val);
1589 priv->use_ict = true;
1590 priv->ict_index = 0;
1591 iwl_write32(priv, CSR_INT, priv->inta_mask);
1592 iwl_enable_interrupts(priv);
1593 spin_unlock_irqrestore(&priv->lock, flags);
1594
1595 return 0;
1596}
1597EXPORT_SYMBOL(iwl_reset_ict);
1598
1599/* Device is going down disable ict interrupt usage */
1600void iwl_disable_ict(struct iwl_priv *priv)
1601{
1602 unsigned long flags;
1603
1604 spin_lock_irqsave(&priv->lock, flags);
1605 priv->use_ict = false;
1606 spin_unlock_irqrestore(&priv->lock, flags);
1607}
1608EXPORT_SYMBOL(iwl_disable_ict);
1609
1610/* interrupt handler using ict table, with this interrupt driver will
1611 * stop using INTA register to get device's interrupt, reading this register
1612 * is expensive, device will write interrupts in ICT dram table, increment
1613 * index then will fire interrupt to driver, driver will OR all ICT table
1614 * entries from current index up to table entry with 0 value. the result is
1615 * the interrupt we need to service, driver will set the entries back to 0 and
1616 * set index.
1617 */
1618irqreturn_t iwl_isr_ict(int irq, void *data)
1619{
1620 struct iwl_priv *priv = data;
1621 u32 inta, inta_mask;
1622 u32 val = 0;
1623
1624 if (!priv)
1625 return IRQ_NONE;
1626
1627 /* dram interrupt table not set yet,
1628 * use legacy interrupt.
1629 */
1630 if (!priv->use_ict)
1631 return iwl_isr(irq, data);
1632
1633 spin_lock(&priv->lock);
1634
1635 /* Disable (but don't clear!) interrupts here to avoid
1636 * back-to-back ISRs and sporadic interrupts from our NIC.
1637 * If we have something to service, the tasklet will re-enable ints.
1638 * If we *don't* have something, we'll re-enable before leaving here.
1639 */
1640 inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
1641 iwl_write32(priv, CSR_INT_MASK, 0x00000000);
1642
1643
1644 /* Ignore interrupt if there's nothing in NIC to service.
1645 * This may be due to IRQ shared with another device,
1646 * or due to sporadic interrupts thrown from our NIC. */
1647 if (!priv->ict_tbl[priv->ict_index]) {
1648 IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
1649 goto none;
1650 }
1651
1652 /* read all entries that not 0 start with ict_index */
1653 while (priv->ict_tbl[priv->ict_index]) {
1654
1655 val |= priv->ict_tbl[priv->ict_index];
1656 IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n",
1657 priv->ict_index,
1658 priv->ict_tbl[priv->ict_index]);
1659 priv->ict_tbl[priv->ict_index] = 0;
1660 priv->ict_index = iwl_queue_inc_wrap(priv->ict_index,
1661 ICT_COUNT);
1662
1663 }
1664
1665 /* We should not get this value, just ignore it. */
1666 if (val == 0xffffffff)
1667 val = 0;
1668
1669 inta = (0xff & val) | ((0xff00 & val) << 16);
1670 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n",
1671 inta, inta_mask, val);
1672
1673 inta &= priv->inta_mask;
1674 priv->inta |= inta;
1675
1676 /* iwl_irq_tasklet() will service interrupts and re-enable them */
1677 if (likely(inta))
1678 tasklet_schedule(&priv->irq_tasklet);
1679 else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) {
1680 /* Allow interrupt if was disabled by this handler and
1681 * no tasklet was schedules, We should not enable interrupt,
1682 * tasklet will enable it.
1683 */
1684 iwl_enable_interrupts(priv);
1685 }
1686
1687 spin_unlock(&priv->lock);
1688 return IRQ_HANDLED;
1689
1690 none:
1691 /* re-enable interrupts here since we don't have anything to service.
1692 * only Re-enable if disabled by irq.
1693 */
1694 if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
1695 iwl_enable_interrupts(priv);
1696
1697 spin_unlock(&priv->lock);
1698 return IRQ_NONE;
1699}
1700EXPORT_SYMBOL(iwl_isr_ict);
1701
1702
1703static irqreturn_t iwl_isr(int irq, void *data)
1704{
1705 struct iwl_priv *priv = data;
1706 u32 inta, inta_mask;
1707 u32 inta_fh;
1708
1709 if (!priv)
1710 return IRQ_NONE;
1711
1712 spin_lock(&priv->lock);
1713
1714 /* Disable (but don't clear!) interrupts here to avoid
1715 * back-to-back ISRs and sporadic interrupts from our NIC.
1716 * If we have something to service, the tasklet will re-enable ints.
1717 * If we *don't* have something, we'll re-enable before leaving here. */
1718 inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
1719 iwl_write32(priv, CSR_INT_MASK, 0x00000000);
1720
1721 /* Discover which interrupts are active/pending */
1722 inta = iwl_read32(priv, CSR_INT);
1723
1724 /* Ignore interrupt if there's nothing in NIC to service.
1725 * This may be due to IRQ shared with another device,
1726 * or due to sporadic interrupts thrown from our NIC. */
1727 if (!inta) {
1728 IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n");
1729 goto none;
1730 }
1731
1732 if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
1733 /* Hardware disappeared. It might have already raised
1734 * an interrupt */
1735 IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
1736 goto unplugged;
1737 }
1738
1739#ifdef CONFIG_IWLWIFI_DEBUG
1740 if (priv->debug_level & (IWL_DL_ISR)) {
1741 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
1742 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, "
1743 "fh 0x%08x\n", inta, inta_mask, inta_fh);
1744 }
1745#endif
1746
1747 priv->inta |= inta;
1748 /* iwl_irq_tasklet() will service interrupts and re-enable them */
1749 if (likely(inta))
1750 tasklet_schedule(&priv->irq_tasklet);
1751 else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
1752 iwl_enable_interrupts(priv);
1753
1754 unplugged:
1755 spin_unlock(&priv->lock);
1756 return IRQ_HANDLED;
1757
1758 none:
1759 /* re-enable interrupts here since we don't have anything to service. */
1760 /* only Re-enable if diabled by irq and no schedules tasklet. */
1761 if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta)
1762 iwl_enable_interrupts(priv);
1763
1764 spin_unlock(&priv->lock);
1765 return IRQ_NONE;
1766}
1767
1768irqreturn_t iwl_isr_legacy(int irq, void *data)
1491{ 1769{
1492 struct iwl_priv *priv = data; 1770 struct iwl_priv *priv = data;
1493 u32 inta, inta_mask; 1771 u32 inta, inta_mask;
@@ -1544,7 +1822,7 @@ irqreturn_t iwl_isr(int irq, void *data)
1544 spin_unlock(&priv->lock); 1822 spin_unlock(&priv->lock);
1545 return IRQ_NONE; 1823 return IRQ_NONE;
1546} 1824}
1547EXPORT_SYMBOL(iwl_isr); 1825EXPORT_SYMBOL(iwl_isr_legacy);
1548 1826
1549int iwl_send_bt_config(struct iwl_priv *priv) 1827int iwl_send_bt_config(struct iwl_priv *priv)
1550{ 1828{
@@ -1588,10 +1866,6 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
1588 1866
1589 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); 1867 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
1590 1868
1591 ret = iwl_grab_nic_access(priv);
1592 if (ret)
1593 return ret;
1594
1595 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { 1869 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
1596 /* read data comes through single port, auto-incr addr */ 1870 /* read data comes through single port, auto-incr addr */
1597 /* NOTE: Use the debugless read so we don't flood kernel log 1871 /* NOTE: Use the debugless read so we don't flood kernel log
@@ -1607,8 +1881,6 @@ static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
1607 } 1881 }
1608 } 1882 }
1609 1883
1610 iwl_release_nic_access(priv);
1611
1612 return ret; 1884 return ret;
1613} 1885}
1614 1886
@@ -1626,10 +1898,6 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
1626 1898
1627 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); 1899 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
1628 1900
1629 ret = iwl_grab_nic_access(priv);
1630 if (ret)
1631 return ret;
1632
1633 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, 1901 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
1634 IWL49_RTC_INST_LOWER_BOUND); 1902 IWL49_RTC_INST_LOWER_BOUND);
1635 1903
@@ -1650,8 +1918,6 @@ static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image,
1650 } 1918 }
1651 } 1919 }
1652 1920
1653 iwl_release_nic_access(priv);
1654
1655 if (!errcnt) 1921 if (!errcnt)
1656 IWL_DEBUG_INFO(priv, 1922 IWL_DEBUG_INFO(priv,
1657 "ucode image in INSTRUCTION memory is good\n"); 1923 "ucode image in INSTRUCTION memory is good\n");
@@ -1760,7 +2026,6 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
1760 u32 data2, line; 2026 u32 data2, line;
1761 u32 desc, time, count, base, data1; 2027 u32 desc, time, count, base, data1;
1762 u32 blink1, blink2, ilink1, ilink2; 2028 u32 blink1, blink2, ilink1, ilink2;
1763 int ret;
1764 2029
1765 if (priv->ucode_type == UCODE_INIT) 2030 if (priv->ucode_type == UCODE_INIT)
1766 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); 2031 base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
@@ -1772,12 +2037,6 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
1772 return; 2037 return;
1773 } 2038 }
1774 2039
1775 ret = iwl_grab_nic_access(priv);
1776 if (ret) {
1777 IWL_WARN(priv, "Can not read from adapter at this time.\n");
1778 return;
1779 }
1780
1781 count = iwl_read_targ_mem(priv, base); 2040 count = iwl_read_targ_mem(priv, base);
1782 2041
1783 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { 2042 if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
@@ -1804,7 +2063,6 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
1804 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, 2063 IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2,
1805 ilink1, ilink2); 2064 ilink1, ilink2);
1806 2065
1807 iwl_release_nic_access(priv);
1808} 2066}
1809EXPORT_SYMBOL(iwl_dump_nic_error_log); 2067EXPORT_SYMBOL(iwl_dump_nic_error_log);
1810 2068
@@ -1813,7 +2071,6 @@ EXPORT_SYMBOL(iwl_dump_nic_error_log);
1813/** 2071/**
1814 * iwl_print_event_log - Dump error event log to syslog 2072 * iwl_print_event_log - Dump error event log to syslog
1815 * 2073 *
1816 * NOTE: Must be called with iwl_grab_nic_access() already obtained!
1817 */ 2074 */
1818static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, 2075static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1819 u32 num_events, u32 mode) 2076 u32 num_events, u32 mode)
@@ -1859,7 +2116,6 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx,
1859 2116
1860void iwl_dump_nic_event_log(struct iwl_priv *priv) 2117void iwl_dump_nic_event_log(struct iwl_priv *priv)
1861{ 2118{
1862 int ret;
1863 u32 base; /* SRAM byte address of event log header */ 2119 u32 base; /* SRAM byte address of event log header */
1864 u32 capacity; /* event log capacity in # entries */ 2120 u32 capacity; /* event log capacity in # entries */
1865 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ 2121 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
@@ -1877,12 +2133,6 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
1877 return; 2133 return;
1878 } 2134 }
1879 2135
1880 ret = iwl_grab_nic_access(priv);
1881 if (ret) {
1882 IWL_WARN(priv, "Can not read from adapter at this time.\n");
1883 return;
1884 }
1885
1886 /* event log header */ 2136 /* event log header */
1887 capacity = iwl_read_targ_mem(priv, base); 2137 capacity = iwl_read_targ_mem(priv, base);
1888 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); 2138 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
@@ -1894,7 +2144,6 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
1894 /* bail out if nothing in log */ 2144 /* bail out if nothing in log */
1895 if (size == 0) { 2145 if (size == 0) {
1896 IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); 2146 IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
1897 iwl_release_nic_access(priv);
1898 return; 2147 return;
1899 } 2148 }
1900 2149
@@ -1909,7 +2158,6 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv)
1909 /* (then/else) start at top of log */ 2158 /* (then/else) start at top of log */
1910 iwl_print_event_log(priv, 0, next_entry, mode); 2159 iwl_print_event_log(priv, 0, next_entry, mode);
1911 2160
1912 iwl_release_nic_access(priv);
1913} 2161}
1914EXPORT_SYMBOL(iwl_dump_nic_event_log); 2162EXPORT_SYMBOL(iwl_dump_nic_event_log);
1915 2163
@@ -2016,11 +2264,11 @@ int iwl_radio_kill_sw_enable_radio(struct iwl_priv *priv)
2016 /* wake up ucode */ 2264 /* wake up ucode */
2017 msleep(10); 2265 msleep(10);
2018 2266
2019 spin_lock_irqsave(&priv->lock, flags);
2020 iwl_read32(priv, CSR_UCODE_DRV_GP1); 2267 iwl_read32(priv, CSR_UCODE_DRV_GP1);
2268 spin_lock_irqsave(&priv->reg_lock, flags);
2021 if (!iwl_grab_nic_access(priv)) 2269 if (!iwl_grab_nic_access(priv))
2022 iwl_release_nic_access(priv); 2270 iwl_release_nic_access(priv);
2023 spin_unlock_irqrestore(&priv->lock, flags); 2271 spin_unlock_irqrestore(&priv->reg_lock, flags);
2024 2272
2025 if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { 2273 if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
2026 IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - " 2274 IWL_DEBUG_RF_KILL(priv, "Can not turn radio back on - "
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index f3544ea559a2..87df1b767941 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -112,6 +112,19 @@ struct iwl_hcmd_utils_ops {
112 struct iwl_rx_phy_res *rx_resp); 112 struct iwl_rx_phy_res *rx_resp);
113}; 113};
114 114
115struct iwl_apm_ops {
116 int (*init)(struct iwl_priv *priv);
117 int (*reset)(struct iwl_priv *priv);
118 void (*stop)(struct iwl_priv *priv);
119 void (*config)(struct iwl_priv *priv);
120 int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
121};
122
123struct iwl_temp_ops {
124 void (*temperature)(struct iwl_priv *priv);
125 void (*set_ct_kill)(struct iwl_priv *priv);
126};
127
115struct iwl_lib_ops { 128struct iwl_lib_ops {
116 /* set hw dependent parameters */ 129 /* set hw dependent parameters */
117 int (*set_hw_params)(struct iwl_priv *priv); 130 int (*set_hw_params)(struct iwl_priv *priv);
@@ -149,23 +162,21 @@ struct iwl_lib_ops {
149 int (*is_valid_rtc_data_addr)(u32 addr); 162 int (*is_valid_rtc_data_addr)(u32 addr);
150 /* 1st ucode load */ 163 /* 1st ucode load */
151 int (*load_ucode)(struct iwl_priv *priv); 164 int (*load_ucode)(struct iwl_priv *priv);
152 /* power management */ 165 /* power management */
153 struct { 166 struct iwl_apm_ops apm_ops;
154 int (*init)(struct iwl_priv *priv); 167
155 int (*reset)(struct iwl_priv *priv);
156 void (*stop)(struct iwl_priv *priv);
157 void (*config)(struct iwl_priv *priv);
158 int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src);
159 } apm_ops;
160 /* power */ 168 /* power */
161 int (*send_tx_power) (struct iwl_priv *priv); 169 int (*send_tx_power) (struct iwl_priv *priv);
162 void (*update_chain_flags)(struct iwl_priv *priv); 170 void (*update_chain_flags)(struct iwl_priv *priv);
163 void (*temperature) (struct iwl_priv *priv);
164 void (*post_associate) (struct iwl_priv *priv); 171 void (*post_associate) (struct iwl_priv *priv);
165 void (*config_ap) (struct iwl_priv *priv); 172 void (*config_ap) (struct iwl_priv *priv);
173 irqreturn_t (*isr) (int irq, void *data);
166 174
167 /* eeprom operations (as defined in iwl-eeprom.h) */ 175 /* eeprom operations (as defined in iwl-eeprom.h) */
168 struct iwl_eeprom_ops eeprom_ops; 176 struct iwl_eeprom_ops eeprom_ops;
177
178 /* temperature */
179 struct iwl_temp_ops temp_ops;
169}; 180};
170 181
171struct iwl_ops { 182struct iwl_ops {
@@ -229,6 +240,7 @@ struct iwl_cfg {
229 u8 valid_tx_ant; 240 u8 valid_tx_ant;
230 u8 valid_rx_ant; 241 u8 valid_rx_ant;
231 bool need_pll_cfg; 242 bool need_pll_cfg;
243 bool use_isr_legacy;
232}; 244};
233 245
234/*************************** 246/***************************
@@ -306,10 +318,11 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
306 struct iwl_rx_queue *q); 318 struct iwl_rx_queue *q);
307void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); 319void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
308void iwl_rx_replenish(struct iwl_priv *priv); 320void iwl_rx_replenish(struct iwl_priv *priv);
321void iwl_rx_replenish_now(struct iwl_priv *priv);
309int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); 322int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
310int iwl_rx_queue_restock(struct iwl_priv *priv); 323int iwl_rx_queue_restock(struct iwl_priv *priv);
311int iwl_rx_queue_space(const struct iwl_rx_queue *q); 324int iwl_rx_queue_space(const struct iwl_rx_queue *q);
312void iwl_rx_allocate(struct iwl_priv *priv); 325void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority);
313void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); 326void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
314int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); 327int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
315/* Handlers */ 328/* Handlers */
@@ -456,7 +469,13 @@ int iwl_send_card_state(struct iwl_priv *priv, u32 flags,
456 *****************************************************/ 469 *****************************************************/
457void iwl_disable_interrupts(struct iwl_priv *priv); 470void iwl_disable_interrupts(struct iwl_priv *priv);
458void iwl_enable_interrupts(struct iwl_priv *priv); 471void iwl_enable_interrupts(struct iwl_priv *priv);
459irqreturn_t iwl_isr(int irq, void *data); 472irqreturn_t iwl_isr_legacy(int irq, void *data);
473int iwl_reset_ict(struct iwl_priv *priv);
474void iwl_disable_ict(struct iwl_priv *priv);
475int iwl_alloc_isr_ict(struct iwl_priv *priv);
476void iwl_free_isr_ict(struct iwl_priv *priv);
477irqreturn_t iwl_isr_ict(int irq, void *data);
478
460static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) 479static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv)
461{ 480{
462 int pos; 481 int pos;
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index 6e983149b83b..f03dae1b2f36 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -89,6 +89,7 @@
89/* EEPROM reads */ 89/* EEPROM reads */
90#define CSR_EEPROM_REG (CSR_BASE+0x02c) 90#define CSR_EEPROM_REG (CSR_BASE+0x02c)
91#define CSR_EEPROM_GP (CSR_BASE+0x030) 91#define CSR_EEPROM_GP (CSR_BASE+0x030)
92#define CSR_OTP_GP_REG (CSR_BASE+0x034)
92#define CSR_GIO_REG (CSR_BASE+0x03C) 93#define CSR_GIO_REG (CSR_BASE+0x03C)
93#define CSR_GP_UCODE (CSR_BASE+0x044) 94#define CSR_GP_UCODE (CSR_BASE+0x044)
94#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) 95#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054)
@@ -96,8 +97,10 @@
96#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) 97#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
97#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) 98#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
98#define CSR_LED_REG (CSR_BASE+0x094) 99#define CSR_LED_REG (CSR_BASE+0x094)
100#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
99#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) 101#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100)
100 102
103#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005)
101/* Analog phase-lock-loop configuration */ 104/* Analog phase-lock-loop configuration */
102#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) 105#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c)
103/* 106/*
@@ -123,16 +126,18 @@
123 126
124#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) 127#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000)
125#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) 128#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000)
126#define CSR_HW_IF_CONFIG_REG_BIT_PCI_OWN_SEM (0x00400000) 129#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000)
127#define CSR_HW_IF_CONFIG_REG_BIT_ME_OWN (0x02000000) 130#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000)
128#define CSR_HW_IF_CONFIG_REG_BIT_WAKE_ME (0x08000000) 131#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000)
129 132
133#define CSR_INT_PERIODIC_DIS (0x00)
134#define CSR_INT_PERIODIC_ENA (0xFF)
130 135
131/* interrupt flags in INTA, set by uCode or hardware (e.g. dma), 136/* interrupt flags in INTA, set by uCode or hardware (e.g. dma),
132 * acknowledged (reset) by host writing "1" to flagged bits. */ 137 * acknowledged (reset) by host writing "1" to flagged bits. */
133#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ 138#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */
134#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ 139#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */
135#define CSR_INT_BIT_DNLD (1 << 28) /* uCode Download */ 140#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */
136#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ 141#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */
137#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ 142#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */
138#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ 143#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */
@@ -226,6 +231,10 @@
226#define CSR_EEPROM_GP_VALID_MSK (0x00000007) 231#define CSR_EEPROM_GP_VALID_MSK (0x00000007)
227#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) 232#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000)
228#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) 233#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180)
234#define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */
235#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */
236#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */
237#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */
229 238
230/* CSR GIO */ 239/* CSR GIO */
231#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) 240#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002)
@@ -251,6 +260,11 @@
251 260
252/* HPET MEM debug */ 261/* HPET MEM debug */
253#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000) 262#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000)
263
264/* DRAM INT TABLE */
265#define CSR_DRAM_INT_TBL_ENABLE (1 << 31)
266#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27)
267
254/*=== HBUS (Host-side Bus) ===*/ 268/*=== HBUS (Host-side Bus) ===*/
255#define HBUS_BASE (0x400) 269#define HBUS_BASE (0x400)
256/* 270/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index db069801bc41..2cf014f523be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -68,7 +68,7 @@ struct iwl_debugfs {
68 struct dentry *dir_rf; 68 struct dentry *dir_rf;
69 struct dir_data_files { 69 struct dir_data_files {
70 struct dentry *file_sram; 70 struct dentry *file_sram;
71 struct dentry *file_eeprom; 71 struct dentry *file_nvm;
72 struct dentry *file_stations; 72 struct dentry *file_stations;
73 struct dentry *file_rx_statistics; 73 struct dentry *file_rx_statistics;
74 struct dentry *file_tx_statistics; 74 struct dentry *file_tx_statistics;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index ffc4be3842b2..af70229144b3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -172,7 +172,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
172 struct iwl_priv *priv = (struct iwl_priv *)file->private_data; 172 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
173 const size_t bufsz = sizeof(buf); 173 const size_t bufsz = sizeof(buf);
174 174
175 iwl_grab_nic_access(priv);
176 for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { 175 for (i = priv->dbgfs->sram_len; i > 0; i -= 4) {
177 val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ 176 val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \
178 priv->dbgfs->sram_len - i); 177 priv->dbgfs->sram_len - i);
@@ -192,7 +191,6 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
192 pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); 191 pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
193 } 192 }
194 pos += scnprintf(buf + pos, bufsz - pos, "\n"); 193 pos += scnprintf(buf + pos, bufsz - pos, "\n");
195 iwl_release_nic_access(priv);
196 194
197 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 195 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
198 return ret; 196 return ret;
@@ -292,7 +290,7 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf,
292 return ret; 290 return ret;
293} 291}
294 292
295static ssize_t iwl_dbgfs_eeprom_read(struct file *file, 293static ssize_t iwl_dbgfs_nvm_read(struct file *file,
296 char __user *user_buf, 294 char __user *user_buf,
297 size_t count, 295 size_t count,
298 loff_t *ppos) 296 loff_t *ppos)
@@ -306,7 +304,7 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
306 buf_size = 4 * eeprom_len + 256; 304 buf_size = 4 * eeprom_len + 256;
307 305
308 if (eeprom_len % 16) { 306 if (eeprom_len % 16) {
309 IWL_ERR(priv, "EEPROM size is not multiple of 16.\n"); 307 IWL_ERR(priv, "NVM size is not multiple of 16.\n");
310 return -ENODATA; 308 return -ENODATA;
311 } 309 }
312 310
@@ -318,6 +316,13 @@ static ssize_t iwl_dbgfs_eeprom_read(struct file *file,
318 } 316 }
319 317
320 ptr = priv->eeprom; 318 ptr = priv->eeprom;
319 if (!ptr) {
320 IWL_ERR(priv, "Invalid EEPROM/OTP memory\n");
321 return -ENOMEM;
322 }
323 pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n",
324 (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
325 ? "OTP" : "EEPROM");
321 for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { 326 for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) {
322 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); 327 pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs);
323 hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, 328 hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos,
@@ -375,51 +380,53 @@ static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf,
375 } 380 }
376 381
377 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); 382 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
378 channels = supp_band->channels; 383 if (supp_band) {
384 channels = supp_band->channels;
379 385
380 pos += scnprintf(buf + pos, bufsz - pos,
381 "Displaying %d channels in 2.4GHz band 802.11bg):\n",
382 supp_band->n_channels);
383
384 for (i = 0; i < supp_band->n_channels; i++)
385 pos += scnprintf(buf + pos, bufsz - pos, 386 pos += scnprintf(buf + pos, bufsz - pos,
386 "%d: %ddBm: BSS%s%s, %s.\n", 387 "Displaying %d channels in 2.4GHz band 802.11bg):\n",
387 ieee80211_frequency_to_channel( 388 supp_band->n_channels);
388 channels[i].center_freq),
389 channels[i].max_power,
390 channels[i].flags & IEEE80211_CHAN_RADAR ?
391 " (IEEE 802.11h required)" : "",
392 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
393 || (channels[i].flags &
394 IEEE80211_CHAN_RADAR)) ? "" :
395 ", IBSS",
396 channels[i].flags &
397 IEEE80211_CHAN_PASSIVE_SCAN ?
398 "passive only" : "active/passive");
399 389
390 for (i = 0; i < supp_band->n_channels; i++)
391 pos += scnprintf(buf + pos, bufsz - pos,
392 "%d: %ddBm: BSS%s%s, %s.\n",
393 ieee80211_frequency_to_channel(
394 channels[i].center_freq),
395 channels[i].max_power,
396 channels[i].flags & IEEE80211_CHAN_RADAR ?
397 " (IEEE 802.11h required)" : "",
398 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
399 || (channels[i].flags &
400 IEEE80211_CHAN_RADAR)) ? "" :
401 ", IBSS",
402 channels[i].flags &
403 IEEE80211_CHAN_PASSIVE_SCAN ?
404 "passive only" : "active/passive");
405 }
400 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); 406 supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ);
401 channels = supp_band->channels; 407 if (supp_band) {
402 408 channels = supp_band->channels;
403 pos += scnprintf(buf + pos, bufsz - pos,
404 "Displaying %d channels in 5.2GHz band (802.11a)\n",
405 supp_band->n_channels);
406 409
407 for (i = 0; i < supp_band->n_channels; i++)
408 pos += scnprintf(buf + pos, bufsz - pos, 410 pos += scnprintf(buf + pos, bufsz - pos,
409 "%d: %ddBm: BSS%s%s, %s.\n", 411 "Displaying %d channels in 5.2GHz band (802.11a)\n",
410 ieee80211_frequency_to_channel( 412 supp_band->n_channels);
411 channels[i].center_freq),
412 channels[i].max_power,
413 channels[i].flags & IEEE80211_CHAN_RADAR ?
414 " (IEEE 802.11h required)" : "",
415 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
416 || (channels[i].flags &
417 IEEE80211_CHAN_RADAR)) ? "" :
418 ", IBSS",
419 channels[i].flags &
420 IEEE80211_CHAN_PASSIVE_SCAN ?
421 "passive only" : "active/passive");
422 413
414 for (i = 0; i < supp_band->n_channels; i++)
415 pos += scnprintf(buf + pos, bufsz - pos,
416 "%d: %ddBm: BSS%s%s, %s.\n",
417 ieee80211_frequency_to_channel(
418 channels[i].center_freq),
419 channels[i].max_power,
420 channels[i].flags & IEEE80211_CHAN_RADAR ?
421 " (IEEE 802.11h required)" : "",
422 ((channels[i].flags & IEEE80211_CHAN_NO_IBSS)
423 || (channels[i].flags &
424 IEEE80211_CHAN_RADAR)) ? "" :
425 ", IBSS",
426 channels[i].flags &
427 IEEE80211_CHAN_PASSIVE_SCAN ?
428 "passive only" : "active/passive");
429 }
423 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); 430 ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
424 kfree(buf); 431 kfree(buf);
425 return ret; 432 return ret;
@@ -564,7 +571,7 @@ static ssize_t iwl_dbgfs_interrupt_write(struct file *file,
564 571
565DEBUGFS_READ_WRITE_FILE_OPS(sram); 572DEBUGFS_READ_WRITE_FILE_OPS(sram);
566DEBUGFS_WRITE_FILE_OPS(log_event); 573DEBUGFS_WRITE_FILE_OPS(log_event);
567DEBUGFS_READ_FILE_OPS(eeprom); 574DEBUGFS_READ_FILE_OPS(nvm);
568DEBUGFS_READ_FILE_OPS(stations); 575DEBUGFS_READ_FILE_OPS(stations);
569DEBUGFS_READ_FILE_OPS(rx_statistics); 576DEBUGFS_READ_FILE_OPS(rx_statistics);
570DEBUGFS_READ_FILE_OPS(tx_statistics); 577DEBUGFS_READ_FILE_OPS(tx_statistics);
@@ -598,7 +605,7 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
598 605
599 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); 606 DEBUGFS_ADD_DIR(data, dbgfs->dir_drv);
600 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); 607 DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv);
601 DEBUGFS_ADD_FILE(eeprom, data); 608 DEBUGFS_ADD_FILE(nvm, data);
602 DEBUGFS_ADD_FILE(sram, data); 609 DEBUGFS_ADD_FILE(sram, data);
603 DEBUGFS_ADD_FILE(log_event, data); 610 DEBUGFS_ADD_FILE(log_event, data);
604 DEBUGFS_ADD_FILE(stations, data); 611 DEBUGFS_ADD_FILE(stations, data);
@@ -629,7 +636,7 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
629 if (!priv->dbgfs) 636 if (!priv->dbgfs)
630 return; 637 return;
631 638
632 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_eeprom); 639 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
633 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics); 640 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_rx_statistics);
634 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics); 641 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_tx_statistics);
635 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); 642 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 3049ba25c3fc..2dafc26fb6a8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -382,6 +382,7 @@ struct iwl_rx_queue {
382 u32 read; 382 u32 read;
383 u32 write; 383 u32 write;
384 u32 free_count; 384 u32 free_count;
385 u32 write_actual;
385 struct list_head rx_free; 386 struct list_head rx_free;
386 struct list_head rx_used; 387 struct list_head rx_used;
387 int need_update; 388 int need_update;
@@ -499,22 +500,13 @@ struct iwl_qos_info {
499#define STA_PS_STATUS_WAKE 0 500#define STA_PS_STATUS_WAKE 0
500#define STA_PS_STATUS_SLEEP 1 501#define STA_PS_STATUS_SLEEP 1
501 502
502struct iwl3945_tid_data {
503 u16 seq_number;
504};
505
506struct iwl3945_hw_key {
507 enum ieee80211_key_alg alg;
508 int keylen;
509 u8 key[32];
510};
511 503
512struct iwl3945_station_entry { 504struct iwl3945_station_entry {
513 struct iwl3945_addsta_cmd sta; 505 struct iwl3945_addsta_cmd sta;
514 struct iwl3945_tid_data tid[MAX_TID_COUNT]; 506 struct iwl_tid_data tid[MAX_TID_COUNT];
515 u8 used; 507 u8 used;
516 u8 ps_status; 508 u8 ps_status;
517 struct iwl3945_hw_key keyinfo; 509 struct iwl_hw_key keyinfo;
518}; 510};
519 511
520struct iwl_station_entry { 512struct iwl_station_entry {
@@ -823,6 +815,11 @@ enum {
823 MEASUREMENT_ACTIVE = (1 << 1), 815 MEASUREMENT_ACTIVE = (1 << 1),
824}; 816};
825 817
818enum iwl_nvm_type {
819 NVM_DEVICE_TYPE_EEPROM = 0,
820 NVM_DEVICE_TYPE_OTP,
821};
822
826/* interrupt statistics */ 823/* interrupt statistics */
827struct isr_statistics { 824struct isr_statistics {
828 u32 hw; 825 u32 hw;
@@ -900,6 +897,7 @@ struct iwl_priv {
900 /* spinlock */ 897 /* spinlock */
901 spinlock_t lock; /* protect general shared data */ 898 spinlock_t lock; /* protect general shared data */
902 spinlock_t hcmd_lock; /* protect hcmd */ 899 spinlock_t hcmd_lock; /* protect hcmd */
900 spinlock_t reg_lock; /* protect hw register access */
903 struct mutex mutex; 901 struct mutex mutex;
904 902
905 /* basic pci-network driver stuff */ 903 /* basic pci-network driver stuff */
@@ -1033,6 +1031,7 @@ struct iwl_priv {
1033 1031
1034 /* eeprom */ 1032 /* eeprom */
1035 u8 *eeprom; 1033 u8 *eeprom;
1034 int nvm_device_type;
1036 struct iwl_eeprom_calib_info *calib_info; 1035 struct iwl_eeprom_calib_info *calib_info;
1037 1036
1038 enum nl80211_iftype iw_mode; 1037 enum nl80211_iftype iw_mode;
@@ -1050,7 +1049,16 @@ struct iwl_priv {
1050 /*End*/ 1049 /*End*/
1051 struct iwl_hw_params hw_params; 1050 struct iwl_hw_params hw_params;
1052 1051
1052 /* INT ICT Table */
1053 u32 *ict_tbl;
1054 dma_addr_t ict_tbl_dma;
1055 dma_addr_t aligned_ict_tbl_dma;
1056 int ict_index;
1057 void *ict_tbl_vir;
1058 u32 inta;
1059 bool use_ict;
1053 1060
1061 u32 inta_mask;
1054 /* Current association information needed to configure the 1062 /* Current association information needed to configure the
1055 * hardware */ 1063 * hardware */
1056 u16 assoc_id; 1064 u16 assoc_id;
@@ -1105,7 +1113,7 @@ struct iwl_priv {
1105 u32 disable_tx_power_cal; 1113 u32 disable_tx_power_cal;
1106 struct work_struct run_time_calib_work; 1114 struct work_struct run_time_calib_work;
1107 struct timer_list statistics_periodic; 1115 struct timer_list statistics_periodic;
1108 1116 bool hw_ready;
1109 /*For 3945*/ 1117 /*For 3945*/
1110#define IWL_DEFAULT_TX_POWER 0x0F 1118#define IWL_DEFAULT_TX_POWER 0x0F
1111 1119
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
index 401438aec19c..cefa501e5971 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c
@@ -152,6 +152,32 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv)
152} 152}
153EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); 153EXPORT_SYMBOL(iwlcore_eeprom_verify_signature);
154 154
155static int iwlcore_get_nvm_type(struct iwl_priv *priv)
156{
157 u32 otpgp;
158 int nvm_type;
159
160 /* OTP only valid for CP/PP and after */
161 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
162 case CSR_HW_REV_TYPE_3945:
163 case CSR_HW_REV_TYPE_4965:
164 case CSR_HW_REV_TYPE_5300:
165 case CSR_HW_REV_TYPE_5350:
166 case CSR_HW_REV_TYPE_5100:
167 case CSR_HW_REV_TYPE_5150:
168 nvm_type = NVM_DEVICE_TYPE_EEPROM;
169 break;
170 default:
171 otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
172 if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT)
173 nvm_type = NVM_DEVICE_TYPE_OTP;
174 else
175 nvm_type = NVM_DEVICE_TYPE_EEPROM;
176 break;
177 }
178 return nvm_type;
179}
180
155/* 181/*
156 * The device's EEPROM semaphore prevents conflicts between driver and uCode 182 * The device's EEPROM semaphore prevents conflicts between driver and uCode
157 * when accessing the EEPROM; each access is a series of pulses to/from the 183 * when accessing the EEPROM; each access is a series of pulses to/from the
@@ -198,6 +224,33 @@ const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
198} 224}
199EXPORT_SYMBOL(iwlcore_eeprom_query_addr); 225EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
200 226
227static int iwl_init_otp_access(struct iwl_priv *priv)
228{
229 int ret;
230
231 /* Enable 40MHz radio clock */
232 _iwl_write32(priv, CSR_GP_CNTRL,
233 _iwl_read32(priv, CSR_GP_CNTRL) |
234 CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
235
236 /* wait for clock to be ready */
237 ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL,
238 CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
239 25000);
240 if (ret < 0)
241 IWL_ERR(priv, "Time out access OTP\n");
242 else {
243 if (!ret) {
244 iwl_set_bits_prph(priv, APMG_PS_CTRL_REG,
245 APMG_PS_CTRL_VAL_RESET_REQ);
246 udelay(5);
247 iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG,
248 APMG_PS_CTRL_VAL_RESET_REQ);
249 }
250 }
251 return ret;
252}
253
201/** 254/**
202 * iwl_eeprom_init - read EEPROM contents 255 * iwl_eeprom_init - read EEPROM contents
203 * 256 *
@@ -209,11 +262,18 @@ int iwl_eeprom_init(struct iwl_priv *priv)
209{ 262{
210 u16 *e; 263 u16 *e;
211 u32 gp = iwl_read32(priv, CSR_EEPROM_GP); 264 u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
212 int sz = priv->cfg->eeprom_size; 265 int sz;
213 int ret; 266 int ret;
214 u16 addr; 267 u16 addr;
268 u32 otpgp;
269
270 priv->nvm_device_type = iwlcore_get_nvm_type(priv);
215 271
216 /* allocate eeprom */ 272 /* allocate eeprom */
273 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP)
274 priv->cfg->eeprom_size =
275 OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL;
276 sz = priv->cfg->eeprom_size;
217 priv->eeprom = kzalloc(sz, GFP_KERNEL); 277 priv->eeprom = kzalloc(sz, GFP_KERNEL);
218 if (!priv->eeprom) { 278 if (!priv->eeprom) {
219 ret = -ENOMEM; 279 ret = -ENOMEM;
@@ -235,30 +295,77 @@ int iwl_eeprom_init(struct iwl_priv *priv)
235 ret = -ENOENT; 295 ret = -ENOENT;
236 goto err; 296 goto err;
237 } 297 }
238 298 if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) {
239 /* eeprom is an array of 16bit values */ 299 ret = iwl_init_otp_access(priv);
240 for (addr = 0; addr < sz; addr += sizeof(u16)) { 300 if (ret) {
241 u32 r; 301 IWL_ERR(priv, "Failed to initialize OTP access.\n");
242 302 ret = -ENOENT;
243 _iwl_write32(priv, CSR_EEPROM_REG, 303 goto err;
244 CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); 304 }
245 305 _iwl_write32(priv, CSR_EEPROM_GP,
246 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, 306 iwl_read32(priv, CSR_EEPROM_GP) &
247 CSR_EEPROM_REG_READ_VALID_MSK, 307 ~CSR_EEPROM_GP_IF_OWNER_MSK);
248 IWL_EEPROM_ACCESS_TIMEOUT); 308 /* clear */
249 if (ret < 0) { 309 _iwl_write32(priv, CSR_OTP_GP_REG,
250 IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); 310 iwl_read32(priv, CSR_OTP_GP_REG) |
251 goto done; 311 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK |
312 CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK);
313
314 for (addr = 0; addr < sz; addr += sizeof(u16)) {
315 u32 r;
316
317 _iwl_write32(priv, CSR_EEPROM_REG,
318 CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
319
320 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
321 CSR_EEPROM_REG_READ_VALID_MSK,
322 IWL_EEPROM_ACCESS_TIMEOUT);
323 if (ret < 0) {
324 IWL_ERR(priv, "Time out reading OTP[%d]\n", addr);
325 goto done;
326 }
327 r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
328 /* check for ECC errors: */
329 otpgp = iwl_read32(priv, CSR_OTP_GP_REG);
330 if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) {
331 /* stop in this case */
332 IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n");
333 goto done;
334 }
335 if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) {
336 /* continue in this case */
337 _iwl_write32(priv, CSR_OTP_GP_REG,
338 iwl_read32(priv, CSR_OTP_GP_REG) |
339 CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK);
340 IWL_ERR(priv, "Correctable OTP ECC error, continue read\n");
341 }
342 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
343 }
344 } else {
345 /* eeprom is an array of 16bit values */
346 for (addr = 0; addr < sz; addr += sizeof(u16)) {
347 u32 r;
348
349 _iwl_write32(priv, CSR_EEPROM_REG,
350 CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
351
352 ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG,
353 CSR_EEPROM_REG_READ_VALID_MSK,
354 IWL_EEPROM_ACCESS_TIMEOUT);
355 if (ret < 0) {
356 IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr);
357 goto done;
358 }
359 r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
360 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
252 } 361 }
253 r = _iwl_read_direct32(priv, CSR_EEPROM_REG);
254 e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16));
255 } 362 }
256 ret = 0; 363 ret = 0;
257done: 364done:
258 priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); 365 priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
259err: 366err:
260 if (ret) 367 if (ret)
261 kfree(priv->eeprom); 368 iwl_eeprom_free(priv);
262alloc_err: 369alloc_err:
263 return ret; 370 return ret;
264} 371}
@@ -301,6 +408,8 @@ EXPORT_SYMBOL(iwl_eeprom_query_addr);
301 408
302u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) 409u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
303{ 410{
411 if (!priv->eeprom)
412 return 0;
304 return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); 413 return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
305} 414}
306EXPORT_SYMBOL(iwl_eeprom_query16); 415EXPORT_SYMBOL(iwl_eeprom_query16);
@@ -481,8 +590,8 @@ int iwl_init_channel_map(struct iwl_priv *priv)
481 /* First write that fat is not enabled, and then enable 590 /* First write that fat is not enabled, and then enable
482 * one by one */ 591 * one by one */
483 ch_info->fat_extension_channel = 592 ch_info->fat_extension_channel =
484 (IEEE80211_CHAN_NO_FAT_ABOVE | 593 (IEEE80211_CHAN_NO_HT40PLUS |
485 IEEE80211_CHAN_NO_FAT_BELOW); 594 IEEE80211_CHAN_NO_HT40MINUS);
486 595
487 if (!(is_channel_valid(ch_info))) { 596 if (!(is_channel_valid(ch_info))) {
488 IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " 597 IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - "
@@ -561,7 +670,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
561 fat_extension_chan = 0; 670 fat_extension_chan = 0;
562 else 671 else
563 fat_extension_chan = 672 fat_extension_chan =
564 IEEE80211_CHAN_NO_FAT_BELOW; 673 IEEE80211_CHAN_NO_HT40MINUS;
565 674
566 /* Set up driver's info for lower half */ 675 /* Set up driver's info for lower half */
567 iwl_set_fat_chan_info(priv, ieeeband, 676 iwl_set_fat_chan_info(priv, ieeeband,
@@ -573,7 +682,7 @@ int iwl_init_channel_map(struct iwl_priv *priv)
573 iwl_set_fat_chan_info(priv, ieeeband, 682 iwl_set_fat_chan_info(priv, ieeeband,
574 (eeprom_ch_index[ch] + 4), 683 (eeprom_ch_index[ch] + 4),
575 &(eeprom_ch_info[ch]), 684 &(eeprom_ch_info[ch]),
576 IEEE80211_CHAN_NO_FAT_ABOVE); 685 IEEE80211_CHAN_NO_HT40PLUS);
577 } 686 }
578 } 687 }
579 688
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index 3479153d96ca..195b4ef12c27 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -179,6 +179,10 @@ struct iwl_eeprom_channel {
179#define EEPROM_5050_TX_POWER_VERSION (4) 179#define EEPROM_5050_TX_POWER_VERSION (4)
180#define EEPROM_5050_EEPROM_VERSION (0x21E) 180#define EEPROM_5050_EEPROM_VERSION (0x21E)
181 181
182/* OTP */
183#define OTP_LOWER_BLOCKS_TOTAL (3)
184#define OTP_BLOCK_SIZE (0x400)
185
182/* 2.4 GHz */ 186/* 2.4 GHz */
183extern const u8 iwl_eeprom_band_1[14]; 187extern const u8 iwl_eeprom_band_1[14];
184 188
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 083ea1ffbe87..d30cb0275d19 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -131,9 +131,23 @@ static inline void __iwl_set_bit(const char *f, u32 l,
131 IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); 131 IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
132 _iwl_write32(priv, reg, val); 132 _iwl_write32(priv, reg, val);
133} 133}
134#define iwl_set_bit(p, r, m) __iwl_set_bit(__FILE__, __LINE__, p, r, m) 134static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m)
135{
136 unsigned long reg_flags;
137
138 spin_lock_irqsave(&p->reg_lock, reg_flags);
139 __iwl_set_bit(__FILE__, __LINE__, p, r, m);
140 spin_unlock_irqrestore(&p->reg_lock, reg_flags);
141}
135#else 142#else
136#define iwl_set_bit(p, r, m) _iwl_set_bit(p, r, m) 143static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m)
144{
145 unsigned long reg_flags;
146
147 spin_lock_irqsave(&p->reg_lock, reg_flags);
148 _iwl_set_bit(p, r, m);
149 spin_unlock_irqrestore(&p->reg_lock, reg_flags);
150}
137#endif 151#endif
138 152
139static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) 153static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
@@ -148,19 +162,30 @@ static inline void __iwl_clear_bit(const char *f, u32 l,
148 IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); 162 IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
149 _iwl_write32(priv, reg, val); 163 _iwl_write32(priv, reg, val);
150} 164}
151#define iwl_clear_bit(p, r, m) __iwl_clear_bit(__FILE__, __LINE__, p, r, m) 165static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m)
166{
167 unsigned long reg_flags;
168
169 spin_lock_irqsave(&p->reg_lock, reg_flags);
170 __iwl_clear_bit(__FILE__, __LINE__, p, r, m);
171 spin_unlock_irqrestore(&p->reg_lock, reg_flags);
172}
152#else 173#else
153#define iwl_clear_bit(p, r, m) _iwl_clear_bit(p, r, m) 174static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m)
175{
176 unsigned long reg_flags;
177
178 spin_lock_irqsave(&p->reg_lock, reg_flags);
179 _iwl_clear_bit(p, r, m);
180 spin_unlock_irqrestore(&p->reg_lock, reg_flags);
181}
154#endif 182#endif
155 183
156static inline int _iwl_grab_nic_access(struct iwl_priv *priv) 184static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
157{ 185{
158 int ret; 186 int ret;
159 u32 val; 187 u32 val;
160#ifdef CONFIG_IWLWIFI_DEBUG 188
161 if (atomic_read(&priv->restrict_refcnt))
162 return 0;
163#endif
164 /* this bit wakes up the NIC */ 189 /* this bit wakes up the NIC */
165 _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); 190 _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
166 ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, 191 ret = _iwl_poll_bit(priv, CSR_GP_CNTRL,
@@ -170,12 +195,10 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
170 if (ret < 0) { 195 if (ret < 0) {
171 val = _iwl_read32(priv, CSR_GP_CNTRL); 196 val = _iwl_read32(priv, CSR_GP_CNTRL);
172 IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); 197 IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val);
198 _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI);
173 return -EIO; 199 return -EIO;
174 } 200 }
175 201
176#ifdef CONFIG_IWLWIFI_DEBUG
177 atomic_inc(&priv->restrict_refcnt);
178#endif
179 return 0; 202 return 0;
180} 203}
181 204
@@ -183,9 +206,6 @@ static inline int _iwl_grab_nic_access(struct iwl_priv *priv)
183static inline int __iwl_grab_nic_access(const char *f, u32 l, 206static inline int __iwl_grab_nic_access(const char *f, u32 l,
184 struct iwl_priv *priv) 207 struct iwl_priv *priv)
185{ 208{
186 if (atomic_read(&priv->restrict_refcnt))
187 IWL_ERR(priv, "Grabbing access while already held %s %d.\n", f, l);
188
189 IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); 209 IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l);
190 return _iwl_grab_nic_access(priv); 210 return _iwl_grab_nic_access(priv);
191} 211}
@@ -198,18 +218,13 @@ static inline int __iwl_grab_nic_access(const char *f, u32 l,
198 218
199static inline void _iwl_release_nic_access(struct iwl_priv *priv) 219static inline void _iwl_release_nic_access(struct iwl_priv *priv)
200{ 220{
201#ifdef CONFIG_IWLWIFI_DEBUG 221 _iwl_clear_bit(priv, CSR_GP_CNTRL,
202 if (atomic_dec_and_test(&priv->restrict_refcnt)) 222 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
203#endif
204 _iwl_clear_bit(priv, CSR_GP_CNTRL,
205 CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
206} 223}
207#ifdef CONFIG_IWLWIFI_DEBUG 224#ifdef CONFIG_IWLWIFI_DEBUG
208static inline void __iwl_release_nic_access(const char *f, u32 l, 225static inline void __iwl_release_nic_access(const char *f, u32 l,
209 struct iwl_priv *priv) 226 struct iwl_priv *priv)
210{ 227{
211 if (atomic_read(&priv->restrict_refcnt) <= 0)
212 IWL_ERR(priv, "Release unheld nic access at line %s %d.\n", f, l);
213 228
214 IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); 229 IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l);
215 _iwl_release_nic_access(priv); 230 _iwl_release_nic_access(priv);
@@ -230,16 +245,37 @@ static inline u32 __iwl_read_direct32(const char *f, u32 l,
230 struct iwl_priv *priv, u32 reg) 245 struct iwl_priv *priv, u32 reg)
231{ 246{
232 u32 value = _iwl_read_direct32(priv, reg); 247 u32 value = _iwl_read_direct32(priv, reg);
233 if (!atomic_read(&priv->restrict_refcnt))
234 IWL_ERR(priv, "Nic access not held from %s %d\n", f, l);
235 IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, 248 IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value,
236 f, l); 249 f, l);
237 return value; 250 return value;
238} 251}
239#define iwl_read_direct32(priv, reg) \ 252static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg)
240 __iwl_read_direct32(__FILE__, __LINE__, priv, reg) 253{
254 u32 value;
255 unsigned long reg_flags;
256
257 spin_lock_irqsave(&priv->reg_lock, reg_flags);
258 iwl_grab_nic_access(priv);
259 value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg);
260 iwl_release_nic_access(priv);
261 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
262 return value;
263}
264
241#else 265#else
242#define iwl_read_direct32 _iwl_read_direct32 266static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg)
267{
268 u32 value;
269 unsigned long reg_flags;
270
271 spin_lock_irqsave(&priv->reg_lock, reg_flags);
272 iwl_grab_nic_access(priv);
273 value = _iwl_read_direct32(priv, reg);
274 iwl_release_nic_access(priv);
275 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
276 return value;
277
278}
243#endif 279#endif
244 280
245static inline void _iwl_write_direct32(struct iwl_priv *priv, 281static inline void _iwl_write_direct32(struct iwl_priv *priv,
@@ -247,19 +283,17 @@ static inline void _iwl_write_direct32(struct iwl_priv *priv,
247{ 283{
248 _iwl_write32(priv, reg, value); 284 _iwl_write32(priv, reg, value);
249} 285}
250#ifdef CONFIG_IWLWIFI_DEBUG 286static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
251static void __iwl_write_direct32(const char *f , u32 line,
252 struct iwl_priv *priv, u32 reg, u32 value)
253{ 287{
254 if (!atomic_read(&priv->restrict_refcnt)) 288 unsigned long reg_flags;
255 IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); 289
256 _iwl_write_direct32(priv, reg, value); 290 spin_lock_irqsave(&priv->reg_lock, reg_flags);
291 if (!iwl_grab_nic_access(priv)) {
292 _iwl_write_direct32(priv, reg, value);
293 iwl_release_nic_access(priv);
294 }
295 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
257} 296}
258#define iwl_write_direct32(priv, reg, value) \
259 __iwl_write_direct32(__func__, __LINE__, priv, reg, value)
260#else
261#define iwl_write_direct32 _iwl_write_direct32
262#endif
263 297
264static inline void iwl_write_reg_buf(struct iwl_priv *priv, 298static inline void iwl_write_reg_buf(struct iwl_priv *priv,
265 u32 reg, u32 len, u32 *values) 299 u32 reg, u32 len, u32 *values)
@@ -268,14 +302,23 @@ static inline void iwl_write_reg_buf(struct iwl_priv *priv,
268 302
269 if ((priv != NULL) && (values != NULL)) { 303 if ((priv != NULL) && (values != NULL)) {
270 for (; 0 < len; len -= count, reg += count, values++) 304 for (; 0 < len; len -= count, reg += count, values++)
271 _iwl_write_direct32(priv, reg, *values); 305 iwl_write_direct32(priv, reg, *values);
272 } 306 }
273} 307}
274 308
275static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, 309static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr,
276 u32 mask, int timeout) 310 u32 mask, int timeout)
277{ 311{
278 return _iwl_poll_bit(priv, addr, mask, mask, timeout); 312 int t = 0;
313
314 do {
315 if ((iwl_read_direct32(priv, addr) & mask) == mask)
316 return t;
317 udelay(IWL_POLL_INTERVAL);
318 t += IWL_POLL_INTERVAL;
319 } while (t < timeout);
320
321 return -ETIMEDOUT;
279} 322}
280 323
281#ifdef CONFIG_IWLWIFI_DEBUG 324#ifdef CONFIG_IWLWIFI_DEBUG
@@ -305,20 +348,18 @@ static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg)
305 rmb(); 348 rmb();
306 return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); 349 return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
307} 350}
308#ifdef CONFIG_IWLWIFI_DEBUG 351static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg)
309static inline u32 __iwl_read_prph(const char *f, u32 line,
310 struct iwl_priv *priv, u32 reg)
311{ 352{
312 if (!atomic_read(&priv->restrict_refcnt)) 353 unsigned long reg_flags;
313 IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); 354 u32 val;
314 return _iwl_read_prph(priv, reg);
315}
316 355
317#define iwl_read_prph(priv, reg) \ 356 spin_lock_irqsave(&priv->reg_lock, reg_flags);
318 __iwl_read_prph(__func__, __LINE__, priv, reg) 357 iwl_grab_nic_access(priv);
319#else 358 val = _iwl_read_prph(priv, reg);
320#define iwl_read_prph _iwl_read_prph 359 iwl_release_nic_access(priv);
321#endif 360 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
361 return val;
362}
322 363
323static inline void _iwl_write_prph(struct iwl_priv *priv, 364static inline void _iwl_write_prph(struct iwl_priv *priv,
324 u32 addr, u32 val) 365 u32 addr, u32 val)
@@ -328,83 +369,107 @@ static inline void _iwl_write_prph(struct iwl_priv *priv,
328 wmb(); 369 wmb();
329 _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); 370 _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
330} 371}
331#ifdef CONFIG_IWLWIFI_DEBUG 372
332static inline void __iwl_write_prph(const char *f, u32 line, 373static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
333 struct iwl_priv *priv, u32 addr, u32 val)
334{ 374{
335 if (!atomic_read(&priv->restrict_refcnt)) 375 unsigned long reg_flags;
336 IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
337 _iwl_write_prph(priv, addr, val);
338}
339 376
340#define iwl_write_prph(priv, addr, val) \ 377 spin_lock_irqsave(&priv->reg_lock, reg_flags);
341 __iwl_write_prph(__func__, __LINE__, priv, addr, val); 378 if (!iwl_grab_nic_access(priv)) {
342#else 379 _iwl_write_prph(priv, addr, val);
343#define iwl_write_prph _iwl_write_prph 380 iwl_release_nic_access(priv);
344#endif 381 }
382 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
383}
345 384
346#define _iwl_set_bits_prph(priv, reg, mask) \ 385#define _iwl_set_bits_prph(priv, reg, mask) \
347 _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) 386 _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask))
348#ifdef CONFIG_IWLWIFI_DEBUG 387
349static inline void __iwl_set_bits_prph(const char *f, u32 line, 388static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
350 struct iwl_priv *priv,
351 u32 reg, u32 mask)
352{ 389{
353 if (!atomic_read(&priv->restrict_refcnt)) 390 unsigned long reg_flags;
354 IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line);
355 391
392 spin_lock_irqsave(&priv->reg_lock, reg_flags);
393 iwl_grab_nic_access(priv);
356 _iwl_set_bits_prph(priv, reg, mask); 394 _iwl_set_bits_prph(priv, reg, mask);
395 iwl_release_nic_access(priv);
396 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
357} 397}
358#define iwl_set_bits_prph(priv, reg, mask) \
359 __iwl_set_bits_prph(__func__, __LINE__, priv, reg, mask)
360#else
361#define iwl_set_bits_prph _iwl_set_bits_prph
362#endif
363 398
364#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ 399#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \
365 _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) 400 _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits))
366 401
367#ifdef CONFIG_IWLWIFI_DEBUG 402static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
368static inline void __iwl_set_bits_mask_prph(const char *f, u32 line, 403 u32 bits, u32 mask)
369 struct iwl_priv *priv, u32 reg, u32 bits, u32 mask)
370{ 404{
371 if (!atomic_read(&priv->restrict_refcnt)) 405 unsigned long reg_flags;
372 IWL_ERR(priv, "Nic access not held from %s line %d\n", f, line); 406
407 spin_lock_irqsave(&priv->reg_lock, reg_flags);
408 iwl_grab_nic_access(priv);
373 _iwl_set_bits_mask_prph(priv, reg, bits, mask); 409 _iwl_set_bits_mask_prph(priv, reg, bits, mask);
410 iwl_release_nic_access(priv);
411 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
374} 412}
375#define iwl_set_bits_mask_prph(priv, reg, bits, mask) \
376 __iwl_set_bits_mask_prph(__func__, __LINE__, priv, reg, bits, mask)
377#else
378#define iwl_set_bits_mask_prph _iwl_set_bits_mask_prph
379#endif
380 413
381static inline void iwl_clear_bits_prph(struct iwl_priv 414static inline void iwl_clear_bits_prph(struct iwl_priv
382 *priv, u32 reg, u32 mask) 415 *priv, u32 reg, u32 mask)
383{ 416{
384 u32 val = _iwl_read_prph(priv, reg); 417 unsigned long reg_flags;
418 u32 val;
419
420 spin_lock_irqsave(&priv->reg_lock, reg_flags);
421 iwl_grab_nic_access(priv);
422 val = _iwl_read_prph(priv, reg);
385 _iwl_write_prph(priv, reg, (val & ~mask)); 423 _iwl_write_prph(priv, reg, (val & ~mask));
424 iwl_release_nic_access(priv);
425 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
386} 426}
387 427
388static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) 428static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr)
389{ 429{
390 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); 430 unsigned long reg_flags;
431 u32 value;
432
433 spin_lock_irqsave(&priv->reg_lock, reg_flags);
434 iwl_grab_nic_access(priv);
435
436 _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
391 rmb(); 437 rmb();
392 return iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); 438 value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
439
440 iwl_release_nic_access(priv);
441 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
442 return value;
393} 443}
394 444
395static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) 445static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
396{ 446{
397 iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); 447 unsigned long reg_flags;
398 wmb(); 448
399 iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); 449 spin_lock_irqsave(&priv->reg_lock, reg_flags);
450 if (!iwl_grab_nic_access(priv)) {
451 _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
452 wmb();
453 _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val);
454 iwl_release_nic_access(priv);
455 }
456 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
400} 457}
401 458
402static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, 459static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
403 u32 len, u32 *values) 460 u32 len, u32 *values)
404{ 461{
405 iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); 462 unsigned long reg_flags;
406 wmb(); 463
407 for (; 0 < len; len -= sizeof(u32), values++) 464 spin_lock_irqsave(&priv->reg_lock, reg_flags);
408 iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); 465 if (!iwl_grab_nic_access(priv)) {
466 _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
467 wmb();
468 for (; 0 < len; len -= sizeof(u32), values++)
469 _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values);
470
471 iwl_release_nic_access(priv);
472 }
473 spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
409} 474}
410#endif 475#endif
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
index fae84262efb6..2b8d40b37a1c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
@@ -145,18 +145,14 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q)
145 goto exit_unlock; 145 goto exit_unlock;
146 } 146 }
147 147
148 ret = iwl_grab_nic_access(priv); 148 q->write_actual = (q->write & ~0x7);
149 if (ret) 149 iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
150 goto exit_unlock;
151
152 /* Device expects a multiple of 8 */
153 iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write & ~0x7);
154 iwl_release_nic_access(priv);
155 150
156 /* Else device is assumed to be awake */ 151 /* Else device is assumed to be awake */
157 } else { 152 } else {
158 /* Device expects a multiple of 8 */ 153 /* Device expects a multiple of 8 */
159 iwl_write32(priv, rx_wrt_ptr_reg, q->write & ~0x7); 154 q->write_actual = (q->write & ~0x7);
155 iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual);
160 } 156 }
161 157
162 q->need_update = 0; 158 q->need_update = 0;
@@ -218,7 +214,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
218 214
219 /* If we've added more space for the firmware to place data, tell it. 215 /* If we've added more space for the firmware to place data, tell it.
220 * Increment device's write pointer in multiples of 8. */ 216 * Increment device's write pointer in multiples of 8. */
221 if (write != (rxq->write & ~0x7)) { 217 if (rxq->write_actual != (rxq->write & ~0x7)) {
222 spin_lock_irqsave(&rxq->lock, flags); 218 spin_lock_irqsave(&rxq->lock, flags);
223 rxq->need_update = 1; 219 rxq->need_update = 1;
224 spin_unlock_irqrestore(&rxq->lock, flags); 220 spin_unlock_irqrestore(&rxq->lock, flags);
@@ -238,7 +234,7 @@ EXPORT_SYMBOL(iwl_rx_queue_restock);
238 * Also restock the Rx queue via iwl_rx_queue_restock. 234 * Also restock the Rx queue via iwl_rx_queue_restock.
239 * This is called as a scheduled work item (except for during initialization) 235 * This is called as a scheduled work item (except for during initialization)
240 */ 236 */
241void iwl_rx_allocate(struct iwl_priv *priv) 237void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
242{ 238{
243 struct iwl_rx_queue *rxq = &priv->rxq; 239 struct iwl_rx_queue *rxq = &priv->rxq;
244 struct list_head *element; 240 struct list_head *element;
@@ -260,7 +256,8 @@ void iwl_rx_allocate(struct iwl_priv *priv)
260 256
261 /* Alloc a new receive buffer */ 257 /* Alloc a new receive buffer */
262 rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, 258 rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
263 GFP_KERNEL); 259 priority);
260
264 if (!rxb->skb) { 261 if (!rxb->skb) {
265 IWL_CRIT(priv, "Can not allocate SKB buffers\n"); 262 IWL_CRIT(priv, "Can not allocate SKB buffers\n");
266 /* We don't reschedule replenish work here -- we will 263 /* We don't reschedule replenish work here -- we will
@@ -295,7 +292,7 @@ void iwl_rx_replenish(struct iwl_priv *priv)
295{ 292{
296 unsigned long flags; 293 unsigned long flags;
297 294
298 iwl_rx_allocate(priv); 295 iwl_rx_allocate(priv, GFP_KERNEL);
299 296
300 spin_lock_irqsave(&priv->lock, flags); 297 spin_lock_irqsave(&priv->lock, flags);
301 iwl_rx_queue_restock(priv); 298 iwl_rx_queue_restock(priv);
@@ -303,6 +300,14 @@ void iwl_rx_replenish(struct iwl_priv *priv)
303} 300}
304EXPORT_SYMBOL(iwl_rx_replenish); 301EXPORT_SYMBOL(iwl_rx_replenish);
305 302
303void iwl_rx_replenish_now(struct iwl_priv *priv)
304{
305 iwl_rx_allocate(priv, GFP_ATOMIC);
306
307 iwl_rx_queue_restock(priv);
308}
309EXPORT_SYMBOL(iwl_rx_replenish_now);
310
306 311
307/* Assumes that the skb field of the buffers in 'pool' is kept accurate. 312/* Assumes that the skb field of the buffers in 'pool' is kept accurate.
308 * If an SKB has been detached, the POOL needs to have its SKB set to NULL 313 * If an SKB has been detached, the POOL needs to have its SKB set to NULL
@@ -358,6 +363,7 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv)
358 /* Set us so that we have processed and used all buffers, but have 363 /* Set us so that we have processed and used all buffers, but have
359 * not restocked the Rx queue with fresh buffers */ 364 * not restocked the Rx queue with fresh buffers */
360 rxq->read = rxq->write = 0; 365 rxq->read = rxq->write = 0;
366 rxq->write_actual = 0;
361 rxq->free_count = 0; 367 rxq->free_count = 0;
362 rxq->need_update = 0; 368 rxq->need_update = 0;
363 return 0; 369 return 0;
@@ -396,6 +402,7 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
396 /* Set us so that we have processed and used all buffers, but have 402 /* Set us so that we have processed and used all buffers, but have
397 * not restocked the Rx queue with fresh buffers */ 403 * not restocked the Rx queue with fresh buffers */
398 rxq->read = rxq->write = 0; 404 rxq->read = rxq->write = 0;
405 rxq->write_actual = 0;
399 rxq->free_count = 0; 406 rxq->free_count = 0;
400 spin_unlock_irqrestore(&rxq->lock, flags); 407 spin_unlock_irqrestore(&rxq->lock, flags);
401} 408}
@@ -403,18 +410,12 @@ EXPORT_SYMBOL(iwl_rx_queue_reset);
403 410
404int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) 411int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
405{ 412{
406 int ret;
407 unsigned long flags;
408 u32 rb_size; 413 u32 rb_size;
409 const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ 414 const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
410 const u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT why this stalls RX */ 415 u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */
411 416
412 spin_lock_irqsave(&priv->lock, flags); 417 if (!priv->cfg->use_isr_legacy)
413 ret = iwl_grab_nic_access(priv); 418 rb_timeout = RX_RB_TIMEOUT;
414 if (ret) {
415 spin_unlock_irqrestore(&priv->lock, flags);
416 return ret;
417 }
418 419
419 if (priv->cfg->mod_params->amsdu_size_8K) 420 if (priv->cfg->mod_params->amsdu_size_8K)
420 rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; 421 rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
@@ -452,35 +453,19 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
452 (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| 453 (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
453 (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); 454 (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
454 455
455 iwl_release_nic_access(priv);
456
457 iwl_write32(priv, CSR_INT_COALESCING, 0x40); 456 iwl_write32(priv, CSR_INT_COALESCING, 0x40);
458 457
459 spin_unlock_irqrestore(&priv->lock, flags);
460
461 return 0; 458 return 0;
462} 459}
463 460
464int iwl_rxq_stop(struct iwl_priv *priv) 461int iwl_rxq_stop(struct iwl_priv *priv)
465{ 462{
466 int ret;
467 unsigned long flags;
468
469 spin_lock_irqsave(&priv->lock, flags);
470 ret = iwl_grab_nic_access(priv);
471 if (unlikely(ret)) {
472 spin_unlock_irqrestore(&priv->lock, flags);
473 return ret;
474 }
475 463
476 /* stop Rx DMA */ 464 /* stop Rx DMA */
477 iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); 465 iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
478 iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, 466 iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG,
479 FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); 467 FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
480 468
481 iwl_release_nic_access(priv);
482 spin_unlock_irqrestore(&priv->lock, flags);
483
484 return 0; 469 return 0;
485} 470}
486EXPORT_SYMBOL(iwl_rxq_stop); 471EXPORT_SYMBOL(iwl_rxq_stop);
@@ -582,8 +567,8 @@ void iwl_rx_statistics(struct iwl_priv *priv,
582 567
583 iwl_leds_background(priv); 568 iwl_leds_background(priv);
584 569
585 if (priv->cfg->ops->lib->temperature && change) 570 if (priv->cfg->ops->lib->temp_ops.temperature && change)
586 priv->cfg->ops->lib->temperature(priv); 571 priv->cfg->ops->lib->temp_ops.temperature(priv);
587} 572}
588EXPORT_SYMBOL(iwl_rx_statistics); 573EXPORT_SYMBOL(iwl_rx_statistics);
589 574
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 065214b55895..f6d4af5c7509 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -586,6 +586,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
586 u8 rx_ant = priv->hw_params.valid_rx_ant; 586 u8 rx_ant = priv->hw_params.valid_rx_ant;
587 u8 rate; 587 u8 rate;
588 bool is_active = false; 588 bool is_active = false;
589 int chan_mod;
589 590
590 conf = ieee80211_get_hw_conf(priv->hw); 591 conf = ieee80211_get_hw_conf(priv->hw);
591 592
@@ -703,7 +704,9 @@ static void iwl_bg_request_scan(struct work_struct *data)
703 if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { 704 if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
704 band = IEEE80211_BAND_2GHZ; 705 band = IEEE80211_BAND_2GHZ;
705 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; 706 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
706 if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) { 707 chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
708 >> RXON_FLG_CHANNEL_MODE_POS;
709 if (chan_mod == CHANNEL_MODE_PURE_40) {
707 rate = IWL_RATE_6M_PLCP; 710 rate = IWL_RATE_6M_PLCP;
708 } else { 711 } else {
709 rate = IWL_RATE_1M_PLCP; 712 rate = IWL_RATE_1M_PLCP;
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index a82cca0a30c7..85ae7a62109c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -102,13 +102,8 @@ int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
102 return ret; 102 return ret;
103 } 103 }
104 104
105 /* restore this queue's parameters in nic hardware. */
106 ret = iwl_grab_nic_access(priv);
107 if (ret)
108 return ret;
109 iwl_write_direct32(priv, HBUS_TARG_WRPTR, 105 iwl_write_direct32(priv, HBUS_TARG_WRPTR,
110 txq->q.write_ptr | (txq_id << 8)); 106 txq->q.write_ptr | (txq_id << 8));
111 iwl_release_nic_access(priv);
112 107
113 /* else not in power-save mode, uCode will never sleep when we're 108 /* else not in power-save mode, uCode will never sleep when we're
114 * trying to tx (during RFKILL, we're not trying to tx). */ 109 * trying to tx (during RFKILL, we're not trying to tx). */
@@ -429,11 +424,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
429 goto error_kw; 424 goto error_kw;
430 } 425 }
431 spin_lock_irqsave(&priv->lock, flags); 426 spin_lock_irqsave(&priv->lock, flags);
432 ret = iwl_grab_nic_access(priv);
433 if (unlikely(ret)) {
434 spin_unlock_irqrestore(&priv->lock, flags);
435 goto error_reset;
436 }
437 427
438 /* Turn off all Tx DMA fifos */ 428 /* Turn off all Tx DMA fifos */
439 priv->cfg->ops->lib->txq_set_sched(priv, 0); 429 priv->cfg->ops->lib->txq_set_sched(priv, 0);
@@ -441,7 +431,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
441 /* Tell NIC where to find the "keep warm" buffer */ 431 /* Tell NIC where to find the "keep warm" buffer */
442 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); 432 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
443 433
444 iwl_release_nic_access(priv);
445 spin_unlock_irqrestore(&priv->lock, flags); 434 spin_unlock_irqrestore(&priv->lock, flags);
446 435
447 /* Alloc and init all Tx queues, including the command queue (#4) */ 436 /* Alloc and init all Tx queues, including the command queue (#4) */
@@ -460,7 +449,6 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
460 449
461 error: 450 error:
462 iwl_hw_txq_ctx_free(priv); 451 iwl_hw_txq_ctx_free(priv);
463 error_reset:
464 iwl_free_dma_ptr(priv, &priv->kw); 452 iwl_free_dma_ptr(priv, &priv->kw);
465 error_kw: 453 error_kw:
466 iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); 454 iwl_free_dma_ptr(priv, &priv->scd_bc_tbls);
@@ -478,10 +466,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
478 466
479 /* Turn off all Tx DMA fifos */ 467 /* Turn off all Tx DMA fifos */
480 spin_lock_irqsave(&priv->lock, flags); 468 spin_lock_irqsave(&priv->lock, flags);
481 if (iwl_grab_nic_access(priv)) {
482 spin_unlock_irqrestore(&priv->lock, flags);
483 return;
484 }
485 469
486 priv->cfg->ops->lib->txq_set_sched(priv, 0); 470 priv->cfg->ops->lib->txq_set_sched(priv, 0);
487 471
@@ -492,7 +476,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
492 FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), 476 FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
493 1000); 477 1000);
494 } 478 }
495 iwl_release_nic_access(priv);
496 spin_unlock_irqrestore(&priv->lock, flags); 479 spin_unlock_irqrestore(&priv->lock, flags);
497 480
498 /* Deallocate memory for all Tx queues */ 481 /* Deallocate memory for all Tx queues */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index c32ec809053f..c434f493daf5 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -340,7 +340,7 @@ static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
340 unsigned long flags; 340 unsigned long flags;
341 341
342 spin_lock_irqsave(&priv->sta_lock, flags); 342 spin_lock_irqsave(&priv->sta_lock, flags);
343 memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl3945_hw_key)); 343 memset(&priv->stations_39[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key));
344 memset(&priv->stations_39[sta_id].sta.key, 0, 344 memset(&priv->stations_39[sta_id].sta.key, 0,
345 sizeof(struct iwl4965_keyinfo)); 345 sizeof(struct iwl4965_keyinfo));
346 priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; 346 priv->stations_39[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC;
@@ -578,8 +578,7 @@ static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
578 int sta_id) 578 int sta_id)
579{ 579{
580 struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; 580 struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
581 struct iwl3945_hw_key *keyinfo = 581 struct iwl_hw_key *keyinfo = &priv->stations_39[sta_id].keyinfo;
582 &priv->stations_39[sta_id].keyinfo;
583 582
584 switch (keyinfo->alg) { 583 switch (keyinfo->alg) {
585 case ALG_CCMP: 584 case ALG_CCMP:
@@ -1687,7 +1686,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
1687 u32 i; 1686 u32 i;
1688 u32 desc, time, count, base, data1; 1687 u32 desc, time, count, base, data1;
1689 u32 blink1, blink2, ilink1, ilink2; 1688 u32 blink1, blink2, ilink1, ilink2;
1690 int rc;
1691 1689
1692 base = le32_to_cpu(priv->card_alive.error_event_table_ptr); 1690 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
1693 1691
@@ -1696,11 +1694,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
1696 return; 1694 return;
1697 } 1695 }
1698 1696
1699 rc = iwl_grab_nic_access(priv);
1700 if (rc) {
1701 IWL_WARN(priv, "Can not read from adapter at this time.\n");
1702 return;
1703 }
1704 1697
1705 count = iwl_read_targ_mem(priv, base); 1698 count = iwl_read_targ_mem(priv, base);
1706 1699
@@ -1735,8 +1728,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
1735 ilink1, ilink2, data1); 1728 ilink1, ilink2, data1);
1736 } 1729 }
1737 1730
1738 iwl_release_nic_access(priv);
1739
1740} 1731}
1741 1732
1742#define EVENT_START_OFFSET (6 * sizeof(u32)) 1733#define EVENT_START_OFFSET (6 * sizeof(u32))
@@ -1744,7 +1735,6 @@ static void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
1744/** 1735/**
1745 * iwl3945_print_event_log - Dump error event log to syslog 1736 * iwl3945_print_event_log - Dump error event log to syslog
1746 * 1737 *
1747 * NOTE: Must be called with iwl_grab_nic_access() already obtained!
1748 */ 1738 */
1749static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, 1739static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
1750 u32 num_events, u32 mode) 1740 u32 num_events, u32 mode)
@@ -1787,7 +1777,6 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
1787 1777
1788static void iwl3945_dump_nic_event_log(struct iwl_priv *priv) 1778static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
1789{ 1779{
1790 int rc;
1791 u32 base; /* SRAM byte address of event log header */ 1780 u32 base; /* SRAM byte address of event log header */
1792 u32 capacity; /* event log capacity in # entries */ 1781 u32 capacity; /* event log capacity in # entries */
1793 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ 1782 u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */
@@ -1801,12 +1790,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
1801 return; 1790 return;
1802 } 1791 }
1803 1792
1804 rc = iwl_grab_nic_access(priv);
1805 if (rc) {
1806 IWL_WARN(priv, "Can not read from adapter at this time.\n");
1807 return;
1808 }
1809
1810 /* event log header */ 1793 /* event log header */
1811 capacity = iwl_read_targ_mem(priv, base); 1794 capacity = iwl_read_targ_mem(priv, base);
1812 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); 1795 mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
@@ -1818,7 +1801,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
1818 /* bail out if nothing in log */ 1801 /* bail out if nothing in log */
1819 if (size == 0) { 1802 if (size == 0) {
1820 IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); 1803 IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
1821 iwl_release_nic_access(priv);
1822 return; 1804 return;
1823 } 1805 }
1824 1806
@@ -1834,7 +1816,6 @@ static void iwl3945_dump_nic_event_log(struct iwl_priv *priv)
1834 /* (then/else) start at top of log */ 1816 /* (then/else) start at top of log */
1835 iwl3945_print_event_log(priv, 0, next_entry, mode); 1817 iwl3945_print_event_log(priv, 0, next_entry, mode);
1836 1818
1837 iwl_release_nic_access(priv);
1838} 1819}
1839 1820
1840static void iwl3945_irq_tasklet(struct iwl_priv *priv) 1821static void iwl3945_irq_tasklet(struct iwl_priv *priv)
@@ -1953,11 +1934,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1953 priv->isr_stats.tx++; 1934 priv->isr_stats.tx++;
1954 1935
1955 iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); 1936 iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6));
1956 if (!iwl_grab_nic_access(priv)) { 1937 iwl_write_direct32(priv, FH39_TCSR_CREDIT
1957 iwl_write_direct32(priv, FH39_TCSR_CREDIT 1938 (FH39_SRVC_CHNL), 0x0);
1958 (FH39_SRVC_CHNL), 0x0);
1959 iwl_release_nic_access(priv);
1960 }
1961 handled |= CSR_INT_BIT_FH_TX; 1939 handled |= CSR_INT_BIT_FH_TX;
1962 } 1940 }
1963 1941
@@ -1966,9 +1944,9 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
1966 priv->isr_stats.unhandled++; 1944 priv->isr_stats.unhandled++;
1967 } 1945 }
1968 1946
1969 if (inta & ~CSR_INI_SET_MASK) { 1947 if (inta & ~priv->inta_mask) {
1970 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", 1948 IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n",
1971 inta & ~CSR_INI_SET_MASK); 1949 inta & ~priv->inta_mask);
1972 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); 1950 IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh);
1973 } 1951 }
1974 1952
@@ -2132,10 +2110,6 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le
2132 2110
2133 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); 2111 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
2134 2112
2135 rc = iwl_grab_nic_access(priv);
2136 if (rc)
2137 return rc;
2138
2139 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, 2113 iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
2140 IWL39_RTC_INST_LOWER_BOUND); 2114 IWL39_RTC_INST_LOWER_BOUND);
2141 2115
@@ -2156,7 +2130,6 @@ static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 le
2156 } 2130 }
2157 } 2131 }
2158 2132
2159 iwl_release_nic_access(priv);
2160 2133
2161 if (!errcnt) 2134 if (!errcnt)
2162 IWL_DEBUG_INFO(priv, 2135 IWL_DEBUG_INFO(priv,
@@ -2180,10 +2153,6 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
2180 2153
2181 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); 2154 IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
2182 2155
2183 rc = iwl_grab_nic_access(priv);
2184 if (rc)
2185 return rc;
2186
2187 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { 2156 for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
2188 /* read data comes through single port, auto-incr addr */ 2157 /* read data comes through single port, auto-incr addr */
2189 /* NOTE: Use the debugless read so we don't flood kernel log 2158 /* NOTE: Use the debugless read so we don't flood kernel log
@@ -2204,8 +2173,6 @@ static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32
2204 } 2173 }
2205 } 2174 }
2206 2175
2207 iwl_release_nic_access(priv);
2208
2209 return rc; 2176 return rc;
2210} 2177}
2211 2178
@@ -2529,20 +2496,11 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
2529{ 2496{
2530 dma_addr_t pinst; 2497 dma_addr_t pinst;
2531 dma_addr_t pdata; 2498 dma_addr_t pdata;
2532 int rc = 0;
2533 unsigned long flags;
2534 2499
2535 /* bits 31:0 for 3945 */ 2500 /* bits 31:0 for 3945 */
2536 pinst = priv->ucode_code.p_addr; 2501 pinst = priv->ucode_code.p_addr;
2537 pdata = priv->ucode_data_backup.p_addr; 2502 pdata = priv->ucode_data_backup.p_addr;
2538 2503
2539 spin_lock_irqsave(&priv->lock, flags);
2540 rc = iwl_grab_nic_access(priv);
2541 if (rc) {
2542 spin_unlock_irqrestore(&priv->lock, flags);
2543 return rc;
2544 }
2545
2546 /* Tell bootstrap uCode where to find image to load */ 2504 /* Tell bootstrap uCode where to find image to load */
2547 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); 2505 iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
2548 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); 2506 iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
@@ -2554,13 +2512,9 @@ static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
2554 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, 2512 iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
2555 priv->ucode_code.len | BSM_DRAM_INST_LOAD); 2513 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
2556 2514
2557 iwl_release_nic_access(priv);
2558
2559 spin_unlock_irqrestore(&priv->lock, flags);
2560
2561 IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); 2515 IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
2562 2516
2563 return rc; 2517 return 0;
2564} 2518}
2565 2519
2566/** 2520/**
@@ -2613,7 +2567,6 @@ static void iwl3945_init_alive_start(struct iwl_priv *priv)
2613 */ 2567 */
2614static void iwl3945_alive_start(struct iwl_priv *priv) 2568static void iwl3945_alive_start(struct iwl_priv *priv)
2615{ 2569{
2616 int rc = 0;
2617 int thermal_spin = 0; 2570 int thermal_spin = 0;
2618 u32 rfkill; 2571 u32 rfkill;
2619 2572
@@ -2638,15 +2591,8 @@ static void iwl3945_alive_start(struct iwl_priv *priv)
2638 2591
2639 priv->cfg->ops->smgmt->clear_station_table(priv); 2592 priv->cfg->ops->smgmt->clear_station_table(priv);
2640 2593
2641 rc = iwl_grab_nic_access(priv);
2642 if (rc) {
2643 IWL_WARN(priv, "Can not read RFKILL status from adapter\n");
2644 return;
2645 }
2646
2647 rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); 2594 rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
2648 IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); 2595 IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
2649 iwl_release_nic_access(priv);
2650 2596
2651 if (rfkill & 0x1) { 2597 if (rfkill & 0x1) {
2652 clear_bit(STATUS_RF_KILL_HW, &priv->status); 2598 clear_bit(STATUS_RF_KILL_HW, &priv->status);
@@ -2792,13 +2738,8 @@ static void __iwl3945_down(struct iwl_priv *priv)
2792 iwl3945_hw_txq_ctx_stop(priv); 2738 iwl3945_hw_txq_ctx_stop(priv);
2793 iwl3945_hw_rxq_stop(priv); 2739 iwl3945_hw_rxq_stop(priv);
2794 2740
2795 spin_lock_irqsave(&priv->lock, flags); 2741 iwl_write_prph(priv, APMG_CLK_DIS_REG,
2796 if (!iwl_grab_nic_access(priv)) { 2742 APMG_CLK_VAL_DMA_CLK_RQT);
2797 iwl_write_prph(priv, APMG_CLK_DIS_REG,
2798 APMG_CLK_VAL_DMA_CLK_RQT);
2799 iwl_release_nic_access(priv);
2800 }
2801 spin_unlock_irqrestore(&priv->lock, flags);
2802 2743
2803 udelay(5); 2744 udelay(5);
2804 2745
@@ -4243,6 +4184,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4243 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); 4184 IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
4244 priv->cfg = cfg; 4185 priv->cfg = cfg;
4245 priv->pci_dev = pdev; 4186 priv->pci_dev = pdev;
4187 priv->inta_mask = CSR_INI_SET_MASK;
4246 4188
4247#ifdef CONFIG_IWLWIFI_DEBUG 4189#ifdef CONFIG_IWLWIFI_DEBUG
4248 priv->debug_level = iwl3945_mod_params.debug; 4190 priv->debug_level = iwl3945_mod_params.debug;
@@ -4289,6 +4231,11 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4289 * PCI Tx retries from interfering with C3 CPU state */ 4231 * PCI Tx retries from interfering with C3 CPU state */
4290 pci_write_config_byte(pdev, 0x41, 0x00); 4232 pci_write_config_byte(pdev, 0x41, 0x00);
4291 4233
4234 /* this spin lock will be used in apm_ops.init and EEPROM access
4235 * we should init now
4236 */
4237 spin_lock_init(&priv->reg_lock);
4238
4292 /* amp init */ 4239 /* amp init */
4293 err = priv->cfg->ops->lib->apm_ops.init(priv); 4240 err = priv->cfg->ops->lib->apm_ops.init(priv);
4294 if (err < 0) { 4241 if (err < 0) {
@@ -4344,8 +4291,8 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4344 4291
4345 pci_enable_msi(priv->pci_dev); 4292 pci_enable_msi(priv->pci_dev);
4346 4293
4347 err = request_irq(priv->pci_dev->irq, iwl_isr, IRQF_SHARED, 4294 err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr,
4348 DRV_NAME, priv); 4295 IRQF_SHARED, DRV_NAME, priv);
4349 if (err) { 4296 if (err) {
4350 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); 4297 IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
4351 goto out_disable_msi; 4298 goto out_disable_msi;
diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig
new file mode 100644
index 000000000000..ae84ddabcc1c
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/Kconfig
@@ -0,0 +1,23 @@
1config IWM
2 tristate "Intel Wireless Multicomm 3200 WiFi driver"
3 depends on MMC && WLAN_80211 && EXPERIMENTAL
4 select LIB80211
5 select FW_LOADER
6 select RFKILL
7
8config IWM_DEBUG
9 bool "Enable full debugging output in iwmc3200wifi"
10 depends on IWM && DEBUG_FS
11 ---help---
12 This option will enable debug tracing and setting for iwm
13
14 You can set the debug level and module through debugfs. By
15 default all modules are set to the IWL_DL_ERR level.
16 To see the list of debug modules and levels, see iwm/debug.h
17
18 For example, if you want the full MLME debug output:
19 echo 0xff > /debug/iwm/phyN/debug/mlme
20
21 Or, if you want the full debug, for all modules:
22 echo 0xff > /debug/iwm/phyN/debug/level
23 echo 0xff > /debug/iwm/phyN/debug/modules
diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile
new file mode 100644
index 000000000000..7cb415e5c11b
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/Makefile
@@ -0,0 +1,5 @@
1obj-$(CONFIG_IWM) := iwmc3200wifi.o
2iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o
3iwmc3200wifi-objs += commands.o wext.o cfg80211.o eeprom.o rfkill.o
4
5iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o
diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h
new file mode 100644
index 000000000000..836663eec257
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/bus.h
@@ -0,0 +1,57 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#ifndef __IWM_BUS_H__
25#define __IWM_BUS_H__
26
27#include "iwm.h"
28
29struct iwm_if_ops {
30 int (*enable)(struct iwm_priv *iwm);
31 int (*disable)(struct iwm_priv *iwm);
32 int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count);
33
34 int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir);
35 void (*debugfs_exit)(struct iwm_priv *iwm);
36
37 const char *umac_name;
38 const char *calib_lmac_name;
39 const char *lmac_name;
40};
41
42static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
43{
44 return iwm->bus_ops->send_chunk(iwm, buf, count);
45}
46
47static inline int iwm_bus_enable(struct iwm_priv *iwm)
48{
49 return iwm->bus_ops->enable(iwm);
50}
51
52static inline int iwm_bus_disable(struct iwm_priv *iwm)
53{
54 return iwm->bus_ops->disable(iwm);
55}
56
57#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
new file mode 100644
index 000000000000..3256ad2c96ce
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -0,0 +1,409 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/netdevice.h>
26#include <linux/wireless.h>
27#include <linux/ieee80211.h>
28#include <net/cfg80211.h>
29
30#include "iwm.h"
31#include "commands.h"
32#include "cfg80211.h"
33#include "debug.h"
34
35#define RATETAB_ENT(_rate, _rateid, _flags) \
36 { \
37 .bitrate = (_rate), \
38 .hw_value = (_rateid), \
39 .flags = (_flags), \
40 }
41
42#define CHAN2G(_channel, _freq, _flags) { \
43 .band = IEEE80211_BAND_2GHZ, \
44 .center_freq = (_freq), \
45 .hw_value = (_channel), \
46 .flags = (_flags), \
47 .max_antenna_gain = 0, \
48 .max_power = 30, \
49}
50
51#define CHAN5G(_channel, _flags) { \
52 .band = IEEE80211_BAND_5GHZ, \
53 .center_freq = 5000 + (5 * (_channel)), \
54 .hw_value = (_channel), \
55 .flags = (_flags), \
56 .max_antenna_gain = 0, \
57 .max_power = 30, \
58}
59
60static struct ieee80211_rate iwm_rates[] = {
61 RATETAB_ENT(10, 0x1, 0),
62 RATETAB_ENT(20, 0x2, 0),
63 RATETAB_ENT(55, 0x4, 0),
64 RATETAB_ENT(110, 0x8, 0),
65 RATETAB_ENT(60, 0x10, 0),
66 RATETAB_ENT(90, 0x20, 0),
67 RATETAB_ENT(120, 0x40, 0),
68 RATETAB_ENT(180, 0x80, 0),
69 RATETAB_ENT(240, 0x100, 0),
70 RATETAB_ENT(360, 0x200, 0),
71 RATETAB_ENT(480, 0x400, 0),
72 RATETAB_ENT(540, 0x800, 0),
73};
74
75#define iwm_a_rates (iwm_rates + 4)
76#define iwm_a_rates_size 8
77#define iwm_g_rates (iwm_rates + 0)
78#define iwm_g_rates_size 12
79
80static struct ieee80211_channel iwm_2ghz_channels[] = {
81 CHAN2G(1, 2412, 0),
82 CHAN2G(2, 2417, 0),
83 CHAN2G(3, 2422, 0),
84 CHAN2G(4, 2427, 0),
85 CHAN2G(5, 2432, 0),
86 CHAN2G(6, 2437, 0),
87 CHAN2G(7, 2442, 0),
88 CHAN2G(8, 2447, 0),
89 CHAN2G(9, 2452, 0),
90 CHAN2G(10, 2457, 0),
91 CHAN2G(11, 2462, 0),
92 CHAN2G(12, 2467, 0),
93 CHAN2G(13, 2472, 0),
94 CHAN2G(14, 2484, 0),
95};
96
97static struct ieee80211_channel iwm_5ghz_a_channels[] = {
98 CHAN5G(34, 0), CHAN5G(36, 0),
99 CHAN5G(38, 0), CHAN5G(40, 0),
100 CHAN5G(42, 0), CHAN5G(44, 0),
101 CHAN5G(46, 0), CHAN5G(48, 0),
102 CHAN5G(52, 0), CHAN5G(56, 0),
103 CHAN5G(60, 0), CHAN5G(64, 0),
104 CHAN5G(100, 0), CHAN5G(104, 0),
105 CHAN5G(108, 0), CHAN5G(112, 0),
106 CHAN5G(116, 0), CHAN5G(120, 0),
107 CHAN5G(124, 0), CHAN5G(128, 0),
108 CHAN5G(132, 0), CHAN5G(136, 0),
109 CHAN5G(140, 0), CHAN5G(149, 0),
110 CHAN5G(153, 0), CHAN5G(157, 0),
111 CHAN5G(161, 0), CHAN5G(165, 0),
112 CHAN5G(184, 0), CHAN5G(188, 0),
113 CHAN5G(192, 0), CHAN5G(196, 0),
114 CHAN5G(200, 0), CHAN5G(204, 0),
115 CHAN5G(208, 0), CHAN5G(212, 0),
116 CHAN5G(216, 0),
117};
118
119static struct ieee80211_supported_band iwm_band_2ghz = {
120 .channels = iwm_2ghz_channels,
121 .n_channels = ARRAY_SIZE(iwm_2ghz_channels),
122 .bitrates = iwm_g_rates,
123 .n_bitrates = iwm_g_rates_size,
124};
125
126static struct ieee80211_supported_band iwm_band_5ghz = {
127 .channels = iwm_5ghz_a_channels,
128 .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels),
129 .bitrates = iwm_a_rates,
130 .n_bitrates = iwm_a_rates_size,
131};
132
133int iwm_cfg80211_inform_bss(struct iwm_priv *iwm)
134{
135 struct wiphy *wiphy = iwm_to_wiphy(iwm);
136 struct iwm_bss_info *bss, *next;
137 struct iwm_umac_notif_bss_info *umac_bss;
138 struct ieee80211_mgmt *mgmt;
139 struct ieee80211_channel *channel;
140 struct ieee80211_supported_band *band;
141 s32 signal;
142 int freq;
143
144 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
145 umac_bss = bss->bss;
146 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
147
148 if (umac_bss->band == UMAC_BAND_2GHZ)
149 band = wiphy->bands[IEEE80211_BAND_2GHZ];
150 else if (umac_bss->band == UMAC_BAND_5GHZ)
151 band = wiphy->bands[IEEE80211_BAND_5GHZ];
152 else {
153 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
154 return -EINVAL;
155 }
156
157 freq = ieee80211_channel_to_frequency(umac_bss->channel);
158 channel = ieee80211_get_channel(wiphy, freq);
159 signal = umac_bss->rssi * 100;
160
161 if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt,
162 le16_to_cpu(umac_bss->frame_len),
163 signal, GFP_KERNEL))
164 return -EINVAL;
165 }
166
167 return 0;
168}
169
170static int iwm_cfg80211_change_iface(struct wiphy *wiphy, int ifindex,
171 enum nl80211_iftype type, u32 *flags,
172 struct vif_params *params)
173{
174 struct net_device *ndev;
175 struct wireless_dev *wdev;
176 struct iwm_priv *iwm;
177 u32 old_mode;
178
179 /* we're under RTNL */
180 ndev = __dev_get_by_index(&init_net, ifindex);
181 if (!ndev)
182 return -ENODEV;
183
184 wdev = ndev->ieee80211_ptr;
185 iwm = ndev_to_iwm(ndev);
186 old_mode = iwm->conf.mode;
187
188 switch (type) {
189 case NL80211_IFTYPE_STATION:
190 iwm->conf.mode = UMAC_MODE_BSS;
191 break;
192 case NL80211_IFTYPE_ADHOC:
193 iwm->conf.mode = UMAC_MODE_IBSS;
194 break;
195 default:
196 return -EOPNOTSUPP;
197 }
198
199 wdev->iftype = type;
200
201 if ((old_mode == iwm->conf.mode) || !iwm->umac_profile)
202 return 0;
203
204 iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode);
205
206 if (iwm->umac_profile_active) {
207 int ret = iwm_invalidate_mlme_profile(iwm);
208 if (ret < 0)
209 IWM_ERR(iwm, "Couldn't invalidate profile\n");
210 }
211
212 return 0;
213}
214
215static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
216 struct cfg80211_scan_request *request)
217{
218 struct iwm_priv *iwm = ndev_to_iwm(ndev);
219 int ret;
220
221 if (!test_bit(IWM_STATUS_READY, &iwm->status)) {
222 IWM_ERR(iwm, "Scan while device is not ready\n");
223 return -EIO;
224 }
225
226 if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) {
227 IWM_ERR(iwm, "Scanning already\n");
228 return -EAGAIN;
229 }
230
231 if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) {
232 IWM_ERR(iwm, "Scanning being aborted\n");
233 return -EAGAIN;
234 }
235
236 set_bit(IWM_STATUS_SCANNING, &iwm->status);
237
238 ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids);
239 if (ret) {
240 clear_bit(IWM_STATUS_SCANNING, &iwm->status);
241 return ret;
242 }
243
244 iwm->scan_request = request;
245 return 0;
246}
247
248static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
249{
250 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
251
252 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
253 (iwm->conf.rts_threshold != wiphy->rts_threshold)) {
254 int ret;
255
256 iwm->conf.rts_threshold = wiphy->rts_threshold;
257
258 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
259 CFG_RTS_THRESHOLD,
260 iwm->conf.rts_threshold);
261 if (ret < 0)
262 return ret;
263 }
264
265 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
266 (iwm->conf.frag_threshold != wiphy->frag_threshold)) {
267 int ret;
268
269 iwm->conf.frag_threshold = wiphy->frag_threshold;
270
271 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
272 CFG_FRAG_THRESHOLD,
273 iwm->conf.frag_threshold);
274 if (ret < 0)
275 return ret;
276 }
277
278 return 0;
279}
280
281static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
282 struct cfg80211_ibss_params *params)
283{
284 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
285 struct ieee80211_channel *chan = params->channel;
286 struct cfg80211_bss *bss;
287
288 if (!test_bit(IWM_STATUS_READY, &iwm->status))
289 return -EIO;
290
291 /* UMAC doesn't support creating IBSS network with specified bssid.
292 * This should be removed after we have join only mode supported. */
293 if (params->bssid)
294 return -EOPNOTSUPP;
295
296 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
297 params->ssid, params->ssid_len);
298 if (!bss) {
299 iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len);
300 schedule_timeout_interruptible(2 * HZ);
301 bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL,
302 params->ssid, params->ssid_len);
303 }
304 /* IBSS join only mode is not supported by UMAC ATM */
305 if (bss) {
306 cfg80211_put_bss(bss);
307 return -EOPNOTSUPP;
308 }
309
310 iwm->channel = ieee80211_frequency_to_channel(chan->center_freq);
311 iwm->umac_profile->ibss.band = chan->band;
312 iwm->umac_profile->ibss.channel = iwm->channel;
313 iwm->umac_profile->ssid.ssid_len = params->ssid_len;
314 memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len);
315
316 if (params->bssid)
317 memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN);
318
319 return iwm_send_mlme_profile(iwm);
320}
321
322static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
323{
324 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
325
326 if (iwm->umac_profile_active)
327 return iwm_invalidate_mlme_profile(iwm);
328
329 return 0;
330}
331
332static struct cfg80211_ops iwm_cfg80211_ops = {
333 .change_virtual_intf = iwm_cfg80211_change_iface,
334 .scan = iwm_cfg80211_scan,
335 .set_wiphy_params = iwm_cfg80211_set_wiphy_params,
336 .join_ibss = iwm_cfg80211_join_ibss,
337 .leave_ibss = iwm_cfg80211_leave_ibss,
338};
339
340struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
341{
342 int ret = 0;
343 struct wireless_dev *wdev;
344
345 /*
346 * We're trying to have the following memory
347 * layout:
348 *
349 * +-------------------------+
350 * | struct wiphy |
351 * +-------------------------+
352 * | struct iwm_priv |
353 * +-------------------------+
354 * | bus private data |
355 * | (e.g. iwm_priv_sdio) |
356 * +-------------------------+
357 *
358 */
359
360 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
361 if (!wdev) {
362 dev_err(dev, "Couldn't allocate wireless device\n");
363 return ERR_PTR(-ENOMEM);
364 }
365
366 wdev->wiphy = wiphy_new(&iwm_cfg80211_ops,
367 sizeof(struct iwm_priv) + sizeof_bus);
368 if (!wdev->wiphy) {
369 dev_err(dev, "Couldn't allocate wiphy device\n");
370 ret = -ENOMEM;
371 goto out_err_new;
372 }
373
374 set_wiphy_dev(wdev->wiphy, dev);
375 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
376 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
377 BIT(NL80211_IFTYPE_ADHOC);
378 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
379 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz;
380 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
381
382 ret = wiphy_register(wdev->wiphy);
383 if (ret < 0) {
384 dev_err(dev, "Couldn't register wiphy device\n");
385 goto out_err_register;
386 }
387
388 return wdev;
389
390 out_err_register:
391 wiphy_free(wdev->wiphy);
392
393 out_err_new:
394 kfree(wdev);
395
396 return ERR_PTR(ret);
397}
398
399void iwm_wdev_free(struct iwm_priv *iwm)
400{
401 struct wireless_dev *wdev = iwm_to_wdev(iwm);
402
403 if (!wdev)
404 return;
405
406 wiphy_unregister(wdev->wiphy);
407 wiphy_free(wdev->wiphy);
408 kfree(wdev);
409}
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.h b/drivers/net/wireless/iwmc3200wifi/cfg80211.h
new file mode 100644
index 000000000000..56a34145acbf
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.h
@@ -0,0 +1,31 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#ifndef __IWM_CFG80211_H__
25#define __IWM_CFG80211_H__
26
27int iwm_cfg80211_inform_bss(struct iwm_priv *iwm);
28struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev);
29void iwm_wdev_free(struct iwm_priv *iwm);
30
31#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
new file mode 100644
index 000000000000..834a7f544e5d
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/commands.c
@@ -0,0 +1,920 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/wireless.h>
41#include <linux/etherdevice.h>
42#include <linux/ieee80211.h>
43
44#include "iwm.h"
45#include "bus.h"
46#include "hal.h"
47#include "umac.h"
48#include "commands.h"
49#include "debug.h"
50
51static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm,
52 u8 lmac_cmd_id,
53 const void *lmac_payload,
54 u16 lmac_payload_size,
55 u8 resp)
56{
57 struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT;
58 struct iwm_umac_cmd umac_cmd;
59 struct iwm_lmac_cmd lmac_cmd;
60
61 lmac_cmd.id = lmac_cmd_id;
62
63 umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH;
64 umac_cmd.resp = resp;
65
66 return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd,
67 lmac_payload, lmac_payload_size);
68}
69
70int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
71 bool resp)
72{
73 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
74 struct iwm_umac_cmd umac_cmd;
75
76 umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER;
77 umac_cmd.resp = resp;
78
79 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
80 payload, payload_size);
81}
82
83static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
84{
85 {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS},
86 {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
87 {4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
88 {4, 3, 0, COEX_CALIBRATION_FLAGS},
89 {4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
90 {4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS},
91 {4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS},
92 {4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
93 {4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
94 {4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
95 {6, 3, 0, COEX_XOR_RF_ON_FLAGS},
96 {4, 3, 0, COEX_RF_OFF_FLAGS},
97 {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
98 {4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
99 {4, 3, 0, COEX_RSRVD1_FLAGS},
100 {4, 3, 0, COEX_RSRVD2_FLAGS}
101};
102
103static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
104{
105 {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS},
106 {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
107 {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
108 {5, 5, 0, COEX_CALIBRATION_FLAGS},
109 {4, 4, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
110 {5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS},
111 {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
112 {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
113 {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
114 {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
115 {1, 1, 0, COEX_RF_ON_FLAGS},
116 {1, 1, 0, COEX_RF_OFF_FLAGS},
117 {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
118 {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
119 {1, 1, 0, COEX_RSRVD1_FLAGS},
120 {1, 1, 0, COEX_RSRVD2_FLAGS}
121};
122
123int iwm_send_prio_table(struct iwm_priv *iwm)
124{
125 struct iwm_coex_prio_table_cmd coex_table_cmd;
126 u32 coex_enabled, mode_enabled;
127
128 memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd));
129
130 coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK;
131
132 switch (iwm->conf.coexist_mode) {
133 case COEX_MODE_XOR:
134 case COEX_MODE_CM:
135 coex_enabled = 1;
136 break;
137 default:
138 coex_enabled = 0;
139 break;
140 }
141
142 switch (iwm->conf.mode) {
143 case UMAC_MODE_BSS:
144 case UMAC_MODE_IBSS:
145 mode_enabled = 1;
146 break;
147 default:
148 mode_enabled = 0;
149 break;
150 }
151
152 if (coex_enabled && mode_enabled) {
153 coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK |
154 COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK |
155 COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK;
156
157 switch (iwm->conf.coexist_mode) {
158 case COEX_MODE_XOR:
159 memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl,
160 sizeof(iwm_sta_xor_prio_tbl));
161 break;
162 case COEX_MODE_CM:
163 memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl,
164 sizeof(iwm_sta_cm_prio_tbl));
165 break;
166 default:
167 IWM_ERR(iwm, "Invalid coex_mode 0x%x\n",
168 iwm->conf.coexist_mode);
169 break;
170 }
171 } else
172 IWM_WARN(iwm, "coexistense disabled\n");
173
174 return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD,
175 &coex_table_cmd,
176 sizeof(struct iwm_coex_prio_table_cmd), 1);
177}
178
179int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
180{
181 struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
182
183 memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
184
185 cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested);
186 cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested);
187 cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested);
188 cal_cfg_cmd.ucode_cfg.flags =
189 cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK);
190
191 return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
192 sizeof(struct iwm_lmac_cal_cfg_cmd), 1);
193}
194
195int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
196{
197 struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd;
198
199 memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd));
200
201 cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested);
202 cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested);
203
204 return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd,
205 sizeof(struct iwm_lmac_cal_cfg_cmd), 0);
206}
207
208int iwm_store_rxiq_calib_result(struct iwm_priv *iwm)
209{
210 struct iwm_calib_rxiq *rxiq;
211 u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
212 int grplen = sizeof(struct iwm_calib_rxiq_group);
213
214 rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL);
215 if (!rxiq) {
216 IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n");
217 return -ENOMEM;
218 }
219
220 eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ);
221 if (IS_ERR(eeprom_rxiq)) {
222 IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n");
223 return PTR_ERR(eeprom_rxiq);
224 }
225
226 iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq;
227 iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq);
228
229 rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD;
230 rxiq->hdr.first_grp = 0;
231 rxiq->hdr.grp_num = 1;
232 rxiq->hdr.all_data_valid = 1;
233
234 memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen);
235 memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen);
236
237 return 0;
238}
239
240int iwm_send_calib_results(struct iwm_priv *iwm)
241{
242 int i, ret = 0;
243
244 for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) {
245 if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM,
246 &iwm->calib_done_map)) {
247 IWM_DBG_CMD(iwm, DBG,
248 "Send calibration %d result\n", i);
249 ret |= iwm_send_lmac_ptrough_cmd(iwm,
250 REPLY_PHY_CALIBRATION_CMD,
251 iwm->calib_res[i].buf,
252 iwm->calib_res[i].size, 0);
253
254 kfree(iwm->calib_res[i].buf);
255 iwm->calib_res[i].buf = NULL;
256 iwm->calib_res[i].size = 0;
257 }
258 }
259
260 return ret;
261}
262
263int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp)
264{
265 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
266 struct iwm_umac_cmd umac_cmd;
267 struct iwm_umac_cmd_reset reset;
268
269 reset.flags = reset_flags;
270
271 umac_cmd.id = UMAC_CMD_OPCODE_RESET;
272 umac_cmd.resp = resp;
273
274 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset,
275 sizeof(struct iwm_umac_cmd_reset));
276}
277
278int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value)
279{
280 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
281 struct iwm_umac_cmd umac_cmd;
282 struct iwm_umac_cmd_set_param_fix param;
283
284 if ((tbl != UMAC_PARAM_TBL_CFG_FIX) &&
285 (tbl != UMAC_PARAM_TBL_FA_CFG_FIX))
286 return -EINVAL;
287
288 umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX;
289 umac_cmd.resp = 0;
290
291 param.tbl = cpu_to_le16(tbl);
292 param.key = cpu_to_le16(key);
293 param.value = cpu_to_le32(value);
294
295 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &param,
296 sizeof(struct iwm_umac_cmd_set_param_fix));
297}
298
299int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
300 void *payload, u16 payload_size)
301{
302 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
303 struct iwm_umac_cmd umac_cmd;
304 struct iwm_umac_cmd_set_param_var *param_hdr;
305 u8 *param;
306 int ret;
307
308 param = kzalloc(payload_size +
309 sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL);
310 if (!param) {
311 IWM_ERR(iwm, "Couldn't allocate param\n");
312 return -ENOMEM;
313 }
314
315 param_hdr = (struct iwm_umac_cmd_set_param_var *)param;
316
317 umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR;
318 umac_cmd.resp = 0;
319
320 param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR);
321 param_hdr->key = cpu_to_le16(key);
322 param_hdr->len = cpu_to_le16(payload_size);
323 memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var),
324 payload, payload_size);
325
326 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param,
327 sizeof(struct iwm_umac_cmd_set_param_var) +
328 payload_size);
329 kfree(param);
330
331 return ret;
332}
333
334int iwm_send_umac_config(struct iwm_priv *iwm,
335 __le32 reset_flags)
336{
337 int ret;
338
339 /* Use UMAC default values */
340 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
341 CFG_POWER_INDEX, iwm->conf.power_index);
342 if (ret < 0)
343 return ret;
344
345 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX,
346 CFG_FRAG_THRESHOLD,
347 iwm->conf.frag_threshold);
348 if (ret < 0)
349 return ret;
350
351 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
352 CFG_RTS_THRESHOLD,
353 iwm->conf.rts_threshold);
354 if (ret < 0)
355 return ret;
356
357 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
358 CFG_CTS_TO_SELF, iwm->conf.cts_to_self);
359 if (ret < 0)
360 return ret;
361
362 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
363 CFG_COEX_MODE, iwm->conf.coexist_mode);
364 if (ret < 0)
365 return ret;
366
367 /*
368 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
369 CFG_ASSOCIATION_TIMEOUT,
370 iwm->conf.assoc_timeout);
371 if (ret < 0)
372 return ret;
373
374 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
375 CFG_ROAM_TIMEOUT,
376 iwm->conf.roam_timeout);
377 if (ret < 0)
378 return ret;
379
380 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
381 CFG_WIRELESS_MODE,
382 WIRELESS_MODE_11A | WIRELESS_MODE_11G);
383 if (ret < 0)
384 return ret;
385 */
386
387 ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR,
388 iwm_to_ndev(iwm)->dev_addr, ETH_ALEN);
389 if (ret < 0)
390 return ret;
391
392 /* UMAC PM static configurations */
393 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
394 CFG_PM_LEGACY_RX_TIMEOUT, 0x12C);
395 if (ret < 0)
396 return ret;
397
398 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
399 CFG_PM_LEGACY_TX_TIMEOUT, 0x15E);
400 if (ret < 0)
401 return ret;
402
403 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
404 CFG_PM_CTRL_FLAGS, 0x30001);
405 if (ret < 0)
406 return ret;
407
408 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
409 CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80);
410 if (ret < 0)
411 return ret;
412
413 /* reset UMAC */
414 ret = iwm_send_umac_reset(iwm, reset_flags, 1);
415 if (ret < 0)
416 return ret;
417
418 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
419 WAIT_NOTIF_TIMEOUT);
420 if (ret) {
421 IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
422 return ret;
423 }
424
425 return ret;
426}
427
428int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id)
429{
430 struct iwm_udma_wifi_cmd udma_cmd;
431 struct iwm_umac_cmd umac_cmd;
432 struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
433
434 udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */
435 udma_cmd.credit_group = pool_id;
436 udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
437 udma_cmd.lmac_offset = 0;
438
439 umac_cmd.id = REPLY_TX;
440 umac_cmd.color = tx_info->color;
441 umac_cmd.resp = 0;
442
443 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd,
444 skb->data, skb->len);
445}
446
447static int iwm_target_read(struct iwm_priv *iwm, __le32 address,
448 u8 *response, u32 resp_size)
449{
450 struct iwm_udma_nonwifi_cmd target_cmd;
451 struct iwm_nonwifi_cmd *cmd;
452 u16 seq_num;
453 int ret = 0;
454
455 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ;
456 target_cmd.addr = address;
457 target_cmd.op1_sz = cpu_to_le32(resp_size);
458 target_cmd.op2 = 0;
459 target_cmd.handle_by_hw = 0;
460 target_cmd.resp = 1;
461 target_cmd.eop = 1;
462
463 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
464 if (ret < 0)
465 IWM_ERR(iwm, "Couldn't send READ command\n");
466
467 /* When succeding, the send_target routine returns the seq number */
468 seq_num = ret;
469
470 ret = wait_event_interruptible_timeout(iwm->nonwifi_queue,
471 (cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num,
472 UMAC_HDI_OUT_OPCODE_READ)) != NULL,
473 2 * HZ);
474
475 if (!ret) {
476 IWM_ERR(iwm, "Didn't receive a target READ answer\n");
477 return ret;
478 }
479
480 memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr),
481 resp_size);
482
483 kfree(cmd);
484
485 return ret;
486}
487
488int iwm_read_mac(struct iwm_priv *iwm, u8 *mac)
489{
490 int ret;
491 u8 mac_align[ALIGN(ETH_ALEN, 8)];
492
493 ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR),
494 mac_align, sizeof(mac_align));
495 if (ret < 0)
496 return ret;
497
498 if (is_valid_ether_addr(mac_align))
499 memcpy(mac, mac_align, ETH_ALEN);
500 else {
501 IWM_ERR(iwm, "Invalid EEPROM MAC\n");
502 memcpy(mac, iwm->conf.mac_addr, ETH_ALEN);
503 get_random_bytes(&mac[3], 3);
504 }
505
506 return 0;
507}
508
509int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx)
510{
511 struct iwm_umac_tx_key_id tx_key_id;
512
513 if (!iwm->default_key || !iwm->default_key->in_use)
514 return -EINVAL;
515
516 tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID;
517 tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) -
518 sizeof(struct iwm_umac_wifi_if));
519
520 tx_key_id.key_idx = key_idx;
521
522 return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1);
523}
524
525static int iwm_check_profile(struct iwm_priv *iwm)
526{
527 if (!iwm->umac_profile_active)
528 return -EAGAIN;
529
530 if (iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
531 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
532 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_TKIP &&
533 iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) {
534 IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n",
535 iwm->umac_profile->sec.ucast_cipher);
536 return -EAGAIN;
537 }
538
539 if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 &&
540 iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 &&
541 iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP &&
542 iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) {
543 IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n",
544 iwm->umac_profile->sec.mcast_cipher);
545 return -EAGAIN;
546 }
547
548 if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 ||
549 iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) &&
550 (iwm->umac_profile->sec.ucast_cipher !=
551 iwm->umac_profile->sec.mcast_cipher)) {
552 IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n");
553 }
554
555 return 0;
556}
557
558int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
559 struct iwm_key *key)
560{
561 int ret;
562 u8 cmd[64], *sta_addr, *key_data, key_len;
563 s8 key_idx;
564 u16 cmd_size = 0;
565 struct iwm_umac_key_hdr *key_hdr = &key->hdr;
566 struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd;
567 struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd;
568 struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd;
569 struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd;
570
571 if (set_tx_key)
572 iwm->default_key = key;
573
574 /*
575 * We check if our current profile is valid.
576 * If not, we dont push the key, we just cache them,
577 * so that with the next siwsessid call, the keys
578 * will be actually pushed.
579 */
580 if (!remove) {
581 ret = iwm_check_profile(iwm);
582 if (ret < 0)
583 return ret;
584 }
585
586 sta_addr = key->hdr.mac;
587 key_data = key->key;
588 key_len = key->key_len;
589 key_idx = key->hdr.key_idx;
590
591 if (!remove) {
592 IWM_DBG_WEXT(iwm, DBG, "key_idx:%d set tx key:%d\n",
593 key_idx, set_tx_key);
594 IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len);
595 IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n",
596 key_hdr->mac, key_hdr->key_idx, key_hdr->multicast);
597
598 IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n",
599 iwm->umac_profile->sec.mcast_cipher,
600 iwm->umac_profile->sec.ucast_cipher);
601 IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n",
602 iwm->umac_profile->sec.auth_type,
603 iwm->umac_profile->sec.flags);
604
605 switch (key->alg) {
606 case UMAC_CIPHER_TYPE_WEP_40:
607 wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY;
608 wep40->hdr.buf_size =
609 cpu_to_le16(sizeof(struct iwm_umac_key_wep40) -
610 sizeof(struct iwm_umac_wifi_if));
611
612 memcpy(&wep40->key_hdr, key_hdr,
613 sizeof(struct iwm_umac_key_hdr));
614 memcpy(wep40->key, key_data, key_len);
615 wep40->static_key = 1;
616
617 cmd_size = sizeof(struct iwm_umac_key_wep40);
618 break;
619
620 case UMAC_CIPHER_TYPE_WEP_104:
621 wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY;
622 wep104->hdr.buf_size =
623 cpu_to_le16(sizeof(struct iwm_umac_key_wep104) -
624 sizeof(struct iwm_umac_wifi_if));
625
626 memcpy(&wep104->key_hdr, key_hdr,
627 sizeof(struct iwm_umac_key_hdr));
628 memcpy(wep104->key, key_data, key_len);
629 wep104->static_key = 1;
630
631 cmd_size = sizeof(struct iwm_umac_key_wep104);
632 break;
633
634 case UMAC_CIPHER_TYPE_CCMP:
635 key_hdr->key_idx++;
636 ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY;
637 ccmp->hdr.buf_size =
638 cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) -
639 sizeof(struct iwm_umac_wifi_if));
640
641 memcpy(&ccmp->key_hdr, key_hdr,
642 sizeof(struct iwm_umac_key_hdr));
643
644 memcpy(ccmp->key, key_data, key_len);
645
646 if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
647 memcpy(ccmp->iv_count, key->rx_seq, 6);
648
649 cmd_size = sizeof(struct iwm_umac_key_ccmp);
650 break;
651
652 case UMAC_CIPHER_TYPE_TKIP:
653 key_hdr->key_idx++;
654 tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY;
655 tkip->hdr.buf_size =
656 cpu_to_le16(sizeof(struct iwm_umac_key_tkip) -
657 sizeof(struct iwm_umac_wifi_if));
658
659 memcpy(&tkip->key_hdr, key_hdr,
660 sizeof(struct iwm_umac_key_hdr));
661
662 memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE);
663 memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE,
664 IWM_TKIP_MIC_SIZE);
665 memcpy(tkip->mic_rx_key,
666 key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE,
667 IWM_TKIP_MIC_SIZE);
668
669 if (key->flags & IW_ENCODE_EXT_RX_SEQ_VALID)
670 memcpy(ccmp->iv_count, key->rx_seq, 6);
671
672 cmd_size = sizeof(struct iwm_umac_key_tkip);
673 break;
674
675 default:
676 return -ENOTSUPP;
677 }
678
679 if ((key->alg == UMAC_CIPHER_TYPE_CCMP) ||
680 (key->alg == UMAC_CIPHER_TYPE_TKIP))
681 /*
682 * UGLY_UGLY_UGLY
683 * Copied HACK from the MWG driver.
684 * Without it, the key is set before the second
685 * EAPOL frame is sent, and the latter is thus
686 * encrypted.
687 */
688 schedule_timeout_interruptible(usecs_to_jiffies(300));
689
690 ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1);
691 if (ret < 0)
692 goto err;
693
694 /*
695 * We need a default key only if it is set and
696 * if we're doing WEP.
697 */
698 if (iwm->default_key == key &&
699 ((key->alg == UMAC_CIPHER_TYPE_WEP_40) ||
700 (key->alg == UMAC_CIPHER_TYPE_WEP_104))) {
701 ret = iwm_set_tx_key(iwm, key_idx);
702 if (ret < 0)
703 goto err;
704 }
705 } else {
706 struct iwm_umac_key_remove key_remove;
707
708 key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY;
709 key_remove.hdr.buf_size =
710 cpu_to_le16(sizeof(struct iwm_umac_key_remove) -
711 sizeof(struct iwm_umac_wifi_if));
712 memcpy(&key_remove.key_hdr, key_hdr,
713 sizeof(struct iwm_umac_key_hdr));
714
715 ret = iwm_send_wifi_if_cmd(iwm, &key_remove,
716 sizeof(struct iwm_umac_key_remove),
717 1);
718 if (ret < 0)
719 return ret;
720
721 iwm->keys[key_idx].in_use = 0;
722 }
723
724 return 0;
725
726 err:
727 kfree(key);
728 return ret;
729}
730
731
732int iwm_send_mlme_profile(struct iwm_priv *iwm)
733{
734 int ret, i;
735 struct iwm_umac_profile profile;
736
737 memcpy(&profile, iwm->umac_profile, sizeof(profile));
738
739 profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE;
740 profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) -
741 sizeof(struct iwm_umac_wifi_if));
742
743 ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1);
744 if (ret < 0) {
745 IWM_ERR(iwm, "Send profile command failed\n");
746 return ret;
747 }
748
749 /* Wait for the profile to be active */
750 ret = wait_event_interruptible_timeout(iwm->mlme_queue,
751 iwm->umac_profile_active == 1,
752 3 * HZ);
753 if (!ret)
754 return -EBUSY;
755
756
757 for (i = 0; i < IWM_NUM_KEYS; i++)
758 if (iwm->keys[i].in_use) {
759 int default_key = 0;
760 struct iwm_key *key = &iwm->keys[i];
761
762 if (key == iwm->default_key)
763 default_key = 1;
764
765 /* Wait for the profile before sending the keys */
766 wait_event_interruptible_timeout(iwm->mlme_queue,
767 (test_bit(IWM_STATUS_ASSOCIATING, &iwm->status) ||
768 test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)),
769 3 * HZ);
770
771 ret = iwm_set_key(iwm, 0, default_key, key);
772 if (ret < 0)
773 return ret;
774 }
775
776 return 0;
777}
778
779int iwm_invalidate_mlme_profile(struct iwm_priv *iwm)
780{
781 int ret;
782 struct iwm_umac_invalidate_profile invalid;
783
784 invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE;
785 invalid.hdr.buf_size =
786 cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) -
787 sizeof(struct iwm_umac_wifi_if));
788
789 invalid.reason = WLAN_REASON_UNSPECIFIED;
790
791 ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1);
792 if (ret < 0)
793 return ret;
794
795 ret = wait_event_interruptible_timeout(iwm->mlme_queue,
796 (iwm->umac_profile_active == 0),
797 2 * HZ);
798 if (!ret)
799 return -EBUSY;
800
801 return 0;
802}
803
804int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags)
805{
806 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
807 struct iwm_umac_cmd umac_cmd;
808 struct iwm_umac_cmd_stats_req stats_req;
809
810 stats_req.flags = cpu_to_le32(flags);
811
812 umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST;
813 umac_cmd.resp = 0;
814
815 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req,
816 sizeof(struct iwm_umac_cmd_stats_req));
817}
818
819int iwm_send_umac_channel_list(struct iwm_priv *iwm)
820{
821 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
822 struct iwm_umac_cmd umac_cmd;
823 struct iwm_umac_cmd_get_channel_list *ch_list;
824 int size = sizeof(struct iwm_umac_cmd_get_channel_list) +
825 sizeof(struct iwm_umac_channel_info) * 4;
826 int ret;
827
828 ch_list = kzalloc(size, GFP_KERNEL);
829 if (!ch_list) {
830 IWM_ERR(iwm, "Couldn't allocate channel list cmd\n");
831 return -ENOMEM;
832 }
833
834 ch_list->ch[0].band = UMAC_BAND_2GHZ;
835 ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ;
836 ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID;
837
838 ch_list->ch[1].band = UMAC_BAND_5GHZ;
839 ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ;
840 ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID;
841
842 ch_list->ch[2].band = UMAC_BAND_2GHZ;
843 ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ;
844 ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
845
846 ch_list->ch[3].band = UMAC_BAND_5GHZ;
847 ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ;
848 ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS;
849
850 ch_list->count = cpu_to_le16(4);
851
852 umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST;
853 umac_cmd.resp = 1;
854
855 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size);
856
857 kfree(ch_list);
858
859 return ret;
860}
861
862int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
863 int ssid_num)
864{
865 struct iwm_umac_cmd_scan_request req;
866 int i, ret;
867
868 memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request));
869
870 req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST;
871 req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request)
872 - sizeof(struct iwm_umac_wifi_if));
873 req.type = UMAC_WIFI_IF_SCAN_TYPE_USER;
874 req.timeout = 2;
875 req.seq_num = iwm->scan_id;
876 req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX);
877
878 for (i = 0; i < req.ssid_num; i++) {
879 memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len);
880 req.ssids[i].ssid_len = ssids[i].ssid_len;
881 }
882
883 ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0);
884 if (ret < 0) {
885 IWM_ERR(iwm, "Couldn't send scan request\n");
886 return ret;
887 }
888
889 iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX;
890
891 return 0;
892}
893
894int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len)
895{
896 struct cfg80211_ssid one_ssid;
897
898 if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status))
899 return 0;
900
901 one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN);
902 memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len);
903
904 return iwm_scan_ssids(iwm, &one_ssid, 1);
905}
906
907int iwm_target_reset(struct iwm_priv *iwm)
908{
909 struct iwm_udma_nonwifi_cmd target_cmd;
910
911 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT;
912 target_cmd.addr = 0;
913 target_cmd.op1_sz = 0;
914 target_cmd.op2 = 0;
915 target_cmd.handle_by_hw = 0;
916 target_cmd.resp = 0;
917 target_cmd.eop = 1;
918
919 return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
920}
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h
new file mode 100644
index 000000000000..36b13a130595
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/commands.h
@@ -0,0 +1,419 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_COMMANDS_H__
40#define __IWM_COMMANDS_H__
41
42#include <linux/ieee80211.h>
43
44#define IWM_BARKER_REBOOT_NOTIFICATION 0xF
45#define IWM_ACK_BARKER_NOTIFICATION 0x10
46
47/* UMAC commands */
48#define UMAC_RST_CTRL_FLG_LARC_CLK_EN 0x0001
49#define UMAC_RST_CTRL_FLG_LARC_RESET 0x0002
50#define UMAC_RST_CTRL_FLG_FUNC_RESET 0x0004
51#define UMAC_RST_CTRL_FLG_DEV_RESET 0x0008
52#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN 0x0010
53#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN 0x0040
54#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN 0x0080
55#define UMAC_RST_CTRL_FLG_NVM_RELOAD 0x0100
56
57struct iwm_umac_cmd_reset {
58 __le32 flags;
59} __attribute__ ((packed));
60
61#define UMAC_PARAM_TBL_ORD_FIX 0x0
62#define UMAC_PARAM_TBL_ORD_VAR 0x1
63#define UMAC_PARAM_TBL_CFG_FIX 0x2
64#define UMAC_PARAM_TBL_CFG_VAR 0x3
65#define UMAC_PARAM_TBL_BSS_TRK 0x4
66#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5
67#define UMAC_PARAM_TBL_STA 0x6
68#define UMAC_PARAM_TBL_CHN 0x7
69#define UMAC_PARAM_TBL_STATISTICS 0x8
70
71/* fast access table */
72enum {
73 CFG_FRAG_THRESHOLD = 0,
74 CFG_FRAME_RETRY_LIMIT,
75 CFG_OS_QUEUE_UTIL_TH,
76 CFG_RX_FILTER,
77 /* <-- LAST --> */
78 FAST_ACCESS_CFG_TBL_FIX_LAST
79};
80
81/* fixed size table */
82enum {
83 CFG_POWER_INDEX = 0,
84 CFG_PM_LEGACY_RX_TIMEOUT,
85 CFG_PM_LEGACY_TX_TIMEOUT,
86 CFG_PM_CTRL_FLAGS,
87 CFG_PM_KEEP_ALIVE_IN_BEACONS,
88 CFG_BT_ON_THRESHOLD,
89 CFG_RTS_THRESHOLD,
90 CFG_CTS_TO_SELF,
91 CFG_COEX_MODE,
92 CFG_WIRELESS_MODE,
93 CFG_ASSOCIATION_TIMEOUT,
94 CFG_ROAM_TIMEOUT,
95 CFG_CAPABILITY_SUPPORTED_RATES,
96 CFG_SCAN_ALLOWED_UNASSOC_FLAGS,
97 CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS,
98 CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS,
99 CFG_SCAN_INTERNAL_PERIODIC_ENABLED,
100 CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT,
101 CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC,
102 CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN,
103 CFG_TLC_SUPPORTED_TX_HT_RATES,
104 CFG_TLC_SUPPORTED_TX_RATES,
105 CFG_TLC_VALID_ANTENNA,
106 CFG_TLC_SPATIAL_STREAM_SUPPORTED,
107 CFG_TLC_RETRY_PER_RATE,
108 CFG_TLC_RETRY_PER_HT_RATE,
109 CFG_TLC_FIXED_RATE,
110 CFG_TLC_FIXED_RATE_FLAGS,
111 CFG_TLC_CONTROL_FLAGS,
112 CFG_TLC_SR_MIN_FAIL,
113 CFG_TLC_SR_MIN_PASS,
114 CFG_TLC_HT_STAY_IN_COL_PASS_THRESH,
115 CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH,
116 CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH,
117 CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH,
118 CFG_TLC_HT_FLUSH_STATS_PACKETS,
119 CFG_TLC_LEGACY_FLUSH_STATS_PACKETS,
120 CFG_TLC_LEGACY_FLUSH_STATS_MS,
121 CFG_TLC_HT_FLUSH_STATS_MS,
122 CFG_TLC_STAY_IN_COL_TIME_OUT,
123 CFG_TLC_AGG_SHORT_LIM,
124 CFG_TLC_AGG_LONG_LIM,
125 CFG_TLC_HT_SR_NO_DECREASE,
126 CFG_TLC_LEGACY_SR_NO_DECREASE,
127 CFG_TLC_SR_FORCE_DECREASE,
128 CFG_TLC_SR_ALLOW_INCREASE,
129 CFG_TLC_AGG_SET_LONG,
130 CFG_TLC_AUTO_AGGREGATION,
131 CFG_TLC_AGG_THRESHOLD,
132 CFG_TLC_TID_LOAD_THRESHOLD,
133 CFG_TLC_BLOCK_ACK_TIMEOUT,
134 CFG_TLC_NO_BA_COUNTED_AS_ONE,
135 CFG_TLC_NUM_BA_STREAMS_ALLOWED,
136 CFG_TLC_NUM_BA_STREAMS_PRESENT,
137 CFG_TLC_RENEW_ADDBA_DELAY,
138 CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD,
139 CFG_TLC_IS_STABLE_IN_HT,
140 CFG_RLC_CHAIN_CTRL,
141 CFG_TRK_TABLE_OP_MODE,
142 CFG_TRK_TABLE_RSSI_THRESHOLD,
143 CFG_TX_PWR_TARGET, /* Used By xVT */
144 CFG_TX_PWR_LIMIT_USR,
145 CFG_TX_PWR_LIMIT_BSS, /* 11d limit */
146 CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */
147 CFG_TX_PWR_MODE,
148 CFG_MLME_DBG_NOTIF_BLOCK,
149 CFG_BT_OFF_BECONS_INTERVALS,
150 CFG_BT_FRAG_DURATION,
151
152 /* <-- LAST --> */
153 CFG_TBL_FIX_LAST
154};
155
156/* variable size table */
157enum {
158 CFG_NET_ADDR = 0,
159 CFG_PROFILE,
160 /* <-- LAST --> */
161 CFG_TBL_VAR_LAST
162};
163
164struct iwm_umac_cmd_set_param_fix {
165 __le16 tbl;
166 __le16 key;
167 __le32 value;
168} __attribute__ ((packed));
169
170struct iwm_umac_cmd_set_param_var {
171 __le16 tbl;
172 __le16 key;
173 __le16 len;
174 __le16 reserved;
175} __attribute__ ((packed));
176
177struct iwm_umac_cmd_get_param {
178 __le16 tbl;
179 __le16 key;
180} __attribute__ ((packed));
181
182struct iwm_umac_cmd_get_param_resp {
183 __le16 tbl;
184 __le16 key;
185 __le16 len;
186 __le16 reserved;
187} __attribute__ ((packed));
188
189struct iwm_umac_cmd_eeprom_proxy_hdr {
190 __le32 type;
191 __le32 offset;
192 __le32 len;
193} __attribute__ ((packed));
194
195struct iwm_umac_cmd_eeprom_proxy {
196 struct iwm_umac_cmd_eeprom_proxy_hdr hdr;
197 u8 buf[0];
198} __attribute__ ((packed));
199
200#define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1
201#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2
202
203#define UMAC_CHANNEL_FLAG_VALID BIT(0)
204#define UMAC_CHANNEL_FLAG_IBSS BIT(1)
205#define UMAC_CHANNEL_FLAG_ACTIVE BIT(3)
206#define UMAC_CHANNEL_FLAG_RADAR BIT(4)
207#define UMAC_CHANNEL_FLAG_DFS BIT(7)
208
209struct iwm_umac_channel_info {
210 u8 band;
211 u8 type;
212 u8 reserved;
213 u8 flags;
214 __le32 channels_mask;
215} __attribute__ ((packed));
216
217struct iwm_umac_cmd_get_channel_list {
218 __le16 count;
219 __le16 reserved;
220 struct iwm_umac_channel_info ch[0];
221} __attribute__ ((packed));
222
223
224/* UMAC WiFi interface commands */
225
226/* Coexistence mode */
227#define COEX_MODE_SA 0x1
228#define COEX_MODE_XOR 0x2
229#define COEX_MODE_CM 0x3
230#define COEX_MODE_MAX 0x4
231
232/* Wireless mode */
233#define WIRELESS_MODE_11A 0x1
234#define WIRELESS_MODE_11G 0x2
235
236#define UMAC_PROFILE_EX_IE_REQUIRED 0x1
237#define UMAC_PROFILE_QOS_ALLOWED 0x2
238
239/* Scanning */
240#define UMAC_WIFI_IF_PROBE_OPTION_MAX 10
241
242#define UMAC_WIFI_IF_SCAN_TYPE_USER 0x0
243#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1
244#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2
245#define UMAC_WIFI_IF_SCAN_TYPE_MAX 0x3
246
247struct iwm_umac_ssid {
248 u8 ssid_len;
249 u8 ssid[IEEE80211_MAX_SSID_LEN];
250 u8 reserved[3];
251} __attribute__ ((packed));
252
253struct iwm_umac_cmd_scan_request {
254 struct iwm_umac_wifi_if hdr;
255 __le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */
256 u8 ssid_num;
257 u8 seq_num;
258 u8 timeout; /* In seconds */
259 u8 reserved;
260 struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX];
261} __attribute__ ((packed));
262
263#define UMAC_CIPHER_TYPE_NONE 0xFF
264#define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00
265#define UMAC_CIPHER_TYPE_WEP_40 0x01
266#define UMAC_CIPHER_TYPE_WEP_104 0x02
267#define UMAC_CIPHER_TYPE_TKIP 0x04
268#define UMAC_CIPHER_TYPE_CCMP 0x08
269
270/* Supported authentication types - bitmap */
271#define UMAC_AUTH_TYPE_OPEN 0x00
272#define UMAC_AUTH_TYPE_LEGACY_PSK 0x01
273#define UMAC_AUTH_TYPE_8021X 0x02
274#define UMAC_AUTH_TYPE_RSNA_PSK 0x04
275
276/* iwm_umac_security.flag is WPA supported -- bits[0:0] */
277#define UMAC_SEC_FLG_WPA_ON_POS 0
278#define UMAC_SEC_FLG_WPA_ON_SEED 1
279#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \
280 UMAC_SEC_FLG_WPA_ON_POS)
281
282/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */
283#define UMAC_SEC_FLG_RSNA_ON_POS 1
284#define UMAC_SEC_FLG_RSNA_ON_SEED 1
285#define UMAC_SEC_FLG_RSNA_ON_MSK (UMAC_SEC_FLG_RSNA_ON_SEED << \
286 UMAC_SEC_FLG_RSNA_ON_POS)
287
288/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */
289#define UMAC_SEC_FLG_WSC_ON_POS 2
290#define UMAC_SEC_FLG_WSC_ON_SEED 1
291
292/* Legacy profile can use only WEP40 and WEP104 for encryption and
293 * OPEN or PSK for authentication */
294#define UMAC_SEC_FLG_LEGACY_PROFILE 0
295
296struct iwm_umac_security {
297 u8 auth_type;
298 u8 ucast_cipher;
299 u8 mcast_cipher;
300 u8 flags;
301} __attribute__ ((packed));
302
303struct iwm_umac_ibss {
304 u8 beacon_interval; /* in millisecond */
305 u8 atim; /* in millisecond */
306 s8 join_only;
307 u8 band;
308 u8 channel;
309 u8 reserved[3];
310} __attribute__ ((packed));
311
312#define UMAC_MODE_BSS 0
313#define UMAC_MODE_IBSS 1
314
315#define UMAC_BSSID_MAX 4
316
317struct iwm_umac_profile {
318 struct iwm_umac_wifi_if hdr;
319 __le32 mode;
320 struct iwm_umac_ssid ssid;
321 u8 bssid[UMAC_BSSID_MAX][ETH_ALEN];
322 struct iwm_umac_security sec;
323 struct iwm_umac_ibss ibss;
324 __le32 channel_2ghz;
325 __le32 channel_5ghz;
326 __le16 flags;
327 u8 wireless_mode;
328 u8 bss_num;
329} __attribute__ ((packed));
330
331struct iwm_umac_invalidate_profile {
332 struct iwm_umac_wifi_if hdr;
333 u8 reason;
334 u8 reserved[3];
335} __attribute__ ((packed));
336
337/* Encryption key commands */
338struct iwm_umac_key_wep40 {
339 struct iwm_umac_wifi_if hdr;
340 struct iwm_umac_key_hdr key_hdr;
341 u8 key[WLAN_KEY_LEN_WEP40];
342 u8 static_key;
343 u8 reserved[2];
344} __attribute__ ((packed));
345
346struct iwm_umac_key_wep104 {
347 struct iwm_umac_wifi_if hdr;
348 struct iwm_umac_key_hdr key_hdr;
349 u8 key[WLAN_KEY_LEN_WEP104];
350 u8 static_key;
351 u8 reserved[2];
352} __attribute__ ((packed));
353
354#define IWM_TKIP_KEY_SIZE 16
355#define IWM_TKIP_MIC_SIZE 8
356struct iwm_umac_key_tkip {
357 struct iwm_umac_wifi_if hdr;
358 struct iwm_umac_key_hdr key_hdr;
359 u8 iv_count[6];
360 u8 reserved[2];
361 u8 tkip_key[IWM_TKIP_KEY_SIZE];
362 u8 mic_rx_key[IWM_TKIP_MIC_SIZE];
363 u8 mic_tx_key[IWM_TKIP_MIC_SIZE];
364} __attribute__ ((packed));
365
366struct iwm_umac_key_ccmp {
367 struct iwm_umac_wifi_if hdr;
368 struct iwm_umac_key_hdr key_hdr;
369 u8 iv_count[6];
370 u8 reserved[2];
371 u8 key[WLAN_KEY_LEN_CCMP];
372} __attribute__ ((packed));
373
374struct iwm_umac_key_remove {
375 struct iwm_umac_wifi_if hdr;
376 struct iwm_umac_key_hdr key_hdr;
377} __attribute__ ((packed));
378
379struct iwm_umac_tx_key_id {
380 struct iwm_umac_wifi_if hdr;
381 u8 key_idx;
382 u8 reserved[3];
383} __attribute__ ((packed));
384
385struct iwm_umac_cmd_stats_req {
386 __le32 flags;
387} __attribute__ ((packed));
388
389/* LMAC commands */
390int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
391int iwm_send_prio_table(struct iwm_priv *iwm);
392int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
393int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested);
394int iwm_send_calib_results(struct iwm_priv *iwm);
395int iwm_store_rxiq_calib_result(struct iwm_priv *iwm);
396
397/* UMAC commands */
398int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
399 bool resp);
400int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp);
401int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value);
402int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key,
403 void *payload, u16 payload_size);
404int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags);
405int iwm_send_mlme_profile(struct iwm_priv *iwm);
406int iwm_invalidate_mlme_profile(struct iwm_priv *iwm);
407int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id);
408int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx);
409int iwm_set_key(struct iwm_priv *iwm, bool remove, bool set_tx_key,
410 struct iwm_key *key);
411int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags);
412int iwm_send_umac_channel_list(struct iwm_priv *iwm);
413int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
414 int ssid_num);
415int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
416
417/* UDMA commands */
418int iwm_target_reset(struct iwm_priv *iwm);
419#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h
new file mode 100644
index 000000000000..8fbb42d9c21f
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/debug.h
@@ -0,0 +1,124 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#ifndef __IWM_DEBUG_H__
25#define __IWM_DEBUG_H__
26
27#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a)
28#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a)
29#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a)
30#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a)
31
32#ifdef CONFIG_IWM_DEBUG
33
34#define IWM_DEBUG_MODULE(i, level, module, f, a...) \
35do { \
36 if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
37 dev_printk(KERN_INFO, (iwm_to_dev(i)), \
38 "%s " f, __func__ , ## a); \
39} while (0)
40
41#define IWM_HEXDUMP(i, level, module, pref, buf, len) \
42do { \
43 if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\
44 print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \
45 16, 1, buf, len, 1); \
46} while (0)
47
48#else
49
50#define IWM_DEBUG_MODULE(i, level, module, f, a...)
51#define IWM_HEXDUMP(i, level, module, pref, buf, len)
52
53#endif /* CONFIG_IWM_DEBUG */
54
55/* Debug modules */
56enum iwm_debug_module_id {
57 IWM_DM_BOOT = 0,
58 IWM_DM_FW,
59 IWM_DM_SDIO,
60 IWM_DM_NTF,
61 IWM_DM_RX,
62 IWM_DM_TX,
63 IWM_DM_MLME,
64 IWM_DM_CMD,
65 IWM_DM_WEXT,
66 __IWM_DM_NR,
67};
68#define IWM_DM_DEFAULT 0
69
70#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a)
71#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a)
72#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a)
73#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a)
74#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a)
75#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a)
76#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a)
77#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a)
78#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a)
79
80/* Debug levels */
81enum iwm_debug_level {
82 IWM_DL_NONE = 0,
83 IWM_DL_ERR,
84 IWM_DL_WARN,
85 IWM_DL_INFO,
86 IWM_DL_DBG,
87};
88#define IWM_DL_DEFAULT IWM_DL_ERR
89
90struct iwm_debugfs {
91 struct iwm_priv *iwm;
92 struct dentry *rootdir;
93 struct dentry *devdir;
94 struct dentry *dbgdir;
95 struct dentry *txdir;
96 struct dentry *rxdir;
97 struct dentry *busdir;
98
99 u32 dbg_level;
100 struct dentry *dbg_level_dentry;
101
102 unsigned long dbg_modules;
103 struct dentry *dbg_modules_dentry;
104
105 u8 dbg_module[__IWM_DM_NR];
106 struct dentry *dbg_module_dentries[__IWM_DM_NR];
107
108 struct dentry *txq_dentry;
109 struct dentry *tx_credit_dentry;
110 struct dentry *rx_ticket_dentry;
111};
112
113#ifdef CONFIG_IWM_DEBUG
114int iwm_debugfs_init(struct iwm_priv *iwm);
115void iwm_debugfs_exit(struct iwm_priv *iwm);
116#else
117static inline int iwm_debugfs_init(struct iwm_priv *iwm)
118{
119 return 0;
120}
121static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {}
122#endif
123
124#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
new file mode 100644
index 000000000000..0fa7b9150d58
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -0,0 +1,453 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/bitops.h>
26#include <linux/debugfs.h>
27
28#include "iwm.h"
29#include "bus.h"
30#include "rx.h"
31#include "debug.h"
32
33static struct {
34 u8 id;
35 char *name;
36} iwm_debug_module[__IWM_DM_NR] = {
37 {IWM_DM_BOOT, "boot"},
38 {IWM_DM_FW, "fw"},
39 {IWM_DM_SDIO, "sdio"},
40 {IWM_DM_NTF, "ntf"},
41 {IWM_DM_RX, "rx"},
42 {IWM_DM_TX, "tx"},
43 {IWM_DM_MLME, "mlme"},
44 {IWM_DM_CMD, "cmd"},
45 {IWM_DM_WEXT, "wext"},
46};
47
48#define add_dbg_module(dbg, name, id, initlevel) \
49do { \
50 struct dentry *d; \
51 dbg.dbg_module[id] = (initlevel); \
52 d = debugfs_create_x8(name, 0600, dbg.dbgdir, \
53 &(dbg.dbg_module[id])); \
54 if (!IS_ERR(d)) \
55 dbg.dbg_module_dentries[id] = d; \
56} while (0)
57
58static int iwm_debugfs_u32_read(void *data, u64 *val)
59{
60 struct iwm_priv *iwm = data;
61
62 *val = iwm->dbg.dbg_level;
63 return 0;
64}
65
66static int iwm_debugfs_dbg_level_write(void *data, u64 val)
67{
68 struct iwm_priv *iwm = data;
69 int i;
70
71 iwm->dbg.dbg_level = val;
72
73 for (i = 0; i < __IWM_DM_NR; i++)
74 iwm->dbg.dbg_module[i] = val;
75
76 return 0;
77}
78DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level,
79 iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write,
80 "%llu\n");
81
82static int iwm_debugfs_dbg_modules_write(void *data, u64 val)
83{
84 struct iwm_priv *iwm = data;
85 int i, bit;
86
87 iwm->dbg.dbg_modules = val;
88
89 for (i = 0; i < __IWM_DM_NR; i++)
90 iwm->dbg.dbg_module[i] = 0;
91
92 for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR)
93 iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level;
94
95 return 0;
96}
97DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules,
98 iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write,
99 "%llu\n");
100
101static int iwm_txrx_open(struct inode *inode, struct file *filp)
102{
103 filp->private_data = inode->i_private;
104 return 0;
105}
106
107
108static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
109 size_t count, loff_t *ppos)
110{
111 struct iwm_priv *iwm = filp->private_data;
112 char *buf;
113 int i, buf_len = 4096;
114 size_t len = 0;
115 ssize_t ret;
116
117 if (*ppos != 0)
118 return 0;
119 if (count < sizeof(buf))
120 return -ENOSPC;
121
122 buf = kzalloc(buf_len, GFP_KERNEL);
123 if (!buf)
124 return -ENOMEM;
125
126 for (i = 0; i < IWM_TX_QUEUES; i++) {
127 struct iwm_tx_queue *txq = &iwm->txq[i];
128 struct sk_buff *skb;
129 int j;
130 unsigned long flags;
131
132 spin_lock_irqsave(&txq->queue.lock, flags);
133
134 skb = (struct sk_buff *)&txq->queue;
135
136 len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i);
137 len += snprintf(buf + len, buf_len - len, "\tStopped: %d\n",
138 __netif_subqueue_stopped(iwm_to_ndev(iwm),
139 txq->id));
140 len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n",
141 txq->concat_count);
142 len += snprintf(buf + len, buf_len - len, "\tQueue len: %d\n",
143 skb_queue_len(&txq->queue));
144 for (j = 0; j < skb_queue_len(&txq->queue); j++) {
145 struct iwm_tx_info *tx_info;
146
147 skb = skb->next;
148 tx_info = skb_to_tx_info(skb);
149
150 len += snprintf(buf + len, buf_len - len,
151 "\tSKB #%d\n", j);
152 len += snprintf(buf + len, buf_len - len,
153 "\t\tsta: %d\n", tx_info->sta);
154 len += snprintf(buf + len, buf_len - len,
155 "\t\tcolor: %d\n", tx_info->color);
156 len += snprintf(buf + len, buf_len - len,
157 "\t\ttid: %d\n", tx_info->tid);
158 }
159
160 spin_unlock_irqrestore(&txq->queue.lock, flags);
161 }
162
163 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
164 kfree(buf);
165
166 return ret;
167}
168
169static ssize_t iwm_debugfs_tx_credit_read(struct file *filp,
170 char __user *buffer,
171 size_t count, loff_t *ppos)
172{
173 struct iwm_priv *iwm = filp->private_data;
174 struct iwm_tx_credit *credit = &iwm->tx_credit;
175 char *buf;
176 int i, buf_len = 4096;
177 size_t len = 0;
178 ssize_t ret;
179
180 if (*ppos != 0)
181 return 0;
182 if (count < sizeof(buf))
183 return -ENOSPC;
184
185 buf = kzalloc(buf_len, GFP_KERNEL);
186 if (!buf)
187 return -ENOMEM;
188
189 len += snprintf(buf + len, buf_len - len,
190 "NR pools: %d\n", credit->pool_nr);
191 len += snprintf(buf + len, buf_len - len,
192 "pools map: 0x%lx\n", credit->full_pools_map);
193
194 len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n");
195 for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) {
196 len += snprintf(buf + len, buf_len - len,
197 "pools entry #%d\n", i);
198 len += snprintf(buf + len, buf_len - len,
199 "\tid: %d\n",
200 credit->pools[i].id);
201 len += snprintf(buf + len, buf_len - len,
202 "\tsid: %d\n",
203 credit->pools[i].sid);
204 len += snprintf(buf + len, buf_len - len,
205 "\tmin_pages: %d\n",
206 credit->pools[i].min_pages);
207 len += snprintf(buf + len, buf_len - len,
208 "\tmax_pages: %d\n",
209 credit->pools[i].max_pages);
210 len += snprintf(buf + len, buf_len - len,
211 "\talloc_pages: %d\n",
212 credit->pools[i].alloc_pages);
213 len += snprintf(buf + len, buf_len - len,
214 "\tfreed_pages: %d\n",
215 credit->pools[i].total_freed_pages);
216 }
217
218 len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n");
219 for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) {
220 len += snprintf(buf + len, buf_len - len,
221 "spools entry #%d\n", i);
222 len += snprintf(buf + len, buf_len - len,
223 "\tid: %d\n",
224 credit->spools[i].id);
225 len += snprintf(buf + len, buf_len - len,
226 "\tmax_pages: %d\n",
227 credit->spools[i].max_pages);
228 len += snprintf(buf + len, buf_len - len,
229 "\talloc_pages: %d\n",
230 credit->spools[i].alloc_pages);
231
232 }
233
234 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
235 kfree(buf);
236
237 return ret;
238}
239
240static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp,
241 char __user *buffer,
242 size_t count, loff_t *ppos)
243{
244 struct iwm_priv *iwm = filp->private_data;
245 struct iwm_rx_ticket_node *ticket, *next;
246 char *buf;
247 int buf_len = 4096, i;
248 size_t len = 0;
249 ssize_t ret;
250
251 if (*ppos != 0)
252 return 0;
253 if (count < sizeof(buf))
254 return -ENOSPC;
255
256 buf = kzalloc(buf_len, GFP_KERNEL);
257 if (!buf)
258 return -ENOMEM;
259
260 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
261 len += snprintf(buf + len, buf_len - len, "Ticket #%d\n",
262 ticket->ticket->id);
263 len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n",
264 ticket->ticket->action);
265 len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n",
266 ticket->ticket->flags);
267 }
268
269 for (i = 0; i < IWM_RX_ID_HASH; i++) {
270 struct iwm_rx_packet *packet, *nxt;
271 struct list_head *pkt_list = &iwm->rx_packets[i];
272 if (!list_empty(pkt_list)) {
273 len += snprintf(buf + len, buf_len - len,
274 "Packet hash #%d\n", i);
275 list_for_each_entry_safe(packet, nxt, pkt_list, node) {
276 len += snprintf(buf + len, buf_len - len,
277 "\tPacket id: %d\n",
278 packet->id);
279 len += snprintf(buf + len, buf_len - len,
280 "\tPacket length: %lu\n",
281 packet->pkt_size);
282 }
283 }
284 }
285
286 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
287 kfree(buf);
288
289 return ret;
290}
291
292
293static const struct file_operations iwm_debugfs_txq_fops = {
294 .owner = THIS_MODULE,
295 .open = iwm_txrx_open,
296 .read = iwm_debugfs_txq_read,
297};
298
299static const struct file_operations iwm_debugfs_tx_credit_fops = {
300 .owner = THIS_MODULE,
301 .open = iwm_txrx_open,
302 .read = iwm_debugfs_tx_credit_read,
303};
304
305static const struct file_operations iwm_debugfs_rx_ticket_fops = {
306 .owner = THIS_MODULE,
307 .open = iwm_txrx_open,
308 .read = iwm_debugfs_rx_ticket_read,
309};
310
311int iwm_debugfs_init(struct iwm_priv *iwm)
312{
313 int i, result;
314 char devdir[16];
315
316 iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL);
317 result = PTR_ERR(iwm->dbg.rootdir);
318 if (!result || IS_ERR(iwm->dbg.rootdir)) {
319 if (result == -ENODEV) {
320 IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not "
321 "enabled in kernel config\n");
322 result = 0; /* No debugfs support */
323 }
324 IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result);
325 goto error;
326 }
327
328 snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm)));
329
330 iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir);
331 result = PTR_ERR(iwm->dbg.devdir);
332 if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) {
333 IWM_ERR(iwm, "Couldn't create devdir: %d\n", result);
334 goto error;
335 }
336
337 iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir);
338 result = PTR_ERR(iwm->dbg.dbgdir);
339 if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) {
340 IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result);
341 goto error;
342 }
343
344 iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir);
345 result = PTR_ERR(iwm->dbg.rxdir);
346 if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) {
347 IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result);
348 goto error;
349 }
350
351 iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir);
352 result = PTR_ERR(iwm->dbg.txdir);
353 if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) {
354 IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result);
355 goto error;
356 }
357
358 iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir);
359 result = PTR_ERR(iwm->dbg.busdir);
360 if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) {
361 IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result);
362 goto error;
363 }
364
365 if (iwm->bus_ops->debugfs_init) {
366 result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir);
367 if (result < 0) {
368 IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result);
369 goto error;
370 }
371 }
372
373
374 iwm->dbg.dbg_level = IWM_DL_NONE;
375 iwm->dbg.dbg_level_dentry =
376 debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm,
377 &fops_iwm_dbg_level);
378 result = PTR_ERR(iwm->dbg.dbg_level_dentry);
379 if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) {
380 IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result);
381 goto error;
382 }
383
384
385 iwm->dbg.dbg_modules = IWM_DM_DEFAULT;
386 iwm->dbg.dbg_modules_dentry =
387 debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm,
388 &fops_iwm_dbg_modules);
389 result = PTR_ERR(iwm->dbg.dbg_modules_dentry);
390 if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) {
391 IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result);
392 goto error;
393 }
394
395 for (i = 0; i < __IWM_DM_NR; i++)
396 add_dbg_module(iwm->dbg, iwm_debug_module[i].name,
397 iwm_debug_module[i].id, IWM_DL_DEFAULT);
398
399 iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200,
400 iwm->dbg.txdir, iwm,
401 &iwm_debugfs_txq_fops);
402 result = PTR_ERR(iwm->dbg.txq_dentry);
403 if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) {
404 IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result);
405 goto error;
406 }
407
408 iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200,
409 iwm->dbg.txdir, iwm,
410 &iwm_debugfs_tx_credit_fops);
411 result = PTR_ERR(iwm->dbg.tx_credit_dentry);
412 if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) {
413 IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result);
414 goto error;
415 }
416
417 iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200,
418 iwm->dbg.rxdir, iwm,
419 &iwm_debugfs_rx_ticket_fops);
420 result = PTR_ERR(iwm->dbg.rx_ticket_dentry);
421 if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) {
422 IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result);
423 goto error;
424 }
425
426 return 0;
427
428 error:
429 return result;
430}
431
432void iwm_debugfs_exit(struct iwm_priv *iwm)
433{
434 int i;
435
436 for (i = 0; i < __IWM_DM_NR; i++)
437 debugfs_remove(iwm->dbg.dbg_module_dentries[i]);
438
439 debugfs_remove(iwm->dbg.dbg_modules_dentry);
440 debugfs_remove(iwm->dbg.dbg_level_dentry);
441 debugfs_remove(iwm->dbg.txq_dentry);
442 debugfs_remove(iwm->dbg.tx_credit_dentry);
443 debugfs_remove(iwm->dbg.rx_ticket_dentry);
444 if (iwm->bus_ops->debugfs_exit)
445 iwm->bus_ops->debugfs_exit(iwm);
446
447 debugfs_remove(iwm->dbg.busdir);
448 debugfs_remove(iwm->dbg.dbgdir);
449 debugfs_remove(iwm->dbg.txdir);
450 debugfs_remove(iwm->dbg.rxdir);
451 debugfs_remove(iwm->dbg.devdir);
452 debugfs_remove(iwm->dbg.rootdir);
453}
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c
new file mode 100644
index 000000000000..0f34b84fd2eb
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/eeprom.c
@@ -0,0 +1,187 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40
41#include "iwm.h"
42#include "umac.h"
43#include "commands.h"
44#include "eeprom.h"
45
46static struct iwm_eeprom_entry eeprom_map[] = {
47 [IWM_EEPROM_SIG] =
48 {"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN},
49
50 [IWM_EEPROM_VERSION] =
51 {"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN},
52
53 [IWM_EEPROM_OEM_HW_VERSION] =
54 {"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF,
55 IWM_EEPROM_OEM_HW_VERSION_LEN},
56
57 [IWM_EEPROM_MAC_VERSION] =
58 {"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN},
59
60 [IWM_EEPROM_CARD_ID] =
61 {"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN},
62
63 [IWM_EEPROM_RADIO_CONF] =
64 {"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN},
65
66 [IWM_EEPROM_SKU_CAP] =
67 {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN},
68
69 [IWM_EEPROM_CALIB_RXIQ_OFFSET] =
70 {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN},
71
72 [IWM_EEPROM_CALIB_RXIQ] =
73 {"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN},
74};
75
76
77static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id)
78{
79 int ret;
80 u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0;
81 u32 addr;
82 struct iwm_udma_wifi_cmd udma_cmd;
83 struct iwm_umac_cmd umac_cmd;
84 struct iwm_umac_cmd_eeprom_proxy eeprom_cmd;
85
86 if (eeprom_id > (IWM_EEPROM_LAST - 1))
87 return -EINVAL;
88
89 entry_size = eeprom_map[eeprom_id].length;
90
91 if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) {
92 /* indirect data */
93 u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA +
94 IWM_EEPROM_INDIRECT_OFFSET;
95
96 eeprom_map[eeprom_id].offset =
97 *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1;
98 }
99
100 addr = eeprom_map[eeprom_id].offset;
101
102 udma_cmd.eop = 1;
103 udma_cmd.credit_group = 0x4;
104 udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD;
105 udma_cmd.lmac_offset = 0;
106
107 umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY;
108 umac_cmd.resp = 1;
109
110 while (entry_size > 0) {
111 chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN);
112
113 eeprom_cmd.hdr.type =
114 cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ);
115 eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset);
116 eeprom_cmd.hdr.len = cpu_to_le32(chunk_size);
117
118 ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd,
119 &umac_cmd, &eeprom_cmd,
120 sizeof(struct iwm_umac_cmd_eeprom_proxy));
121 if (ret < 0) {
122 IWM_ERR(iwm, "Couldn't read eeprom\n");
123 return ret;
124 }
125
126 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY,
127 IWM_SRC_UMAC, 2*HZ);
128 if (ret < 0) {
129 IWM_ERR(iwm, "Did not get any eeprom answer\n");
130 return ret;
131 }
132
133 data_offset += chunk_size;
134 addr_offset += chunk_size;
135 entry_size -= chunk_size;
136 }
137
138 return 0;
139}
140
141u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id)
142{
143 if (!iwm->eeprom)
144 return ERR_PTR(-ENODEV);
145
146 return iwm->eeprom + eeprom_map[eeprom_id].offset;
147}
148
149int iwm_eeprom_init(struct iwm_priv *iwm)
150{
151 int i, ret = 0;
152 char name[32];
153
154 iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL);
155 if (!iwm->eeprom)
156 return -ENOMEM;
157
158 for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
159#ifdef CONFIG_IWM_B0_HW_SUPPORT
160 if (iwm->conf.hw_b0 && (i >= IWM_EEPROM_INDIRECT_OFFSET))
161 break;
162#endif
163 ret = iwm_eeprom_read(iwm, i);
164 if (ret < 0) {
165 IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n",
166 i, eeprom_map[i].name);
167 break;
168 }
169 }
170
171 IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n");
172 for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) {
173 memset(name, 0, 32);
174 sprintf(name, "%s: ", eeprom_map[i].name);
175
176 IWM_HEXDUMP(iwm, DBG, BOOT, name,
177 iwm->eeprom + eeprom_map[i].offset,
178 eeprom_map[i].length);
179 }
180
181 return ret;
182}
183
184void iwm_eeprom_exit(struct iwm_priv *iwm)
185{
186 kfree(iwm->eeprom);
187}
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.h b/drivers/net/wireless/iwmc3200wifi/eeprom.h
new file mode 100644
index 000000000000..cdb31a6a1f5f
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/eeprom.h
@@ -0,0 +1,114 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_EEPROM_H__
40#define __IWM_EEPROM_H__
41
42enum {
43 IWM_EEPROM_SIG = 0,
44 IWM_EEPROM_FIRST = IWM_EEPROM_SIG,
45 IWM_EEPROM_VERSION,
46 IWM_EEPROM_OEM_HW_VERSION,
47 IWM_EEPROM_MAC_VERSION,
48 IWM_EEPROM_CARD_ID,
49 IWM_EEPROM_RADIO_CONF,
50 IWM_EEPROM_SKU_CAP,
51
52 IWM_EEPROM_INDIRECT_OFFSET,
53 IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET,
54
55 IWM_EEPROM_INDIRECT_DATA,
56 IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA,
57
58 IWM_EEPROM_LAST,
59};
60
61#define IWM_EEPROM_SIG_OFF 0x00
62#define IWM_EEPROM_VERSION_OFF (0x54 << 1)
63#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1)
64#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1)
65#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1)
66#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1)
67#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1)
68#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1)
69
70#define IWM_EEPROM_SIG_LEN 4
71#define IWM_EEPROM_VERSION_LEN 2
72#define IWM_EEPROM_OEM_HW_VERSION_LEN 2
73#define IWM_EEPROM_MAC_VERSION_LEN 1
74#define IWM_EEPROM_CARD_ID_LEN 2
75#define IWM_EEPROM_RADIO_CONF_LEN 2
76#define IWM_EEPROM_SKU_CAP_LEN 2
77#define IWM_EEPROM_INDIRECT_LEN 2
78
79#define IWM_MAX_EEPROM_DATA_LEN 240
80#define IWM_EEPROM_LEN 0x800
81
82#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610
83#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700
84#define IWM_EEPROM_CURRENT_VERSION 0x0612
85
86#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4)
87#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
88#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
89
90enum {
91 IWM_EEPROM_CALIB_CAL_HDR,
92 IWM_EEPROM_CALIB_TX_POWER,
93 IWM_EEPROM_CALIB_XTAL,
94 IWM_EEPROM_CALIB_TEMPERATURE,
95 IWM_EEPROM_CALIB_RX_BB_FILTER,
96 IWM_EEPROM_CALIB_RX_IQ,
97 IWM_EEPROM_CALIB_MAX,
98};
99
100#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \
101 (IWM_EEPROM_CALIB_RX_IQ << 1))
102#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq)
103
104struct iwm_eeprom_entry {
105 char *name;
106 u32 offset;
107 u32 length;
108};
109
110int iwm_eeprom_init(struct iwm_priv *iwm);
111void iwm_eeprom_exit(struct iwm_priv *iwm);
112u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id);
113
114#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
new file mode 100644
index 000000000000..db4ba0864730
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -0,0 +1,388 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/firmware.h>
41
42#include "iwm.h"
43#include "bus.h"
44#include "hal.h"
45#include "umac.h"
46#include "debug.h"
47#include "fw.h"
48#include "commands.h"
49
50static const char fw_barker[] = "*WESTOPFORNOONE*";
51
52/*
53 * @op_code: Op code we're looking for.
54 * @index: There can be several instances of the same opcode within
55 * the firmware. Index specifies which one we're looking for.
56 */
57static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw,
58 u16 op_code, u32 index)
59{
60 int offset = -EINVAL, fw_offset;
61 u32 op_index = 0;
62 const u8 *fw_ptr;
63 struct iwm_fw_hdr_rec *rec;
64
65 fw_offset = 0;
66 fw_ptr = fw->data;
67
68 /* We first need to look for the firmware barker */
69 if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) {
70 IWM_ERR(iwm, "No barker string in this FW\n");
71 return -EINVAL;
72 }
73
74 if (fw->size < IWM_HDR_LEN) {
75 IWM_ERR(iwm, "FW is too small (%d)\n", fw->size);
76 return -EINVAL;
77 }
78
79 fw_offset += IWM_HDR_BARKER_LEN;
80
81 while (fw_offset < fw->size) {
82 rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset);
83
84 IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n",
85 rec->op_code, rec->len, fw_offset);
86
87 if (rec->op_code == IWM_HDR_REC_OP_INVALID) {
88 IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n");
89 break;
90 }
91
92 if (rec->op_code == op_code) {
93 if (op_index == index) {
94 fw_offset += sizeof(struct iwm_fw_hdr_rec);
95 offset = fw_offset;
96 goto out;
97 }
98 op_index++;
99 }
100
101 fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len;
102 }
103
104 out:
105 return offset;
106}
107
108static int iwm_load_firmware_chunk(struct iwm_priv *iwm,
109 const struct firmware *fw,
110 struct iwm_fw_img_desc *img_desc)
111{
112 struct iwm_udma_nonwifi_cmd target_cmd;
113 u32 chunk_size;
114 const u8 *chunk_ptr;
115 int ret = 0;
116
117 IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n",
118 img_desc->length, img_desc->address);
119
120 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
121 target_cmd.handle_by_hw = 1;
122 target_cmd.op2 = 0;
123 target_cmd.resp = 0;
124 target_cmd.eop = 1;
125
126 chunk_size = img_desc->length;
127 chunk_ptr = fw->data + img_desc->offset;
128
129 while (chunk_size > 0) {
130 u32 tmp_chunk_size;
131
132 tmp_chunk_size = min_t(u32, chunk_size,
133 IWM_MAX_NONWIFI_CMD_BUFF_SIZE);
134
135 target_cmd.addr = cpu_to_le32(img_desc->address +
136 (chunk_ptr - fw->data - img_desc->offset));
137 target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size);
138
139 IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n",
140 tmp_chunk_size, target_cmd.addr);
141
142 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr);
143 if (ret < 0) {
144 IWM_ERR(iwm, "Couldn't load FW chunk\n");
145 break;
146 }
147
148 chunk_size -= tmp_chunk_size;
149 chunk_ptr += tmp_chunk_size;
150 }
151
152 return ret;
153}
154/*
155 * To load a fw image to the target, we basically go through the
156 * fw, looking for OP_MEM_DESC records. Once we found one, we
157 * pass it to iwm_load_firmware_chunk().
158 * The OP_MEM_DESC records contain the actuall memory chunk to be
159 * sent, but also the destination address.
160 */
161static int iwm_load_img(struct iwm_priv *iwm, const char *img_name)
162{
163 const struct firmware *fw;
164 struct iwm_fw_img_desc *img_desc;
165 struct iwm_fw_img_ver *ver;
166 int ret = 0, fw_offset;
167 u32 opcode_idx = 0, build_date;
168 char *build_tag;
169
170 ret = request_firmware(&fw, img_name, iwm_to_dev(iwm));
171 if (ret) {
172 IWM_ERR(iwm, "Request firmware failed");
173 return ret;
174 }
175
176 IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name);
177
178 while (1) {
179 fw_offset = iwm_fw_op_offset(iwm, fw,
180 IWM_HDR_REC_OP_MEM_DESC,
181 opcode_idx);
182 if (fw_offset < 0)
183 break;
184
185 img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset);
186 ret = iwm_load_firmware_chunk(iwm, fw, img_desc);
187 if (ret < 0)
188 goto err_release_fw;
189 opcode_idx++;
190 };
191
192 /* Read firmware version */
193 fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0);
194 if (fw_offset < 0)
195 goto err_release_fw;
196
197 ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset);
198
199 /* Read build tag */
200 fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0);
201 if (fw_offset < 0)
202 goto err_release_fw;
203
204 build_tag = (char *)(fw->data + fw_offset);
205
206 /* Read build date */
207 fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0);
208 if (fw_offset < 0)
209 goto err_release_fw;
210
211 build_date = *(u32 *)(fw->data + fw_offset);
212
213 IWM_INFO(iwm, "%s:\n", img_name);
214 IWM_INFO(iwm, "\tVersion: %02X.%02X\n", ver->major, ver->minor);
215 IWM_INFO(iwm, "\tBuild tag: %s\n", build_tag);
216 IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n",
217 IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date),
218 IWM_BUILD_DAY(build_date));
219
220
221 err_release_fw:
222 release_firmware(fw);
223
224 return ret;
225}
226
227static int iwm_load_umac(struct iwm_priv *iwm)
228{
229 struct iwm_udma_nonwifi_cmd target_cmd;
230 int ret;
231
232 ret = iwm_load_img(iwm, iwm->bus_ops->umac_name);
233 if (ret < 0)
234 return ret;
235
236 /* We've loaded the UMAC, we can tell the target to jump there */
237 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP;
238 target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR);
239 target_cmd.op1_sz = 0;
240 target_cmd.op2 = 0;
241 target_cmd.handle_by_hw = 0;
242 target_cmd.resp = 1 ;
243 target_cmd.eop = 1;
244
245 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
246 if (ret < 0)
247 IWM_ERR(iwm, "Couldn't send JMP command\n");
248
249 return ret;
250}
251
252static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
253{
254 int ret;
255
256 ret = iwm_load_img(iwm, img_name);
257 if (ret < 0)
258 return ret;
259
260 return iwm_send_umac_reset(iwm,
261 cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
262}
263
264/*
265 * We currently have to load 3 FWs:
266 * 1) The UMAC (Upper MAC).
267 * 2) The calibration LMAC (Lower MAC).
268 * We then send the calibration init command, so that the device can
269 * run a first calibration round.
270 * 3) The operational LMAC, which replaces the calibration one when it's
271 * done with the first calibration round.
272 *
273 * Once those 3 FWs have been loaded, we send the periodic calibration
274 * command, and then the device is available for regular 802.11 operations.
275 */
276int iwm_load_fw(struct iwm_priv *iwm)
277{
278 int ret;
279
280 /* We first start downloading the UMAC */
281 ret = iwm_load_umac(iwm);
282 if (ret < 0) {
283 IWM_ERR(iwm, "UMAC loading failed\n");
284 return ret;
285 }
286
287 /* Handle UMAC_ALIVE notification */
288 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC,
289 WAIT_NOTIF_TIMEOUT);
290 if (ret) {
291 IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret);
292 return ret;
293 }
294
295 /* UMAC is alive, we can download the calibration LMAC */
296 ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name);
297 if (ret) {
298 IWM_ERR(iwm, "Calibration LMAC loading failed\n");
299 return ret;
300 }
301
302 /* Handle UMAC_INIT_COMPLETE notification */
303 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
304 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
305 if (ret) {
306 IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration "
307 "LMAC: %d\n", ret);
308 return ret;
309 }
310
311 /* Read EEPROM data */
312 ret = iwm_eeprom_init(iwm);
313 if (ret < 0) {
314 IWM_ERR(iwm, "Couldn't init eeprom array\n");
315 return ret;
316 }
317
318#ifdef CONFIG_IWM_B0_HW_SUPPORT
319 if (iwm->conf.hw_b0) {
320 clear_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map);
321 clear_bit(PHY_CALIBRATE_RX_IQ_CMD,
322 &iwm->conf.periodic_calib_map);
323 }
324#endif
325 /* Read RX IQ calibration result from EEPROM */
326 if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->conf.init_calib_map)) {
327 iwm_store_rxiq_calib_result(iwm);
328 set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
329 }
330
331 iwm_send_prio_table(iwm);
332 iwm_send_init_calib_cfg(iwm, iwm->conf.init_calib_map);
333
334 while (iwm->calib_done_map != iwm->conf.init_calib_map) {
335 ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
336 IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
337 if (ret) {
338 IWM_ERR(iwm, "Wait for calibration result timeout\n");
339 goto out;
340 }
341 IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
342 "0x%lx, requested calibrations: 0x%lx\n",
343 iwm->calib_done_map, iwm->conf.init_calib_map);
344 }
345
346 /* Handle LMAC CALIBRATION_COMPLETE notification */
347 ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION,
348 IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
349 if (ret) {
350 IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n");
351 goto out;
352 }
353
354 IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map);
355
356 iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1);
357
358 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC,
359 WAIT_NOTIF_TIMEOUT);
360 if (ret) {
361 IWM_ERR(iwm, "Wait for UMAC RESET timeout\n");
362 goto out;
363 }
364
365 /* Download the operational LMAC */
366 ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name);
367 if (ret) {
368 IWM_ERR(iwm, "LMAC loading failed\n");
369 goto out;
370 }
371
372 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE,
373 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
374 if (ret) {
375 IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret);
376 goto out;
377 }
378
379 iwm_send_prio_table(iwm);
380 iwm_send_calib_results(iwm);
381 iwm_send_periodic_calib_cfg(iwm, iwm->conf.periodic_calib_map);
382
383 return 0;
384
385 out:
386 iwm_eeprom_exit(iwm);
387 return ret;
388}
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.h b/drivers/net/wireless/iwmc3200wifi/fw.h
new file mode 100644
index 000000000000..c70a3b40dad3
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/fw.h
@@ -0,0 +1,100 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_FW_H__
40#define __IWM_FW_H__
41
42/**
43 * struct iwm_fw_hdr_rec - An iwm firmware image is a
44 * concatenation of various records. Each of them is
45 * defined by an ID (aka op code), a length, and the
46 * actual data.
47 * @op_code: The record ID, see IWM_HDR_REC_OP_*
48 *
49 * @len: The record payload length
50 *
51 * @buf: The record payload
52 */
53struct iwm_fw_hdr_rec {
54 u16 op_code;
55 u16 len;
56 u8 buf[0];
57};
58
59/* Header's definitions */
60#define IWM_HDR_LEN (512)
61#define IWM_HDR_BARKER_LEN (16)
62
63/* Header's opcodes */
64#define IWM_HDR_REC_OP_INVALID (0x00)
65#define IWM_HDR_REC_OP_BUILD_DATE (0x01)
66#define IWM_HDR_REC_OP_BUILD_TAG (0x02)
67#define IWM_HDR_REC_OP_SW_VER (0x03)
68#define IWM_HDR_REC_OP_HW_SKU (0x04)
69#define IWM_HDR_REC_OP_BUILD_OPT (0x05)
70#define IWM_HDR_REC_OP_MEM_DESC (0x06)
71#define IWM_HDR_REC_USERDEFS (0x07)
72
73/* Header's records length (in bytes) */
74#define IWM_HDR_REC_LEN_BUILD_DATE (4)
75#define IWM_HDR_REC_LEN_BUILD_TAG (64)
76#define IWM_HDR_REC_LEN_SW_VER (4)
77#define IWM_HDR_REC_LEN_HW_SKU (4)
78#define IWM_HDR_REC_LEN_BUILD_OPT (4)
79#define IWM_HDR_REC_LEN_MEM_DESC (12)
80#define IWM_HDR_REC_LEN_USERDEF (64)
81
82#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff)
83#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff)
84#define IWM_BUILD_DAY(date) (date & 0xff)
85
86struct iwm_fw_img_desc {
87 u32 offset;
88 u32 address;
89 u32 length;
90};
91
92struct iwm_fw_img_ver {
93 u8 minor;
94 u8 major;
95 u16 reserved;
96};
97
98int iwm_load_fw(struct iwm_priv *iwm);
99
100#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c
new file mode 100644
index 000000000000..ee127fe4f43f
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/hal.c
@@ -0,0 +1,464 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39/*
40 * Hardware Abstraction Layer for iwm.
41 *
42 * This file mostly defines an abstraction API for
43 * sending various commands to the target.
44 *
45 * We have 2 types of commands: wifi and non-wifi ones.
46 *
47 * - wifi commands:
48 * They are used for sending LMAC and UMAC commands,
49 * and thus are the most commonly used ones.
50 * There are 2 different wifi command types, the regular
51 * one and the LMAC one. The former is used to send
52 * UMAC commands (see UMAC_CMD_OPCODE_* from umac.h)
53 * while the latter is used for sending commands to the
54 * LMAC. If you look at LMAC commands you'll se that they
55 * are actually regular iwlwifi target commands encapsulated
56 * into a special UMAC command called UMAC passthrough.
57 * This is due to the fact the the host talks exclusively
58 * to the UMAC and so there needs to be a special UMAC
59 * command for talking to the LMAC.
60 * This is how a wifi command is layed out:
61 * ------------------------
62 * | iwm_udma_out_wifi_hdr |
63 * ------------------------
64 * | SW meta_data (32 bits) |
65 * ------------------------
66 * | iwm_dev_cmd_hdr |
67 * ------------------------
68 * | payload |
69 * | .... |
70 *
71 * - non-wifi, or general commands:
72 * Those commands are handled by the device's bootrom,
73 * and are typically sent when the UMAC and the LMAC
74 * are not yet available.
75 * * This is how a non-wifi command is layed out:
76 * ---------------------------
77 * | iwm_udma_out_nonwifi_hdr |
78 * ---------------------------
79 * | payload |
80 * | .... |
81
82 *
83 * All the commands start with a UDMA header, which is
84 * basically a 32 bits field. The 4 LSB there define
85 * an opcode that allows the target to differentiate
86 * between wifi (opcode is 0xf) and non-wifi commands
87 * (opcode is [0..0xe]).
88 *
89 * When a command (wifi or non-wifi) is supposed to receive
90 * an answer, we queue the command buffer. When we do receive
91 * a command response from the UMAC, we go through the list
92 * of pending command, and pass both the command and the answer
93 * to the rx handler. Each command is sent with a unique
94 * sequence id, and the answer is sent with the same one. This
95 * is how we're supposed to match an answer with its command.
96 * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi()
97 * for the implementation details.
98 */
99#include <linux/kernel.h>
100#include <linux/netdevice.h>
101
102#include "iwm.h"
103#include "bus.h"
104#include "hal.h"
105#include "umac.h"
106#include "debug.h"
107
108static void iwm_nonwifi_cmd_init(struct iwm_priv *iwm,
109 struct iwm_nonwifi_cmd *cmd,
110 struct iwm_udma_nonwifi_cmd *udma_cmd)
111{
112 INIT_LIST_HEAD(&cmd->pending);
113
114 spin_lock(&iwm->cmd_lock);
115
116 cmd->resp_received = 0;
117
118 cmd->seq_num = iwm->nonwifi_seq_num;
119 udma_cmd->seq_num = cpu_to_le16(cmd->seq_num);
120
121 cmd->seq_num = iwm->nonwifi_seq_num++;
122 iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX;
123
124 if (udma_cmd->resp)
125 list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd);
126
127 spin_unlock(&iwm->cmd_lock);
128
129 cmd->buf.start = cmd->buf.payload;
130 cmd->buf.len = 0;
131
132 memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
133}
134
135u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm)
136{
137 u16 seq_num = iwm->wifi_seq_num;
138
139 iwm->wifi_seq_num++;
140 iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX;
141
142 return seq_num;
143}
144
145static void iwm_wifi_cmd_init(struct iwm_priv *iwm,
146 struct iwm_wifi_cmd *cmd,
147 struct iwm_udma_wifi_cmd *udma_cmd,
148 struct iwm_umac_cmd *umac_cmd,
149 struct iwm_lmac_cmd *lmac_cmd,
150 u16 payload_size)
151{
152 INIT_LIST_HEAD(&cmd->pending);
153
154 spin_lock(&iwm->cmd_lock);
155
156 cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm);
157 umac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
158
159 if (umac_cmd->resp)
160 list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd);
161
162 spin_unlock(&iwm->cmd_lock);
163
164 cmd->buf.start = cmd->buf.payload;
165 cmd->buf.len = 0;
166
167 if (lmac_cmd) {
168 cmd->buf.start -= sizeof(struct iwm_lmac_hdr);
169
170 lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num);
171 lmac_cmd->count = cpu_to_le16(payload_size);
172
173 memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd));
174
175 umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr));
176 } else
177 umac_cmd->count = 0;
178
179 umac_cmd->count = cpu_to_le16(payload_size +
180 le16_to_cpu(umac_cmd->count));
181 udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) +
182 le16_to_cpu(umac_cmd->count));
183
184 memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd));
185 memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd));
186}
187
188void iwm_cmd_flush(struct iwm_priv *iwm)
189{
190 struct iwm_wifi_cmd *wcmd, *wnext;
191 struct iwm_nonwifi_cmd *nwcmd, *nwnext;
192
193 list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) {
194 list_del(&wcmd->pending);
195 kfree(wcmd);
196 }
197
198 list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd,
199 pending) {
200 list_del(&nwcmd->pending);
201 kfree(nwcmd);
202 }
203}
204
205struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num)
206{
207 struct iwm_wifi_cmd *cmd, *next;
208
209 list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending)
210 if (cmd->seq_num == seq_num) {
211 list_del(&cmd->pending);
212 return cmd;
213 }
214
215 return NULL;
216}
217
218struct iwm_nonwifi_cmd *
219iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode)
220{
221 struct iwm_nonwifi_cmd *cmd, *next;
222
223 list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending)
224 if ((cmd->seq_num == seq_num) &&
225 (cmd->udma_cmd.opcode == cmd_opcode) &&
226 (cmd->resp_received)) {
227 list_del(&cmd->pending);
228 return cmd;
229 }
230
231 return NULL;
232}
233
234static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm,
235 struct iwm_udma_out_nonwifi_hdr *hdr,
236 struct iwm_udma_nonwifi_cmd *cmd)
237{
238 memset(hdr, 0, sizeof(*hdr));
239
240 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode);
241 SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp);
242 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1);
243 SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW,
244 cmd->handle_by_hw);
245 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
246 SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM,
247 le16_to_cpu(cmd->seq_num));
248
249 hdr->addr = cmd->addr;
250 hdr->op1_sz = cmd->op1_sz;
251 hdr->op2 = cmd->op2;
252}
253
254static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm,
255 struct iwm_nonwifi_cmd *cmd)
256{
257 struct iwm_udma_out_nonwifi_hdr *udma_hdr;
258 struct iwm_nonwifi_cmd_buff *buf;
259 struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd;
260
261 buf = &cmd->buf;
262
263 buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr);
264 buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr);
265
266 udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start);
267
268 iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd);
269
270 IWM_DBG_CMD(iwm, DBG,
271 "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, "
272 "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, "
273 "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp,
274 udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr,
275 udma_cmd->op1_sz, udma_cmd->op2);
276
277 return iwm_bus_send_chunk(iwm, buf->start, buf->len);
278}
279
280void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop)
281{
282 struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf;
283
284 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop);
285}
286
287void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
288 struct iwm_udma_out_wifi_hdr *hdr,
289 struct iwm_udma_wifi_cmd *cmd)
290{
291 memset(hdr, 0, sizeof(*hdr));
292
293 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI);
294 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop);
295 SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE);
296
297 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT,
298 le16_to_cpu(cmd->count));
299 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group);
300 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid);
301 SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset);
302}
303
304void iwm_build_umac_hdr(struct iwm_priv *iwm,
305 struct iwm_umac_fw_cmd_hdr *hdr,
306 struct iwm_umac_cmd *cmd)
307{
308 memset(hdr, 0, sizeof(*hdr));
309
310 SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT,
311 le16_to_cpu(cmd->count));
312 SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color);
313 SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp);
314
315 hdr->cmd.cmd = cmd->id;
316 hdr->cmd.seq_num = cmd->seq_num;
317}
318
319static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm,
320 struct iwm_wifi_cmd *cmd)
321{
322 struct iwm_umac_wifi_out_hdr *umac_hdr;
323 struct iwm_wifi_cmd_buff *buf;
324 struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd;
325 struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd;
326 int ret;
327
328 buf = &cmd->buf;
329
330 buf->start -= sizeof(struct iwm_umac_wifi_out_hdr);
331 buf->len += sizeof(struct iwm_umac_wifi_out_hdr);
332
333 umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start);
334
335 iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd);
336 iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd);
337
338 IWM_DBG_CMD(iwm, DBG,
339 "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, "
340 "eop = 0x%x, count = 0x%x, credit_group = 0x%x, "
341 "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n",
342 UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id,
343 udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group,
344 udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num);
345
346 if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH)
347 IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n",
348 cmd->lmac_cmd.id);
349
350 ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len);
351
352 /* We keep sending UMAC reset regardless of the command credits.
353 * The UMAC is supposed to be reset anyway and the Tx credits are
354 * reinitialized afterwards. If we are lucky, the reset could
355 * still be done even though we have run out of credits for the
356 * command pool at this moment.*/
357 if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) {
358 IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n",
359 umac_cmd->id);
360 return ret;
361 }
362
363 return iwm_bus_send_chunk(iwm, buf->start, buf->len);
364}
365
366/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */
367int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
368 struct iwm_udma_nonwifi_cmd *udma_cmd,
369 const void *payload)
370{
371 struct iwm_nonwifi_cmd *cmd;
372 int ret;
373
374 cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL);
375 if (!cmd) {
376 IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n");
377 return -ENOMEM;
378 }
379
380 iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd);
381
382 if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE ||
383 cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) {
384 cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz);
385 memcpy(&cmd->buf.payload, payload, cmd->buf.len);
386 }
387
388 ret = iwm_send_udma_nonwifi_cmd(iwm, cmd);
389
390 if (!udma_cmd->resp)
391 kfree(cmd);
392
393 if (ret < 0)
394 return ret;
395
396 return cmd->seq_num;
397}
398
399static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr,
400 struct iwm_lmac_cmd *cmd)
401{
402 memset(hdr, 0, sizeof(*hdr));
403
404 hdr->id = cmd->id;
405 hdr->flags = 0; /* Is this ever used? */
406 hdr->seq_num = cmd->seq_num;
407}
408
409/*
410 * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC.
411 * Sending command to the LMAC is equivalent to sending a
412 * regular UMAC command with the LMAC passtrough or the LMAC
413 * wrapper UMAC command IDs.
414 */
415int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
416 struct iwm_udma_wifi_cmd *udma_cmd,
417 struct iwm_umac_cmd *umac_cmd,
418 struct iwm_lmac_cmd *lmac_cmd,
419 const void *payload, u16 payload_size)
420{
421 struct iwm_wifi_cmd *cmd;
422 struct iwm_lmac_hdr *hdr;
423 int lmac_hdr_len = 0;
424 int ret;
425
426 cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL);
427 if (!cmd) {
428 IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n");
429 return -ENOMEM;
430 }
431
432 iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size);
433
434 if (lmac_cmd) {
435 hdr = (struct iwm_lmac_hdr *)(cmd->buf.start);
436
437 iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd);
438 lmac_hdr_len = sizeof(struct iwm_lmac_hdr);
439 }
440
441 memcpy(cmd->buf.payload, payload, payload_size);
442 cmd->buf.len = le16_to_cpu(umac_cmd->count);
443
444 ret = iwm_send_udma_wifi_cmd(iwm, cmd);
445
446 /* We free the cmd if we're not expecting any response */
447 if (!umac_cmd->resp)
448 kfree(cmd);
449 return ret;
450}
451
452/*
453 * iwm_hal_send_umac_cmd(): This is a special case for
454 * iwm_hal_send_host_cmd() to send direct UMAC cmd (without
455 * LMAC involved).
456 */
457int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
458 struct iwm_udma_wifi_cmd *udma_cmd,
459 struct iwm_umac_cmd *umac_cmd,
460 const void *payload, u16 payload_size)
461{
462 return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL,
463 payload, payload_size);
464}
diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h
new file mode 100644
index 000000000000..0adfdc85765d
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/hal.h
@@ -0,0 +1,236 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef _IWM_HAL_H_
40#define _IWM_HAL_H_
41
42#include "umac.h"
43
44#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED)
45#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED)
46#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED)
47
48#define SET_VAL8(s, name, val) \
49do { \
50 s = (s & ~(name##_SEED << name##_POS)) | \
51 ((val & name##_SEED) << name##_POS); \
52} while (0)
53
54#define SET_VAL16(s, name, val) \
55do { \
56 s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
57 ((val & name##_SEED) << name##_POS)); \
58} while (0)
59
60#define SET_VAL32(s, name, val) \
61do { \
62 s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \
63 ((val & name##_SEED) << name##_POS)); \
64} while (0)
65
66
67#define UDMA_UMAC_INIT { .eop = 1, \
68 .credit_group = 0x4, \
69 .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
70 .lmac_offset = 0 }
71#define UDMA_LMAC_INIT { .eop = 1, \
72 .credit_group = 0x4, \
73 .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \
74 .lmac_offset = 4 }
75
76
77/* UDMA IN OP CODE -- cmd bits [3:0] */
78#define UDMA_IN_OPCODE_MASK 0xF
79
80#define UDMA_IN_OPCODE_GENERAL_RESP 0x0
81#define UDMA_IN_OPCODE_READ_RESP 0x1
82#define UDMA_IN_OPCODE_WRITE_RESP 0x2
83#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5
84#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6
85#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7
86#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8
87#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9
88#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA
89#define UDMA_IN_OPCODE_SW_MSG 0xB
90#define UDMA_IN_OPCODE_WIFI 0xF
91#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F
92#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F
93
94/* HW API: udma_hdi_nonwifi API (OUT and IN) */
95
96/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */
97#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9
98#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1
99
100/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */
101#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11
102#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1
103
104/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */
105#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12
106#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF
107
108/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */
109#define UDMA_IN_NW_HW_SEQ_NUM_POS 12
110#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF
111
112/* UDMA IN Non-WIFI HW signature -- bits [16:31] */
113#define UDMA_IN_NW_HW_SIG_POS 16
114#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF
115
116/* fixed signature */
117#define UDMA_IN_NW_HW_SIG 0xCBBC
118
119/* UDMA IN Non-WIFI HW block length -- bits [32:35] */
120#define UDMA_IN_NW_HW_LENGTH_SEED 0xF
121#define UDMA_IN_NW_HW_LENGTH_POS 32
122
123/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */
124
125#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032
126#define IWM_MAX_WIFI_HEADERS_SIZE 32
127#define IWM_MAX_NONWIFI_HEADERS_SIZE 16
128#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
129 IWM_MAX_NONWIFI_HEADERS_SIZE)
130#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \
131 IWM_MAX_WIFI_HEADERS_SIZE)
132
133#define IWM_HAL_CONCATENATE_BUF_SIZE 8192
134
135struct iwm_wifi_cmd_buff {
136 u16 len;
137 u8 *start;
138 u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE];
139 u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE];
140};
141
142struct iwm_nonwifi_cmd_buff {
143 u16 len;
144 u8 *start;
145 u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE];
146 u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE];
147};
148
149struct iwm_udma_nonwifi_cmd {
150 u8 opcode;
151 u8 eop;
152 u8 resp;
153 u8 handle_by_hw;
154 __le32 addr;
155 __le32 op1_sz;
156 __le32 op2;
157 __le16 seq_num;
158};
159
160struct iwm_udma_wifi_cmd {
161 __le16 count;
162 u8 eop;
163 u8 credit_group;
164 u8 ra_tid;
165 u8 lmac_offset;
166};
167
168struct iwm_umac_cmd {
169 u8 id;
170 __le16 count;
171 u8 resp;
172 __le16 seq_num;
173 u8 color;
174};
175
176struct iwm_lmac_cmd {
177 u8 id;
178 __le16 count;
179 u8 resp;
180 __le16 seq_num;
181};
182
183struct iwm_nonwifi_cmd {
184 u16 seq_num;
185 bool resp_received;
186 struct list_head pending;
187 struct iwm_udma_nonwifi_cmd udma_cmd;
188 struct iwm_umac_cmd umac_cmd;
189 struct iwm_lmac_cmd lmac_cmd;
190 struct iwm_nonwifi_cmd_buff buf;
191 u32 flags;
192};
193
194struct iwm_wifi_cmd {
195 u16 seq_num;
196 struct list_head pending;
197 struct iwm_udma_wifi_cmd udma_cmd;
198 struct iwm_umac_cmd umac_cmd;
199 struct iwm_lmac_cmd lmac_cmd;
200 struct iwm_wifi_cmd_buff buf;
201 u32 flags;
202};
203
204void iwm_cmd_flush(struct iwm_priv *iwm);
205
206struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm,
207 u16 seq_num);
208struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm,
209 u8 seq_num, u8 cmd_opcode);
210
211
212int iwm_hal_send_target_cmd(struct iwm_priv *iwm,
213 struct iwm_udma_nonwifi_cmd *ucmd,
214 const void *payload);
215
216int iwm_hal_send_host_cmd(struct iwm_priv *iwm,
217 struct iwm_udma_wifi_cmd *udma_cmd,
218 struct iwm_umac_cmd *umac_cmd,
219 struct iwm_lmac_cmd *lmac_cmd,
220 const void *payload, u16 payload_size);
221
222int iwm_hal_send_umac_cmd(struct iwm_priv *iwm,
223 struct iwm_udma_wifi_cmd *udma_cmd,
224 struct iwm_umac_cmd *umac_cmd,
225 const void *payload, u16 payload_size);
226
227u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm);
228
229void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop);
230void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm,
231 struct iwm_udma_out_wifi_hdr *hdr,
232 struct iwm_udma_wifi_cmd *cmd);
233void iwm_build_umac_hdr(struct iwm_priv *iwm,
234 struct iwm_umac_fw_cmd_hdr *hdr,
235 struct iwm_umac_cmd *cmd);
236#endif /* _IWM_HAL_H_ */
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
new file mode 100644
index 000000000000..3b29681792bb
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -0,0 +1,350 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_H__
40#define __IWM_H__
41
42#include <linux/netdevice.h>
43#include <linux/wireless.h>
44#include <net/cfg80211.h>
45
46#include "debug.h"
47#include "hal.h"
48#include "umac.h"
49#include "lmac.h"
50#include "eeprom.h"
51
52#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation"
53#define IWM_AUTHOR "<ilw@linux.intel.com>"
54
55#define CONFIG_IWM_B0_HW_SUPPORT 1
56
57#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX
58#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA
59#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW
60#define IWM_SRC_NUM 3
61
62#define IWM_POWER_INDEX_MIN 0
63#define IWM_POWER_INDEX_MAX 5
64#define IWM_POWER_INDEX_DEFAULT 3
65
66struct iwm_conf {
67 u32 sdio_ior_timeout;
68 unsigned long init_calib_map;
69 unsigned long periodic_calib_map;
70 bool reset_on_fatal_err;
71 bool auto_connect;
72 bool wimax_not_present;
73 bool enable_qos;
74 u32 mode;
75
76 u32 power_index;
77 u32 frag_threshold;
78 u32 rts_threshold;
79 bool cts_to_self;
80
81 u32 assoc_timeout;
82 u32 roam_timeout;
83 u32 wireless_mode;
84 u32 coexist_mode;
85
86 u8 ibss_band;
87 u8 ibss_channel;
88
89 u8 mac_addr[ETH_ALEN];
90#ifdef CONFIG_IWM_B0_HW_SUPPORT
91 bool hw_b0;
92#endif
93};
94
95enum {
96 COEX_MODE_SA = 1,
97 COEX_MODE_XOR,
98 COEX_MODE_CM,
99 COEX_MODE_MAX,
100};
101
102struct iwm_if_ops;
103struct iwm_wifi_cmd;
104
105struct pool_entry {
106 int id; /* group id */
107 int sid; /* super group id */
108 int min_pages; /* min capacity in pages */
109 int max_pages; /* max capacity in pages */
110 int alloc_pages; /* allocated # of pages. incresed by driver */
111 int total_freed_pages; /* total freed # of pages. incresed by UMAC */
112};
113
114struct spool_entry {
115 int id;
116 int max_pages;
117 int alloc_pages;
118};
119
120struct iwm_tx_credit {
121 spinlock_t lock;
122 int pool_nr;
123 unsigned long full_pools_map; /* bitmap for # of filled tx pools */
124 struct pool_entry pools[IWM_MACS_OUT_GROUPS];
125 struct spool_entry spools[IWM_MACS_OUT_SGROUPS];
126};
127
128struct iwm_notif {
129 struct list_head pending;
130 u32 cmd_id;
131 void *cmd;
132 u8 src;
133 void *buf;
134 unsigned long buf_size;
135};
136
137struct iwm_sta_info {
138 u8 addr[ETH_ALEN];
139 bool valid;
140 bool qos;
141 u8 color;
142};
143
144struct iwm_tx_info {
145 u8 sta;
146 u8 color;
147 u8 tid;
148};
149
150struct iwm_rx_info {
151 unsigned long rx_size;
152 unsigned long rx_buf_size;
153};
154
155#define IWM_NUM_KEYS 4
156
157struct iwm_umac_key_hdr {
158 u8 mac[ETH_ALEN];
159 u8 key_idx;
160 u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */
161} __attribute__ ((packed));
162
163struct iwm_key {
164 struct iwm_umac_key_hdr hdr;
165 u8 in_use;
166 u8 alg;
167 u32 flags;
168 u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE];
169 u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE];
170 u8 key_len;
171 u8 key[32];
172};
173
174#define IWM_RX_ID_HASH 0xff
175#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH)
176
177#define IWM_STA_TABLE_NUM 16
178#define IWM_TX_LIST_SIZE 64
179#define IWM_RX_LIST_SIZE 256
180
181#define IWM_SCAN_ID_MAX 0xff
182
183#define IWM_STATUS_READY 0
184#define IWM_STATUS_SCANNING 1
185#define IWM_STATUS_SCAN_ABORTING 2
186#define IWM_STATUS_ASSOCIATING 3
187#define IWM_STATUS_ASSOCIATED 4
188
189#define IWM_RADIO_RFKILL_OFF 0
190#define IWM_RADIO_RFKILL_HW 1
191#define IWM_RADIO_RFKILL_SW 2
192
193struct iwm_tx_queue {
194 int id;
195 struct sk_buff_head queue;
196 struct workqueue_struct *wq;
197 struct work_struct worker;
198 u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE];
199 int concat_count;
200 u8 *concat_ptr;
201};
202
203/* Queues 0 ~ 3 for AC data, 5 for iPAN */
204#define IWM_TX_QUEUES 5
205#define IWM_TX_DATA_QUEUES 4
206#define IWM_TX_CMD_QUEUE 4
207
208struct iwm_bss_info {
209 struct list_head node;
210 struct cfg80211_bss *cfg_bss;
211 struct iwm_umac_notif_bss_info *bss;
212};
213
214typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf,
215 unsigned long buf_size, struct iwm_wifi_cmd *cmd);
216
217#define IWM_WATCHDOG_PERIOD (6 * HZ)
218
219struct iwm_priv {
220 struct wireless_dev *wdev;
221 struct iwm_if_ops *bus_ops;
222
223 struct iwm_conf conf;
224
225 unsigned long status;
226 unsigned long radio;
227
228 struct list_head pending_notif;
229 wait_queue_head_t notif_queue;
230
231 wait_queue_head_t nonwifi_queue;
232
233 unsigned long calib_done_map;
234 struct {
235 u8 *buf;
236 u32 size;
237 } calib_res[CALIBRATION_CMD_NUM];
238
239 struct iwm_umac_profile *umac_profile;
240 bool umac_profile_active;
241
242 u8 bssid[ETH_ALEN];
243 u8 channel;
244 u16 rate;
245
246 struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM];
247 struct list_head bss_list;
248
249 void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX])
250 (struct iwm_priv *priv, u8 *buf, unsigned long buf_size);
251
252 const iwm_handler *umac_handlers;
253 const iwm_handler *lmac_handlers;
254 DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM);
255 DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM);
256 DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM);
257
258 struct list_head wifi_pending_cmd;
259 struct list_head nonwifi_pending_cmd;
260 u16 wifi_seq_num;
261 u8 nonwifi_seq_num;
262 spinlock_t cmd_lock;
263
264 u32 core_enabled;
265
266 u8 scan_id;
267 struct cfg80211_scan_request *scan_request;
268
269 struct sk_buff_head rx_list;
270 struct list_head rx_tickets;
271 struct list_head rx_packets[IWM_RX_ID_HASH];
272 struct workqueue_struct *rx_wq;
273 struct work_struct rx_worker;
274
275 struct iwm_tx_credit tx_credit;
276 struct iwm_tx_queue txq[IWM_TX_QUEUES];
277
278 struct iwm_key keys[IWM_NUM_KEYS];
279 struct iwm_key *default_key;
280
281 wait_queue_head_t mlme_queue;
282
283 struct iw_statistics wstats;
284 struct delayed_work stats_request;
285
286 struct iwm_debugfs dbg;
287
288 u8 *eeprom;
289 struct timer_list watchdog;
290 struct work_struct reset_worker;
291 struct rfkill *rfkill;
292
293 char private[0] __attribute__((__aligned__(NETDEV_ALIGN)));
294};
295
296static inline void *iwm_private(struct iwm_priv *iwm)
297{
298 BUG_ON(!iwm);
299 return &iwm->private;
300}
301
302#define hw_to_iwm(h) (h->iwm)
303#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy))
304#define iwm_to_wiphy(i) (i->wdev->wiphy)
305#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w))
306#define iwm_to_wdev(i) (i->wdev)
307#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w))
308#define iwm_to_ndev(i) (i->wdev->netdev)
309#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr))
310#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb))
311#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb)
312
313extern const struct iw_handler_def iwm_iw_handler_def;
314
315void *iwm_if_alloc(int sizeof_bus, struct device *dev,
316 struct iwm_if_ops *if_ops);
317void iwm_if_free(struct iwm_priv *iwm);
318int iwm_mode_to_nl80211_iftype(int mode);
319int iwm_priv_init(struct iwm_priv *iwm);
320void iwm_reset(struct iwm_priv *iwm);
321void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
322 struct iwm_umac_notif_alive *alive);
323int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb);
324int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
325 u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size);
326int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout);
327void iwm_init_default_profile(struct iwm_priv *iwm,
328 struct iwm_umac_profile *profile);
329void iwm_link_on(struct iwm_priv *iwm);
330void iwm_link_off(struct iwm_priv *iwm);
331int iwm_up(struct iwm_priv *iwm);
332int iwm_down(struct iwm_priv *iwm);
333
334/* TX API */
335void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
336void iwm_tx_worker(struct work_struct *work);
337int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
338
339/* RX API */
340void iwm_rx_setup_handlers(struct iwm_priv *iwm);
341int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size);
342int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
343 struct iwm_wifi_cmd *cmd);
344void iwm_rx_free(struct iwm_priv *iwm);
345
346/* RF Kill API */
347int iwm_rfkill_init(struct iwm_priv *iwm);
348void iwm_rfkill_exit(struct iwm_priv *iwm);
349
350#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
new file mode 100644
index 000000000000..db2e5eea1895
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/lmac.h
@@ -0,0 +1,457 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_LMAC_H__
40#define __IWM_LMAC_H__
41
42struct iwm_lmac_hdr {
43 u8 id;
44 u8 flags;
45 __le16 seq_num;
46} __attribute__ ((packed));
47
48/* LMAC commands */
49#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1
50
51struct iwm_lmac_cal_cfg_elt {
52 __le32 enable; /* 1 means LMAC needs to do something */
53 __le32 start; /* 1 to start calibration, 0 to stop */
54 __le32 send_res; /* 1 for sending back results */
55 __le32 apply_res; /* 1 for applying calibration results to HW */
56 __le32 reserved;
57} __attribute__ ((packed));
58
59struct iwm_lmac_cal_cfg_status {
60 struct iwm_lmac_cal_cfg_elt init;
61 struct iwm_lmac_cal_cfg_elt periodic;
62 __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */
63} __attribute__ ((packed));
64
65struct iwm_lmac_cal_cfg_cmd {
66 struct iwm_lmac_cal_cfg_status ucode_cfg;
67 struct iwm_lmac_cal_cfg_status driver_cfg;
68 __le32 reserved;
69} __attribute__ ((packed));
70
71struct iwm_lmac_cal_cfg_resp {
72 __le32 status;
73} __attribute__ ((packed));
74
75#define IWM_CARD_STATE_SW_HW_ENABLED 0x00
76#define IWM_CARD_STATE_HW_DISABLED 0x01
77#define IWM_CARD_STATE_SW_DISABLED 0x02
78#define IWM_CARD_STATE_CTKILL_DISABLED 0x04
79#define IWM_CARD_STATE_IS_RXON 0x10
80
81struct iwm_lmac_card_state {
82 __le32 flags;
83} __attribute__ ((packed));
84
85/**
86 * COEX_PRIORITY_TABLE_CMD
87 *
88 * Priority entry for each state
89 * Will keep two tables, for STA and WIPAN
90 */
91enum {
92 /* UN-ASSOCIATION PART */
93 COEX_UNASSOC_IDLE = 0,
94 COEX_UNASSOC_MANUAL_SCAN,
95 COEX_UNASSOC_AUTO_SCAN,
96
97 /* CALIBRATION */
98 COEX_CALIBRATION,
99 COEX_PERIODIC_CALIBRATION,
100
101 /* CONNECTION */
102 COEX_CONNECTION_ESTAB,
103
104 /* ASSOCIATION PART */
105 COEX_ASSOCIATED_IDLE,
106 COEX_ASSOC_MANUAL_SCAN,
107 COEX_ASSOC_AUTO_SCAN,
108 COEX_ASSOC_ACTIVE_LEVEL,
109
110 /* RF ON/OFF */
111 COEX_RF_ON,
112 COEX_RF_OFF,
113 COEX_STAND_ALONE_DEBUG,
114
115 /* IPNN */
116 COEX_IPAN_ASSOC_LEVEL,
117
118 /* RESERVED */
119 COEX_RSRVD1,
120 COEX_RSRVD2,
121
122 COEX_EVENTS_NUM
123};
124
125#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK 0x1
126#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK 0x2
127#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK 0x4
128
129struct coex_event {
130 u8 req_prio;
131 u8 win_med_prio;
132 u8 reserved;
133 u8 flags;
134} __attribute__ ((packed));
135
136#define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1
137#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4
138#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK 0x8
139#define COEX_FLAGS_COEX_ENABLE_MSK 0x80
140
141struct iwm_coex_prio_table_cmd {
142 u8 flags;
143 u8 reserved[3];
144 struct coex_event sta_prio[COEX_EVENTS_NUM];
145} __attribute__ ((packed));
146
147/* Coexistence definitions
148 *
149 * Constants to fill in the Priorities' Tables
150 * RP - Requested Priority
151 * WP - Win Medium Priority: priority assigned when the contention has been won
152 * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and
153 * COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK
154 */
155
156#define COEX_UNASSOC_IDLE_FLAGS 0
157#define COEX_UNASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
158 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
159#define COEX_UNASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
160 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
161#define COEX_CALIBRATION_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
162 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
163#define COEX_PERIODIC_CALIBRATION_FLAGS 0
164/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX
165 * disconnect from network. */
166#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
167 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
168 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
169#define COEX_ASSOCIATED_IDLE_FLAGS 0
170#define COEX_ASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
171 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
172#define COEX_ASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
173 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
174#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0
175#define COEX_RF_ON_FLAGS 0
176#define COEX_RF_OFF_FLAGS 0
177#define COEX_STAND_ALONE_DEBUG_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
178 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK)
179#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
180 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
181 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
182#define COEX_RSRVD1_FLAGS 0
183#define COEX_RSRVD2_FLAGS 0
184/* XOR_RF_ON is the event wrapping all radio ownership. We need
185 * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */
186#define COEX_XOR_RF_ON_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \
187 COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \
188 COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK)
189
190/* LMAC OP CODES */
191#define REPLY_PAD 0x0
192#define REPLY_ALIVE 0x1
193#define REPLY_ERROR 0x2
194#define REPLY_ECHO 0x3
195#define REPLY_HALT 0x6
196
197/* RXON state commands */
198#define REPLY_RX_ON 0x10
199#define REPLY_RX_ON_ASSOC 0x11
200#define REPLY_RX_OFF 0x12
201#define REPLY_QOS_PARAM 0x13
202#define REPLY_RX_ON_TIMING 0x14
203#define REPLY_INTERNAL_QOS_PARAM 0x15
204#define REPLY_RX_INT_TIMEOUT_CNFG 0x16
205#define REPLY_NULL 0x17
206
207/* Multi-Station support */
208#define REPLY_ADD_STA 0x18
209#define REPLY_REMOVE_STA 0x19
210#define REPLY_RESET_ALL_STA 0x1a
211
212/* RX, TX */
213#define REPLY_ALM_RX 0x1b
214#define REPLY_TX 0x1c
215#define REPLY_TXFIFO_FLUSH 0x1e
216
217/* MISC commands */
218#define REPLY_MGMT_MCAST_KEY 0x1f
219#define REPLY_WEPKEY 0x20
220#define REPLY_INIT_IV 0x21
221#define REPLY_WRITE_MIB 0x22
222#define REPLY_READ_MIB 0x23
223#define REPLY_RADIO_FE 0x24
224#define REPLY_TXFIFO_CFG 0x25
225#define REPLY_WRITE_READ 0x26
226#define REPLY_INSTALL_SEC_KEY 0x27
227
228
229#define REPLY_RATE_SCALE 0x47
230#define REPLY_LEDS_CMD 0x48
231#define REPLY_TX_LINK_QUALITY_CMD 0x4e
232#define REPLY_ANA_MIB_OVERRIDE_CMD 0x4f
233#define REPLY_WRITE2REG_CMD 0x50
234
235/* winfi-wifi coexistence */
236#define COEX_PRIORITY_TABLE_CMD 0x5a
237#define COEX_MEDIUM_NOTIFICATION 0x5b
238#define COEX_EVENT_CMD 0x5c
239
240/* more Protocol and Protocol-test commands */
241#define REPLY_MAX_SLEEP_TIME_CMD 0x61
242#define CALIBRATION_CFG_CMD 0x65
243#define CALIBRATION_RES_NOTIFICATION 0x66
244#define CALIBRATION_COMPLETE_NOTIFICATION 0x67
245
246/* Measurements */
247#define REPLY_QUIET_CMD 0x71
248#define REPLY_CHANNEL_SWITCH 0x72
249#define CHANNEL_SWITCH_NOTIFICATION 0x73
250
251#define REPLY_SPECTRUM_MEASUREMENT_CMD 0x74
252#define SPECTRUM_MEASURE_NOTIFICATION 0x75
253#define REPLY_MEASUREMENT_ABORT_CMD 0x76
254
255/* Power Management */
256#define POWER_TABLE_CMD 0x77
257#define SAVE_RESTORE_ADRESS_CMD 0x78
258#define REPLY_WATERMARK_CMD 0x79
259#define PM_DEBUG_STATISTIC_NOTIFIC 0x7B
260#define PD_FLUSH_N_NOTIFICATION 0x7C
261
262/* Scan commands and notifications */
263#define REPLY_SCAN_REQUEST_CMD 0x80
264#define REPLY_SCAN_ABORT_CMD 0x81
265#define SCAN_START_NOTIFICATION 0x82
266#define SCAN_RESULTS_NOTIFICATION 0x83
267#define SCAN_COMPLETE_NOTIFICATION 0x84
268
269/* Continuous TX commands */
270#define REPLY_CONT_TX_CMD 0x85
271#define END_OF_CONT_TX_NOTIFICATION 0x86
272
273/* Timer/Eeprom commands */
274#define TIMER_CMD 0x87
275#define EEPROM_WRITE_CMD 0x88
276
277/* PAPD commands */
278#define FEEDBACK_REQUEST_NOTIFICATION 0x8b
279#define REPLY_CW_CMD 0x8c
280
281/* IBSS/AP commands Continue */
282#define BEACON_NOTIFICATION 0x90
283#define REPLY_TX_BEACON 0x91
284#define REPLY_REQUEST_ATIM 0x93
285#define WHO_IS_AWAKE_NOTIFICATION 0x94
286#define TX_PWR_DBM_LIMIT_CMD 0x95
287#define QUIET_NOTIFICATION 0x96
288#define TX_PWR_TABLE_CMD 0x97
289#define TX_ANT_CONFIGURATION_CMD 0x98
290#define MEASURE_ABORT_NOTIFICATION 0x99
291#define REPLY_CALIBRATION_TUNE 0x9a
292
293/* bt config command */
294#define REPLY_BT_CONFIG 0x9b
295#define REPLY_STATISTICS_CMD 0x9c
296#define STATISTICS_NOTIFICATION 0x9d
297
298/* RF-KILL commands and notifications */
299#define REPLY_CARD_STATE_CMD 0xa0
300#define CARD_STATE_NOTIFICATION 0xa1
301
302/* Missed beacons notification */
303#define MISSED_BEACONS_NOTIFICATION 0xa2
304#define MISSED_BEACONS_NOTIFICATION_TH_CMD 0xa3
305
306#define REPLY_CT_KILL_CONFIG_CMD 0xa4
307
308/* HD commands and notifications */
309#define REPLY_HD_PARAMS_CMD 0xa6
310#define HD_PARAMS_NOTIFICATION 0xa7
311#define SENSITIVITY_CMD 0xa8
312#define U_APSD_PARAMS_CMD 0xa9
313#define NOISY_PLATFORM_CMD 0xaa
314#define ILLEGAL_CMD 0xac
315#define REPLY_PHY_CALIBRATION_CMD 0xb0
316#define REPLAY_RX_GAIN_CALIB_CMD 0xb1
317
318/* WiPAN commands */
319#define REPLY_WIPAN_PARAMS_CMD 0xb2
320#define REPLY_WIPAN_RX_ON_CMD 0xb3
321#define REPLY_WIPAN_RX_ON_TIMING 0xb4
322#define REPLY_WIPAN_TX_PWR_TABLE_CMD 0xb5
323#define REPLY_WIPAN_RXON_ASSOC_CMD 0xb6
324#define REPLY_WIPAN_QOS_PARAM 0xb7
325#define WIPAN_REPLY_WEPKEY 0xb8
326
327/* BeamForming commands */
328#define BEAMFORMER_CFG_CMD 0xba
329#define BEAMFORMEE_NOTIFICATION 0xbb
330
331/* TGn new Commands */
332#define REPLY_RX_PHY_CMD 0xc0
333#define REPLY_RX_MPDU_CMD 0xc1
334#define REPLY_MULTICAST_HASH 0xc2
335#define REPLY_KDR_RX 0xc3
336#define REPLY_RX_DSP_EXT_INFO 0xc4
337#define REPLY_COMPRESSED_BA 0xc5
338
339/* PNC commands */
340#define PNC_CONFIG_CMD 0xc8
341#define PNC_UPDATE_TABLE_CMD 0xc9
342#define XVT_GENERAL_CTRL_CMD 0xca
343#define REPLY_LEGACY_RADIO_FE 0xdd
344
345/* WoWLAN commands */
346#define WOWLAN_PATTERNS 0xe0
347#define WOWLAN_WAKEUP_FILTER 0xe1
348#define WOWLAN_TSC_RSC_PARAM 0xe2
349#define WOWLAN_TKIP_PARAM 0xe3
350#define WOWLAN_KEK_KCK_MATERIAL 0xe4
351#define WOWLAN_GET_STATUSES 0xe5
352#define WOWLAN_TX_POWER_PER_DB 0xe6
353#define REPLY_WOWLAN_GET_STATUSES WOWLAN_GET_STATUSES
354
355#define REPLY_DEBUG_CMD 0xf0
356#define REPLY_DSP_DEBUG_CMD 0xf1
357#define REPLY_DEBUG_MONITOR_CMD 0xf2
358#define REPLY_DEBUG_XVT_CMD 0xf3
359#define REPLY_DEBUG_DC_CALIB 0xf4
360#define REPLY_DYNAMIC_BP 0xf5
361
362/* General purpose Commands */
363#define REPLY_GP1_CMD 0xfa
364#define REPLY_GP2_CMD 0xfb
365#define REPLY_GP3_CMD 0xfc
366#define REPLY_GP4_CMD 0xfd
367#define REPLY_REPLAY_WRAPPER 0xfe
368#define REPLY_FRAME_DURATION_CALC_CMD 0xff
369
370#define LMAC_COMMAND_ID_MAX 0xff
371#define LMAC_COMMAND_ID_NUM (LMAC_COMMAND_ID_MAX + 1)
372
373
374/* Calibration */
375
376enum {
377 PHY_CALIBRATE_DC_CMD = 0,
378 PHY_CALIBRATE_LO_CMD = 1,
379 PHY_CALIBRATE_RX_BB_CMD = 2,
380 PHY_CALIBRATE_TX_IQ_CMD = 3,
381 PHY_CALIBRATE_RX_IQ_CMD = 4,
382 PHY_CALIBRATION_NOISE_CMD = 5,
383 PHY_CALIBRATE_AGC_TABLE_CMD = 6,
384 PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 7,
385 PHY_CALIBRATE_OPCODES_NUM,
386 SHILOH_PHY_CALIBRATE_DC_CMD = 8,
387 SHILOH_PHY_CALIBRATE_LO_CMD = 9,
388 SHILOH_PHY_CALIBRATE_RX_BB_CMD = 10,
389 SHILOH_PHY_CALIBRATE_TX_IQ_CMD = 11,
390 SHILOH_PHY_CALIBRATE_RX_IQ_CMD = 12,
391 SHILOH_PHY_CALIBRATION_NOISE_CMD = 13,
392 SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
393 SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
394 SHILOH_PHY_CALIBRATE_BASE_BAND_CMD = 16,
395 SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD = 17,
396 CALIBRATION_CMD_NUM,
397};
398
399struct iwm_lmac_calib_hdr {
400 u8 opcode;
401 u8 first_grp;
402 u8 grp_num;
403 u8 all_data_valid;
404} __attribute__ ((packed));
405
406#define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7
407#define IWM_CALIB_FREQ_GROUPS_NR 5
408#define IWM_CALIB_DC_MODES_NR 12
409
410struct iwm_calib_rxiq_entry {
411 u16 ptam_postdist_ars;
412 u16 ptam_postdist_arc;
413} __attribute__ ((packed));
414
415struct iwm_calib_rxiq_group {
416 struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR];
417} __attribute__ ((packed));
418
419struct iwm_lmac_calib_rxiq {
420 struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR];
421} __attribute__ ((packed));
422
423struct iwm_calib_rxiq {
424 struct iwm_lmac_calib_hdr hdr;
425 struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR];
426} __attribute__ ((packed));
427
428#define LMAC_STA_ID_SEED 0x0f
429#define LMAC_STA_ID_POS 0
430
431#define LMAC_STA_COLOR_SEED 0x7
432#define LMAC_STA_COLOR_POS 4
433
434struct iwm_lmac_power_report {
435 u8 pa_status;
436 u8 pa_integ_res_A[3];
437 u8 pa_integ_res_B[3];
438 u8 pa_integ_res_C[3];
439} __attribute__ ((packed));
440
441struct iwm_lmac_tx_resp {
442 u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */
443 u8 bt_kill_cnt;
444 __le16 retry_cnt;
445 __le32 initial_tx_rate;
446 __le16 wireless_media_time;
447 struct iwm_lmac_power_report power_report;
448 __le32 tfd_info;
449 __le16 seq_ctl;
450 __le16 byte_cnt;
451 u8 tlc_rate_info;
452 u8 ra_tid;
453 __le16 frame_ctl;
454 __le32 status;
455} __attribute__ ((packed));
456
457#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
new file mode 100644
index 000000000000..6a2640f16b6d
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -0,0 +1,680 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/netdevice.h>
41#include <linux/ieee80211.h>
42#include <linux/wireless.h>
43
44#include "iwm.h"
45#include "debug.h"
46#include "bus.h"
47#include "umac.h"
48#include "commands.h"
49#include "hal.h"
50#include "fw.h"
51#include "rx.h"
52
53static struct iwm_conf def_iwm_conf = {
54
55 .sdio_ior_timeout = 5000,
56 .init_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
57 BIT(PHY_CALIBRATE_LO_CMD) |
58 BIT(PHY_CALIBRATE_TX_IQ_CMD) |
59 BIT(PHY_CALIBRATE_RX_IQ_CMD),
60 .periodic_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
61 BIT(PHY_CALIBRATE_LO_CMD) |
62 BIT(PHY_CALIBRATE_TX_IQ_CMD) |
63 BIT(PHY_CALIBRATE_RX_IQ_CMD) |
64 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
65 .reset_on_fatal_err = 1,
66 .auto_connect = 1,
67 .wimax_not_present = 0,
68 .enable_qos = 1,
69 .mode = UMAC_MODE_BSS,
70
71 /* UMAC configuration */
72 .power_index = 0,
73 .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
74 .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD,
75 .cts_to_self = 0,
76
77 .assoc_timeout = 2,
78 .roam_timeout = 10,
79 .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G,
80 .coexist_mode = COEX_MODE_CM,
81
82 /* IBSS */
83 .ibss_band = UMAC_BAND_2GHZ,
84 .ibss_channel = 1,
85
86 .mac_addr = {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03},
87};
88
89static int modparam_reset;
90module_param_named(reset, modparam_reset, bool, 0644);
91MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])");
92
93int iwm_mode_to_nl80211_iftype(int mode)
94{
95 switch (mode) {
96 case UMAC_MODE_BSS:
97 return NL80211_IFTYPE_STATION;
98 case UMAC_MODE_IBSS:
99 return NL80211_IFTYPE_ADHOC;
100 default:
101 return NL80211_IFTYPE_UNSPECIFIED;
102 }
103
104 return 0;
105}
106
107static void iwm_statistics_request(struct work_struct *work)
108{
109 struct iwm_priv *iwm =
110 container_of(work, struct iwm_priv, stats_request.work);
111
112 iwm_send_umac_stats_req(iwm, 0);
113}
114
115static void iwm_reset_worker(struct work_struct *work)
116{
117 struct iwm_priv *iwm;
118 struct iwm_umac_profile *profile = NULL;
119 int uninitialized_var(ret), retry = 0;
120
121 iwm = container_of(work, struct iwm_priv, reset_worker);
122
123 if (iwm->umac_profile_active) {
124 profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL);
125 if (profile)
126 memcpy(profile, iwm->umac_profile, sizeof(*profile));
127 else
128 IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
129 }
130
131 iwm_down(iwm);
132
133 while (retry++ < 3) {
134 ret = iwm_up(iwm);
135 if (!ret)
136 break;
137
138 schedule_timeout_uninterruptible(10 * HZ);
139 }
140
141 if (ret) {
142 IWM_WARN(iwm, "iwm_up() failed: %d\n", ret);
143
144 kfree(profile);
145 return;
146 }
147
148 if (profile) {
149 IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n");
150 memcpy(iwm->umac_profile, profile, sizeof(*profile));
151 iwm_send_mlme_profile(iwm);
152 kfree(profile);
153 }
154}
155
156static void iwm_watchdog(unsigned long data)
157{
158 struct iwm_priv *iwm = (struct iwm_priv *)data;
159
160 IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n");
161
162 if (modparam_reset)
163 schedule_work(&iwm->reset_worker);
164}
165
166int iwm_priv_init(struct iwm_priv *iwm)
167{
168 int i;
169 char name[32];
170
171 iwm->status = 0;
172 INIT_LIST_HEAD(&iwm->pending_notif);
173 init_waitqueue_head(&iwm->notif_queue);
174 init_waitqueue_head(&iwm->nonwifi_queue);
175 init_waitqueue_head(&iwm->mlme_queue);
176 memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf));
177 spin_lock_init(&iwm->tx_credit.lock);
178 INIT_LIST_HEAD(&iwm->wifi_pending_cmd);
179 INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd);
180 iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE;
181 iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE;
182 spin_lock_init(&iwm->cmd_lock);
183 iwm->scan_id = 1;
184 INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request);
185 INIT_WORK(&iwm->reset_worker, iwm_reset_worker);
186 INIT_LIST_HEAD(&iwm->bss_list);
187
188 skb_queue_head_init(&iwm->rx_list);
189 INIT_LIST_HEAD(&iwm->rx_tickets);
190 for (i = 0; i < IWM_RX_ID_HASH; i++)
191 INIT_LIST_HEAD(&iwm->rx_packets[i]);
192
193 INIT_WORK(&iwm->rx_worker, iwm_rx_worker);
194
195 iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx");
196 if (!iwm->rx_wq)
197 return -EAGAIN;
198
199 for (i = 0; i < IWM_TX_QUEUES; i++) {
200 INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker);
201 snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i);
202 iwm->txq[i].id = i;
203 iwm->txq[i].wq = create_singlethread_workqueue(name);
204 if (!iwm->txq[i].wq)
205 return -EAGAIN;
206
207 skb_queue_head_init(&iwm->txq[i].queue);
208 }
209
210 for (i = 0; i < IWM_NUM_KEYS; i++)
211 memset(&iwm->keys[i], 0, sizeof(struct iwm_key));
212
213 iwm->default_key = NULL;
214
215 init_timer(&iwm->watchdog);
216 iwm->watchdog.function = iwm_watchdog;
217 iwm->watchdog.data = (unsigned long)iwm;
218
219 return 0;
220}
221
222/*
223 * We reset all the structures, and we reset the UMAC.
224 * After calling this routine, you're expected to reload
225 * the firmware.
226 */
227void iwm_reset(struct iwm_priv *iwm)
228{
229 struct iwm_notif *notif, *next;
230
231 if (test_bit(IWM_STATUS_READY, &iwm->status))
232 iwm_target_reset(iwm);
233
234 iwm->status = 0;
235 iwm->scan_id = 1;
236
237 list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
238 list_del(&notif->pending);
239 kfree(notif->buf);
240 kfree(notif);
241 }
242
243 iwm_cmd_flush(iwm);
244
245 flush_workqueue(iwm->rx_wq);
246
247 iwm_link_off(iwm);
248}
249
250/*
251 * Notification code:
252 *
253 * We're faced with the following issue: Any host command can
254 * have an answer or not, and if there's an answer to expect,
255 * it can be treated synchronously or asynchronously.
256 * To work around the synchronous answer case, we implemented
257 * our notification mechanism.
258 * When a code path needs to wait for a command response
259 * synchronously, it calls notif_handle(), which waits for the
260 * right notification to show up, and then process it. Before
261 * starting to wait, it registered as a waiter for this specific
262 * answer (by toggling a bit in on of the handler_map), so that
263 * the rx code knows that it needs to send a notification to the
264 * waiting processes. It does so by calling iwm_notif_send(),
265 * which adds the notification to the pending notifications list,
266 * and then wakes the waiting processes up.
267 */
268int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd,
269 u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size)
270{
271 struct iwm_notif *notif;
272
273 notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL);
274 if (!notif) {
275 IWM_ERR(iwm, "Couldn't alloc memory for notification\n");
276 return -ENOMEM;
277 }
278
279 INIT_LIST_HEAD(&notif->pending);
280 notif->cmd = cmd;
281 notif->cmd_id = cmd_id;
282 notif->src = source;
283 notif->buf = kzalloc(buf_size, GFP_KERNEL);
284 if (!notif->buf) {
285 IWM_ERR(iwm, "Couldn't alloc notification buffer\n");
286 kfree(notif);
287 return -ENOMEM;
288 }
289 notif->buf_size = buf_size;
290 memcpy(notif->buf, buf, buf_size);
291 list_add_tail(&notif->pending, &iwm->pending_notif);
292
293 wake_up_interruptible(&iwm->notif_queue);
294
295 return 0;
296}
297
298static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd,
299 u8 source)
300{
301 struct iwm_notif *notif, *next;
302
303 list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) {
304 if ((notif->cmd_id == cmd) && (notif->src == source)) {
305 list_del(&notif->pending);
306 return notif;
307 }
308 }
309
310 return NULL;
311}
312
313static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd,
314 u8 source, long timeout)
315{
316 int ret;
317 struct iwm_notif *notif;
318 unsigned long *map = NULL;
319
320 switch (source) {
321 case IWM_SRC_LMAC:
322 map = &iwm->lmac_handler_map[0];
323 break;
324 case IWM_SRC_UMAC:
325 map = &iwm->umac_handler_map[0];
326 break;
327 case IWM_SRC_UDMA:
328 map = &iwm->udma_handler_map[0];
329 break;
330 }
331
332 set_bit(cmd, map);
333
334 ret = wait_event_interruptible_timeout(iwm->notif_queue,
335 ((notif = iwm_notif_find(iwm, cmd, source)) != NULL),
336 timeout);
337 clear_bit(cmd, map);
338
339 if (!ret)
340 return NULL;
341
342 return notif;
343}
344
345int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout)
346{
347 int ret;
348 struct iwm_notif *notif;
349
350 notif = iwm_notif_wait(iwm, cmd, source, timeout);
351 if (!notif)
352 return -ETIME;
353
354 ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd);
355 kfree(notif->buf);
356 kfree(notif);
357
358 return ret;
359}
360
361static int iwm_config_boot_params(struct iwm_priv *iwm)
362{
363 struct iwm_udma_nonwifi_cmd target_cmd;
364 int ret;
365
366 /* check Wimax is off and config debug monitor */
367 if (iwm->conf.wimax_not_present) {
368 u32 data1 = 0x1f;
369 u32 addr1 = 0x606BE258;
370
371 u32 data2_set = 0x0;
372 u32 data2_clr = 0x1;
373 u32 addr2 = 0x606BE100;
374
375 u32 data3 = 0x1;
376 u32 addr3 = 0x606BEC00;
377
378 target_cmd.resp = 0;
379 target_cmd.handle_by_hw = 0;
380 target_cmd.eop = 1;
381
382 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
383 target_cmd.addr = cpu_to_le32(addr1);
384 target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
385 target_cmd.op2 = 0;
386
387 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
388 if (ret < 0) {
389 IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
390 return ret;
391 }
392
393 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE;
394 target_cmd.addr = cpu_to_le32(addr2);
395 target_cmd.op1_sz = cpu_to_le32(data2_set);
396 target_cmd.op2 = cpu_to_le32(data2_clr);
397
398 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1);
399 if (ret < 0) {
400 IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
401 return ret;
402 }
403
404 target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE;
405 target_cmd.addr = cpu_to_le32(addr3);
406 target_cmd.op1_sz = cpu_to_le32(sizeof(u32));
407 target_cmd.op2 = 0;
408
409 ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3);
410 if (ret < 0) {
411 IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n");
412 return ret;
413 }
414 }
415
416 return 0;
417}
418
419void iwm_init_default_profile(struct iwm_priv *iwm,
420 struct iwm_umac_profile *profile)
421{
422 memset(profile, 0, sizeof(struct iwm_umac_profile));
423
424 profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
425 profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
426 profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE;
427 profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE;
428
429 if (iwm->conf.enable_qos)
430 profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED);
431
432 profile->wireless_mode = iwm->conf.wireless_mode;
433 profile->mode = cpu_to_le32(iwm->conf.mode);
434
435 profile->ibss.atim = 0;
436 profile->ibss.beacon_interval = 100;
437 profile->ibss.join_only = 0;
438 profile->ibss.band = iwm->conf.ibss_band;
439 profile->ibss.channel = iwm->conf.ibss_channel;
440}
441
442void iwm_link_on(struct iwm_priv *iwm)
443{
444 netif_carrier_on(iwm_to_ndev(iwm));
445 netif_tx_wake_all_queues(iwm_to_ndev(iwm));
446
447 iwm_send_umac_stats_req(iwm, 0);
448}
449
450void iwm_link_off(struct iwm_priv *iwm)
451{
452 struct iw_statistics *wstats = &iwm->wstats;
453 int i;
454
455 netif_tx_stop_all_queues(iwm_to_ndev(iwm));
456 netif_carrier_off(iwm_to_ndev(iwm));
457
458 for (i = 0; i < IWM_TX_QUEUES; i++) {
459 skb_queue_purge(&iwm->txq[i].queue);
460
461 iwm->txq[i].concat_count = 0;
462 iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf;
463
464 flush_workqueue(iwm->txq[i].wq);
465 }
466
467 iwm_rx_free(iwm);
468
469 cancel_delayed_work(&iwm->stats_request);
470 memset(wstats, 0, sizeof(struct iw_statistics));
471 wstats->qual.updated = IW_QUAL_ALL_INVALID;
472
473 del_timer_sync(&iwm->watchdog);
474}
475
476static void iwm_bss_list_clean(struct iwm_priv *iwm)
477{
478 struct iwm_bss_info *bss, *next;
479
480 list_for_each_entry_safe(bss, next, &iwm->bss_list, node) {
481 list_del(&bss->node);
482 kfree(bss->bss);
483 kfree(bss);
484 }
485}
486
487static int iwm_channels_init(struct iwm_priv *iwm)
488{
489 int ret;
490
491#ifdef CONFIG_IWM_B0_HW_SUPPORT
492 if (iwm->conf.hw_b0) {
493 IWM_INFO(iwm, "Workaround EEPROM channels for B0 hardware\n");
494 return 0;
495 }
496#endif
497
498 ret = iwm_send_umac_channel_list(iwm);
499 if (ret) {
500 IWM_ERR(iwm, "Send channel list failed\n");
501 return ret;
502 }
503
504 ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST,
505 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
506 if (ret) {
507 IWM_ERR(iwm, "Didn't get a channel list notification\n");
508 return ret;
509 }
510
511 return 0;
512}
513
514int iwm_up(struct iwm_priv *iwm)
515{
516 int ret;
517 struct iwm_notif *notif_reboot, *notif_ack = NULL;
518
519 ret = iwm_bus_enable(iwm);
520 if (ret) {
521 IWM_ERR(iwm, "Couldn't enable function\n");
522 return ret;
523 }
524
525 iwm_rx_setup_handlers(iwm);
526
527 /* Wait for initial BARKER_REBOOT from hardware */
528 notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION,
529 IWM_SRC_UDMA, 2 * HZ);
530 if (!notif_reboot) {
531 IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n");
532 goto err_disable;
533 }
534
535 /* We send the barker back */
536 ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16);
537 if (ret) {
538 IWM_ERR(iwm, "REBOOT barker response failed\n");
539 kfree(notif_reboot);
540 goto err_disable;
541 }
542
543 kfree(notif_reboot->buf);
544 kfree(notif_reboot);
545
546 /* Wait for ACK_BARKER from hardware */
547 notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION,
548 IWM_SRC_UDMA, 2 * HZ);
549 if (!notif_ack) {
550 IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n");
551 goto err_disable;
552 }
553
554 kfree(notif_ack->buf);
555 kfree(notif_ack);
556
557 /* We start to config static boot parameters */
558 ret = iwm_config_boot_params(iwm);
559 if (ret) {
560 IWM_ERR(iwm, "Config boot parameters failed\n");
561 goto err_disable;
562 }
563
564 ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr);
565 if (ret) {
566 IWM_ERR(iwm, "MAC reading failed\n");
567 goto err_disable;
568 }
569
570 /* We can load the FWs */
571 ret = iwm_load_fw(iwm);
572 if (ret) {
573 IWM_ERR(iwm, "FW loading failed\n");
574 goto err_disable;
575 }
576
577 /* We configure the UMAC and enable the wifi module */
578 ret = iwm_send_umac_config(iwm,
579 cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) |
580 cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) |
581 cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN));
582 if (ret) {
583 IWM_ERR(iwm, "UMAC config failed\n");
584 goto err_fw;
585 }
586
587 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
588 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
589 if (ret) {
590 IWM_ERR(iwm, "Didn't get a wifi core status notification\n");
591 goto err_fw;
592 }
593
594 if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
595 UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
596 IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n",
597 iwm->core_enabled);
598 ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS,
599 IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT);
600 if (ret) {
601 IWM_ERR(iwm, "Didn't get a core status notification\n");
602 goto err_fw;
603 }
604
605 if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN |
606 UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) {
607 IWM_ERR(iwm, "Not all cores enabled: 0x%x\n",
608 iwm->core_enabled);
609 goto err_fw;
610 } else {
611 IWM_INFO(iwm, "All cores enabled\n");
612 }
613 }
614
615 iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile),
616 GFP_KERNEL);
617 if (!iwm->umac_profile) {
618 IWM_ERR(iwm, "Couldn't alloc memory for profile\n");
619 goto err_fw;
620 }
621
622 iwm_init_default_profile(iwm, iwm->umac_profile);
623
624 ret = iwm_channels_init(iwm);
625 if (ret < 0) {
626 IWM_ERR(iwm, "Couldn't init channels\n");
627 goto err_profile;
628 }
629
630 /* Set the READY bit to indicate interface is brought up successfully */
631 set_bit(IWM_STATUS_READY, &iwm->status);
632
633 return 0;
634
635 err_profile:
636 kfree(iwm->umac_profile);
637 iwm->umac_profile = NULL;
638
639 err_fw:
640 iwm_eeprom_exit(iwm);
641
642 err_disable:
643 ret = iwm_bus_disable(iwm);
644 if (ret < 0)
645 IWM_ERR(iwm, "Couldn't disable function\n");
646
647 return -EIO;
648}
649
650int iwm_down(struct iwm_priv *iwm)
651{
652 int ret;
653
654 /* The interface is already down */
655 if (!test_bit(IWM_STATUS_READY, &iwm->status))
656 return 0;
657
658 if (iwm->scan_request) {
659 cfg80211_scan_done(iwm->scan_request, true);
660 iwm->scan_request = NULL;
661 }
662
663 clear_bit(IWM_STATUS_READY, &iwm->status);
664
665 iwm_eeprom_exit(iwm);
666 kfree(iwm->umac_profile);
667 iwm->umac_profile = NULL;
668 iwm_bss_list_clean(iwm);
669
670 iwm->default_key = NULL;
671 iwm->core_enabled = 0;
672
673 ret = iwm_bus_disable(iwm);
674 if (ret < 0) {
675 IWM_ERR(iwm, "Couldn't disable function\n");
676 return ret;
677 }
678
679 return 0;
680}
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c
new file mode 100644
index 000000000000..eec7201e91a8
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/netdev.c
@@ -0,0 +1,172 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24/*
25 * This is the netdev related hooks for iwm.
26 *
27 * Some interesting code paths:
28 *
29 * iwm_open() (Called at netdev interface bringup time)
30 * -> iwm_up() (main.c)
31 * -> iwm_bus_enable()
32 * -> if_sdio_enable() (In case of an SDIO bus)
33 * -> sdio_enable_func()
34 * -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker)
35 * -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker)
36 * -> iwm_load_fw() (fw.c)
37 * -> iwm_load_umac()
38 * -> iwm_load_lmac() (Calibration LMAC)
39 * -> iwm_load_lmac() (Operational LMAC)
40 * -> iwm_send_umac_config()
41 *
42 * iwm_stop() (Called at netdev interface bringdown time)
43 * -> iwm_down()
44 * -> iwm_bus_disable()
45 * -> if_sdio_disable() (In case of an SDIO bus)
46 * -> sdio_disable_func()
47 */
48#include <linux/netdevice.h>
49
50#include "iwm.h"
51#include "cfg80211.h"
52#include "debug.h"
53
54static int iwm_open(struct net_device *ndev)
55{
56 struct iwm_priv *iwm = ndev_to_iwm(ndev);
57 int ret = 0;
58
59 if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
60 ret = iwm_up(iwm);
61
62 return ret;
63}
64
65static int iwm_stop(struct net_device *ndev)
66{
67 struct iwm_priv *iwm = ndev_to_iwm(ndev);
68 int ret = 0;
69
70 if (!test_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
71 ret = iwm_down(iwm);
72
73 return ret;
74}
75
76/*
77 * iwm AC to queue mapping
78 *
79 * AC_VO -> queue 3
80 * AC_VI -> queue 2
81 * AC_BE -> queue 1
82 * AC_BK -> queue 0
83 */
84static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
85
86static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb)
87{
88 skb->priority = cfg80211_classify8021d(skb);
89
90 return iwm_1d_to_queue[skb->priority];
91}
92
93static const struct net_device_ops iwm_netdev_ops = {
94 .ndo_open = iwm_open,
95 .ndo_stop = iwm_stop,
96 .ndo_start_xmit = iwm_xmit_frame,
97 .ndo_select_queue = iwm_select_queue,
98};
99
100void *iwm_if_alloc(int sizeof_bus, struct device *dev,
101 struct iwm_if_ops *if_ops)
102{
103 struct net_device *ndev;
104 struct wireless_dev *wdev;
105 struct iwm_priv *iwm;
106 int ret = 0;
107
108 wdev = iwm_wdev_alloc(sizeof_bus, dev);
109 if (!wdev) {
110 dev_err(dev, "no memory for wireless device instance\n");
111 return ERR_PTR(-ENOMEM);
112 }
113
114 iwm = wdev_to_iwm(wdev);
115 iwm->bus_ops = if_ops;
116 iwm->wdev = wdev;
117 iwm_priv_init(iwm);
118 wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode);
119
120 ndev = alloc_netdev_mq(0, "wlan%d", ether_setup,
121 IWM_TX_QUEUES);
122 if (!ndev) {
123 dev_err(dev, "no memory for network device instance\n");
124 goto out_wdev;
125 }
126
127 ndev->netdev_ops = &iwm_netdev_ops;
128 ndev->wireless_handlers = &iwm_iw_handler_def;
129 ndev->ieee80211_ptr = wdev;
130 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
131 ret = register_netdev(ndev);
132 if (ret < 0) {
133 dev_err(dev, "Failed to register netdev: %d\n", ret);
134 goto out_ndev;
135 }
136
137 wdev->netdev = ndev;
138
139 ret = iwm_rfkill_init(iwm);
140 if (ret) {
141 dev_err(dev, "Failed to init rfkill\n");
142 goto out_rfkill;
143 }
144
145 return iwm;
146
147 out_rfkill:
148 unregister_netdev(ndev);
149
150 out_ndev:
151 free_netdev(ndev);
152
153 out_wdev:
154 iwm_wdev_free(iwm);
155 return ERR_PTR(ret);
156}
157
158void iwm_if_free(struct iwm_priv *iwm)
159{
160 int i;
161
162 if (!iwm_to_ndev(iwm))
163 return;
164
165 iwm_rfkill_exit(iwm);
166 unregister_netdev(iwm_to_ndev(iwm));
167 free_netdev(iwm_to_ndev(iwm));
168 iwm_wdev_free(iwm);
169 destroy_workqueue(iwm->rx_wq);
170 for (i = 0; i < IWM_TX_QUEUES; i++)
171 destroy_workqueue(iwm->txq[i].wq);
172}
diff --git a/drivers/net/wireless/iwmc3200wifi/rfkill.c b/drivers/net/wireless/iwmc3200wifi/rfkill.c
new file mode 100644
index 000000000000..4ca8b495f82d
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/rfkill.c
@@ -0,0 +1,88 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#include <linux/rfkill.h>
25
26#include "iwm.h"
27
28static int iwm_rfkill_soft_toggle(void *data, enum rfkill_state state)
29{
30 struct iwm_priv *iwm = data;
31
32 switch (state) {
33 case RFKILL_STATE_UNBLOCKED:
34 if (test_bit(IWM_RADIO_RFKILL_HW, &iwm->radio))
35 return -EBUSY;
36
37 if (test_and_clear_bit(IWM_RADIO_RFKILL_SW, &iwm->radio) &&
38 (iwm_to_ndev(iwm)->flags & IFF_UP))
39 iwm_up(iwm);
40
41 break;
42 case RFKILL_STATE_SOFT_BLOCKED:
43 if (!test_and_set_bit(IWM_RADIO_RFKILL_SW, &iwm->radio))
44 iwm_down(iwm);
45
46 break;
47 default:
48 break;
49 }
50
51 return 0;
52}
53
54int iwm_rfkill_init(struct iwm_priv *iwm)
55{
56 int ret;
57
58 iwm->rfkill = rfkill_allocate(iwm_to_dev(iwm), RFKILL_TYPE_WLAN);
59 if (!iwm->rfkill) {
60 IWM_ERR(iwm, "Unable to allocate rfkill device\n");
61 return -ENOMEM;
62 }
63
64 iwm->rfkill->name = KBUILD_MODNAME;
65 iwm->rfkill->data = iwm;
66 iwm->rfkill->state = RFKILL_STATE_UNBLOCKED;
67 iwm->rfkill->toggle_radio = iwm_rfkill_soft_toggle;
68
69 ret = rfkill_register(iwm->rfkill);
70 if (ret) {
71 IWM_ERR(iwm, "Failed to register rfkill device\n");
72 goto fail;
73 }
74
75 return 0;
76 fail:
77 rfkill_free(iwm->rfkill);
78 return ret;
79}
80
81void iwm_rfkill_exit(struct iwm_priv *iwm)
82{
83 if (iwm->rfkill)
84 rfkill_unregister(iwm->rfkill);
85
86 rfkill_free(iwm->rfkill);
87 iwm->rfkill = NULL;
88}
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
new file mode 100644
index 000000000000..d73cf96c6dc6
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -0,0 +1,1431 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#include <linux/kernel.h>
40#include <linux/netdevice.h>
41#include <linux/etherdevice.h>
42#include <linux/wireless.h>
43#include <linux/ieee80211.h>
44#include <linux/if_arp.h>
45#include <linux/list.h>
46#include <net/iw_handler.h>
47
48#include "iwm.h"
49#include "debug.h"
50#include "hal.h"
51#include "umac.h"
52#include "lmac.h"
53#include "commands.h"
54#include "rx.h"
55#include "cfg80211.h"
56#include "eeprom.h"
57
58static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr)
59{
60 if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) ||
61 (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL))
62 return -EINVAL;
63
64 return 0;
65}
66
67static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr)
68{
69 return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr),
70 16);
71}
72
73/*
74 * Notification handlers:
75 *
76 * For every possible notification we can receive from the
77 * target, we have a handler.
78 * When we get a target notification, and there is no one
79 * waiting for it, it's just processed through the rx code
80 * path:
81 *
82 * iwm_rx_handle()
83 * -> iwm_rx_handle_umac()
84 * -> iwm_rx_handle_wifi()
85 * -> iwm_rx_handle_resp()
86 * -> iwm_ntf_*()
87 *
88 * OR
89 *
90 * -> iwm_rx_handle_non_wifi()
91 *
92 * If there are processes waiting for this notification, then
93 * iwm_rx_handle_wifi() just wakes those processes up and they
94 * grab the pending notification.
95 */
96static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf,
97 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
98{
99 struct iwm_umac_notif_error *error;
100 struct iwm_fw_error_hdr *fw_err;
101
102 error = (struct iwm_umac_notif_error *)buf;
103 fw_err = &error->err;
104
105
106 IWM_ERR(iwm, "%cMAC FW ERROR:\n",
107 (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U');
108 IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category));
109 IWM_ERR(iwm, "\tStatus: 0x%x\n", le32_to_cpu(fw_err->status));
110 IWM_ERR(iwm, "\tPC: 0x%x\n", le32_to_cpu(fw_err->pc));
111 IWM_ERR(iwm, "\tblink1: %d\n", le32_to_cpu(fw_err->blink1));
112 IWM_ERR(iwm, "\tblink2: %d\n", le32_to_cpu(fw_err->blink2));
113 IWM_ERR(iwm, "\tilink1: %d\n", le32_to_cpu(fw_err->ilink1));
114 IWM_ERR(iwm, "\tilink2: %d\n", le32_to_cpu(fw_err->ilink2));
115 IWM_ERR(iwm, "\tData1: 0x%x\n", le32_to_cpu(fw_err->data1));
116 IWM_ERR(iwm, "\tData2: 0x%x\n", le32_to_cpu(fw_err->data2));
117 IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num));
118 IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status));
119 IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status));
120 IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status));
121
122 return 0;
123}
124
125static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf,
126 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
127{
128 struct iwm_umac_notif_alive *alive_resp =
129 (struct iwm_umac_notif_alive *)(buf);
130 u16 status = le16_to_cpu(alive_resp->status);
131
132 if (status == UMAC_NTFY_ALIVE_STATUS_ERR) {
133 IWM_ERR(iwm, "Receive error UMAC_ALIVE\n");
134 return -EIO;
135 }
136
137 iwm_tx_credit_init_pools(iwm, alive_resp);
138
139 return 0;
140}
141
142static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf,
143 unsigned long buf_size,
144 struct iwm_wifi_cmd *cmd)
145{
146 struct iwm_umac_notif_init_complete *init_complete =
147 (struct iwm_umac_notif_init_complete *)(buf);
148 u16 status = le16_to_cpu(init_complete->status);
149
150 if (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR) {
151 IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n");
152 set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
153 } else {
154 IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n");
155 clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
156 }
157
158 return 0;
159}
160
161static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf,
162 unsigned long buf_size,
163 struct iwm_wifi_cmd *cmd)
164{
165 int pool_nr, total_freed_pages;
166 unsigned long pool_map;
167 int i, id;
168 struct iwm_umac_notif_page_dealloc *dealloc =
169 (struct iwm_umac_notif_page_dealloc *)buf;
170
171 pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT);
172 pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK);
173
174 IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, "
175 "update map 0x%lx\n", pool_nr, pool_map);
176
177 spin_lock(&iwm->tx_credit.lock);
178
179 for (i = 0; i < pool_nr; i++) {
180 id = GET_VAL32(dealloc->grp_info[i],
181 UMAC_DEALLOC_NTFY_GROUP_NUM);
182 if (test_bit(id, &pool_map)) {
183 total_freed_pages = GET_VAL32(dealloc->grp_info[i],
184 UMAC_DEALLOC_NTFY_PAGE_CNT);
185 iwm_tx_credit_inc(iwm, id, total_freed_pages);
186 }
187 }
188
189 spin_unlock(&iwm->tx_credit.lock);
190
191 return 0;
192}
193
194static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf,
195 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
196{
197 IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n");
198
199 return 0;
200}
201
202static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf,
203 unsigned long buf_size,
204 struct iwm_wifi_cmd *cmd)
205{
206 IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]);
207
208 return 0;
209}
210
211static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf,
212 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
213{
214 struct iwm_lmac_tx_resp *tx_resp;
215 struct iwm_umac_wifi_in_hdr *hdr;
216
217 tx_resp = (struct iwm_lmac_tx_resp *)
218 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
219 hdr = (struct iwm_umac_wifi_in_hdr *)buf;
220
221 IWM_DBG_NTF(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size);
222
223 IWM_DBG_NTF(iwm, DBG, "Seqnum: %d\n",
224 le16_to_cpu(hdr->sw_hdr.cmd.seq_num));
225 IWM_DBG_NTF(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt);
226 IWM_DBG_NTF(iwm, DBG, "\tRetry cnt: %d\n",
227 le16_to_cpu(tx_resp->retry_cnt));
228 IWM_DBG_NTF(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl));
229 IWM_DBG_NTF(iwm, DBG, "\tByte cnt: %d\n",
230 le16_to_cpu(tx_resp->byte_cnt));
231 IWM_DBG_NTF(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status));
232
233 return 0;
234}
235
236
237static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf,
238 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
239{
240 u8 opcode;
241 u8 *calib_buf;
242 struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *)
243 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
244
245 opcode = hdr->opcode;
246
247 BUG_ON(opcode >= CALIBRATION_CMD_NUM ||
248 opcode < PHY_CALIBRATE_OPCODES_NUM);
249
250 IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n",
251 opcode);
252
253 buf_size -= sizeof(struct iwm_umac_wifi_in_hdr);
254 calib_buf = iwm->calib_res[opcode].buf;
255
256 if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) {
257 kfree(calib_buf);
258 calib_buf = kzalloc(buf_size, GFP_KERNEL);
259 if (!calib_buf) {
260 IWM_ERR(iwm, "Memory allocation failed: calib_res\n");
261 return -ENOMEM;
262 }
263 iwm->calib_res[opcode].buf = calib_buf;
264 iwm->calib_res[opcode].size = buf_size;
265 }
266
267 memcpy(calib_buf, hdr, buf_size);
268 set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map);
269
270 return 0;
271}
272
273static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf,
274 unsigned long buf_size,
275 struct iwm_wifi_cmd *cmd)
276{
277 IWM_DBG_NTF(iwm, DBG, "Calibration completed\n");
278
279 return 0;
280}
281
282static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf,
283 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
284{
285 struct iwm_lmac_cal_cfg_resp *cal_resp;
286
287 cal_resp = (struct iwm_lmac_cal_cfg_resp *)
288 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
289
290 IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n",
291 le32_to_cpu(cal_resp->status));
292
293 return 0;
294}
295
296static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf,
297 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
298{
299 struct iwm_umac_notif_wifi_status *status =
300 (struct iwm_umac_notif_wifi_status *)buf;
301
302 iwm->core_enabled |= le16_to_cpu(status->status);
303
304 return 0;
305}
306
307static struct iwm_rx_ticket_node *
308iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket)
309{
310 struct iwm_rx_ticket_node *ticket_node;
311
312 ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL);
313 if (!ticket_node) {
314 IWM_ERR(iwm, "Couldn't allocate ticket node\n");
315 return ERR_PTR(-ENOMEM);
316 }
317
318 ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL);
319 if (!ticket_node->ticket) {
320 IWM_ERR(iwm, "Couldn't allocate RX ticket\n");
321 kfree(ticket_node);
322 return ERR_PTR(-ENOMEM);
323 }
324
325 memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket));
326 INIT_LIST_HEAD(&ticket_node->node);
327
328 return ticket_node;
329}
330
331static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node)
332{
333 kfree(ticket_node->ticket);
334 kfree(ticket_node);
335}
336
337static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id)
338{
339 u8 id_hash = IWM_RX_ID_GET_HASH(id);
340 struct list_head *packet_list;
341 struct iwm_rx_packet *packet, *next;
342
343 packet_list = &iwm->rx_packets[id_hash];
344
345 list_for_each_entry_safe(packet, next, packet_list, node)
346 if (packet->id == id)
347 return packet;
348
349 return NULL;
350}
351
352static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf,
353 u32 size, u16 id)
354{
355 struct iwm_rx_packet *packet;
356
357 packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL);
358 if (!packet) {
359 IWM_ERR(iwm, "Couldn't allocate packet\n");
360 return ERR_PTR(-ENOMEM);
361 }
362
363 packet->skb = dev_alloc_skb(size);
364 if (!packet->skb) {
365 IWM_ERR(iwm, "Couldn't allocate packet SKB\n");
366 kfree(packet);
367 return ERR_PTR(-ENOMEM);
368 }
369
370 packet->pkt_size = size;
371
372 skb_put(packet->skb, size);
373 memcpy(packet->skb->data, buf, size);
374 INIT_LIST_HEAD(&packet->node);
375 packet->id = id;
376
377 return packet;
378}
379
380void iwm_rx_free(struct iwm_priv *iwm)
381{
382 struct iwm_rx_ticket_node *ticket, *nt;
383 struct iwm_rx_packet *packet, *np;
384 int i;
385
386 list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) {
387 list_del(&ticket->node);
388 iwm_rx_ticket_node_free(ticket);
389 }
390
391 for (i = 0; i < IWM_RX_ID_HASH; i++) {
392 list_for_each_entry_safe(packet, np, &iwm->rx_packets[i],
393 node) {
394 list_del(&packet->node);
395 kfree_skb(packet->skb);
396 kfree(packet);
397 }
398 }
399}
400
401static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf,
402 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
403{
404 struct iwm_umac_notif_rx_ticket *ntf_rx_ticket =
405 (struct iwm_umac_notif_rx_ticket *)buf;
406 struct iwm_rx_ticket *ticket =
407 (struct iwm_rx_ticket *)ntf_rx_ticket->tickets;
408 int i, schedule_rx = 0;
409
410 for (i = 0; i < ntf_rx_ticket->num_tickets; i++) {
411 struct iwm_rx_ticket_node *ticket_node;
412
413 switch (le16_to_cpu(ticket->action)) {
414 case IWM_RX_TICKET_RELEASE:
415 case IWM_RX_TICKET_DROP:
416 /* We can push the packet to the stack */
417 ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket);
418 if (IS_ERR(ticket_node))
419 return PTR_ERR(ticket_node);
420
421 IWM_DBG_NTF(iwm, DBG, "TICKET RELEASE(%d)\n",
422 ticket->id);
423 list_add_tail(&ticket_node->node, &iwm->rx_tickets);
424
425 /*
426 * We received an Rx ticket, most likely there's
427 * a packet pending for it, it's not worth going
428 * through the packet hash list to double check.
429 * Let's just fire the rx worker..
430 */
431 schedule_rx = 1;
432
433 break;
434
435 default:
436 IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n",
437 ticket->action);
438 }
439
440 ticket++;
441 }
442
443 if (schedule_rx)
444 queue_work(iwm->rx_wq, &iwm->rx_worker);
445
446 return 0;
447}
448
449static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf,
450 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
451{
452 struct iwm_umac_wifi_in_hdr *wifi_hdr;
453 struct iwm_rx_packet *packet;
454 u16 id, buf_offset;
455 u32 packet_size;
456
457 IWM_DBG_NTF(iwm, DBG, "\n");
458
459 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
460 id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
461 buf_offset = sizeof(struct iwm_umac_wifi_in_hdr);
462 packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr);
463
464 IWM_DBG_NTF(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n",
465 wifi_hdr->sw_hdr.cmd.cmd, id, packet_size);
466 IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id);
467 IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size);
468
469 packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id);
470 if (IS_ERR(packet))
471 return PTR_ERR(packet);
472
473 list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]);
474
475 /* We might (unlikely) have received the packet _after_ the ticket */
476 queue_work(iwm->rx_wq, &iwm->rx_worker);
477
478 return 0;
479}
480
481/* MLME handlers */
482static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf,
483 unsigned long buf_size,
484 struct iwm_wifi_cmd *cmd)
485{
486 struct iwm_umac_notif_assoc_start *start;
487
488 start = (struct iwm_umac_notif_assoc_start *)buf;
489
490 set_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
491
492 IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n",
493 start->bssid, le32_to_cpu(start->roam_reason));
494
495 wake_up_interruptible(&iwm->mlme_queue);
496
497 return 0;
498}
499
500static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf,
501 unsigned long buf_size,
502 struct iwm_wifi_cmd *cmd)
503{
504 struct iwm_umac_notif_assoc_complete *complete =
505 (struct iwm_umac_notif_assoc_complete *)buf;
506 union iwreq_data wrqu;
507
508 IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n",
509 complete->bssid, complete->status);
510
511 memset(&wrqu, 0, sizeof(wrqu));
512
513 clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
514
515 switch (le32_to_cpu(complete->status)) {
516 case UMAC_ASSOC_COMPLETE_SUCCESS:
517 set_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
518 memcpy(iwm->bssid, complete->bssid, ETH_ALEN);
519 iwm->channel = complete->channel;
520
521 iwm_link_on(iwm);
522
523 memcpy(wrqu.ap_addr.sa_data, complete->bssid, ETH_ALEN);
524 break;
525 case UMAC_ASSOC_COMPLETE_FAILURE:
526 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
527 memset(iwm->bssid, 0, ETH_ALEN);
528 iwm->channel = 0;
529
530 iwm_link_off(iwm);
531 default:
532 break;
533 }
534
535 if (iwm->conf.mode == UMAC_MODE_IBSS) {
536 cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL);
537 return 0;
538 }
539
540 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
541 wireless_send_event(iwm_to_ndev(iwm), SIOCGIWAP, &wrqu, NULL);
542
543 return 0;
544}
545
546static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf,
547 unsigned long buf_size,
548 struct iwm_wifi_cmd *cmd)
549{
550 struct iwm_umac_notif_profile_invalidate *invalid;
551
552 invalid = (struct iwm_umac_notif_profile_invalidate *)buf;
553
554 IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n",
555 le32_to_cpu(invalid->reason));
556
557 clear_bit(IWM_STATUS_ASSOCIATING, &iwm->status);
558 clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status);
559
560 iwm->umac_profile_active = 0;
561 memset(iwm->bssid, 0, ETH_ALEN);
562 iwm->channel = 0;
563
564 iwm_link_off(iwm);
565
566 wake_up_interruptible(&iwm->mlme_queue);
567
568 return 0;
569}
570
571static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf,
572 unsigned long buf_size,
573 struct iwm_wifi_cmd *cmd)
574{
575 int ret;
576 struct iwm_umac_notif_scan_complete *scan_complete =
577 (struct iwm_umac_notif_scan_complete *)buf;
578 u32 result = le32_to_cpu(scan_complete->result);
579
580 IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n",
581 le32_to_cpu(scan_complete->type),
582 le32_to_cpu(scan_complete->result),
583 scan_complete->seq_num);
584
585 if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) {
586 IWM_ERR(iwm, "Scan complete while device not scanning\n");
587 return -EIO;
588 }
589 if (!iwm->scan_request)
590 return 0;
591
592 ret = iwm_cfg80211_inform_bss(iwm);
593
594 cfg80211_scan_done(iwm->scan_request,
595 (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret);
596 iwm->scan_request = NULL;
597
598 return ret;
599}
600
601static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf,
602 unsigned long buf_size,
603 struct iwm_wifi_cmd *cmd)
604{
605 struct iwm_umac_notif_sta_info *umac_sta =
606 (struct iwm_umac_notif_sta_info *)buf;
607 struct iwm_sta_info *sta;
608 int i;
609
610 switch (le32_to_cpu(umac_sta->opcode)) {
611 case UMAC_OPCODE_ADD_MODIFY:
612 sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
613
614 IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, "
615 "addr = %pM, qos = %d\n",
616 sta->valid ? "Modify" : "Add",
617 GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
618 GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
619 umac_sta->mac_addr,
620 umac_sta->flags & UMAC_STA_FLAG_QOS);
621
622 sta->valid = 1;
623 sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS;
624 sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR);
625 memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN);
626 break;
627 case UMAC_OPCODE_REMOVE:
628 IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, "
629 "addr = %pM\n",
630 GET_VAL8(umac_sta->sta_id, LMAC_STA_ID),
631 GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR),
632 umac_sta->mac_addr);
633
634 sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)];
635
636 if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN))
637 sta->valid = 0;
638
639 break;
640 case UMAC_OPCODE_CLEAR_ALL:
641 for (i = 0; i < IWM_STA_TABLE_NUM; i++)
642 iwm->sta_table[i].valid = 0;
643
644 break;
645 default:
646 break;
647 }
648
649 return 0;
650}
651
652static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf,
653 unsigned long buf_size,
654 struct iwm_wifi_cmd *cmd)
655{
656 struct wiphy *wiphy = iwm_to_wiphy(iwm);
657 struct ieee80211_mgmt *mgmt;
658 struct iwm_umac_notif_bss_info *umac_bss =
659 (struct iwm_umac_notif_bss_info *)buf;
660 struct ieee80211_channel *channel;
661 struct ieee80211_supported_band *band;
662 struct iwm_bss_info *bss, *next;
663 s32 signal;
664 int freq;
665 u16 frame_len = le16_to_cpu(umac_bss->frame_len);
666 size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len;
667
668 mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf);
669
670 IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid);
671 IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type));
672 IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n",
673 le32_to_cpu(umac_bss->timestamp));
674 IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n",
675 le16_to_cpu(umac_bss->table_idx));
676 IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band);
677 IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel);
678 IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi);
679 IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len);
680
681 list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
682 if (bss->bss->table_idx == umac_bss->table_idx)
683 break;
684
685 if (&bss->node != &iwm->bss_list) {
686 /* Remove the old BSS entry, we will add it back later. */
687 list_del(&bss->node);
688 kfree(bss->bss);
689 } else {
690 /* New BSS entry */
691
692 bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL);
693 if (!bss) {
694 IWM_ERR(iwm, "Couldn't allocate bss_info\n");
695 return -ENOMEM;
696 }
697 }
698
699 bss->bss = kzalloc(bss_len, GFP_KERNEL);
700 if (!bss) {
701 kfree(bss);
702 IWM_ERR(iwm, "Couldn't allocate bss\n");
703 return -ENOMEM;
704 }
705
706 INIT_LIST_HEAD(&bss->node);
707 memcpy(bss->bss, umac_bss, bss_len);
708
709 if (umac_bss->band == UMAC_BAND_2GHZ)
710 band = wiphy->bands[IEEE80211_BAND_2GHZ];
711 else if (umac_bss->band == UMAC_BAND_5GHZ)
712 band = wiphy->bands[IEEE80211_BAND_5GHZ];
713 else {
714 IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band);
715 goto err;
716 }
717
718 freq = ieee80211_channel_to_frequency(umac_bss->channel);
719 channel = ieee80211_get_channel(wiphy, freq);
720 signal = umac_bss->rssi * 100;
721
722 bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel,
723 mgmt, frame_len,
724 signal, GFP_KERNEL);
725 if (!bss->cfg_bss)
726 goto err;
727
728 list_add_tail(&bss->node, &iwm->bss_list);
729
730 return 0;
731 err:
732 kfree(bss->bss);
733 kfree(bss);
734
735 return -EINVAL;
736}
737
738static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf,
739 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
740{
741 struct iwm_umac_notif_bss_removed *bss_rm =
742 (struct iwm_umac_notif_bss_removed *)buf;
743 struct iwm_bss_info *bss, *next;
744 u16 table_idx;
745 int i;
746
747 for (i = 0; i < le32_to_cpu(bss_rm->count); i++) {
748 table_idx = (le16_to_cpu(bss_rm->entries[i])
749 & IWM_BSS_REMOVE_INDEX_MSK);
750 list_for_each_entry_safe(bss, next, &iwm->bss_list, node)
751 if (bss->bss->table_idx == cpu_to_le16(table_idx)) {
752 struct ieee80211_mgmt *mgmt;
753
754 mgmt = (struct ieee80211_mgmt *)
755 (bss->bss->frame_buf);
756 IWM_DBG_MLME(iwm, ERR,
757 "BSS removed: %pM\n",
758 mgmt->bssid);
759 list_del(&bss->node);
760 kfree(bss->bss);
761 kfree(bss);
762 }
763 }
764
765 return 0;
766}
767
768static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf,
769 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
770{
771 struct iwm_umac_notif_mgt_frame *mgt_frame =
772 (struct iwm_umac_notif_mgt_frame *)buf;
773 struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame;
774 u8 *ie;
775 unsigned int event;
776 union iwreq_data wrqu;
777
778 IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame,
779 le16_to_cpu(mgt_frame->len));
780
781 if (ieee80211_is_assoc_req(mgt->frame_control)) {
782 ie = mgt->u.assoc_req.variable;;
783 event = IWEVASSOCREQIE;
784 } else if (ieee80211_is_reassoc_req(mgt->frame_control)) {
785 ie = mgt->u.reassoc_req.variable;;
786 event = IWEVASSOCREQIE;
787 } else if (ieee80211_is_assoc_resp(mgt->frame_control)) {
788 ie = mgt->u.assoc_resp.variable;;
789 event = IWEVASSOCRESPIE;
790 } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) {
791 ie = mgt->u.reassoc_resp.variable;;
792 event = IWEVASSOCRESPIE;
793 } else {
794 IWM_ERR(iwm, "Unsupported management frame");
795 return 0;
796 }
797
798 wrqu.data.length = le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt);
799
800 IWM_HEXDUMP(iwm, DBG, MLME, "EVT: ", ie, wrqu.data.length);
801 wireless_send_event(iwm_to_ndev(iwm), event, &wrqu, ie);
802
803 return 0;
804}
805
806static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf,
807 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
808{
809 struct iwm_umac_notif_wifi_if *notif =
810 (struct iwm_umac_notif_wifi_if *)buf;
811
812 switch (notif->status) {
813 case WIFI_IF_NTFY_ASSOC_START:
814 return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd);
815 case WIFI_IF_NTFY_ASSOC_COMPLETE:
816 return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd);
817 case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE:
818 return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd);
819 case WIFI_IF_NTFY_CONNECTION_TERMINATED:
820 IWM_DBG_MLME(iwm, DBG, "Connection terminated\n");
821 break;
822 case WIFI_IF_NTFY_SCAN_COMPLETE:
823 return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd);
824 case WIFI_IF_NTFY_STA_TABLE_CHANGE:
825 return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd);
826 case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED:
827 IWM_DBG_MLME(iwm, DBG, "Extended IE required\n");
828 break;
829 case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED:
830 return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd);
831 case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED:
832 return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd);
833 break;
834 case WIFI_IF_NTFY_MGMT_FRAME:
835 return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd);
836 case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START:
837 case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE:
838 case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START:
839 case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT:
840 case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START:
841 case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE:
842 case WIFI_DBG_IF_NTFY_CNCT_ATC_START:
843 case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION:
844 case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP:
845 case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP:
846 IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n",
847 notif->status);
848 break;
849 default:
850 IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status);
851 break;
852 }
853
854 return 0;
855}
856
857#define IWM_STATS_UPDATE_INTERVAL (2 * HZ)
858
859static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf,
860 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
861{
862 struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf;
863 struct iw_statistics *wstats = &iwm->wstats;
864 u16 max_rate = 0;
865 int i;
866
867 IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n");
868
869 if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
870 for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) {
871 max_rate = max_t(u16, max_rate,
872 max(le16_to_cpu(stats->tx_rate[i]),
873 le16_to_cpu(stats->rx_rate[i])));
874 }
875 /* UMAC passes rate info multiplies by 2 */
876 iwm->rate = max_rate >> 1;
877 }
878
879 wstats->status = 0;
880
881 wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid);
882 wstats->discard.code = le32_to_cpu(stats->rx_drop_decode);
883 wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly);
884 wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry);
885
886 wstats->miss.beacon = le32_to_cpu(stats->missed_beacons);
887
888 /* according to cfg80211 */
889 if (stats->rssi_dbm < -110)
890 wstats->qual.qual = 0;
891 else if (stats->rssi_dbm > -40)
892 wstats->qual.qual = 70;
893 else
894 wstats->qual.qual = stats->rssi_dbm + 110;
895
896 wstats->qual.level = stats->rssi_dbm;
897 wstats->qual.noise = stats->noise_dbm;
898 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
899
900 schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL);
901
902 mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD));
903
904 return 0;
905}
906
907static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf,
908 unsigned long buf_size,
909 struct iwm_wifi_cmd *cmd)
910{
911 struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy =
912 (struct iwm_umac_cmd_eeprom_proxy *)
913 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
914 struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr;
915 u32 hdr_offset = le32_to_cpu(hdr->offset);
916 u32 hdr_len = le32_to_cpu(hdr->len);
917 u32 hdr_type = le32_to_cpu(hdr->type);
918
919 IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n",
920 hdr_type, hdr_len, hdr_offset);
921
922 if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN)
923 return -EINVAL;
924
925#ifdef CONFIG_IWM_B0_HW_SUPPORT
926 if (hdr_offset == IWM_EEPROM_SKU_CAP_OFF) {
927 if (eeprom_proxy->buf[0] == 0xff)
928 iwm->conf.hw_b0 = 1;
929 }
930#endif
931
932 switch (hdr_type) {
933 case IWM_UMAC_CMD_EEPROM_TYPE_READ:
934 memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len);
935 break;
936 case IWM_UMAC_CMD_EEPROM_TYPE_WRITE:
937 default:
938 return -ENOTSUPP;
939 }
940
941 return 0;
942}
943
944static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
945 unsigned long buf_size,
946 struct iwm_wifi_cmd *cmd)
947{
948 struct iwm_umac_cmd_get_channel_list *ch_list =
949 (struct iwm_umac_cmd_get_channel_list *)
950 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
951 struct wiphy *wiphy = iwm_to_wiphy(iwm);
952 struct ieee80211_supported_band *band;
953 int i;
954
955 band = wiphy->bands[IEEE80211_BAND_2GHZ];
956
957 for (i = 0; i < band->n_channels; i++) {
958 unsigned long ch_mask_0 =
959 le32_to_cpu(ch_list->ch[0].channels_mask);
960 unsigned long ch_mask_2 =
961 le32_to_cpu(ch_list->ch[2].channels_mask);
962
963 if (!test_bit(i, &ch_mask_0))
964 band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
965
966 if (!test_bit(i, &ch_mask_2))
967 band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
968 }
969
970 band = wiphy->bands[IEEE80211_BAND_5GHZ];
971
972 for (i = 0; i < min(band->n_channels, 32); i++) {
973 unsigned long ch_mask_1 =
974 le32_to_cpu(ch_list->ch[1].channels_mask);
975 unsigned long ch_mask_3 =
976 le32_to_cpu(ch_list->ch[3].channels_mask);
977
978 if (!test_bit(i, &ch_mask_1))
979 band->channels[i].flags |= IEEE80211_CHAN_DISABLED;
980
981 if (!test_bit(i, &ch_mask_3))
982 band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS;
983 }
984
985 return 0;
986}
987
988static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
989 unsigned long buf_size,
990 struct iwm_wifi_cmd *cmd)
991{
992 struct iwm_umac_wifi_if *hdr =
993 (struct iwm_umac_wifi_if *)cmd->buf.payload;
994
995 IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: "
996 "oid is %d\n", hdr->oid);
997
998 switch (hdr->oid) {
999 case UMAC_WIFI_IF_CMD_SET_PROFILE:
1000 iwm->umac_profile_active = 1;
1001 wake_up_interruptible(&iwm->mlme_queue);
1002 break;
1003 default:
1004 break;
1005 }
1006
1007 return 0;
1008}
1009
1010static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf,
1011 unsigned long buf_size, struct iwm_wifi_cmd *cmd)
1012{
1013 struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *)
1014 (buf + sizeof(struct iwm_umac_wifi_in_hdr));
1015 u32 flags = le32_to_cpu(state->flags);
1016
1017 IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n",
1018 flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF",
1019 flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF");
1020
1021 if (flags & IWM_CARD_STATE_HW_DISABLED)
1022 set_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
1023 else
1024 clear_bit(IWM_RADIO_RFKILL_HW, &iwm->radio);
1025
1026 return 0;
1027}
1028
1029static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf,
1030 unsigned long buf_size)
1031{
1032 struct iwm_umac_wifi_in_hdr *wifi_hdr;
1033 struct iwm_wifi_cmd *cmd;
1034 u8 source, cmd_id;
1035 u16 seq_num;
1036 u32 count;
1037 u8 resp;
1038
1039 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1040 cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1041
1042 source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1043 if (source >= IWM_SRC_NUM) {
1044 IWM_CRIT(iwm, "invalid source %d\n", source);
1045 return -EINVAL;
1046 }
1047
1048 count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT));
1049 count += sizeof(struct iwm_umac_wifi_in_hdr) -
1050 sizeof(struct iwm_dev_cmd_hdr);
1051 if (count > buf_size) {
1052 IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size);
1053 return -EINVAL;
1054 }
1055
1056 resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS);
1057
1058 seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num);
1059
1060 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n",
1061 cmd_id, source, seq_num);
1062
1063 /*
1064 * If this is a response to a previously sent command, there must
1065 * be a pending command for this sequence number.
1066 */
1067 cmd = iwm_get_pending_wifi_cmd(iwm, seq_num);
1068
1069 /* Notify the caller only for sync commands. */
1070 switch (source) {
1071 case UMAC_HDI_IN_SOURCE_FHRX:
1072 if (iwm->lmac_handlers[cmd_id] &&
1073 test_bit(cmd_id, &iwm->lmac_handler_map[0]))
1074 return iwm_notif_send(iwm, cmd, cmd_id, source,
1075 buf, count);
1076 break;
1077 case UMAC_HDI_IN_SOURCE_FW:
1078 if (iwm->umac_handlers[cmd_id] &&
1079 test_bit(cmd_id, &iwm->umac_handler_map[0]))
1080 return iwm_notif_send(iwm, cmd, cmd_id, source,
1081 buf, count);
1082 break;
1083 case UMAC_HDI_IN_SOURCE_UDMA:
1084 break;
1085 }
1086
1087 return iwm_rx_handle_resp(iwm, buf, count, cmd);
1088}
1089
1090int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size,
1091 struct iwm_wifi_cmd *cmd)
1092{
1093 u8 source, cmd_id;
1094 struct iwm_umac_wifi_in_hdr *wifi_hdr;
1095 int ret = 0;
1096
1097 wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf;
1098 cmd_id = wifi_hdr->sw_hdr.cmd.cmd;
1099
1100 source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE);
1101
1102 IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source);
1103
1104 switch (source) {
1105 case UMAC_HDI_IN_SOURCE_FHRX:
1106 if (iwm->lmac_handlers[cmd_id])
1107 ret = iwm->lmac_handlers[cmd_id]
1108 (iwm, buf, buf_size, cmd);
1109 break;
1110 case UMAC_HDI_IN_SOURCE_FW:
1111 if (iwm->umac_handlers[cmd_id])
1112 ret = iwm->umac_handlers[cmd_id]
1113 (iwm, buf, buf_size, cmd);
1114 break;
1115 case UMAC_HDI_IN_SOURCE_UDMA:
1116 ret = -EINVAL;
1117 break;
1118 }
1119
1120 kfree(cmd);
1121
1122 return ret;
1123}
1124
1125static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf,
1126 unsigned long buf_size)
1127{
1128 u8 seq_num;
1129 struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf;
1130 struct iwm_nonwifi_cmd *cmd, *next;
1131
1132 seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM);
1133
1134 /*
1135 * We received a non wifi answer.
1136 * Let's check if there's a pending command for it, and if so
1137 * replace the command payload with the buffer, and then wake the
1138 * callers up.
1139 * That means we only support synchronised non wifi command response
1140 * schemes.
1141 */
1142 list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending)
1143 if (cmd->seq_num == seq_num) {
1144 cmd->resp_received = 1;
1145 cmd->buf.len = buf_size;
1146 memcpy(cmd->buf.hdr, buf, buf_size);
1147 wake_up_interruptible(&iwm->nonwifi_queue);
1148 }
1149
1150 return 0;
1151}
1152
1153static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf,
1154 unsigned long buf_size)
1155{
1156 int ret = 0;
1157 u8 op_code;
1158 unsigned long buf_offset = 0;
1159 struct iwm_udma_in_hdr *hdr;
1160
1161 /*
1162 * To allow for a more efficient bus usage, UMAC
1163 * messages are encapsulated into UDMA ones. This
1164 * way we can have several UMAC messages in one bus
1165 * transfer.
1166 * A UDMA frame size is always aligned on 16 bytes,
1167 * and a UDMA frame must not start with a UMAC_PAD_TERMINAL
1168 * word. This is how we parse a bus frame into several
1169 * UDMA ones.
1170 */
1171 while (buf_offset < buf_size) {
1172
1173 hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset);
1174
1175 if (iwm_rx_check_udma_hdr(hdr) < 0) {
1176 IWM_DBG_RX(iwm, DBG, "End of frame\n");
1177 break;
1178 }
1179
1180 op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE);
1181
1182 IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code);
1183
1184 if (op_code == UMAC_HDI_IN_OPCODE_WIFI) {
1185 ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset,
1186 buf_size - buf_offset);
1187 } else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) {
1188 if (GET_VAL32(hdr->cmd,
1189 UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) !=
1190 UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) {
1191 IWM_ERR(iwm, "Incorrect hw signature\n");
1192 return -EINVAL;
1193 }
1194 ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset,
1195 buf_size - buf_offset);
1196 } else {
1197 IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code);
1198 ret |= -EINVAL;
1199 }
1200
1201 buf_offset += iwm_rx_resp_size(hdr);
1202 }
1203
1204 return ret;
1205}
1206
1207int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size)
1208{
1209 struct iwm_udma_in_hdr *hdr;
1210
1211 hdr = (struct iwm_udma_in_hdr *)buf;
1212
1213 switch (le32_to_cpu(hdr->cmd)) {
1214 case UMAC_REBOOT_BARKER:
1215 return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION,
1216 IWM_SRC_UDMA, buf, buf_size);
1217 case UMAC_ACK_BARKER:
1218 return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION,
1219 IWM_SRC_UDMA, NULL, 0);
1220 default:
1221 IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd);
1222 return iwm_rx_handle_umac(iwm, buf, buf_size);
1223 }
1224
1225 return 0;
1226}
1227
1228static const iwm_handler iwm_umac_handlers[] =
1229{
1230 [UMAC_NOTIFY_OPCODE_ERROR] = iwm_ntf_error,
1231 [UMAC_NOTIFY_OPCODE_ALIVE] = iwm_ntf_umac_alive,
1232 [UMAC_NOTIFY_OPCODE_INIT_COMPLETE] = iwm_ntf_init_complete,
1233 [UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS] = iwm_ntf_wifi_status,
1234 [UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_mlme,
1235 [UMAC_NOTIFY_OPCODE_PAGE_DEALLOC] = iwm_ntf_tx_credit_update,
1236 [UMAC_NOTIFY_OPCODE_RX_TICKET] = iwm_ntf_rx_ticket,
1237 [UMAC_CMD_OPCODE_RESET] = iwm_ntf_umac_reset,
1238 [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics,
1239 [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy,
1240 [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list,
1241 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
1242 [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper,
1243};
1244
1245static const iwm_handler iwm_lmac_handlers[] =
1246{
1247 [REPLY_TX] = iwm_ntf_tx,
1248 [REPLY_ALIVE] = iwm_ntf_lmac_version,
1249 [CALIBRATION_RES_NOTIFICATION] = iwm_ntf_calib_res,
1250 [CALIBRATION_COMPLETE_NOTIFICATION] = iwm_ntf_calib_complete,
1251 [CALIBRATION_CFG_CMD] = iwm_ntf_calib_cfg,
1252 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
1253 [CARD_STATE_NOTIFICATION] = iwm_ntf_card_state,
1254};
1255
1256void iwm_rx_setup_handlers(struct iwm_priv *iwm)
1257{
1258 iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers;
1259 iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers;
1260}
1261
1262static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len)
1263{
1264 struct ieee80211_hdr *hdr;
1265 unsigned int hdr_len;
1266
1267 hdr = (struct ieee80211_hdr *)skb->data;
1268
1269 if (!ieee80211_has_protected(hdr->frame_control))
1270 return;
1271
1272 hdr_len = ieee80211_hdrlen(hdr->frame_control);
1273 if (hdr_total_len <= hdr_len)
1274 return;
1275
1276 memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len);
1277 skb_pull(skb, (hdr_total_len - hdr_len));
1278}
1279
1280static void iwm_rx_adjust_packet(struct iwm_priv *iwm,
1281 struct iwm_rx_packet *packet,
1282 struct iwm_rx_ticket_node *ticket_node)
1283{
1284 u32 payload_offset = 0, payload_len;
1285 struct iwm_rx_ticket *ticket = ticket_node->ticket;
1286 struct iwm_rx_mpdu_hdr *mpdu_hdr;
1287 struct ieee80211_hdr *hdr;
1288
1289 mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data;
1290 payload_offset += sizeof(struct iwm_rx_mpdu_hdr);
1291 /* Padding is 0 or 2 bytes */
1292 payload_len = le16_to_cpu(mpdu_hdr->len) +
1293 (le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK);
1294 payload_len -= ticket->tail_len;
1295
1296 IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, "
1297 "ticket offset:%d ticket tail len:%d\n",
1298 payload_len, payload_offset, ticket->payload_offset,
1299 ticket->tail_len);
1300
1301 IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len);
1302
1303 skb_pull(packet->skb, payload_offset);
1304 skb_trim(packet->skb, payload_len);
1305
1306 iwm_remove_iv(packet->skb, ticket->payload_offset);
1307
1308 hdr = (struct ieee80211_hdr *) packet->skb->data;
1309 if (ieee80211_is_data_qos(hdr->frame_control)) {
1310 /* UMAC handed QOS_DATA frame with 2 padding bytes appended
1311 * to the qos_ctl field in IEEE 802.11 headers. */
1312 memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2,
1313 packet->skb->data,
1314 ieee80211_hdrlen(hdr->frame_control) -
1315 IEEE80211_QOS_CTL_LEN);
1316 hdr = (struct ieee80211_hdr *) skb_pull(packet->skb,
1317 IEEE80211_QOS_CTL_LEN + 2);
1318 hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
1319 }
1320
1321 IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ",
1322 packet->skb->data, packet->skb->len);
1323}
1324
1325static void classify8023(struct sk_buff *skb)
1326{
1327 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1328
1329 if (ieee80211_is_data_qos(hdr->frame_control)) {
1330 u8 *qc = ieee80211_get_qos_ctl(hdr);
1331 /* frame has qos control */
1332 skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK;
1333 } else {
1334 skb->priority = 0;
1335 }
1336}
1337
1338static void iwm_rx_process_packet(struct iwm_priv *iwm,
1339 struct iwm_rx_packet *packet,
1340 struct iwm_rx_ticket_node *ticket_node)
1341{
1342 int ret;
1343 struct sk_buff *skb = packet->skb;
1344 struct wireless_dev *wdev = iwm_to_wdev(iwm);
1345 struct net_device *ndev = iwm_to_ndev(iwm);
1346
1347 IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id);
1348
1349 switch (le16_to_cpu(ticket_node->ticket->action)) {
1350 case IWM_RX_TICKET_RELEASE:
1351 IWM_DBG_RX(iwm, DBG, "RELEASE packet\n");
1352 classify8023(skb);
1353 iwm_rx_adjust_packet(iwm, packet, ticket_node);
1354 ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype);
1355 if (ret < 0) {
1356 IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - "
1357 "%d\n", ret);
1358 break;
1359 }
1360
1361 IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len);
1362
1363 skb->dev = iwm_to_ndev(iwm);
1364 skb->protocol = eth_type_trans(skb, ndev);
1365 skb->ip_summed = CHECKSUM_UNNECESSARY;
1366 memset(skb->cb, 0, sizeof(skb->cb));
1367
1368 ndev->stats.rx_packets++;
1369 ndev->stats.rx_bytes += skb->len;
1370
1371 if (netif_rx(skb) == NET_RX_DROP) {
1372 IWM_ERR(iwm, "Packet dropped\n");
1373 ndev->stats.rx_dropped++;
1374 }
1375 break;
1376 case IWM_RX_TICKET_DROP:
1377 IWM_DBG_RX(iwm, DBG, "DROP packet\n");
1378 kfree_skb(packet->skb);
1379 break;
1380 default:
1381 IWM_ERR(iwm, "Unknow ticket action: %d\n",
1382 le16_to_cpu(ticket_node->ticket->action));
1383 kfree_skb(packet->skb);
1384 }
1385
1386 kfree(packet);
1387 iwm_rx_ticket_node_free(ticket_node);
1388}
1389
1390/*
1391 * Rx data processing:
1392 *
1393 * We're receiving Rx packet from the LMAC, and Rx ticket from
1394 * the UMAC.
1395 * To forward a target data packet upstream (i.e. to the
1396 * kernel network stack), we must have received an Rx ticket
1397 * that tells us we're allowed to release this packet (ticket
1398 * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates,
1399 * among other things, where valid data actually starts in the Rx
1400 * packet.
1401 */
1402void iwm_rx_worker(struct work_struct *work)
1403{
1404 struct iwm_priv *iwm;
1405 struct iwm_rx_ticket_node *ticket, *next;
1406
1407 iwm = container_of(work, struct iwm_priv, rx_worker);
1408
1409 /*
1410 * We go through the tickets list and if there is a pending
1411 * packet for it, we push it upstream.
1412 * We stop whenever a ticket is missing its packet, as we're
1413 * supposed to send the packets in order.
1414 */
1415 list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) {
1416 struct iwm_rx_packet *packet =
1417 iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id));
1418
1419 if (!packet) {
1420 IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d "
1421 "to be handled first\n",
1422 le16_to_cpu(ticket->ticket->id));
1423 return;
1424 }
1425
1426 list_del(&ticket->node);
1427 list_del(&packet->node);
1428 iwm_rx_process_packet(iwm, packet, ticket);
1429 }
1430}
1431
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.h b/drivers/net/wireless/iwmc3200wifi/rx.h
new file mode 100644
index 000000000000..da0db91cee59
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/rx.h
@@ -0,0 +1,60 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_RX_H__
40#define __IWM_RX_H__
41
42#include <linux/skbuff.h>
43
44#include "umac.h"
45
46struct iwm_rx_ticket_node {
47 struct list_head node;
48 struct iwm_rx_ticket *ticket;
49};
50
51struct iwm_rx_packet {
52 struct list_head node;
53 u16 id;
54 struct sk_buff *skb;
55 unsigned long pkt_size;
56};
57
58void iwm_rx_worker(struct work_struct *work);
59
60#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c
new file mode 100644
index 000000000000..edc0a0091058
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.c
@@ -0,0 +1,516 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39/*
40 * This is the SDIO bus specific hooks for iwm.
41 * It also is the module's entry point.
42 *
43 * Interesting code paths:
44 * iwm_sdio_probe() (Called by an SDIO bus scan)
45 * -> iwm_if_alloc() (netdev.c)
46 * -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy)
47 * -> wiphy_new()
48 * -> wiphy_register()
49 * -> alloc_netdev_mq()
50 * -> register_netdev()
51 *
52 * iwm_sdio_remove()
53 * -> iwm_if_free() (netdev.c)
54 * -> unregister_netdev()
55 * -> iwm_wdev_free() (cfg80211.c)
56 * -> wiphy_unregister()
57 * -> wiphy_free()
58 *
59 * iwm_sdio_isr() (called in process context from the SDIO core code)
60 * -> queue_work(.., isr_worker)
61 * -- [async] --> iwm_sdio_isr_worker()
62 * -> iwm_rx_handle()
63 */
64
65#include <linux/kernel.h>
66#include <linux/netdevice.h>
67#include <linux/debugfs.h>
68#include <linux/mmc/sdio.h>
69#include <linux/mmc/sdio_func.h>
70
71#include "iwm.h"
72#include "debug.h"
73#include "bus.h"
74#include "sdio.h"
75
76static void iwm_sdio_isr_worker(struct work_struct *work)
77{
78 struct iwm_sdio_priv *hw;
79 struct iwm_priv *iwm;
80 struct iwm_rx_info *rx_info;
81 struct sk_buff *skb;
82 u8 *rx_buf;
83 unsigned long rx_size;
84
85 hw = container_of(work, struct iwm_sdio_priv, isr_worker);
86 iwm = hw_to_iwm(hw);
87
88 while (!skb_queue_empty(&iwm->rx_list)) {
89 skb = skb_dequeue(&iwm->rx_list);
90 rx_info = skb_to_rx_info(skb);
91 rx_size = rx_info->rx_size;
92 rx_buf = skb->data;
93
94 IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size);
95 if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0)
96 IWM_WARN(iwm, "RX error\n");
97
98 kfree_skb(skb);
99 }
100}
101
102static void iwm_sdio_isr(struct sdio_func *func)
103{
104 struct iwm_priv *iwm;
105 struct iwm_sdio_priv *hw;
106 struct iwm_rx_info *rx_info;
107 struct sk_buff *skb;
108 unsigned long buf_size, read_size;
109 int ret;
110 u8 val;
111
112 hw = sdio_get_drvdata(func);
113 iwm = hw_to_iwm(hw);
114
115 buf_size = hw->blk_size;
116
117 /* We're checking the status */
118 val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret);
119 if (val == 0 || ret < 0) {
120 IWM_ERR(iwm, "Wrong INTR_STATUS\n");
121 return;
122 }
123
124 /* See if we have free buffers */
125 if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) {
126 IWM_ERR(iwm, "No buffer for more Rx frames\n");
127 return;
128 }
129
130 /* We first read the transaction size */
131 read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret);
132 read_size = read_size << 8;
133
134 if (ret < 0) {
135 IWM_ERR(iwm, "Couldn't read the xfer size\n");
136 return;
137 }
138
139 /* We need to clear the INT register */
140 sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret);
141 if (ret < 0) {
142 IWM_ERR(iwm, "Couldn't clear the INT register\n");
143 return;
144 }
145
146 while (buf_size < read_size)
147 buf_size <<= 1;
148
149 skb = dev_alloc_skb(buf_size);
150 if (!skb) {
151 IWM_ERR(iwm, "Couldn't alloc RX skb\n");
152 return;
153 }
154 rx_info = skb_to_rx_info(skb);
155 rx_info->rx_size = read_size;
156 rx_info->rx_buf_size = buf_size;
157
158 /* Now we can read the actual buffer */
159 ret = sdio_memcpy_fromio(func, skb_put(skb, read_size),
160 IWM_SDIO_DATA_ADDR, read_size);
161
162 /* The skb is put on a driver's specific Rx SKB list */
163 skb_queue_tail(&iwm->rx_list, skb);
164
165 /* We can now schedule the actual worker */
166 queue_work(hw->isr_wq, &hw->isr_worker);
167}
168
169static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw)
170{
171 struct iwm_priv *iwm = hw_to_iwm(hw);
172
173 flush_workqueue(hw->isr_wq);
174
175 skb_queue_purge(&iwm->rx_list);
176}
177
178/* Bus ops */
179static int if_sdio_enable(struct iwm_priv *iwm)
180{
181 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
182 int ret;
183
184 sdio_claim_host(hw->func);
185
186 ret = sdio_enable_func(hw->func);
187 if (ret) {
188 IWM_ERR(iwm, "Couldn't enable the device: is TOP driver "
189 "loaded and functional?\n");
190 goto release_host;
191 }
192
193 iwm_reset(iwm);
194
195 ret = sdio_claim_irq(hw->func, iwm_sdio_isr);
196 if (ret) {
197 IWM_ERR(iwm, "Failed to claim irq: %d\n", ret);
198 goto release_host;
199 }
200
201 sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
202 if (ret < 0) {
203 IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret);
204 goto release_irq;
205 }
206
207 sdio_release_host(hw->func);
208
209 IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n");
210
211 return 0;
212
213 release_irq:
214 sdio_release_irq(hw->func);
215 release_host:
216 sdio_release_host(hw->func);
217
218 return ret;
219}
220
221static int if_sdio_disable(struct iwm_priv *iwm)
222{
223 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
224 int ret;
225
226 iwm_reset(iwm);
227
228 sdio_claim_host(hw->func);
229 sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret);
230 if (ret < 0)
231 IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret);
232
233 sdio_release_irq(hw->func);
234 sdio_disable_func(hw->func);
235 sdio_release_host(hw->func);
236
237 iwm_sdio_rx_free(hw);
238
239 IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n");
240
241 return 0;
242}
243
244static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count)
245{
246 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
247 int aligned_count = ALIGN(count, hw->blk_size);
248 int ret;
249
250 if ((unsigned long)buf & 0x3) {
251 IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf);
252 /* TODO: Is this a hardware limitation? use get_unligned */
253 return -EINVAL;
254 }
255
256 sdio_claim_host(hw->func);
257 ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf,
258 aligned_count);
259 sdio_release_host(hw->func);
260
261 return ret;
262}
263
264/* debugfs hooks */
265static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp)
266{
267 filp->private_data = inode->i_private;
268 return 0;
269}
270
271static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer,
272 size_t count, loff_t *ppos)
273{
274 struct iwm_priv *iwm = filp->private_data;
275 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
276 char *buf;
277 u8 cccr;
278 int buf_len = 4096, ret;
279 size_t len = 0;
280
281 if (*ppos != 0)
282 return 0;
283 if (count < sizeof(buf))
284 return -ENOSPC;
285
286 buf = kzalloc(buf_len, GFP_KERNEL);
287 if (!buf)
288 return -ENOMEM;
289
290 sdio_claim_host(hw->func);
291
292 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret);
293 if (ret) {
294 IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n");
295 goto err;
296 }
297 len += snprintf(buf + len, buf_len - len, "CCCR_IOEx: 0x%x\n", cccr);
298
299 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret);
300 if (ret) {
301 IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n");
302 goto err;
303 }
304 len += snprintf(buf + len, buf_len - len, "CCCR_IORx: 0x%x\n", cccr);
305
306
307 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret);
308 if (ret) {
309 IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n");
310 goto err;
311 }
312 len += snprintf(buf + len, buf_len - len, "CCCR_IENx: 0x%x\n", cccr);
313
314
315 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret);
316 if (ret) {
317 IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n");
318 goto err;
319 }
320 len += snprintf(buf + len, buf_len - len, "CCCR_INTx: 0x%x\n", cccr);
321
322
323 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret);
324 if (ret) {
325 IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n");
326 goto err;
327 }
328 len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr);
329
330 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret);
331 if (ret) {
332 IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n");
333 goto err;
334 }
335 len += snprintf(buf + len, buf_len - len, "CCCR_IF: 0x%x\n", cccr);
336
337
338 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret);
339 if (ret) {
340 IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n");
341 goto err;
342 }
343 len += snprintf(buf + len, buf_len - len, "CCCR_CAPS: 0x%x\n", cccr);
344
345 cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret);
346 if (ret) {
347 IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n");
348 goto err;
349 }
350 len += snprintf(buf + len, buf_len - len, "CCCR_CIS: 0x%x\n", cccr);
351
352 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
353err:
354 sdio_release_host(hw->func);
355
356 kfree(buf);
357
358 return ret;
359}
360
361static const struct file_operations iwm_debugfs_sdio_fops = {
362 .owner = THIS_MODULE,
363 .open = iwm_debugfs_sdio_open,
364 .read = iwm_debugfs_sdio_read,
365};
366
367static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir)
368{
369 int result;
370 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
371
372 hw->cccr_dentry = debugfs_create_file("cccr", 0200,
373 parent_dir, iwm,
374 &iwm_debugfs_sdio_fops);
375 result = PTR_ERR(hw->cccr_dentry);
376 if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) {
377 IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result);
378 return result;
379 }
380
381 return 0;
382}
383
384static void if_sdio_debugfs_exit(struct iwm_priv *iwm)
385{
386 struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm);
387
388 debugfs_remove(hw->cccr_dentry);
389}
390
391static struct iwm_if_ops if_sdio_ops = {
392 .enable = if_sdio_enable,
393 .disable = if_sdio_disable,
394 .send_chunk = if_sdio_send_chunk,
395 .debugfs_init = if_sdio_debugfs_init,
396 .debugfs_exit = if_sdio_debugfs_exit,
397 .umac_name = "iwmc3200wifi-umac-sdio.bin",
398 .calib_lmac_name = "iwmc3200wifi-lmac-calib-sdio.bin",
399 .lmac_name = "iwmc3200wifi-lmac-sdio.bin",
400};
401
402static int iwm_sdio_probe(struct sdio_func *func,
403 const struct sdio_device_id *id)
404{
405 struct iwm_priv *iwm;
406 struct iwm_sdio_priv *hw;
407 struct device *dev = &func->dev;
408 int ret;
409
410 /* check if TOP has already initialized the card */
411 sdio_claim_host(func);
412 ret = sdio_enable_func(func);
413 if (ret) {
414 dev_err(dev, "wait for TOP to enable the device\n");
415 sdio_release_host(func);
416 return ret;
417 }
418
419 ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE);
420
421 sdio_disable_func(func);
422 sdio_release_host(func);
423
424 if (ret < 0) {
425 dev_err(dev, "Failed to set block size: %d\n", ret);
426 return ret;
427 }
428
429 iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops);
430 if (IS_ERR(iwm)) {
431 dev_err(dev, "allocate SDIO interface failed\n");
432 return PTR_ERR(iwm);
433 }
434
435 hw = iwm_private(iwm);
436 hw->iwm = iwm;
437
438 ret = iwm_debugfs_init(iwm);
439 if (ret < 0) {
440 IWM_ERR(iwm, "Debugfs registration failed\n");
441 goto if_free;
442 }
443
444 sdio_set_drvdata(func, hw);
445
446 hw->func = func;
447 hw->blk_size = IWM_SDIO_BLK_SIZE;
448
449 hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio");
450 if (!hw->isr_wq) {
451 ret = -ENOMEM;
452 goto debugfs_exit;
453 }
454
455 INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker);
456
457 dev_info(dev, "IWM SDIO probe\n");
458
459 return 0;
460
461 debugfs_exit:
462 iwm_debugfs_exit(iwm);
463 if_free:
464 iwm_if_free(iwm);
465 return ret;
466}
467
468static void iwm_sdio_remove(struct sdio_func *func)
469{
470 struct iwm_sdio_priv *hw = sdio_get_drvdata(func);
471 struct iwm_priv *iwm = hw_to_iwm(hw);
472 struct device *dev = &func->dev;
473
474 iwm_debugfs_exit(iwm);
475 iwm_if_free(iwm);
476 destroy_workqueue(hw->isr_wq);
477
478 sdio_set_drvdata(func, NULL);
479
480 dev_info(dev, "IWM SDIO remove\n");
481
482 return;
483}
484
485static const struct sdio_device_id iwm_sdio_ids[] = {
486 { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, SDIO_DEVICE_ID_IWM) },
487 { /* end: all zeroes */ },
488};
489MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids);
490
491static struct sdio_driver iwm_sdio_driver = {
492 .name = "iwm_sdio",
493 .id_table = iwm_sdio_ids,
494 .probe = iwm_sdio_probe,
495 .remove = iwm_sdio_remove,
496};
497
498static int __init iwm_sdio_init_module(void)
499{
500 int ret;
501
502 ret = sdio_register_driver(&iwm_sdio_driver);
503
504 return ret;
505}
506
507static void __exit iwm_sdio_exit_module(void)
508{
509 sdio_unregister_driver(&iwm_sdio_driver);
510}
511
512module_init(iwm_sdio_init_module);
513module_exit(iwm_sdio_exit_module);
514
515MODULE_LICENSE("GPL");
516MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR);
diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h
new file mode 100644
index 000000000000..b3c156b08dda
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/sdio.h
@@ -0,0 +1,67 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_SDIO_H__
40#define __IWM_SDIO_H__
41
42#define SDIO_VENDOR_ID_INTEL 0x89
43#define SDIO_DEVICE_ID_IWM 0x1403
44
45#define IWM_SDIO_DATA_ADDR 0x0
46#define IWM_SDIO_INTR_ENABLE_ADDR 0x14
47#define IWM_SDIO_INTR_STATUS_ADDR 0x13
48#define IWM_SDIO_INTR_CLEAR_ADDR 0x13
49#define IWM_SDIO_INTR_GET_SIZE_ADDR 0x2C
50
51#define IWM_SDIO_BLK_SIZE 256
52
53#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private)
54
55struct iwm_sdio_priv {
56 struct sdio_func *func;
57 struct iwm_priv *iwm;
58
59 struct workqueue_struct *isr_wq;
60 struct work_struct isr_worker;
61
62 struct dentry *cccr_dentry;
63
64 unsigned int blk_size;
65};
66
67#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c
new file mode 100644
index 000000000000..e3b4f7902daf
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/tx.c
@@ -0,0 +1,492 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39/*
40 * iwm Tx theory of operation:
41 *
42 * 1) We receive a 802.3 frame from the stack
43 * 2) We convert it to a 802.11 frame [iwm_xmit_frame]
44 * 3) We queue it to its corresponding tx queue [iwm_xmit_frame]
45 * 4) We schedule the tx worker. There is one worker per tx
46 * queue. [iwm_xmit_frame]
47 * 5) The tx worker is scheduled
48 * 6) We go through every queued skb on the tx queue, and for each
49 * and every one of them: [iwm_tx_worker]
50 * a) We check if we have enough Tx credits (see below for a Tx
51 * credits description) for the frame length. [iwm_tx_worker]
52 * b) If we do, we aggregate the Tx frame into a UDMA one, by
53 * concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker]
54 * c) When we run out of credits, or when we reach the maximum
55 * concatenation size, we actually send the concatenated UDMA
56 * frame. [iwm_tx_worker]
57 *
58 * When we run out of Tx credits, the skbs are filling the tx queue,
59 * and eventually we will stop the netdev queue. [iwm_tx_worker]
60 * The tx queue is emptied as we're getting new tx credits, by
61 * scheduling the tx_worker. [iwm_tx_credit_inc]
62 * The netdev queue is started again when we have enough tx credits,
63 * and when our tx queue has some reasonable amout of space available
64 * (i.e. half of the max size). [iwm_tx_worker]
65 */
66
67#include <linux/skbuff.h>
68#include <linux/netdevice.h>
69#include <linux/ieee80211.h>
70
71#include "iwm.h"
72#include "debug.h"
73#include "commands.h"
74#include "hal.h"
75#include "umac.h"
76#include "bus.h"
77
78#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff
79
80#define BYTES_TO_PAGES(n) (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \
81 (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0))
82
83#define pool_id_to_queue(id) ((id < IWM_TX_CMD_QUEUE) ? id : id - 1)
84#define queue_to_pool_id(q) ((q < IWM_TX_CMD_QUEUE) ? q : q + 1)
85
86/* require to hold tx_credit lock */
87static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id)
88{
89 struct pool_entry *pool = &tx_credit->pools[id];
90 struct spool_entry *spool = &tx_credit->spools[pool->sid];
91 int spool_pages;
92
93 /* number of pages can be taken from spool by this pool */
94 spool_pages = spool->max_pages - spool->alloc_pages +
95 max(pool->min_pages - pool->alloc_pages, 0);
96
97 return min(pool->max_pages - pool->alloc_pages, spool_pages);
98}
99
100static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb)
101{
102 u32 npages = BYTES_TO_PAGES(nb);
103
104 if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id))
105 return 1;
106
107 set_bit(id, &iwm->tx_credit.full_pools_map);
108
109 IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n",
110 pool_id_to_queue(id),
111 iwm_tx_credit_get(&iwm->tx_credit, id));
112
113 return 0;
114}
115
116void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages)
117{
118 struct pool_entry *pool;
119 struct spool_entry *spool;
120 int freed_pages;
121 int queue;
122
123 BUG_ON(id >= IWM_MACS_OUT_GROUPS);
124
125 pool = &iwm->tx_credit.pools[id];
126 spool = &iwm->tx_credit.spools[pool->sid];
127
128 freed_pages = total_freed_pages - pool->total_freed_pages;
129 IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id);
130
131 if (!freed_pages) {
132 IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n");
133 return;
134 } else if (freed_pages < 0)
135 freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1;
136
137 if (pool->alloc_pages > pool->min_pages) {
138 int spool_pages = pool->alloc_pages - pool->min_pages;
139 spool_pages = min(spool_pages, freed_pages);
140 spool->alloc_pages -= spool_pages;
141 }
142
143 pool->alloc_pages -= freed_pages;
144 pool->total_freed_pages = total_freed_pages;
145
146 IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
147 "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
148 pool->total_freed_pages, pool->sid, spool->alloc_pages);
149
150 if (test_bit(id, &iwm->tx_credit.full_pools_map) &&
151 (pool->alloc_pages < pool->max_pages / 2)) {
152 clear_bit(id, &iwm->tx_credit.full_pools_map);
153
154 queue = pool_id_to_queue(id);
155
156 IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available "
157 "credit: %d\n", queue,
158 iwm_tx_credit_get(&iwm->tx_credit, id));
159 queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
160 }
161}
162
163static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages)
164{
165 struct pool_entry *pool;
166 struct spool_entry *spool;
167 int spool_pages;
168
169 IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n",
170 alloc_pages, id);
171
172 BUG_ON(id >= IWM_MACS_OUT_GROUPS);
173
174 pool = &iwm->tx_credit.pools[id];
175 spool = &iwm->tx_credit.spools[pool->sid];
176
177 spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages;
178
179 if (pool->alloc_pages >= pool->min_pages)
180 spool->alloc_pages += alloc_pages;
181 else if (spool_pages > 0)
182 spool->alloc_pages += spool_pages;
183
184 pool->alloc_pages += alloc_pages;
185
186 IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, "
187 "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages,
188 pool->total_freed_pages, pool->sid, spool->alloc_pages);
189}
190
191int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb)
192{
193 u32 npages = BYTES_TO_PAGES(nb);
194 int ret = 0;
195
196 spin_lock(&iwm->tx_credit.lock);
197
198 if (!iwm_tx_credit_ok(iwm, id, nb)) {
199 IWM_DBG_TX(iwm, DBG, "No credit avaliable for pool[%d]\n", id);
200 ret = -ENOSPC;
201 goto out;
202 }
203
204 iwm_tx_credit_dec(iwm, id, npages);
205
206 out:
207 spin_unlock(&iwm->tx_credit.lock);
208 return ret;
209}
210
211/*
212 * Since we're on an SDIO or USB bus, we are not sharing memory
213 * for storing to be transmitted frames. The host needs to push
214 * them upstream. As a consequence there needs to be a way for
215 * the target to let us know if it can actually take more TX frames
216 * or not. This is what Tx credits are for.
217 *
218 * For each Tx HW queue, we have a Tx pool, and then we have one
219 * unique super pool (spool), which is actually a global pool of
220 * all the UMAC pages.
221 * For each Tx pool we have a min_pages, a max_pages fields, and a
222 * alloc_pages fields. The alloc_pages tracks the number of pages
223 * currently allocated from the tx pool.
224 * Here are the rules to check if given a tx frame we have enough
225 * tx credits for it:
226 * 1) We translate the frame length into a number of UMAC pages.
227 * Let's call them n_pages.
228 * 2) For the corresponding tx pool, we check if n_pages +
229 * pool->alloc_pages is higher than pool->min_pages. min_pages
230 * represent a set of pre-allocated pages on the tx pool. If
231 * that's the case, then we need to allocate those pages from
232 * the spool. We can do so until we reach spool->max_pages.
233 * 3) Each tx pool is not allowed to allocate more than pool->max_pages
234 * from the spool, so once we're over min_pages, we can allocate
235 * pages from the spool, but not more than max_pages.
236 *
237 * When the tx code path needs to send a tx frame, it checks first
238 * if it has enough tx credits, following those rules. [iwm_tx_credit_get]
239 * If it does, it then updates the pool and spool counters and
240 * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec]
241 * On the other side, when the UMAC is done transmitting frames, it
242 * will send a credit update notification to the host. This is when
243 * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc,
244 * called from rx.c:iwm_ntf_tx_credit_update]
245 *
246 */
247void iwm_tx_credit_init_pools(struct iwm_priv *iwm,
248 struct iwm_umac_notif_alive *alive)
249{
250 int i, sid, pool_pages;
251
252 spin_lock(&iwm->tx_credit.lock);
253
254 iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count);
255 iwm->tx_credit.full_pools_map = 0;
256 memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry));
257
258 IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr);
259
260 for (i = 0; i < iwm->tx_credit.pool_nr; i++) {
261 __le32 page_grp_state = alive->page_grp_state[i];
262
263 iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state,
264 UMAC_ALIVE_PAGE_STS_GRP_NUM);
265 iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state,
266 UMAC_ALIVE_PAGE_STS_SGRP_NUM);
267 iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state,
268 UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE);
269 iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state,
270 UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE);
271 iwm->tx_credit.pools[i].alloc_pages = 0;
272 iwm->tx_credit.pools[i].total_freed_pages = 0;
273
274 sid = iwm->tx_credit.pools[i].sid;
275 pool_pages = iwm->tx_credit.pools[i].min_pages;
276
277 if (iwm->tx_credit.spools[sid].max_pages == 0) {
278 iwm->tx_credit.spools[sid].id = sid;
279 iwm->tx_credit.spools[sid].max_pages =
280 GET_VAL32(page_grp_state,
281 UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE);
282 iwm->tx_credit.spools[sid].alloc_pages = 0;
283 }
284
285 iwm->tx_credit.spools[sid].alloc_pages += pool_pages;
286
287 IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity "
288 "min: %d, max: %d, pool alloc: %d, total_free: %d, "
289 "super poll alloc: %d\n",
290 i, iwm->tx_credit.pools[i].id,
291 iwm->tx_credit.pools[i].sid,
292 iwm->tx_credit.pools[i].min_pages,
293 iwm->tx_credit.pools[i].max_pages,
294 iwm->tx_credit.pools[i].alloc_pages,
295 iwm->tx_credit.pools[i].total_freed_pages,
296 iwm->tx_credit.spools[sid].alloc_pages);
297 }
298
299 spin_unlock(&iwm->tx_credit.lock);
300}
301
302#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr)
303
304static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
305 int pool_id, u8 *buf)
306{
307 struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf;
308 struct iwm_udma_wifi_cmd udma_cmd;
309 struct iwm_umac_cmd umac_cmd;
310 struct iwm_tx_info *tx_info = skb_to_tx_info(skb);
311
312 udma_cmd.count = cpu_to_le16(skb->len +
313 sizeof(struct iwm_umac_fw_cmd_hdr));
314 /* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be
315 * called later to set EOP for the last packet. */
316 udma_cmd.eop = 0;
317 udma_cmd.credit_group = pool_id;
318 udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid;
319 udma_cmd.lmac_offset = 0;
320
321 umac_cmd.id = REPLY_TX;
322 umac_cmd.count = cpu_to_le16(skb->len);
323 umac_cmd.color = tx_info->color;
324 umac_cmd.resp = 0;
325 umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm));
326
327 iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd);
328 iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd);
329
330 memcpy(buf + sizeof(*hdr), skb->data, skb->len);
331
332 return 0;
333}
334
335static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
336 struct iwm_tx_queue *txq)
337{
338 int ret;
339
340 if (!txq->concat_count)
341 return 0;
342
343 IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n",
344 txq->id, txq->concat_count);
345
346 /* mark EOP for the last packet */
347 iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1);
348
349 ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count);
350
351 txq->concat_count = 0;
352 txq->concat_ptr = txq->concat_buf;
353
354 return ret;
355}
356
357#define CONFIG_IWM_TX_CONCATENATED 1
358
359void iwm_tx_worker(struct work_struct *work)
360{
361 struct iwm_priv *iwm;
362 struct iwm_tx_info *tx_info = NULL;
363 struct sk_buff *skb;
364 int cmdlen, ret;
365 struct iwm_tx_queue *txq;
366 int pool_id;
367
368 txq = container_of(work, struct iwm_tx_queue, worker);
369 iwm = container_of(txq, struct iwm_priv, txq[txq->id]);
370
371 pool_id = queue_to_pool_id(txq->id);
372
373 while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
374 !skb_queue_empty(&txq->queue)) {
375
376 skb = skb_dequeue(&txq->queue);
377 tx_info = skb_to_tx_info(skb);
378 cmdlen = IWM_UDMA_HDR_LEN + skb->len;
379
380 IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: "
381 "%d, color: %d\n", txq->id, skb, tx_info->sta,
382 tx_info->color);
383
384#if !CONFIG_IWM_TX_CONCATENATED
385 /* temporarily keep this to comparing the performance */
386 ret = iwm_send_packet(iwm, skb, pool_id);
387#else
388
389 if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE)
390 iwm_tx_send_concat_packets(iwm, txq);
391
392 ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen);
393 if (ret) {
394 IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue "
395 "%d, Tx worker stopped\n", txq->id);
396 skb_queue_head(&txq->queue, skb);
397 break;
398 }
399
400 txq->concat_ptr = txq->concat_buf + txq->concat_count;
401 iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr);
402 txq->concat_count += ALIGN(cmdlen, 16);
403#endif
404 kfree_skb(skb);
405 }
406
407 iwm_tx_send_concat_packets(iwm, txq);
408
409 if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) &&
410 !test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
411 (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) {
412 IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id);
413 netif_wake_subqueue(iwm_to_ndev(iwm), txq->id);
414 }
415}
416
417int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
418{
419 struct iwm_priv *iwm = ndev_to_iwm(netdev);
420 struct net_device *ndev = iwm_to_ndev(iwm);
421 struct wireless_dev *wdev = iwm_to_wdev(iwm);
422 u8 *dst_addr;
423 struct iwm_tx_info *tx_info;
424 struct iwm_tx_queue *txq;
425 struct iwm_sta_info *sta_info;
426 u8 sta_id;
427 u16 queue;
428 int ret;
429
430 if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
431 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: "
432 "not associated\n");
433 netif_tx_stop_all_queues(netdev);
434 goto drop;
435 }
436
437 queue = skb_get_queue_mapping(skb);
438 BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */
439
440 txq = &iwm->txq[queue];
441
442 /* No free space for Tx, tx_worker is too slow */
443 if (skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) {
444 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue);
445 netif_stop_subqueue(netdev, queue);
446 return NETDEV_TX_BUSY;
447 }
448
449 ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype,
450 iwm->bssid, 0);
451 if (ret) {
452 IWM_ERR(iwm, "build wifi header failed\n");
453 goto drop;
454 }
455
456 dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1;
457
458 for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) {
459 sta_info = &iwm->sta_table[sta_id];
460 if (sta_info->valid &&
461 !memcmp(dst_addr, sta_info->addr, ETH_ALEN))
462 break;
463 }
464
465 if (sta_id == IWM_STA_TABLE_NUM) {
466 IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n",
467 dst_addr);
468 goto drop;
469 }
470
471 tx_info = skb_to_tx_info(skb);
472 tx_info->sta = sta_id;
473 tx_info->color = sta_info->color;
474 /* UMAC uses TID 8 (vs. 0) for non QoS packets */
475 if (sta_info->qos)
476 tx_info->tid = skb->priority;
477 else
478 tx_info->tid = IWM_UMAC_MGMT_TID;
479
480 skb_queue_tail(&iwm->txq[queue].queue, skb);
481
482 queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
483
484 ndev->stats.tx_packets++;
485 ndev->stats.tx_bytes += skb->len;
486 return NETDEV_TX_OK;
487
488 drop:
489 ndev->stats.tx_dropped++;
490 dev_kfree_skb_any(skb);
491 return NETDEV_TX_OK;
492}
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h
new file mode 100644
index 000000000000..4a95cce1f0a6
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/umac.h
@@ -0,0 +1,744 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Intel Corporation nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 *
33 * Intel Corporation <ilw@linux.intel.com>
34 * Samuel Ortiz <samuel.ortiz@intel.com>
35 * Zhu Yi <yi.zhu@intel.com>
36 *
37 */
38
39#ifndef __IWM_UMAC_H__
40#define __IWM_UMAC_H__
41
42struct iwm_udma_in_hdr {
43 __le32 cmd;
44 __le32 size;
45} __attribute__ ((packed));
46
47struct iwm_udma_out_nonwifi_hdr {
48 __le32 cmd;
49 __le32 addr;
50 __le32 op1_sz;
51 __le32 op2;
52} __attribute__ ((packed));
53
54struct iwm_udma_out_wifi_hdr {
55 __le32 cmd;
56 __le32 meta_data;
57} __attribute__ ((packed));
58
59/* Sequence numbering */
60#define UMAC_WIFI_SEQ_NUM_BASE 1
61#define UMAC_WIFI_SEQ_NUM_MAX 0x4000
62#define UMAC_NONWIFI_SEQ_NUM_BASE 1
63#define UMAC_NONWIFI_SEQ_NUM_MAX 0x10
64
65/* MAC address address */
66#define WICO_MAC_ADDRESS_ADDR 0x604008F8
67
68/* RA / TID */
69#define UMAC_HDI_ACT_TBL_IDX_TID_POS 0
70#define UMAC_HDI_ACT_TBL_IDX_TID_SEED 0xF
71
72#define UMAC_HDI_ACT_TBL_IDX_RA_POS 4
73#define UMAC_HDI_ACT_TBL_IDX_RA_SEED 0xF
74
75#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC 0xF
76#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC 0x9
77#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC 0xA
78
79#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \
80 ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
81 (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
82#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \
83 ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
84 (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
85
86/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */
87#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0
88#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF
89
90/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */
91#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS 4
92#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED 0xF
93
94/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */
95#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS 8
96#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED 0xFF
97
98/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */
99#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS 16
100#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED 0xFF
101
102/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */
103#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS 24
104#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED 0xFF
105
106/* Barkers */
107#define UMAC_REBOOT_BARKER 0xdeadbeef
108#define UMAC_ACK_BARKER 0xfeedbabe
109#define UMAC_PAD_TERMINAL 0xadadadad
110
111/* UMAC JMP address */
112#define UMAC_MU_FW_INST_DATA_12_ADDR 0xBF0000
113
114/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */
115#define UMAC_HDI_OUT_CMD_OPCODE_POS 0
116#define UMAC_HDI_OUT_CMD_OPCODE_SEED 0xF
117
118/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */
119#define UMAC_HDI_OUT_CMD_EOT_POS 10
120#define UMAC_HDI_OUT_CMD_EOT_SEED 0x1
121
122/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */
123#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS 11
124#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED 0x1
125
126/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
127#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS 12
128#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF
129
130/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */
131#define UMAC_HDI_OUT_CMD_SIGNATURE_POS 16
132#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED 0xFFFF
133
134/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */
135#define UMAC_HDI_OUT_BYTE_COUNT_POS 0
136#define UMAC_HDI_OUT_BYTE_COUNT_SEED 0xFFF
137
138/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */
139#define UMAC_HDI_OUT_CREDIT_GRP_POS 12
140#define UMAC_HDI_OUT_CREDIT_GRP_SEED 0xF
141
142/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */
143#define UMAC_HDI_OUT_RATID_POS 16
144#define UMAC_HDI_OUT_RATID_SEED 0xFF
145
146/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */
147#define UMAC_HDI_OUT_LMAC_OFFSET_POS 24
148#define UMAC_HDI_OUT_LMAC_OFFSET_SEED 0xFF
149
150/* Signature */
151#define UMAC_HDI_OUT_SIGNATURE 0xCBBC
152
153/* buffer alignment */
154#define UMAC_HDI_BUF_ALIGN_MSK 0xF
155
156/* iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */
157#define UMAC_HDI_IN_CMD_OPCODE_POS 0
158#define UMAC_HDI_IN_CMD_OPCODE_SEED 0xF
159
160/* iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */
161#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS 4
162#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED 0x7
163
164/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */
165#define UMAC_HDI_IN_CMD_SOURCE_POS 4
166#define UMAC_HDI_IN_CMD_SOURCE_SEED 0x3
167
168/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */
169#define UMAC_HDI_IN_CMD_EOT_POS 6
170#define UMAC_HDI_IN_CMD_EOT_SEED 0x1
171
172/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */
173#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS 7
174#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED 0x1
175
176/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */
177#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS 8
178#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED 0x1
179
180/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */
181#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS 9
182#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED 0x7FFFFF
183
184/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */
185#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS 12
186#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF
187
188/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */
189#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS 16
190#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED 0xFFFF
191
192/* Fixed Non-WiFi signature */
193#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG 0xCBBC
194
195/* IN NTFY op-codes */
196#define UMAC_NOTIFY_OPCODE_ALIVE 0xA1
197#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE 0xA2
198#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS 0xA3
199#define UMAC_NOTIFY_OPCODE_ERROR 0xA4
200#define UMAC_NOTIFY_OPCODE_DEBUG 0xA5
201#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER 0xB0
202#define UMAC_NOTIFY_OPCODE_STATS 0xB1
203#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC 0xB3
204#define UMAC_NOTIFY_OPCODE_RX_TICKET 0xB4
205#define UMAC_NOTIFY_OPCODE_MAX (UMAC_NOTIFY_OPCODE_RX_TICKET -\
206 UMAC_NOTIFY_OPCODE_ALIVE + 1)
207#define UMAC_NOTIFY_OPCODE_FIRST (UMAC_NOTIFY_OPCODE_ALIVE)
208
209/* HDI OUT OP CODE */
210#define UMAC_HDI_OUT_OPCODE_PING 0x0
211#define UMAC_HDI_OUT_OPCODE_READ 0x1
212#define UMAC_HDI_OUT_OPCODE_WRITE 0x2
213#define UMAC_HDI_OUT_OPCODE_JUMP 0x3
214#define UMAC_HDI_OUT_OPCODE_REBOOT 0x4
215#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT 0x5
216#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT 0x6
217#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE 0x7
218/* #define UMAC_HDI_OUT_OPCODE_RESERVED 0x8..0xA */
219#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG 0xB
220#define UMAC_HDI_OUT_OPCODE_WIFI 0xF
221
222/* HDI IN OP CODE -- Non WiFi*/
223#define UMAC_HDI_IN_OPCODE_PING 0x0
224#define UMAC_HDI_IN_OPCODE_READ 0x1
225#define UMAC_HDI_IN_OPCODE_WRITE 0x2
226#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT 0x5
227#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT 0x6
228#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE 0x7
229#define UMAC_HDI_IN_OPCODE_EP_MGMT 0x8
230#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE 0x9
231#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE 0xA
232#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG 0xB
233#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \
234 (UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1)
235#define UMAC_HDI_IN_OPCODE_WIFI 0xF
236
237/* HDI IN SOURCE */
238#define UMAC_HDI_IN_SOURCE_FHRX 0x0
239#define UMAC_HDI_IN_SOURCE_UDMA 0x1
240#define UMAC_HDI_IN_SOURCE_FW 0x2
241#define UMAC_HDI_IN_SOURCE_RESERVED 0x3
242
243/* OUT CMD op-codes */
244#define UMAC_CMD_OPCODE_ECHO 0x01
245#define UMAC_CMD_OPCODE_HALT 0x02
246#define UMAC_CMD_OPCODE_RESET 0x03
247#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT 0x09
248#define UMAC_CMD_OPCODE_URB_CANCEL_ACK 0x0A
249#define UMAC_CMD_OPCODE_DCACHE_FLUSH 0x0B
250#define UMAC_CMD_OPCODE_EEPROM_PROXY 0x0C
251#define UMAC_CMD_OPCODE_TX_ECHO 0x0D
252#define UMAC_CMD_OPCODE_DBG_MON 0x0E
253#define UMAC_CMD_OPCODE_INTERNAL_TX 0x0F
254#define UMAC_CMD_OPCODE_SET_PARAM_FIX 0x10
255#define UMAC_CMD_OPCODE_SET_PARAM_VAR 0x11
256#define UMAC_CMD_OPCODE_GET_PARAM 0x12
257#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER 0x13
258#define UMAC_CMD_OPCODE_TARGET 0x14
259#define UMAC_CMD_OPCODE_STATISTIC_REQUEST 0x15
260#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16
261#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17
262#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18
263#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA
264#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB
265#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC
266#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER 0xFD
267#define UMAC_CMD_OPCODE_WIFI_WRAPPER 0xFE
268#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH 0xFF
269
270/* UMAC WiFi interface op-codes */
271#define UMAC_WIFI_IF_CMD_SET_PROFILE 0x11
272#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE 0x12
273#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST 0x13
274#define UMAC_WIFI_IF_CMD_SCAN_REQUEST 0x14
275#define UMAC_WIFI_IF_CMD_SCAN_CONFIG 0x15
276#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY 0x16
277#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY 0x17
278#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY 0x18
279#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY 0x19
280#define UMAC_WIFI_IF_CMD_REMOVE_KEY 0x1A
281#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B
282#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C
283#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E
284#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20
285
286/* UMAC WiFi interface ports */
287#define UMAC_WIFI_IF_FLG_PORT_DEF 0x00
288#define UMAC_WIFI_IF_FLG_PORT_PAN 0x01
289#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID WIFI_IF_FLG_PORT_DEF
290
291/* UMAC WiFi interface actions */
292#define UMAC_WIFI_IF_FLG_ACT_GET 0x10
293#define UMAC_WIFI_IF_FLG_ACT_SET 0x20
294
295/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */
296#define UMAC_FW_CMD_BYTE_COUNT_POS 0
297#define UMAC_FW_CMD_BYTE_COUNT_SEED 0xFFF
298
299/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */
300#define UMAC_FW_CMD_STATUS_POS 12
301#define UMAC_FW_CMD_STATUS_SEED 0xF
302
303/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */
304#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS 16
305#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED 0x1
306
307/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */
308#define UMAC_FW_CMD_TX_FW_CMD_POS 17
309#define UMAC_FW_CMD_TX_FW_CMD_SEED 0x1
310
311/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */
312#define UMAC_FW_CMD_TX_PLAINTEXT_POS 18
313#define UMAC_FW_CMD_TX_PLAINTEXT_SEED 0x1
314
315/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */
316#define UMAC_FW_CMD_TX_STA_COLOR_POS 20
317#define UMAC_FW_CMD_TX_STA_COLOR_SEED 0x7
318
319/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */
320#define UMAC_FW_CMD_TX_LIFETIME_TU_POS 24
321#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED 0xFF
322
323/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */
324#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS 5
325#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED 0x1
326
327/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */
328#define UMAC_DEV_CMD_FLAGS_ABORT_POS 6
329#define UMAC_DEV_CMD_FLAGS_ABORT_SEED 0x1
330
331/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */
332#define DEV_CMD_FLAGS_FLD_INTERNAL_POS 7
333#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED 0x1
334
335/* Rx */
336/* Rx actions */
337#define IWM_RX_TICKET_DROP 0x0
338#define IWM_RX_TICKET_RELEASE 0x1
339#define IWM_RX_TICKET_SNIFFER 0x2
340#define IWM_RX_TICKET_ENQUEUE 0x3
341
342/* Rx flags */
343#define IWM_RX_TICKET_PAD_SIZE_MSK 0x2
344#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4
345#define IWM_RX_TICKET_AMSDU_MSK 0x8
346#define IWM_RX_TICKET_DROP_REASON_POS 4
347#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS)
348
349#define IWM_RX_DROP_NO_DROP 0x0
350#define IWM_RX_DROP_BAD_CRC 0x1
351/* L2P no address match */
352#define IWM_RX_DROP_LMAC_ADDR_FILTER 0x2
353/* Multicast address not in list */
354#define IWM_RX_DROP_MCAST_ADDR_FILTER 0x3
355/* Control frames are not sent to the driver */
356#define IWM_RX_DROP_CTL_FRAME 0x4
357/* Our frame is back */
358#define IWM_RX_DROP_OUR_TX 0x5
359/* Association class filtering */
360#define IWM_RX_DROP_CLASS_FILTER 0x6
361/* Duplicated frame */
362#define IWM_RX_DROP_DUPLICATE_FILTER 0x7
363/* Decryption error */
364#define IWM_RX_DROP_SEC_ERR 0x8
365/* Unencrypted frame while encryption is on */
366#define IWM_RX_DROP_SEC_NO_ENCRYPTION 0x9
367/* Replay check failure */
368#define IWM_RX_DROP_SEC_REPLAY_ERR 0xa
369/* uCode and FW key color mismatch, check before replay */
370#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH 0xb
371#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE 0xc
372/* No fragmentations Db is found */
373#define IWM_RX_DROP_FRAG_NO_RESOURCE 0xd
374/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */
375#define IWM_RX_DROP_FRAG_ERR 0xe
376#define IWM_RX_DROP_FRAG_LOST 0xf
377#define IWM_RX_DROP_FRAG_COMPLETE 0x10
378/* Should be handled by UMAC */
379#define IWM_RX_DROP_MANAGEMENT 0x11
380/* STA not found by UMAC */
381#define IWM_RX_DROP_NO_STATION 0x12
382/* NULL or QoS NULL */
383#define IWM_RX_DROP_NULL_DATA 0x13
384#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL 0x14
385#define IWM_RX_DROP_BA_REORDER_DUPLICATE 0x15
386
387struct iwm_rx_ticket {
388 __le16 action;
389 __le16 id;
390 __le16 flags;
391 u8 payload_offset; /* includes: MAC header, pad, IV */
392 u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */
393} __attribute__ ((packed));
394
395struct iwm_rx_mpdu_hdr {
396 __le16 len;
397 __le16 reserved;
398} __attribute__ ((packed));
399
400/* UMAC SW WIFI API */
401
402struct iwm_dev_cmd_hdr {
403 u8 cmd;
404 u8 flags;
405 __le16 seq_num;
406} __attribute__ ((packed));
407
408struct iwm_umac_fw_cmd_hdr {
409 __le32 meta_data;
410 struct iwm_dev_cmd_hdr cmd;
411} __attribute__ ((packed));
412
413struct iwm_umac_wifi_out_hdr {
414 struct iwm_udma_out_wifi_hdr hw_hdr;
415 struct iwm_umac_fw_cmd_hdr sw_hdr;
416} __attribute__ ((packed));
417
418struct iwm_umac_nonwifi_out_hdr {
419 struct iwm_udma_out_nonwifi_hdr hw_hdr;
420} __attribute__ ((packed));
421
422struct iwm_umac_wifi_in_hdr {
423 struct iwm_udma_in_hdr hw_hdr;
424 struct iwm_umac_fw_cmd_hdr sw_hdr;
425} __attribute__ ((packed));
426
427struct iwm_umac_nonwifi_in_hdr {
428 struct iwm_udma_in_hdr hw_hdr;
429 __le32 time_stamp;
430} __attribute__ ((packed));
431
432#define IWM_UMAC_PAGE_SIZE 0x200
433
434/* Notify structures */
435struct iwm_fw_version {
436 u8 minor;
437 u8 major;
438 __le16 id;
439};
440
441struct iwm_fw_build {
442 u8 type;
443 u8 subtype;
444 u8 platform;
445 u8 opt;
446};
447
448struct iwm_fw_alive_hdr {
449 struct iwm_fw_version ver;
450 struct iwm_fw_build build;
451 __le32 os_build;
452 __le32 log_hdr_addr;
453 __le32 log_buf_addr;
454 __le32 sys_timer_addr;
455};
456
457#define WAIT_NOTIF_TIMEOUT (2 * HZ)
458#define SCAN_COMPLETE_TIMEOUT (3 * HZ)
459
460#define UMAC_NTFY_ALIVE_STATUS_ERR 0xDEAD
461#define UMAC_NTFY_ALIVE_STATUS_OK 0xCAFE
462
463#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR 0xDEAD
464#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK 0xCAFE
465
466#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN 0x40
467#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN 0x80
468
469#define IWM_MACS_OUT_GROUPS 6
470#define IWM_MACS_OUT_SGROUPS 1
471
472
473#define WIFI_IF_NTFY_ASSOC_START 0x80
474#define WIFI_IF_NTFY_ASSOC_COMPLETE 0x81
475#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE 0x82
476#define WIFI_IF_NTFY_CONNECTION_TERMINATED 0x83
477#define WIFI_IF_NTFY_SCAN_COMPLETE 0x84
478#define WIFI_IF_NTFY_STA_TABLE_CHANGE 0x85
479#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED 0x86
480#define WIFI_IF_NTFY_RADIO_PREEMPTION 0x87
481#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED 0x88
482#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED 0x89
483#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS 0x8A
484#define WIFI_IF_NTFY_MGMT_FRAME 0x8B
485
486/* DEBUG INDICATIONS */
487#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START 0xE0
488#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE 0xE1
489#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START 0xE2
490#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT 0xE3
491#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START 0xE4
492#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE 0xE5
493#define WIFI_DBG_IF_NTFY_CNCT_ATC_START 0xE6
494#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION 0xE7
495#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8
496#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9
497
498/* Notification structures */
499struct iwm_umac_notif_wifi_if {
500 struct iwm_umac_wifi_in_hdr hdr;
501 u8 status;
502 u8 flags;
503 __le16 buf_size;
504} __attribute__ ((packed));
505
506#define UMAC_ROAM_REASON_FIRST_SELECTION 0x1
507#define UMAC_ROAM_REASON_AP_DEAUTH 0x2
508#define UMAC_ROAM_REASON_AP_CONNECT_LOST 0x3
509#define UMAC_ROAM_REASON_RSSI 0x4
510#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM 0x5
511#define UMAC_ROAM_REASON_IBSS_COALESCING 0x6
512
513struct iwm_umac_notif_assoc_start {
514 struct iwm_umac_notif_wifi_if mlme_hdr;
515 __le32 roam_reason;
516 u8 bssid[ETH_ALEN];
517 u8 reserved[2];
518} __attribute__ ((packed));
519
520#define UMAC_ASSOC_COMPLETE_SUCCESS 0x0
521#define UMAC_ASSOC_COMPLETE_FAILURE 0x1
522
523struct iwm_umac_notif_assoc_complete {
524 struct iwm_umac_notif_wifi_if mlme_hdr;
525 __le32 status;
526 u8 bssid[ETH_ALEN];
527 u8 band;
528 u8 channel;
529} __attribute__ ((packed));
530
531#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0
532#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1
533#define UMAC_PROFILE_INVALID_REQUEST 0x2
534#define UMAC_PROFILE_INVALID_RF_PREEMPTED 0x3
535
536struct iwm_umac_notif_profile_invalidate {
537 struct iwm_umac_notif_wifi_if mlme_hdr;
538 __le32 reason;
539} __attribute__ ((packed));
540
541#define UMAC_SCAN_RESULT_SUCCESS 0x0
542#define UMAC_SCAN_RESULT_ABORTED 0x1
543#define UMAC_SCAN_RESULT_REJECTED 0x2
544#define UMAC_SCAN_RESULT_FAILED 0x3
545
546struct iwm_umac_notif_scan_complete {
547 struct iwm_umac_notif_wifi_if mlme_hdr;
548 __le32 type;
549 __le32 result;
550 u8 seq_num;
551} __attribute__ ((packed));
552
553#define UMAC_OPCODE_ADD_MODIFY 0x0
554#define UMAC_OPCODE_REMOVE 0x1
555#define UMAC_OPCODE_CLEAR_ALL 0x2
556
557#define UMAC_STA_FLAG_QOS 0x1
558
559struct iwm_umac_notif_sta_info {
560 struct iwm_umac_notif_wifi_if mlme_hdr;
561 __le32 opcode;
562 u8 mac_addr[ETH_ALEN];
563 u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */
564 u8 flags;
565} __attribute__ ((packed));
566
567#define UMAC_BAND_2GHZ 0
568#define UMAC_BAND_5GHZ 1
569
570#define UMAC_CHANNEL_WIDTH_20MHZ 0
571#define UMAC_CHANNEL_WIDTH_40MHZ 1
572
573struct iwm_umac_notif_bss_info {
574 struct iwm_umac_notif_wifi_if mlme_hdr;
575 __le32 type;
576 __le32 timestamp;
577 __le16 table_idx;
578 __le16 frame_len;
579 u8 band;
580 u8 channel;
581 s8 rssi;
582 u8 reserved;
583 u8 frame_buf[1];
584} __attribute__ ((packed));
585
586#define IWM_BSS_REMOVE_INDEX_MSK 0x0fff
587#define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00
588
589#define IWM_BSS_REMOVE_FLG_AGE 0x1000
590#define IWM_BSS_REMOVE_FLG_TIMEOUT 0x2000
591#define IWM_BSS_REMOVE_FLG_TABLE_FULL 0x4000
592
593struct iwm_umac_notif_bss_removed {
594 struct iwm_umac_notif_wifi_if mlme_hdr;
595 __le32 count;
596 __le16 entries[0];
597} __attribute__ ((packed));
598
599struct iwm_umac_notif_mgt_frame {
600 struct iwm_umac_notif_wifi_if mlme_hdr;
601 __le16 len;
602 u8 frame[1];
603} __attribute__ ((packed));
604
605struct iwm_umac_notif_alive {
606 struct iwm_umac_wifi_in_hdr hdr;
607 __le16 status;
608 __le16 reserved1;
609 struct iwm_fw_alive_hdr alive_data;
610 __le16 reserved2;
611 __le16 page_grp_count;
612 __le32 page_grp_state[IWM_MACS_OUT_GROUPS];
613} __attribute__ ((packed));
614
615struct iwm_umac_notif_init_complete {
616 __le16 status;
617 __le16 reserved;
618} __attribute__ ((packed));
619
620/* error categories */
621enum {
622 UMAC_SYS_ERR_CAT_NONE = 0,
623 UMAC_SYS_ERR_CAT_BOOT,
624 UMAC_SYS_ERR_CAT_UMAC,
625 UMAC_SYS_ERR_CAT_UAXM,
626 UMAC_SYS_ERR_CAT_LMAC,
627 UMAC_SYS_ERR_CAT_MAX
628};
629
630struct iwm_fw_error_hdr {
631 __le32 category;
632 __le32 status;
633 __le32 pc;
634 __le32 blink1;
635 __le32 blink2;
636 __le32 ilink1;
637 __le32 ilink2;
638 __le32 data1;
639 __le32 data2;
640 __le32 line_num;
641 __le32 umac_status;
642 __le32 lmac_status;
643 __le32 sdio_status;
644} __attribute__ ((packed));
645
646struct iwm_umac_notif_error {
647 struct iwm_umac_wifi_in_hdr hdr;
648 struct iwm_fw_error_hdr err;
649} __attribute__ ((packed));
650
651#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0
652#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff
653#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS 8
654#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED 0xffffff
655#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS 0
656#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED 0xffffff
657#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS 24
658#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED 0xf
659
660struct iwm_umac_notif_page_dealloc {
661 struct iwm_umac_wifi_in_hdr hdr;
662 __le32 changes;
663 __le32 grp_info[IWM_MACS_OUT_GROUPS];
664} __attribute__ ((packed));
665
666struct iwm_umac_notif_wifi_status {
667 struct iwm_umac_wifi_in_hdr hdr;
668 __le16 status;
669 __le16 reserved;
670} __attribute__ ((packed));
671
672struct iwm_umac_notif_rx_ticket {
673 struct iwm_umac_wifi_in_hdr hdr;
674 u8 num_tickets;
675 u8 reserved[3];
676 struct iwm_rx_ticket tickets[1];
677} __attribute__ ((packed));
678
679/* Tx/Rx rates window (number of max of last update window per second) */
680#define UMAC_NTF_RATE_SAMPLE_NR 4
681
682#define IWM_UMAC_MGMT_TID 8
683#define IWM_UMAC_TID_NR 8
684
685struct iwm_umac_notif_stats {
686 struct iwm_umac_wifi_in_hdr hdr;
687 __le32 flags;
688 __le32 timestamp;
689 __le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */
690 __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR];
691 __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR];
692 s32 rssi_dbm;
693 s32 noise_dbm;
694 __le32 supp_rates;
695 __le32 missed_beacons;
696 __le32 rx_beacons;
697 __le32 rx_dir_pkts;
698 __le32 rx_nondir_pkts;
699 __le32 rx_multicast;
700 __le32 rx_errors;
701 __le32 rx_drop_other_bssid;
702 __le32 rx_drop_decode;
703 __le32 rx_drop_reassembly;
704 __le32 rx_drop_bad_len;
705 __le32 rx_drop_overflow;
706 __le32 rx_drop_crc;
707 __le32 rx_drop_missed;
708 __le32 tx_dir_pkts;
709 __le32 tx_nondir_pkts;
710 __le32 tx_failure;
711 __le32 tx_errors;
712 __le32 tx_drop_max_retry;
713 __le32 tx_err_abort;
714 __le32 tx_err_carrier;
715 __le32 rx_bytes;
716 __le32 tx_bytes;
717 __le32 tx_power;
718 __le32 tx_max_power;
719 __le32 roam_threshold;
720 __le32 ap_assoc_nr;
721 __le32 scan_full;
722 __le32 scan_abort;
723 __le32 ap_nr;
724 __le32 roam_nr;
725 __le32 roam_missed_beacons;
726 __le32 roam_rssi;
727 __le32 roam_unassoc;
728 __le32 roam_deauth;
729 __le32 roam_ap_loadblance;
730} __attribute__ ((packed));
731
732/* WiFi interface wrapper header */
733struct iwm_umac_wifi_if {
734 u8 oid;
735 u8 flags;
736 __le16 buf_size;
737} __attribute__ ((packed));
738
739#define IWM_SEQ_NUM_HOST_MSK 0x0000
740#define IWM_SEQ_NUM_UMAC_MSK 0x4000
741#define IWM_SEQ_NUM_LMAC_MSK 0x8000
742#define IWM_SEQ_NUM_MSK 0xC000
743
744#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/wext.c b/drivers/net/wireless/iwmc3200wifi/wext.c
new file mode 100644
index 000000000000..584c94d0f399
--- /dev/null
+++ b/drivers/net/wireless/iwmc3200wifi/wext.c
@@ -0,0 +1,723 @@
1/*
2 * Intel Wireless Multicomm 3200 WiFi driver
3 *
4 * Copyright (C) 2009 Intel Corporation <ilw@linux.intel.com>
5 * Samuel Ortiz <samuel.ortiz@intel.com>
6 * Zhu Yi <yi.zhu@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License version
10 * 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 * 02110-1301, USA.
21 *
22 */
23
24#include <linux/kernel.h>
25#include <linux/netdevice.h>
26#include <linux/wireless.h>
27#include <linux/if_arp.h>
28#include <linux/etherdevice.h>
29#include <net/cfg80211.h>
30#include <net/iw_handler.h>
31
32#include "iwm.h"
33#include "umac.h"
34#include "commands.h"
35#include "debug.h"
36
37static struct iw_statistics *iwm_get_wireless_stats(struct net_device *dev)
38{
39 struct iwm_priv *iwm = ndev_to_iwm(dev);
40 struct iw_statistics *wstats = &iwm->wstats;
41
42 if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
43 memset(wstats, 0, sizeof(struct iw_statistics));
44 wstats->qual.updated = IW_QUAL_ALL_INVALID;
45 }
46
47 return wstats;
48}
49
50static int iwm_wext_siwfreq(struct net_device *dev,
51 struct iw_request_info *info,
52 struct iw_freq *freq, char *extra)
53{
54 struct iwm_priv *iwm = ndev_to_iwm(dev);
55
56 if (freq->flags == IW_FREQ_AUTO)
57 return 0;
58
59 /* frequency/channel can only be set in IBSS mode */
60 if (iwm->conf.mode != UMAC_MODE_IBSS)
61 return -EOPNOTSUPP;
62
63 return cfg80211_ibss_wext_siwfreq(dev, info, freq, extra);
64}
65
66static int iwm_wext_giwfreq(struct net_device *dev,
67 struct iw_request_info *info,
68 struct iw_freq *freq, char *extra)
69{
70 struct iwm_priv *iwm = ndev_to_iwm(dev);
71
72 if (iwm->conf.mode == UMAC_MODE_IBSS)
73 return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
74
75 freq->e = 0;
76 freq->m = iwm->channel;
77
78 return 0;
79}
80
81static int iwm_wext_siwap(struct net_device *dev, struct iw_request_info *info,
82 struct sockaddr *ap_addr, char *extra)
83{
84 struct iwm_priv *iwm = ndev_to_iwm(dev);
85
86 if (iwm->conf.mode == UMAC_MODE_IBSS)
87 return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
88
89 if (!test_bit(IWM_STATUS_READY, &iwm->status))
90 return -EIO;
91
92 if (is_zero_ether_addr(ap_addr->sa_data) ||
93 is_broadcast_ether_addr(ap_addr->sa_data)) {
94 IWM_DBG_WEXT(iwm, DBG, "clear mandatory bssid %pM\n",
95 iwm->umac_profile->bssid[0]);
96 memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN);
97 iwm->umac_profile->bss_num = 0;
98 } else {
99 IWM_DBG_WEXT(iwm, DBG, "add mandatory bssid %pM\n",
100 ap_addr->sa_data);
101 memcpy(&iwm->umac_profile->bssid[0], ap_addr->sa_data,
102 ETH_ALEN);
103 iwm->umac_profile->bss_num = 1;
104 }
105
106 if (iwm->umac_profile_active) {
107 if (!memcmp(&iwm->umac_profile->bssid[0], iwm->bssid, ETH_ALEN))
108 return 0;
109
110 iwm_invalidate_mlme_profile(iwm);
111 }
112
113 if (iwm->umac_profile->ssid.ssid_len)
114 return iwm_send_mlme_profile(iwm);
115
116 return 0;
117}
118
119static int iwm_wext_giwap(struct net_device *dev, struct iw_request_info *info,
120 struct sockaddr *ap_addr, char *extra)
121{
122 struct iwm_priv *iwm = ndev_to_iwm(dev);
123
124 switch (iwm->conf.mode) {
125 case UMAC_MODE_IBSS:
126 return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
127 case UMAC_MODE_BSS:
128 if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
129 ap_addr->sa_family = ARPHRD_ETHER;
130 memcpy(&ap_addr->sa_data, iwm->bssid, ETH_ALEN);
131 } else
132 memset(&ap_addr->sa_data, 0, ETH_ALEN);
133 break;
134 default:
135 return -EOPNOTSUPP;
136 }
137
138 return 0;
139}
140
141static int iwm_wext_siwessid(struct net_device *dev,
142 struct iw_request_info *info,
143 struct iw_point *data, char *ssid)
144{
145 struct iwm_priv *iwm = ndev_to_iwm(dev);
146 size_t len = data->length;
147 int ret;
148
149 if (iwm->conf.mode == UMAC_MODE_IBSS)
150 return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
151
152 if (!test_bit(IWM_STATUS_READY, &iwm->status))
153 return -EIO;
154
155 if (len > 0 && ssid[len - 1] == '\0')
156 len--;
157
158 if (iwm->umac_profile_active) {
159 if (iwm->umac_profile->ssid.ssid_len == len &&
160 !memcmp(iwm->umac_profile->ssid.ssid, ssid, len))
161 return 0;
162
163 ret = iwm_invalidate_mlme_profile(iwm);
164 if (ret < 0) {
165 IWM_ERR(iwm, "Couldn't invalidate profile\n");
166 return ret;
167 }
168 }
169
170 iwm->umac_profile->ssid.ssid_len = len;
171 memcpy(iwm->umac_profile->ssid.ssid, ssid, len);
172
173 return iwm_send_mlme_profile(iwm);
174}
175
176static int iwm_wext_giwessid(struct net_device *dev,
177 struct iw_request_info *info,
178 struct iw_point *data, char *ssid)
179{
180 struct iwm_priv *iwm = ndev_to_iwm(dev);
181
182 if (iwm->conf.mode == UMAC_MODE_IBSS)
183 return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
184
185 if (!test_bit(IWM_STATUS_READY, &iwm->status))
186 return -EIO;
187
188 data->length = iwm->umac_profile->ssid.ssid_len;
189 if (data->length) {
190 memcpy(ssid, iwm->umac_profile->ssid.ssid, data->length);
191 data->flags = 1;
192 } else
193 data->flags = 0;
194
195 return 0;
196}
197
198static struct iwm_key *
199iwm_key_init(struct iwm_priv *iwm, u8 key_idx, bool in_use,
200 struct iw_encode_ext *ext, u8 alg)
201{
202 struct iwm_key *key = &iwm->keys[key_idx];
203
204 memset(key, 0, sizeof(struct iwm_key));
205 memcpy(key->hdr.mac, ext->addr.sa_data, ETH_ALEN);
206 key->hdr.key_idx = key_idx;
207 if (is_broadcast_ether_addr(ext->addr.sa_data))
208 key->hdr.multicast = 1;
209
210 key->in_use = in_use;
211 key->flags = ext->ext_flags;
212 key->alg = alg;
213 key->key_len = ext->key_len;
214 memcpy(key->key, ext->key, ext->key_len);
215
216 return key;
217}
218
219static int iwm_wext_giwrate(struct net_device *dev,
220 struct iw_request_info *info,
221 struct iw_param *rate, char *extra)
222{
223 struct iwm_priv *iwm = ndev_to_iwm(dev);
224
225 rate->value = iwm->rate * 1000000;
226
227 return 0;
228}
229
230static int iwm_wext_siwencode(struct net_device *dev,
231 struct iw_request_info *info,
232 struct iw_point *erq, char *key_buf)
233{
234 struct iwm_priv *iwm = ndev_to_iwm(dev);
235 struct iwm_key *uninitialized_var(key);
236 int idx, i, uninitialized_var(alg), remove = 0, ret;
237
238 IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", erq->length);
239 IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
240
241 if (!iwm->umac_profile) {
242 IWM_ERR(iwm, "UMAC profile not allocated yet\n");
243 return -ENODEV;
244 }
245
246 if (erq->length == WLAN_KEY_LEN_WEP40) {
247 alg = UMAC_CIPHER_TYPE_WEP_40;
248 iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_40;
249 iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_40;
250 } else if (erq->length == WLAN_KEY_LEN_WEP104) {
251 alg = UMAC_CIPHER_TYPE_WEP_104;
252 iwm->umac_profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_WEP_104;
253 iwm->umac_profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_WEP_104;
254 }
255
256 if (erq->flags & IW_ENCODE_RESTRICTED)
257 iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
258 else
259 iwm->umac_profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN;
260
261 idx = erq->flags & IW_ENCODE_INDEX;
262 if (idx == 0) {
263 if (iwm->default_key)
264 for (i = 0; i < IWM_NUM_KEYS; i++) {
265 if (iwm->default_key == &iwm->keys[i]) {
266 idx = i;
267 break;
268 }
269 }
270 else
271 iwm->default_key = &iwm->keys[idx];
272 } else if (idx < 1 || idx > 4) {
273 return -EINVAL;
274 } else
275 idx--;
276
277 if (erq->flags & IW_ENCODE_DISABLED)
278 remove = 1;
279 else if (erq->length == 0) {
280 if (!iwm->keys[idx].in_use)
281 return -EINVAL;
282 iwm->default_key = &iwm->keys[idx];
283 }
284
285 if (erq->length) {
286 key = &iwm->keys[idx];
287 memset(key, 0, sizeof(struct iwm_key));
288 memset(key->hdr.mac, 0xff, ETH_ALEN);
289 key->hdr.key_idx = idx;
290 key->hdr.multicast = 1;
291 key->in_use = !remove;
292 key->alg = alg;
293 key->key_len = erq->length;
294 memcpy(key->key, key_buf, erq->length);
295
296 IWM_DBG_WEXT(iwm, DBG, "Setting key %d, default: %d\n",
297 idx, !!iwm->default_key);
298 }
299
300 if (remove) {
301 if ((erq->flags & IW_ENCODE_NOKEY) || (erq->length == 0)) {
302 int j;
303 for (j = 0; j < IWM_NUM_KEYS; j++)
304 if (iwm->keys[j].in_use) {
305 struct iwm_key *k = &iwm->keys[j];
306
307 k->in_use = 0;
308 ret = iwm_set_key(iwm, remove, 0, k);
309 if (ret < 0)
310 return ret;
311 }
312
313 iwm->umac_profile->sec.ucast_cipher =
314 UMAC_CIPHER_TYPE_NONE;
315 iwm->umac_profile->sec.mcast_cipher =
316 UMAC_CIPHER_TYPE_NONE;
317 iwm->umac_profile->sec.auth_type =
318 UMAC_AUTH_TYPE_OPEN;
319
320 return 0;
321 } else {
322 key->in_use = 0;
323 return iwm_set_key(iwm, remove, 0, key);
324 }
325 }
326
327 /*
328 * If we havent set a profile yet, we cant set keys.
329 * Keys will be pushed after we're associated.
330 */
331 if (!iwm->umac_profile_active)
332 return 0;
333
334 /*
335 * If there is a current active profile, but no
336 * default key, it's not worth trying to associate again.
337 */
338 if (!iwm->default_key)
339 return 0;
340
341 /*
342 * Here we have an active profile, but a key setting changed.
343 * We thus have to invalidate the current profile, and push the
344 * new one. Keys will be pushed when association takes place.
345 */
346 ret = iwm_invalidate_mlme_profile(iwm);
347 if (ret < 0) {
348 IWM_ERR(iwm, "Couldn't invalidate profile\n");
349 return ret;
350 }
351
352 return iwm_send_mlme_profile(iwm);
353}
354
355static int iwm_wext_giwencode(struct net_device *dev,
356 struct iw_request_info *info,
357 struct iw_point *erq, char *key)
358{
359 struct iwm_priv *iwm = ndev_to_iwm(dev);
360 int idx, i;
361
362 idx = erq->flags & IW_ENCODE_INDEX;
363 if (idx < 1 || idx > 4) {
364 idx = -1;
365 if (!iwm->default_key) {
366 erq->length = 0;
367 erq->flags |= IW_ENCODE_NOKEY;
368 return 0;
369 } else
370 for (i = 0; i < IWM_NUM_KEYS; i++) {
371 if (iwm->default_key == &iwm->keys[i]) {
372 idx = i;
373 break;
374 }
375 }
376 if (idx < 0)
377 return -EINVAL;
378 } else
379 idx--;
380
381 erq->flags = idx + 1;
382
383 if (!iwm->keys[idx].in_use) {
384 erq->length = 0;
385 erq->flags |= IW_ENCODE_DISABLED;
386 return 0;
387 }
388
389 memcpy(key, iwm->keys[idx].key,
390 min_t(int, erq->length, iwm->keys[idx].key_len));
391 erq->length = iwm->keys[idx].key_len;
392 erq->flags |= IW_ENCODE_ENABLED;
393
394 if (iwm->umac_profile->mode == UMAC_MODE_BSS) {
395 switch (iwm->umac_profile->sec.auth_type) {
396 case UMAC_AUTH_TYPE_OPEN:
397 erq->flags |= IW_ENCODE_OPEN;
398 break;
399 default:
400 erq->flags |= IW_ENCODE_RESTRICTED;
401 break;
402 }
403 }
404
405 return 0;
406}
407
408static int iwm_set_wpa_version(struct iwm_priv *iwm, u8 wpa_version)
409{
410 if (wpa_version & IW_AUTH_WPA_VERSION_WPA2)
411 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK;
412 else if (wpa_version & IW_AUTH_WPA_VERSION_WPA)
413 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_WPA_ON_MSK;
414 else
415 iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE;
416
417 return 0;
418}
419
420static int iwm_wext_siwpower(struct net_device *dev,
421 struct iw_request_info *info,
422 struct iw_param *wrq, char *extra)
423{
424 struct iwm_priv *iwm = ndev_to_iwm(dev);
425 u32 power_index;
426
427 if (wrq->disabled) {
428 power_index = IWM_POWER_INDEX_MIN;
429 goto set;
430 } else
431 power_index = IWM_POWER_INDEX_DEFAULT;
432
433 switch (wrq->flags & IW_POWER_MODE) {
434 case IW_POWER_ON:
435 case IW_POWER_MODE:
436 case IW_POWER_ALL_R:
437 break;
438 default:
439 return -EINVAL;
440 }
441
442 set:
443 if (power_index == iwm->conf.power_index)
444 return 0;
445
446 iwm->conf.power_index = power_index;
447
448 return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
449 CFG_POWER_INDEX, iwm->conf.power_index);
450}
451
452static int iwm_wext_giwpower(struct net_device *dev,
453 struct iw_request_info *info,
454 union iwreq_data *wrqu, char *extra)
455{
456 struct iwm_priv *iwm = ndev_to_iwm(dev);
457
458 wrqu->power.disabled = (iwm->conf.power_index == IWM_POWER_INDEX_MIN);
459
460 return 0;
461}
462
463static int iwm_set_key_mgt(struct iwm_priv *iwm, u8 key_mgt)
464{
465 u8 *auth_type = &iwm->umac_profile->sec.auth_type;
466
467 if (key_mgt == IW_AUTH_KEY_MGMT_802_1X)
468 *auth_type = UMAC_AUTH_TYPE_8021X;
469 else if (key_mgt == IW_AUTH_KEY_MGMT_PSK) {
470 if (iwm->umac_profile->sec.flags &
471 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK))
472 *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
473 else
474 *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
475 } else {
476 IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt);
477 return -EINVAL;
478 }
479
480 return 0;
481}
482
483static int iwm_set_cipher(struct iwm_priv *iwm, u8 cipher, u8 ucast)
484{
485 u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher :
486 &iwm->umac_profile->sec.mcast_cipher;
487
488 switch (cipher) {
489 case IW_AUTH_CIPHER_NONE:
490 *profile_cipher = UMAC_CIPHER_TYPE_NONE;
491 break;
492 case IW_AUTH_CIPHER_WEP40:
493 *profile_cipher = UMAC_CIPHER_TYPE_WEP_40;
494 break;
495 case IW_AUTH_CIPHER_TKIP:
496 *profile_cipher = UMAC_CIPHER_TYPE_TKIP;
497 break;
498 case IW_AUTH_CIPHER_CCMP:
499 *profile_cipher = UMAC_CIPHER_TYPE_CCMP;
500 break;
501 case IW_AUTH_CIPHER_WEP104:
502 *profile_cipher = UMAC_CIPHER_TYPE_WEP_104;
503 break;
504 default:
505 IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher);
506 return -ENOTSUPP;
507 }
508
509 return 0;
510}
511
512static int iwm_set_auth_alg(struct iwm_priv *iwm, u8 auth_alg)
513{
514 u8 *auth_type = &iwm->umac_profile->sec.auth_type;
515
516 switch (auth_alg) {
517 case IW_AUTH_ALG_OPEN_SYSTEM:
518 *auth_type = UMAC_AUTH_TYPE_OPEN;
519 break;
520 case IW_AUTH_ALG_SHARED_KEY:
521 if (iwm->umac_profile->sec.flags &
522 (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) {
523 if (*auth_type == UMAC_AUTH_TYPE_8021X)
524 return -EINVAL;
525 *auth_type = UMAC_AUTH_TYPE_RSNA_PSK;
526 } else {
527 *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK;
528 }
529 break;
530 case IW_AUTH_ALG_LEAP:
531 default:
532 IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", auth_alg);
533 return -ENOTSUPP;
534 }
535
536 return 0;
537}
538
539static int iwm_wext_siwauth(struct net_device *dev,
540 struct iw_request_info *info,
541 struct iw_param *data, char *extra)
542{
543 struct iwm_priv *iwm = ndev_to_iwm(dev);
544 int ret;
545
546 if ((data->flags) &
547 (IW_AUTH_WPA_VERSION | IW_AUTH_KEY_MGMT |
548 IW_AUTH_WPA_ENABLED | IW_AUTH_80211_AUTH_ALG)) {
549 /* We need to invalidate the current profile */
550 if (iwm->umac_profile_active) {
551 ret = iwm_invalidate_mlme_profile(iwm);
552 if (ret < 0) {
553 IWM_ERR(iwm, "Couldn't invalidate profile\n");
554 return ret;
555 }
556 }
557 }
558
559 switch (data->flags & IW_AUTH_INDEX) {
560 case IW_AUTH_WPA_VERSION:
561 return iwm_set_wpa_version(iwm, data->value);
562 break;
563 case IW_AUTH_CIPHER_PAIRWISE:
564 return iwm_set_cipher(iwm, data->value, 1);
565 break;
566 case IW_AUTH_CIPHER_GROUP:
567 return iwm_set_cipher(iwm, data->value, 0);
568 break;
569 case IW_AUTH_KEY_MGMT:
570 return iwm_set_key_mgt(iwm, data->value);
571 break;
572 case IW_AUTH_80211_AUTH_ALG:
573 return iwm_set_auth_alg(iwm, data->value);
574 break;
575 default:
576 return -ENOTSUPP;
577 }
578
579 return 0;
580}
581
582static int iwm_wext_giwauth(struct net_device *dev,
583 struct iw_request_info *info,
584 struct iw_param *data, char *extra)
585{
586 return 0;
587}
588
589static int iwm_wext_siwencodeext(struct net_device *dev,
590 struct iw_request_info *info,
591 struct iw_point *erq, char *extra)
592{
593 struct iwm_priv *iwm = ndev_to_iwm(dev);
594 struct iwm_key *key;
595 struct iw_encode_ext *ext = (struct iw_encode_ext *) extra;
596 int uninitialized_var(alg), idx, i, remove = 0;
597
598 IWM_DBG_WEXT(iwm, DBG, "alg: 0x%x\n", ext->alg);
599 IWM_DBG_WEXT(iwm, DBG, "key len: %d\n", ext->key_len);
600 IWM_DBG_WEXT(iwm, DBG, "ext_flags: 0x%x\n", ext->ext_flags);
601 IWM_DBG_WEXT(iwm, DBG, "flags: 0x%x\n", erq->flags);
602 IWM_DBG_WEXT(iwm, DBG, "length: 0x%x\n", erq->length);
603
604 switch (ext->alg) {
605 case IW_ENCODE_ALG_NONE:
606 remove = 1;
607 break;
608 case IW_ENCODE_ALG_WEP:
609 if (ext->key_len == WLAN_KEY_LEN_WEP40)
610 alg = UMAC_CIPHER_TYPE_WEP_40;
611 else if (ext->key_len == WLAN_KEY_LEN_WEP104)
612 alg = UMAC_CIPHER_TYPE_WEP_104;
613 else {
614 IWM_ERR(iwm, "Invalid key length: %d\n", ext->key_len);
615 return -EINVAL;
616 }
617
618 break;
619 case IW_ENCODE_ALG_TKIP:
620 alg = UMAC_CIPHER_TYPE_TKIP;
621 break;
622 case IW_ENCODE_ALG_CCMP:
623 alg = UMAC_CIPHER_TYPE_CCMP;
624 break;
625 default:
626 return -EOPNOTSUPP;
627 }
628
629 idx = erq->flags & IW_ENCODE_INDEX;
630
631 if (idx == 0) {
632 if (iwm->default_key)
633 for (i = 0; i < IWM_NUM_KEYS; i++) {
634 if (iwm->default_key == &iwm->keys[i]) {
635 idx = i;
636 break;
637 }
638 }
639 } else if (idx < 1 || idx > 4) {
640 return -EINVAL;
641 } else
642 idx--;
643
644 if (erq->flags & IW_ENCODE_DISABLED)
645 remove = 1;
646 else if ((erq->length == 0) ||
647 (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) {
648 iwm->default_key = &iwm->keys[idx];
649 if (iwm->umac_profile_active && ext->alg == IW_ENCODE_ALG_WEP)
650 return iwm_set_tx_key(iwm, idx);
651 }
652
653 key = iwm_key_init(iwm, idx, !remove, ext, alg);
654
655 return iwm_set_key(iwm, remove, !iwm->default_key, key);
656}
657
658static const iw_handler iwm_handlers[] =
659{
660 (iw_handler) NULL, /* SIOCSIWCOMMIT */
661 (iw_handler) cfg80211_wext_giwname, /* SIOCGIWNAME */
662 (iw_handler) NULL, /* SIOCSIWNWID */
663 (iw_handler) NULL, /* SIOCGIWNWID */
664 (iw_handler) iwm_wext_siwfreq, /* SIOCSIWFREQ */
665 (iw_handler) iwm_wext_giwfreq, /* SIOCGIWFREQ */
666 (iw_handler) cfg80211_wext_siwmode, /* SIOCSIWMODE */
667 (iw_handler) cfg80211_wext_giwmode, /* SIOCGIWMODE */
668 (iw_handler) NULL, /* SIOCSIWSENS */
669 (iw_handler) NULL, /* SIOCGIWSENS */
670 (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */
671 (iw_handler) cfg80211_wext_giwrange, /* SIOCGIWRANGE */
672 (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
673 (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
674 (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
675 (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
676 (iw_handler) NULL, /* SIOCSIWSPY */
677 (iw_handler) NULL, /* SIOCGIWSPY */
678 (iw_handler) NULL, /* SIOCSIWTHRSPY */
679 (iw_handler) NULL, /* SIOCGIWTHRSPY */
680 (iw_handler) iwm_wext_siwap, /* SIOCSIWAP */
681 (iw_handler) iwm_wext_giwap, /* SIOCGIWAP */
682 (iw_handler) NULL, /* SIOCSIWMLME */
683 (iw_handler) NULL, /* SIOCGIWAPLIST */
684 (iw_handler) cfg80211_wext_siwscan, /* SIOCSIWSCAN */
685 (iw_handler) cfg80211_wext_giwscan, /* SIOCGIWSCAN */
686 (iw_handler) iwm_wext_siwessid, /* SIOCSIWESSID */
687 (iw_handler) iwm_wext_giwessid, /* SIOCGIWESSID */
688 (iw_handler) NULL, /* SIOCSIWNICKN */
689 (iw_handler) NULL, /* SIOCGIWNICKN */
690 (iw_handler) NULL, /* -- hole -- */
691 (iw_handler) NULL, /* -- hole -- */
692 (iw_handler) NULL, /* SIOCSIWRATE */
693 (iw_handler) iwm_wext_giwrate, /* SIOCGIWRATE */
694 (iw_handler) cfg80211_wext_siwrts, /* SIOCSIWRTS */
695 (iw_handler) cfg80211_wext_giwrts, /* SIOCGIWRTS */
696 (iw_handler) cfg80211_wext_siwfrag, /* SIOCSIWFRAG */
697 (iw_handler) cfg80211_wext_giwfrag, /* SIOCGIWFRAG */
698 (iw_handler) NULL, /* SIOCSIWTXPOW */
699 (iw_handler) NULL, /* SIOCGIWTXPOW */
700 (iw_handler) NULL, /* SIOCSIWRETRY */
701 (iw_handler) NULL, /* SIOCGIWRETRY */
702 (iw_handler) iwm_wext_siwencode, /* SIOCSIWENCODE */
703 (iw_handler) iwm_wext_giwencode, /* SIOCGIWENCODE */
704 (iw_handler) iwm_wext_siwpower, /* SIOCSIWPOWER */
705 (iw_handler) iwm_wext_giwpower, /* SIOCGIWPOWER */
706 (iw_handler) NULL, /* -- hole -- */
707 (iw_handler) NULL, /* -- hole -- */
708 (iw_handler) NULL, /* SIOCSIWGENIE */
709 (iw_handler) NULL, /* SIOCGIWGENIE */
710 (iw_handler) iwm_wext_siwauth, /* SIOCSIWAUTH */
711 (iw_handler) iwm_wext_giwauth, /* SIOCGIWAUTH */
712 (iw_handler) iwm_wext_siwencodeext, /* SIOCSIWENCODEEXT */
713 (iw_handler) NULL, /* SIOCGIWENCODEEXT */
714 (iw_handler) NULL, /* SIOCSIWPMKSA */
715 (iw_handler) NULL, /* -- hole -- */
716};
717
718const struct iw_handler_def iwm_iw_handler_def = {
719 .num_standard = ARRAY_SIZE(iwm_handlers),
720 .standard = (iw_handler *) iwm_handlers,
721 .get_wireless_stats = iwm_get_wireless_stats,
722};
723
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index cbaafa653b6a..a4455ec7c354 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -321,6 +321,8 @@ struct lbs_private {
321 321
322 u32 monitormode; 322 u32 monitormode;
323 u8 fw_ready; 323 u8 fw_ready;
324 u8 fn_init_required;
325 u8 fn_shutdown_required;
324}; 326};
325 327
326extern struct cmd_confirm_sleep confirm_sleep; 328extern struct cmd_confirm_sleep confirm_sleep;
diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
index 8ff8ac9d817e..fe8f0cb737bc 100644
--- a/drivers/net/wireless/libertas/host.h
+++ b/drivers/net/wireless/libertas/host.h
@@ -86,6 +86,8 @@
86#define CMD_MESH_CONFIG_OLD 0x00a3 86#define CMD_MESH_CONFIG_OLD 0x00a3
87#define CMD_MESH_CONFIG 0x00ac 87#define CMD_MESH_CONFIG 0x00ac
88#define CMD_SET_BOOT2_VER 0x00a5 88#define CMD_SET_BOOT2_VER 0x00a5
89#define CMD_FUNC_INIT 0x00a9
90#define CMD_FUNC_SHUTDOWN 0x00aa
89#define CMD_802_11_BEACON_CTRL 0x00b0 91#define CMD_802_11_BEACON_CTRL 0x00b0
90 92
91/* For the IEEE Power Save */ 93/* For the IEEE Power Save */
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 55864c10f9f1..a7e3fc119b70 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -61,26 +61,30 @@ struct if_sdio_model {
61 int model; 61 int model;
62 const char *helper; 62 const char *helper;
63 const char *firmware; 63 const char *firmware;
64 struct if_sdio_card *card;
64}; 65};
65 66
66static struct if_sdio_model if_sdio_models[] = { 67static struct if_sdio_model if_sdio_models[] = {
67 { 68 {
68 /* 8385 */ 69 /* 8385 */
69 .model = 0x04, 70 .model = IF_SDIO_MODEL_8385,
70 .helper = "sd8385_helper.bin", 71 .helper = "sd8385_helper.bin",
71 .firmware = "sd8385.bin", 72 .firmware = "sd8385.bin",
73 .card = NULL,
72 }, 74 },
73 { 75 {
74 /* 8686 */ 76 /* 8686 */
75 .model = 0x0B, 77 .model = IF_SDIO_MODEL_8686,
76 .helper = "sd8686_helper.bin", 78 .helper = "sd8686_helper.bin",
77 .firmware = "sd8686.bin", 79 .firmware = "sd8686.bin",
80 .card = NULL,
78 }, 81 },
79 { 82 {
80 /* 8688 */ 83 /* 8688 */
81 .model = 0x10, 84 .model = IF_SDIO_MODEL_8688,
82 .helper = "sd8688_helper.bin", 85 .helper = "sd8688_helper.bin",
83 .firmware = "sd8688.bin", 86 .firmware = "sd8688.bin",
87 .card = NULL,
84 }, 88 },
85}; 89};
86 90
@@ -96,6 +100,7 @@ struct if_sdio_card {
96 100
97 int model; 101 int model;
98 unsigned long ioport; 102 unsigned long ioport;
103 unsigned int scratch_reg;
99 104
100 const char *helper; 105 const char *helper;
101 const char *firmware; 106 const char *firmware;
@@ -107,25 +112,29 @@ struct if_sdio_card {
107 112
108 struct workqueue_struct *workqueue; 113 struct workqueue_struct *workqueue;
109 struct work_struct packet_worker; 114 struct work_struct packet_worker;
115
116 u8 rx_unit;
110}; 117};
111 118
112/********************************************************************/ 119/********************************************************************/
113/* I/O */ 120/* I/O */
114/********************************************************************/ 121/********************************************************************/
115 122
123/*
124 * For SD8385/SD8686, this function reads firmware status after
125 * the image is downloaded, or reads RX packet length when
126 * interrupt (with IF_SDIO_H_INT_UPLD bit set) is received.
127 * For SD8688, this function reads firmware status only.
128 */
116static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) 129static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
117{ 130{
118 int ret, reg; 131 int ret;
119 u16 scratch; 132 u16 scratch;
120 133
121 if (card->model == 0x04) 134 scratch = sdio_readb(card->func, card->scratch_reg, &ret);
122 reg = IF_SDIO_SCRATCH_OLD;
123 else
124 reg = IF_SDIO_SCRATCH;
125
126 scratch = sdio_readb(card->func, reg, &ret);
127 if (!ret) 135 if (!ret)
128 scratch |= sdio_readb(card->func, reg + 1, &ret) << 8; 136 scratch |= sdio_readb(card->func, card->scratch_reg + 1,
137 &ret) << 8;
129 138
130 if (err) 139 if (err)
131 *err = ret; 140 *err = ret;
@@ -136,6 +145,46 @@ static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err)
136 return scratch; 145 return scratch;
137} 146}
138 147
148static u8 if_sdio_read_rx_unit(struct if_sdio_card *card)
149{
150 int ret;
151 u8 rx_unit;
152
153 rx_unit = sdio_readb(card->func, IF_SDIO_RX_UNIT, &ret);
154
155 if (ret)
156 rx_unit = 0;
157
158 return rx_unit;
159}
160
161static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err)
162{
163 int ret;
164 u16 rx_len;
165
166 switch (card->model) {
167 case IF_SDIO_MODEL_8385:
168 case IF_SDIO_MODEL_8686:
169 rx_len = if_sdio_read_scratch(card, &ret);
170 break;
171 case IF_SDIO_MODEL_8688:
172 default: /* for newer chipsets */
173 rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret);
174 if (!ret)
175 rx_len <<= card->rx_unit;
176 else
177 rx_len = 0xffff; /* invalid length */
178
179 break;
180 }
181
182 if (err)
183 *err = ret;
184
185 return rx_len;
186}
187
139static int if_sdio_handle_cmd(struct if_sdio_card *card, 188static int if_sdio_handle_cmd(struct if_sdio_card *card,
140 u8 *buffer, unsigned size) 189 u8 *buffer, unsigned size)
141{ 190{
@@ -216,7 +265,7 @@ static int if_sdio_handle_event(struct if_sdio_card *card,
216 265
217 lbs_deb_enter(LBS_DEB_SDIO); 266 lbs_deb_enter(LBS_DEB_SDIO);
218 267
219 if (card->model == 0x04) { 268 if (card->model == IF_SDIO_MODEL_8385) {
220 event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); 269 event = sdio_readb(card->func, IF_SDIO_EVENT, &ret);
221 if (ret) 270 if (ret)
222 goto out; 271 goto out;
@@ -254,7 +303,7 @@ static int if_sdio_card_to_host(struct if_sdio_card *card)
254 303
255 lbs_deb_enter(LBS_DEB_SDIO); 304 lbs_deb_enter(LBS_DEB_SDIO);
256 305
257 size = if_sdio_read_scratch(card, &ret); 306 size = if_sdio_read_rx_len(card, &ret);
258 if (ret) 307 if (ret)
259 goto out; 308 goto out;
260 309
@@ -497,7 +546,6 @@ static int if_sdio_prog_helper(struct if_sdio_card *card)
497 ret = 0; 546 ret = 0;
498 547
499release: 548release:
500 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
501 sdio_release_host(card->func); 549 sdio_release_host(card->func);
502 kfree(chunk_buffer); 550 kfree(chunk_buffer);
503release_fw: 551release_fw:
@@ -633,7 +681,6 @@ static int if_sdio_prog_real(struct if_sdio_card *card)
633 ret = 0; 681 ret = 0;
634 682
635release: 683release:
636 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
637 sdio_release_host(card->func); 684 sdio_release_host(card->func);
638 kfree(chunk_buffer); 685 kfree(chunk_buffer);
639release_fw: 686release_fw:
@@ -662,6 +709,8 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
662 if (ret) 709 if (ret)
663 goto out; 710 goto out;
664 711
712 lbs_deb_sdio("firmware status = %#x\n", scratch);
713
665 if (scratch == IF_SDIO_FIRMWARE_OK) { 714 if (scratch == IF_SDIO_FIRMWARE_OK) {
666 lbs_deb_sdio("firmware already loaded\n"); 715 lbs_deb_sdio("firmware already loaded\n");
667 goto success; 716 goto success;
@@ -676,6 +725,9 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card)
676 goto out; 725 goto out;
677 726
678success: 727success:
728 sdio_claim_host(card->func);
729 sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE);
730 sdio_release_host(card->func);
679 ret = 0; 731 ret = 0;
680 732
681out: 733out:
@@ -829,10 +881,10 @@ static int if_sdio_probe(struct sdio_func *func,
829 if (sscanf(func->card->info[i], 881 if (sscanf(func->card->info[i],
830 "ID: %x", &model) == 1) 882 "ID: %x", &model) == 1)
831 break; 883 break;
832 if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { 884 if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) {
833 model = 4; 885 model = IF_SDIO_MODEL_8385;
834 break; 886 break;
835 } 887 }
836 } 888 }
837 889
838 if (i == func->card->num_info) { 890 if (i == func->card->num_info) {
@@ -846,6 +898,20 @@ static int if_sdio_probe(struct sdio_func *func,
846 898
847 card->func = func; 899 card->func = func;
848 card->model = model; 900 card->model = model;
901
902 switch (card->model) {
903 case IF_SDIO_MODEL_8385:
904 card->scratch_reg = IF_SDIO_SCRATCH_OLD;
905 break;
906 case IF_SDIO_MODEL_8686:
907 card->scratch_reg = IF_SDIO_SCRATCH;
908 break;
909 case IF_SDIO_MODEL_8688:
910 default: /* for newer chipsets */
911 card->scratch_reg = IF_SDIO_FW_STATUS;
912 break;
913 }
914
849 spin_lock_init(&card->lock); 915 spin_lock_init(&card->lock);
850 card->workqueue = create_workqueue("libertas_sdio"); 916 card->workqueue = create_workqueue("libertas_sdio");
851 INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); 917 INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker);
@@ -861,6 +927,8 @@ static int if_sdio_probe(struct sdio_func *func,
861 goto free; 927 goto free;
862 } 928 }
863 929
930 if_sdio_models[i].card = card;
931
864 card->helper = if_sdio_models[i].helper; 932 card->helper = if_sdio_models[i].helper;
865 card->firmware = if_sdio_models[i].firmware; 933 card->firmware = if_sdio_models[i].firmware;
866 934
@@ -923,15 +991,32 @@ static int if_sdio_probe(struct sdio_func *func,
923 991
924 priv->fw_ready = 1; 992 priv->fw_ready = 1;
925 993
994 sdio_claim_host(func);
995
996 /*
997 * Get rx_unit if the chip is SD8688 or newer.
998 * SD8385 & SD8686 do not have rx_unit.
999 */
1000 if ((card->model != IF_SDIO_MODEL_8385)
1001 && (card->model != IF_SDIO_MODEL_8686))
1002 card->rx_unit = if_sdio_read_rx_unit(card);
1003 else
1004 card->rx_unit = 0;
1005
926 /* 1006 /*
927 * Enable interrupts now that everything is set up 1007 * Enable interrupts now that everything is set up
928 */ 1008 */
929 sdio_claim_host(func);
930 sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret); 1009 sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
931 sdio_release_host(func); 1010 sdio_release_host(func);
932 if (ret) 1011 if (ret)
933 goto reclaim; 1012 goto reclaim;
934 1013
1014 /*
1015 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
1016 */
1017 priv->fn_init_required =
1018 (card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
1019
935 ret = lbs_start_card(priv); 1020 ret = lbs_start_card(priv);
936 if (ret) 1021 if (ret)
937 goto err_activate_card; 1022 goto err_activate_card;
@@ -972,23 +1057,30 @@ static void if_sdio_remove(struct sdio_func *func)
972{ 1057{
973 struct if_sdio_card *card; 1058 struct if_sdio_card *card;
974 struct if_sdio_packet *packet; 1059 struct if_sdio_packet *packet;
1060 int ret;
975 1061
976 lbs_deb_enter(LBS_DEB_SDIO); 1062 lbs_deb_enter(LBS_DEB_SDIO);
977 1063
978 card = sdio_get_drvdata(func); 1064 card = sdio_get_drvdata(func);
979 1065
1066 lbs_stop_card(card->priv);
1067
980 card->priv->surpriseremoved = 1; 1068 card->priv->surpriseremoved = 1;
981 1069
982 lbs_deb_sdio("call remove card\n"); 1070 lbs_deb_sdio("call remove card\n");
983 lbs_stop_card(card->priv);
984 lbs_remove_card(card->priv); 1071 lbs_remove_card(card->priv);
985 1072
986 flush_workqueue(card->workqueue); 1073 flush_workqueue(card->workqueue);
987 destroy_workqueue(card->workqueue); 1074 destroy_workqueue(card->workqueue);
988 1075
989 sdio_claim_host(func); 1076 sdio_claim_host(func);
1077
1078 /* Disable interrupts */
1079 sdio_writeb(func, 0x00, IF_SDIO_H_INT_MASK, &ret);
1080
990 sdio_release_irq(func); 1081 sdio_release_irq(func);
991 sdio_disable_func(func); 1082 sdio_disable_func(func);
1083
992 sdio_release_host(func); 1084 sdio_release_host(func);
993 1085
994 while (card->packets) { 1086 while (card->packets) {
@@ -1031,8 +1123,23 @@ static int __init if_sdio_init_module(void)
1031 1123
1032static void __exit if_sdio_exit_module(void) 1124static void __exit if_sdio_exit_module(void)
1033{ 1125{
1126 int i;
1127 struct if_sdio_card *card;
1128
1034 lbs_deb_enter(LBS_DEB_SDIO); 1129 lbs_deb_enter(LBS_DEB_SDIO);
1035 1130
1131 for (i = 0; i < ARRAY_SIZE(if_sdio_models); i++) {
1132 card = if_sdio_models[i].card;
1133
1134 /*
1135 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
1136 * multiple functions
1137 */
1138 if (card && card->priv)
1139 card->priv->fn_shutdown_required =
1140 (card->model == IF_SDIO_MODEL_8688) ? 1 : 0;
1141 }
1142
1036 sdio_unregister_driver(&if_sdio_driver); 1143 sdio_unregister_driver(&if_sdio_driver);
1037 1144
1038 lbs_deb_leave(LBS_DEB_SDIO); 1145 lbs_deb_leave(LBS_DEB_SDIO);
diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h
index 37ada2c29aa9..60c9b2fcef03 100644
--- a/drivers/net/wireless/libertas/if_sdio.h
+++ b/drivers/net/wireless/libertas/if_sdio.h
@@ -12,6 +12,10 @@
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
15#define IF_SDIO_IOPORT 0x00 19#define IF_SDIO_IOPORT 0x00
16 20
17#define IF_SDIO_H_INT_MASK 0x04 21#define IF_SDIO_H_INT_MASK 0x04
@@ -38,8 +42,12 @@
38 42
39#define IF_SDIO_SCRATCH 0x34 43#define IF_SDIO_SCRATCH 0x34
40#define IF_SDIO_SCRATCH_OLD 0x80fe 44#define IF_SDIO_SCRATCH_OLD 0x80fe
45#define IF_SDIO_FW_STATUS 0x40
41#define IF_SDIO_FIRMWARE_OK 0xfedc 46#define IF_SDIO_FIRMWARE_OK 0xfedc
42 47
48#define IF_SDIO_RX_LEN 0x42
49#define IF_SDIO_RX_UNIT 0x43
50
43#define IF_SDIO_EVENT 0x80fc 51#define IF_SDIO_EVENT 0x80fc
44 52
45#define IF_SDIO_BLOCK_SIZE 256 53#define IF_SDIO_BLOCK_SIZE 256
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index dccd01fd1f10..5fa55fe1f860 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -814,6 +814,13 @@ static void if_spi_e2h(struct if_spi_card *card)
814 if (err) 814 if (err)
815 goto out; 815 goto out;
816 816
817 /* re-enable the card event interrupt */
818 spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG,
819 ~IF_SPI_HICU_CARD_EVENT);
820
821 /* generate a card interrupt */
822 spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT);
823
817 spin_lock_irqsave(&priv->driver_lock, flags); 824 spin_lock_irqsave(&priv->driver_lock, flags);
818 lbs_queue_event(priv, cause & 0xff); 825 lbs_queue_event(priv, cause & 0xff);
819 spin_unlock_irqrestore(&priv->driver_lock, flags); 826 spin_unlock_irqrestore(&priv->driver_lock, flags);
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 89575e448015..a58a12352672 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -1002,9 +1002,17 @@ static int lbs_setup_firmware(struct lbs_private *priv)
1002{ 1002{
1003 int ret = -1; 1003 int ret = -1;
1004 s16 curlevel = 0, minlevel = 0, maxlevel = 0; 1004 s16 curlevel = 0, minlevel = 0, maxlevel = 0;
1005 struct cmd_header cmd;
1005 1006
1006 lbs_deb_enter(LBS_DEB_FW); 1007 lbs_deb_enter(LBS_DEB_FW);
1007 1008
1009 if (priv->fn_init_required) {
1010 memset(&cmd, 0, sizeof(cmd));
1011 if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
1012 lbs_cmd_copyback, (unsigned long) &cmd))
1013 lbs_pr_alert("CMD_FUNC_INIT command failed\n");
1014 }
1015
1008 /* Read MAC address from firmware */ 1016 /* Read MAC address from firmware */
1009 memset(priv->current_addr, 0xff, ETH_ALEN); 1017 memset(priv->current_addr, 0xff, ETH_ALEN);
1010 ret = lbs_update_hw_spec(priv); 1018 ret = lbs_update_hw_spec(priv);
@@ -1192,6 +1200,9 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1192 priv->mesh_open = 0; 1200 priv->mesh_open = 0;
1193 priv->infra_open = 0; 1201 priv->infra_open = 0;
1194 1202
1203 priv->fn_init_required = 0;
1204 priv->fn_shutdown_required = 0;
1205
1195 /* Setup the OS Interface to our functions */ 1206 /* Setup the OS Interface to our functions */
1196 dev->netdev_ops = &lbs_netdev_ops; 1207 dev->netdev_ops = &lbs_netdev_ops;
1197 dev->watchdog_timeo = 5 * HZ; 1208 dev->watchdog_timeo = 5 * HZ;
@@ -1373,11 +1384,20 @@ void lbs_stop_card(struct lbs_private *priv)
1373 struct net_device *dev; 1384 struct net_device *dev;
1374 struct cmd_ctrl_node *cmdnode; 1385 struct cmd_ctrl_node *cmdnode;
1375 unsigned long flags; 1386 unsigned long flags;
1387 struct cmd_header cmd;
1376 1388
1377 lbs_deb_enter(LBS_DEB_MAIN); 1389 lbs_deb_enter(LBS_DEB_MAIN);
1378 1390
1379 if (!priv) 1391 if (!priv)
1380 goto out; 1392 goto out;
1393
1394 if (priv->fn_shutdown_required) {
1395 memset(&cmd, 0, sizeof(cmd));
1396 if (__lbs_cmd(priv, CMD_FUNC_SHUTDOWN, &cmd, sizeof(cmd),
1397 lbs_cmd_copyback, (unsigned long) &cmd))
1398 lbs_pr_alert("CMD_FUNC_SHUTDOWN command failed\n");
1399 }
1400
1381 dev = priv->dev; 1401 dev = priv->dev;
1382 1402
1383 netif_stop_queue(dev); 1403 netif_stop_queue(dev);
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 61a4ad7cc1c2..574b8bb121e1 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -291,6 +291,14 @@ struct mac80211_hwsim_data {
291 bool ps_poll_pending; 291 bool ps_poll_pending;
292 struct dentry *debugfs; 292 struct dentry *debugfs;
293 struct dentry *debugfs_ps; 293 struct dentry *debugfs_ps;
294
295 /*
296 * Only radios in the same group can communicate together (the
297 * channel has to match too). Each bit represents a group. A
298 * radio can be in more then one group.
299 */
300 u64 group;
301 struct dentry *debugfs_group;
294}; 302};
295 303
296 304
@@ -412,7 +420,8 @@ static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
412 420
413 if (!data2->started || !data2->radio_enabled || 421 if (!data2->started || !data2->radio_enabled ||
414 !hwsim_ps_rx_ok(data2, skb) || 422 !hwsim_ps_rx_ok(data2, skb) ||
415 data->channel->center_freq != data2->channel->center_freq) 423 data->channel->center_freq != data2->channel->center_freq ||
424 !(data->group & data2->group))
416 continue; 425 continue;
417 426
418 nskb = skb_copy(skb, GFP_ATOMIC); 427 nskb = skb_copy(skb, GFP_ATOMIC);
@@ -720,6 +729,7 @@ static void mac80211_hwsim_free(void)
720 spin_unlock_bh(&hwsim_radio_lock); 729 spin_unlock_bh(&hwsim_radio_lock);
721 730
722 list_for_each_entry(data, &tmplist, list) { 731 list_for_each_entry(data, &tmplist, list) {
732 debugfs_remove(data->debugfs_group);
723 debugfs_remove(data->debugfs_ps); 733 debugfs_remove(data->debugfs_ps);
724 debugfs_remove(data->debugfs); 734 debugfs_remove(data->debugfs);
725 ieee80211_unregister_hw(data->hw); 735 ieee80211_unregister_hw(data->hw);
@@ -872,6 +882,24 @@ DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
872 "%llu\n"); 882 "%llu\n");
873 883
874 884
885static int hwsim_fops_group_read(void *dat, u64 *val)
886{
887 struct mac80211_hwsim_data *data = dat;
888 *val = data->group;
889 return 0;
890}
891
892static int hwsim_fops_group_write(void *dat, u64 val)
893{
894 struct mac80211_hwsim_data *data = dat;
895 data->group = val;
896 return 0;
897}
898
899DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group,
900 hwsim_fops_group_read, hwsim_fops_group_write,
901 "%llx\n");
902
875static int __init init_mac80211_hwsim(void) 903static int __init init_mac80211_hwsim(void)
876{ 904{
877 int i, err = 0; 905 int i, err = 0;
@@ -976,6 +1004,8 @@ static int __init init_mac80211_hwsim(void)
976 1004
977 hw->wiphy->bands[band] = sband; 1005 hw->wiphy->bands[band] = sband;
978 } 1006 }
1007 /* By default all radios are belonging to the first group */
1008 data->group = 1;
979 1009
980 /* Work to be done prior to ieee80211_register_hw() */ 1010 /* Work to be done prior to ieee80211_register_hw() */
981 switch (regtest) { 1011 switch (regtest) {
@@ -1100,6 +1130,9 @@ static int __init init_mac80211_hwsim(void)
1100 data->debugfs_ps = debugfs_create_file("ps", 0666, 1130 data->debugfs_ps = debugfs_create_file("ps", 0666,
1101 data->debugfs, data, 1131 data->debugfs, data,
1102 &hwsim_fops_ps); 1132 &hwsim_fops_ps);
1133 data->debugfs_group = debugfs_create_file("group", 0666,
1134 data->debugfs, data,
1135 &hwsim_fops_group);
1103 1136
1104 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, 1137 setup_timer(&data->beacon_timer, mac80211_hwsim_beacon,
1105 (unsigned long) hw); 1138 (unsigned long) hw);
diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c
index 59a5e778bb08..83116baeb110 100644
--- a/drivers/net/wireless/p54/p54spi.c
+++ b/drivers/net/wireless/p54/p54spi.c
@@ -96,7 +96,7 @@ static void p54spi_spi_write(struct p54s_priv *priv, u8 address,
96 spi_message_add_tail(&t[0], &m); 96 spi_message_add_tail(&t[0], &m);
97 97
98 t[1].tx_buf = buf; 98 t[1].tx_buf = buf;
99 t[1].len = len; 99 t[1].len = len & ~1;
100 spi_message_add_tail(&t[1], &m); 100 spi_message_add_tail(&t[1], &m);
101 101
102 if (len % 2) { 102 if (len % 2) {
@@ -172,8 +172,6 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
172 __le32 buffer = p54spi_read32(priv, reg); 172 __le32 buffer = p54spi_read32(priv, reg);
173 if ((buffer & bits) == bits) 173 if ((buffer & bits) == bits)
174 return 1; 174 return 1;
175
176 msleep(0);
177 } 175 }
178 return 0; 176 return 0;
179} 177}
@@ -181,9 +179,6 @@ static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, __le32 bits)
181static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base, 179static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
182 const void *buf, size_t len) 180 const void *buf, size_t len)
183{ 181{
184 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
185 cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
186
187 if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, 182 if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL,
188 cpu_to_le32(HOST_ALLOWED))) { 183 cpu_to_le32(HOST_ALLOWED))) {
189 dev_err(&priv->spi->dev, "spi_write_dma not allowed " 184 dev_err(&priv->spi->dev, "spi_write_dma not allowed "
@@ -191,6 +186,9 @@ static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base,
191 return -EAGAIN; 186 return -EAGAIN;
192 } 187 }
193 188
189 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL,
190 cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE));
191
194 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len)); 192 p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len));
195 p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base); 193 p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base);
196 p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len); 194 p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len);
@@ -327,7 +325,7 @@ static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val)
327 p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val)); 325 p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val));
328} 326}
329 327
330static void p54spi_wakeup(struct p54s_priv *priv) 328static int p54spi_wakeup(struct p54s_priv *priv)
331{ 329{
332 /* wake the chip */ 330 /* wake the chip */
333 p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, 331 p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS,
@@ -337,13 +335,11 @@ static void p54spi_wakeup(struct p54s_priv *priv)
337 if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, 335 if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
338 cpu_to_le32(SPI_HOST_INT_READY))) { 336 cpu_to_le32(SPI_HOST_INT_READY))) {
339 dev_err(&priv->spi->dev, "INT_READY timeout\n"); 337 dev_err(&priv->spi->dev, "INT_READY timeout\n");
340 goto out; 338 return -EBUSY;
341 } 339 }
342 340
343 p54spi_int_ack(priv, SPI_HOST_INT_READY); 341 p54spi_int_ack(priv, SPI_HOST_INT_READY);
344 342 return 0;
345out:
346 return;
347} 343}
348 344
349static inline void p54spi_sleep(struct p54s_priv *priv) 345static inline void p54spi_sleep(struct p54s_priv *priv)
@@ -375,31 +371,44 @@ static int p54spi_rx(struct p54s_priv *priv)
375{ 371{
376 struct sk_buff *skb; 372 struct sk_buff *skb;
377 u16 len; 373 u16 len;
374 u16 rx_head[2];
375#define READAHEAD_SZ (sizeof(rx_head)-sizeof(u16))
378 376
379 p54spi_wakeup(priv); 377 if (p54spi_wakeup(priv) < 0)
380 378 return -EBUSY;
381 /* dummy read to flush SPI DMA controller bug */
382 p54spi_read16(priv, SPI_ADRS_GEN_PURP_1);
383 379
384 len = p54spi_read16(priv, SPI_ADRS_DMA_DATA); 380 /* Read data size and first data word in one SPI transaction
381 * This is workaround for firmware/DMA bug,
382 * when first data word gets lost under high load.
383 */
384 p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, rx_head, sizeof(rx_head));
385 len = rx_head[0];
385 386
386 if (len == 0) { 387 if (len == 0) {
387 dev_err(&priv->spi->dev, "rx request of zero bytes"); 388 p54spi_sleep(priv);
389 dev_err(&priv->spi->dev, "rx request of zero bytes\n");
388 return 0; 390 return 0;
389 } 391 }
390 392
391
392 /* Firmware may insert up to 4 padding bytes after the lmac header, 393 /* Firmware may insert up to 4 padding bytes after the lmac header,
393 * but it does not amend the size of SPI data transfer. 394 * but it does not amend the size of SPI data transfer.
394 * Such packets has correct data size in header, thus referencing 395 * Such packets has correct data size in header, thus referencing
395 * past the end of allocated skb. Reserve extra 4 bytes for this case */ 396 * past the end of allocated skb. Reserve extra 4 bytes for this case */
396 skb = dev_alloc_skb(len + 4); 397 skb = dev_alloc_skb(len + 4);
397 if (!skb) { 398 if (!skb) {
399 p54spi_sleep(priv);
398 dev_err(&priv->spi->dev, "could not alloc skb"); 400 dev_err(&priv->spi->dev, "could not alloc skb");
399 return 0; 401 return -ENOMEM;
400 } 402 }
401 403
402 p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, skb_put(skb, len), len); 404 if (len <= READAHEAD_SZ) {
405 memcpy(skb_put(skb, len), rx_head + 1, len);
406 } else {
407 memcpy(skb_put(skb, READAHEAD_SZ), rx_head + 1, READAHEAD_SZ);
408 p54spi_spi_read(priv, SPI_ADRS_DMA_DATA,
409 skb_put(skb, len - READAHEAD_SZ),
410 len - READAHEAD_SZ);
411 }
403 p54spi_sleep(priv); 412 p54spi_sleep(priv);
404 /* Put additional bytes to compensate for the possible 413 /* Put additional bytes to compensate for the possible
405 * alignment-caused truncation */ 414 * alignment-caused truncation */
@@ -427,7 +436,8 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
427 struct p54_hdr *hdr = (struct p54_hdr *) skb->data; 436 struct p54_hdr *hdr = (struct p54_hdr *) skb->data;
428 int ret = 0; 437 int ret = 0;
429 438
430 p54spi_wakeup(priv); 439 if (p54spi_wakeup(priv) < 0)
440 return -EBUSY;
431 441
432 ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len); 442 ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len);
433 if (ret < 0) 443 if (ret < 0)
@@ -436,16 +446,16 @@ static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb)
436 if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, 446 if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS,
437 cpu_to_le32(SPI_HOST_INT_WR_READY))) { 447 cpu_to_le32(SPI_HOST_INT_WR_READY))) {
438 dev_err(&priv->spi->dev, "WR_READY timeout\n"); 448 dev_err(&priv->spi->dev, "WR_READY timeout\n");
439 ret = -1; 449 ret = -EAGAIN;
440 goto out; 450 goto out;
441 } 451 }
442 452
443 p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); 453 p54spi_int_ack(priv, SPI_HOST_INT_WR_READY);
444 p54spi_sleep(priv);
445 454
446 if (FREE_AFTER_TX(skb)) 455 if (FREE_AFTER_TX(skb))
447 p54_free_skb(priv->hw, skb); 456 p54_free_skb(priv->hw, skb);
448out: 457out:
458 p54spi_sleep(priv);
449 return ret; 459 return ret;
450} 460}
451 461
@@ -515,8 +525,7 @@ static void p54spi_work(struct work_struct *work)
515 525
516 mutex_lock(&priv->mutex); 526 mutex_lock(&priv->mutex);
517 527
518 if (priv->fw_state == FW_STATE_OFF && 528 if (priv->fw_state == FW_STATE_OFF)
519 priv->fw_state == FW_STATE_RESET)
520 goto out; 529 goto out;
521 530
522 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); 531 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
@@ -543,11 +552,6 @@ static void p54spi_work(struct work_struct *work)
543 } 552 }
544 553
545 ret = p54spi_wq_tx(priv); 554 ret = p54spi_wq_tx(priv);
546 if (ret < 0)
547 goto out;
548
549 ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS);
550
551out: 555out:
552 mutex_unlock(&priv->mutex); 556 mutex_unlock(&priv->mutex);
553} 557}
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 52fc647e6cb6..c254fdf446fd 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2,7 +2,7 @@
2 * Driver for RNDIS based wireless USB devices. 2 * Driver for RNDIS based wireless USB devices.
3 * 3 *
4 * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net> 4 * Copyright (C) 2007 by Bjorge Dijkstra <bjd@jooz.net>
5 * Copyright (C) 2008 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi> 5 * Copyright (C) 2008-2009 by Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by 8 * it under the terms of the GNU General Public License as published by
@@ -196,6 +196,18 @@ enum ndis_80211_priv_filter {
196 ndis_80211_priv_8021x_wep 196 ndis_80211_priv_8021x_wep
197}; 197};
198 198
199enum ndis_80211_addkey_bits {
200 ndis_80211_addkey_8021x_auth = cpu_to_le32(1 << 28),
201 ndis_80211_addkey_set_init_recv_seq = cpu_to_le32(1 << 29),
202 ndis_80211_addkey_pairwise_key = cpu_to_le32(1 << 30),
203 ndis_80211_addkey_transmit_key = cpu_to_le32(1 << 31),
204};
205
206enum ndis_80211_addwep_bits {
207 ndis_80211_addwep_perclient_key = cpu_to_le32(1 << 30),
208 ndis_80211_addwep_transmit_key = cpu_to_le32(1 << 31),
209};
210
199struct ndis_80211_ssid { 211struct ndis_80211_ssid {
200 __le32 length; 212 __le32 length;
201 u8 essid[NDIS_802_11_LENGTH_SSID]; 213 u8 essid[NDIS_802_11_LENGTH_SSID];
@@ -309,7 +321,6 @@ enum wpa_key_mgmt { KEY_MGMT_802_1X, KEY_MGMT_PSK, KEY_MGMT_NONE,
309#define CAP_MODE_80211B 2 321#define CAP_MODE_80211B 2
310#define CAP_MODE_80211G 4 322#define CAP_MODE_80211G 4
311#define CAP_MODE_MASK 7 323#define CAP_MODE_MASK 7
312#define CAP_SUPPORT_TXPOWER 8
313 324
314#define WORK_LINK_UP (1<<0) 325#define WORK_LINK_UP (1<<0)
315#define WORK_LINK_DOWN (1<<1) 326#define WORK_LINK_DOWN (1<<1)
@@ -394,6 +405,7 @@ struct rndis_wext_private {
394 int encr_tx_key_index; 405 int encr_tx_key_index;
395 char encr_keys[4][32]; 406 char encr_keys[4][32];
396 int encr_key_len[4]; 407 int encr_key_len[4];
408 char encr_key_wpa[4];
397 int wpa_version; 409 int wpa_version;
398 int wpa_keymgmt; 410 int wpa_keymgmt;
399 int wpa_authalg; 411 int wpa_authalg;
@@ -945,7 +957,7 @@ static int set_infra_mode(struct usbnet *usbdev, int mode)
945 if (priv->wpa_keymgmt == 0 || 957 if (priv->wpa_keymgmt == 0 ||
946 priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) { 958 priv->wpa_keymgmt == IW_AUTH_KEY_MGMT_802_1X) {
947 for (i = 0; i < 4; i++) { 959 for (i = 0; i < 4; i++) {
948 if (priv->encr_key_len[i] > 0) 960 if (priv->encr_key_len[i] > 0 && !priv->encr_key_wpa[i])
949 add_wep_key(usbdev, priv->encr_keys[i], 961 add_wep_key(usbdev, priv->encr_keys[i],
950 priv->encr_key_len[i], i); 962 priv->encr_key_len[i], i);
951 } 963 }
@@ -999,7 +1011,7 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
999 memcpy(&ndis_key.material, key, key_len); 1011 memcpy(&ndis_key.material, key, key_len);
1000 1012
1001 if (index == priv->encr_tx_key_index) { 1013 if (index == priv->encr_tx_key_index) {
1002 ndis_key.index |= cpu_to_le32(1 << 31); 1014 ndis_key.index |= ndis_80211_addwep_transmit_key;
1003 ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104, 1015 ret = set_encr_mode(usbdev, IW_AUTH_CIPHER_WEP104,
1004 IW_AUTH_CIPHER_NONE); 1016 IW_AUTH_CIPHER_NONE);
1005 if (ret) 1017 if (ret)
@@ -1016,12 +1028,81 @@ static int add_wep_key(struct usbnet *usbdev, char *key, int key_len, int index)
1016 } 1028 }
1017 1029
1018 priv->encr_key_len[index] = key_len; 1030 priv->encr_key_len[index] = key_len;
1031 priv->encr_key_wpa[index] = 0;
1019 memcpy(&priv->encr_keys[index], key, key_len); 1032 memcpy(&priv->encr_keys[index], key, key_len);
1020 1033
1021 return 0; 1034 return 0;
1022} 1035}
1023 1036
1024 1037
1038static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len,
1039 int index, const struct sockaddr *addr,
1040 const u8 *rx_seq, int alg, int flags)
1041{
1042 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1043 struct ndis_80211_key ndis_key;
1044 int ret;
1045
1046 if (index < 0 || index >= 4)
1047 return -EINVAL;
1048 if (key_len > sizeof(ndis_key.material) || key_len < 0)
1049 return -EINVAL;
1050 if ((flags & ndis_80211_addkey_set_init_recv_seq) && !rx_seq)
1051 return -EINVAL;
1052 if ((flags & ndis_80211_addkey_pairwise_key) && !addr)
1053 return -EINVAL;
1054
1055 devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index,
1056 !!(flags & ndis_80211_addkey_transmit_key),
1057 !!(flags & ndis_80211_addkey_pairwise_key),
1058 !!(flags & ndis_80211_addkey_set_init_recv_seq));
1059
1060 memset(&ndis_key, 0, sizeof(ndis_key));
1061
1062 ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
1063 sizeof(ndis_key.material) + key_len);
1064 ndis_key.length = cpu_to_le32(key_len);
1065 ndis_key.index = cpu_to_le32(index) | flags;
1066
1067 if (alg == IW_ENCODE_ALG_TKIP && key_len == 32) {
1068 /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1069 * different order than NDIS spec, so swap the order here. */
1070 memcpy(ndis_key.material, key, 16);
1071 memcpy(ndis_key.material + 16, key + 24, 8);
1072 memcpy(ndis_key.material + 24, key + 16, 8);
1073 } else
1074 memcpy(ndis_key.material, key, key_len);
1075
1076 if (flags & ndis_80211_addkey_set_init_recv_seq)
1077 memcpy(ndis_key.rsc, rx_seq, 6);
1078
1079 if (flags & ndis_80211_addkey_pairwise_key) {
1080 /* pairwise key */
1081 memcpy(ndis_key.bssid, addr->sa_data, ETH_ALEN);
1082 } else {
1083 /* group key */
1084 if (priv->infra_mode == ndis_80211_infra_adhoc)
1085 memset(ndis_key.bssid, 0xff, ETH_ALEN);
1086 else
1087 get_bssid(usbdev, ndis_key.bssid);
1088 }
1089
1090 ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
1091 le32_to_cpu(ndis_key.size));
1092 devdbg(usbdev, "add_wpa_key: OID_802_11_ADD_KEY -> %08X", ret);
1093 if (ret != 0)
1094 return ret;
1095
1096 priv->encr_key_len[index] = key_len;
1097 priv->encr_key_wpa[index] = 1;
1098
1099 if (flags & ndis_80211_addkey_transmit_key)
1100 priv->encr_tx_key_index = index;
1101
1102 return 0;
1103}
1104
1105
1025/* remove_key is for both wep and wpa */ 1106/* remove_key is for both wep and wpa */
1026static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN]) 1107static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1027{ 1108{
@@ -1034,6 +1115,7 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1034 return 0; 1115 return 0;
1035 1116
1036 priv->encr_key_len[index] = 0; 1117 priv->encr_key_len[index] = 0;
1118 priv->encr_key_wpa[index] = 0;
1037 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index])); 1119 memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index]));
1038 1120
1039 if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP || 1121 if (priv->wpa_cipher_pair == IW_AUTH_CIPHER_TKIP ||
@@ -1045,7 +1127,8 @@ static int remove_key(struct usbnet *usbdev, int index, u8 bssid[ETH_ALEN])
1045 if (bssid) { 1127 if (bssid) {
1046 /* pairwise key */ 1128 /* pairwise key */
1047 if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0) 1129 if (memcmp(bssid, ffff_bssid, ETH_ALEN) != 0)
1048 remove_key.index |= cpu_to_le32(1 << 30); 1130 remove_key.index |=
1131 ndis_80211_addkey_pairwise_key;
1049 memcpy(remove_key.bssid, bssid, 1132 memcpy(remove_key.bssid, bssid,
1050 sizeof(remove_key.bssid)); 1133 sizeof(remove_key.bssid));
1051 } else 1134 } else
@@ -1590,9 +1673,7 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1590 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 1673 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1591 struct usbnet *usbdev = netdev_priv(dev); 1674 struct usbnet *usbdev = netdev_priv(dev);
1592 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 1675 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1593 struct ndis_80211_key ndis_key; 1676 int keyidx, flags;
1594 int keyidx, ret;
1595 u8 *addr;
1596 1677
1597 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX; 1678 keyidx = wrqu->encoding.flags & IW_ENCODE_INDEX;
1598 1679
@@ -1615,58 +1696,16 @@ static int rndis_iw_set_encode_ext(struct net_device *dev,
1615 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0) 1696 ext->alg == IW_ENCODE_ALG_NONE || ext->key_len == 0)
1616 return remove_key(usbdev, keyidx, NULL); 1697 return remove_key(usbdev, keyidx, NULL);
1617 1698
1618 if (ext->key_len > sizeof(ndis_key.material)) 1699 flags = 0;
1619 return -1; 1700 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
1620 1701 flags |= ndis_80211_addkey_set_init_recv_seq;
1621 memset(&ndis_key, 0, sizeof(ndis_key)); 1702 if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY))
1622 1703 flags |= ndis_80211_addkey_pairwise_key;
1623 ndis_key.size = cpu_to_le32(sizeof(ndis_key) -
1624 sizeof(ndis_key.material) + ext->key_len);
1625 ndis_key.length = cpu_to_le32(ext->key_len);
1626 ndis_key.index = cpu_to_le32(keyidx);
1627
1628 if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
1629 memcpy(ndis_key.rsc, ext->rx_seq, 6);
1630 ndis_key.index |= cpu_to_le32(1 << 29);
1631 }
1632
1633 addr = ext->addr.sa_data;
1634 if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
1635 /* group key */
1636 if (priv->infra_mode == ndis_80211_infra_adhoc)
1637 memset(ndis_key.bssid, 0xff, ETH_ALEN);
1638 else
1639 get_bssid(usbdev, ndis_key.bssid);
1640 } else {
1641 /* pairwise key */
1642 ndis_key.index |= cpu_to_le32(1 << 30);
1643 memcpy(ndis_key.bssid, addr, ETH_ALEN);
1644 }
1645
1646 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1647 ndis_key.index |= cpu_to_le32(1 << 31);
1648
1649 if (ext->alg == IW_ENCODE_ALG_TKIP && ext->key_len == 32) {
1650 /* wpa_supplicant gives us the Michael MIC RX/TX keys in
1651 * different order than NDIS spec, so swap the order here. */
1652 memcpy(ndis_key.material, ext->key, 16);
1653 memcpy(ndis_key.material + 16, ext->key + 24, 8);
1654 memcpy(ndis_key.material + 24, ext->key + 16, 8);
1655 } else
1656 memcpy(ndis_key.material, ext->key, ext->key_len);
1657
1658 ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key,
1659 le32_to_cpu(ndis_key.size));
1660 devdbg(usbdev, "SIOCSIWENCODEEXT: OID_802_11_ADD_KEY -> %08X", ret);
1661 if (ret != 0)
1662 return ret;
1663
1664 priv->encr_key_len[keyidx] = ext->key_len;
1665 memcpy(&priv->encr_keys[keyidx], ndis_key.material, ext->key_len);
1666 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) 1704 if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
1667 priv->encr_tx_key_index = keyidx; 1705 flags |= ndis_80211_addkey_transmit_key;
1668 1706
1669 return 0; 1707 return add_wpa_key(usbdev, ext->key, ext->key_len, keyidx, &ext->addr,
1708 ext->rx_seq, ext->alg, flags);
1670} 1709}
1671 1710
1672 1711
@@ -1849,18 +1888,10 @@ static int rndis_iw_get_txpower(struct net_device *dev,
1849 struct usbnet *usbdev = netdev_priv(dev); 1888 struct usbnet *usbdev = netdev_priv(dev);
1850 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 1889 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1851 __le32 tx_power; 1890 __le32 tx_power;
1852 int ret = 0, len;
1853 1891
1854 if (priv->radio_on) { 1892 if (priv->radio_on) {
1855 if (priv->caps & CAP_SUPPORT_TXPOWER) { 1893 /* fake since changing tx_power (by userlevel) not supported */
1856 len = sizeof(tx_power); 1894 tx_power = cpu_to_le32(get_bcm4320_power(priv));
1857 ret = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
1858 &tx_power, &len);
1859 if (ret != 0)
1860 return ret;
1861 } else
1862 /* fake incase not supported */
1863 tx_power = cpu_to_le32(get_bcm4320_power(priv));
1864 1895
1865 wrqu->txpower.flags = IW_TXPOW_MWATT; 1896 wrqu->txpower.flags = IW_TXPOW_MWATT;
1866 wrqu->txpower.value = le32_to_cpu(tx_power); 1897 wrqu->txpower.value = le32_to_cpu(tx_power);
@@ -1873,7 +1904,7 @@ static int rndis_iw_get_txpower(struct net_device *dev,
1873 1904
1874 devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value); 1905 devdbg(usbdev, "SIOCGIWTXPOW: %d", wrqu->txpower.value);
1875 1906
1876 return ret; 1907 return 0;
1877} 1908}
1878 1909
1879 1910
@@ -1883,7 +1914,6 @@ static int rndis_iw_set_txpower(struct net_device *dev,
1883 struct usbnet *usbdev = netdev_priv(dev); 1914 struct usbnet *usbdev = netdev_priv(dev);
1884 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 1915 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
1885 __le32 tx_power = 0; 1916 __le32 tx_power = 0;
1886 int ret = 0;
1887 1917
1888 if (!wrqu->txpower.disabled) { 1918 if (!wrqu->txpower.disabled) {
1889 if (wrqu->txpower.flags == IW_TXPOW_MWATT) 1919 if (wrqu->txpower.flags == IW_TXPOW_MWATT)
@@ -1906,22 +1936,10 @@ static int rndis_iw_set_txpower(struct net_device *dev,
1906 devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power)); 1936 devdbg(usbdev, "SIOCSIWTXPOW: %d", le32_to_cpu(tx_power));
1907 1937
1908 if (le32_to_cpu(tx_power) != 0) { 1938 if (le32_to_cpu(tx_power) != 0) {
1909 if (priv->caps & CAP_SUPPORT_TXPOWER) { 1939 /* txpower unsupported, just turn radio on */
1910 /* turn radio on first */ 1940 if (!priv->radio_on)
1911 if (!priv->radio_on) 1941 return disassociate(usbdev, 1);
1912 disassociate(usbdev, 1); 1942 return 0; /* all ready on */
1913
1914 ret = rndis_set_oid(usbdev, OID_802_11_TX_POWER_LEVEL,
1915 &tx_power, sizeof(tx_power));
1916 if (ret != 0)
1917 ret = -EOPNOTSUPP;
1918 return ret;
1919 } else {
1920 /* txpower unsupported, just turn radio on */
1921 if (!priv->radio_on)
1922 return disassociate(usbdev, 1);
1923 return 0; /* all ready on */
1924 }
1925 } 1943 }
1926 1944
1927 /* tx_power == 0, turn off radio */ 1945 /* tx_power == 0, turn off radio */
@@ -2130,16 +2148,8 @@ static int rndis_wext_get_caps(struct usbnet *usbdev)
2130 __le32 items[8]; 2148 __le32 items[8];
2131 } networks_supported; 2149 } networks_supported;
2132 int len, retval, i, n; 2150 int len, retval, i, n;
2133 __le32 tx_power;
2134 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 2151 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2135 2152
2136 /* determine if supports setting txpower */
2137 len = sizeof(tx_power);
2138 retval = rndis_query_oid(usbdev, OID_802_11_TX_POWER_LEVEL, &tx_power,
2139 &len);
2140 if (retval == 0 && le32_to_cpu(tx_power) != 0xFF)
2141 priv->caps |= CAP_SUPPORT_TXPOWER;
2142
2143 /* determine supported modes */ 2153 /* determine supported modes */
2144 len = sizeof(networks_supported); 2154 len = sizeof(networks_supported);
2145 retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED, 2155 retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED,
@@ -2275,7 +2285,17 @@ end:
2275} 2285}
2276 2286
2277 2287
2278static int bcm4320_early_init(struct usbnet *usbdev) 2288static int bcm4320a_early_init(struct usbnet *usbdev)
2289{
2290 /* bcm4320a doesn't handle configuration parameters well. Try
2291 * set any and you get partially zeroed mac and broken device.
2292 */
2293
2294 return 0;
2295}
2296
2297
2298static int bcm4320b_early_init(struct usbnet *usbdev)
2279{ 2299{
2280 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev); 2300 struct rndis_wext_private *priv = get_rndis_wext_priv(usbdev);
2281 char buf[8]; 2301 char buf[8];
@@ -2515,7 +2535,7 @@ static const struct driver_info bcm4320b_info = {
2515 .rx_fixup = rndis_rx_fixup, 2535 .rx_fixup = rndis_rx_fixup,
2516 .tx_fixup = rndis_tx_fixup, 2536 .tx_fixup = rndis_tx_fixup,
2517 .reset = rndis_wext_reset, 2537 .reset = rndis_wext_reset,
2518 .early_init = bcm4320_early_init, 2538 .early_init = bcm4320b_early_init,
2519 .link_change = rndis_wext_link_change, 2539 .link_change = rndis_wext_link_change,
2520}; 2540};
2521 2541
@@ -2528,7 +2548,7 @@ static const struct driver_info bcm4320a_info = {
2528 .rx_fixup = rndis_rx_fixup, 2548 .rx_fixup = rndis_rx_fixup,
2529 .tx_fixup = rndis_tx_fixup, 2549 .tx_fixup = rndis_tx_fixup,
2530 .reset = rndis_wext_reset, 2550 .reset = rndis_wext_reset,
2531 .early_init = bcm4320_early_init, 2551 .early_init = bcm4320a_early_init,
2532 .link_change = rndis_wext_link_change, 2552 .link_change = rndis_wext_link_change,
2533}; 2553};
2534 2554
@@ -2541,7 +2561,7 @@ static const struct driver_info rndis_wext_info = {
2541 .rx_fixup = rndis_rx_fixup, 2561 .rx_fixup = rndis_rx_fixup,
2542 .tx_fixup = rndis_tx_fixup, 2562 .tx_fixup = rndis_tx_fixup,
2543 .reset = rndis_wext_reset, 2563 .reset = rndis_wext_reset,
2544 .early_init = bcm4320_early_init, 2564 .early_init = bcm4320a_early_init,
2545 .link_change = rndis_wext_link_change, 2565 .link_change = rndis_wext_link_change,
2546}; 2566};
2547 2567
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6f39ba662188..0197531bd88c 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -335,10 +335,11 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
335 preamble_mask = erp->short_preamble << 3; 335 preamble_mask = erp->short_preamble << 3;
336 336
337 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg); 337 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
338 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 338 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, erp->ack_timeout);
339 erp->ack_timeout);
340 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 339 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
341 erp->ack_consume_time); 340 erp->ack_consume_time);
341 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
342 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
342 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); 343 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
343 344
344 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg); 345 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
@@ -371,6 +372,11 @@ static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev,
371 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time); 372 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
372 rt2x00pci_register_write(rt2x00dev, CSR11, reg); 373 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
373 374
375 rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
376 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
377 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
378 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
379
374 rt2x00pci_register_read(rt2x00dev, CSR18, &reg); 380 rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
375 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs); 381 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
376 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs); 382 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
@@ -503,24 +509,6 @@ static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
503 rt2x00pci_register_write(rt2x00dev, CSR11, reg); 509 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
504} 510}
505 511
506static void rt2400pci_config_duration(struct rt2x00_dev *rt2x00dev,
507 struct rt2x00lib_conf *libconf)
508{
509 u32 reg;
510
511 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
512 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
513 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
514 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
515
516 rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
517 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
518 libconf->conf->beacon_int * 16);
519 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
520 libconf->conf->beacon_int * 16);
521 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
522}
523
524static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, 512static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev,
525 struct rt2x00lib_conf *libconf) 513 struct rt2x00lib_conf *libconf)
526{ 514{
@@ -558,8 +546,6 @@ static void rt2400pci_config(struct rt2x00_dev *rt2x00dev,
558 libconf->conf->power_level); 546 libconf->conf->power_level);
559 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 547 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
560 rt2400pci_config_retry_limit(rt2x00dev, libconf); 548 rt2400pci_config_retry_limit(rt2x00dev, libconf);
561 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
562 rt2400pci_config_duration(rt2x00dev, libconf);
563 if (flags & IEEE80211_CONF_CHANGE_PS) 549 if (flags & IEEE80211_CONF_CHANGE_PS)
564 rt2400pci_config_ps(rt2x00dev, libconf); 550 rt2400pci_config_ps(rt2x00dev, libconf);
565} 551}
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 906960f67b6c..f95cb646f85a 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -341,10 +341,11 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
341 preamble_mask = erp->short_preamble << 3; 341 preamble_mask = erp->short_preamble << 3;
342 342
343 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg); 343 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
344 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, 344 rt2x00_set_field32(&reg, TXCSR1_ACK_TIMEOUT, erp->ack_timeout);
345 erp->ack_timeout);
346 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME, 345 rt2x00_set_field32(&reg, TXCSR1_ACK_CONSUME_TIME,
347 erp->ack_consume_time); 346 erp->ack_consume_time);
347 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
348 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
348 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); 349 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
349 350
350 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg); 351 rt2x00pci_register_read(rt2x00dev, ARCSR2, &reg);
@@ -377,6 +378,11 @@ static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev,
377 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time); 378 rt2x00_set_field32(&reg, CSR11_SLOT_TIME, erp->slot_time);
378 rt2x00pci_register_write(rt2x00dev, CSR11, reg); 379 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
379 380
381 rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
382 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL, erp->beacon_int * 16);
383 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16);
384 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
385
380 rt2x00pci_register_read(rt2x00dev, CSR18, &reg); 386 rt2x00pci_register_read(rt2x00dev, CSR18, &reg);
381 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs); 387 rt2x00_set_field32(&reg, CSR18_SIFS, erp->sifs);
382 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs); 388 rt2x00_set_field32(&reg, CSR18_PIFS, erp->pifs);
@@ -552,24 +558,6 @@ static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
552 rt2x00pci_register_write(rt2x00dev, CSR11, reg); 558 rt2x00pci_register_write(rt2x00dev, CSR11, reg);
553} 559}
554 560
555static void rt2500pci_config_duration(struct rt2x00_dev *rt2x00dev,
556 struct rt2x00lib_conf *libconf)
557{
558 u32 reg;
559
560 rt2x00pci_register_read(rt2x00dev, TXCSR1, &reg);
561 rt2x00_set_field32(&reg, TXCSR1_TSF_OFFSET, IEEE80211_HEADER);
562 rt2x00_set_field32(&reg, TXCSR1_AUTORESPONDER, 1);
563 rt2x00pci_register_write(rt2x00dev, TXCSR1, reg);
564
565 rt2x00pci_register_read(rt2x00dev, CSR12, &reg);
566 rt2x00_set_field32(&reg, CSR12_BEACON_INTERVAL,
567 libconf->conf->beacon_int * 16);
568 rt2x00_set_field32(&reg, CSR12_CFP_MAX_DURATION,
569 libconf->conf->beacon_int * 16);
570 rt2x00pci_register_write(rt2x00dev, CSR12, reg);
571}
572
573static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, 561static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev,
574 struct rt2x00lib_conf *libconf) 562 struct rt2x00lib_conf *libconf)
575{ 563{
@@ -609,8 +597,6 @@ static void rt2500pci_config(struct rt2x00_dev *rt2x00dev,
609 libconf->conf->power_level); 597 libconf->conf->power_level);
610 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 598 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
611 rt2500pci_config_retry_limit(rt2x00dev, libconf); 599 rt2500pci_config_retry_limit(rt2x00dev, libconf);
612 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
613 rt2500pci_config_duration(rt2x00dev, libconf);
614 if (flags & IEEE80211_CONF_CHANGE_PS) 600 if (flags & IEEE80211_CONF_CHANGE_PS)
615 rt2500pci_config_ps(rt2x00dev, libconf); 601 rt2500pci_config_ps(rt2x00dev, libconf);
616} 602}
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 1debb88bc60e..69f966f1ce54 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -503,6 +503,10 @@ static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev,
503 503
504 rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); 504 rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates);
505 505
506 rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
507 rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL, erp->beacon_int * 4);
508 rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
509
506 rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); 510 rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time);
507 rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); 511 rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs);
508 rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); 512 rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs);
@@ -632,17 +636,6 @@ static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev,
632 rt2500usb_rf_write(rt2x00dev, 3, rf3); 636 rt2500usb_rf_write(rt2x00dev, 3, rf3);
633} 637}
634 638
635static void rt2500usb_config_duration(struct rt2x00_dev *rt2x00dev,
636 struct rt2x00lib_conf *libconf)
637{
638 u16 reg;
639
640 rt2500usb_register_read(rt2x00dev, TXRX_CSR18, &reg);
641 rt2x00_set_field16(&reg, TXRX_CSR18_INTERVAL,
642 libconf->conf->beacon_int * 4);
643 rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
644}
645
646static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, 639static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev,
647 struct rt2x00lib_conf *libconf) 640 struct rt2x00lib_conf *libconf)
648{ 641{
@@ -680,8 +673,6 @@ static void rt2500usb_config(struct rt2x00_dev *rt2x00dev,
680 !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) 673 !(flags & IEEE80211_CONF_CHANGE_CHANNEL))
681 rt2500usb_config_txpower(rt2x00dev, 674 rt2500usb_config_txpower(rt2x00dev,
682 libconf->conf->power_level); 675 libconf->conf->power_level);
683 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
684 rt2500usb_config_duration(rt2x00dev, libconf);
685 if (flags & IEEE80211_CONF_CHANGE_PS) 676 if (flags & IEEE80211_CONF_CHANGE_PS)
686 rt2500usb_config_ps(rt2x00dev, libconf); 677 rt2500usb_config_ps(rt2x00dev, libconf);
687} 678}
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 257bfb5483c9..142ad34fdc49 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -616,6 +616,11 @@ static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev,
616 rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs); 616 rt2x00_set_field32(&reg, XIFS_TIME_CFG_EIFS, erp->eifs);
617 rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); 617 rt2x00_set_field32(&reg, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1);
618 rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg); 618 rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg);
619
620 rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
621 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
622 erp->beacon_int * 16);
623 rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
619} 624}
620 625
621static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, 626static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev,
@@ -955,17 +960,6 @@ static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
955 rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg); 960 rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg);
956} 961}
957 962
958static void rt2800usb_config_duration(struct rt2x00_dev *rt2x00dev,
959 struct rt2x00lib_conf *libconf)
960{
961 u32 reg;
962
963 rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
964 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
965 libconf->conf->beacon_int * 16);
966 rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg);
967}
968
969static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, 963static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev,
970 struct rt2x00lib_conf *libconf) 964 struct rt2x00lib_conf *libconf)
971{ 965{
@@ -1010,8 +1004,6 @@ static void rt2800usb_config(struct rt2x00_dev *rt2x00dev,
1010 rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); 1004 rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level);
1011 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 1005 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
1012 rt2800usb_config_retry_limit(rt2x00dev, libconf); 1006 rt2800usb_config_retry_limit(rt2x00dev, libconf);
1013 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
1014 rt2800usb_config_duration(rt2x00dev, libconf);
1015 if (flags & IEEE80211_CONF_CHANGE_PS) 1007 if (flags & IEEE80211_CONF_CHANGE_PS)
1016 rt2800usb_config_ps(rt2x00dev, libconf); 1008 rt2800usb_config_ps(rt2x00dev, libconf);
1017} 1009}
@@ -2881,8 +2873,6 @@ static const struct rt2x00_ops rt2800usb_ops = {
2881 * rt2800usb module information. 2873 * rt2800usb module information.
2882 */ 2874 */
2883static struct usb_device_id rt2800usb_device_table[] = { 2875static struct usb_device_id rt2800usb_device_table[] = {
2884 /* ??? */
2885 { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
2886 /* Abocom */ 2876 /* Abocom */
2887 { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, 2877 { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) },
2888 { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, 2878 { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -2912,6 +2902,7 @@ static struct usb_device_id rt2800usb_device_table[] = {
2912 { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, 2902 { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) },
2913 { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, 2903 { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) },
2914 { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, 2904 { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) },
2905 { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) },
2915 /* Buffalo */ 2906 /* Buffalo */
2916 { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, 2907 { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
2917 { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, 2908 { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -3026,6 +3017,10 @@ static struct usb_device_id rt2800usb_device_table[] = {
3026 { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, 3017 { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) },
3027 /* Sparklan */ 3018 /* Sparklan */
3028 { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, 3019 { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) },
3020 /* Sweex */
3021 { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) },
3022 { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) },
3023 { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) },
3029 /* U-Media*/ 3024 /* U-Media*/
3030 { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, 3025 { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) },
3031 /* ZCOM */ 3026 /* ZCOM */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 419b1b9f998e..2b64a6198698 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -417,6 +417,8 @@ struct rt2x00lib_erp {
417 short pifs; 417 short pifs;
418 short difs; 418 short difs;
419 short eifs; 419 short eifs;
420
421 u16 beacon_int;
420}; 422};
421 423
422/* 424/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index 863e399d4fa6..c5bbf0b6e207 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -106,6 +106,7 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
106 } 106 }
107 107
108 erp.basic_rates = bss_conf->basic_rates; 108 erp.basic_rates = bss_conf->basic_rates;
109 erp.beacon_int = bss_conf->beacon_int;
109 110
110 rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); 111 rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp);
111} 112}
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c
index 57ab42cfed34..bc4e81e21841 100644
--- a/drivers/net/wireless/rt2x00/rt2x00crypto.c
+++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c
@@ -33,7 +33,7 @@ enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key)
33{ 33{
34 switch (key->alg) { 34 switch (key->alg) {
35 case ALG_WEP: 35 case ALG_WEP:
36 if (key->keylen == LEN_WEP40) 36 if (key->keylen == WLAN_KEY_LEN_WEP40)
37 return CIPHER_WEP64; 37 return CIPHER_WEP64;
38 else 38 else
39 return CIPHER_WEP128; 39 return CIPHER_WEP128;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index f2270845072a..57813e72c808 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -260,7 +260,8 @@ void rt2x00lib_txdone(struct queue_entry *entry,
260 * Update TX statistics. 260 * Update TX statistics.
261 */ 261 */
262 rt2x00dev->link.qual.tx_success += 262 rt2x00dev->link.qual.tx_success +=
263 test_bit(TXDONE_SUCCESS, &txdesc->flags); 263 test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
264 test_bit(TXDONE_UNKNOWN, &txdesc->flags);
264 rt2x00dev->link.qual.tx_failed += 265 rt2x00dev->link.qual.tx_failed +=
265 test_bit(TXDONE_FAILURE, &txdesc->flags); 266 test_bit(TXDONE_FAILURE, &txdesc->flags);
266 267
@@ -278,14 +279,16 @@ void rt2x00lib_txdone(struct queue_entry *entry,
278 tx_info->status.rates[1].idx = -1; /* terminate */ 279 tx_info->status.rates[1].idx = -1; /* terminate */
279 280
280 if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { 281 if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) {
281 if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) 282 if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
283 test_bit(TXDONE_UNKNOWN, &txdesc->flags))
282 tx_info->flags |= IEEE80211_TX_STAT_ACK; 284 tx_info->flags |= IEEE80211_TX_STAT_ACK;
283 else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) 285 else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
284 rt2x00dev->low_level_stats.dot11ACKFailureCount++; 286 rt2x00dev->low_level_stats.dot11ACKFailureCount++;
285 } 287 }
286 288
287 if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { 289 if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
288 if (test_bit(TXDONE_SUCCESS, &txdesc->flags)) 290 if (test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
291 test_bit(TXDONE_UNKNOWN, &txdesc->flags))
289 rt2x00dev->low_level_stats.dot11RTSSuccessCount++; 292 rt2x00dev->low_level_stats.dot11RTSSuccessCount++;
290 else if (test_bit(TXDONE_FAILURE, &txdesc->flags)) 293 else if (test_bit(TXDONE_FAILURE, &txdesc->flags))
291 rt2x00dev->low_level_stats.dot11RTSFailureCount++; 294 rt2x00dev->low_level_stats.dot11RTSFailureCount++;
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index cb521ee7a8f0..a8bf5c432858 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -603,15 +603,22 @@ static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev,
603 603
604 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg); 604 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
605 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); 605 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
606 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
606 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); 607 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
607 608
608 rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg); 609 rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
610 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
609 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE, 611 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
610 !!erp->short_preamble); 612 !!erp->short_preamble);
611 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); 613 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
612 614
613 rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); 615 rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
614 616
617 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
618 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
619 erp->beacon_int * 16);
620 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
621
615 rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg); 622 rt2x00pci_register_read(rt2x00dev, MAC_CSR9, &reg);
616 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time); 623 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
617 rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); 624 rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -938,25 +945,6 @@ static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev,
938 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); 945 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
939} 946}
940 947
941static void rt61pci_config_duration(struct rt2x00_dev *rt2x00dev,
942 struct rt2x00lib_conf *libconf)
943{
944 u32 reg;
945
946 rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, &reg);
947 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
948 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
949
950 rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, &reg);
951 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
952 rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg);
953
954 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
955 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
956 libconf->conf->beacon_int * 16);
957 rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
958}
959
960static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, 948static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev,
961 struct rt2x00lib_conf *libconf) 949 struct rt2x00lib_conf *libconf)
962{ 950{
@@ -1016,8 +1004,6 @@ static void rt61pci_config(struct rt2x00_dev *rt2x00dev,
1016 rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level); 1004 rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level);
1017 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 1005 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
1018 rt61pci_config_retry_limit(rt2x00dev, libconf); 1006 rt61pci_config_retry_limit(rt2x00dev, libconf);
1019 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
1020 rt61pci_config_duration(rt2x00dev, libconf);
1021 if (flags & IEEE80211_CONF_CHANGE_PS) 1007 if (flags & IEEE80211_CONF_CHANGE_PS)
1022 rt61pci_config_ps(rt2x00dev, libconf); 1008 rt61pci_config_ps(rt2x00dev, libconf);
1023} 1009}
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 270dd4e59f7f..211a3d6bc054 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -566,15 +566,22 @@ static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev,
566 566
567 rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg); 567 rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
568 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout); 568 rt2x00_set_field32(&reg, TXRX_CSR0_RX_ACK_TIMEOUT, erp->ack_timeout);
569 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
569 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); 570 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
570 571
571 rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg); 572 rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
573 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
572 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE, 574 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_PREAMBLE,
573 !!erp->short_preamble); 575 !!erp->short_preamble);
574 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); 576 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
575 577
576 rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); 578 rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates);
577 579
580 rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
581 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
582 erp->beacon_int * 16);
583 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
584
578 rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg); 585 rt2x00usb_register_read(rt2x00dev, MAC_CSR9, &reg);
579 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time); 586 rt2x00_set_field32(&reg, MAC_CSR9_SLOT_TIME, erp->slot_time);
580 rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); 587 rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg);
@@ -834,25 +841,6 @@ static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev,
834 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); 841 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
835} 842}
836 843
837static void rt73usb_config_duration(struct rt2x00_dev *rt2x00dev,
838 struct rt2x00lib_conf *libconf)
839{
840 u32 reg;
841
842 rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, &reg);
843 rt2x00_set_field32(&reg, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER);
844 rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg);
845
846 rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, &reg);
847 rt2x00_set_field32(&reg, TXRX_CSR4_AUTORESPOND_ENABLE, 1);
848 rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg);
849
850 rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
851 rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_INTERVAL,
852 libconf->conf->beacon_int * 16);
853 rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
854}
855
856static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, 844static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev,
857 struct rt2x00lib_conf *libconf) 845 struct rt2x00lib_conf *libconf)
858{ 846{
@@ -906,8 +894,6 @@ static void rt73usb_config(struct rt2x00_dev *rt2x00dev,
906 rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level); 894 rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level);
907 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) 895 if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
908 rt73usb_config_retry_limit(rt2x00dev, libconf); 896 rt73usb_config_retry_limit(rt2x00dev, libconf);
909 if (flags & IEEE80211_CONF_CHANGE_BEACON_INTERVAL)
910 rt73usb_config_duration(rt2x00dev, libconf);
911 if (flags & IEEE80211_CONF_CHANGE_PS) 897 if (flags & IEEE80211_CONF_CHANGE_PS)
912 rt73usb_config_ps(rt2x00dev, libconf); 898 rt73usb_config_ps(rt2x00dev, libconf);
913} 899}
diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c
index f95204632690..b7b0c46adb46 100644
--- a/drivers/net/wireless/strip.c
+++ b/drivers/net/wireless/strip.c
@@ -2509,7 +2509,7 @@ static void strip_dev_setup(struct net_device *dev)
2509 * netdev_priv(dev) Already holds a pointer to our struct strip 2509 * netdev_priv(dev) Already holds a pointer to our struct strip
2510 */ 2510 */
2511 2511
2512 *(MetricomAddress *) & dev->broadcast = broadcast_address; 2512 *(MetricomAddress *)dev->broadcast = broadcast_address;
2513 dev->dev_addr[0] = 0; 2513 dev->dev_addr[0] = 0;
2514 dev->addr_len = sizeof(MetricomAddress); 2514 dev->addr_len = sizeof(MetricomAddress);
2515 2515
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index 6bdb1704083b..40b07b988224 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -420,9 +420,9 @@ static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs,
420 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) 420 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
421 cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; 421 cs->control |= ZD_CS_NEED_RANDOM_BACKOFF;
422 422
423 /* Multicast */ 423 /* No ACK expected (multicast, etc.) */
424 if (is_multicast_ether_addr(header->addr1)) 424 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
425 cs->control |= ZD_CS_MULTICAST; 425 cs->control |= ZD_CS_NO_ACK;
426 426
427 /* PS-POLL */ 427 /* PS-POLL */
428 if (ieee80211_is_pspoll(header->frame_control)) 428 if (ieee80211_is_pspoll(header->frame_control))
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index 4c05d3ee4c37..7c2759118d13 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -87,7 +87,7 @@ struct zd_ctrlset {
87 87
88/* zd_ctrlset control field */ 88/* zd_ctrlset control field */
89#define ZD_CS_NEED_RANDOM_BACKOFF 0x01 89#define ZD_CS_NEED_RANDOM_BACKOFF 0x01
90#define ZD_CS_MULTICAST 0x02 90#define ZD_CS_NO_ACK 0x02
91 91
92#define ZD_CS_FRAME_TYPE_MASK 0x0c 92#define ZD_CS_FRAME_TYPE_MASK 0x0c
93#define ZD_CS_DATA_FRAME 0x00 93#define ZD_CS_DATA_FRAME 0x00
diff --git a/drivers/staging/agnx/pci.c b/drivers/staging/agnx/pci.c
index 25c0ffd2faa0..43b3fe352616 100644
--- a/drivers/staging/agnx/pci.c
+++ b/drivers/staging/agnx/pci.c
@@ -303,14 +303,18 @@ static int agnx_config(struct ieee80211_hw *dev, u32 changed)
303 return 0; 303 return 0;
304} 304}
305 305
306static int agnx_config_interface(struct ieee80211_hw *dev, 306static void agnx_bss_info_changed(struct ieee80211_hw *dev,
307 struct ieee80211_vif *vif, 307 struct ieee80211_vif *vif,
308 struct ieee80211_if_conf *conf) 308 struct ieee80211_bss_conf *conf,
309 u32 changed)
309{ 310{
310 struct agnx_priv *priv = dev->priv; 311 struct agnx_priv *priv = dev->priv;
311 void __iomem *ctl = priv->ctl; 312 void __iomem *ctl = priv->ctl;
312 AGNX_TRACE; 313 AGNX_TRACE;
313 314
315 if (!(changed & BSS_CHANGED_BSSID))
316 return;
317
314 spin_lock(&priv->lock); 318 spin_lock(&priv->lock);
315 319
316 if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) { 320 if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) {
@@ -323,8 +327,7 @@ static int agnx_config_interface(struct ieee80211_hw *dev,
323 agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1); 327 agnx_write32(ctl, AGNX_BM_MTSM, 0xff & ~0x1);
324 } 328 }
325 spin_unlock(&priv->lock); 329 spin_unlock(&priv->lock);
326 return 0; 330} /* agnx_bss_info_changed */
327} /* agnx_config_interface */
328 331
329 332
330static void agnx_configure_filter(struct ieee80211_hw *dev, 333static void agnx_configure_filter(struct ieee80211_hw *dev,
@@ -422,7 +425,7 @@ static struct ieee80211_ops agnx_ops = {
422 .add_interface = agnx_add_interface, 425 .add_interface = agnx_add_interface,
423 .remove_interface = agnx_remove_interface, 426 .remove_interface = agnx_remove_interface,
424 .config = agnx_config, 427 .config = agnx_config,
425 .config_interface = agnx_config_interface, 428 .bss_info_changed = agnx_bss_info_changed,
426 .configure_filter = agnx_configure_filter, 429 .configure_filter = agnx_configure_filter,
427 .get_stats = agnx_get_stats, 430 .get_stats = agnx_get_stats,
428 .get_tx_stats = agnx_get_tx_stats, 431 .get_tx_stats = agnx_get_tx_stats,
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 05c29c01174c..34de8b21f6d4 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -493,6 +493,7 @@ struct ieee80211s_hdr {
493/* Mesh flags */ 493/* Mesh flags */
494#define MESH_FLAGS_AE_A4 0x1 494#define MESH_FLAGS_AE_A4 0x1
495#define MESH_FLAGS_AE_A5_A6 0x2 495#define MESH_FLAGS_AE_A5_A6 0x2
496#define MESH_FLAGS_AE 0x3
496#define MESH_FLAGS_PS_DEEP 0x4 497#define MESH_FLAGS_PS_DEEP 0x4
497 498
498/** 499/**
@@ -1085,6 +1086,14 @@ enum ieee80211_spectrum_mgmt_actioncode {
1085 WLAN_ACTION_SPCT_CHL_SWITCH = 4, 1086 WLAN_ACTION_SPCT_CHL_SWITCH = 4,
1086}; 1087};
1087 1088
1089/* Security key length */
1090enum ieee80211_key_len {
1091 WLAN_KEY_LEN_WEP40 = 5,
1092 WLAN_KEY_LEN_WEP104 = 13,
1093 WLAN_KEY_LEN_CCMP = 16,
1094 WLAN_KEY_LEN_TKIP = 32,
1095};
1096
1088/* 1097/*
1089 * IEEE 802.11-2007 7.3.2.9 Country information element 1098 * IEEE 802.11-2007 7.3.2.9 Country information element
1090 * 1099 *
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 9e17a83d3432..f20da7d63b1e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -56,9 +56,9 @@ enum ieee80211_band {
56 * on this channel. 56 * on this channel.
57 * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. 57 * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel.
58 * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. 58 * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel.
59 * @IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel 59 * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel
60 * is not permitted. 60 * is not permitted.
61 * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel 61 * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
62 * is not permitted. 62 * is not permitted.
63 */ 63 */
64enum ieee80211_channel_flags { 64enum ieee80211_channel_flags {
@@ -66,10 +66,13 @@ enum ieee80211_channel_flags {
66 IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, 66 IEEE80211_CHAN_PASSIVE_SCAN = 1<<1,
67 IEEE80211_CHAN_NO_IBSS = 1<<2, 67 IEEE80211_CHAN_NO_IBSS = 1<<2,
68 IEEE80211_CHAN_RADAR = 1<<3, 68 IEEE80211_CHAN_RADAR = 1<<3,
69 IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, 69 IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
70 IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, 70 IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
71}; 71};
72 72
73#define IEEE80211_CHAN_NO_HT40 \
74 (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS)
75
73/** 76/**
74 * struct ieee80211_channel - channel definition 77 * struct ieee80211_channel - channel definition
75 * 78 *
@@ -778,10 +781,11 @@ enum wiphy_params_flags {
778 * @get_key: get information about the key with the given parameters. 781 * @get_key: get information about the key with the given parameters.
779 * @mac_addr will be %NULL when requesting information for a group 782 * @mac_addr will be %NULL when requesting information for a group
780 * key. All pointers given to the @callback function need not be valid 783 * key. All pointers given to the @callback function need not be valid
781 * after it returns. 784 * after it returns. This function should return an error if it is
785 * not possible to retrieve the key, -ENOENT if it doesn't exist.
782 * 786 *
783 * @del_key: remove a key given the @mac_addr (%NULL for a group key) 787 * @del_key: remove a key given the @mac_addr (%NULL for a group key)
784 * and @key_index 788 * and @key_index, return -ENOENT if the key doesn't exist.
785 * 789 *
786 * @set_default_key: set the default key on an interface 790 * @set_default_key: set the default key on an interface
787 * 791 *
@@ -994,7 +998,7 @@ struct wiphy {
994 * know whether it points to a wiphy your driver has registered 998 * know whether it points to a wiphy your driver has registered
995 * or not. Assign this to something global to your driver to 999 * or not. Assign this to something global to your driver to
996 * help determine whether you own this wiphy or not. */ 1000 * help determine whether you own this wiphy or not. */
997 void *privid; 1001 const void *privid;
998 1002
999 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS]; 1003 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS];
1000 1004
@@ -1070,7 +1074,7 @@ static inline const char *wiphy_name(struct wiphy *wiphy)
1070 * The returned pointer must be assigned to each netdev's 1074 * The returned pointer must be assigned to each netdev's
1071 * ieee80211_ptr for proper operation. 1075 * ieee80211_ptr for proper operation.
1072 */ 1076 */
1073struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv); 1077struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
1074 1078
1075/** 1079/**
1076 * wiphy_register - register a wiphy with cfg80211 1080 * wiphy_register - register a wiphy with cfg80211
@@ -1240,6 +1244,53 @@ extern int ieee80211_radiotap_iterator_init(
1240extern int ieee80211_radiotap_iterator_next( 1244extern int ieee80211_radiotap_iterator_next(
1241 struct ieee80211_radiotap_iterator *iterator); 1245 struct ieee80211_radiotap_iterator *iterator);
1242 1246
1247extern const unsigned char rfc1042_header[6];
1248extern const unsigned char bridge_tunnel_header[6];
1249
1250/**
1251 * ieee80211_get_hdrlen_from_skb - get header length from data
1252 *
1253 * Given an skb with a raw 802.11 header at the data pointer this function
1254 * returns the 802.11 header length in bytes (not including encryption
1255 * headers). If the data in the sk_buff is too short to contain a valid 802.11
1256 * header the function returns 0.
1257 *
1258 * @skb: the frame
1259 */
1260unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
1261
1262/**
1263 * ieee80211_hdrlen - get header length in bytes from frame control
1264 * @fc: frame control field in little-endian format
1265 */
1266unsigned int ieee80211_hdrlen(__le16 fc);
1267
1268/**
1269 * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
1270 * @skb: the 802.11 data frame
1271 * @addr: the device MAC address
1272 * @iftype: the virtual interface type
1273 */
1274int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
1275 enum nl80211_iftype iftype);
1276
1277/**
1278 * ieee80211_data_from_8023 - convert an 802.3 frame to 802.11
1279 * @skb: the 802.3 frame
1280 * @addr: the device MAC address
1281 * @iftype: the virtual interface type
1282 * @bssid: the network bssid (used only for iftype STATION and ADHOC)
1283 * @qos: build 802.11 QoS data frame
1284 */
1285int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr,
1286 enum nl80211_iftype iftype, u8 *bssid, bool qos);
1287
1288/**
1289 * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
1290 * @skb: the data frame
1291 */
1292unsigned int cfg80211_classify8021d(struct sk_buff *skb);
1293
1243/* 1294/*
1244 * Regulatory helper functions for wiphys 1295 * Regulatory helper functions for wiphys
1245 */ 1296 */
@@ -1303,9 +1354,10 @@ extern void wiphy_apply_custom_regulatory(
1303 * freq_reg_info - get regulatory information for the given frequency 1354 * freq_reg_info - get regulatory information for the given frequency
1304 * @wiphy: the wiphy for which we want to process this rule for 1355 * @wiphy: the wiphy for which we want to process this rule for
1305 * @center_freq: Frequency in KHz for which we want regulatory information for 1356 * @center_freq: Frequency in KHz for which we want regulatory information for
1306 * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one 1357 * @desired_bw_khz: the desired max bandwidth you want to use per
1307 * you can set this to 0. If this frequency is allowed we then set 1358 * channel. Note that this is still 20 MHz if you want to use HT40
1308 * this value to the maximum allowed bandwidth. 1359 * as HT40 makes use of two channels for its 40 MHz width bandwidth.
1360 * If set to 0 we'll assume you want the standard 20 MHz.
1309 * @reg_rule: the regulatory rule which we have for this frequency 1361 * @reg_rule: the regulatory rule which we have for this frequency
1310 * 1362 *
1311 * Use this function to get the regulatory rule for a specific frequency on 1363 * Use this function to get the regulatory rule for a specific frequency on
@@ -1320,7 +1372,9 @@ extern void wiphy_apply_custom_regulatory(
1320 * freq_in_rule_band() for our current definition of a band -- this is purely 1372 * freq_in_rule_band() for our current definition of a band -- this is purely
1321 * subjective and right now its 802.11 specific. 1373 * subjective and right now its 802.11 specific.
1322 */ 1374 */
1323extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, 1375extern int freq_reg_info(struct wiphy *wiphy,
1376 u32 center_freq,
1377 u32 desired_bw_khz,
1324 const struct ieee80211_reg_rule **reg_rule); 1378 const struct ieee80211_reg_rule **reg_rule);
1325 1379
1326/* 1380/*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d10ed1776fcd..d72346ff3247 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -173,7 +173,6 @@ enum ieee80211_bss_change {
173 * @timestamp: beacon timestamp 173 * @timestamp: beacon timestamp
174 * @beacon_int: beacon interval 174 * @beacon_int: beacon interval
175 * @assoc_capability: capabilities taken from assoc resp 175 * @assoc_capability: capabilities taken from assoc resp
176 * @ht: BSS's HT configuration
177 * @basic_rates: bitmap of basic rates, each bit stands for an 176 * @basic_rates: bitmap of basic rates, each bit stands for an
178 * index into the rate table configured by the driver in 177 * index into the rate table configured by the driver in
179 * the current band. 178 * the current band.
@@ -673,16 +672,6 @@ enum ieee80211_key_alg {
673}; 672};
674 673
675/** 674/**
676 * enum ieee80211_key_len - key length
677 * @LEN_WEP40: WEP 5-byte long key
678 * @LEN_WEP104: WEP 13-byte long key
679 */
680enum ieee80211_key_len {
681 LEN_WEP40 = 5,
682 LEN_WEP104 = 13,
683};
684
685/**
686 * enum ieee80211_key_flags - key flags 675 * enum ieee80211_key_flags - key flags
687 * 676 *
688 * These flags are used for communication about keys between the driver 677 * These flags are used for communication about keys between the driver
@@ -1813,24 +1802,6 @@ struct sk_buff *
1813ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); 1802ieee80211_get_buffered_bc(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
1814 1803
1815/** 1804/**
1816 * ieee80211_get_hdrlen_from_skb - get header length from data
1817 *
1818 * Given an skb with a raw 802.11 header at the data pointer this function
1819 * returns the 802.11 header length in bytes (not including encryption
1820 * headers). If the data in the sk_buff is too short to contain a valid 802.11
1821 * header the function returns 0.
1822 *
1823 * @skb: the frame
1824 */
1825unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);
1826
1827/**
1828 * ieee80211_hdrlen - get header length in bytes from frame control
1829 * @fc: frame control field in little-endian format
1830 */
1831unsigned int ieee80211_hdrlen(__le16 fc);
1832
1833/**
1834 * ieee80211_get_tkip_key - get a TKIP rc4 for skb 1805 * ieee80211_get_tkip_key - get a TKIP rc4 for skb
1835 * 1806 *
1836 * This function computes a TKIP rc4 key for an skb. It computes 1807 * This function computes a TKIP rc4 key for an skb. It computes
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index e7682fe1c590..11c72311f35b 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -52,14 +52,6 @@ static const struct file_operations name## _ops = { \
52 52
53DEBUGFS_READONLY_FILE(frequency, 20, "%d", 53DEBUGFS_READONLY_FILE(frequency, 20, "%d",
54 local->hw.conf.channel->center_freq); 54 local->hw.conf.channel->center_freq);
55DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
56 local->hw.wiphy->rts_threshold);
57DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
58 local->hw.wiphy->frag_threshold);
59DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
60 local->hw.wiphy->retry_short);
61DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
62 local->hw.wiphy->retry_long);
63DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", 55DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d",
64 local->total_ps_buffered); 56 local->total_ps_buffered);
65DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", 57DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x",
@@ -303,10 +295,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
303 local->debugfs.keys = debugfs_create_dir("keys", phyd); 295 local->debugfs.keys = debugfs_create_dir("keys", phyd);
304 296
305 DEBUGFS_ADD(frequency); 297 DEBUGFS_ADD(frequency);
306 DEBUGFS_ADD(rts_threshold);
307 DEBUGFS_ADD(fragmentation_threshold);
308 DEBUGFS_ADD(short_retry_limit);
309 DEBUGFS_ADD(long_retry_limit);
310 DEBUGFS_ADD(total_ps_buffered); 298 DEBUGFS_ADD(total_ps_buffered);
311 DEBUGFS_ADD(wep_iv); 299 DEBUGFS_ADD(wep_iv);
312 DEBUGFS_ADD(tsf); 300 DEBUGFS_ADD(tsf);
@@ -359,10 +347,6 @@ void debugfs_hw_add(struct ieee80211_local *local)
359void debugfs_hw_del(struct ieee80211_local *local) 347void debugfs_hw_del(struct ieee80211_local *local)
360{ 348{
361 DEBUGFS_DEL(frequency); 349 DEBUGFS_DEL(frequency);
362 DEBUGFS_DEL(rts_threshold);
363 DEBUGFS_DEL(fragmentation_threshold);
364 DEBUGFS_DEL(short_retry_limit);
365 DEBUGFS_DEL(long_retry_limit);
366 DEBUGFS_DEL(total_ps_buffered); 350 DEBUGFS_DEL(total_ps_buffered);
367 DEBUGFS_DEL(wep_iv); 351 DEBUGFS_DEL(wep_iv);
368 DEBUGFS_DEL(tsf); 352 DEBUGFS_DEL(tsf);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index c236079ed38a..0b30277eb366 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -535,9 +535,9 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
535 bssid = ifibss->bssid; 535 bssid = ifibss->bssid;
536 bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid, 536 bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan, bssid,
537 ifibss->ssid, ifibss->ssid_len, 537 ifibss->ssid, ifibss->ssid_len,
538 capability,
539 WLAN_CAPABILITY_IBSS | 538 WLAN_CAPABILITY_IBSS |
540 WLAN_CAPABILITY_PRIVACY); 539 WLAN_CAPABILITY_PRIVACY,
540 capability);
541 541
542#ifdef CONFIG_MAC80211_IBSS_DEBUG 542#ifdef CONFIG_MAC80211_IBSS_DEBUG
543 if (bss) 543 if (bss)
@@ -737,6 +737,9 @@ static void ieee80211_ibss_work(struct work_struct *work)
737 struct ieee80211_if_ibss *ifibss; 737 struct ieee80211_if_ibss *ifibss;
738 struct sk_buff *skb; 738 struct sk_buff *skb;
739 739
740 if (WARN_ON(local->suspended))
741 return;
742
740 if (!netif_running(sdata->dev)) 743 if (!netif_running(sdata->dev))
741 return; 744 return;
742 745
@@ -773,10 +776,36 @@ static void ieee80211_ibss_timer(unsigned long data)
773 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 776 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
774 struct ieee80211_local *local = sdata->local; 777 struct ieee80211_local *local = sdata->local;
775 778
779 if (local->quiescing) {
780 ifibss->timer_running = true;
781 return;
782 }
783
776 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request); 784 set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
777 queue_work(local->hw.workqueue, &ifibss->work); 785 queue_work(local->hw.workqueue, &ifibss->work);
778} 786}
779 787
788#ifdef CONFIG_PM
789void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
790{
791 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
792
793 cancel_work_sync(&ifibss->work);
794 if (del_timer_sync(&ifibss->timer))
795 ifibss->timer_running = true;
796}
797
798void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
799{
800 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
801
802 if (ifibss->timer_running) {
803 add_timer(&ifibss->timer);
804 ifibss->timer_running = false;
805 }
806}
807#endif
808
780void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata) 809void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
781{ 810{
782 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; 811 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 9d1514727f6e..c088c46704a3 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -293,6 +293,7 @@ struct ieee80211_if_managed {
293 int auth_tries; /* retries for auth req */ 293 int auth_tries; /* retries for auth req */
294 int assoc_tries; /* retries for assoc req */ 294 int assoc_tries; /* retries for assoc req */
295 295
296 unsigned long timers_running; /* used for quiesce/restart */
296 bool powersave; /* powersave requested for this iface */ 297 bool powersave; /* powersave requested for this iface */
297 298
298 unsigned long request; 299 unsigned long request;
@@ -333,6 +334,9 @@ struct ieee80211_if_ibss {
333 334
334 unsigned long request; 335 unsigned long request;
335 unsigned long last_scan_completed; 336 unsigned long last_scan_completed;
337
338 bool timer_running;
339
336 bool fixed_bssid; 340 bool fixed_bssid;
337 bool fixed_channel; 341 bool fixed_channel;
338 342
@@ -358,6 +362,8 @@ struct ieee80211_if_mesh {
358 struct timer_list mesh_path_timer; 362 struct timer_list mesh_path_timer;
359 struct sk_buff_head skb_queue; 363 struct sk_buff_head skb_queue;
360 364
365 unsigned long timers_running;
366
361 bool housekeeping; 367 bool housekeeping;
362 368
363 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN]; 369 u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
@@ -609,6 +615,21 @@ struct ieee80211_local {
609 unsigned int filter_flags; /* FIF_* */ 615 unsigned int filter_flags; /* FIF_* */
610 struct iw_statistics wstats; 616 struct iw_statistics wstats;
611 bool tim_in_locked_section; /* see ieee80211_beacon_get() */ 617 bool tim_in_locked_section; /* see ieee80211_beacon_get() */
618
619 /*
620 * suspended is true if we finished all the suspend _and_ we have
621 * not yet come up from resume. This is to be used by mac80211
622 * to ensure driver sanity during suspend and mac80211's own
623 * sanity. It can eventually be used for WoW as well.
624 */
625 bool suspended;
626
627 /*
628 * quiescing is true during the suspend process _only_ to
629 * ease timer cancelling etc.
630 */
631 bool quiescing;
632
612 int tx_headroom; /* required headroom for hardware/radiotap */ 633 int tx_headroom; /* required headroom for hardware/radiotap */
613 634
614 /* Tasklet and skb queue to process calls from IRQ mode. All frames 635 /* Tasklet and skb queue to process calls from IRQ mode. All frames
@@ -758,10 +779,6 @@ struct ieee80211_local {
758 struct dentry *rcdir; 779 struct dentry *rcdir;
759 struct dentry *rcname; 780 struct dentry *rcname;
760 struct dentry *frequency; 781 struct dentry *frequency;
761 struct dentry *rts_threshold;
762 struct dentry *fragmentation_threshold;
763 struct dentry *short_retry_limit;
764 struct dentry *long_retry_limit;
765 struct dentry *total_ps_buffered; 782 struct dentry *total_ps_buffered;
766 struct dentry *wep_iv; 783 struct dentry *wep_iv;
767 struct dentry *tsf; 784 struct dentry *tsf;
@@ -938,6 +955,11 @@ void ieee80211_send_pspoll(struct ieee80211_local *local,
938void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); 955void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
939int ieee80211_max_network_latency(struct notifier_block *nb, 956int ieee80211_max_network_latency(struct notifier_block *nb,
940 unsigned long data, void *dummy); 957 unsigned long data, void *dummy);
958void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
959 struct ieee80211_channel_sw_ie *sw_elem,
960 struct ieee80211_bss *bss);
961void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
962void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
941 963
942/* IBSS code */ 964/* IBSS code */
943void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); 965void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -950,6 +972,8 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
950int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, 972int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
951 struct cfg80211_ibss_params *params); 973 struct cfg80211_ibss_params *params);
952int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata); 974int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
975void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
976void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
953 977
954/* scan/BSS handling */ 978/* scan/BSS handling */
955void ieee80211_scan_work(struct work_struct *work); 979void ieee80211_scan_work(struct work_struct *work);
@@ -960,6 +984,7 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
960int ieee80211_scan_results(struct ieee80211_local *local, 984int ieee80211_scan_results(struct ieee80211_local *local,
961 struct iw_request_info *info, 985 struct iw_request_info *info,
962 char *buf, size_t len); 986 char *buf, size_t len);
987void ieee80211_scan_cancel(struct ieee80211_local *local);
963ieee80211_rx_result 988ieee80211_rx_result
964ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, 989ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
965 struct sk_buff *skb, 990 struct sk_buff *skb,
@@ -1035,14 +1060,6 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
1035void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, 1060void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
1036 struct ieee80211_mgmt *mgmt, 1061 struct ieee80211_mgmt *mgmt,
1037 size_t len); 1062 size_t len);
1038void ieee80211_chswitch_timer(unsigned long data);
1039void ieee80211_chswitch_work(struct work_struct *work);
1040void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
1041 struct ieee80211_channel_sw_ie *sw_elem,
1042 struct ieee80211_bss *bss);
1043void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
1044 u16 capab_info, u8 *pwr_constr_elem,
1045 u8 pwr_constr_elem_len);
1046 1063
1047/* Suspend/resume and hw reconfiguration */ 1064/* Suspend/resume and hw reconfiguration */
1048int ieee80211_reconfig(struct ieee80211_local *local); 1065int ieee80211_reconfig(struct ieee80211_local *local);
@@ -1068,8 +1085,6 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw)
1068 1085
1069/* utility functions/constants */ 1086/* utility functions/constants */
1070extern void *mac80211_wiphy_privid; /* for wiphy privid */ 1087extern void *mac80211_wiphy_privid; /* for wiphy privid */
1071extern const unsigned char rfc1042_header[6];
1072extern const unsigned char bridge_tunnel_header[6];
1073u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, 1088u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
1074 enum nl80211_iftype type); 1089 enum nl80211_iftype type);
1075int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, 1090int ieee80211_frame_duration(struct ieee80211_local *local, size_t len,
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 827ea8e6ee0a..ce267565e180 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -320,7 +320,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
320 case ALG_TKIP: 320 case ALG_TKIP:
321 key->conf.iv_len = TKIP_IV_LEN; 321 key->conf.iv_len = TKIP_IV_LEN;
322 key->conf.icv_len = TKIP_ICV_LEN; 322 key->conf.icv_len = TKIP_ICV_LEN;
323 if (seq && seq_len == 6) { 323 if (seq) {
324 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) { 324 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) {
325 key->u.tkip.rx[i].iv32 = 325 key->u.tkip.rx[i].iv32 =
326 get_unaligned_le32(&seq[2]); 326 get_unaligned_le32(&seq[2]);
@@ -332,7 +332,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
332 case ALG_CCMP: 332 case ALG_CCMP:
333 key->conf.iv_len = CCMP_HDR_LEN; 333 key->conf.iv_len = CCMP_HDR_LEN;
334 key->conf.icv_len = CCMP_MIC_LEN; 334 key->conf.icv_len = CCMP_MIC_LEN;
335 if (seq && seq_len == CCMP_PN_LEN) { 335 if (seq) {
336 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) 336 for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
337 for (j = 0; j < CCMP_PN_LEN; j++) 337 for (j = 0; j < CCMP_PN_LEN; j++)
338 key->u.ccmp.rx_pn[i][j] = 338 key->u.ccmp.rx_pn[i][j] =
@@ -342,7 +342,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
342 case ALG_AES_CMAC: 342 case ALG_AES_CMAC:
343 key->conf.iv_len = 0; 343 key->conf.iv_len = 0;
344 key->conf.icv_len = sizeof(struct ieee80211_mmie); 344 key->conf.icv_len = sizeof(struct ieee80211_mmie);
345 if (seq && seq_len == 6) 345 if (seq)
346 for (j = 0; j < 6; j++) 346 for (j = 0; j < 6; j++)
347 key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1]; 347 key->u.aes_cmac.rx_pn[j] = seq[6 - j - 1];
348 break; 348 break;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 76df5eabf268..6b7e92eaab47 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -219,18 +219,26 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
219 u32 changed) 219 u32 changed)
220{ 220{
221 struct ieee80211_local *local = sdata->local; 221 struct ieee80211_local *local = sdata->local;
222 static const u8 zero[ETH_ALEN] = { 0 };
222 223
223 if (!changed) 224 if (!changed)
224 return; 225 return;
225 226
226 if (sdata->vif.type == NL80211_IFTYPE_STATION) 227 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
227 sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid; 228 /*
228 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) 229 * While not associated, claim a BSSID of all-zeroes
230 * so that drivers don't do any weird things with the
231 * BSSID at that time.
232 */
233 if (sdata->vif.bss_conf.assoc)
234 sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
235 else
236 sdata->vif.bss_conf.bssid = zero;
237 } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
229 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid; 238 sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
230 else if (sdata->vif.type == NL80211_IFTYPE_AP) 239 else if (sdata->vif.type == NL80211_IFTYPE_AP)
231 sdata->vif.bss_conf.bssid = sdata->dev->dev_addr; 240 sdata->vif.bss_conf.bssid = sdata->dev->dev_addr;
232 else if (ieee80211_vif_is_mesh(&sdata->vif)) { 241 else if (ieee80211_vif_is_mesh(&sdata->vif)) {
233 static const u8 zero[ETH_ALEN] = { 0 };
234 sdata->vif.bss_conf.bssid = zero; 242 sdata->vif.bss_conf.bssid = zero;
235 } else { 243 } else {
236 WARN_ON(1); 244 WARN_ON(1);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 9000b01a1671..fc712e60705d 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -21,6 +21,9 @@
21#define CAPAB_OFFSET 17 21#define CAPAB_OFFSET 17
22#define ACCEPT_PLINKS 0x80 22#define ACCEPT_PLINKS 0x80
23 23
24#define TMR_RUNNING_HK 0
25#define TMR_RUNNING_MP 1
26
24int mesh_allocated; 27int mesh_allocated;
25static struct kmem_cache *rm_cache; 28static struct kmem_cache *rm_cache;
26 29
@@ -45,6 +48,12 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
45 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 48 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
46 49
47 ifmsh->housekeeping = true; 50 ifmsh->housekeeping = true;
51
52 if (local->quiescing) {
53 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
54 return;
55 }
56
48 queue_work(local->hw.workqueue, &ifmsh->work); 57 queue_work(local->hw.workqueue, &ifmsh->work);
49} 58}
50 59
@@ -343,6 +352,11 @@ static void ieee80211_mesh_path_timer(unsigned long data)
343 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; 352 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
344 struct ieee80211_local *local = sdata->local; 353 struct ieee80211_local *local = sdata->local;
345 354
355 if (local->quiescing) {
356 set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
357 return;
358 }
359
346 queue_work(local->hw.workqueue, &ifmsh->work); 360 queue_work(local->hw.workqueue, &ifmsh->work);
347} 361}
348 362
@@ -424,6 +438,32 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
424 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); 438 round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
425} 439}
426 440
441#ifdef CONFIG_PM
442void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
443{
444 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
445
446 /* might restart the timer but that doesn't matter */
447 cancel_work_sync(&ifmsh->work);
448
449 /* use atomic bitops in case both timers fire at the same time */
450
451 if (del_timer_sync(&ifmsh->housekeeping_timer))
452 set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
453 if (del_timer_sync(&ifmsh->mesh_path_timer))
454 set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
455}
456
457void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
458{
459 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
460
461 if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
462 add_timer(&ifmsh->housekeeping_timer);
463 if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
464 add_timer(&ifmsh->mesh_path_timer);
465}
466#endif
427 467
428void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) 468void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
429{ 469{
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index d891d7ddccd7..c7d72819cdd2 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -191,12 +191,8 @@ struct mesh_rmc {
191#define PLINK_CATEGORY 30 191#define PLINK_CATEGORY 30
192#define MESH_PATH_SEL_CATEGORY 32 192#define MESH_PATH_SEL_CATEGORY 32
193 193
194/* Mesh Header Flags */
195#define IEEE80211S_FLAGS_AE 0x3
196
197/* Public interfaces */ 194/* Public interfaces */
198/* Various */ 195/* Various */
199int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
200int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, 196int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
201 struct ieee80211_sub_if_data *sdata); 197 struct ieee80211_sub_if_data *sdata);
202int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr, 198int mesh_rmc_check(u8 *addr, struct ieee80211s_hdr *mesh_hdr,
@@ -267,6 +263,8 @@ void mesh_path_timer(unsigned long data);
267void mesh_path_flush_by_nexthop(struct sta_info *sta); 263void mesh_path_flush_by_nexthop(struct sta_info *sta);
268void mesh_path_discard_frame(struct sk_buff *skb, 264void mesh_path_discard_frame(struct sk_buff *skb,
269 struct ieee80211_sub_if_data *sdata); 265 struct ieee80211_sub_if_data *sdata);
266void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
267void mesh_path_restart(struct ieee80211_sub_if_data *sdata);
270 268
271#ifdef CONFIG_MAC80211_MESH 269#ifdef CONFIG_MAC80211_MESH
272extern int mesh_allocated; 270extern int mesh_allocated;
@@ -294,10 +292,20 @@ static inline void mesh_path_activate(struct mesh_path *mpath)
294 292
295void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local); 293void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);
296 294
295void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
296void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata);
297void mesh_plink_quiesce(struct sta_info *sta);
298void mesh_plink_restart(struct sta_info *sta);
297#else 299#else
298#define mesh_allocated 0 300#define mesh_allocated 0
299static inline void 301static inline void
300ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {} 302ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
303static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
304{}
305static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
306{}
307static inline void mesh_plink_quiesce(struct sta_info *sta) {}
308static inline void mesh_plink_restart(struct sta_info *sta) {}
301#endif 309#endif
302 310
303#endif /* IEEE80211S_H */ 311#endif /* IEEE80211S_H */
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 60b35accda91..003cb470ac84 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -836,8 +836,14 @@ void mesh_path_timer(unsigned long data)
836 mpath = rcu_dereference(mpath); 836 mpath = rcu_dereference(mpath);
837 if (!mpath) 837 if (!mpath)
838 goto endmpathtimer; 838 goto endmpathtimer;
839 spin_lock_bh(&mpath->state_lock);
840 sdata = mpath->sdata; 839 sdata = mpath->sdata;
840
841 if (sdata->local->quiescing) {
842 rcu_read_unlock();
843 return;
844 }
845
846 spin_lock_bh(&mpath->state_lock);
841 if (mpath->flags & MESH_PATH_RESOLVED || 847 if (mpath->flags & MESH_PATH_RESOLVED ||
842 (!(mpath->flags & MESH_PATH_RESOLVING))) 848 (!(mpath->flags & MESH_PATH_RESOLVING)))
843 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED); 849 mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index a8bbdeca013a..cb14253587f1 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -266,6 +266,11 @@ static void mesh_plink_timer(unsigned long data)
266 */ 266 */
267 sta = (struct sta_info *) data; 267 sta = (struct sta_info *) data;
268 268
269 if (sta->sdata->local->quiescing) {
270 sta->plink_timer_was_running = true;
271 return;
272 }
273
269 spin_lock_bh(&sta->lock); 274 spin_lock_bh(&sta->lock);
270 if (sta->ignore_plink_timer) { 275 if (sta->ignore_plink_timer) {
271 sta->ignore_plink_timer = false; 276 sta->ignore_plink_timer = false;
@@ -322,6 +327,22 @@ static void mesh_plink_timer(unsigned long data)
322 } 327 }
323} 328}
324 329
330#ifdef CONFIG_PM
331void mesh_plink_quiesce(struct sta_info *sta)
332{
333 if (del_timer_sync(&sta->plink_timer))
334 sta->plink_timer_was_running = true;
335}
336
337void mesh_plink_restart(struct sta_info *sta)
338{
339 if (sta->plink_timer_was_running) {
340 add_timer(&sta->plink_timer);
341 sta->plink_timer_was_running = false;
342 }
343}
344#endif
345
325static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) 346static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
326{ 347{
327 sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); 348 sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index ae030688771f..509469cb9265 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -33,10 +33,13 @@
33#define IEEE80211_ASSOC_TIMEOUT (HZ / 5) 33#define IEEE80211_ASSOC_TIMEOUT (HZ / 5)
34#define IEEE80211_ASSOC_MAX_TRIES 3 34#define IEEE80211_ASSOC_MAX_TRIES 3
35#define IEEE80211_MONITORING_INTERVAL (2 * HZ) 35#define IEEE80211_MONITORING_INTERVAL (2 * HZ)
36#define IEEE80211_PROBE_WAIT (HZ / 20) 36#define IEEE80211_PROBE_WAIT (HZ / 5)
37#define IEEE80211_PROBE_IDLE_TIME (60 * HZ) 37#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
38#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ) 38#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)
39 39
40#define TMR_RUNNING_TIMER 0
41#define TMR_RUNNING_CHANSW 1
42
40/* utils */ 43/* utils */
41static int ecw2cw(int ecw) 44static int ecw2cw(int ecw)
42{ 45{
@@ -121,10 +124,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
121 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { 124 (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
122 switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 125 switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
123 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 126 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
124 channel_type = NL80211_CHAN_HT40PLUS; 127 if (!(local->hw.conf.channel->flags &
128 IEEE80211_CHAN_NO_HT40PLUS))
129 channel_type = NL80211_CHAN_HT40PLUS;
125 break; 130 break;
126 case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 131 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
127 channel_type = NL80211_CHAN_HT40MINUS; 132 if (!(local->hw.conf.channel->flags &
133 IEEE80211_CHAN_NO_HT40MINUS))
134 channel_type = NL80211_CHAN_HT40MINUS;
128 break; 135 break;
129 } 136 }
130 } 137 }
@@ -349,13 +356,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
349 356
350 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { 357 switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
351 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: 358 case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
352 if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { 359 if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
353 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 360 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
354 cap &= ~IEEE80211_HT_CAP_SGI_40; 361 cap &= ~IEEE80211_HT_CAP_SGI_40;
355 } 362 }
356 break; 363 break;
357 case IEEE80211_HT_PARAM_CHA_SEC_BELOW: 364 case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
358 if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { 365 if (flags & IEEE80211_CHAN_NO_HT40MINUS) {
359 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; 366 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
360 cap &= ~IEEE80211_HT_CAP_SGI_40; 367 cap &= ~IEEE80211_HT_CAP_SGI_40;
361 } 368 }
@@ -482,6 +489,108 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
482 ieee80211_tx_skb(sdata, skb, 0); 489 ieee80211_tx_skb(sdata, skb, 0);
483} 490}
484 491
492/* spectrum management related things */
493static void ieee80211_chswitch_work(struct work_struct *work)
494{
495 struct ieee80211_sub_if_data *sdata =
496 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
497 struct ieee80211_bss *bss;
498 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
499
500 if (!netif_running(sdata->dev))
501 return;
502
503 bss = ieee80211_rx_bss_get(sdata->local, ifmgd->bssid,
504 sdata->local->hw.conf.channel->center_freq,
505 ifmgd->ssid, ifmgd->ssid_len);
506 if (!bss)
507 goto exit;
508
509 sdata->local->oper_channel = sdata->local->csa_channel;
510 /* XXX: shouldn't really modify cfg80211-owned data! */
511 if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
512 bss->cbss.channel = sdata->local->oper_channel;
513
514 ieee80211_rx_bss_put(sdata->local, bss);
515exit:
516 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
517 ieee80211_wake_queues_by_reason(&sdata->local->hw,
518 IEEE80211_QUEUE_STOP_REASON_CSA);
519}
520
521static void ieee80211_chswitch_timer(unsigned long data)
522{
523 struct ieee80211_sub_if_data *sdata =
524 (struct ieee80211_sub_if_data *) data;
525 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
526
527 if (sdata->local->quiescing) {
528 set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
529 return;
530 }
531
532 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
533}
534
535void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
536 struct ieee80211_channel_sw_ie *sw_elem,
537 struct ieee80211_bss *bss)
538{
539 struct ieee80211_channel *new_ch;
540 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
541 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
542
543 if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATED)
544 return;
545
546 if (sdata->local->sw_scanning || sdata->local->hw_scanning)
547 return;
548
549 /* Disregard subsequent beacons if we are already running a timer
550 processing a CSA */
551
552 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
553 return;
554
555 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
556 if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED)
557 return;
558
559 sdata->local->csa_channel = new_ch;
560
561 if (sw_elem->count <= 1) {
562 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
563 } else {
564 ieee80211_stop_queues_by_reason(&sdata->local->hw,
565 IEEE80211_QUEUE_STOP_REASON_CSA);
566 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
567 mod_timer(&ifmgd->chswitch_timer,
568 jiffies +
569 msecs_to_jiffies(sw_elem->count *
570 bss->cbss.beacon_interval));
571 }
572}
573
574static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
575 u16 capab_info, u8 *pwr_constr_elem,
576 u8 pwr_constr_elem_len)
577{
578 struct ieee80211_conf *conf = &sdata->local->hw.conf;
579
580 if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
581 return;
582
583 /* Power constraint IE length should be 1 octet */
584 if (pwr_constr_elem_len != 1)
585 return;
586
587 if ((*pwr_constr_elem <= conf->channel->max_power) &&
588 (*pwr_constr_elem != sdata->local->power_constr_level)) {
589 sdata->local->power_constr_level = *pwr_constr_elem;
590 ieee80211_hw_config(sdata->local, 0);
591 }
592}
593
485/* powersave */ 594/* powersave */
486static void ieee80211_enable_ps(struct ieee80211_local *local, 595static void ieee80211_enable_ps(struct ieee80211_local *local,
487 struct ieee80211_sub_if_data *sdata) 596 struct ieee80211_sub_if_data *sdata)
@@ -613,6 +722,9 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
613{ 722{
614 struct ieee80211_local *local = (void *) data; 723 struct ieee80211_local *local = (void *) data;
615 724
725 if (local->quiescing)
726 return;
727
616 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); 728 queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
617} 729}
618 730
@@ -865,6 +977,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
865 * changed or not. 977 * changed or not.
866 */ 978 */
867 bss_info_changed |= BSS_CHANGED_BASIC_RATES; 979 bss_info_changed |= BSS_CHANGED_BASIC_RATES;
980
981 /* And the BSSID changed - we're associated now */
982 bss_info_changed |= BSS_CHANGED_BSSID;
983
868 ieee80211_bss_info_change_notify(sdata, bss_info_changed); 984 ieee80211_bss_info_change_notify(sdata, bss_info_changed);
869 985
870 /* will be same as sdata */ 986 /* will be same as sdata */
@@ -1064,6 +1180,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
1064 } 1180 }
1065 1181
1066 ieee80211_hw_config(local, config_changed); 1182 ieee80211_hw_config(local, config_changed);
1183
1184 /* And the BSSID changed -- not very interesting here */
1185 changed |= BSS_CHANGED_BSSID;
1067 ieee80211_bss_info_change_notify(sdata, changed); 1186 ieee80211_bss_info_change_notify(sdata, changed);
1068 1187
1069 rcu_read_lock(); 1188 rcu_read_lock();
@@ -1270,8 +1389,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
1270 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL; 1389 ifmgd->flags |= IEEE80211_STA_PROBEREQ_POLL;
1271 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid, 1390 ieee80211_send_probe_req(sdata, ifmgd->bssid, ifmgd->ssid,
1272 ifmgd->ssid_len, NULL, 0); 1391 ifmgd->ssid_len, NULL, 0);
1392 mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT);
1273 goto unlock; 1393 goto unlock;
1274
1275 } 1394 }
1276 1395
1277 if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) { 1396 if (time_after(jiffies, sta->last_rx + IEEE80211_PROBE_IDLE_TIME)) {
@@ -1280,15 +1399,16 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata)
1280 ifmgd->ssid_len, NULL, 0); 1399 ifmgd->ssid_len, NULL, 0);
1281 } 1400 }
1282 1401
1402 if (!disassoc)
1403 mod_timer(&ifmgd->timer,
1404 jiffies + IEEE80211_MONITORING_INTERVAL);
1405
1283 unlock: 1406 unlock:
1284 rcu_read_unlock(); 1407 rcu_read_unlock();
1285 1408
1286 if (disassoc) 1409 if (disassoc)
1287 ieee80211_set_disassoc(sdata, true, true, 1410 ieee80211_set_disassoc(sdata, true, true,
1288 WLAN_REASON_PREV_AUTH_NOT_VALID); 1411 WLAN_REASON_PREV_AUTH_NOT_VALID);
1289 else
1290 mod_timer(&ifmgd->timer, jiffies +
1291 IEEE80211_MONITORING_INTERVAL);
1292} 1412}
1293 1413
1294 1414
@@ -1732,7 +1852,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
1732 (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) { 1852 (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN) == 0)) {
1733 struct ieee80211_channel_sw_ie *sw_elem = 1853 struct ieee80211_channel_sw_ie *sw_elem =
1734 (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; 1854 (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem;
1735 ieee80211_process_chanswitch(sdata, sw_elem, bss); 1855 ieee80211_sta_process_chanswitch(sdata, sw_elem, bss);
1736 } 1856 }
1737 1857
1738 ieee80211_rx_bss_put(local, bss); 1858 ieee80211_rx_bss_put(local, bss);
@@ -1820,6 +1940,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1820 memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0) 1940 memcmp(ifmgd->bssid, mgmt->bssid, ETH_ALEN) != 0)
1821 return; 1941 return;
1822 1942
1943 if (ifmgd->flags & IEEE80211_STA_PROBEREQ_POLL) {
1944#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
1945 if (net_ratelimit()) {
1946 printk(KERN_DEBUG "%s: cancelling probereq poll due "
1947 "to a received beacon\n", sdata->dev->name);
1948 }
1949#endif
1950 ifmgd->flags &= ~IEEE80211_STA_PROBEREQ_POLL;
1951 }
1952
1823 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); 1953 ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
1824 ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable, 1954 ncrc = ieee802_11_parse_elems_crc(mgmt->u.beacon.variable,
1825 len - baselen, &elems, 1955 len - baselen, &elems,
@@ -1829,16 +1959,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1829 directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len, 1959 directed_tim = ieee80211_check_tim(elems.tim, elems.tim_len,
1830 ifmgd->aid); 1960 ifmgd->aid);
1831 1961
1832 ncrc = crc32_be(ncrc, (void *)&directed_tim, sizeof(directed_tim)); 1962 if (ncrc != ifmgd->beacon_crc) {
1963 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems,
1964 true);
1833 1965
1834 if (ncrc == ifmgd->beacon_crc) 1966 ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
1835 return; 1967 elems.wmm_param_len);
1836 ifmgd->beacon_crc = ncrc; 1968 }
1837
1838 ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
1839
1840 ieee80211_sta_wmm_params(local, ifmgd, elems.wmm_param,
1841 elems.wmm_param_len);
1842 1969
1843 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) { 1970 if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
1844 if (directed_tim) { 1971 if (directed_tim) {
@@ -1863,6 +1990,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
1863 } 1990 }
1864 } 1991 }
1865 1992
1993 if (ncrc == ifmgd->beacon_crc)
1994 return;
1995 ifmgd->beacon_crc = ncrc;
1996
1866 if (elems.erp_info && elems.erp_info_len >= 1) { 1997 if (elems.erp_info && elems.erp_info_len >= 1) {
1867 erp_valid = true; 1998 erp_valid = true;
1868 erp_value = elems.erp_info[0]; 1999 erp_value = elems.erp_info[0];
@@ -1997,6 +2128,11 @@ static void ieee80211_sta_timer(unsigned long data)
1997 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2128 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1998 struct ieee80211_local *local = sdata->local; 2129 struct ieee80211_local *local = sdata->local;
1999 2130
2131 if (local->quiescing) {
2132 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
2133 return;
2134 }
2135
2000 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request); 2136 set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
2001 queue_work(local->hw.workqueue, &ifmgd->work); 2137 queue_work(local->hw.workqueue, &ifmgd->work);
2002} 2138}
@@ -2129,6 +2265,17 @@ static void ieee80211_sta_work(struct work_struct *work)
2129 2265
2130 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) 2266 if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
2131 return; 2267 return;
2268
2269 /*
2270 * Nothing should have been stuffed into the workqueue during
2271 * the suspend->resume cycle. If this WARN is seen then there
2272 * is a bug with either the driver suspend or something in
2273 * mac80211 stuffing into the workqueue which we haven't yet
2274 * cleared during mac80211's suspend cycle.
2275 */
2276 if (WARN_ON(local->suspended))
2277 return;
2278
2132 ifmgd = &sdata->u.mgd; 2279 ifmgd = &sdata->u.mgd;
2133 2280
2134 while ((skb = skb_dequeue(&ifmgd->skb_queue))) 2281 while ((skb = skb_dequeue(&ifmgd->skb_queue)))
@@ -2196,6 +2343,38 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
2196 } 2343 }
2197} 2344}
2198 2345
2346#ifdef CONFIG_PM
2347void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
2348{
2349 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2350
2351 /*
2352 * we need to use atomic bitops for the running bits
2353 * only because both timers might fire at the same
2354 * time -- the code here is properly synchronised.
2355 */
2356
2357 cancel_work_sync(&ifmgd->work);
2358 cancel_work_sync(&ifmgd->beacon_loss_work);
2359 if (del_timer_sync(&ifmgd->timer))
2360 set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
2361
2362 cancel_work_sync(&ifmgd->chswitch_work);
2363 if (del_timer_sync(&ifmgd->chswitch_timer))
2364 set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
2365}
2366
2367void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
2368{
2369 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2370
2371 if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
2372 add_timer(&ifmgd->timer);
2373 if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
2374 add_timer(&ifmgd->chswitch_timer);
2375}
2376#endif
2377
2199/* interface setup */ 2378/* interface setup */
2200void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) 2379void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
2201{ 2380{
@@ -2310,9 +2489,6 @@ int ieee80211_sta_set_bssid(struct ieee80211_sub_if_data *sdata, u8 *bssid)
2310 ifmgd->flags &= ~IEEE80211_STA_BSSID_SET; 2489 ifmgd->flags &= ~IEEE80211_STA_BSSID_SET;
2311 } 2490 }
2312 2491
2313 if (netif_running(sdata->dev))
2314 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
2315
2316 return ieee80211_sta_commit(sdata); 2492 return ieee80211_sta_commit(sdata);
2317} 2493}
2318 2494
@@ -2321,6 +2497,13 @@ int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
2321{ 2497{
2322 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2498 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2323 2499
2500 if (len == 0 && ifmgd->extra_ie_len == 0)
2501 return -EALREADY;
2502
2503 if (len == ifmgd->extra_ie_len && ifmgd->extra_ie &&
2504 memcmp(ifmgd->extra_ie, ie, len) == 0)
2505 return -EALREADY;
2506
2324 kfree(ifmgd->extra_ie); 2507 kfree(ifmgd->extra_ie);
2325 if (len == 0) { 2508 if (len == 0) {
2326 ifmgd->extra_ie = NULL; 2509 ifmgd->extra_ie = NULL;
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index 9d3d89abbb57..7a549f9deb96 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -2,6 +2,7 @@
2#include <net/rtnetlink.h> 2#include <net/rtnetlink.h>
3 3
4#include "ieee80211_i.h" 4#include "ieee80211_i.h"
5#include "mesh.h"
5#include "driver-ops.h" 6#include "driver-ops.h"
6#include "led.h" 7#include "led.h"
7 8
@@ -13,11 +14,30 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
13 struct sta_info *sta; 14 struct sta_info *sta;
14 unsigned long flags; 15 unsigned long flags;
15 16
17 ieee80211_scan_cancel(local);
18
16 ieee80211_stop_queues_by_reason(hw, 19 ieee80211_stop_queues_by_reason(hw,
17 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 20 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
18 21
22 /* flush out all packets */
23 synchronize_net();
24
25 local->quiescing = true;
26 /* make quiescing visible to timers everywhere */
27 mb();
28
19 flush_workqueue(local->hw.workqueue); 29 flush_workqueue(local->hw.workqueue);
20 30
31 /* Don't try to run timers while suspended. */
32 del_timer_sync(&local->sta_cleanup);
33
34 /*
35 * Note that this particular timer doesn't need to be
36 * restarted at resume.
37 */
38 cancel_work_sync(&local->dynamic_ps_enable_work);
39 del_timer_sync(&local->dynamic_ps_timer);
40
21 /* disable keys */ 41 /* disable keys */
22 list_for_each_entry(sdata, &local->interfaces, list) 42 list_for_each_entry(sdata, &local->interfaces, list)
23 ieee80211_disable_keys(sdata); 43 ieee80211_disable_keys(sdata);
@@ -35,10 +55,20 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
35 55
36 rcu_read_unlock(); 56 rcu_read_unlock();
37 57
58 /* flush again, in case driver queued work */
59 flush_workqueue(local->hw.workqueue);
60
61 /* stop hardware - this must stop RX */
62 if (local->open_count) {
63 ieee80211_led_radio(local, false);
64 drv_stop(local);
65 }
66
38 /* remove STAs */ 67 /* remove STAs */
39 if (local->ops->sta_notify) { 68 spin_lock_irqsave(&local->sta_lock, flags);
40 spin_lock_irqsave(&local->sta_lock, flags); 69 list_for_each_entry(sta, &local->sta_list, list) {
41 list_for_each_entry(sta, &local->sta_list, list) { 70 if (local->ops->sta_notify) {
71 sdata = sta->sdata;
42 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 72 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
43 sdata = container_of(sdata->bss, 73 sdata = container_of(sdata->bss,
44 struct ieee80211_sub_if_data, 74 struct ieee80211_sub_if_data,
@@ -47,29 +77,43 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
47 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE, 77 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
48 &sta->sta); 78 &sta->sta);
49 } 79 }
50 spin_unlock_irqrestore(&local->sta_lock, flags); 80
81 mesh_plink_quiesce(sta);
51 } 82 }
83 spin_unlock_irqrestore(&local->sta_lock, flags);
52 84
53 /* remove all interfaces */ 85 /* remove all interfaces */
54 list_for_each_entry(sdata, &local->interfaces, list) { 86 list_for_each_entry(sdata, &local->interfaces, list) {
55 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 87 switch(sdata->vif.type) {
56 sdata->vif.type != NL80211_IFTYPE_MONITOR && 88 case NL80211_IFTYPE_STATION:
57 netif_running(sdata->dev)) { 89 ieee80211_sta_quiesce(sdata);
58 conf.vif = &sdata->vif; 90 break;
59 conf.type = sdata->vif.type; 91 case NL80211_IFTYPE_ADHOC:
60 conf.mac_addr = sdata->dev->dev_addr; 92 ieee80211_ibss_quiesce(sdata);
61 drv_remove_interface(local, &conf); 93 break;
94 case NL80211_IFTYPE_MESH_POINT:
95 ieee80211_mesh_quiesce(sdata);
96 break;
97 case NL80211_IFTYPE_AP_VLAN:
98 case NL80211_IFTYPE_MONITOR:
99 /* don't tell driver about this */
100 continue;
101 default:
102 break;
62 } 103 }
63 }
64 104
65 /* flush again, in case driver queued work */ 105 if (!netif_running(sdata->dev))
66 flush_workqueue(local->hw.workqueue); 106 continue;
67 107
68 /* stop hardware */ 108 conf.vif = &sdata->vif;
69 if (local->open_count) { 109 conf.type = sdata->vif.type;
70 ieee80211_led_radio(local, false); 110 conf.mac_addr = sdata->dev->dev_addr;
71 drv_stop(local); 111 drv_remove_interface(local, &conf);
72 } 112 }
113
114 local->suspended = true;
115 local->quiescing = false;
116
73 return 0; 117 return 0;
74} 118}
75 119
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index f962bd1b16e2..6a9b8e63a6bf 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1247,93 +1247,12 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
1247} 1247}
1248 1248
1249static int 1249static int
1250ieee80211_data_to_8023(struct ieee80211_rx_data *rx) 1250__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
1251{ 1251{
1252 struct net_device *dev = rx->dev; 1252 struct net_device *dev = rx->dev;
1253 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
1254 u16 hdrlen, ethertype;
1255 u8 *payload;
1256 u8 dst[ETH_ALEN];
1257 u8 src[ETH_ALEN] __aligned(2);
1258 struct sk_buff *skb = rx->skb;
1259 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 1253 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
1260 1254
1261 if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) 1255 return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type);
1262 return -1;
1263
1264 hdrlen = ieee80211_hdrlen(hdr->frame_control);
1265
1266 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
1267 * header
1268 * IEEE 802.11 address fields:
1269 * ToDS FromDS Addr1 Addr2 Addr3 Addr4
1270 * 0 0 DA SA BSSID n/a
1271 * 0 1 DA BSSID SA n/a
1272 * 1 0 BSSID SA DA n/a
1273 * 1 1 RA TA DA SA
1274 */
1275 memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
1276 memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
1277
1278 switch (hdr->frame_control &
1279 cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
1280 case cpu_to_le16(IEEE80211_FCTL_TODS):
1281 if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP &&
1282 sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
1283 return -1;
1284 break;
1285 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
1286 if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS &&
1287 sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
1288 return -1;
1289 if (ieee80211_vif_is_mesh(&sdata->vif)) {
1290 struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *)
1291 (skb->data + hdrlen);
1292 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
1293 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
1294 memcpy(dst, meshdr->eaddr1, ETH_ALEN);
1295 memcpy(src, meshdr->eaddr2, ETH_ALEN);
1296 }
1297 }
1298 break;
1299 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
1300 if (sdata->vif.type != NL80211_IFTYPE_STATION ||
1301 (is_multicast_ether_addr(dst) &&
1302 !compare_ether_addr(src, dev->dev_addr)))
1303 return -1;
1304 break;
1305 case cpu_to_le16(0):
1306 if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
1307 return -1;
1308 break;
1309 }
1310
1311 if (unlikely(skb->len - hdrlen < 8))
1312 return -1;
1313
1314 payload = skb->data + hdrlen;
1315 ethertype = (payload[6] << 8) | payload[7];
1316
1317 if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
1318 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
1319 compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
1320 /* remove RFC1042 or Bridge-Tunnel encapsulation and
1321 * replace EtherType */
1322 skb_pull(skb, hdrlen + 6);
1323 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
1324 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
1325 } else {
1326 struct ethhdr *ehdr;
1327 __be16 len;
1328
1329 skb_pull(skb, hdrlen);
1330 len = htons(skb->len);
1331 ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
1332 memcpy(ehdr->h_dest, dst, ETH_ALEN);
1333 memcpy(ehdr->h_source, src, ETH_ALEN);
1334 ehdr->h_proto = len;
1335 }
1336 return 0;
1337} 1256}
1338 1257
1339/* 1258/*
@@ -1472,7 +1391,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
1472 if (!(rx->flags & IEEE80211_RX_AMSDU)) 1391 if (!(rx->flags & IEEE80211_RX_AMSDU))
1473 return RX_CONTINUE; 1392 return RX_CONTINUE;
1474 1393
1475 err = ieee80211_data_to_8023(rx); 1394 err = __ieee80211_data_to_8023(rx);
1476 if (unlikely(err)) 1395 if (unlikely(err))
1477 return RX_DROP_UNUSABLE; 1396 return RX_DROP_UNUSABLE;
1478 1397
@@ -1658,7 +1577,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1658 if (unlikely(!ieee80211_is_data_present(hdr->frame_control))) 1577 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
1659 return RX_DROP_MONITOR; 1578 return RX_DROP_MONITOR;
1660 1579
1661 err = ieee80211_data_to_8023(rx); 1580 err = __ieee80211_data_to_8023(rx);
1662 if (unlikely(err)) 1581 if (unlikely(err))
1663 return RX_DROP_UNUSABLE; 1582 return RX_DROP_UNUSABLE;
1664 1583
@@ -1846,6 +1765,9 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1846 sizeof(mgmt->u.action.u.chan_switch))) 1765 sizeof(mgmt->u.action.u.chan_switch)))
1847 return RX_DROP_MONITOR; 1766 return RX_DROP_MONITOR;
1848 1767
1768 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1769 return RX_DROP_MONITOR;
1770
1849 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN)) 1771 if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
1850 return RX_DROP_MONITOR; 1772 return RX_DROP_MONITOR;
1851 1773
@@ -1856,7 +1778,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
1856 if (!bss) 1778 if (!bss)
1857 return RX_DROP_MONITOR; 1779 return RX_DROP_MONITOR;
1858 1780
1859 ieee80211_process_chanswitch(sdata, 1781 ieee80211_sta_process_chanswitch(sdata,
1860 &mgmt->u.action.u.chan_switch.sw_elem, bss); 1782 &mgmt->u.action.u.chan_switch.sw_elem, bss);
1861 ieee80211_rx_bss_put(local, bss); 1783 ieee80211_rx_bss_put(local, bss);
1862 break; 1784 break;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index e65d74ba404b..2a8d09ad17ff 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -631,3 +631,21 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
631 mutex_unlock(&local->scan_mtx); 631 mutex_unlock(&local->scan_mtx);
632 return ret; 632 return ret;
633} 633}
634
635void ieee80211_scan_cancel(struct ieee80211_local *local)
636{
637 bool swscan;
638
639 cancel_delayed_work_sync(&local->scan_work);
640
641 /*
642 * Only call this function when a scan can't be
643 * queued -- mostly at suspend under RTNL.
644 */
645 mutex_lock(&local->scan_mtx);
646 swscan = local->sw_scanning;
647 mutex_unlock(&local->scan_mtx);
648
649 if (swscan)
650 ieee80211_scan_completed(&local->hw, true);
651}
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 48bf78e7fa7a..68953033403d 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -84,104 +84,3 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
84 mgmt->sa, mgmt->bssid, 84 mgmt->sa, mgmt->bssid,
85 mgmt->u.action.u.measurement.dialog_token); 85 mgmt->u.action.u.measurement.dialog_token);
86} 86}
87
88void ieee80211_chswitch_work(struct work_struct *work)
89{
90 struct ieee80211_sub_if_data *sdata =
91 container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work);
92 struct ieee80211_bss *bss;
93 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
94
95 if (!netif_running(sdata->dev))
96 return;
97
98 bss = ieee80211_rx_bss_get(sdata->local, ifmgd->bssid,
99 sdata->local->hw.conf.channel->center_freq,
100 ifmgd->ssid, ifmgd->ssid_len);
101 if (!bss)
102 goto exit;
103
104 sdata->local->oper_channel = sdata->local->csa_channel;
105 /* XXX: shouldn't really modify cfg80211-owned data! */
106 if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
107 bss->cbss.channel = sdata->local->oper_channel;
108
109 ieee80211_rx_bss_put(sdata->local, bss);
110exit:
111 ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
112 ieee80211_wake_queues_by_reason(&sdata->local->hw,
113 IEEE80211_QUEUE_STOP_REASON_CSA);
114}
115
116void ieee80211_chswitch_timer(unsigned long data)
117{
118 struct ieee80211_sub_if_data *sdata =
119 (struct ieee80211_sub_if_data *) data;
120 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
121
122 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
123}
124
125void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
126 struct ieee80211_channel_sw_ie *sw_elem,
127 struct ieee80211_bss *bss)
128{
129 struct ieee80211_channel *new_ch;
130 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
131 int new_freq = ieee80211_channel_to_frequency(sw_elem->new_ch_num);
132
133 /* FIXME: Handle ADHOC later */
134 if (sdata->vif.type != NL80211_IFTYPE_STATION)
135 return;
136
137 if (ifmgd->state != IEEE80211_STA_MLME_ASSOCIATED)
138 return;
139
140 if (sdata->local->sw_scanning || sdata->local->hw_scanning)
141 return;
142
143 /* Disregard subsequent beacons if we are already running a timer
144 processing a CSA */
145
146 if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED)
147 return;
148
149 new_ch = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
150 if (!new_ch || new_ch->flags & IEEE80211_CHAN_DISABLED)
151 return;
152
153 sdata->local->csa_channel = new_ch;
154
155 if (sw_elem->count <= 1) {
156 queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
157 } else {
158 ieee80211_stop_queues_by_reason(&sdata->local->hw,
159 IEEE80211_QUEUE_STOP_REASON_CSA);
160 ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED;
161 mod_timer(&ifmgd->chswitch_timer,
162 jiffies +
163 msecs_to_jiffies(sw_elem->count *
164 bss->cbss.beacon_interval));
165 }
166}
167
168void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
169 u16 capab_info, u8 *pwr_constr_elem,
170 u8 pwr_constr_elem_len)
171{
172 struct ieee80211_conf *conf = &sdata->local->hw.conf;
173
174 if (!(capab_info & WLAN_CAPABILITY_SPECTRUM_MGMT))
175 return;
176
177 /* Power constraint IE length should be 1 octet */
178 if (pwr_constr_elem_len != 1)
179 return;
180
181 if ((*pwr_constr_elem <= conf->channel->max_power) &&
182 (*pwr_constr_elem != sdata->local->power_constr_level)) {
183 sdata->local->power_constr_level = *pwr_constr_elem;
184 ieee80211_hw_config(sdata->local, 0);
185 }
186}
187
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a98ea273a155..d5611d8fd0d6 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -293,6 +293,9 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
293 skb_queue_head_init(&sta->ps_tx_buf); 293 skb_queue_head_init(&sta->ps_tx_buf);
294 skb_queue_head_init(&sta->tx_filtered); 294 skb_queue_head_init(&sta->tx_filtered);
295 295
296 for (i = 0; i < NUM_RX_DATA_QUEUES; i++)
297 sta->last_seq_ctrl[i] = cpu_to_le16(USHORT_MAX);
298
296#ifdef CONFIG_MAC80211_VERBOSE_DEBUG 299#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
297 printk(KERN_DEBUG "%s: Allocated STA %pM\n", 300 printk(KERN_DEBUG "%s: Allocated STA %pM\n",
298 wiphy_name(local->hw.wiphy), sta->sta.addr); 301 wiphy_name(local->hw.wiphy), sta->sta.addr);
@@ -608,6 +611,9 @@ static void sta_info_cleanup(unsigned long data)
608 sta_info_cleanup_expire_buffered(local, sta); 611 sta_info_cleanup_expire_buffered(local, sta);
609 rcu_read_unlock(); 612 rcu_read_unlock();
610 613
614 if (local->quiescing)
615 return;
616
611 local->sta_cleanup.expires = 617 local->sta_cleanup.expires =
612 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL); 618 round_jiffies(jiffies + STA_INFO_CLEANUP_INTERVAL);
613 add_timer(&local->sta_cleanup); 619 add_timer(&local->sta_cleanup);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 164b16cbe0a5..49a1a1f76511 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -216,6 +216,7 @@ struct sta_ampdu_mlme {
216 * @plink_state: peer link state 216 * @plink_state: peer link state
217 * @plink_timeout: timeout of peer link 217 * @plink_timeout: timeout of peer link
218 * @plink_timer: peer link watch timer 218 * @plink_timer: peer link watch timer
219 * @plink_timer_was_running: used by suspend/resume to restore timers
219 * @debugfs: debug filesystem info 220 * @debugfs: debug filesystem info
220 * @sta: station information we share with the driver 221 * @sta: station information we share with the driver
221 */ 222 */
@@ -293,6 +294,7 @@ struct sta_info {
293 __le16 reason; 294 __le16 reason;
294 u8 plink_retries; 295 u8 plink_retries;
295 bool ignore_plink_timer; 296 bool ignore_plink_timer;
297 bool plink_timer_was_running;
296 enum plink_state plink_state; 298 enum plink_state plink_state;
297 u32 plink_timeout; 299 u32 plink_timeout;
298 struct timer_list plink_timer; 300 struct timer_list plink_timer;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8f68bf9746d0..a910148b8228 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -872,6 +872,8 @@ ieee80211_tx_h_calculate_duration(struct ieee80211_tx_data *tx)
872 872
873 do { 873 do {
874 hdr = (void *) skb->data; 874 hdr = (void *) skb->data;
875 if (unlikely(ieee80211_is_pspoll(hdr->frame_control)))
876 break; /* must not overwrite AID */
875 next_len = skb->next ? skb->next->len : 0; 877 next_len = skb->next ? skb->next->len : 0;
876 group_addr = is_multicast_ether_addr(hdr->addr1); 878 group_addr = is_multicast_ether_addr(hdr->addr1);
877 879
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0689a8fbd1e6..949d857debd8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -35,15 +35,6 @@
35/* privid for wiphys to determine whether they belong to us or not */ 35/* privid for wiphys to determine whether they belong to us or not */
36void *mac80211_wiphy_privid = &mac80211_wiphy_privid; 36void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
37 37
38/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
39/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
40const unsigned char rfc1042_header[] __aligned(2) =
41 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
42
43/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
44const unsigned char bridge_tunnel_header[] __aligned(2) =
45 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
46
47struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) 38struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
48{ 39{
49 struct ieee80211_local *local; 40 struct ieee80211_local *local;
@@ -103,70 +94,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
103 return NULL; 94 return NULL;
104} 95}
105 96
106unsigned int ieee80211_hdrlen(__le16 fc)
107{
108 unsigned int hdrlen = 24;
109
110 if (ieee80211_is_data(fc)) {
111 if (ieee80211_has_a4(fc))
112 hdrlen = 30;
113 if (ieee80211_is_data_qos(fc))
114 hdrlen += IEEE80211_QOS_CTL_LEN;
115 goto out;
116 }
117
118 if (ieee80211_is_ctl(fc)) {
119 /*
120 * ACK and CTS are 10 bytes, all others 16. To see how
121 * to get this condition consider
122 * subtype mask: 0b0000000011110000 (0x00F0)
123 * ACK subtype: 0b0000000011010000 (0x00D0)
124 * CTS subtype: 0b0000000011000000 (0x00C0)
125 * bits that matter: ^^^ (0x00E0)
126 * value of those: 0b0000000011000000 (0x00C0)
127 */
128 if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
129 hdrlen = 10;
130 else
131 hdrlen = 16;
132 }
133out:
134 return hdrlen;
135}
136EXPORT_SYMBOL(ieee80211_hdrlen);
137
138unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
139{
140 const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data;
141 unsigned int hdrlen;
142
143 if (unlikely(skb->len < 10))
144 return 0;
145 hdrlen = ieee80211_hdrlen(hdr->frame_control);
146 if (unlikely(hdrlen > skb->len))
147 return 0;
148 return hdrlen;
149}
150EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
151
152int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
153{
154 int ae = meshhdr->flags & IEEE80211S_FLAGS_AE;
155 /* 7.1.3.5a.2 */
156 switch (ae) {
157 case 0:
158 return 6;
159 case 1:
160 return 12;
161 case 2:
162 return 18;
163 case 3:
164 return 24;
165 default:
166 return 6;
167 }
168}
169
170void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) 97void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
171{ 98{
172 struct sk_buff *skb = tx->skb; 99 struct sk_buff *skb = tx->skb;
@@ -1034,6 +961,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1034 struct sta_info *sta; 961 struct sta_info *sta;
1035 unsigned long flags; 962 unsigned long flags;
1036 int res; 963 int res;
964 bool from_suspend = local->suspended;
965
966 /*
967 * We're going to start the hardware, at that point
968 * we are no longer suspended and can RX frames.
969 */
970 local->suspended = false;
1037 971
1038 /* restart hardware */ 972 /* restart hardware */
1039 if (local->open_count) { 973 if (local->open_count) {
@@ -1058,6 +992,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1058 if (local->ops->sta_notify) { 992 if (local->ops->sta_notify) {
1059 spin_lock_irqsave(&local->sta_lock, flags); 993 spin_lock_irqsave(&local->sta_lock, flags);
1060 list_for_each_entry(sta, &local->sta_list, list) { 994 list_for_each_entry(sta, &local->sta_list, list) {
995 sdata = sta->sdata;
1061 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 996 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1062 sdata = container_of(sdata->bss, 997 sdata = container_of(sdata->bss,
1063 struct ieee80211_sub_if_data, 998 struct ieee80211_sub_if_data,
@@ -1128,5 +1063,40 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1128 ieee80211_wake_queues_by_reason(hw, 1063 ieee80211_wake_queues_by_reason(hw,
1129 IEEE80211_QUEUE_STOP_REASON_SUSPEND); 1064 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
1130 1065
1066 /*
1067 * If this is for hw restart things are still running.
1068 * We may want to change that later, however.
1069 */
1070 if (!from_suspend)
1071 return 0;
1072
1073#ifdef CONFIG_PM
1074 local->suspended = false;
1075
1076 list_for_each_entry(sdata, &local->interfaces, list) {
1077 switch(sdata->vif.type) {
1078 case NL80211_IFTYPE_STATION:
1079 ieee80211_sta_restart(sdata);
1080 break;
1081 case NL80211_IFTYPE_ADHOC:
1082 ieee80211_ibss_restart(sdata);
1083 break;
1084 case NL80211_IFTYPE_MESH_POINT:
1085 ieee80211_mesh_restart(sdata);
1086 break;
1087 default:
1088 break;
1089 }
1090 }
1091
1092 add_timer(&local->sta_cleanup);
1093
1094 spin_lock_irqsave(&local->sta_lock, flags);
1095 list_for_each_entry(sta, &local->sta_list, list)
1096 mesh_plink_restart(sta);
1097 spin_unlock_irqrestore(&local->sta_lock, flags);
1098#else
1099 WARN_ON(1);
1100#endif
1131 return 0; 1101 return 0;
1132} 1102}
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c
index c14394744a9c..a01154e127f0 100644
--- a/net/mac80211/wext.c
+++ b/net/mac80211/wext.c
@@ -37,12 +37,13 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
37 37
38 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 38 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
39 int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length); 39 int ret = ieee80211_sta_set_extra_ie(sdata, extra, data->length);
40 if (ret) 40 if (ret && ret != -EALREADY)
41 return ret; 41 return ret;
42 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL; 42 sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
43 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME; 43 sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
44 sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT; 44 sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
45 ieee80211_sta_req_auth(sdata); 45 if (ret != -EALREADY)
46 ieee80211_sta_req_auth(sdata);
46 return 0; 47 return 0;
47 } 48 }
48 49
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 45b74f38b867..694343b9102b 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -23,34 +23,6 @@
23 */ 23 */
24const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 }; 24const int ieee802_1d_to_ac[8] = { 2, 3, 3, 2, 1, 1, 0, 0 };
25 25
26static const char llc_ip_hdr[8] = {0xAA, 0xAA, 0x3, 0, 0, 0, 0x08, 0};
27
28/* Given a data frame determine the 802.1p/1d tag to use. */
29static unsigned int classify_1d(struct sk_buff *skb)
30{
31 unsigned int dscp;
32
33 /* skb->priority values from 256->263 are magic values to
34 * directly indicate a specific 802.1d priority. This is used
35 * to allow 802.1d priority to be passed directly in from VLAN
36 * tags, etc.
37 */
38 if (skb->priority >= 256 && skb->priority <= 263)
39 return skb->priority - 256;
40
41 switch (skb->protocol) {
42 case htons(ETH_P_IP):
43 dscp = ip_hdr(skb)->tos & 0xfc;
44 break;
45
46 default:
47 return 0;
48 }
49
50 return dscp >> 5;
51}
52
53
54static int wme_downgrade_ac(struct sk_buff *skb) 26static int wme_downgrade_ac(struct sk_buff *skb)
55{ 27{
56 switch (skb->priority) { 28 switch (skb->priority) {
@@ -94,7 +66,7 @@ static u16 classify80211(struct ieee80211_local *local, struct sk_buff *skb)
94 66
95 /* use the data classifier to determine what 802.1d tag the 67 /* use the data classifier to determine what 802.1d tag the
96 * data frame has */ 68 * data frame has */
97 skb->priority = classify_1d(skb); 69 skb->priority = cfg80211_classify8021d(skb);
98 70
99 /* in case we are a client verify acm is not set for this ac */ 71 /* in case we are a client verify acm is not set for this ac */
100 while (unlikely(local->wmm_acm & BIT(skb->priority))) { 72 while (unlikely(local->wmm_acm & BIT(skb->priority))) {
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 3c3bc9e579ed..45005497c634 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -10,6 +10,14 @@ config CFG80211_REG_DEBUG
10 10
11 If unsure, say N. 11 If unsure, say N.
12 12
13config CFG80211_DEBUGFS
14 bool "cfg80211 DebugFS entries"
15 depends on CFG80211 && DEBUG_FS
16 ---help---
17 You can enable this if you want to debugfs entries for cfg80211.
18
19 If unsure, say N.
20
13config WIRELESS_OLD_REGULATORY 21config WIRELESS_OLD_REGULATORY
14 bool "Old wireless static regulatory definitions" 22 bool "Old wireless static regulatory definitions"
15 default n 23 default n
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 14ea01c4a103..f78c4832a9ca 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o
6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o 6obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o
7 7
8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o 8cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o
9cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
9cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o 10cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o
10 11
11ccflags-y += -D__CHECK_ENDIAN__ 12ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 47c20eb0c04d..a5dbea1da476 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -17,6 +17,7 @@
17#include "nl80211.h" 17#include "nl80211.h"
18#include "core.h" 18#include "core.h"
19#include "sysfs.h" 19#include "sysfs.h"
20#include "debugfs.h"
20 21
21/* name for sysfs, %d is appended */ 22/* name for sysfs, %d is appended */
22#define PHY_NAME "phy" 23#define PHY_NAME "phy"
@@ -228,7 +229,7 @@ int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
228 229
229/* exported functions */ 230/* exported functions */
230 231
231struct wiphy *wiphy_new(struct cfg80211_ops *ops, int sizeof_priv) 232struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
232{ 233{
233 static int wiphy_counter; 234 static int wiphy_counter;
234 235
@@ -375,6 +376,8 @@ int wiphy_register(struct wiphy *wiphy)
375 nl80211_send_reg_change_event(&request); 376 nl80211_send_reg_change_event(&request);
376 } 377 }
377 378
379 cfg80211_debugfs_drv_add(drv);
380
378 res = 0; 381 res = 0;
379out_unlock: 382out_unlock:
380 mutex_unlock(&cfg80211_mutex); 383 mutex_unlock(&cfg80211_mutex);
@@ -405,6 +408,8 @@ void wiphy_unregister(struct wiphy *wiphy)
405 /* unlock again before freeing */ 408 /* unlock again before freeing */
406 mutex_unlock(&drv->mtx); 409 mutex_unlock(&drv->mtx);
407 410
411 cfg80211_debugfs_drv_del(drv);
412
408 /* If this device got a regulatory hint tell core its 413 /* If this device got a regulatory hint tell core its
409 * free to listen now to a new shiny device regulatory hint */ 414 * free to listen now to a new shiny device regulatory hint */
410 reg_device_remove(wiphy); 415 reg_device_remove(wiphy);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index f14b6c5f4221..ab512bcd8153 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -10,12 +10,13 @@
10#include <linux/netdevice.h> 10#include <linux/netdevice.h>
11#include <linux/kref.h> 11#include <linux/kref.h>
12#include <linux/rbtree.h> 12#include <linux/rbtree.h>
13#include <linux/debugfs.h>
13#include <net/genetlink.h> 14#include <net/genetlink.h>
14#include <net/cfg80211.h> 15#include <net/cfg80211.h>
15#include "reg.h" 16#include "reg.h"
16 17
17struct cfg80211_registered_device { 18struct cfg80211_registered_device {
18 struct cfg80211_ops *ops; 19 const struct cfg80211_ops *ops;
19 struct list_head list; 20 struct list_head list;
20 /* we hold this mutex during any call so that 21 /* we hold this mutex during any call so that
21 * we cannot do multiple calls at once, and also 22 * we cannot do multiple calls at once, and also
@@ -50,6 +51,17 @@ struct cfg80211_registered_device {
50 struct cfg80211_scan_request *scan_req; /* protected by RTNL */ 51 struct cfg80211_scan_request *scan_req; /* protected by RTNL */
51 unsigned long suspend_at; 52 unsigned long suspend_at;
52 53
54#ifdef CONFIG_CFG80211_DEBUGFS
55 /* Debugfs entries */
56 struct wiphy_debugfsdentries {
57 struct dentry *rts_threshold;
58 struct dentry *fragmentation_threshold;
59 struct dentry *short_retry_limit;
60 struct dentry *long_retry_limit;
61 struct dentry *ht40allow_map;
62 } debugfs;
63#endif
64
53 /* must be last because of the way we do wiphy_priv(), 65 /* must be last because of the way we do wiphy_priv(),
54 * and it should at least be aligned to NETDEV_ALIGN */ 66 * and it should at least be aligned to NETDEV_ALIGN */
55 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); 67 struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN)));
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
new file mode 100644
index 000000000000..679ddfcec1ee
--- /dev/null
+++ b/net/wireless/debugfs.c
@@ -0,0 +1,131 @@
1/*
2 * cfg80211 debugfs
3 *
4 * Copyright 2009 Luis R. Rodriguez <lrodriguez@atheros.com>
5 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include "core.h"
13#include "debugfs.h"
14
15static int cfg80211_open_file_generic(struct inode *inode, struct file *file)
16{
17 file->private_data = inode->i_private;
18 return 0;
19}
20
21#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \
22static ssize_t name## _read(struct file *file, char __user *userbuf, \
23 size_t count, loff_t *ppos) \
24{ \
25 struct wiphy *wiphy= file->private_data; \
26 char buf[buflen]; \
27 int res; \
28 \
29 res = scnprintf(buf, buflen, fmt "\n", ##value); \
30 return simple_read_from_buffer(userbuf, count, ppos, buf, res); \
31} \
32 \
33static const struct file_operations name## _ops = { \
34 .read = name## _read, \
35 .open = cfg80211_open_file_generic, \
36};
37
38DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d",
39 wiphy->rts_threshold)
40DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d",
41 wiphy->frag_threshold);
42DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d",
43 wiphy->retry_short)
44DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d",
45 wiphy->retry_long);
46
47static int ht_print_chan(struct ieee80211_channel *chan,
48 char *buf, int buf_size, int offset)
49{
50 if (WARN_ON(offset > buf_size))
51 return 0;
52
53 if (chan->flags & IEEE80211_CHAN_DISABLED)
54 return snprintf(buf + offset,
55 buf_size - offset,
56 "%d Disabled\n",
57 chan->center_freq);
58
59 return snprintf(buf + offset,
60 buf_size - offset,
61 "%d HT40 %c%c\n",
62 chan->center_freq,
63 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) ? ' ' : '-',
64 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) ? ' ' : '+');
65}
66
67static ssize_t ht40allow_map_read(struct file *file,
68 char __user *user_buf,
69 size_t count, loff_t *ppos)
70{
71 struct wiphy *wiphy = file->private_data;
72 char *buf;
73 unsigned int offset = 0, buf_size = PAGE_SIZE, i, r;
74 enum ieee80211_band band;
75 struct ieee80211_supported_band *sband;
76
77 buf = kzalloc(buf_size, GFP_KERNEL);
78 if (!buf)
79 return -ENOMEM;
80
81 mutex_lock(&cfg80211_mutex);
82
83 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
84 sband = wiphy->bands[band];
85 if (!sband)
86 continue;
87 for (i = 0; i < sband->n_channels; i++)
88 offset += ht_print_chan(&sband->channels[i],
89 buf, buf_size, offset);
90 }
91
92 mutex_unlock(&cfg80211_mutex);
93
94 r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
95
96 kfree(buf);
97
98 return r;
99}
100
101static const struct file_operations ht40allow_map_ops = {
102 .read = ht40allow_map_read,
103 .open = cfg80211_open_file_generic,
104};
105
106#define DEBUGFS_ADD(name) \
107 drv->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \
108 &drv->wiphy, &name## _ops);
109#define DEBUGFS_DEL(name) \
110 debugfs_remove(drv->debugfs.name); \
111 drv->debugfs.name = NULL;
112
113void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv)
114{
115 struct dentry *phyd = drv->wiphy.debugfsdir;
116
117 DEBUGFS_ADD(rts_threshold);
118 DEBUGFS_ADD(fragmentation_threshold);
119 DEBUGFS_ADD(short_retry_limit);
120 DEBUGFS_ADD(long_retry_limit);
121 DEBUGFS_ADD(ht40allow_map);
122}
123
124void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv)
125{
126 DEBUGFS_DEL(rts_threshold);
127 DEBUGFS_DEL(fragmentation_threshold);
128 DEBUGFS_DEL(short_retry_limit);
129 DEBUGFS_DEL(long_retry_limit);
130 DEBUGFS_DEL(ht40allow_map);
131}
diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h
new file mode 100644
index 000000000000..c226983ae66b
--- /dev/null
+++ b/net/wireless/debugfs.h
@@ -0,0 +1,14 @@
1#ifndef __CFG80211_DEBUGFS_H
2#define __CFG80211_DEBUGFS_H
3
4#ifdef CONFIG_CFG80211_DEBUGFS
5void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv);
6void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv);
7#else
8static inline
9void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) {}
10static inline
11void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) {}
12#endif
13
14#endif /* __CFG80211_DEBUGFS_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a3a152f55dd0..56d729c43b31 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -77,6 +77,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
77 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, 77 [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 },
78 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, 78 [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 },
79 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, 79 [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG },
80 [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 },
80 81
81 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, 82 [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 },
82 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 }, 83 [NL80211_ATTR_DTIM_PERIOD] = { .type = NLA_U32 },
@@ -492,7 +493,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
492 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; 493 enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
493 struct ieee80211_channel *chan; 494 struct ieee80211_channel *chan;
494 struct ieee80211_sta_ht_cap *ht_cap; 495 struct ieee80211_sta_ht_cap *ht_cap;
495 u32 freq, sec_freq; 496 u32 freq;
496 497
497 if (!rdev->ops->set_channel) { 498 if (!rdev->ops->set_channel) {
498 result = -EOPNOTSUPP; 499 result = -EOPNOTSUPP;
@@ -518,33 +519,28 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
518 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) 519 if (!chan || chan->flags & IEEE80211_CHAN_DISABLED)
519 goto bad_res; 520 goto bad_res;
520 521
521 if (channel_type == NL80211_CHAN_HT40MINUS) 522 if (channel_type == NL80211_CHAN_HT40MINUS &&
522 sec_freq = freq - 20; 523 (chan->flags & IEEE80211_CHAN_NO_HT40MINUS))
523 else if (channel_type == NL80211_CHAN_HT40PLUS) 524 goto bad_res;
524 sec_freq = freq + 20; 525 else if (channel_type == NL80211_CHAN_HT40PLUS &&
525 else 526 (chan->flags & IEEE80211_CHAN_NO_HT40PLUS))
526 sec_freq = 0;
527
528 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
529
530 /* no HT capabilities */
531 if (channel_type != NL80211_CHAN_NO_HT &&
532 !ht_cap->ht_supported)
533 goto bad_res; 527 goto bad_res;
534 528
535 if (sec_freq) { 529 /*
536 struct ieee80211_channel *schan; 530 * At this point we know if that if HT40 was requested
531 * we are allowed to use it and the extension channel
532 * exists.
533 */
534
535 ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap;
537 536
538 /* no 40 MHz capabilities */ 537 /* no HT capabilities or intolerant */
538 if (channel_type != NL80211_CHAN_NO_HT) {
539 if (!ht_cap->ht_supported)
540 goto bad_res;
539 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || 541 if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) ||
540 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) 542 (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT))
541 goto bad_res; 543 goto bad_res;
542
543 schan = ieee80211_get_channel(&rdev->wiphy, sec_freq);
544
545 /* Secondary channel not allowed */
546 if (!schan || schan->flags & IEEE80211_CHAN_DISABLED)
547 goto bad_res;
548 } 544 }
549 545
550 result = rdev->ops->set_channel(&rdev->wiphy, chan, 546 result = rdev->ops->set_channel(&rdev->wiphy, chan,
@@ -2571,18 +2567,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2571 rem_reg_rules) { 2567 rem_reg_rules) {
2572 num_rules++; 2568 num_rules++;
2573 if (num_rules > NL80211_MAX_SUPP_REG_RULES) 2569 if (num_rules > NL80211_MAX_SUPP_REG_RULES)
2574 goto bad_reg; 2570 return -EINVAL;
2575 } 2571 }
2576 2572
2577 if (!reg_is_valid_request(alpha2)) 2573 mutex_lock(&cfg80211_mutex);
2578 return -EINVAL; 2574
2575 if (!reg_is_valid_request(alpha2)) {
2576 r = -EINVAL;
2577 goto bad_reg;
2578 }
2579 2579
2580 size_of_regd = sizeof(struct ieee80211_regdomain) + 2580 size_of_regd = sizeof(struct ieee80211_regdomain) +
2581 (num_rules * sizeof(struct ieee80211_reg_rule)); 2581 (num_rules * sizeof(struct ieee80211_reg_rule));
2582 2582
2583 rd = kzalloc(size_of_regd, GFP_KERNEL); 2583 rd = kzalloc(size_of_regd, GFP_KERNEL);
2584 if (!rd) 2584 if (!rd) {
2585 return -ENOMEM; 2585 r = -ENOMEM;
2586 goto bad_reg;
2587 }
2586 2588
2587 rd->n_reg_rules = num_rules; 2589 rd->n_reg_rules = num_rules;
2588 rd->alpha2[0] = alpha2[0]; 2590 rd->alpha2[0] = alpha2[0];
@@ -2599,20 +2601,24 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2599 2601
2600 rule_idx++; 2602 rule_idx++;
2601 2603
2602 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) 2604 if (rule_idx > NL80211_MAX_SUPP_REG_RULES) {
2605 r = -EINVAL;
2603 goto bad_reg; 2606 goto bad_reg;
2607 }
2604 } 2608 }
2605 2609
2606 BUG_ON(rule_idx != num_rules); 2610 BUG_ON(rule_idx != num_rules);
2607 2611
2608 mutex_lock(&cfg80211_mutex);
2609 r = set_regdom(rd); 2612 r = set_regdom(rd);
2613
2610 mutex_unlock(&cfg80211_mutex); 2614 mutex_unlock(&cfg80211_mutex);
2615
2611 return r; 2616 return r;
2612 2617
2613 bad_reg: 2618 bad_reg:
2619 mutex_unlock(&cfg80211_mutex);
2614 kfree(rd); 2620 kfree(rd);
2615 return -EINVAL; 2621 return r;
2616} 2622}
2617 2623
2618static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) 2624static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 537af62ec42b..df0ced9405d3 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -48,12 +48,6 @@ static struct regulatory_request *last_request;
48/* To trigger userspace events */ 48/* To trigger userspace events */
49static struct platform_device *reg_pdev; 49static struct platform_device *reg_pdev;
50 50
51/* Keep the ordering from large to small */
52static u32 supported_bandwidths[] = {
53 MHZ_TO_KHZ(40),
54 MHZ_TO_KHZ(20),
55};
56
57/* 51/*
58 * Central wireless core regulatory domains, we only need two, 52 * Central wireless core regulatory domains, we only need two,
59 * the current one and a world regulatory domain in case we have no 53 * the current one and a world regulatory domain in case we have no
@@ -388,6 +382,8 @@ static int call_crda(const char *alpha2)
388/* Used by nl80211 before kmalloc'ing our regulatory domain */ 382/* Used by nl80211 before kmalloc'ing our regulatory domain */
389bool reg_is_valid_request(const char *alpha2) 383bool reg_is_valid_request(const char *alpha2)
390{ 384{
385 assert_cfg80211_lock();
386
391 if (!last_request) 387 if (!last_request)
392 return false; 388 return false;
393 389
@@ -435,19 +431,20 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
435 return true; 431 return true;
436} 432}
437 433
438/* Returns value in KHz */ 434static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range,
439static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, 435 u32 center_freq_khz,
440 u32 freq) 436 u32 bw_khz)
441{ 437{
442 unsigned int i; 438 u32 start_freq_khz, end_freq_khz;
443 for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { 439
444 u32 start_freq_khz = freq - supported_bandwidths[i]/2; 440 start_freq_khz = center_freq_khz - (bw_khz/2);
445 u32 end_freq_khz = freq + supported_bandwidths[i]/2; 441 end_freq_khz = center_freq_khz + (bw_khz/2);
446 if (start_freq_khz >= freq_range->start_freq_khz && 442
447 end_freq_khz <= freq_range->end_freq_khz) 443 if (start_freq_khz >= freq_range->start_freq_khz &&
448 return supported_bandwidths[i]; 444 end_freq_khz <= freq_range->end_freq_khz)
449 } 445 return true;
450 return 0; 446
447 return false;
451} 448}
452 449
453/** 450/**
@@ -847,14 +844,17 @@ static u32 map_regdom_flags(u32 rd_flags)
847 844
848static int freq_reg_info_regd(struct wiphy *wiphy, 845static int freq_reg_info_regd(struct wiphy *wiphy,
849 u32 center_freq, 846 u32 center_freq,
850 u32 *bandwidth, 847 u32 desired_bw_khz,
851 const struct ieee80211_reg_rule **reg_rule, 848 const struct ieee80211_reg_rule **reg_rule,
852 const struct ieee80211_regdomain *custom_regd) 849 const struct ieee80211_regdomain *custom_regd)
853{ 850{
854 int i; 851 int i;
855 bool band_rule_found = false; 852 bool band_rule_found = false;
856 const struct ieee80211_regdomain *regd; 853 const struct ieee80211_regdomain *regd;
857 u32 max_bandwidth = 0; 854 bool bw_fits = false;
855
856 if (!desired_bw_khz)
857 desired_bw_khz = MHZ_TO_KHZ(20);
858 858
859 regd = custom_regd ? custom_regd : cfg80211_regdomain; 859 regd = custom_regd ? custom_regd : cfg80211_regdomain;
860 860
@@ -887,38 +887,54 @@ static int freq_reg_info_regd(struct wiphy *wiphy,
887 if (!band_rule_found) 887 if (!band_rule_found)
888 band_rule_found = freq_in_rule_band(fr, center_freq); 888 band_rule_found = freq_in_rule_band(fr, center_freq);
889 889
890 max_bandwidth = freq_max_bandwidth(fr, center_freq); 890 bw_fits = reg_does_bw_fit(fr,
891 center_freq,
892 desired_bw_khz);
891 893
892 if (max_bandwidth && *bandwidth <= max_bandwidth) { 894 if (band_rule_found && bw_fits) {
893 *reg_rule = rr; 895 *reg_rule = rr;
894 *bandwidth = max_bandwidth; 896 return 0;
895 break;
896 } 897 }
897 } 898 }
898 899
899 if (!band_rule_found) 900 if (!band_rule_found)
900 return -ERANGE; 901 return -ERANGE;
901 902
902 return !max_bandwidth; 903 return -EINVAL;
903} 904}
904EXPORT_SYMBOL(freq_reg_info); 905EXPORT_SYMBOL(freq_reg_info);
905 906
906int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, 907int freq_reg_info(struct wiphy *wiphy,
907 const struct ieee80211_reg_rule **reg_rule) 908 u32 center_freq,
909 u32 desired_bw_khz,
910 const struct ieee80211_reg_rule **reg_rule)
908{ 911{
909 assert_cfg80211_lock(); 912 assert_cfg80211_lock();
910 return freq_reg_info_regd(wiphy, center_freq, 913 return freq_reg_info_regd(wiphy,
911 bandwidth, reg_rule, NULL); 914 center_freq,
915 desired_bw_khz,
916 reg_rule,
917 NULL);
912} 918}
913 919
920/*
921 * Note that right now we assume the desired channel bandwidth
922 * is always 20 MHz for each individual channel (HT40 uses 20 MHz
923 * per channel, the primary and the extension channel). To support
924 * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a
925 * new ieee80211_channel.target_bw and re run the regulatory check
926 * on the wiphy with the target_bw specified. Then we can simply use
927 * that below for the desired_bw_khz below.
928 */
914static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, 929static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
915 unsigned int chan_idx) 930 unsigned int chan_idx)
916{ 931{
917 int r; 932 int r;
918 u32 flags; 933 u32 flags, bw_flags = 0;
919 u32 max_bandwidth = 0; 934 u32 desired_bw_khz = MHZ_TO_KHZ(20);
920 const struct ieee80211_reg_rule *reg_rule = NULL; 935 const struct ieee80211_reg_rule *reg_rule = NULL;
921 const struct ieee80211_power_rule *power_rule = NULL; 936 const struct ieee80211_power_rule *power_rule = NULL;
937 const struct ieee80211_freq_range *freq_range = NULL;
922 struct ieee80211_supported_band *sband; 938 struct ieee80211_supported_band *sband;
923 struct ieee80211_channel *chan; 939 struct ieee80211_channel *chan;
924 struct wiphy *request_wiphy = NULL; 940 struct wiphy *request_wiphy = NULL;
@@ -933,8 +949,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
933 949
934 flags = chan->orig_flags; 950 flags = chan->orig_flags;
935 951
936 r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), 952 r = freq_reg_info(wiphy,
937 &max_bandwidth, &reg_rule); 953 MHZ_TO_KHZ(chan->center_freq),
954 desired_bw_khz,
955 &reg_rule);
938 956
939 if (r) { 957 if (r) {
940 /* 958 /*
@@ -977,6 +995,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
977 } 995 }
978 996
979 power_rule = &reg_rule->power_rule; 997 power_rule = &reg_rule->power_rule;
998 freq_range = &reg_rule->freq_range;
999
1000 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
1001 bw_flags = IEEE80211_CHAN_NO_HT40;
980 1002
981 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && 1003 if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
982 request_wiphy && request_wiphy == wiphy && 1004 request_wiphy && request_wiphy == wiphy &&
@@ -987,19 +1009,19 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band,
987 * settings 1009 * settings
988 */ 1010 */
989 chan->flags = chan->orig_flags = 1011 chan->flags = chan->orig_flags =
990 map_regdom_flags(reg_rule->flags); 1012 map_regdom_flags(reg_rule->flags) | bw_flags;
991 chan->max_antenna_gain = chan->orig_mag = 1013 chan->max_antenna_gain = chan->orig_mag =
992 (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1014 (int) MBI_TO_DBI(power_rule->max_antenna_gain);
993 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); 1015 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
994 chan->max_power = chan->orig_mpwr = 1016 chan->max_power = chan->orig_mpwr =
995 (int) MBM_TO_DBM(power_rule->max_eirp); 1017 (int) MBM_TO_DBM(power_rule->max_eirp);
996 return; 1018 return;
997 } 1019 }
998 1020
999 chan->flags = flags | map_regdom_flags(reg_rule->flags); 1021 chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags);
1000 chan->max_antenna_gain = min(chan->orig_mag, 1022 chan->max_antenna_gain = min(chan->orig_mag,
1001 (int) MBI_TO_DBI(power_rule->max_antenna_gain)); 1023 (int) MBI_TO_DBI(power_rule->max_antenna_gain));
1002 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); 1024 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1003 if (chan->orig_mpwr) 1025 if (chan->orig_mpwr)
1004 chan->max_power = min(chan->orig_mpwr, 1026 chan->max_power = min(chan->orig_mpwr,
1005 (int) MBM_TO_DBM(power_rule->max_eirp)); 1027 (int) MBM_TO_DBM(power_rule->max_eirp));
@@ -1156,6 +1178,93 @@ static void reg_process_beacons(struct wiphy *wiphy)
1156 wiphy_update_beacon_reg(wiphy); 1178 wiphy_update_beacon_reg(wiphy);
1157} 1179}
1158 1180
1181static bool is_ht40_not_allowed(struct ieee80211_channel *chan)
1182{
1183 if (!chan)
1184 return true;
1185 if (chan->flags & IEEE80211_CHAN_DISABLED)
1186 return true;
1187 /* This would happen when regulatory rules disallow HT40 completely */
1188 if (IEEE80211_CHAN_NO_HT40 == (chan->flags & (IEEE80211_CHAN_NO_HT40)))
1189 return true;
1190 return false;
1191}
1192
1193static void reg_process_ht_flags_channel(struct wiphy *wiphy,
1194 enum ieee80211_band band,
1195 unsigned int chan_idx)
1196{
1197 struct ieee80211_supported_band *sband;
1198 struct ieee80211_channel *channel;
1199 struct ieee80211_channel *channel_before = NULL, *channel_after = NULL;
1200 unsigned int i;
1201
1202 assert_cfg80211_lock();
1203
1204 sband = wiphy->bands[band];
1205 BUG_ON(chan_idx >= sband->n_channels);
1206 channel = &sband->channels[chan_idx];
1207
1208 if (is_ht40_not_allowed(channel)) {
1209 channel->flags |= IEEE80211_CHAN_NO_HT40;
1210 return;
1211 }
1212
1213 /*
1214 * We need to ensure the extension channels exist to
1215 * be able to use HT40- or HT40+, this finds them (or not)
1216 */
1217 for (i = 0; i < sband->n_channels; i++) {
1218 struct ieee80211_channel *c = &sband->channels[i];
1219 if (c->center_freq == (channel->center_freq - 20))
1220 channel_before = c;
1221 if (c->center_freq == (channel->center_freq + 20))
1222 channel_after = c;
1223 }
1224
1225 /*
1226 * Please note that this assumes target bandwidth is 20 MHz,
1227 * if that ever changes we also need to change the below logic
1228 * to include that as well.
1229 */
1230 if (is_ht40_not_allowed(channel_before))
1231 channel->flags |= IEEE80211_CHAN_NO_HT40MINUS;
1232 else
1233 channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS;
1234
1235 if (is_ht40_not_allowed(channel_after))
1236 channel->flags |= IEEE80211_CHAN_NO_HT40PLUS;
1237 else
1238 channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS;
1239}
1240
1241static void reg_process_ht_flags_band(struct wiphy *wiphy,
1242 enum ieee80211_band band)
1243{
1244 unsigned int i;
1245 struct ieee80211_supported_band *sband;
1246
1247 BUG_ON(!wiphy->bands[band]);
1248 sband = wiphy->bands[band];
1249
1250 for (i = 0; i < sband->n_channels; i++)
1251 reg_process_ht_flags_channel(wiphy, band, i);
1252}
1253
1254static void reg_process_ht_flags(struct wiphy *wiphy)
1255{
1256 enum ieee80211_band band;
1257
1258 if (!wiphy)
1259 return;
1260
1261 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1262 if (wiphy->bands[band])
1263 reg_process_ht_flags_band(wiphy, band);
1264 }
1265
1266}
1267
1159void wiphy_update_regulatory(struct wiphy *wiphy, 1268void wiphy_update_regulatory(struct wiphy *wiphy,
1160 enum nl80211_reg_initiator initiator) 1269 enum nl80211_reg_initiator initiator)
1161{ 1270{
@@ -1169,6 +1278,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy,
1169 } 1278 }
1170out: 1279out:
1171 reg_process_beacons(wiphy); 1280 reg_process_beacons(wiphy);
1281 reg_process_ht_flags(wiphy);
1172 if (wiphy->reg_notifier) 1282 if (wiphy->reg_notifier)
1173 wiphy->reg_notifier(wiphy, last_request); 1283 wiphy->reg_notifier(wiphy, last_request);
1174} 1284}
@@ -1179,9 +1289,11 @@ static void handle_channel_custom(struct wiphy *wiphy,
1179 const struct ieee80211_regdomain *regd) 1289 const struct ieee80211_regdomain *regd)
1180{ 1290{
1181 int r; 1291 int r;
1182 u32 max_bandwidth = 0; 1292 u32 desired_bw_khz = MHZ_TO_KHZ(20);
1293 u32 bw_flags = 0;
1183 const struct ieee80211_reg_rule *reg_rule = NULL; 1294 const struct ieee80211_reg_rule *reg_rule = NULL;
1184 const struct ieee80211_power_rule *power_rule = NULL; 1295 const struct ieee80211_power_rule *power_rule = NULL;
1296 const struct ieee80211_freq_range *freq_range = NULL;
1185 struct ieee80211_supported_band *sband; 1297 struct ieee80211_supported_band *sband;
1186 struct ieee80211_channel *chan; 1298 struct ieee80211_channel *chan;
1187 1299
@@ -1191,8 +1303,11 @@ static void handle_channel_custom(struct wiphy *wiphy,
1191 BUG_ON(chan_idx >= sband->n_channels); 1303 BUG_ON(chan_idx >= sband->n_channels);
1192 chan = &sband->channels[chan_idx]; 1304 chan = &sband->channels[chan_idx];
1193 1305
1194 r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), 1306 r = freq_reg_info_regd(wiphy,
1195 &max_bandwidth, &reg_rule, regd); 1307 MHZ_TO_KHZ(chan->center_freq),
1308 desired_bw_khz,
1309 &reg_rule,
1310 regd);
1196 1311
1197 if (r) { 1312 if (r) {
1198 chan->flags = IEEE80211_CHAN_DISABLED; 1313 chan->flags = IEEE80211_CHAN_DISABLED;
@@ -1200,10 +1315,14 @@ static void handle_channel_custom(struct wiphy *wiphy,
1200 } 1315 }
1201 1316
1202 power_rule = &reg_rule->power_rule; 1317 power_rule = &reg_rule->power_rule;
1318 freq_range = &reg_rule->freq_range;
1203 1319
1204 chan->flags |= map_regdom_flags(reg_rule->flags); 1320 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
1321 bw_flags = IEEE80211_CHAN_NO_HT40;
1322
1323 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1205 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1324 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
1206 chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); 1325 chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz);
1207 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); 1326 chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp);
1208} 1327}
1209 1328
@@ -1225,13 +1344,22 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1225 const struct ieee80211_regdomain *regd) 1344 const struct ieee80211_regdomain *regd)
1226{ 1345{
1227 enum ieee80211_band band; 1346 enum ieee80211_band band;
1347 unsigned int bands_set = 0;
1228 1348
1229 mutex_lock(&cfg80211_mutex); 1349 mutex_lock(&cfg80211_mutex);
1230 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1350 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1231 if (wiphy->bands[band]) 1351 if (!wiphy->bands[band])
1232 handle_band_custom(wiphy, band, regd); 1352 continue;
1353 handle_band_custom(wiphy, band, regd);
1354 bands_set++;
1233 } 1355 }
1234 mutex_unlock(&cfg80211_mutex); 1356 mutex_unlock(&cfg80211_mutex);
1357
1358 /*
1359 * no point in calling this if it won't have any effect
1360 * on your device's supportd bands.
1361 */
1362 WARN_ON(!bands_set);
1235} 1363}
1236EXPORT_SYMBOL(wiphy_apply_custom_regulatory); 1364EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
1237 1365
diff --git a/net/wireless/util.c b/net/wireless/util.c
index beb226e78cd7..d072bff463aa 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -4,7 +4,9 @@
4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6#include <linux/bitops.h> 6#include <linux/bitops.h>
7#include <linux/etherdevice.h>
7#include <net/cfg80211.h> 8#include <net/cfg80211.h>
9#include <net/ip.h>
8#include "core.h" 10#include "core.h"
9 11
10struct ieee80211_rate * 12struct ieee80211_rate *
@@ -181,5 +183,323 @@ int cfg80211_validate_key_settings(struct key_params *params, int key_idx,
181 return -EINVAL; 183 return -EINVAL;
182 } 184 }
183 185
186 if (params->seq) {
187 switch (params->cipher) {
188 case WLAN_CIPHER_SUITE_WEP40:
189 case WLAN_CIPHER_SUITE_WEP104:
190 /* These ciphers do not use key sequence */
191 return -EINVAL;
192 case WLAN_CIPHER_SUITE_TKIP:
193 case WLAN_CIPHER_SUITE_CCMP:
194 case WLAN_CIPHER_SUITE_AES_CMAC:
195 if (params->seq_len != 6)
196 return -EINVAL;
197 break;
198 }
199 }
200
201 return 0;
202}
203
204/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
205/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
206const unsigned char rfc1042_header[] __aligned(2) =
207 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
208EXPORT_SYMBOL(rfc1042_header);
209
210/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
211const unsigned char bridge_tunnel_header[] __aligned(2) =
212 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
213EXPORT_SYMBOL(bridge_tunnel_header);
214
215unsigned int ieee80211_hdrlen(__le16 fc)
216{
217 unsigned int hdrlen = 24;
218
219 if (ieee80211_is_data(fc)) {
220 if (ieee80211_has_a4(fc))
221 hdrlen = 30;
222 if (ieee80211_is_data_qos(fc))
223 hdrlen += IEEE80211_QOS_CTL_LEN;
224 goto out;
225 }
226
227 if (ieee80211_is_ctl(fc)) {
228 /*
229 * ACK and CTS are 10 bytes, all others 16. To see how
230 * to get this condition consider
231 * subtype mask: 0b0000000011110000 (0x00F0)
232 * ACK subtype: 0b0000000011010000 (0x00D0)
233 * CTS subtype: 0b0000000011000000 (0x00C0)
234 * bits that matter: ^^^ (0x00E0)
235 * value of those: 0b0000000011000000 (0x00C0)
236 */
237 if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
238 hdrlen = 10;
239 else
240 hdrlen = 16;
241 }
242out:
243 return hdrlen;
244}
245EXPORT_SYMBOL(ieee80211_hdrlen);
246
247unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
248{
249 const struct ieee80211_hdr *hdr =
250 (const struct ieee80211_hdr *)skb->data;
251 unsigned int hdrlen;
252
253 if (unlikely(skb->len < 10))
254 return 0;
255 hdrlen = ieee80211_hdrlen(hdr->frame_control);
256 if (unlikely(hdrlen > skb->len))
257 return 0;
258 return hdrlen;
259}
260EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
261
262int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
263{
264 int ae = meshhdr->flags & MESH_FLAGS_AE;
265 /* 7.1.3.5a.2 */
266 switch (ae) {
267 case 0:
268 return 6;
269 case 1:
270 return 12;
271 case 2:
272 return 18;
273 case 3:
274 return 24;
275 default:
276 return 6;
277 }
278}
279
280int ieee80211_data_to_8023(struct sk_buff *skb, u8 *addr,
281 enum nl80211_iftype iftype)
282{
283 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
284 u16 hdrlen, ethertype;
285 u8 *payload;
286 u8 dst[ETH_ALEN];
287 u8 src[ETH_ALEN] __aligned(2);
288
289 if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
290 return -1;
291
292 hdrlen = ieee80211_hdrlen(hdr->frame_control);
293
294 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
295 * header
296 * IEEE 802.11 address fields:
297 * ToDS FromDS Addr1 Addr2 Addr3 Addr4
298 * 0 0 DA SA BSSID n/a
299 * 0 1 DA BSSID SA n/a
300 * 1 0 BSSID SA DA n/a
301 * 1 1 RA TA DA SA
302 */
303 memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
304 memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
305
306 switch (hdr->frame_control &
307 cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
308 case cpu_to_le16(IEEE80211_FCTL_TODS):
309 if (unlikely(iftype != NL80211_IFTYPE_AP &&
310 iftype != NL80211_IFTYPE_AP_VLAN))
311 return -1;
312 break;
313 case cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
314 if (unlikely(iftype != NL80211_IFTYPE_WDS &&
315 iftype != NL80211_IFTYPE_MESH_POINT))
316 return -1;
317 if (iftype == NL80211_IFTYPE_MESH_POINT) {
318 struct ieee80211s_hdr *meshdr =
319 (struct ieee80211s_hdr *) (skb->data + hdrlen);
320 hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
321 if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
322 memcpy(dst, meshdr->eaddr1, ETH_ALEN);
323 memcpy(src, meshdr->eaddr2, ETH_ALEN);
324 }
325 }
326 break;
327 case cpu_to_le16(IEEE80211_FCTL_FROMDS):
328 if (iftype != NL80211_IFTYPE_STATION ||
329 (is_multicast_ether_addr(dst) &&
330 !compare_ether_addr(src, addr)))
331 return -1;
332 break;
333 case cpu_to_le16(0):
334 if (iftype != NL80211_IFTYPE_ADHOC)
335 return -1;
336 break;
337 }
338
339 if (unlikely(skb->len - hdrlen < 8))
340 return -1;
341
342 payload = skb->data + hdrlen;
343 ethertype = (payload[6] << 8) | payload[7];
344
345 if (likely((compare_ether_addr(payload, rfc1042_header) == 0 &&
346 ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
347 compare_ether_addr(payload, bridge_tunnel_header) == 0)) {
348 /* remove RFC1042 or Bridge-Tunnel encapsulation and
349 * replace EtherType */
350 skb_pull(skb, hdrlen + 6);
351 memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
352 memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
353 } else {
354 struct ethhdr *ehdr;
355 __be16 len;
356
357 skb_pull(skb, hdrlen);
358 len = htons(skb->len);
359 ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
360 memcpy(ehdr->h_dest, dst, ETH_ALEN);
361 memcpy(ehdr->h_source, src, ETH_ALEN);
362 ehdr->h_proto = len;
363 }
364 return 0;
365}
366EXPORT_SYMBOL(ieee80211_data_to_8023);
367
368int ieee80211_data_from_8023(struct sk_buff *skb, u8 *addr,
369 enum nl80211_iftype iftype, u8 *bssid, bool qos)
370{
371 struct ieee80211_hdr hdr;
372 u16 hdrlen, ethertype;
373 __le16 fc;
374 const u8 *encaps_data;
375 int encaps_len, skip_header_bytes;
376 int nh_pos, h_pos;
377 int head_need;
378
379 if (unlikely(skb->len < ETH_HLEN))
380 return -EINVAL;
381
382 nh_pos = skb_network_header(skb) - skb->data;
383 h_pos = skb_transport_header(skb) - skb->data;
384
385 /* convert Ethernet header to proper 802.11 header (based on
386 * operation mode) */
387 ethertype = (skb->data[12] << 8) | skb->data[13];
388 fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
389
390 switch (iftype) {
391 case NL80211_IFTYPE_AP:
392 case NL80211_IFTYPE_AP_VLAN:
393 fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
394 /* DA BSSID SA */
395 memcpy(hdr.addr1, skb->data, ETH_ALEN);
396 memcpy(hdr.addr2, addr, ETH_ALEN);
397 memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
398 hdrlen = 24;
399 break;
400 case NL80211_IFTYPE_STATION:
401 fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
402 /* BSSID SA DA */
403 memcpy(hdr.addr1, bssid, ETH_ALEN);
404 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
405 memcpy(hdr.addr3, skb->data, ETH_ALEN);
406 hdrlen = 24;
407 break;
408 case NL80211_IFTYPE_ADHOC:
409 /* DA SA BSSID */
410 memcpy(hdr.addr1, skb->data, ETH_ALEN);
411 memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
412 memcpy(hdr.addr3, bssid, ETH_ALEN);
413 hdrlen = 24;
414 break;
415 default:
416 return -EOPNOTSUPP;
417 }
418
419 if (qos) {
420 fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
421 hdrlen += 2;
422 }
423
424 hdr.frame_control = fc;
425 hdr.duration_id = 0;
426 hdr.seq_ctrl = 0;
427
428 skip_header_bytes = ETH_HLEN;
429 if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
430 encaps_data = bridge_tunnel_header;
431 encaps_len = sizeof(bridge_tunnel_header);
432 skip_header_bytes -= 2;
433 } else if (ethertype > 0x600) {
434 encaps_data = rfc1042_header;
435 encaps_len = sizeof(rfc1042_header);
436 skip_header_bytes -= 2;
437 } else {
438 encaps_data = NULL;
439 encaps_len = 0;
440 }
441
442 skb_pull(skb, skip_header_bytes);
443 nh_pos -= skip_header_bytes;
444 h_pos -= skip_header_bytes;
445
446 head_need = hdrlen + encaps_len - skb_headroom(skb);
447
448 if (head_need > 0 || skb_cloned(skb)) {
449 head_need = max(head_need, 0);
450 if (head_need)
451 skb_orphan(skb);
452
453 if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) {
454 printk(KERN_ERR "failed to reallocate Tx buffer\n");
455 return -ENOMEM;
456 }
457 skb->truesize += head_need;
458 }
459
460 if (encaps_data) {
461 memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
462 nh_pos += encaps_len;
463 h_pos += encaps_len;
464 }
465
466 memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
467
468 nh_pos += hdrlen;
469 h_pos += hdrlen;
470
471 /* Update skb pointers to various headers since this modified frame
472 * is going to go through Linux networking code that may potentially
473 * need things like pointer to IP header. */
474 skb_set_mac_header(skb, 0);
475 skb_set_network_header(skb, nh_pos);
476 skb_set_transport_header(skb, h_pos);
477
184 return 0; 478 return 0;
185} 479}
480EXPORT_SYMBOL(ieee80211_data_from_8023);
481
482/* Given a data frame determine the 802.1p/1d tag to use. */
483unsigned int cfg80211_classify8021d(struct sk_buff *skb)
484{
485 unsigned int dscp;
486
487 /* skb->priority values from 256->263 are magic values to
488 * directly indicate a specific 802.1d priority. This is used
489 * to allow 802.1d priority to be passed directly in from VLAN
490 * tags, etc.
491 */
492 if (skb->priority >= 256 && skb->priority <= 263)
493 return skb->priority - 256;
494
495 switch (skb->protocol) {
496 case htons(ETH_P_IP):
497 dscp = ip_hdr(skb)->tos & 0xfc;
498 break;
499 default:
500 return 0;
501 }
502
503 return dscp >> 5;
504}
505EXPORT_SYMBOL(cfg80211_classify8021d);
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index f98090b90fbf..711e00a0c9b5 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -504,6 +504,13 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
504 else if (idx == wdev->wext.default_mgmt_key) 504 else if (idx == wdev->wext.default_mgmt_key)
505 wdev->wext.default_mgmt_key = -1; 505 wdev->wext.default_mgmt_key = -1;
506 } 506 }
507 /*
508 * Applications using wireless extensions expect to be
509 * able to delete keys that don't exist, so allow that.
510 */
511 if (err == -ENOENT)
512 return 0;
513
507 return err; 514 return err;
508 } else { 515 } else {
509 if (addr) 516 if (addr)
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index d3bbef70cc7c..22378daceb94 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -636,8 +636,10 @@ static void wireless_seq_printf_stats(struct seq_file *seq,
636/* 636/*
637 * Print info for /proc/net/wireless (print all entries) 637 * Print info for /proc/net/wireless (print all entries)
638 */ 638 */
639static int wireless_seq_show(struct seq_file *seq, void *v) 639static int wireless_dev_seq_show(struct seq_file *seq, void *v)
640{ 640{
641 might_sleep();
642
641 if (v == SEQ_START_TOKEN) 643 if (v == SEQ_START_TOKEN)
642 seq_printf(seq, "Inter-| sta-| Quality | Discarded " 644 seq_printf(seq, "Inter-| sta-| Quality | Discarded "
643 "packets | Missed | WE\n" 645 "packets | Missed | WE\n"
@@ -651,21 +653,41 @@ static int wireless_seq_show(struct seq_file *seq, void *v)
651 653
652static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos) 654static void *wireless_dev_seq_start(struct seq_file *seq, loff_t *pos)
653{ 655{
656 struct net *net = seq_file_net(seq);
657 loff_t off;
658 struct net_device *dev;
659
654 rtnl_lock(); 660 rtnl_lock();
655 return dev_seq_start(seq, pos); 661 if (!*pos)
662 return SEQ_START_TOKEN;
663
664 off = 1;
665 for_each_netdev(net, dev)
666 if (off++ == *pos)
667 return dev;
668 return NULL;
669}
670
671static void *wireless_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
672{
673 struct net *net = seq_file_net(seq);
674
675 ++*pos;
676
677 return v == SEQ_START_TOKEN ?
678 first_net_device(net) : next_net_device(v);
656} 679}
657 680
658static void wireless_dev_seq_stop(struct seq_file *seq, void *v) 681static void wireless_dev_seq_stop(struct seq_file *seq, void *v)
659{ 682{
660 dev_seq_stop(seq, v);
661 rtnl_unlock(); 683 rtnl_unlock();
662} 684}
663 685
664static const struct seq_operations wireless_seq_ops = { 686static const struct seq_operations wireless_seq_ops = {
665 .start = wireless_dev_seq_start, 687 .start = wireless_dev_seq_start,
666 .next = dev_seq_next, 688 .next = wireless_dev_seq_next,
667 .stop = wireless_dev_seq_stop, 689 .stop = wireless_dev_seq_stop,
668 .show = wireless_seq_show, 690 .show = wireless_dev_seq_show,
669}; 691};
670 692
671static int seq_open_wireless(struct inode *inode, struct file *file) 693static int seq_open_wireless(struct inode *inode, struct file *file)