diff options
99 files changed, 2790 insertions, 2170 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 866253d7abd7..9b55c661c3fb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -3272,6 +3272,12 @@ S: Supported | |||
3272 | F: drivers/net/mv643xx_eth.* | 3272 | F: drivers/net/mv643xx_eth.* |
3273 | F: include/linux/mv643xx.h | 3273 | F: include/linux/mv643xx.h |
3274 | 3274 | ||
3275 | MARVELL MWL8K WIRELESS DRIVER | ||
3276 | M: Lennert Buytenhek <buytenh@marvell.com> | ||
3277 | L: linux-wireless@vger.kernel.org | ||
3278 | S: Supported | ||
3279 | F: drivers/net/wireless/mwl8k.c | ||
3280 | |||
3275 | MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER | 3281 | MARVELL SOC MMC/SD/SDIO CONTROLLER DRIVER |
3276 | M: Nicolas Pitre <nico@cam.org> | 3282 | M: Nicolas Pitre <nico@cam.org> |
3277 | S: Maintained | 3283 | S: Maintained |
diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c index 5695911bc602..b80f514877d8 100644 --- a/drivers/net/wireless/adm8211.c +++ b/drivers/net/wireless/adm8211.c | |||
@@ -1328,16 +1328,39 @@ static void adm8211_bss_info_changed(struct ieee80211_hw *dev, | |||
1328 | } | 1328 | } |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, | ||
1332 | int mc_count, struct dev_addr_list *mclist) | ||
1333 | { | ||
1334 | unsigned int bit_nr, i; | ||
1335 | u32 mc_filter[2]; | ||
1336 | |||
1337 | mc_filter[1] = mc_filter[0] = 0; | ||
1338 | |||
1339 | for (i = 0; i < mc_count; i++) { | ||
1340 | if (!mclist) | ||
1341 | break; | ||
1342 | bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | ||
1343 | |||
1344 | bit_nr &= 0x3F; | ||
1345 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
1346 | mclist = mclist->next; | ||
1347 | } | ||
1348 | |||
1349 | return mc_filter[0] | ((u64)(mc_filter[1]) << 32); | ||
1350 | } | ||
1351 | |||
1331 | static void adm8211_configure_filter(struct ieee80211_hw *dev, | 1352 | static void adm8211_configure_filter(struct ieee80211_hw *dev, |
1332 | unsigned int changed_flags, | 1353 | unsigned int changed_flags, |
1333 | unsigned int *total_flags, | 1354 | unsigned int *total_flags, |
1334 | int mc_count, struct dev_mc_list *mclist) | 1355 | u64 multicast) |
1335 | { | 1356 | { |
1336 | static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 1357 | static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
1337 | struct adm8211_priv *priv = dev->priv; | 1358 | struct adm8211_priv *priv = dev->priv; |
1338 | unsigned int bit_nr, new_flags; | 1359 | unsigned int new_flags; |
1339 | u32 mc_filter[2]; | 1360 | u32 mc_filter[2]; |
1340 | int i; | 1361 | |
1362 | mc_filter[0] = multicast; | ||
1363 | mc_filter[1] = multicast >> 32; | ||
1341 | 1364 | ||
1342 | new_flags = 0; | 1365 | new_flags = 0; |
1343 | 1366 | ||
@@ -1346,23 +1369,13 @@ static void adm8211_configure_filter(struct ieee80211_hw *dev, | |||
1346 | priv->nar |= ADM8211_NAR_PR; | 1369 | priv->nar |= ADM8211_NAR_PR; |
1347 | priv->nar &= ~ADM8211_NAR_MM; | 1370 | priv->nar &= ~ADM8211_NAR_MM; |
1348 | mc_filter[1] = mc_filter[0] = ~0; | 1371 | mc_filter[1] = mc_filter[0] = ~0; |
1349 | } else if ((*total_flags & FIF_ALLMULTI) || (mc_count > 32)) { | 1372 | } else if (*total_flags & FIF_ALLMULTI || multicast == ~(0ULL)) { |
1350 | new_flags |= FIF_ALLMULTI; | 1373 | new_flags |= FIF_ALLMULTI; |
1351 | priv->nar &= ~ADM8211_NAR_PR; | 1374 | priv->nar &= ~ADM8211_NAR_PR; |
1352 | priv->nar |= ADM8211_NAR_MM; | 1375 | priv->nar |= ADM8211_NAR_MM; |
1353 | mc_filter[1] = mc_filter[0] = ~0; | 1376 | mc_filter[1] = mc_filter[0] = ~0; |
1354 | } else { | 1377 | } else { |
1355 | priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); | 1378 | priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); |
1356 | mc_filter[1] = mc_filter[0] = 0; | ||
1357 | for (i = 0; i < mc_count; i++) { | ||
1358 | if (!mclist) | ||
1359 | break; | ||
1360 | bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; | ||
1361 | |||
1362 | bit_nr &= 0x3F; | ||
1363 | mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); | ||
1364 | mclist = mclist->next; | ||
1365 | } | ||
1366 | } | 1379 | } |
1367 | 1380 | ||
1368 | ADM8211_IDLE_RX(); | 1381 | ADM8211_IDLE_RX(); |
@@ -1757,6 +1770,7 @@ static const struct ieee80211_ops adm8211_ops = { | |||
1757 | .remove_interface = adm8211_remove_interface, | 1770 | .remove_interface = adm8211_remove_interface, |
1758 | .config = adm8211_config, | 1771 | .config = adm8211_config, |
1759 | .bss_info_changed = adm8211_bss_info_changed, | 1772 | .bss_info_changed = adm8211_bss_info_changed, |
1773 | .prepare_multicast = adm8211_prepare_multicast, | ||
1760 | .configure_filter = adm8211_configure_filter, | 1774 | .configure_filter = adm8211_configure_filter, |
1761 | .get_stats = adm8211_get_stats, | 1775 | .get_stats = adm8211_get_stats, |
1762 | .get_tx_stats = adm8211_get_tx_stats, | 1776 | .get_tx_stats = adm8211_get_tx_stats, |
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 7218dbabad3e..8e1a55dec351 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
@@ -1950,9 +1950,8 @@ static int at76_config(struct ieee80211_hw *hw, u32 changed) | |||
1950 | { | 1950 | { |
1951 | struct at76_priv *priv = hw->priv; | 1951 | struct at76_priv *priv = hw->priv; |
1952 | 1952 | ||
1953 | at76_dbg(DBG_MAC80211, "%s(): channel %d radio %d", | 1953 | at76_dbg(DBG_MAC80211, "%s(): channel %d", |
1954 | __func__, hw->conf.channel->hw_value, | 1954 | __func__, hw->conf.channel->hw_value); |
1955 | hw->conf.radio_enabled); | ||
1956 | at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:"); | 1955 | at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:"); |
1957 | 1956 | ||
1958 | mutex_lock(&priv->mtx); | 1957 | mutex_lock(&priv->mtx); |
@@ -1997,15 +1996,14 @@ static void at76_bss_info_changed(struct ieee80211_hw *hw, | |||
1997 | /* must be atomic */ | 1996 | /* must be atomic */ |
1998 | static void at76_configure_filter(struct ieee80211_hw *hw, | 1997 | static void at76_configure_filter(struct ieee80211_hw *hw, |
1999 | unsigned int changed_flags, | 1998 | unsigned int changed_flags, |
2000 | unsigned int *total_flags, int mc_count, | 1999 | unsigned int *total_flags, u64 multicast) |
2001 | struct dev_addr_list *mc_list) | ||
2002 | { | 2000 | { |
2003 | struct at76_priv *priv = hw->priv; | 2001 | struct at76_priv *priv = hw->priv; |
2004 | int flags; | 2002 | int flags; |
2005 | 2003 | ||
2006 | at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " | 2004 | at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " |
2007 | "total_flags=0x%08x mc_count=%d", | 2005 | "total_flags=0x%08x", |
2008 | __func__, changed_flags, *total_flags, mc_count); | 2006 | __func__, changed_flags, *total_flags); |
2009 | 2007 | ||
2010 | flags = changed_flags & AT76_SUPPORTED_FILTERS; | 2008 | flags = changed_flags & AT76_SUPPORTED_FILTERS; |
2011 | *total_flags = AT76_SUPPORTED_FILTERS; | 2009 | *total_flags = AT76_SUPPORTED_FILTERS; |
diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index e6c3ee3e0581..ce407248d7d8 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h | |||
@@ -157,6 +157,7 @@ struct ar9170_sta_tid { | |||
157 | 157 | ||
158 | struct ar9170 { | 158 | struct ar9170 { |
159 | struct ieee80211_hw *hw; | 159 | struct ieee80211_hw *hw; |
160 | struct ath_common common; | ||
160 | struct mutex mutex; | 161 | struct mutex mutex; |
161 | enum ar9170_device_state state; | 162 | enum ar9170_device_state state; |
162 | unsigned long bad_hw_nagger; | 163 | unsigned long bad_hw_nagger; |
@@ -184,10 +185,8 @@ struct ar9170 { | |||
184 | bool disable_offload; | 185 | bool disable_offload; |
185 | 186 | ||
186 | /* filter settings */ | 187 | /* filter settings */ |
187 | struct work_struct filter_config_work; | 188 | u64 cur_mc_hash; |
188 | u64 cur_mc_hash, want_mc_hash; | 189 | u32 cur_filter; |
189 | u32 cur_filter, want_filter; | ||
190 | unsigned long filter_changed; | ||
191 | unsigned int filter_state; | 190 | unsigned int filter_state; |
192 | bool sniffer_enabled; | 191 | bool sniffer_enabled; |
193 | 192 | ||
@@ -222,7 +221,6 @@ struct ar9170 { | |||
222 | 221 | ||
223 | /* EEPROM */ | 222 | /* EEPROM */ |
224 | struct ar9170_eeprom eeprom; | 223 | struct ar9170_eeprom eeprom; |
225 | struct ath_regulatory regulatory; | ||
226 | 224 | ||
227 | /* tx queues - as seen by hw - */ | 225 | /* tx queues - as seen by hw - */ |
228 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; | 226 | struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; |
@@ -261,10 +259,6 @@ struct ar9170_tx_info { | |||
261 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) | 259 | #define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) |
262 | #define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) | 260 | #define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) |
263 | 261 | ||
264 | #define AR9170_FILTER_CHANGED_MODE BIT(0) | ||
265 | #define AR9170_FILTER_CHANGED_MULTICAST BIT(1) | ||
266 | #define AR9170_FILTER_CHANGED_FRAMEFILTER BIT(2) | ||
267 | |||
268 | /* exported interface */ | 262 | /* exported interface */ |
269 | void *ar9170_alloc(size_t priv_size); | 263 | void *ar9170_alloc(size_t priv_size); |
270 | int ar9170_register(struct ar9170 *ar, struct device *pdev); | 264 | int ar9170_register(struct ar9170 *ar, struct device *pdev); |
@@ -278,8 +272,8 @@ int ar9170_nag_limiter(struct ar9170 *ar); | |||
278 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); | 272 | int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); |
279 | int ar9170_init_mac(struct ar9170 *ar); | 273 | int ar9170_init_mac(struct ar9170 *ar); |
280 | int ar9170_set_qos(struct ar9170 *ar); | 274 | int ar9170_set_qos(struct ar9170 *ar); |
281 | int ar9170_update_multicast(struct ar9170 *ar); | 275 | int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); |
282 | int ar9170_update_frame_filter(struct ar9170 *ar); | 276 | int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); |
283 | int ar9170_set_operating_mode(struct ar9170 *ar); | 277 | int ar9170_set_operating_mode(struct ar9170 *ar); |
284 | int ar9170_set_beacon_timers(struct ar9170 *ar); | 278 | int ar9170_set_beacon_timers(struct ar9170 *ar); |
285 | int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); | 279 | int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); |
diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c index d9f1f46de183..60049366e863 100644 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ b/drivers/net/wireless/ath/ar9170/mac.c | |||
@@ -238,39 +238,31 @@ static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) | |||
238 | return ar9170_regwrite_result(); | 238 | return ar9170_regwrite_result(); |
239 | } | 239 | } |
240 | 240 | ||
241 | int ar9170_update_multicast(struct ar9170 *ar) | 241 | int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) |
242 | { | 242 | { |
243 | int err; | 243 | int err; |
244 | 244 | ||
245 | ar9170_regwrite_begin(ar); | 245 | ar9170_regwrite_begin(ar); |
246 | ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, | 246 | ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); |
247 | ar->want_mc_hash >> 32); | 247 | ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); |
248 | ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, | ||
249 | ar->want_mc_hash); | ||
250 | |||
251 | ar9170_regwrite_finish(); | 248 | ar9170_regwrite_finish(); |
252 | err = ar9170_regwrite_result(); | 249 | err = ar9170_regwrite_result(); |
253 | |||
254 | if (err) | 250 | if (err) |
255 | return err; | 251 | return err; |
256 | 252 | ||
257 | ar->cur_mc_hash = ar->want_mc_hash; | 253 | ar->cur_mc_hash = mc_hash; |
258 | |||
259 | return 0; | 254 | return 0; |
260 | } | 255 | } |
261 | 256 | ||
262 | int ar9170_update_frame_filter(struct ar9170 *ar) | 257 | int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) |
263 | { | 258 | { |
264 | int err; | 259 | int err; |
265 | 260 | ||
266 | err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, | 261 | err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); |
267 | ar->want_filter); | ||
268 | |||
269 | if (err) | 262 | if (err) |
270 | return err; | 263 | return err; |
271 | 264 | ||
272 | ar->cur_filter = ar->want_filter; | 265 | ar->cur_filter = filter; |
273 | |||
274 | return 0; | 266 | return 0; |
275 | } | 267 | } |
276 | 268 | ||
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index ea8c9419336d..658b32312caf 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -1232,8 +1232,6 @@ static int ar9170_op_start(struct ieee80211_hw *hw) | |||
1232 | 1232 | ||
1233 | mutex_lock(&ar->mutex); | 1233 | mutex_lock(&ar->mutex); |
1234 | 1234 | ||
1235 | ar->filter_changed = 0; | ||
1236 | |||
1237 | /* reinitialize queues statistics */ | 1235 | /* reinitialize queues statistics */ |
1238 | memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); | 1236 | memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); |
1239 | for (i = 0; i < __AR9170_NUM_TXQ; i++) | 1237 | for (i = 0; i < __AR9170_NUM_TXQ; i++) |
@@ -1296,7 +1294,6 @@ static void ar9170_op_stop(struct ieee80211_hw *hw) | |||
1296 | #ifdef CONFIG_AR9170_LEDS | 1294 | #ifdef CONFIG_AR9170_LEDS |
1297 | cancel_delayed_work_sync(&ar->led_work); | 1295 | cancel_delayed_work_sync(&ar->led_work); |
1298 | #endif | 1296 | #endif |
1299 | cancel_work_sync(&ar->filter_config_work); | ||
1300 | cancel_work_sync(&ar->beacon_work); | 1297 | cancel_work_sync(&ar->beacon_work); |
1301 | 1298 | ||
1302 | mutex_lock(&ar->mutex); | 1299 | mutex_lock(&ar->mutex); |
@@ -1973,8 +1970,7 @@ static int ar9170_op_add_interface(struct ieee80211_hw *hw, | |||
1973 | } | 1970 | } |
1974 | 1971 | ||
1975 | ar->cur_filter = 0; | 1972 | ar->cur_filter = 0; |
1976 | ar->want_filter = AR9170_MAC_REG_FTF_DEFAULTS; | 1973 | err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); |
1977 | err = ar9170_update_frame_filter(ar); | ||
1978 | if (err) | 1974 | if (err) |
1979 | goto unlock; | 1975 | goto unlock; |
1980 | 1976 | ||
@@ -1992,8 +1988,7 @@ static void ar9170_op_remove_interface(struct ieee80211_hw *hw, | |||
1992 | 1988 | ||
1993 | mutex_lock(&ar->mutex); | 1989 | mutex_lock(&ar->mutex); |
1994 | ar->vif = NULL; | 1990 | ar->vif = NULL; |
1995 | ar->want_filter = 0; | 1991 | ar9170_update_frame_filter(ar, 0); |
1996 | ar9170_update_frame_filter(ar); | ||
1997 | ar9170_set_beacon_timers(ar); | 1992 | ar9170_set_beacon_timers(ar); |
1998 | dev_kfree_skb(ar->beacon); | 1993 | dev_kfree_skb(ar->beacon); |
1999 | ar->beacon = NULL; | 1994 | ar->beacon = NULL; |
@@ -2065,48 +2060,37 @@ out: | |||
2065 | return err; | 2060 | return err; |
2066 | } | 2061 | } |
2067 | 2062 | ||
2068 | static void ar9170_set_filters(struct work_struct *work) | 2063 | static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, |
2064 | struct dev_addr_list *mclist) | ||
2069 | { | 2065 | { |
2070 | struct ar9170 *ar = container_of(work, struct ar9170, | 2066 | u64 mchash; |
2071 | filter_config_work); | 2067 | int i; |
2072 | int err; | ||
2073 | |||
2074 | if (unlikely(!IS_STARTED(ar))) | ||
2075 | return ; | ||
2076 | |||
2077 | mutex_lock(&ar->mutex); | ||
2078 | if (test_and_clear_bit(AR9170_FILTER_CHANGED_MODE, | ||
2079 | &ar->filter_changed)) { | ||
2080 | err = ar9170_set_operating_mode(ar); | ||
2081 | if (err) | ||
2082 | goto unlock; | ||
2083 | } | ||
2084 | 2068 | ||
2085 | if (test_and_clear_bit(AR9170_FILTER_CHANGED_MULTICAST, | 2069 | /* always get broadcast frames */ |
2086 | &ar->filter_changed)) { | 2070 | mchash = 1ULL << (0xff >> 2); |
2087 | err = ar9170_update_multicast(ar); | ||
2088 | if (err) | ||
2089 | goto unlock; | ||
2090 | } | ||
2091 | 2071 | ||
2092 | if (test_and_clear_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, | 2072 | for (i = 0; i < mc_count; i++) { |
2093 | &ar->filter_changed)) { | 2073 | if (WARN_ON(!mclist)) |
2094 | err = ar9170_update_frame_filter(ar); | 2074 | break; |
2095 | if (err) | 2075 | mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); |
2096 | goto unlock; | 2076 | mclist = mclist->next; |
2097 | } | 2077 | } |
2098 | 2078 | ||
2099 | unlock: | 2079 | return mchash; |
2100 | mutex_unlock(&ar->mutex); | ||
2101 | } | 2080 | } |
2102 | 2081 | ||
2103 | static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | 2082 | static void ar9170_op_configure_filter(struct ieee80211_hw *hw, |
2104 | unsigned int changed_flags, | 2083 | unsigned int changed_flags, |
2105 | unsigned int *new_flags, | 2084 | unsigned int *new_flags, |
2106 | int mc_count, struct dev_mc_list *mclist) | 2085 | u64 multicast) |
2107 | { | 2086 | { |
2108 | struct ar9170 *ar = hw->priv; | 2087 | struct ar9170 *ar = hw->priv; |
2109 | 2088 | ||
2089 | if (unlikely(!IS_ACCEPTING_CMD(ar))) | ||
2090 | return ; | ||
2091 | |||
2092 | mutex_lock(&ar->mutex); | ||
2093 | |||
2110 | /* mask supported flags */ | 2094 | /* mask supported flags */ |
2111 | *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | | 2095 | *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | |
2112 | FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; | 2096 | FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; |
@@ -2116,26 +2100,11 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | |||
2116 | * then checking the error flags, later. | 2100 | * then checking the error flags, later. |
2117 | */ | 2101 | */ |
2118 | 2102 | ||
2119 | if (changed_flags & FIF_ALLMULTI) { | 2103 | if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) |
2120 | if (*new_flags & FIF_ALLMULTI) { | 2104 | multicast = ~0ULL; |
2121 | ar->want_mc_hash = ~0ULL; | ||
2122 | } else { | ||
2123 | u64 mchash; | ||
2124 | int i; | ||
2125 | 2105 | ||
2126 | /* always get broadcast frames */ | 2106 | if (multicast != ar->cur_mc_hash) |
2127 | mchash = 1ULL << (0xff >> 2); | 2107 | ar9170_update_multicast(ar, multicast); |
2128 | |||
2129 | for (i = 0; i < mc_count; i++) { | ||
2130 | if (WARN_ON(!mclist)) | ||
2131 | break; | ||
2132 | mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); | ||
2133 | mclist = mclist->next; | ||
2134 | } | ||
2135 | ar->want_mc_hash = mchash; | ||
2136 | } | ||
2137 | set_bit(AR9170_FILTER_CHANGED_MULTICAST, &ar->filter_changed); | ||
2138 | } | ||
2139 | 2108 | ||
2140 | if (changed_flags & FIF_CONTROL) { | 2109 | if (changed_flags & FIF_CONTROL) { |
2141 | u32 filter = AR9170_MAC_REG_FTF_PSPOLL | | 2110 | u32 filter = AR9170_MAC_REG_FTF_PSPOLL | |
@@ -2146,24 +2115,22 @@ static void ar9170_op_configure_filter(struct ieee80211_hw *hw, | |||
2146 | AR9170_MAC_REG_FTF_CFE_ACK; | 2115 | AR9170_MAC_REG_FTF_CFE_ACK; |
2147 | 2116 | ||
2148 | if (*new_flags & FIF_CONTROL) | 2117 | if (*new_flags & FIF_CONTROL) |
2149 | ar->want_filter = ar->cur_filter | filter; | 2118 | filter |= ar->cur_filter; |
2150 | else | 2119 | else |
2151 | ar->want_filter = ar->cur_filter & ~filter; | 2120 | filter &= (~ar->cur_filter); |
2152 | 2121 | ||
2153 | set_bit(AR9170_FILTER_CHANGED_FRAMEFILTER, | 2122 | ar9170_update_frame_filter(ar, filter); |
2154 | &ar->filter_changed); | ||
2155 | } | 2123 | } |
2156 | 2124 | ||
2157 | if (changed_flags & FIF_PROMISC_IN_BSS) { | 2125 | if (changed_flags & FIF_PROMISC_IN_BSS) { |
2158 | ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; | 2126 | ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; |
2159 | set_bit(AR9170_FILTER_CHANGED_MODE, | 2127 | ar9170_set_operating_mode(ar); |
2160 | &ar->filter_changed); | ||
2161 | } | 2128 | } |
2162 | 2129 | ||
2163 | if (likely(IS_STARTED(ar))) | 2130 | mutex_unlock(&ar->mutex); |
2164 | ieee80211_queue_work(ar->hw, &ar->filter_config_work); | ||
2165 | } | 2131 | } |
2166 | 2132 | ||
2133 | |||
2167 | static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, | 2134 | static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, |
2168 | struct ieee80211_vif *vif, | 2135 | struct ieee80211_vif *vif, |
2169 | struct ieee80211_bss_conf *bss_conf, | 2136 | struct ieee80211_bss_conf *bss_conf, |
@@ -2417,9 +2384,6 @@ static void ar9170_sta_notify(struct ieee80211_hw *hw, | |||
2417 | default: | 2384 | default: |
2418 | break; | 2385 | break; |
2419 | } | 2386 | } |
2420 | |||
2421 | if (IS_STARTED(ar) && ar->filter_changed) | ||
2422 | ieee80211_queue_work(ar->hw, &ar->filter_config_work); | ||
2423 | } | 2387 | } |
2424 | 2388 | ||
2425 | static int ar9170_get_stats(struct ieee80211_hw *hw, | 2389 | static int ar9170_get_stats(struct ieee80211_hw *hw, |
@@ -2543,6 +2507,7 @@ static const struct ieee80211_ops ar9170_ops = { | |||
2543 | .add_interface = ar9170_op_add_interface, | 2507 | .add_interface = ar9170_op_add_interface, |
2544 | .remove_interface = ar9170_op_remove_interface, | 2508 | .remove_interface = ar9170_op_remove_interface, |
2545 | .config = ar9170_op_config, | 2509 | .config = ar9170_op_config, |
2510 | .prepare_multicast = ar9170_op_prepare_multicast, | ||
2546 | .configure_filter = ar9170_op_configure_filter, | 2511 | .configure_filter = ar9170_op_configure_filter, |
2547 | .conf_tx = ar9170_conf_tx, | 2512 | .conf_tx = ar9170_conf_tx, |
2548 | .bss_info_changed = ar9170_op_bss_info_changed, | 2513 | .bss_info_changed = ar9170_op_bss_info_changed, |
@@ -2589,7 +2554,6 @@ void *ar9170_alloc(size_t priv_size) | |||
2589 | skb_queue_head_init(&ar->tx_pending[i]); | 2554 | skb_queue_head_init(&ar->tx_pending[i]); |
2590 | } | 2555 | } |
2591 | ar9170_rx_reset_rx_mpdu(ar); | 2556 | ar9170_rx_reset_rx_mpdu(ar); |
2592 | INIT_WORK(&ar->filter_config_work, ar9170_set_filters); | ||
2593 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); | 2557 | INIT_WORK(&ar->beacon_work, ar9170_new_beacon); |
2594 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); | 2558 | INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); |
2595 | INIT_LIST_HEAD(&ar->tx_ampdu_list); | 2559 | INIT_LIST_HEAD(&ar->tx_ampdu_list); |
@@ -2634,6 +2598,7 @@ static int ar9170_read_eeprom(struct ar9170 *ar) | |||
2634 | { | 2598 | { |
2635 | #define RW 8 /* number of words to read at once */ | 2599 | #define RW 8 /* number of words to read at once */ |
2636 | #define RB (sizeof(u32) * RW) | 2600 | #define RB (sizeof(u32) * RW) |
2601 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
2637 | u8 *eeprom = (void *)&ar->eeprom; | 2602 | u8 *eeprom = (void *)&ar->eeprom; |
2638 | u8 *addr = ar->eeprom.mac_address; | 2603 | u8 *addr = ar->eeprom.mac_address; |
2639 | __le32 offsets[RW]; | 2604 | __le32 offsets[RW]; |
@@ -2700,8 +2665,8 @@ static int ar9170_read_eeprom(struct ar9170 *ar) | |||
2700 | else | 2665 | else |
2701 | ar->hw->channel_change_time = 80 * 1000; | 2666 | ar->hw->channel_change_time = 80 * 1000; |
2702 | 2667 | ||
2703 | ar->regulatory.current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); | 2668 | regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); |
2704 | ar->regulatory.current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); | 2669 | regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); |
2705 | 2670 | ||
2706 | /* second part of wiphy init */ | 2671 | /* second part of wiphy init */ |
2707 | SET_IEEE80211_PERM_ADDR(ar->hw, addr); | 2672 | SET_IEEE80211_PERM_ADDR(ar->hw, addr); |
@@ -2715,11 +2680,12 @@ static int ar9170_reg_notifier(struct wiphy *wiphy, | |||
2715 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 2680 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
2716 | struct ar9170 *ar = hw->priv; | 2681 | struct ar9170 *ar = hw->priv; |
2717 | 2682 | ||
2718 | return ath_reg_notifier_apply(wiphy, request, &ar->regulatory); | 2683 | return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); |
2719 | } | 2684 | } |
2720 | 2685 | ||
2721 | int ar9170_register(struct ar9170 *ar, struct device *pdev) | 2686 | int ar9170_register(struct ar9170 *ar, struct device *pdev) |
2722 | { | 2687 | { |
2688 | struct ath_regulatory *regulatory = &ar->common.regulatory; | ||
2723 | int err; | 2689 | int err; |
2724 | 2690 | ||
2725 | /* try to read EEPROM, init MAC addr */ | 2691 | /* try to read EEPROM, init MAC addr */ |
@@ -2727,7 +2693,7 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) | |||
2727 | if (err) | 2693 | if (err) |
2728 | goto err_out; | 2694 | goto err_out; |
2729 | 2695 | ||
2730 | err = ath_regd_init(&ar->regulatory, ar->hw->wiphy, | 2696 | err = ath_regd_init(regulatory, ar->hw->wiphy, |
2731 | ar9170_reg_notifier); | 2697 | ar9170_reg_notifier); |
2732 | if (err) | 2698 | if (err) |
2733 | goto err_out; | 2699 | goto err_out; |
@@ -2736,8 +2702,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) | |||
2736 | if (err) | 2702 | if (err) |
2737 | goto err_out; | 2703 | goto err_out; |
2738 | 2704 | ||
2739 | if (!ath_is_world_regd(&ar->regulatory)) | 2705 | if (!ath_is_world_regd(regulatory)) |
2740 | regulatory_hint(ar->hw->wiphy, ar->regulatory.alpha2); | 2706 | regulatory_hint(ar->hw->wiphy, regulatory->alpha2); |
2741 | 2707 | ||
2742 | err = ar9170_init_leds(ar); | 2708 | err = ar9170_init_leds(ar); |
2743 | if (err) | 2709 | if (err) |
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index e284cd3ac6d4..a63e90cbf9e5 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -19,8 +19,26 @@ | |||
19 | 19 | ||
20 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
21 | 21 | ||
22 | struct reg_dmn_pair_mapping { | ||
23 | u16 regDmnEnum; | ||
24 | u16 reg_5ghz_ctl; | ||
25 | u16 reg_2ghz_ctl; | ||
26 | }; | ||
27 | |||
28 | struct ath_regulatory { | ||
29 | char alpha2[2]; | ||
30 | u16 country_code; | ||
31 | u16 max_power_level; | ||
32 | u32 tp_scale; | ||
33 | u16 current_rd; | ||
34 | u16 current_rd_ext; | ||
35 | int16_t power_limit; | ||
36 | struct reg_dmn_pair_mapping *regpair; | ||
37 | }; | ||
38 | |||
22 | struct ath_common { | 39 | struct ath_common { |
23 | u16 cachelsz; | 40 | u16 cachelsz; |
41 | struct ath_regulatory regulatory; | ||
24 | }; | 42 | }; |
25 | 43 | ||
26 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | 44 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, |
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h index c09402eea7f3..862762cea54c 100644 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ b/drivers/net/wireless/ath/ath5k/ath5k.h | |||
@@ -27,8 +27,6 @@ | |||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <net/mac80211.h> | 28 | #include <net/mac80211.h> |
29 | 29 | ||
30 | #include "../regd.h" | ||
31 | |||
32 | /* RX/TX descriptor hw structs | 30 | /* RX/TX descriptor hw structs |
33 | * TODO: Driver part should only see sw structs */ | 31 | * TODO: Driver part should only see sw structs */ |
34 | #include "desc.h" | 32 | #include "desc.h" |
@@ -1077,7 +1075,6 @@ struct ath5k_hw { | |||
1077 | 1075 | ||
1078 | int ah_gpio_npins; | 1076 | int ah_gpio_npins; |
1079 | 1077 | ||
1080 | struct ath_regulatory ah_regulatory; | ||
1081 | struct ath5k_capabilities ah_capabilities; | 1078 | struct ath5k_capabilities ah_capabilities; |
1082 | 1079 | ||
1083 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; | 1080 | struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 2b3cf39dd4b1..5056410d788a 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -229,10 +229,12 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, | |||
229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, | 229 | static void ath5k_remove_interface(struct ieee80211_hw *hw, |
230 | struct ieee80211_if_init_conf *conf); | 230 | struct ieee80211_if_init_conf *conf); |
231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); | 231 | static int ath5k_config(struct ieee80211_hw *hw, u32 changed); |
232 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
233 | int mc_count, struct dev_addr_list *mc_list); | ||
232 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | 234 | static void ath5k_configure_filter(struct ieee80211_hw *hw, |
233 | unsigned int changed_flags, | 235 | unsigned int changed_flags, |
234 | unsigned int *new_flags, | 236 | unsigned int *new_flags, |
235 | int mc_count, struct dev_mc_list *mclist); | 237 | u64 multicast); |
236 | static int ath5k_set_key(struct ieee80211_hw *hw, | 238 | static int ath5k_set_key(struct ieee80211_hw *hw, |
237 | enum set_key_cmd cmd, | 239 | enum set_key_cmd cmd, |
238 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, | 240 | struct ieee80211_vif *vif, struct ieee80211_sta *sta, |
@@ -260,6 +262,7 @@ static const struct ieee80211_ops ath5k_hw_ops = { | |||
260 | .add_interface = ath5k_add_interface, | 262 | .add_interface = ath5k_add_interface, |
261 | .remove_interface = ath5k_remove_interface, | 263 | .remove_interface = ath5k_remove_interface, |
262 | .config = ath5k_config, | 264 | .config = ath5k_config, |
265 | .prepare_multicast = ath5k_prepare_multicast, | ||
263 | .configure_filter = ath5k_configure_filter, | 266 | .configure_filter = ath5k_configure_filter, |
264 | .set_key = ath5k_set_key, | 267 | .set_key = ath5k_set_key, |
265 | .get_stats = ath5k_get_stats, | 268 | .get_stats = ath5k_get_stats, |
@@ -715,9 +718,9 @@ static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *re | |||
715 | { | 718 | { |
716 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 719 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
717 | struct ath5k_softc *sc = hw->priv; | 720 | struct ath5k_softc *sc = hw->priv; |
718 | struct ath_regulatory *reg = &sc->ah->ah_regulatory; | 721 | struct ath_regulatory *regulatory = &sc->common.regulatory; |
719 | 722 | ||
720 | return ath_reg_notifier_apply(wiphy, request, reg); | 723 | return ath_reg_notifier_apply(wiphy, request, regulatory); |
721 | } | 724 | } |
722 | 725 | ||
723 | static int | 726 | static int |
@@ -725,6 +728,7 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
725 | { | 728 | { |
726 | struct ath5k_softc *sc = hw->priv; | 729 | struct ath5k_softc *sc = hw->priv; |
727 | struct ath5k_hw *ah = sc->ah; | 730 | struct ath5k_hw *ah = sc->ah; |
731 | struct ath_regulatory *regulatory = &sc->common.regulatory; | ||
728 | u8 mac[ETH_ALEN] = {}; | 732 | u8 mac[ETH_ALEN] = {}; |
729 | int ret; | 733 | int ret; |
730 | 734 | ||
@@ -814,9 +818,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
814 | memset(sc->bssidmask, 0xff, ETH_ALEN); | 818 | memset(sc->bssidmask, 0xff, ETH_ALEN); |
815 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); | 819 | ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); |
816 | 820 | ||
817 | ah->ah_regulatory.current_rd = | 821 | regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; |
818 | ah->ah_capabilities.cap_eeprom.ee_regdomain; | 822 | ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); |
819 | ret = ath_regd_init(&ah->ah_regulatory, hw->wiphy, ath5k_reg_notifier); | ||
820 | if (ret) { | 823 | if (ret) { |
821 | ATH5K_ERR(sc, "can't initialize regulatory system\n"); | 824 | ATH5K_ERR(sc, "can't initialize regulatory system\n"); |
822 | goto err_queues; | 825 | goto err_queues; |
@@ -828,8 +831,8 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) | |||
828 | goto err_queues; | 831 | goto err_queues; |
829 | } | 832 | } |
830 | 833 | ||
831 | if (!ath_is_world_regd(&sc->ah->ah_regulatory)) | 834 | if (!ath_is_world_regd(regulatory)) |
832 | regulatory_hint(hw->wiphy, sc->ah->ah_regulatory.alpha2); | 835 | regulatory_hint(hw->wiphy, regulatory->alpha2); |
833 | 836 | ||
834 | ath5k_init_leds(sc); | 837 | ath5k_init_leds(sc); |
835 | 838 | ||
@@ -2853,6 +2856,37 @@ unlock: | |||
2853 | return ret; | 2856 | return ret; |
2854 | } | 2857 | } |
2855 | 2858 | ||
2859 | static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, | ||
2860 | int mc_count, struct dev_addr_list *mclist) | ||
2861 | { | ||
2862 | u32 mfilt[2], val; | ||
2863 | int i; | ||
2864 | u8 pos; | ||
2865 | |||
2866 | mfilt[0] = 0; | ||
2867 | mfilt[1] = 1; | ||
2868 | |||
2869 | for (i = 0; i < mc_count; i++) { | ||
2870 | if (!mclist) | ||
2871 | break; | ||
2872 | /* calculate XOR of eight 6-bit values */ | ||
2873 | val = get_unaligned_le32(mclist->dmi_addr + 0); | ||
2874 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2875 | val = get_unaligned_le32(mclist->dmi_addr + 3); | ||
2876 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2877 | pos &= 0x3f; | ||
2878 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
2879 | /* XXX: we might be able to just do this instead, | ||
2880 | * but not sure, needs testing, if we do use this we'd | ||
2881 | * neet to inform below to not reset the mcast */ | ||
2882 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
2883 | * mclist->dmi_addr[5]); */ | ||
2884 | mclist = mclist->next; | ||
2885 | } | ||
2886 | |||
2887 | return ((u64)(mfilt[1]) << 32) | mfilt[0]; | ||
2888 | } | ||
2889 | |||
2856 | #define SUPPORTED_FIF_FLAGS \ | 2890 | #define SUPPORTED_FIF_FLAGS \ |
2857 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ | 2891 | FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ |
2858 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ | 2892 | FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ |
@@ -2878,16 +2912,14 @@ unlock: | |||
2878 | static void ath5k_configure_filter(struct ieee80211_hw *hw, | 2912 | static void ath5k_configure_filter(struct ieee80211_hw *hw, |
2879 | unsigned int changed_flags, | 2913 | unsigned int changed_flags, |
2880 | unsigned int *new_flags, | 2914 | unsigned int *new_flags, |
2881 | int mc_count, struct dev_mc_list *mclist) | 2915 | u64 multicast) |
2882 | { | 2916 | { |
2883 | struct ath5k_softc *sc = hw->priv; | 2917 | struct ath5k_softc *sc = hw->priv; |
2884 | struct ath5k_hw *ah = sc->ah; | 2918 | struct ath5k_hw *ah = sc->ah; |
2885 | u32 mfilt[2], val, rfilt; | 2919 | u32 mfilt[2], rfilt; |
2886 | u8 pos; | ||
2887 | int i; | ||
2888 | 2920 | ||
2889 | mfilt[0] = 0; | 2921 | mfilt[0] = multicast; |
2890 | mfilt[1] = 0; | 2922 | mfilt[1] = multicast >> 32; |
2891 | 2923 | ||
2892 | /* Only deal with supported flags */ | 2924 | /* Only deal with supported flags */ |
2893 | changed_flags &= SUPPORTED_FIF_FLAGS; | 2925 | changed_flags &= SUPPORTED_FIF_FLAGS; |
@@ -2913,24 +2945,6 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw, | |||
2913 | if (*new_flags & FIF_ALLMULTI) { | 2945 | if (*new_flags & FIF_ALLMULTI) { |
2914 | mfilt[0] = ~0; | 2946 | mfilt[0] = ~0; |
2915 | mfilt[1] = ~0; | 2947 | mfilt[1] = ~0; |
2916 | } else { | ||
2917 | for (i = 0; i < mc_count; i++) { | ||
2918 | if (!mclist) | ||
2919 | break; | ||
2920 | /* calculate XOR of eight 6-bit values */ | ||
2921 | val = get_unaligned_le32(mclist->dmi_addr + 0); | ||
2922 | pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2923 | val = get_unaligned_le32(mclist->dmi_addr + 3); | ||
2924 | pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; | ||
2925 | pos &= 0x3f; | ||
2926 | mfilt[pos / 32] |= (1 << (pos % 32)); | ||
2927 | /* XXX: we might be able to just do this instead, | ||
2928 | * but not sure, needs testing, if we do use this we'd | ||
2929 | * neet to inform below to not reset the mcast */ | ||
2930 | /* ath5k_hw_set_mcast_filterindex(ah, | ||
2931 | * mclist->dmi_addr[5]); */ | ||
2932 | mclist = mclist->next; | ||
2933 | } | ||
2934 | } | 2948 | } |
2935 | 2949 | ||
2936 | /* This is the best we can do */ | 2950 | /* This is the best we can do */ |
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h index 25a72a85aaa5..a28c42f32c9d 100644 --- a/drivers/net/wireless/ath/ath5k/base.h +++ b/drivers/net/wireless/ath/ath5k/base.h | |||
@@ -50,6 +50,8 @@ | |||
50 | 50 | ||
51 | #include "ath5k.h" | 51 | #include "ath5k.h" |
52 | #include "debug.h" | 52 | #include "debug.h" |
53 | |||
54 | #include "../regd.h" | ||
53 | #include "../ath.h" | 55 | #include "../ath.h" |
54 | 56 | ||
55 | #define ATH_RXBUF 40 /* number of RX buffers */ | 57 | #define ATH_RXBUF 40 /* number of RX buffers */ |
@@ -200,4 +202,15 @@ struct ath5k_softc { | |||
200 | #define ath5k_hw_hasveol(_ah) \ | 202 | #define ath5k_hw_hasveol(_ah) \ |
201 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) | 203 | (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) |
202 | 204 | ||
205 | static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) | ||
206 | { | ||
207 | return &ah->ah_sc->common; | ||
208 | } | ||
209 | |||
210 | static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) | ||
211 | { | ||
212 | return &(ath5k_hw_common(ah)->regulatory); | ||
213 | |||
214 | } | ||
215 | |||
203 | #endif | 216 | #endif |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 298fcf015227..1a039f2bd732 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -2198,6 +2198,7 @@ static void | |||
2198 | ath5k_get_max_ctl_power(struct ath5k_hw *ah, | 2198 | ath5k_get_max_ctl_power(struct ath5k_hw *ah, |
2199 | struct ieee80211_channel *channel) | 2199 | struct ieee80211_channel *channel) |
2200 | { | 2200 | { |
2201 | struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); | ||
2201 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; | 2202 | struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; |
2202 | struct ath5k_edge_power *rep = ee->ee_ctl_pwr; | 2203 | struct ath5k_edge_power *rep = ee->ee_ctl_pwr; |
2203 | u8 *ctl_val = ee->ee_ctl; | 2204 | u8 *ctl_val = ee->ee_ctl; |
@@ -2208,7 +2209,7 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah, | |||
2208 | u8 ctl_idx = 0xFF; | 2209 | u8 ctl_idx = 0xFF; |
2209 | u32 target = channel->center_freq; | 2210 | u32 target = channel->center_freq; |
2210 | 2211 | ||
2211 | ctl_mode = ath_regd_get_band_ctl(&ah->ah_regulatory, channel->band); | 2212 | ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band); |
2212 | 2213 | ||
2213 | switch (channel->hw_value & CHANNEL_MODES) { | 2214 | switch (channel->hw_value & CHANNEL_MODES) { |
2214 | case CHANNEL_A: | 2215 | case CHANNEL_A: |
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c index f264097a2f4e..a7cbb07988cf 100644 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ b/drivers/net/wireless/ath/ath9k/ani.c | |||
@@ -538,7 +538,6 @@ void ath9k_ani_reset(struct ath_hw *ah) | |||
538 | } | 538 | } |
539 | 539 | ||
540 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 540 | void ath9k_hw_ani_monitor(struct ath_hw *ah, |
541 | const struct ath9k_node_stats *stats, | ||
542 | struct ath9k_channel *chan) | 541 | struct ath9k_channel *chan) |
543 | { | 542 | { |
544 | struct ar5416AniState *aniState; | 543 | struct ar5416AniState *aniState; |
@@ -550,7 +549,6 @@ void ath9k_hw_ani_monitor(struct ath_hw *ah, | |||
550 | return; | 549 | return; |
551 | 550 | ||
552 | aniState = ah->curani; | 551 | aniState = ah->curani; |
553 | ah->stats.ast_nodestats = *stats; | ||
554 | 552 | ||
555 | listenTime = ath9k_hw_ani_get_listen_time(ah); | 553 | listenTime = ath9k_hw_ani_get_listen_time(ah); |
556 | if (listenTime < 0) { | 554 | if (listenTime < 0) { |
@@ -693,8 +691,7 @@ u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, | |||
693 | * any of the MIB counters overflow/trigger so don't assume we're | 691 | * any of the MIB counters overflow/trigger so don't assume we're |
694 | * here because a PHY error counter triggered. | 692 | * here because a PHY error counter triggered. |
695 | */ | 693 | */ |
696 | void ath9k_hw_procmibevent(struct ath_hw *ah, | 694 | void ath9k_hw_procmibevent(struct ath_hw *ah) |
697 | const struct ath9k_node_stats *stats) | ||
698 | { | 695 | { |
699 | u32 phyCnt1, phyCnt2; | 696 | u32 phyCnt1, phyCnt2; |
700 | 697 | ||
@@ -706,7 +703,6 @@ void ath9k_hw_procmibevent(struct ath_hw *ah, | |||
706 | 703 | ||
707 | /* Clear the mib counters and save them in the stats */ | 704 | /* Clear the mib counters and save them in the stats */ |
708 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); | 705 | ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); |
709 | ah->stats.ast_nodestats = *stats; | ||
710 | 706 | ||
711 | if (!DO_ANI(ah)) | 707 | if (!DO_ANI(ah)) |
712 | return; | 708 | return; |
diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h index 119924511f85..4e1ab94a5153 100644 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ b/drivers/net/wireless/ath/ath9k/ani.h | |||
@@ -18,15 +18,10 @@ | |||
18 | #define ANI_H | 18 | #define ANI_H |
19 | 19 | ||
20 | #define HAL_PROCESS_ANI 0x00000001 | 20 | #define HAL_PROCESS_ANI 0x00000001 |
21 | #define ATH9K_RSSI_EP_MULTIPLIER (1<<7) | ||
22 | 21 | ||
23 | #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) | 22 | #define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) |
24 | 23 | ||
25 | #define HAL_EP_RND(x, mul) \ | 24 | #define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) |
26 | ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) | ||
27 | #define BEACON_RSSI(ahp) \ | ||
28 | HAL_EP_RND(ahp->stats.ast_nodestats.ns_avgbrssi, \ | ||
29 | ATH9K_RSSI_EP_MULTIPLIER) | ||
30 | 25 | ||
31 | #define ATH9K_ANI_OFDM_TRIG_HIGH 500 | 26 | #define ATH9K_ANI_OFDM_TRIG_HIGH 500 |
32 | #define ATH9K_ANI_OFDM_TRIG_LOW 200 | 27 | #define ATH9K_ANI_OFDM_TRIG_LOW 200 |
@@ -65,13 +60,6 @@ struct ath9k_mib_stats { | |||
65 | u32 beacons; | 60 | u32 beacons; |
66 | }; | 61 | }; |
67 | 62 | ||
68 | struct ath9k_node_stats { | ||
69 | u32 ns_avgbrssi; | ||
70 | u32 ns_avgrssi; | ||
71 | u32 ns_avgtxrssi; | ||
72 | u32 ns_avgtxrate; | ||
73 | }; | ||
74 | |||
75 | struct ar5416AniState { | 63 | struct ar5416AniState { |
76 | struct ath9k_channel *c; | 64 | struct ath9k_channel *c; |
77 | u8 noiseImmunityLevel; | 65 | u8 noiseImmunityLevel; |
@@ -115,21 +103,19 @@ struct ar5416Stats { | |||
115 | u32 ast_ani_reset; | 103 | u32 ast_ani_reset; |
116 | u32 ast_ani_lzero; | 104 | u32 ast_ani_lzero; |
117 | u32 ast_ani_lneg; | 105 | u32 ast_ani_lneg; |
106 | u32 avgbrssi; | ||
118 | struct ath9k_mib_stats ast_mibstats; | 107 | struct ath9k_mib_stats ast_mibstats; |
119 | struct ath9k_node_stats ast_nodestats; | ||
120 | }; | 108 | }; |
121 | #define ah_mibStats stats.ast_mibstats | 109 | #define ah_mibStats stats.ast_mibstats |
122 | 110 | ||
123 | void ath9k_ani_reset(struct ath_hw *ah); | 111 | void ath9k_ani_reset(struct ath_hw *ah); |
124 | void ath9k_hw_ani_monitor(struct ath_hw *ah, | 112 | void ath9k_hw_ani_monitor(struct ath_hw *ah, |
125 | const struct ath9k_node_stats *stats, | ||
126 | struct ath9k_channel *chan); | 113 | struct ath9k_channel *chan); |
127 | void ath9k_enable_mib_counters(struct ath_hw *ah); | 114 | void ath9k_enable_mib_counters(struct ath_hw *ah); |
128 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); | 115 | void ath9k_hw_disable_mib_counters(struct ath_hw *ah); |
129 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, | 116 | u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, |
130 | u32 *rxf_pcnt, u32 *txf_pcnt); | 117 | u32 *rxf_pcnt, u32 *txf_pcnt); |
131 | void ath9k_hw_procmibevent(struct ath_hw *ah, | 118 | void ath9k_hw_procmibevent(struct ath_hw *ah); |
132 | const struct ath9k_node_stats *stats); | ||
133 | void ath9k_hw_ani_setup(struct ath_hw *ah); | 119 | void ath9k_hw_ani_setup(struct ath_hw *ah); |
134 | void ath9k_hw_ani_init(struct ath_hw *ah); | 120 | void ath9k_hw_ani_init(struct ath_hw *ah); |
135 | void ath9k_hw_ani_disable(struct ath_hw *ah); | 121 | void ath9k_hw_ani_disable(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 2fd663c01b8e..7705da1103f4 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -454,7 +454,8 @@ struct ath_ani { | |||
454 | /* LED Control */ | 454 | /* LED Control */ |
455 | /********************/ | 455 | /********************/ |
456 | 456 | ||
457 | #define ATH_LED_PIN 1 | 457 | #define ATH_LED_PIN_DEF 1 |
458 | #define ATH_LED_PIN_9287 8 | ||
458 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ | 459 | #define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ |
459 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ | 460 | #define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ |
460 | 461 | ||
@@ -602,7 +603,6 @@ struct ath_softc { | |||
602 | int beacon_interval; | 603 | int beacon_interval; |
603 | 604 | ||
604 | struct ath_ani ani; | 605 | struct ath_ani ani; |
605 | struct ath9k_node_stats nodestats; | ||
606 | #ifdef CONFIG_ATH9K_DEBUG | 606 | #ifdef CONFIG_ATH9K_DEBUG |
607 | struct ath9k_debug debug; | 607 | struct ath9k_debug debug; |
608 | #endif | 608 | #endif |
@@ -630,6 +630,16 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); | |||
630 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); | 630 | int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); |
631 | int ath_cabq_update(struct ath_softc *); | 631 | int ath_cabq_update(struct ath_softc *); |
632 | 632 | ||
633 | static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) | ||
634 | { | ||
635 | return &ah->ah_sc->common; | ||
636 | } | ||
637 | |||
638 | static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) | ||
639 | { | ||
640 | return &(ath9k_hw_common(ah)->regulatory); | ||
641 | } | ||
642 | |||
633 | static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) | 643 | static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) |
634 | { | 644 | { |
635 | sc->bus_ops->read_cachesize(sc, csz); | 645 | sc->bus_ops->read_cachesize(sc, csz); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 26d87527acbd..20f74b5b5703 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -729,26 +729,42 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | |||
729 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) | 729 | static void ath9k_olc_temp_compensation(struct ath_hw *ah) |
730 | { | 730 | { |
731 | u32 rddata, i; | 731 | u32 rddata, i; |
732 | int delta, currPDADC, regval; | 732 | int delta, currPDADC, regval, slope; |
733 | 733 | ||
734 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); | 734 | rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); |
735 | |||
736 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); | 735 | currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); |
737 | 736 | ||
738 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) | ||
739 | delta = (currPDADC - ah->initPDADC + 4) / 8; | ||
740 | else | ||
741 | delta = (currPDADC - ah->initPDADC + 5) / 10; | ||
742 | 737 | ||
743 | if (delta != ah->PDADCdelta) { | 738 | if (OLC_FOR_AR9287_10_LATER) { |
744 | ah->PDADCdelta = delta; | 739 | if (ah->initPDADC == 0 || currPDADC == 0) { |
745 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { | 740 | return; |
746 | regval = ah->originalGain[i] - delta; | 741 | } else { |
747 | if (regval < 0) | 742 | slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); |
748 | regval = 0; | 743 | if (slope == 0) |
744 | delta = 0; | ||
745 | else | ||
746 | delta = ((currPDADC - ah->initPDADC)*4) / slope; | ||
747 | REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, | ||
748 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
749 | REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, | ||
750 | AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); | ||
751 | } | ||
752 | } else { | ||
753 | if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) | ||
754 | delta = (currPDADC - ah->initPDADC + 4) / 8; | ||
755 | else | ||
756 | delta = (currPDADC - ah->initPDADC + 5) / 10; | ||
757 | |||
758 | if (delta != ah->PDADCdelta) { | ||
759 | ah->PDADCdelta = delta; | ||
760 | for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { | ||
761 | regval = ah->originalGain[i] - delta; | ||
762 | if (regval < 0) | ||
763 | regval = 0; | ||
749 | 764 | ||
750 | REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, | 765 | REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, |
751 | AR_PHY_TX_GAIN, regval); | 766 | AR_PHY_TX_GAIN, regval); |
767 | } | ||
752 | } | 768 | } |
753 | } | 769 | } |
754 | } | 770 | } |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index d34dd23e806a..b8eca7be5f3a 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
@@ -508,6 +508,7 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
508 | || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ | 508 | || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ |
509 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) | 509 | ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) |
510 | 510 | ||
511 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
511 | int i; | 512 | int i; |
512 | int16_t twiceLargestAntenna; | 513 | int16_t twiceLargestAntenna; |
513 | u16 twiceMinEdgePower; | 514 | u16 twiceMinEdgePower; |
@@ -541,9 +542,9 @@ static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, | |||
541 | twiceLargestAntenna, 0); | 542 | twiceLargestAntenna, 0); |
542 | 543 | ||
543 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | 544 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; |
544 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | 545 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { |
545 | maxRegAllowedPower -= | 546 | maxRegAllowedPower -= |
546 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | 547 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); |
547 | } | 548 | } |
548 | 549 | ||
549 | scaledPower = min(powerLimit, maxRegAllowedPower); | 550 | scaledPower = min(powerLimit, maxRegAllowedPower); |
@@ -707,6 +708,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
707 | u8 twiceMaxRegulatoryPower, | 708 | u8 twiceMaxRegulatoryPower, |
708 | u8 powerLimit) | 709 | u8 powerLimit) |
709 | { | 710 | { |
711 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
710 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; | 712 | struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; |
711 | struct modal_eep_4k_header *pModal = &pEepData->modalHeader; | 713 | struct modal_eep_4k_header *pModal = &pEepData->modalHeader; |
712 | int16_t ratesArray[Ar5416RateSize]; | 714 | int16_t ratesArray[Ar5416RateSize]; |
@@ -744,7 +746,7 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, | |||
744 | else if (IS_CHAN_HT20(chan)) | 746 | else if (IS_CHAN_HT20(chan)) |
745 | i = rateHt20_0; | 747 | i = rateHt20_0; |
746 | 748 | ||
747 | ah->regulatory.max_power_level = ratesArray[i]; | 749 | regulatory->max_power_level = ratesArray[i]; |
748 | 750 | ||
749 | if (AR_SREV_9280_10_OR_LATER(ah)) { | 751 | if (AR_SREV_9280_10_OR_LATER(ah)) { |
750 | for (i = 0; i < Ar5416RateSize; i++) | 752 | for (i = 0; i < Ar5416RateSize; i++) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index aeb7f484b6e1..c20c21a79b21 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
@@ -374,7 +374,6 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | |||
374 | u8 *pCalChans, u16 availPiers, | 374 | u8 *pCalChans, u16 availPiers, |
375 | int8_t *pPwr) | 375 | int8_t *pPwr) |
376 | { | 376 | { |
377 | u8 pcdac, i = 0; | ||
378 | u16 idxL = 0, idxR = 0, numPiers; | 377 | u16 idxL = 0, idxR = 0, numPiers; |
379 | bool match; | 378 | bool match; |
380 | struct chan_centers centers; | 379 | struct chan_centers centers; |
@@ -392,17 +391,12 @@ static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, | |||
392 | &idxL, &idxR); | 391 | &idxL, &idxR); |
393 | 392 | ||
394 | if (match) { | 393 | if (match) { |
395 | pcdac = pRawDatasetOpLoop[idxL].pcdac[0][0]; | 394 | *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; |
396 | *pPwr = pRawDatasetOpLoop[idxL].pwrPdg[0][0]; | ||
397 | } else { | 395 | } else { |
398 | pcdac = pRawDatasetOpLoop[idxR].pcdac[0][0]; | 396 | *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + |
399 | *pPwr = (pRawDatasetOpLoop[idxL].pwrPdg[0][0] + | 397 | (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; |
400 | pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; | ||
401 | } | 398 | } |
402 | 399 | ||
403 | while ((pcdac > ah->originalGain[i]) && | ||
404 | (i < (AR9280_TX_GAIN_TABLE_SIZE - 1))) | ||
405 | i++; | ||
406 | } | 400 | } |
407 | 401 | ||
408 | static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, | 402 | static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, |
@@ -605,7 +599,7 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
605 | { | 599 | { |
606 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 | 600 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 |
607 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 | 601 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 |
608 | 602 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | |
609 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 603 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; |
610 | static const u16 tpScaleReductionTable[5] = | 604 | static const u16 tpScaleReductionTable[5] = |
611 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; | 605 | { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; |
@@ -638,9 +632,9 @@ static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, | |||
638 | twiceLargestAntenna, 0); | 632 | twiceLargestAntenna, 0); |
639 | 633 | ||
640 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | 634 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; |
641 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) | 635 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) |
642 | maxRegAllowedPower -= | 636 | maxRegAllowedPower -= |
643 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | 637 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); |
644 | 638 | ||
645 | scaledPower = min(powerLimit, maxRegAllowedPower); | 639 | scaledPower = min(powerLimit, maxRegAllowedPower); |
646 | 640 | ||
@@ -837,7 +831,7 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
837 | { | 831 | { |
838 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 | 832 | #define INCREASE_MAXPOW_BY_TWO_CHAIN 6 |
839 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 | 833 | #define INCREASE_MAXPOW_BY_THREE_CHAIN 10 |
840 | 834 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | |
841 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; | 835 | struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; |
842 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; | 836 | struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; |
843 | int16_t ratesArray[Ar5416RateSize]; | 837 | int16_t ratesArray[Ar5416RateSize]; |
@@ -955,20 +949,20 @@ static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, | |||
955 | i = rate6mb; | 949 | i = rate6mb; |
956 | 950 | ||
957 | if (AR_SREV_9280_10_OR_LATER(ah)) | 951 | if (AR_SREV_9280_10_OR_LATER(ah)) |
958 | ah->regulatory.max_power_level = | 952 | regulatory->max_power_level = |
959 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; | 953 | ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; |
960 | else | 954 | else |
961 | ah->regulatory.max_power_level = ratesArray[i]; | 955 | regulatory->max_power_level = ratesArray[i]; |
962 | 956 | ||
963 | switch (ar5416_get_ntxchains(ah->txchainmask)) { | 957 | switch (ar5416_get_ntxchains(ah->txchainmask)) { |
964 | case 1: | 958 | case 1: |
965 | break; | 959 | break; |
966 | case 2: | 960 | case 2: |
967 | ah->regulatory.max_power_level += | 961 | regulatory->max_power_level += |
968 | INCREASE_MAXPOW_BY_TWO_CHAIN; | 962 | INCREASE_MAXPOW_BY_TWO_CHAIN; |
969 | break; | 963 | break; |
970 | case 3: | 964 | case 3: |
971 | ah->regulatory.max_power_level += | 965 | regulatory->max_power_level += |
972 | INCREASE_MAXPOW_BY_THREE_CHAIN; | 966 | INCREASE_MAXPOW_BY_THREE_CHAIN; |
973 | break; | 967 | break; |
974 | default: | 968 | default: |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 5211ad94c8fb..ae7fb5dcb266 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -904,6 +904,7 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
904 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ | 904 | #define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ |
905 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ | 905 | #define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ |
906 | 906 | ||
907 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
907 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 908 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
908 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; | 909 | u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; |
909 | static const u16 tpScaleReductionTable[5] = | 910 | static const u16 tpScaleReductionTable[5] = |
@@ -953,9 +954,9 @@ static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, | |||
953 | 954 | ||
954 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; | 955 | maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; |
955 | 956 | ||
956 | if (ah->regulatory.tp_scale != ATH9K_TP_SCALE_MAX) { | 957 | if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { |
957 | maxRegAllowedPower -= | 958 | maxRegAllowedPower -= |
958 | (tpScaleReductionTable[(ah->regulatory.tp_scale)] * 2); | 959 | (tpScaleReductionTable[(regulatory->tp_scale)] * 2); |
959 | } | 960 | } |
960 | 961 | ||
961 | scaledPower = min(powerLimit, maxRegAllowedPower); | 962 | scaledPower = min(powerLimit, maxRegAllowedPower); |
@@ -1163,6 +1164,7 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1163 | u8 powerLimit) | 1164 | u8 powerLimit) |
1164 | { | 1165 | { |
1165 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) | 1166 | #define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) |
1167 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
1166 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; | 1168 | struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; |
1167 | struct modal_eep_header *pModal = | 1169 | struct modal_eep_header *pModal = |
1168 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); | 1170 | &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); |
@@ -1292,19 +1294,19 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah, | |||
1292 | i = rateHt20_0; | 1294 | i = rateHt20_0; |
1293 | 1295 | ||
1294 | if (AR_SREV_9280_10_OR_LATER(ah)) | 1296 | if (AR_SREV_9280_10_OR_LATER(ah)) |
1295 | ah->regulatory.max_power_level = | 1297 | regulatory->max_power_level = |
1296 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; | 1298 | ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; |
1297 | else | 1299 | else |
1298 | ah->regulatory.max_power_level = ratesArray[i]; | 1300 | regulatory->max_power_level = ratesArray[i]; |
1299 | 1301 | ||
1300 | switch(ar5416_get_ntxchains(ah->txchainmask)) { | 1302 | switch(ar5416_get_ntxchains(ah->txchainmask)) { |
1301 | case 1: | 1303 | case 1: |
1302 | break; | 1304 | break; |
1303 | case 2: | 1305 | case 2: |
1304 | ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; | 1306 | regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; |
1305 | break; | 1307 | break; |
1306 | case 3: | 1308 | case 3: |
1307 | ah->regulatory.max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; | 1309 | regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; |
1308 | break; | 1310 | break; |
1309 | default: | 1311 | default: |
1310 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, | 1312 | DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 9f1b34d9861a..4f3d5ea34812 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -439,8 +439,13 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
439 | 439 | ||
440 | static void ath9k_hw_init_defaults(struct ath_hw *ah) | 440 | static void ath9k_hw_init_defaults(struct ath_hw *ah) |
441 | { | 441 | { |
442 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
443 | |||
444 | regulatory->country_code = CTRY_DEFAULT; | ||
445 | regulatory->power_limit = MAX_RATE_POWER; | ||
446 | regulatory->tp_scale = ATH9K_TP_SCALE_MAX; | ||
447 | |||
442 | ah->hw_version.magic = AR5416_MAGIC; | 448 | ah->hw_version.magic = AR5416_MAGIC; |
443 | ah->regulatory.country_code = CTRY_DEFAULT; | ||
444 | ah->hw_version.subvendorid = 0; | 449 | ah->hw_version.subvendorid = 0; |
445 | 450 | ||
446 | ah->ah_flags = 0; | 451 | ah->ah_flags = 0; |
@@ -449,8 +454,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
449 | if (!AR_SREV_9100(ah)) | 454 | if (!AR_SREV_9100(ah)) |
450 | ah->ah_flags = AH_USE_EEPROM; | 455 | ah->ah_flags = AH_USE_EEPROM; |
451 | 456 | ||
452 | ah->regulatory.power_limit = MAX_RATE_POWER; | ||
453 | ah->regulatory.tp_scale = ATH9K_TP_SCALE_MAX; | ||
454 | ah->atim_window = 0; | 457 | ah->atim_window = 0; |
455 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; | 458 | ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; |
456 | ah->beacon_interval = 100; | 459 | ah->beacon_interval = 100; |
@@ -1332,11 +1335,21 @@ static void ath9k_olc_init(struct ath_hw *ah) | |||
1332 | { | 1335 | { |
1333 | u32 i; | 1336 | u32 i; |
1334 | 1337 | ||
1335 | for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) | 1338 | if (OLC_FOR_AR9287_10_LATER) { |
1336 | ah->originalGain[i] = | 1339 | REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, |
1337 | MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), | 1340 | AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); |
1338 | AR_PHY_TX_GAIN); | 1341 | ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, |
1339 | ah->PDADCdelta = 0; | 1342 | AR9287_AN_TXPC0_TXPCMODE, |
1343 | AR9287_AN_TXPC0_TXPCMODE_S, | ||
1344 | AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); | ||
1345 | udelay(100); | ||
1346 | } else { | ||
1347 | for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) | ||
1348 | ah->originalGain[i] = | ||
1349 | MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), | ||
1350 | AR_PHY_TX_GAIN); | ||
1351 | ah->PDADCdelta = 0; | ||
1352 | } | ||
1340 | } | 1353 | } |
1341 | 1354 | ||
1342 | static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, | 1355 | static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, |
@@ -1358,6 +1371,7 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1358 | struct ath9k_channel *chan, | 1371 | struct ath9k_channel *chan, |
1359 | enum ath9k_ht_macmode macmode) | 1372 | enum ath9k_ht_macmode macmode) |
1360 | { | 1373 | { |
1374 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
1361 | int i, regWrites = 0; | 1375 | int i, regWrites = 0; |
1362 | struct ieee80211_channel *channel = chan->chan; | 1376 | struct ieee80211_channel *channel = chan->chan; |
1363 | u32 modesIndex, freqIndex; | 1377 | u32 modesIndex, freqIndex; |
@@ -1464,11 +1478,11 @@ static int ath9k_hw_process_ini(struct ath_hw *ah, | |||
1464 | ath9k_olc_init(ah); | 1478 | ath9k_olc_init(ah); |
1465 | 1479 | ||
1466 | ah->eep_ops->set_txpower(ah, chan, | 1480 | ah->eep_ops->set_txpower(ah, chan, |
1467 | ath9k_regd_get_ctl(&ah->regulatory, chan), | 1481 | ath9k_regd_get_ctl(regulatory, chan), |
1468 | channel->max_antenna_gain * 2, | 1482 | channel->max_antenna_gain * 2, |
1469 | channel->max_power * 2, | 1483 | channel->max_power * 2, |
1470 | min((u32) MAX_RATE_POWER, | 1484 | min((u32) MAX_RATE_POWER, |
1471 | (u32) ah->regulatory.power_limit)); | 1485 | (u32) regulatory->power_limit)); |
1472 | 1486 | ||
1473 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { | 1487 | if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { |
1474 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, | 1488 | DPRINTF(ah->ah_sc, ATH_DBG_FATAL, |
@@ -1786,6 +1800,7 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1786 | struct ath9k_channel *chan, | 1800 | struct ath9k_channel *chan, |
1787 | enum ath9k_ht_macmode macmode) | 1801 | enum ath9k_ht_macmode macmode) |
1788 | { | 1802 | { |
1803 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
1789 | struct ieee80211_channel *channel = chan->chan; | 1804 | struct ieee80211_channel *channel = chan->chan; |
1790 | u32 synthDelay, qnum; | 1805 | u32 synthDelay, qnum; |
1791 | 1806 | ||
@@ -1818,11 +1833,11 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah, | |||
1818 | } | 1833 | } |
1819 | 1834 | ||
1820 | ah->eep_ops->set_txpower(ah, chan, | 1835 | ah->eep_ops->set_txpower(ah, chan, |
1821 | ath9k_regd_get_ctl(&ah->regulatory, chan), | 1836 | ath9k_regd_get_ctl(regulatory, chan), |
1822 | channel->max_antenna_gain * 2, | 1837 | channel->max_antenna_gain * 2, |
1823 | channel->max_power * 2, | 1838 | channel->max_power * 2, |
1824 | min((u32) MAX_RATE_POWER, | 1839 | min((u32) MAX_RATE_POWER, |
1825 | (u32) ah->regulatory.power_limit)); | 1840 | (u32) regulatory->power_limit)); |
1826 | 1841 | ||
1827 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | 1842 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; |
1828 | if (IS_CHAN_B(chan)) | 1843 | if (IS_CHAN_B(chan)) |
@@ -2382,7 +2397,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2382 | if (AR_SREV_9280_10_OR_LATER(ah)) | 2397 | if (AR_SREV_9280_10_OR_LATER(ah)) |
2383 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); | 2398 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); |
2384 | 2399 | ||
2385 | if (AR_SREV_9287_10_OR_LATER(ah)) { | 2400 | if (AR_SREV_9287_12_OR_LATER(ah)) { |
2386 | /* Enable ASYNC FIFO */ | 2401 | /* Enable ASYNC FIFO */ |
2387 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, | 2402 | REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, |
2388 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); | 2403 | AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); |
@@ -2468,7 +2483,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2468 | 2483 | ||
2469 | ath9k_hw_init_user_settings(ah); | 2484 | ath9k_hw_init_user_settings(ah); |
2470 | 2485 | ||
2471 | if (AR_SREV_9287_10_OR_LATER(ah)) { | 2486 | if (AR_SREV_9287_12_OR_LATER(ah)) { |
2472 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, | 2487 | REG_WRITE(ah, AR_D_GBL_IFS_SIFS, |
2473 | AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); | 2488 | AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); |
2474 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, | 2489 | REG_WRITE(ah, AR_D_GBL_IFS_SLOT, |
@@ -2484,7 +2499,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2484 | REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, | 2499 | REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, |
2485 | AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); | 2500 | AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); |
2486 | } | 2501 | } |
2487 | if (AR_SREV_9287_10_OR_LATER(ah)) { | 2502 | if (AR_SREV_9287_12_OR_LATER(ah)) { |
2488 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | 2503 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, |
2489 | AR_PCU_MISC_MODE2_ENABLE_AGGWEP); | 2504 | AR_PCU_MISC_MODE2_ENABLE_AGGWEP); |
2490 | } | 2505 | } |
@@ -3063,7 +3078,7 @@ void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore) | |||
3063 | if (ah->config.pcie_waen) { | 3078 | if (ah->config.pcie_waen) { |
3064 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); | 3079 | REG_WRITE(ah, AR_WA, ah->config.pcie_waen); |
3065 | } else { | 3080 | } else { |
3066 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) | 3081 | if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || AR_SREV_9287(ah)) |
3067 | REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); | 3082 | REG_WRITE(ah, AR_WA, AR9285_WA_DEFAULT); |
3068 | /* | 3083 | /* |
3069 | * On AR9280 chips bit 22 of 0x4004 needs to be set to | 3084 | * On AR9280 chips bit 22 of 0x4004 needs to be set to |
@@ -3470,27 +3485,29 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
3470 | void ath9k_hw_fill_cap_info(struct ath_hw *ah) | 3485 | void ath9k_hw_fill_cap_info(struct ath_hw *ah) |
3471 | { | 3486 | { |
3472 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 3487 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
3488 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
3489 | |||
3473 | u16 capField = 0, eeval; | 3490 | u16 capField = 0, eeval; |
3474 | 3491 | ||
3475 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); | 3492 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); |
3476 | ah->regulatory.current_rd = eeval; | 3493 | regulatory->current_rd = eeval; |
3477 | 3494 | ||
3478 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); | 3495 | eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); |
3479 | if (AR_SREV_9285_10_OR_LATER(ah)) | 3496 | if (AR_SREV_9285_10_OR_LATER(ah)) |
3480 | eeval |= AR9285_RDEXT_DEFAULT; | 3497 | eeval |= AR9285_RDEXT_DEFAULT; |
3481 | ah->regulatory.current_rd_ext = eeval; | 3498 | regulatory->current_rd_ext = eeval; |
3482 | 3499 | ||
3483 | capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); | 3500 | capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); |
3484 | 3501 | ||
3485 | if (ah->opmode != NL80211_IFTYPE_AP && | 3502 | if (ah->opmode != NL80211_IFTYPE_AP && |
3486 | ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { | 3503 | ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { |
3487 | if (ah->regulatory.current_rd == 0x64 || | 3504 | if (regulatory->current_rd == 0x64 || |
3488 | ah->regulatory.current_rd == 0x65) | 3505 | regulatory->current_rd == 0x65) |
3489 | ah->regulatory.current_rd += 5; | 3506 | regulatory->current_rd += 5; |
3490 | else if (ah->regulatory.current_rd == 0x41) | 3507 | else if (regulatory->current_rd == 0x41) |
3491 | ah->regulatory.current_rd = 0x43; | 3508 | regulatory->current_rd = 0x43; |
3492 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, | 3509 | DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, |
3493 | "regdomain mapped to 0x%x\n", ah->regulatory.current_rd); | 3510 | "regdomain mapped to 0x%x\n", regulatory->current_rd); |
3494 | } | 3511 | } |
3495 | 3512 | ||
3496 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); | 3513 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); |
@@ -3625,7 +3642,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3625 | else | 3642 | else |
3626 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; | 3643 | pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; |
3627 | 3644 | ||
3628 | if (ah->regulatory.current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { | 3645 | if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { |
3629 | pCap->reg_cap = | 3646 | pCap->reg_cap = |
3630 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | | 3647 | AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | |
3631 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | | 3648 | AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | |
@@ -3654,6 +3671,7 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
3654 | bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | 3671 | bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, |
3655 | u32 capability, u32 *result) | 3672 | u32 capability, u32 *result) |
3656 | { | 3673 | { |
3674 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
3657 | switch (type) { | 3675 | switch (type) { |
3658 | case ATH9K_CAP_CIPHER: | 3676 | case ATH9K_CAP_CIPHER: |
3659 | switch (capability) { | 3677 | switch (capability) { |
@@ -3702,13 +3720,13 @@ bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, | |||
3702 | case 0: | 3720 | case 0: |
3703 | return 0; | 3721 | return 0; |
3704 | case 1: | 3722 | case 1: |
3705 | *result = ah->regulatory.power_limit; | 3723 | *result = regulatory->power_limit; |
3706 | return 0; | 3724 | return 0; |
3707 | case 2: | 3725 | case 2: |
3708 | *result = ah->regulatory.max_power_level; | 3726 | *result = regulatory->max_power_level; |
3709 | return 0; | 3727 | return 0; |
3710 | case 3: | 3728 | case 3: |
3711 | *result = ah->regulatory.tp_scale; | 3729 | *result = regulatory->tp_scale; |
3712 | return 0; | 3730 | return 0; |
3713 | } | 3731 | } |
3714 | return false; | 3732 | return false; |
@@ -3946,17 +3964,18 @@ bool ath9k_hw_disable(struct ath_hw *ah) | |||
3946 | 3964 | ||
3947 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) | 3965 | void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) |
3948 | { | 3966 | { |
3967 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | ||
3949 | struct ath9k_channel *chan = ah->curchan; | 3968 | struct ath9k_channel *chan = ah->curchan; |
3950 | struct ieee80211_channel *channel = chan->chan; | 3969 | struct ieee80211_channel *channel = chan->chan; |
3951 | 3970 | ||
3952 | ah->regulatory.power_limit = min(limit, (u32) MAX_RATE_POWER); | 3971 | regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); |
3953 | 3972 | ||
3954 | ah->eep_ops->set_txpower(ah, chan, | 3973 | ah->eep_ops->set_txpower(ah, chan, |
3955 | ath9k_regd_get_ctl(&ah->regulatory, chan), | 3974 | ath9k_regd_get_ctl(regulatory, chan), |
3956 | channel->max_antenna_gain * 2, | 3975 | channel->max_antenna_gain * 2, |
3957 | channel->max_power * 2, | 3976 | channel->max_power * 2, |
3958 | min((u32) MAX_RATE_POWER, | 3977 | min((u32) MAX_RATE_POWER, |
3959 | (u32) ah->regulatory.power_limit)); | 3978 | (u32) regulatory->power_limit)); |
3960 | } | 3979 | } |
3961 | 3980 | ||
3962 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) | 3981 | void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0336981a70ec..24b30631d93e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -396,7 +396,6 @@ struct ath_hw { | |||
396 | struct ath9k_hw_version hw_version; | 396 | struct ath9k_hw_version hw_version; |
397 | struct ath9k_ops_config config; | 397 | struct ath9k_ops_config config; |
398 | struct ath9k_hw_capabilities caps; | 398 | struct ath9k_hw_capabilities caps; |
399 | struct ath_regulatory regulatory; | ||
400 | struct ath9k_channel channels[38]; | 399 | struct ath9k_channel channels[38]; |
401 | struct ath9k_channel *curchan; | 400 | struct ath9k_channel *curchan; |
402 | 401 | ||
@@ -522,6 +521,7 @@ struct ath_hw { | |||
522 | u32 originalGain[22]; | 521 | u32 originalGain[22]; |
523 | int initPDADC; | 522 | int initPDADC; |
524 | int PDADCdelta; | 523 | int PDADCdelta; |
524 | u8 led_pin; | ||
525 | 525 | ||
526 | struct ar5416IniArray iniModes; | 526 | struct ar5416IniArray iniModes; |
527 | struct ar5416IniArray iniCommon; | 527 | struct ar5416IniArray iniCommon; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index fa4c6e74f977..9b9b4e8ee1ea 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -384,7 +384,7 @@ static void ath_ani_calibrate(unsigned long data) | |||
384 | if (longcal || shortcal || aniflag) { | 384 | if (longcal || shortcal || aniflag) { |
385 | /* Call ANI routine if necessary */ | 385 | /* Call ANI routine if necessary */ |
386 | if (aniflag) | 386 | if (aniflag) |
387 | ath9k_hw_ani_monitor(ah, &sc->nodestats, ah->curchan); | 387 | ath9k_hw_ani_monitor(ah, ah->curchan); |
388 | 388 | ||
389 | /* Perform calibration if necessary */ | 389 | /* Perform calibration if necessary */ |
390 | if (longcal || shortcal) { | 390 | if (longcal || shortcal) { |
@@ -589,7 +589,7 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
589 | * it will clear whatever condition caused | 589 | * it will clear whatever condition caused |
590 | * the interrupt. | 590 | * the interrupt. |
591 | */ | 591 | */ |
592 | ath9k_hw_procmibevent(ah, &sc->nodestats); | 592 | ath9k_hw_procmibevent(ah); |
593 | ath9k_hw_set_interrupts(ah, sc->imask); | 593 | ath9k_hw_set_interrupts(ah, sc->imask); |
594 | } | 594 | } |
595 | 595 | ||
@@ -940,10 +940,7 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
940 | ath_beacon_config(sc, vif); | 940 | ath_beacon_config(sc, vif); |
941 | 941 | ||
942 | /* Reset rssi stats */ | 942 | /* Reset rssi stats */ |
943 | sc->nodestats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; | 943 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
944 | sc->nodestats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; | ||
945 | sc->nodestats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; | ||
946 | sc->nodestats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; | ||
947 | 944 | ||
948 | ath_start_ani(sc); | 945 | ath_start_ani(sc); |
949 | } else { | 946 | } else { |
@@ -968,9 +965,9 @@ static void ath_led_blink_work(struct work_struct *work) | |||
968 | 965 | ||
969 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || | 966 | if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || |
970 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) | 967 | (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) |
971 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); | 968 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); |
972 | else | 969 | else |
973 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, | 970 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, |
974 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); | 971 | (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); |
975 | 972 | ||
976 | ieee80211_queue_delayed_work(sc->hw, | 973 | ieee80211_queue_delayed_work(sc->hw, |
@@ -1002,7 +999,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev, | |||
1002 | case LED_OFF: | 999 | case LED_OFF: |
1003 | if (led->led_type == ATH_LED_ASSOC || | 1000 | if (led->led_type == ATH_LED_ASSOC || |
1004 | led->led_type == ATH_LED_RADIO) { | 1001 | led->led_type == ATH_LED_RADIO) { |
1005 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, | 1002 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, |
1006 | (led->led_type == ATH_LED_RADIO)); | 1003 | (led->led_type == ATH_LED_RADIO)); |
1007 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; | 1004 | sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; |
1008 | if (led->led_type == ATH_LED_RADIO) | 1005 | if (led->led_type == ATH_LED_RADIO) |
@@ -1017,7 +1014,7 @@ static void ath_led_brightness(struct led_classdev *led_cdev, | |||
1017 | ieee80211_queue_delayed_work(sc->hw, | 1014 | ieee80211_queue_delayed_work(sc->hw, |
1018 | &sc->ath_led_blink_work, 0); | 1015 | &sc->ath_led_blink_work, 0); |
1019 | } else if (led->led_type == ATH_LED_RADIO) { | 1016 | } else if (led->led_type == ATH_LED_RADIO) { |
1020 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 0); | 1017 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); |
1021 | sc->sc_flags |= SC_OP_LED_ON; | 1018 | sc->sc_flags |= SC_OP_LED_ON; |
1022 | } else { | 1019 | } else { |
1023 | sc->led_on_cnt++; | 1020 | sc->led_on_cnt++; |
@@ -1062,7 +1059,7 @@ static void ath_deinit_leds(struct ath_softc *sc) | |||
1062 | ath_unregister_led(&sc->tx_led); | 1059 | ath_unregister_led(&sc->tx_led); |
1063 | ath_unregister_led(&sc->rx_led); | 1060 | ath_unregister_led(&sc->rx_led); |
1064 | ath_unregister_led(&sc->radio_led); | 1061 | ath_unregister_led(&sc->radio_led); |
1065 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | 1062 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
1066 | } | 1063 | } |
1067 | 1064 | ||
1068 | static void ath_init_leds(struct ath_softc *sc) | 1065 | static void ath_init_leds(struct ath_softc *sc) |
@@ -1070,11 +1067,16 @@ static void ath_init_leds(struct ath_softc *sc) | |||
1070 | char *trigger; | 1067 | char *trigger; |
1071 | int ret; | 1068 | int ret; |
1072 | 1069 | ||
1070 | if (AR_SREV_9287(sc->sc_ah)) | ||
1071 | sc->sc_ah->led_pin = ATH_LED_PIN_9287; | ||
1072 | else | ||
1073 | sc->sc_ah->led_pin = ATH_LED_PIN_DEF; | ||
1074 | |||
1073 | /* Configure gpio 1 for output */ | 1075 | /* Configure gpio 1 for output */ |
1074 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, | 1076 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, |
1075 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 1077 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
1076 | /* LED off, active low */ | 1078 | /* LED off, active low */ |
1077 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | 1079 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
1078 | 1080 | ||
1079 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); | 1081 | INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); |
1080 | 1082 | ||
@@ -1153,9 +1155,9 @@ void ath_radio_enable(struct ath_softc *sc) | |||
1153 | ath9k_hw_set_interrupts(ah, sc->imask); | 1155 | ath9k_hw_set_interrupts(ah, sc->imask); |
1154 | 1156 | ||
1155 | /* Enable LED */ | 1157 | /* Enable LED */ |
1156 | ath9k_hw_cfg_output(ah, ATH_LED_PIN, | 1158 | ath9k_hw_cfg_output(ah, ah->led_pin, |
1157 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 1159 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
1158 | ath9k_hw_set_gpio(ah, ATH_LED_PIN, 0); | 1160 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); |
1159 | 1161 | ||
1160 | ieee80211_wake_queues(sc->hw); | 1162 | ieee80211_wake_queues(sc->hw); |
1161 | ath9k_ps_restore(sc); | 1163 | ath9k_ps_restore(sc); |
@@ -1171,8 +1173,8 @@ void ath_radio_disable(struct ath_softc *sc) | |||
1171 | ieee80211_stop_queues(sc->hw); | 1173 | ieee80211_stop_queues(sc->hw); |
1172 | 1174 | ||
1173 | /* Disable LED */ | 1175 | /* Disable LED */ |
1174 | ath9k_hw_set_gpio(ah, ATH_LED_PIN, 1); | 1176 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); |
1175 | ath9k_hw_cfg_gpio_input(ah, ATH_LED_PIN); | 1177 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); |
1176 | 1178 | ||
1177 | /* Disable interrupts */ | 1179 | /* Disable interrupts */ |
1178 | ath9k_hw_set_interrupts(ah, 0); | 1180 | ath9k_hw_set_interrupts(ah, 0); |
@@ -1288,7 +1290,7 @@ static int ath9k_reg_notifier(struct wiphy *wiphy, | |||
1288 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); | 1290 | struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); |
1289 | struct ath_wiphy *aphy = hw->priv; | 1291 | struct ath_wiphy *aphy = hw->priv; |
1290 | struct ath_softc *sc = aphy->sc; | 1292 | struct ath_softc *sc = aphy->sc; |
1291 | struct ath_regulatory *reg = &sc->sc_ah->regulatory; | 1293 | struct ath_regulatory *reg = &sc->common.regulatory; |
1292 | 1294 | ||
1293 | return ath_reg_notifier_apply(wiphy, request, reg); | 1295 | return ath_reg_notifier_apply(wiphy, request, reg); |
1294 | } | 1296 | } |
@@ -1581,12 +1583,12 @@ int ath_init_device(u16 devid, struct ath_softc *sc) | |||
1581 | 1583 | ||
1582 | ath_set_hw_capab(sc, hw); | 1584 | ath_set_hw_capab(sc, hw); |
1583 | 1585 | ||
1584 | error = ath_regd_init(&sc->sc_ah->regulatory, sc->hw->wiphy, | 1586 | error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy, |
1585 | ath9k_reg_notifier); | 1587 | ath9k_reg_notifier); |
1586 | if (error) | 1588 | if (error) |
1587 | return error; | 1589 | return error; |
1588 | 1590 | ||
1589 | reg = &sc->sc_ah->regulatory; | 1591 | reg = &sc->common.regulatory; |
1590 | 1592 | ||
1591 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { | 1593 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { |
1592 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | 1594 | setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); |
@@ -2100,6 +2102,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2100 | struct ath_wiphy *aphy = hw->priv; | 2102 | struct ath_wiphy *aphy = hw->priv; |
2101 | struct ath_softc *sc = aphy->sc; | 2103 | struct ath_softc *sc = aphy->sc; |
2102 | 2104 | ||
2105 | mutex_lock(&sc->mutex); | ||
2106 | |||
2103 | aphy->state = ATH_WIPHY_INACTIVE; | 2107 | aphy->state = ATH_WIPHY_INACTIVE; |
2104 | 2108 | ||
2105 | cancel_delayed_work_sync(&sc->ath_led_blink_work); | 2109 | cancel_delayed_work_sync(&sc->ath_led_blink_work); |
@@ -2112,13 +2116,10 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2112 | 2116 | ||
2113 | if (sc->sc_flags & SC_OP_INVALID) { | 2117 | if (sc->sc_flags & SC_OP_INVALID) { |
2114 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); | 2118 | DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); |
2119 | mutex_unlock(&sc->mutex); | ||
2115 | return; | 2120 | return; |
2116 | } | 2121 | } |
2117 | 2122 | ||
2118 | mutex_lock(&sc->mutex); | ||
2119 | |||
2120 | cancel_delayed_work_sync(&sc->tx_complete_work); | ||
2121 | |||
2122 | if (ath9k_wiphy_started(sc)) { | 2123 | if (ath9k_wiphy_started(sc)) { |
2123 | mutex_unlock(&sc->mutex); | 2124 | mutex_unlock(&sc->mutex); |
2124 | return; /* another wiphy still in use */ | 2125 | return; /* another wiphy still in use */ |
@@ -2389,8 +2390,7 @@ skip_chan_change: | |||
2389 | static void ath9k_configure_filter(struct ieee80211_hw *hw, | 2390 | static void ath9k_configure_filter(struct ieee80211_hw *hw, |
2390 | unsigned int changed_flags, | 2391 | unsigned int changed_flags, |
2391 | unsigned int *total_flags, | 2392 | unsigned int *total_flags, |
2392 | int mc_count, | 2393 | u64 multicast) |
2393 | struct dev_mc_list *mclist) | ||
2394 | { | 2394 | { |
2395 | struct ath_wiphy *aphy = hw->priv; | 2395 | struct ath_wiphy *aphy = hw->priv; |
2396 | struct ath_softc *sc = aphy->sc; | 2396 | struct ath_softc *sc = aphy->sc; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 616bdff2b6a1..685a8cebb468 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -236,7 +236,7 @@ static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) | |||
236 | struct ath_wiphy *aphy = hw->priv; | 236 | struct ath_wiphy *aphy = hw->priv; |
237 | struct ath_softc *sc = aphy->sc; | 237 | struct ath_softc *sc = aphy->sc; |
238 | 238 | ||
239 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | 239 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
240 | 240 | ||
241 | pci_save_state(pdev); | 241 | pci_save_state(pdev); |
242 | pci_disable_device(pdev); | 242 | pci_disable_device(pdev); |
@@ -269,9 +269,9 @@ static int ath_pci_resume(struct pci_dev *pdev) | |||
269 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); | 269 | pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); |
270 | 270 | ||
271 | /* Enable LED */ | 271 | /* Enable LED */ |
272 | ath9k_hw_cfg_output(sc->sc_ah, ATH_LED_PIN, | 272 | ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, |
273 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 273 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
274 | ath9k_hw_set_gpio(sc->sc_ah, ATH_LED_PIN, 1); | 274 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); |
275 | 275 | ||
276 | return 0; | 276 | return 0; |
277 | } | 277 | } |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index e83cd4ab87f0..dfda6f444648 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -490,11 +490,18 @@ bool ath9k_hw_init_rf(struct ath_hw *ah, | |||
490 | #define AR_PHY_TX_PWRCTRL9 0xa27C | 490 | #define AR_PHY_TX_PWRCTRL9 0xa27C |
491 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 | 491 | #define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 |
492 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 | 492 | #define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 |
493 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 | ||
494 | #define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 | ||
493 | 495 | ||
494 | #define AR_PHY_TX_GAIN_TBL1 0xa300 | 496 | #define AR_PHY_TX_GAIN_TBL1 0xa300 |
495 | #define AR_PHY_TX_GAIN 0x0007F000 | 497 | #define AR_PHY_TX_GAIN 0x0007F000 |
496 | #define AR_PHY_TX_GAIN_S 12 | 498 | #define AR_PHY_TX_GAIN_S 12 |
497 | 499 | ||
500 | #define AR_PHY_CH0_TX_PWRCTRL11 0xa398 | ||
501 | #define AR_PHY_CH1_TX_PWRCTRL11 0xb398 | ||
502 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 | ||
503 | #define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 | ||
504 | |||
498 | #define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 | 505 | #define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 |
499 | #define AR_PHY_MASK2_M_31_45 0xa3a4 | 506 | #define AR_PHY_MASK2_M_31_45 0xa3a4 |
500 | #define AR_PHY_MASK2_M_16_30 0xa3a8 | 507 | #define AR_PHY_MASK2_M_16_30 0xa3a8 |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 61dbdd227444..7b62c220d5fd 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -222,7 +222,7 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
222 | 222 | ||
223 | /* Update Beacon RSSI, this is used by ANI. */ | 223 | /* Update Beacon RSSI, this is used by ANI. */ |
224 | if (ieee80211_is_beacon(fc)) | 224 | if (ieee80211_is_beacon(fc)) |
225 | sc->nodestats.ns_avgbrssi = ds->ds_rxstat.rs_rssi; | 225 | sc->sc_ah->stats.avgbrssi = ds->ds_rxstat.rs_rssi; |
226 | 226 | ||
227 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | 227 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); |
228 | rx_status->band = hw->conf.channel->band; | 228 | rx_status->band = hw->conf.channel->band; |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 13fd658b5d33..c9e1ac92d0e9 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -744,6 +744,7 @@ | |||
744 | #define AR_SREV_VERSION_9287 0x180 | 744 | #define AR_SREV_VERSION_9287 0x180 |
745 | #define AR_SREV_REVISION_9287_10 0 | 745 | #define AR_SREV_REVISION_9287_10 0 |
746 | #define AR_SREV_REVISION_9287_11 1 | 746 | #define AR_SREV_REVISION_9287_11 1 |
747 | #define AR_SREV_REVISION_9287_12 2 | ||
747 | #define AR_SREV_VERSION_9271 0x140 | 748 | #define AR_SREV_VERSION_9271 0x140 |
748 | #define AR_SREV_REVISION_9271_10 0 | 749 | #define AR_SREV_REVISION_9271_10 0 |
749 | #define AR_SREV_REVISION_9271_11 1 | 750 | #define AR_SREV_REVISION_9271_11 1 |
@@ -817,7 +818,13 @@ | |||
817 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ | 818 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ |
818 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | 819 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ |
819 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) | 820 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) |
820 | 821 | #define AR_SREV_9287_12(_ah) \ | |
822 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
823 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12)) | ||
824 | #define AR_SREV_9287_12_OR_LATER(_ah) \ | ||
825 | (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ | ||
826 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ | ||
827 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12))) | ||
821 | #define AR_SREV_9271(_ah) \ | 828 | #define AR_SREV_9271(_ah) \ |
822 | (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) | 829 | (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) |
823 | #define AR_SREV_9271_10(_ah) \ | 830 | #define AR_SREV_9271_10(_ah) \ |
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 07291ccb23f2..4d3c53674e5a 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h | |||
@@ -18,9 +18,10 @@ | |||
18 | #define REGD_H | 18 | #define REGD_H |
19 | 19 | ||
20 | #include <linux/nl80211.h> | 20 | #include <linux/nl80211.h> |
21 | |||
22 | #include <net/cfg80211.h> | 21 | #include <net/cfg80211.h> |
23 | 22 | ||
23 | #include "ath.h" | ||
24 | |||
24 | #define NO_CTL 0xff | 25 | #define NO_CTL 0xff |
25 | #define SD_NO_CTL 0xE0 | 26 | #define SD_NO_CTL 0xE0 |
26 | #define NO_CTL 0xff | 27 | #define NO_CTL 0xff |
@@ -47,29 +48,12 @@ | |||
47 | #define CHANNEL_HALF_BW 10 | 48 | #define CHANNEL_HALF_BW 10 |
48 | #define CHANNEL_QUARTER_BW 5 | 49 | #define CHANNEL_QUARTER_BW 5 |
49 | 50 | ||
50 | struct reg_dmn_pair_mapping { | ||
51 | u16 regDmnEnum; | ||
52 | u16 reg_5ghz_ctl; | ||
53 | u16 reg_2ghz_ctl; | ||
54 | }; | ||
55 | |||
56 | struct country_code_to_enum_rd { | 51 | struct country_code_to_enum_rd { |
57 | u16 countryCode; | 52 | u16 countryCode; |
58 | u16 regDmnEnum; | 53 | u16 regDmnEnum; |
59 | const char *isoName; | 54 | const char *isoName; |
60 | }; | 55 | }; |
61 | 56 | ||
62 | struct ath_regulatory { | ||
63 | char alpha2[2]; | ||
64 | u16 country_code; | ||
65 | u16 max_power_level; | ||
66 | u32 tp_scale; | ||
67 | u16 current_rd; | ||
68 | u16 current_rd_ext; | ||
69 | int16_t power_limit; | ||
70 | struct reg_dmn_pair_mapping *regpair; | ||
71 | }; | ||
72 | |||
73 | enum CountryCode { | 57 | enum CountryCode { |
74 | CTRY_ALBANIA = 8, | 58 | CTRY_ALBANIA = 8, |
75 | CTRY_ALGERIA = 12, | 59 | CTRY_ALGERIA = 12, |
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig index 67f564e37225..237b1aadf9b6 100644 --- a/drivers/net/wireless/b43/Kconfig +++ b/drivers/net/wireless/b43/Kconfig | |||
@@ -80,16 +80,16 @@ config B43_NPHY | |||
80 | SAY N. | 80 | SAY N. |
81 | 81 | ||
82 | config B43_PHY_LP | 82 | config B43_PHY_LP |
83 | bool "IEEE 802.11g LP-PHY support (BROKEN)" | 83 | bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)" |
84 | depends on B43 && EXPERIMENTAL && BROKEN | 84 | depends on B43 && EXPERIMENTAL |
85 | ---help--- | 85 | ---help--- |
86 | Support for the LP-PHY. | 86 | Support for the LP-PHY. |
87 | The LP-PHY is an IEEE 802.11g based PHY built into some notebooks | 87 | The LP-PHY is a low-power PHY built into some notebooks |
88 | and embedded devices. | 88 | and embedded devices. It supports 802.11a/g |
89 | 89 | (802.11a support is optional, and currently disabled). | |
90 | THIS IS BROKEN AND DOES NOT WORK YET. | ||
91 | 90 | ||
92 | SAY N. | 91 | This is heavily experimental, and probably will not work for you. |
92 | Say N unless you want to help debug the driver. | ||
93 | 93 | ||
94 | # This config option automatically enables b43 LEDS support, | 94 | # This config option automatically enables b43 LEDS support, |
95 | # if it's possible. | 95 | # if it's possible. |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 41a0e9c2b339..289aaf6dfe79 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1188,7 +1188,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1188 | header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]); | 1188 | header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]); |
1189 | cookie = generate_cookie(ring, slot); | 1189 | cookie = generate_cookie(ring, slot); |
1190 | err = b43_generate_txhdr(ring->dev, header, | 1190 | err = b43_generate_txhdr(ring->dev, header, |
1191 | skb->data, skb->len, info, cookie); | 1191 | skb, info, cookie); |
1192 | if (unlikely(err)) { | 1192 | if (unlikely(err)) { |
1193 | ring->current_slot = old_top_slot; | 1193 | ring->current_slot = old_top_slot; |
1194 | ring->used_slots = old_used_slots; | 1194 | ring->used_slots = old_used_slots; |
diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c index 22d0fbd83a62..976104f634a1 100644 --- a/drivers/net/wireless/b43/lo.c +++ b/drivers/net/wireless/b43/lo.c | |||
@@ -477,7 +477,7 @@ static void lo_measure_setup(struct b43_wldev *dev, | |||
477 | } else | 477 | } else |
478 | b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); | 478 | b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); |
479 | if (phy->rev >= 2) | 479 | if (phy->rev >= 2) |
480 | b43_dummy_transmission(dev); | 480 | b43_dummy_transmission(dev, false, true); |
481 | b43_gphy_channel_switch(dev, 6, 0); | 481 | b43_gphy_channel_switch(dev, 6, 0); |
482 | b43_radio_read16(dev, 0x51); /* dummy read */ | 482 | b43_radio_read16(dev, 0x51); /* dummy read */ |
483 | if (phy->type == B43_PHYTYPE_G) | 483 | if (phy->type == B43_PHYTYPE_G) |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 950beefbeaeb..f5bdf1cae1d1 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -80,6 +80,10 @@ static int modparam_nohwcrypt; | |||
80 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); | 80 | module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); |
81 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); | 81 | MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); |
82 | 82 | ||
83 | static int modparam_hwtkip; | ||
84 | module_param_named(hwtkip, modparam_hwtkip, int, 0444); | ||
85 | MODULE_PARM_DESC(hwtkip, "Enable hardware tkip."); | ||
86 | |||
83 | static int modparam_qos = 1; | 87 | static int modparam_qos = 1; |
84 | module_param_named(qos, modparam_qos, int, 0444); | 88 | module_param_named(qos, modparam_qos, int, 0444); |
85 | MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); | 89 | MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); |
@@ -691,9 +695,9 @@ static void b43_synchronize_irq(struct b43_wldev *dev) | |||
691 | } | 695 | } |
692 | 696 | ||
693 | /* DummyTransmission function, as documented on | 697 | /* DummyTransmission function, as documented on |
694 | * http://bcm-specs.sipsolutions.net/DummyTransmission | 698 | * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission |
695 | */ | 699 | */ |
696 | void b43_dummy_transmission(struct b43_wldev *dev) | 700 | void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) |
697 | { | 701 | { |
698 | struct b43_wl *wl = dev->wl; | 702 | struct b43_wl *wl = dev->wl; |
699 | struct b43_phy *phy = &dev->phy; | 703 | struct b43_phy *phy = &dev->phy; |
@@ -707,19 +711,12 @@ void b43_dummy_transmission(struct b43_wldev *dev) | |||
707 | 0x00000000, | 711 | 0x00000000, |
708 | }; | 712 | }; |
709 | 713 | ||
710 | switch (phy->type) { | 714 | if (ofdm) { |
711 | case B43_PHYTYPE_A: | ||
712 | max_loop = 0x1E; | 715 | max_loop = 0x1E; |
713 | buffer[0] = 0x000201CC; | 716 | buffer[0] = 0x000201CC; |
714 | break; | 717 | } else { |
715 | case B43_PHYTYPE_B: | ||
716 | case B43_PHYTYPE_G: | ||
717 | max_loop = 0xFA; | 718 | max_loop = 0xFA; |
718 | buffer[0] = 0x000B846E; | 719 | buffer[0] = 0x000B846E; |
719 | break; | ||
720 | default: | ||
721 | B43_WARN_ON(1); | ||
722 | return; | ||
723 | } | 720 | } |
724 | 721 | ||
725 | spin_lock_irq(&wl->irq_lock); | 722 | spin_lock_irq(&wl->irq_lock); |
@@ -728,20 +725,35 @@ void b43_dummy_transmission(struct b43_wldev *dev) | |||
728 | for (i = 0; i < 5; i++) | 725 | for (i = 0; i < 5; i++) |
729 | b43_ram_write(dev, i * 4, buffer[i]); | 726 | b43_ram_write(dev, i * 4, buffer[i]); |
730 | 727 | ||
731 | /* Commit writes */ | ||
732 | b43_read32(dev, B43_MMIO_MACCTL); | ||
733 | |||
734 | b43_write16(dev, 0x0568, 0x0000); | 728 | b43_write16(dev, 0x0568, 0x0000); |
735 | b43_write16(dev, 0x07C0, 0x0000); | 729 | if (dev->dev->id.revision < 11) |
736 | value = ((phy->type == B43_PHYTYPE_A) ? 1 : 0); | 730 | b43_write16(dev, 0x07C0, 0x0000); |
731 | else | ||
732 | b43_write16(dev, 0x07C0, 0x0100); | ||
733 | value = (ofdm ? 0x41 : 0x40); | ||
737 | b43_write16(dev, 0x050C, value); | 734 | b43_write16(dev, 0x050C, value); |
735 | if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP)) | ||
736 | b43_write16(dev, 0x0514, 0x1A02); | ||
738 | b43_write16(dev, 0x0508, 0x0000); | 737 | b43_write16(dev, 0x0508, 0x0000); |
739 | b43_write16(dev, 0x050A, 0x0000); | 738 | b43_write16(dev, 0x050A, 0x0000); |
740 | b43_write16(dev, 0x054C, 0x0000); | 739 | b43_write16(dev, 0x054C, 0x0000); |
741 | b43_write16(dev, 0x056A, 0x0014); | 740 | b43_write16(dev, 0x056A, 0x0014); |
742 | b43_write16(dev, 0x0568, 0x0826); | 741 | b43_write16(dev, 0x0568, 0x0826); |
743 | b43_write16(dev, 0x0500, 0x0000); | 742 | b43_write16(dev, 0x0500, 0x0000); |
744 | b43_write16(dev, 0x0502, 0x0030); | 743 | if (!pa_on && (phy->type == B43_PHYTYPE_N)) { |
744 | //SPEC TODO | ||
745 | } | ||
746 | |||
747 | switch (phy->type) { | ||
748 | case B43_PHYTYPE_N: | ||
749 | b43_write16(dev, 0x0502, 0x00D0); | ||
750 | break; | ||
751 | case B43_PHYTYPE_LP: | ||
752 | b43_write16(dev, 0x0502, 0x0050); | ||
753 | break; | ||
754 | default: | ||
755 | b43_write16(dev, 0x0502, 0x0030); | ||
756 | } | ||
745 | 757 | ||
746 | if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) | 758 | if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) |
747 | b43_radio_write16(dev, 0x0051, 0x0017); | 759 | b43_radio_write16(dev, 0x0051, 0x0017); |
@@ -826,6 +838,85 @@ static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) | |||
826 | (index * 2) + 1, addrtmp[1]); | 838 | (index * 2) + 1, addrtmp[1]); |
827 | } | 839 | } |
828 | 840 | ||
841 | /* The ucode will use phase1 key with TEK key to decrypt rx packets. | ||
842 | * When a packet is received, the iv32 is checked. | ||
843 | * - if it doesn't the packet is returned without modification (and software | ||
844 | * decryption can be done). That's what happen when iv16 wrap. | ||
845 | * - if it does, the rc4 key is computed, and decryption is tried. | ||
846 | * Either it will success and B43_RX_MAC_DEC is returned, | ||
847 | * either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned | ||
848 | * and the packet is not usable (it got modified by the ucode). | ||
849 | * So in order to never have B43_RX_MAC_DECERR, we should provide | ||
850 | * a iv32 and phase1key that match. Because we drop packets in case of | ||
851 | * B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all | ||
852 | * packets will be lost without higher layer knowing (ie no resync possible | ||
853 | * until next wrap). | ||
854 | * | ||
855 | * NOTE : this should support 50 key like RCMTA because | ||
856 | * (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50 | ||
857 | */ | ||
858 | static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32, | ||
859 | u16 *phase1key) | ||
860 | { | ||
861 | unsigned int i; | ||
862 | u32 offset; | ||
863 | u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; | ||
864 | |||
865 | if (!modparam_hwtkip) | ||
866 | return; | ||
867 | |||
868 | if (b43_new_kidx_api(dev)) | ||
869 | pairwise_keys_start = B43_NR_GROUP_KEYS; | ||
870 | |||
871 | B43_WARN_ON(index < pairwise_keys_start); | ||
872 | /* We have four default TX keys and possibly four default RX keys. | ||
873 | * Physical mac 0 is mapped to physical key 4 or 8, depending | ||
874 | * on the firmware version. | ||
875 | * So we must adjust the index here. | ||
876 | */ | ||
877 | index -= pairwise_keys_start; | ||
878 | B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS); | ||
879 | |||
880 | if (b43_debug(dev, B43_DBG_KEYS)) { | ||
881 | b43dbg(dev->wl, "rx_tkip_phase1_write : idx 0x%x, iv32 0x%x\n", | ||
882 | index, iv32); | ||
883 | } | ||
884 | /* Write the key to the RX tkip shared mem */ | ||
885 | offset = B43_SHM_SH_TKIPTSCTTAK + index * (10 + 4); | ||
886 | for (i = 0; i < 10; i += 2) { | ||
887 | b43_shm_write16(dev, B43_SHM_SHARED, offset + i, | ||
888 | phase1key ? phase1key[i / 2] : 0); | ||
889 | } | ||
890 | b43_shm_write16(dev, B43_SHM_SHARED, offset + i, iv32); | ||
891 | b43_shm_write16(dev, B43_SHM_SHARED, offset + i + 2, iv32 >> 16); | ||
892 | } | ||
893 | |||
894 | static void b43_op_update_tkip_key(struct ieee80211_hw *hw, | ||
895 | struct ieee80211_key_conf *keyconf, const u8 *addr, | ||
896 | u32 iv32, u16 *phase1key) | ||
897 | { | ||
898 | struct b43_wl *wl = hw_to_b43_wl(hw); | ||
899 | struct b43_wldev *dev; | ||
900 | int index = keyconf->hw_key_idx; | ||
901 | |||
902 | if (B43_WARN_ON(!modparam_hwtkip)) | ||
903 | return; | ||
904 | |||
905 | mutex_lock(&wl->mutex); | ||
906 | |||
907 | dev = wl->current_dev; | ||
908 | if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) | ||
909 | goto out_unlock; | ||
910 | |||
911 | keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ | ||
912 | |||
913 | rx_tkip_phase1_write(dev, index, iv32, phase1key); | ||
914 | keymac_write(dev, index, addr); | ||
915 | |||
916 | out_unlock: | ||
917 | mutex_unlock(&wl->mutex); | ||
918 | } | ||
919 | |||
829 | static void do_key_write(struct b43_wldev *dev, | 920 | static void do_key_write(struct b43_wldev *dev, |
830 | u8 index, u8 algorithm, | 921 | u8 index, u8 algorithm, |
831 | const u8 *key, size_t key_len, const u8 *mac_addr) | 922 | const u8 *key, size_t key_len, const u8 *mac_addr) |
@@ -841,6 +932,19 @@ static void do_key_write(struct b43_wldev *dev, | |||
841 | 932 | ||
842 | if (index >= pairwise_keys_start) | 933 | if (index >= pairwise_keys_start) |
843 | keymac_write(dev, index, NULL); /* First zero out mac. */ | 934 | keymac_write(dev, index, NULL); /* First zero out mac. */ |
935 | if (algorithm == B43_SEC_ALGO_TKIP) { | ||
936 | /* | ||
937 | * We should provide an initial iv32, phase1key pair. | ||
938 | * We could start with iv32=0 and compute the corresponding | ||
939 | * phase1key, but this means calling ieee80211_get_tkip_key | ||
940 | * with a fake skb (or export other tkip function). | ||
941 | * Because we are lazy we hope iv32 won't start with | ||
942 | * 0xffffffff and let's b43_op_update_tkip_key provide a | ||
943 | * correct pair. | ||
944 | */ | ||
945 | rx_tkip_phase1_write(dev, index, 0xffffffff, (u16*)buf); | ||
946 | } else if (index >= pairwise_keys_start) /* clear it */ | ||
947 | rx_tkip_phase1_write(dev, index, 0, NULL); | ||
844 | if (key) | 948 | if (key) |
845 | memcpy(buf, key, key_len); | 949 | memcpy(buf, key, key_len); |
846 | key_write(dev, index, algorithm, buf); | 950 | key_write(dev, index, algorithm, buf); |
@@ -859,6 +963,15 @@ static int b43_key_write(struct b43_wldev *dev, | |||
859 | int i; | 963 | int i; |
860 | int pairwise_keys_start; | 964 | int pairwise_keys_start; |
861 | 965 | ||
966 | /* For ALG_TKIP the key is encoded as a 256-bit (32 byte) data block: | ||
967 | * - Temporal Encryption Key (128 bits) | ||
968 | * - Temporal Authenticator Tx MIC Key (64 bits) | ||
969 | * - Temporal Authenticator Rx MIC Key (64 bits) | ||
970 | * | ||
971 | * Hardware only store TEK | ||
972 | */ | ||
973 | if (algorithm == B43_SEC_ALGO_TKIP && key_len == 32) | ||
974 | key_len = 16; | ||
862 | if (key_len > B43_SEC_KEYSIZE) | 975 | if (key_len > B43_SEC_KEYSIZE) |
863 | return -EINVAL; | 976 | return -EINVAL; |
864 | for (i = 0; i < ARRAY_SIZE(dev->key); i++) { | 977 | for (i = 0; i < ARRAY_SIZE(dev->key); i++) { |
@@ -965,6 +1078,14 @@ static void b43_dump_keymemory(struct b43_wldev *dev) | |||
965 | printk(" Algo: %04X/%02X", algo, key->algorithm); | 1078 | printk(" Algo: %04X/%02X", algo, key->algorithm); |
966 | 1079 | ||
967 | if (index >= pairwise_keys_start) { | 1080 | if (index >= pairwise_keys_start) { |
1081 | if (key->algorithm == B43_SEC_ALGO_TKIP) { | ||
1082 | printk(" TKIP: "); | ||
1083 | offset = B43_SHM_SH_TKIPTSCTTAK + (index - 4) * (10 + 4); | ||
1084 | for (i = 0; i < 14; i += 2) { | ||
1085 | u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i); | ||
1086 | printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF)); | ||
1087 | } | ||
1088 | } | ||
968 | rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, | 1089 | rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, |
969 | ((index - pairwise_keys_start) * 2) + 0); | 1090 | ((index - pairwise_keys_start) * 2) + 0); |
970 | rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, | 1091 | rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, |
@@ -1947,8 +2068,12 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
1947 | filename = "ucode5"; | 2068 | filename = "ucode5"; |
1948 | else if ((rev >= 11) && (rev <= 12)) | 2069 | else if ((rev >= 11) && (rev <= 12)) |
1949 | filename = "ucode11"; | 2070 | filename = "ucode11"; |
1950 | else if (rev >= 13) | 2071 | else if (rev == 13) |
1951 | filename = "ucode13"; | 2072 | filename = "ucode13"; |
2073 | else if (rev == 14) | ||
2074 | filename = "ucode14"; | ||
2075 | else if (rev >= 15) | ||
2076 | filename = "ucode15"; | ||
1952 | else | 2077 | else |
1953 | goto err_no_ucode; | 2078 | goto err_no_ucode; |
1954 | err = b43_do_request_fw(ctx, filename, &fw->ucode); | 2079 | err = b43_do_request_fw(ctx, filename, &fw->ucode); |
@@ -1996,6 +2121,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
1996 | else | 2121 | else |
1997 | goto err_no_initvals; | 2122 | goto err_no_initvals; |
1998 | break; | 2123 | break; |
2124 | case B43_PHYTYPE_LP: | ||
2125 | if (rev == 13) | ||
2126 | filename = "lp0initvals13"; | ||
2127 | else if (rev == 14) | ||
2128 | filename = "lp0initvals14"; | ||
2129 | else if (rev >= 15) | ||
2130 | filename = "lp0initvals15"; | ||
2131 | else | ||
2132 | goto err_no_initvals; | ||
2133 | break; | ||
1999 | default: | 2134 | default: |
2000 | goto err_no_initvals; | 2135 | goto err_no_initvals; |
2001 | } | 2136 | } |
@@ -2030,6 +2165,16 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2030 | else | 2165 | else |
2031 | goto err_no_initvals; | 2166 | goto err_no_initvals; |
2032 | break; | 2167 | break; |
2168 | case B43_PHYTYPE_LP: | ||
2169 | if (rev == 13) | ||
2170 | filename = "lp0bsinitvals13"; | ||
2171 | else if (rev == 14) | ||
2172 | filename = "lp0bsinitvals14"; | ||
2173 | else if (rev >= 15) | ||
2174 | filename = "lp0bsinitvals15"; | ||
2175 | else | ||
2176 | goto err_no_initvals; | ||
2177 | break; | ||
2033 | default: | 2178 | default: |
2034 | goto err_no_initvals; | 2179 | goto err_no_initvals; |
2035 | } | 2180 | } |
@@ -2557,6 +2702,7 @@ static void b43_rate_memory_init(struct b43_wldev *dev) | |||
2557 | case B43_PHYTYPE_A: | 2702 | case B43_PHYTYPE_A: |
2558 | case B43_PHYTYPE_G: | 2703 | case B43_PHYTYPE_G: |
2559 | case B43_PHYTYPE_N: | 2704 | case B43_PHYTYPE_N: |
2705 | case B43_PHYTYPE_LP: | ||
2560 | b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); | 2706 | b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); |
2561 | b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); | 2707 | b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); |
2562 | b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); | 2708 | b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); |
@@ -3587,8 +3733,10 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3587 | 3733 | ||
3588 | switch (cmd) { | 3734 | switch (cmd) { |
3589 | case SET_KEY: | 3735 | case SET_KEY: |
3590 | if (algorithm == B43_SEC_ALGO_TKIP) { | 3736 | if (algorithm == B43_SEC_ALGO_TKIP && |
3591 | /* FIXME: No TKIP hardware encryption for now. */ | 3737 | (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) || |
3738 | !modparam_hwtkip)) { | ||
3739 | /* We support only pairwise key */ | ||
3592 | err = -EOPNOTSUPP; | 3740 | err = -EOPNOTSUPP; |
3593 | goto out_unlock; | 3741 | goto out_unlock; |
3594 | } | 3742 | } |
@@ -3618,6 +3766,8 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3618 | b43_hf_read(dev) & ~B43_HF_USEDEFKEYS); | 3766 | b43_hf_read(dev) & ~B43_HF_USEDEFKEYS); |
3619 | } | 3767 | } |
3620 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 3768 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
3769 | if (algorithm == B43_SEC_ALGO_TKIP) | ||
3770 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | ||
3621 | break; | 3771 | break; |
3622 | case DISABLE_KEY: { | 3772 | case DISABLE_KEY: { |
3623 | err = b43_key_clear(dev, key->hw_key_idx); | 3773 | err = b43_key_clear(dev, key->hw_key_idx); |
@@ -3646,7 +3796,7 @@ out_unlock: | |||
3646 | 3796 | ||
3647 | static void b43_op_configure_filter(struct ieee80211_hw *hw, | 3797 | static void b43_op_configure_filter(struct ieee80211_hw *hw, |
3648 | unsigned int changed, unsigned int *fflags, | 3798 | unsigned int changed, unsigned int *fflags, |
3649 | int mc_count, struct dev_addr_list *mc_list) | 3799 | u64 multicast) |
3650 | { | 3800 | { |
3651 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3801 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3652 | struct b43_wldev *dev = wl->current_dev; | 3802 | struct b43_wldev *dev = wl->current_dev; |
@@ -3785,7 +3935,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
3785 | #endif | 3935 | #endif |
3786 | #ifdef CONFIG_B43_PHY_LP | 3936 | #ifdef CONFIG_B43_PHY_LP |
3787 | case B43_PHYTYPE_LP: | 3937 | case B43_PHYTYPE_LP: |
3788 | if (phy_rev > 1) | 3938 | if (phy_rev > 2) |
3789 | unsupported = 1; | 3939 | unsupported = 1; |
3790 | break; | 3940 | break; |
3791 | #endif | 3941 | #endif |
@@ -3842,7 +3992,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) | |||
3842 | unsupported = 1; | 3992 | unsupported = 1; |
3843 | break; | 3993 | break; |
3844 | case B43_PHYTYPE_LP: | 3994 | case B43_PHYTYPE_LP: |
3845 | if (radio_ver != 0x2062) | 3995 | if (radio_ver != 0x2062 && radio_ver != 0x2063) |
3846 | unsupported = 1; | 3996 | unsupported = 1; |
3847 | break; | 3997 | break; |
3848 | default: | 3998 | default: |
@@ -4345,6 +4495,7 @@ static const struct ieee80211_ops b43_hw_ops = { | |||
4345 | .bss_info_changed = b43_op_bss_info_changed, | 4495 | .bss_info_changed = b43_op_bss_info_changed, |
4346 | .configure_filter = b43_op_configure_filter, | 4496 | .configure_filter = b43_op_configure_filter, |
4347 | .set_key = b43_op_set_key, | 4497 | .set_key = b43_op_set_key, |
4498 | .update_tkip_key = b43_op_update_tkip_key, | ||
4348 | .get_stats = b43_op_get_stats, | 4499 | .get_stats = b43_op_get_stats, |
4349 | .get_tx_stats = b43_op_get_tx_stats, | 4500 | .get_tx_stats = b43_op_get_tx_stats, |
4350 | .get_tsf = b43_op_get_tsf, | 4501 | .get_tsf = b43_op_get_tsf, |
@@ -4480,9 +4631,12 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4480 | case B43_PHYTYPE_A: | 4631 | case B43_PHYTYPE_A: |
4481 | have_5ghz_phy = 1; | 4632 | have_5ghz_phy = 1; |
4482 | break; | 4633 | break; |
4634 | case B43_PHYTYPE_LP: //FIXME not always! | ||
4635 | #if 0 //FIXME enabling 5GHz causes a NULL pointer dereference | ||
4636 | have_5ghz_phy = 1; | ||
4637 | #endif | ||
4483 | case B43_PHYTYPE_G: | 4638 | case B43_PHYTYPE_G: |
4484 | case B43_PHYTYPE_N: | 4639 | case B43_PHYTYPE_N: |
4485 | case B43_PHYTYPE_LP: | ||
4486 | have_2ghz_phy = 1; | 4640 | have_2ghz_phy = 1; |
4487 | break; | 4641 | break; |
4488 | default: | 4642 | default: |
@@ -4497,7 +4651,8 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) | |||
4497 | } | 4651 | } |
4498 | if (1 /* disable A-PHY */) { | 4652 | if (1 /* disable A-PHY */) { |
4499 | /* FIXME: For now we disable the A-PHY on multi-PHY devices. */ | 4653 | /* FIXME: For now we disable the A-PHY on multi-PHY devices. */ |
4500 | if (dev->phy.type != B43_PHYTYPE_N) { | 4654 | if (dev->phy.type != B43_PHYTYPE_N && |
4655 | dev->phy.type != B43_PHYTYPE_LP) { | ||
4501 | have_2ghz_phy = 1; | 4656 | have_2ghz_phy = 1; |
4502 | have_5ghz_phy = 0; | 4657 | have_5ghz_phy = 0; |
4503 | } | 4658 | } |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 950fb1b0546d..0406e06781d4 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -123,7 +123,7 @@ void __b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value | |||
123 | u64 b43_hf_read(struct b43_wldev *dev); | 123 | u64 b43_hf_read(struct b43_wldev *dev); |
124 | void b43_hf_write(struct b43_wldev *dev, u64 value); | 124 | void b43_hf_write(struct b43_wldev *dev, u64 value); |
125 | 125 | ||
126 | void b43_dummy_transmission(struct b43_wldev *dev); | 126 | void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on); |
127 | 127 | ||
128 | void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags); | 128 | void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags); |
129 | 129 | ||
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 5300232449f6..e47131216a67 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c | |||
@@ -333,7 +333,7 @@ static void b43_set_all_gains(struct b43_wldev *dev, | |||
333 | b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp); | 333 | b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp); |
334 | b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp); | 334 | b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp); |
335 | } | 335 | } |
336 | b43_dummy_transmission(dev); | 336 | b43_dummy_transmission(dev, false, true); |
337 | } | 337 | } |
338 | 338 | ||
339 | static void b43_set_original_gains(struct b43_wldev *dev) | 339 | static void b43_set_original_gains(struct b43_wldev *dev) |
@@ -365,7 +365,7 @@ static void b43_set_original_gains(struct b43_wldev *dev) | |||
365 | b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040); | 365 | b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040); |
366 | b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040); | 366 | b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040); |
367 | b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000); | 367 | b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000); |
368 | b43_dummy_transmission(dev); | 368 | b43_dummy_transmission(dev, false, true); |
369 | } | 369 | } |
370 | 370 | ||
371 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ | 371 | /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ |
@@ -1964,7 +1964,7 @@ static void b43_phy_init_pctl(struct b43_wldev *dev) | |||
1964 | } | 1964 | } |
1965 | b43_set_txpower_g(dev, &bbatt, &rfatt, 0); | 1965 | b43_set_txpower_g(dev, &bbatt, &rfatt, 0); |
1966 | } | 1966 | } |
1967 | b43_dummy_transmission(dev); | 1967 | b43_dummy_transmission(dev, false, true); |
1968 | gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); | 1968 | gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); |
1969 | if (B43_DEBUG) { | 1969 | if (B43_DEBUG) { |
1970 | /* Current-Idle-TSSI sanity check. */ | 1970 | /* Current-Idle-TSSI sanity check. */ |
diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c index cfb8337d3859..2d3a5d812c42 100644 --- a/drivers/net/wireless/b43/phy_lp.c +++ b/drivers/net/wireless/b43/phy_lp.c | |||
@@ -29,6 +29,25 @@ | |||
29 | #include "tables_lpphy.h" | 29 | #include "tables_lpphy.h" |
30 | 30 | ||
31 | 31 | ||
32 | static inline u16 channel2freq_lp(u8 channel) | ||
33 | { | ||
34 | if (channel < 14) | ||
35 | return (2407 + 5 * channel); | ||
36 | else if (channel == 14) | ||
37 | return 2484; | ||
38 | else if (channel < 184) | ||
39 | return (5000 + 5 * channel); | ||
40 | else | ||
41 | return (4000 + 5 * channel); | ||
42 | } | ||
43 | |||
44 | static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) | ||
45 | { | ||
46 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
47 | return 1; | ||
48 | return 36; | ||
49 | } | ||
50 | |||
32 | static int b43_lpphy_op_allocate(struct b43_wldev *dev) | 51 | static int b43_lpphy_op_allocate(struct b43_wldev *dev) |
33 | { | 52 | { |
34 | struct b43_phy_lp *lpphy; | 53 | struct b43_phy_lp *lpphy; |
@@ -142,10 +161,9 @@ static void lpphy_read_band_sprom(struct b43_wldev *dev) | |||
142 | } | 161 | } |
143 | } | 162 | } |
144 | 163 | ||
145 | static void lpphy_adjust_gain_table(struct b43_wldev *dev) | 164 | static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq) |
146 | { | 165 | { |
147 | struct b43_phy_lp *lpphy = dev->phy.lp; | 166 | struct b43_phy_lp *lpphy = dev->phy.lp; |
148 | u32 freq = dev->wl->hw->conf.channel->center_freq; | ||
149 | u16 temp[3]; | 167 | u16 temp[3]; |
150 | u16 isolation; | 168 | u16 isolation; |
151 | 169 | ||
@@ -170,6 +188,8 @@ static void lpphy_adjust_gain_table(struct b43_wldev *dev) | |||
170 | 188 | ||
171 | static void lpphy_table_init(struct b43_wldev *dev) | 189 | static void lpphy_table_init(struct b43_wldev *dev) |
172 | { | 190 | { |
191 | u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev)); | ||
192 | |||
173 | if (dev->phy.rev < 2) | 193 | if (dev->phy.rev < 2) |
174 | lpphy_rev0_1_table_init(dev); | 194 | lpphy_rev0_1_table_init(dev); |
175 | else | 195 | else |
@@ -178,14 +198,68 @@ static void lpphy_table_init(struct b43_wldev *dev) | |||
178 | lpphy_init_tx_gain_table(dev); | 198 | lpphy_init_tx_gain_table(dev); |
179 | 199 | ||
180 | if (dev->phy.rev < 2) | 200 | if (dev->phy.rev < 2) |
181 | lpphy_adjust_gain_table(dev); | 201 | lpphy_adjust_gain_table(dev, freq); |
182 | } | 202 | } |
183 | 203 | ||
184 | static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | 204 | static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) |
185 | { | 205 | { |
186 | struct ssb_bus *bus = dev->dev->bus; | 206 | struct ssb_bus *bus = dev->dev->bus; |
207 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
187 | u16 tmp, tmp2; | 208 | u16 tmp, tmp2; |
188 | 209 | ||
210 | b43_phy_mask(dev, B43_LPPHY_AFE_DAC_CTL, 0xF7FF); | ||
211 | b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0); | ||
212 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0); | ||
213 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0); | ||
214 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0); | ||
215 | b43_phy_set(dev, B43_LPPHY_AFE_DAC_CTL, 0x0004); | ||
216 | b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x0078); | ||
217 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800); | ||
218 | b43_phy_write(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x0016); | ||
219 | b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_0, 0xFFF8, 0x0004); | ||
220 | b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5400); | ||
221 | b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2400); | ||
222 | b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100); | ||
223 | b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006); | ||
224 | b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE); | ||
225 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005); | ||
226 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC10, 0x0180); | ||
227 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3800); | ||
228 | b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005); | ||
229 | b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A); | ||
230 | b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3); | ||
231 | b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00); | ||
232 | b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, | ||
233 | 0xFF00, lpphy->rx_pwr_offset); | ||
234 | if ((bus->sprom.boardflags_lo & B43_BFL_FEM) && | ||
235 | ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || | ||
236 | (bus->sprom.boardflags_hi & B43_BFH_PAREF))) { | ||
237 | /* TODO: | ||
238 | * Set the LDO voltage to 0x0028 - FIXME: What is this? | ||
239 | * Call sb_pmu_set_ldo_voltage with 4 and the LDO voltage | ||
240 | * as arguments | ||
241 | * Call sb_pmu_paref_ldo_enable with argument TRUE | ||
242 | */ | ||
243 | if (dev->phy.rev == 0) { | ||
244 | b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, | ||
245 | 0xFFCF, 0x0010); | ||
246 | } | ||
247 | b43_lptab_write(dev, B43_LPTAB16(11, 7), 60); | ||
248 | } else { | ||
249 | //TODO: Call ssb_pmu_paref_ldo_enable with argument FALSE | ||
250 | b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, | ||
251 | 0xFFCF, 0x0020); | ||
252 | b43_lptab_write(dev, B43_LPTAB16(11, 7), 100); | ||
253 | } | ||
254 | tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000; | ||
255 | b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp); | ||
256 | if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV) | ||
257 | b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA); | ||
258 | else | ||
259 | b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA); | ||
260 | b43_lptab_write(dev, B43_LPTAB16(11, 1), 24); | ||
261 | b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL, | ||
262 | 0xFFF9, (lpphy->bx_arch << 1)); | ||
189 | if (dev->phy.rev == 1 && | 263 | if (dev->phy.rev == 1 && |
190 | (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) { | 264 | (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) { |
191 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); | 265 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); |
@@ -235,7 +309,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | |||
235 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006); | 309 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006); |
236 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700); | 310 | b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700); |
237 | } | 311 | } |
238 | if (dev->phy.rev == 1) { | 312 | if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) { |
239 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1); | 313 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1); |
240 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2); | 314 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2); |
241 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3); | 315 | b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3); |
@@ -247,6 +321,7 @@ static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) | |||
247 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); | 321 | b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); |
248 | b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); | 322 | b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); |
249 | b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); | 323 | b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); |
324 | //FIXME the Broadcom driver caches & delays this HF write! | ||
250 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W); | 325 | b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W); |
251 | } | 326 | } |
252 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 327 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
@@ -364,7 +439,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
364 | b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9); | 439 | b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9); |
365 | b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF); | 440 | b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF); |
366 | b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500); | 441 | b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500); |
367 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xF81F, 0xA0); | 442 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0); |
368 | b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300); | 443 | b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300); |
369 | b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); | 444 | b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); |
370 | if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { | 445 | if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { |
@@ -385,7 +460,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
385 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); | 460 | b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); |
386 | b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); | 461 | b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); |
387 | 462 | ||
388 | if ((bus->chip_id == 0x4325) && (bus->chip_rev == 1)) { | 463 | if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { |
389 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); | 464 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); |
390 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); | 465 | b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); |
391 | } | 466 | } |
@@ -396,6 +471,7 @@ static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) | |||
396 | b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6); | 471 | b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6); |
397 | b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00); | 472 | b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00); |
398 | b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1); | 473 | b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1); |
474 | b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF); | ||
399 | } else /* 5GHz */ | 475 | } else /* 5GHz */ |
400 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40); | 476 | b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40); |
401 | 477 | ||
@@ -435,8 +511,9 @@ struct b2062_freqdata { | |||
435 | /* Initialize the 2062 radio. */ | 511 | /* Initialize the 2062 radio. */ |
436 | static void lpphy_2062_init(struct b43_wldev *dev) | 512 | static void lpphy_2062_init(struct b43_wldev *dev) |
437 | { | 513 | { |
514 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
438 | struct ssb_bus *bus = dev->dev->bus; | 515 | struct ssb_bus *bus = dev->dev->bus; |
439 | u32 crystalfreq, pdiv, tmp, ref; | 516 | u32 crystalfreq, tmp, ref; |
440 | unsigned int i; | 517 | unsigned int i; |
441 | const struct b2062_freqdata *fd = NULL; | 518 | const struct b2062_freqdata *fd = NULL; |
442 | 519 | ||
@@ -460,10 +537,15 @@ static void lpphy_2062_init(struct b43_wldev *dev) | |||
460 | b43_radio_write(dev, B2062_N_TX_CTL3, 0); | 537 | b43_radio_write(dev, B2062_N_TX_CTL3, 0); |
461 | b43_radio_write(dev, B2062_N_TX_CTL4, 0); | 538 | b43_radio_write(dev, B2062_N_TX_CTL4, 0); |
462 | b43_radio_write(dev, B2062_N_TX_CTL5, 0); | 539 | b43_radio_write(dev, B2062_N_TX_CTL5, 0); |
540 | b43_radio_write(dev, B2062_N_TX_CTL6, 0); | ||
463 | b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40); | 541 | b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40); |
464 | b43_radio_write(dev, B2062_N_PDN_CTL0, 0); | 542 | b43_radio_write(dev, B2062_N_PDN_CTL0, 0); |
465 | b43_radio_write(dev, B2062_N_CALIB_TS, 0x10); | 543 | b43_radio_write(dev, B2062_N_CALIB_TS, 0x10); |
466 | b43_radio_write(dev, B2062_N_CALIB_TS, 0); | 544 | b43_radio_write(dev, B2062_N_CALIB_TS, 0); |
545 | if (dev->phy.rev > 0) { | ||
546 | b43_radio_write(dev, B2062_S_BG_CTL1, | ||
547 | (b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80); | ||
548 | } | ||
467 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 549 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) |
468 | b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1); | 550 | b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1); |
469 | else | 551 | else |
@@ -475,23 +557,27 @@ static void lpphy_2062_init(struct b43_wldev *dev) | |||
475 | B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)); | 557 | B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)); |
476 | B43_WARN_ON(crystalfreq == 0); | 558 | B43_WARN_ON(crystalfreq == 0); |
477 | 559 | ||
478 | if (crystalfreq >= 30000000) { | 560 | if (crystalfreq <= 30000000) { |
479 | pdiv = 1; | 561 | lpphy->pdiv = 1; |
480 | b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); | 562 | b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); |
481 | } else { | 563 | } else { |
482 | pdiv = 2; | 564 | lpphy->pdiv = 2; |
483 | b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); | 565 | b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); |
484 | } | 566 | } |
485 | 567 | ||
486 | tmp = (800000000 * pdiv + crystalfreq) / (32000000 * pdiv); | 568 | tmp = (((800000000 * lpphy->pdiv + crystalfreq) / |
487 | tmp = (tmp - 1) & 0xFF; | 569 | (2 * crystalfreq)) - 8) & 0xFF; |
570 | b43_radio_write(dev, B2062_S_RFPLL_CTL7, tmp); | ||
571 | |||
572 | tmp = (((100 * crystalfreq + 16000000 * lpphy->pdiv) / | ||
573 | (32000000 * lpphy->pdiv)) - 1) & 0xFF; | ||
488 | b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); | 574 | b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); |
489 | 575 | ||
490 | tmp = (2 * crystalfreq + 1000000 * pdiv) / (2000000 * pdiv); | 576 | tmp = (((2 * crystalfreq + 1000000 * lpphy->pdiv) / |
491 | tmp = ((tmp & 0xFF) - 1) & 0xFFFF; | 577 | (2000000 * lpphy->pdiv)) - 1) & 0xFF; |
492 | b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); | 578 | b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); |
493 | 579 | ||
494 | ref = (1000 * pdiv + 2 * crystalfreq) / (2000 * pdiv); | 580 | ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv); |
495 | ref &= 0xFFFF; | 581 | ref &= 0xFFFF; |
496 | for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { | 582 | for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { |
497 | if (ref < freqdata_tab[i].freq) { | 583 | if (ref < freqdata_tab[i].freq) { |
@@ -523,9 +609,14 @@ static void lpphy_2063_init(struct b43_wldev *dev) | |||
523 | b43_radio_write(dev, B2063_PA_SP7, 0); | 609 | b43_radio_write(dev, B2063_PA_SP7, 0); |
524 | b43_radio_write(dev, B2063_TX_RF_SP6, 0x20); | 610 | b43_radio_write(dev, B2063_TX_RF_SP6, 0x20); |
525 | b43_radio_write(dev, B2063_TX_RF_SP9, 0x40); | 611 | b43_radio_write(dev, B2063_TX_RF_SP9, 0x40); |
526 | b43_radio_write(dev, B2063_PA_SP3, 0xa0); | 612 | if (dev->phy.rev == 2) { |
527 | b43_radio_write(dev, B2063_PA_SP4, 0xa0); | 613 | b43_radio_write(dev, B2063_PA_SP3, 0xa0); |
528 | b43_radio_write(dev, B2063_PA_SP2, 0x18); | 614 | b43_radio_write(dev, B2063_PA_SP4, 0xa0); |
615 | b43_radio_write(dev, B2063_PA_SP2, 0x18); | ||
616 | } else { | ||
617 | b43_radio_write(dev, B2063_PA_SP3, 0x20); | ||
618 | b43_radio_write(dev, B2063_PA_SP2, 0x20); | ||
619 | } | ||
529 | } | 620 | } |
530 | 621 | ||
531 | struct lpphy_stx_table_entry { | 622 | struct lpphy_stx_table_entry { |
@@ -592,7 +683,7 @@ static void lpphy_radio_init(struct b43_wldev *dev) | |||
592 | b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD); | 683 | b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD); |
593 | udelay(1); | 684 | udelay(1); |
594 | 685 | ||
595 | if (dev->phy.rev < 2) { | 686 | if (dev->phy.radio_ver == 0x2062) { |
596 | lpphy_2062_init(dev); | 687 | lpphy_2062_init(dev); |
597 | } else { | 688 | } else { |
598 | lpphy_2063_init(dev); | 689 | lpphy_2063_init(dev); |
@@ -609,11 +700,18 @@ struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; }; | |||
609 | 700 | ||
610 | static void lpphy_set_rc_cap(struct b43_wldev *dev) | 701 | static void lpphy_set_rc_cap(struct b43_wldev *dev) |
611 | { | 702 | { |
612 | u8 rc_cap = dev->phy.lp->rc_cap; | 703 | struct b43_phy_lp *lpphy = dev->phy.lp; |
704 | |||
705 | u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1; | ||
706 | |||
707 | if (dev->phy.rev == 1) //FIXME check channel 14! | ||
708 | rc_cap = max_t(u8, rc_cap + 5, 15); | ||
613 | 709 | ||
614 | b43_radio_write(dev, B2062_N_RXBB_CALIB2, max_t(u8, rc_cap-4, 0x80)); | 710 | b43_radio_write(dev, B2062_N_RXBB_CALIB2, |
615 | b43_radio_write(dev, B2062_N_TX_CTL_A, ((rc_cap & 0x1F) >> 1) | 0x80); | 711 | max_t(u8, lpphy->rc_cap - 4, 0x80)); |
616 | b43_radio_write(dev, B2062_S_RXG_CNT16, ((rc_cap & 0x1F) >> 2) | 0x80); | 712 | b43_radio_write(dev, B2062_N_TX_CTL_A, rc_cap | 0x80); |
713 | b43_radio_write(dev, B2062_S_RXG_CNT16, | ||
714 | ((lpphy->rc_cap & 0x1F) >> 2) | 0x80); | ||
617 | } | 715 | } |
618 | 716 | ||
619 | static u8 lpphy_get_bb_mult(struct b43_wldev *dev) | 717 | static u8 lpphy_get_bb_mult(struct b43_wldev *dev) |
@@ -626,9 +724,39 @@ static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult) | |||
626 | b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8); | 724 | b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8); |
627 | } | 725 | } |
628 | 726 | ||
629 | static void lpphy_disable_crs(struct b43_wldev *dev) | 727 | static void lpphy_set_deaf(struct b43_wldev *dev, bool user) |
630 | { | 728 | { |
729 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
730 | |||
731 | if (user) | ||
732 | lpphy->crs_usr_disable = 1; | ||
733 | else | ||
734 | lpphy->crs_sys_disable = 1; | ||
631 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80); | 735 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80); |
736 | } | ||
737 | |||
738 | static void lpphy_clear_deaf(struct b43_wldev *dev, bool user) | ||
739 | { | ||
740 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
741 | |||
742 | if (user) | ||
743 | lpphy->crs_usr_disable = 0; | ||
744 | else | ||
745 | lpphy->crs_sys_disable = 0; | ||
746 | |||
747 | if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) { | ||
748 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | ||
749 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, | ||
750 | 0xFF1F, 0x60); | ||
751 | else | ||
752 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, | ||
753 | 0xFF1F, 0x20); | ||
754 | } | ||
755 | } | ||
756 | |||
757 | static void lpphy_disable_crs(struct b43_wldev *dev, bool user) | ||
758 | { | ||
759 | lpphy_set_deaf(dev, user); | ||
632 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1); | 760 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1); |
633 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); | 761 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); |
634 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); | 762 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); |
@@ -656,12 +784,9 @@ static void lpphy_disable_crs(struct b43_wldev *dev) | |||
656 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF); | 784 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF); |
657 | } | 785 | } |
658 | 786 | ||
659 | static void lpphy_restore_crs(struct b43_wldev *dev) | 787 | static void lpphy_restore_crs(struct b43_wldev *dev, bool user) |
660 | { | 788 | { |
661 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 789 | lpphy_clear_deaf(dev, user); |
662 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x60); | ||
663 | else | ||
664 | b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x20); | ||
665 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80); | 790 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80); |
666 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00); | 791 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00); |
667 | } | 792 | } |
@@ -707,10 +832,11 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev, | |||
707 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | 832 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, |
708 | 0xF800, rf_gain); | 833 | 0xF800, rf_gain); |
709 | } else { | 834 | } else { |
710 | pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F00; | 835 | pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0; |
836 | pa_gain <<= 2; | ||
711 | b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | 837 | b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, |
712 | (gains.pga << 8) | gains.gm); | 838 | (gains.pga << 8) | gains.gm); |
713 | b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, | 839 | b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), |
714 | 0x8000, gains.pad | pa_gain); | 840 | 0x8000, gains.pad | pa_gain); |
715 | b43_phy_write(dev, B43_PHY_OFDM(0xFC), | 841 | b43_phy_write(dev, B43_PHY_OFDM(0xFC), |
716 | (gains.pga << 8) | gains.gm); | 842 | (gains.pga << 8) | gains.gm); |
@@ -724,7 +850,7 @@ static void lpphy_set_tx_gains(struct b43_wldev *dev, | |||
724 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7); | 850 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7); |
725 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14); | 851 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14); |
726 | } | 852 | } |
727 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFBF, 1 << 4); | 853 | b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6); |
728 | } | 854 | } |
729 | 855 | ||
730 | static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) | 856 | static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) |
@@ -764,33 +890,33 @@ static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) | |||
764 | } | 890 | } |
765 | } | 891 | } |
766 | 892 | ||
767 | static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) | 893 | static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) |
768 | { | 894 | { |
769 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); | 895 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); |
770 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); | 896 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); |
771 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); | 897 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); |
772 | if (dev->phy.rev >= 2) { | 898 | if (dev->phy.rev >= 2) { |
773 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); | 899 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); |
774 | if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) | 900 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
775 | return; | 901 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); |
776 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); | 902 | b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7); |
777 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFF7); | 903 | } |
778 | } else { | 904 | } else { |
779 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); | 905 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); |
780 | } | 906 | } |
781 | } | 907 | } |
782 | 908 | ||
783 | static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) | 909 | static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) |
784 | { | 910 | { |
785 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); | 911 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); |
786 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); | 912 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); |
787 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); | 913 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); |
788 | if (dev->phy.rev >= 2) { | 914 | if (dev->phy.rev >= 2) { |
789 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); | 915 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); |
790 | if (b43_current_band(dev->wl) != IEEE80211_BAND_2GHZ) | 916 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { |
791 | return; | 917 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); |
792 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); | 918 | b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8); |
793 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x8); | 919 | } |
794 | } else { | 920 | } else { |
795 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); | 921 | b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); |
796 | } | 922 | } |
@@ -909,26 +1035,22 @@ static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) | |||
909 | { | 1035 | { |
910 | u32 quotient, remainder, rbit, roundup, tmp; | 1036 | u32 quotient, remainder, rbit, roundup, tmp; |
911 | 1037 | ||
912 | if (divisor == 0) { | 1038 | if (divisor == 0) |
913 | quotient = 0; | 1039 | return 0; |
914 | remainder = 0; | 1040 | |
915 | } else { | 1041 | quotient = dividend / divisor; |
916 | quotient = dividend / divisor; | 1042 | remainder = dividend % divisor; |
917 | remainder = dividend % divisor; | ||
918 | } | ||
919 | 1043 | ||
920 | rbit = divisor & 0x1; | 1044 | rbit = divisor & 0x1; |
921 | roundup = (divisor >> 1) + rbit; | 1045 | roundup = (divisor >> 1) + rbit; |
922 | precision--; | ||
923 | 1046 | ||
924 | while (precision != 0xFF) { | 1047 | while (precision != 0) { |
925 | tmp = remainder - roundup; | 1048 | tmp = remainder - roundup; |
926 | quotient <<= 1; | 1049 | quotient <<= 1; |
927 | remainder <<= 1; | 1050 | if (remainder >= roundup) |
928 | if (remainder >= roundup) { | ||
929 | remainder = (tmp << 1) + rbit; | 1051 | remainder = (tmp << 1) + rbit; |
930 | quotient--; | 1052 | else |
931 | } | 1053 | remainder <<= 1; |
932 | precision--; | 1054 | precision--; |
933 | } | 1055 | } |
934 | 1056 | ||
@@ -992,9 +1114,9 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, | |||
992 | struct b43_phy_lp *lpphy = dev->phy.lp; | 1114 | struct b43_phy_lp *lpphy = dev->phy.lp; |
993 | enum b43_lpphy_txpctl_mode oldmode; | 1115 | enum b43_lpphy_txpctl_mode oldmode; |
994 | 1116 | ||
995 | oldmode = lpphy->txpctl_mode; | ||
996 | lpphy_read_tx_pctl_mode_from_hardware(dev); | 1117 | lpphy_read_tx_pctl_mode_from_hardware(dev); |
997 | if (lpphy->txpctl_mode == mode) | 1118 | oldmode = lpphy->txpctl_mode; |
1119 | if (oldmode == mode) | ||
998 | return; | 1120 | return; |
999 | lpphy->txpctl_mode = mode; | 1121 | lpphy->txpctl_mode = mode; |
1000 | 1122 | ||
@@ -1022,28 +1144,37 @@ static void lpphy_set_tx_power_control(struct b43_wldev *dev, | |||
1022 | lpphy_write_tx_pctl_mode_to_hardware(dev); | 1144 | lpphy_write_tx_pctl_mode_to_hardware(dev); |
1023 | } | 1145 | } |
1024 | 1146 | ||
1147 | static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, | ||
1148 | unsigned int new_channel); | ||
1149 | |||
1025 | static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | 1150 | static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) |
1026 | { | 1151 | { |
1027 | struct b43_phy_lp *lpphy = dev->phy.lp; | 1152 | struct b43_phy_lp *lpphy = dev->phy.lp; |
1028 | struct lpphy_iq_est iq_est; | 1153 | struct lpphy_iq_est iq_est; |
1029 | struct lpphy_tx_gains tx_gains; | 1154 | struct lpphy_tx_gains tx_gains; |
1030 | static const u32 ideal_pwr_table[22] = { | 1155 | static const u32 ideal_pwr_table[21] = { |
1031 | 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64, | 1156 | 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64, |
1032 | 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35, | 1157 | 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35, |
1033 | 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088, | 1158 | 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088, |
1034 | 0x0004c, 0x0002c, 0x0001a, 0xc0006, | 1159 | 0x0004c, 0x0002c, 0x0001a, |
1035 | }; | 1160 | }; |
1036 | bool old_txg_ovr; | 1161 | bool old_txg_ovr; |
1037 | u8 old_bbmult; | 1162 | u8 old_bbmult; |
1038 | u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval, | 1163 | u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval, |
1039 | old_rf2_ovr, old_rf2_ovrval, old_phy_ctl, old_txpctl; | 1164 | old_rf2_ovr, old_rf2_ovrval, old_phy_ctl; |
1165 | enum b43_lpphy_txpctl_mode old_txpctl; | ||
1040 | u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; | 1166 | u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; |
1041 | int loopback, i, j, inner_sum; | 1167 | int loopback, i, j, inner_sum, err; |
1042 | 1168 | ||
1043 | memset(&iq_est, 0, sizeof(iq_est)); | 1169 | memset(&iq_est, 0, sizeof(iq_est)); |
1044 | 1170 | ||
1045 | b43_switch_channel(dev, 7); | 1171 | err = b43_lpphy_op_switch_channel(dev, 7); |
1046 | old_txg_ovr = (b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) >> 6) & 1; | 1172 | if (err) { |
1173 | b43dbg(dev->wl, | ||
1174 | "RC calib: Failed to switch to channel 7, error = %d", | ||
1175 | err); | ||
1176 | } | ||
1177 | old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40); | ||
1047 | old_bbmult = lpphy_get_bb_mult(dev); | 1178 | old_bbmult = lpphy_get_bb_mult(dev); |
1048 | if (old_txg_ovr) | 1179 | if (old_txg_ovr) |
1049 | tx_gains = lpphy_get_tx_gains(dev); | 1180 | tx_gains = lpphy_get_tx_gains(dev); |
@@ -1054,11 +1185,11 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | |||
1054 | old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2); | 1185 | old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2); |
1055 | old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL); | 1186 | old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL); |
1056 | old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL); | 1187 | old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL); |
1057 | old_txpctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD) & | 1188 | lpphy_read_tx_pctl_mode_from_hardware(dev); |
1058 | B43_LPPHY_TX_PWR_CTL_CMD_MODE; | 1189 | old_txpctl = lpphy->txpctl_mode; |
1059 | 1190 | ||
1060 | lpphy_set_tx_power_control(dev, B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); | 1191 | lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); |
1061 | lpphy_disable_crs(dev); | 1192 | lpphy_disable_crs(dev, true); |
1062 | loopback = lpphy_loopback(dev); | 1193 | loopback = lpphy_loopback(dev); |
1063 | if (loopback == -1) | 1194 | if (loopback == -1) |
1064 | goto finish; | 1195 | goto finish; |
@@ -1091,7 +1222,7 @@ static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) | |||
1091 | lpphy_stop_ddfs(dev); | 1222 | lpphy_stop_ddfs(dev); |
1092 | 1223 | ||
1093 | finish: | 1224 | finish: |
1094 | lpphy_restore_crs(dev); | 1225 | lpphy_restore_crs(dev, true); |
1095 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval); | 1226 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval); |
1096 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr); | 1227 | b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr); |
1097 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval); | 1228 | b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval); |
@@ -1257,33 +1388,110 @@ static void lpphy_calibration(struct b43_wldev *dev) | |||
1257 | b43_mac_enable(dev); | 1388 | b43_mac_enable(dev); |
1258 | } | 1389 | } |
1259 | 1390 | ||
1260 | /* Initialize TX power control */ | 1391 | static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode) |
1261 | static void lpphy_tx_pctl_init(struct b43_wldev *dev) | ||
1262 | { | 1392 | { |
1263 | if (0/*FIXME HWPCTL capable */) { | 1393 | if (mode != TSSI_MUX_EXT) { |
1264 | //TODO | 1394 | b43_radio_set(dev, B2063_PA_SP1, 0x2); |
1265 | } else { /* This device is only software TX power control capable. */ | 1395 | b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000); |
1266 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | 1396 | b43_radio_write(dev, B2063_PA_CTL10, 0x51); |
1267 | //TODO | 1397 | if (mode == TSSI_MUX_POSTPA) { |
1398 | b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE); | ||
1399 | b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7); | ||
1268 | } else { | 1400 | } else { |
1269 | //TODO | 1401 | b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1); |
1402 | b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL, | ||
1403 | 0xFFC7, 0x20); | ||
1270 | } | 1404 | } |
1271 | //TODO set BB multiplier to 0x0096 | 1405 | } else { |
1406 | B43_WARN_ON(1); | ||
1272 | } | 1407 | } |
1273 | } | 1408 | } |
1274 | 1409 | ||
1275 | static int b43_lpphy_op_init(struct b43_wldev *dev) | 1410 | static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev) |
1276 | { | 1411 | { |
1277 | lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? | 1412 | u16 tmp; |
1278 | lpphy_baseband_init(dev); | 1413 | int i; |
1279 | lpphy_radio_init(dev); | ||
1280 | lpphy_calibrate_rc(dev); | ||
1281 | //TODO set channel | ||
1282 | lpphy_tx_pctl_init(dev); | ||
1283 | lpphy_calibration(dev); | ||
1284 | //TODO ACI init | ||
1285 | 1414 | ||
1286 | return 0; | 1415 | //SPEC TODO Call LP PHY Clear TX Power offsets |
1416 | for (i = 0; i < 64; i++) { | ||
1417 | if (dev->phy.rev >= 2) | ||
1418 | b43_lptab_write(dev, B43_LPTAB32(7, i + 1), i); | ||
1419 | else | ||
1420 | b43_lptab_write(dev, B43_LPTAB32(10, i + 1), i); | ||
1421 | } | ||
1422 | |||
1423 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF); | ||
1424 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000); | ||
1425 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F); | ||
1426 | if (dev->phy.rev < 2) { | ||
1427 | b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF); | ||
1428 | b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000); | ||
1429 | } else { | ||
1430 | b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE); | ||
1431 | b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4); | ||
1432 | b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10); | ||
1433 | b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1); | ||
1434 | lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA); | ||
1435 | } | ||
1436 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000); | ||
1437 | b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF); | ||
1438 | b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA); | ||
1439 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, | ||
1440 | (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, | ||
1441 | B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); | ||
1442 | b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF); | ||
1443 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, | ||
1444 | (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, | ||
1445 | B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW); | ||
1446 | |||
1447 | if (dev->phy.rev < 2) { | ||
1448 | b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000); | ||
1449 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF); | ||
1450 | } else { | ||
1451 | lpphy_set_tx_power_by_index(dev, 0x7F); | ||
1452 | } | ||
1453 | |||
1454 | b43_dummy_transmission(dev, true, true); | ||
1455 | |||
1456 | tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT); | ||
1457 | if (tmp & 0x8000) { | ||
1458 | b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, | ||
1459 | 0xFFC0, (tmp & 0xFF) - 32); | ||
1460 | } | ||
1461 | |||
1462 | b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF); | ||
1463 | |||
1464 | // (SPEC?) TODO Set "Target TX frequency" variable to 0 | ||
1465 | // SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8! | ||
1466 | } | ||
1467 | |||
1468 | static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev) | ||
1469 | { | ||
1470 | struct lpphy_tx_gains gains; | ||
1471 | |||
1472 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { | ||
1473 | gains.gm = 4; | ||
1474 | gains.pad = 12; | ||
1475 | gains.pga = 12; | ||
1476 | gains.dac = 0; | ||
1477 | } else { | ||
1478 | gains.gm = 7; | ||
1479 | gains.pad = 14; | ||
1480 | gains.pga = 15; | ||
1481 | gains.dac = 0; | ||
1482 | } | ||
1483 | lpphy_set_tx_gains(dev, gains); | ||
1484 | lpphy_set_bb_mult(dev, 150); | ||
1485 | } | ||
1486 | |||
1487 | /* Initialize TX power control */ | ||
1488 | static void lpphy_tx_pctl_init(struct b43_wldev *dev) | ||
1489 | { | ||
1490 | if (0/*FIXME HWPCTL capable */) { | ||
1491 | lpphy_tx_pctl_init_hw(dev); | ||
1492 | } else { /* This device is only software TX power control capable. */ | ||
1493 | lpphy_tx_pctl_init_sw(dev); | ||
1494 | } | ||
1287 | } | 1495 | } |
1288 | 1496 | ||
1289 | static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) | 1497 | static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) |
@@ -1328,18 +1536,668 @@ static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, | |||
1328 | //TODO | 1536 | //TODO |
1329 | } | 1537 | } |
1330 | 1538 | ||
1539 | struct b206x_channel { | ||
1540 | u8 channel; | ||
1541 | u16 freq; | ||
1542 | u8 data[12]; | ||
1543 | }; | ||
1544 | |||
1545 | static const struct b206x_channel b2062_chantbl[] = { | ||
1546 | { .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1547 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1548 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1549 | { .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1550 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1551 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1552 | { .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1553 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1554 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1555 | { .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1556 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1557 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1558 | { .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1559 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1560 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1561 | { .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1562 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1563 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1564 | { .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1565 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1566 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1567 | { .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1568 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1569 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1570 | { .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1571 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1572 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1573 | { .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1574 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1575 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1576 | { .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1577 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1578 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1579 | { .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1580 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1581 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1582 | { .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1583 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1584 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1585 | { .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF, | ||
1586 | .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, | ||
1587 | .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, | ||
1588 | { .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22, | ||
1589 | .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, | ||
1590 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1591 | { .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11, | ||
1592 | .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1593 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1594 | { .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11, | ||
1595 | .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1596 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1597 | { .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00, | ||
1598 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1599 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1600 | { .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11, | ||
1601 | .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1602 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1603 | { .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11, | ||
1604 | .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, | ||
1605 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1606 | { .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11, | ||
1607 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1608 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1609 | { .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00, | ||
1610 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1611 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1612 | { .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00, | ||
1613 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1614 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1615 | { .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00, | ||
1616 | .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, | ||
1617 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1618 | { .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00, | ||
1619 | .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77, | ||
1620 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1621 | { .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00, | ||
1622 | .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77, | ||
1623 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1624 | { .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00, | ||
1625 | .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77, | ||
1626 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1627 | { .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00, | ||
1628 | .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, | ||
1629 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1630 | { .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00, | ||
1631 | .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, | ||
1632 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1633 | { .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00, | ||
1634 | .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, | ||
1635 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1636 | { .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00, | ||
1637 | .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77, | ||
1638 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1639 | { .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00, | ||
1640 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1641 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1642 | { .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00, | ||
1643 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1644 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1645 | { .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00, | ||
1646 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1647 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1648 | { .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00, | ||
1649 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1650 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1651 | { .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00, | ||
1652 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1653 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1654 | { .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00, | ||
1655 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1656 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1657 | { .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00, | ||
1658 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1659 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1660 | { .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00, | ||
1661 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1662 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1663 | { .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00, | ||
1664 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1665 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1666 | { .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00, | ||
1667 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1668 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1669 | { .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00, | ||
1670 | .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, | ||
1671 | .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1672 | { .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77, | ||
1673 | .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1674 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1675 | { .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77, | ||
1676 | .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1677 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1678 | { .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66, | ||
1679 | .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1680 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1681 | { .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66, | ||
1682 | .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1683 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1684 | { .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55, | ||
1685 | .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1686 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1687 | { .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55, | ||
1688 | .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1689 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1690 | { .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44, | ||
1691 | .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, | ||
1692 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, | ||
1693 | { .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44, | ||
1694 | .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77, | ||
1695 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1696 | { .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44, | ||
1697 | .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77, | ||
1698 | .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, | ||
1699 | }; | ||
1700 | |||
1701 | static const struct b206x_channel b2063_chantbl[] = { | ||
1702 | { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C, | ||
1703 | .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1704 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1705 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1706 | { .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C, | ||
1707 | .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1708 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1709 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1710 | { .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C, | ||
1711 | .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1712 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1713 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1714 | { .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C, | ||
1715 | .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1716 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1717 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1718 | { .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C, | ||
1719 | .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1720 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1721 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1722 | { .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C, | ||
1723 | .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1724 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1725 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1726 | { .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C, | ||
1727 | .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1728 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1729 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1730 | { .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C, | ||
1731 | .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1732 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1733 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1734 | { .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C, | ||
1735 | .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1736 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1737 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1738 | { .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C, | ||
1739 | .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1740 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1741 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1742 | { .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C, | ||
1743 | .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1744 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1745 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1746 | { .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C, | ||
1747 | .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1748 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1749 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1750 | { .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C, | ||
1751 | .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1752 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1753 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1754 | { .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C, | ||
1755 | .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, | ||
1756 | .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, | ||
1757 | .data[10] = 0x80, .data[11] = 0x70, }, | ||
1758 | { .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C, | ||
1759 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05, | ||
1760 | .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80, | ||
1761 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1762 | { .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C, | ||
1763 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05, | ||
1764 | .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80, | ||
1765 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1766 | { .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C, | ||
1767 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, | ||
1768 | .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80, | ||
1769 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1770 | { .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C, | ||
1771 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, | ||
1772 | .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70, | ||
1773 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1774 | { .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C, | ||
1775 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, | ||
1776 | .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70, | ||
1777 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1778 | { .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C, | ||
1779 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04, | ||
1780 | .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60, | ||
1781 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1782 | { .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C, | ||
1783 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03, | ||
1784 | .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60, | ||
1785 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1786 | { .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C, | ||
1787 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03, | ||
1788 | .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60, | ||
1789 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1790 | { .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C, | ||
1791 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02, | ||
1792 | .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60, | ||
1793 | .data[10] = 0x20, .data[11] = 0x00, }, | ||
1794 | { .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C, | ||
1795 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01, | ||
1796 | .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, | ||
1797 | .data[10] = 0x10, .data[11] = 0x00, }, | ||
1798 | { .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C, | ||
1799 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01, | ||
1800 | .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, | ||
1801 | .data[10] = 0x10, .data[11] = 0x00, }, | ||
1802 | { .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C, | ||
1803 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1804 | .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, | ||
1805 | .data[10] = 0x10, .data[11] = 0x00, }, | ||
1806 | { .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C, | ||
1807 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1808 | .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20, | ||
1809 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1810 | { .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C, | ||
1811 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1812 | .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20, | ||
1813 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1814 | { .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C, | ||
1815 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1816 | .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, | ||
1817 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1818 | { .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C, | ||
1819 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1820 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, | ||
1821 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1822 | { .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C, | ||
1823 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1824 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, | ||
1825 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1826 | { .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C, | ||
1827 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1828 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1829 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1830 | { .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C, | ||
1831 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1832 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1833 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1834 | { .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C, | ||
1835 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1836 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1837 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1838 | { .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C, | ||
1839 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1840 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1841 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1842 | { .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C, | ||
1843 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1844 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1845 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1846 | { .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C, | ||
1847 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1848 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1849 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1850 | { .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C, | ||
1851 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1852 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1853 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1854 | { .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C, | ||
1855 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1856 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1857 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1858 | { .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C, | ||
1859 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1860 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1861 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1862 | { .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C, | ||
1863 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1864 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1865 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1866 | { .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C, | ||
1867 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, | ||
1868 | .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, | ||
1869 | .data[10] = 0x00, .data[11] = 0x00, }, | ||
1870 | { .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C, | ||
1871 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E, | ||
1872 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0, | ||
1873 | .data[10] = 0x50, .data[11] = 0x00, }, | ||
1874 | { .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C, | ||
1875 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D, | ||
1876 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0, | ||
1877 | .data[10] = 0x50, .data[11] = 0x00, }, | ||
1878 | { .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C, | ||
1879 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C, | ||
1880 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0, | ||
1881 | .data[10] = 0x50, .data[11] = 0x00, }, | ||
1882 | { .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C, | ||
1883 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C, | ||
1884 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, | ||
1885 | .data[10] = 0x40, .data[11] = 0x00, }, | ||
1886 | { .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C, | ||
1887 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B, | ||
1888 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, | ||
1889 | .data[10] = 0x40, .data[11] = 0x00, }, | ||
1890 | { .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C, | ||
1891 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A, | ||
1892 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, | ||
1893 | .data[10] = 0x40, .data[11] = 0x00, }, | ||
1894 | { .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C, | ||
1895 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09, | ||
1896 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, | ||
1897 | .data[10] = 0x40, .data[11] = 0x00, }, | ||
1898 | { .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C, | ||
1899 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08, | ||
1900 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, | ||
1901 | .data[10] = 0x40, .data[11] = 0x00, }, | ||
1902 | { .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C, | ||
1903 | .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08, | ||
1904 | .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, | ||
1905 | .data[10] = 0x40, .data[11] = 0x00, }, | ||
1906 | }; | ||
1907 | |||
1908 | static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) | ||
1909 | { | ||
1910 | struct ssb_bus *bus = dev->dev->bus; | ||
1911 | |||
1912 | b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF); | ||
1913 | udelay(20); | ||
1914 | if (bus->chip_id == 0x5354) { | ||
1915 | b43_radio_write(dev, B2062_N_COMM1, 4); | ||
1916 | b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4); | ||
1917 | } else { | ||
1918 | b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0); | ||
1919 | } | ||
1920 | udelay(5); | ||
1921 | } | ||
1922 | |||
1923 | static void lpphy_b2062_vco_calib(struct b43_wldev *dev) | ||
1924 | { | ||
1925 | b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x42); | ||
1926 | b43_phy_write(dev, B2062_S_RFPLL_CTL21, 0x62); | ||
1927 | udelay(200); | ||
1928 | } | ||
1929 | |||
1930 | static int lpphy_b2062_tune(struct b43_wldev *dev, | ||
1931 | unsigned int channel) | ||
1932 | { | ||
1933 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
1934 | struct ssb_bus *bus = dev->dev->bus; | ||
1935 | const struct b206x_channel *chandata = NULL; | ||
1936 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | ||
1937 | u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; | ||
1938 | int i, err = 0; | ||
1939 | |||
1940 | for (i = 0; i < ARRAY_SIZE(b2062_chantbl); i++) { | ||
1941 | if (b2062_chantbl[i].channel == channel) { | ||
1942 | chandata = &b2062_chantbl[i]; | ||
1943 | break; | ||
1944 | } | ||
1945 | } | ||
1946 | |||
1947 | if (B43_WARN_ON(!chandata)) | ||
1948 | return -EINVAL; | ||
1949 | |||
1950 | b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04); | ||
1951 | b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]); | ||
1952 | b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]); | ||
1953 | b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]); | ||
1954 | b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]); | ||
1955 | b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]); | ||
1956 | b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]); | ||
1957 | b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]); | ||
1958 | b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]); | ||
1959 | b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]); | ||
1960 | |||
1961 | tmp1 = crystal_freq / 1000; | ||
1962 | tmp2 = lpphy->pdiv * 1000; | ||
1963 | b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC); | ||
1964 | b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07); | ||
1965 | lpphy_b2062_reset_pll_bias(dev); | ||
1966 | tmp3 = tmp2 * channel2freq_lp(channel); | ||
1967 | if (channel2freq_lp(channel) < 4000) | ||
1968 | tmp3 *= 2; | ||
1969 | tmp4 = 48 * tmp1; | ||
1970 | tmp6 = tmp3 / tmp4; | ||
1971 | tmp7 = tmp3 % tmp4; | ||
1972 | b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6); | ||
1973 | tmp5 = tmp7 * 0x100; | ||
1974 | tmp6 = tmp5 / tmp4; | ||
1975 | tmp7 = tmp5 % tmp4; | ||
1976 | b43_radio_write(dev, B2062_S_RFPLL_CTL27, tmp6); | ||
1977 | tmp5 = tmp7 * 0x100; | ||
1978 | tmp6 = tmp5 / tmp4; | ||
1979 | tmp7 = tmp5 % tmp4; | ||
1980 | b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6); | ||
1981 | tmp5 = tmp7 * 0x100; | ||
1982 | tmp6 = tmp5 / tmp4; | ||
1983 | tmp7 = tmp5 % tmp4; | ||
1984 | b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4)); | ||
1985 | tmp8 = b43_phy_read(dev, B2062_S_RFPLL_CTL19); | ||
1986 | tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1); | ||
1987 | b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16); | ||
1988 | b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF); | ||
1989 | |||
1990 | lpphy_b2062_vco_calib(dev); | ||
1991 | if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) { | ||
1992 | b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC); | ||
1993 | b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0); | ||
1994 | lpphy_b2062_reset_pll_bias(dev); | ||
1995 | lpphy_b2062_vco_calib(dev); | ||
1996 | if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) | ||
1997 | err = -EIO; | ||
1998 | } | ||
1999 | |||
2000 | b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04); | ||
2001 | return err; | ||
2002 | } | ||
2003 | |||
2004 | |||
2005 | /* This was previously called lpphy_japan_filter */ | ||
2006 | static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel) | ||
2007 | { | ||
2008 | struct b43_phy_lp *lpphy = dev->phy.lp; | ||
2009 | u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! | ||
2010 | |||
2011 | if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific? | ||
2012 | b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9); | ||
2013 | if ((dev->phy.rev == 1) && (lpphy->rc_cap)) | ||
2014 | lpphy_set_rc_cap(dev); | ||
2015 | } else { | ||
2016 | b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F); | ||
2017 | } | ||
2018 | } | ||
2019 | |||
2020 | static void lpphy_b2063_vco_calib(struct b43_wldev *dev) | ||
2021 | { | ||
2022 | u16 tmp; | ||
2023 | |||
2024 | b43_phy_mask(dev, B2063_PLL_SP1, ~0x40); | ||
2025 | tmp = b43_phy_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8; | ||
2026 | b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp); | ||
2027 | udelay(1); | ||
2028 | b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4); | ||
2029 | udelay(1); | ||
2030 | b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6); | ||
2031 | udelay(1); | ||
2032 | b43_phy_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7); | ||
2033 | udelay(300); | ||
2034 | b43_phy_set(dev, B2063_PLL_SP1, 0x40); | ||
2035 | } | ||
2036 | |||
2037 | static int lpphy_b2063_tune(struct b43_wldev *dev, | ||
2038 | unsigned int channel) | ||
2039 | { | ||
2040 | struct ssb_bus *bus = dev->dev->bus; | ||
2041 | |||
2042 | static const struct b206x_channel *chandata = NULL; | ||
2043 | u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; | ||
2044 | u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count; | ||
2045 | u16 old_comm15, scale; | ||
2046 | u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; | ||
2047 | int i, div = (crystal_freq <= 26000000 ? 1 : 2); | ||
2048 | |||
2049 | for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) { | ||
2050 | if (b2063_chantbl[i].channel == channel) { | ||
2051 | chandata = &b2063_chantbl[i]; | ||
2052 | break; | ||
2053 | } | ||
2054 | } | ||
2055 | |||
2056 | if (B43_WARN_ON(!chandata)) | ||
2057 | return -EINVAL; | ||
2058 | |||
2059 | b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]); | ||
2060 | b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]); | ||
2061 | b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]); | ||
2062 | b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]); | ||
2063 | b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]); | ||
2064 | b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]); | ||
2065 | b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]); | ||
2066 | b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]); | ||
2067 | b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]); | ||
2068 | b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]); | ||
2069 | b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]); | ||
2070 | b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]); | ||
2071 | |||
2072 | old_comm15 = b43_radio_read(dev, B2063_COMM15); | ||
2073 | b43_radio_set(dev, B2063_COMM15, 0x1E); | ||
2074 | |||
2075 | if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */ | ||
2076 | vco_freq = chandata->freq << 1; | ||
2077 | else | ||
2078 | vco_freq = chandata->freq << 2; | ||
2079 | |||
2080 | freqref = crystal_freq * 3; | ||
2081 | val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16); | ||
2082 | val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16); | ||
2083 | val3 = lpphy_qdiv_roundup(vco_freq, 3, 16); | ||
2084 | timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1; | ||
2085 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2); | ||
2086 | b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6, | ||
2087 | 0xFFF8, timeout >> 2); | ||
2088 | b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7, | ||
2089 | 0xFF9F,timeout << 5); | ||
2090 | |||
2091 | timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) + | ||
2092 | 999999) / 1000000) + 1; | ||
2093 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref); | ||
2094 | |||
2095 | count = lpphy_qdiv_roundup(val3, val2 + 16, 16); | ||
2096 | count *= (timeout + 1) * (timeoutref + 1); | ||
2097 | count--; | ||
2098 | b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7, | ||
2099 | 0xF0, count >> 8); | ||
2100 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF); | ||
2101 | |||
2102 | tmp1 = ((val3 * 62500) / freqref) << 4; | ||
2103 | tmp2 = ((val3 * 62500) % freqref) << 4; | ||
2104 | while (tmp2 >= freqref) { | ||
2105 | tmp1++; | ||
2106 | tmp2 -= freqref; | ||
2107 | } | ||
2108 | b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4); | ||
2109 | b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4); | ||
2110 | b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16); | ||
2111 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF); | ||
2112 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF); | ||
2113 | |||
2114 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9); | ||
2115 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88); | ||
2116 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28); | ||
2117 | b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63); | ||
2118 | |||
2119 | tmp3 = ((41 * (val3 - 3000)) /1200) + 27; | ||
2120 | tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16); | ||
2121 | |||
2122 | if ((tmp4 + tmp3 - 1) / tmp3 > 60) { | ||
2123 | scale = 1; | ||
2124 | tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8; | ||
2125 | } else { | ||
2126 | scale = 0; | ||
2127 | tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8; | ||
2128 | } | ||
2129 | b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5); | ||
2130 | b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6); | ||
2131 | |||
2132 | tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16); | ||
2133 | tmp6 *= (tmp5 * 8) * (scale + 1); | ||
2134 | if (tmp6 > 150) | ||
2135 | tmp6 = 0; | ||
2136 | |||
2137 | b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6); | ||
2138 | b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5); | ||
2139 | |||
2140 | b43_phy_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4); | ||
2141 | if (crystal_freq > 26000000) | ||
2142 | b43_phy_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2); | ||
2143 | else | ||
2144 | b43_phy_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD); | ||
2145 | |||
2146 | if (val1 == 45) | ||
2147 | b43_phy_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2); | ||
2148 | else | ||
2149 | b43_phy_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD); | ||
2150 | |||
2151 | b43_phy_set(dev, B2063_PLL_SP2, 0x3); | ||
2152 | udelay(1); | ||
2153 | b43_phy_mask(dev, B2063_PLL_SP2, 0xFFFC); | ||
2154 | lpphy_b2063_vco_calib(dev); | ||
2155 | b43_radio_write(dev, B2063_COMM15, old_comm15); | ||
2156 | |||
2157 | return 0; | ||
2158 | } | ||
2159 | |||
1331 | static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, | 2160 | static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, |
1332 | unsigned int new_channel) | 2161 | unsigned int new_channel) |
1333 | { | 2162 | { |
1334 | //TODO | 2163 | int err; |
2164 | |||
2165 | b43_write16(dev, B43_MMIO_CHANNEL, new_channel); | ||
2166 | |||
2167 | if (dev->phy.radio_ver == 0x2063) { | ||
2168 | err = lpphy_b2063_tune(dev, new_channel); | ||
2169 | if (err) | ||
2170 | return err; | ||
2171 | } else { | ||
2172 | err = lpphy_b2062_tune(dev, new_channel); | ||
2173 | if (err) | ||
2174 | return err; | ||
2175 | lpphy_set_analog_filter(dev, new_channel); | ||
2176 | lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); | ||
2177 | } | ||
2178 | |||
1335 | return 0; | 2179 | return 0; |
1336 | } | 2180 | } |
1337 | 2181 | ||
1338 | static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) | 2182 | static int b43_lpphy_op_init(struct b43_wldev *dev) |
1339 | { | 2183 | { |
1340 | if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) | 2184 | int err; |
1341 | return 1; | 2185 | |
1342 | return 36; | 2186 | lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? |
2187 | lpphy_baseband_init(dev); | ||
2188 | lpphy_radio_init(dev); | ||
2189 | lpphy_calibrate_rc(dev); | ||
2190 | err = b43_lpphy_op_switch_channel(dev, | ||
2191 | b43_lpphy_op_get_default_chan(dev)); | ||
2192 | if (err) { | ||
2193 | b43dbg(dev->wl, "Switch to init channel failed, error = %d.\n", | ||
2194 | err); | ||
2195 | } | ||
2196 | lpphy_tx_pctl_init(dev); | ||
2197 | lpphy_calibration(dev); | ||
2198 | //TODO ACI init | ||
2199 | |||
2200 | return 0; | ||
1343 | } | 2201 | } |
1344 | 2202 | ||
1345 | static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) | 2203 | static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) |
diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h index 0461d5b3144f..e158d1f66c0e 100644 --- a/drivers/net/wireless/b43/phy_lp.h +++ b/drivers/net/wireless/b43/phy_lp.h | |||
@@ -825,11 +825,11 @@ struct b43_phy_lp { | |||
825 | enum b43_lpphy_txpctl_mode txpctl_mode; | 825 | enum b43_lpphy_txpctl_mode txpctl_mode; |
826 | 826 | ||
827 | /* Transmit isolation medium band */ | 827 | /* Transmit isolation medium band */ |
828 | u8 tx_isolation_med_band; /* FIXME initial value? */ | 828 | u8 tx_isolation_med_band; |
829 | /* Transmit isolation low band */ | 829 | /* Transmit isolation low band */ |
830 | u8 tx_isolation_low_band; /* FIXME initial value? */ | 830 | u8 tx_isolation_low_band; |
831 | /* Transmit isolation high band */ | 831 | /* Transmit isolation high band */ |
832 | u8 tx_isolation_hi_band; /* FIXME initial value? */ | 832 | u8 tx_isolation_hi_band; |
833 | 833 | ||
834 | /* Max transmit power medium band */ | 834 | /* Max transmit power medium band */ |
835 | u16 max_tx_pwr_med_band; | 835 | u16 max_tx_pwr_med_band; |
@@ -848,7 +848,7 @@ struct b43_phy_lp { | |||
848 | s16 txpa[3], txpal[3], txpah[3]; | 848 | s16 txpa[3], txpal[3], txpah[3]; |
849 | 849 | ||
850 | /* Receive power offset */ | 850 | /* Receive power offset */ |
851 | u8 rx_pwr_offset; /* FIXME initial value? */ | 851 | u8 rx_pwr_offset; |
852 | 852 | ||
853 | /* TSSI transmit count */ | 853 | /* TSSI transmit count */ |
854 | u16 tssi_tx_count; | 854 | u16 tssi_tx_count; |
@@ -864,16 +864,16 @@ struct b43_phy_lp { | |||
864 | s8 tx_pwr_idx_over; /* FIXME initial value? */ | 864 | s8 tx_pwr_idx_over; /* FIXME initial value? */ |
865 | 865 | ||
866 | /* RSSI vf */ | 866 | /* RSSI vf */ |
867 | u8 rssi_vf; /* FIXME initial value? */ | 867 | u8 rssi_vf; |
868 | /* RSSI vc */ | 868 | /* RSSI vc */ |
869 | u8 rssi_vc; /* FIXME initial value? */ | 869 | u8 rssi_vc; |
870 | /* RSSI gs */ | 870 | /* RSSI gs */ |
871 | u8 rssi_gs; /* FIXME initial value? */ | 871 | u8 rssi_gs; |
872 | 872 | ||
873 | /* RC cap */ | 873 | /* RC cap */ |
874 | u8 rc_cap; /* FIXME initial value? */ | 874 | u8 rc_cap; /* FIXME initial value? */ |
875 | /* BX arch */ | 875 | /* BX arch */ |
876 | u8 bx_arch; /* FIXME initial value? */ | 876 | u8 bx_arch; |
877 | 877 | ||
878 | /* Full calibration channel */ | 878 | /* Full calibration channel */ |
879 | u8 full_calib_chan; /* FIXME initial value? */ | 879 | u8 full_calib_chan; /* FIXME initial value? */ |
@@ -884,8 +884,17 @@ struct b43_phy_lp { | |||
884 | 884 | ||
885 | /* Used for "Save/Restore Dig Filt State" */ | 885 | /* Used for "Save/Restore Dig Filt State" */ |
886 | u16 dig_flt_state[9]; | 886 | u16 dig_flt_state[9]; |
887 | |||
888 | bool crs_usr_disable, crs_sys_disable; | ||
889 | |||
890 | unsigned int pdiv; | ||
887 | }; | 891 | }; |
888 | 892 | ||
893 | enum tssi_mux_mode { | ||
894 | TSSI_MUX_PREPA, | ||
895 | TSSI_MUX_POSTPA, | ||
896 | TSSI_MUX_EXT, | ||
897 | }; | ||
889 | 898 | ||
890 | struct b43_phy_operations; | 899 | struct b43_phy_operations; |
891 | extern const struct b43_phy_operations b43_phyops_lp; | 900 | extern const struct b43_phy_operations b43_phyops_lp; |
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 73c047d8de40..3fd653c78b10 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c | |||
@@ -461,8 +461,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q, | |||
461 | 461 | ||
462 | cookie = generate_cookie(q, pack); | 462 | cookie = generate_cookie(q, pack); |
463 | hdrlen = b43_txhdr_size(q->dev); | 463 | hdrlen = b43_txhdr_size(q->dev); |
464 | err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb->data, | 464 | err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb, |
465 | skb->len, info, cookie); | 465 | info, cookie); |
466 | if (err) | 466 | if (err) |
467 | return err; | 467 | return err; |
468 | 468 | ||
diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c index 2721310acb2a..60d472f285af 100644 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ b/drivers/net/wireless/b43/tables_lpphy.c | |||
@@ -2367,7 +2367,17 @@ static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset, | |||
2367 | tmp = data.pad << 16; | 2367 | tmp = data.pad << 16; |
2368 | tmp |= data.pga << 8; | 2368 | tmp |= data.pga << 8; |
2369 | tmp |= data.gm; | 2369 | tmp |= data.gm; |
2370 | tmp |= 0x7f000000; | 2370 | if (dev->phy.rev >= 3) { |
2371 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
2372 | tmp |= 0x10 << 24; | ||
2373 | else | ||
2374 | tmp |= 0x70 << 24; | ||
2375 | } else { | ||
2376 | if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) | ||
2377 | tmp |= 0x14 << 24; | ||
2378 | else | ||
2379 | tmp |= 0x7F << 24; | ||
2380 | } | ||
2371 | b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp); | 2381 | b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp); |
2372 | tmp = data.bb_mult << 20; | 2382 | tmp = data.bb_mult << 20; |
2373 | tmp |= data.dac << 28; | 2383 | tmp |= data.dac << 28; |
diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c index e1e20f69f6d7..97c79161c208 100644 --- a/drivers/net/wireless/b43/wa.c +++ b/drivers/net/wireless/b43/wa.c | |||
@@ -37,7 +37,7 @@ static void b43_wa_papd(struct b43_wldev *dev) | |||
37 | backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0); | 37 | backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0); |
38 | b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7); | 38 | b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7); |
39 | b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0); | 39 | b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0); |
40 | b43_dummy_transmission(dev); | 40 | b43_dummy_transmission(dev, true, true); |
41 | b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup); | 41 | b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup); |
42 | } | 42 | } |
43 | 43 | ||
@@ -628,7 +628,7 @@ void b43_wa_all(struct b43_wldev *dev) | |||
628 | B43_WARN_ON(1); | 628 | B43_WARN_ON(1); |
629 | } | 629 | } |
630 | b43_wa_boards_g(dev); | 630 | b43_wa_boards_g(dev); |
631 | } else { /* No N PHY support so far */ | 631 | } else { /* No N PHY support so far, LP PHY is in phy_lp.c */ |
632 | B43_WARN_ON(1); | 632 | B43_WARN_ON(1); |
633 | } | 633 | } |
634 | 634 | ||
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5280ebc8c6e9..e7075d2c7757 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -180,11 +180,12 @@ static u8 b43_calc_fallback_rate(u8 bitrate) | |||
180 | /* Generate a TX data header. */ | 180 | /* Generate a TX data header. */ |
181 | int b43_generate_txhdr(struct b43_wldev *dev, | 181 | int b43_generate_txhdr(struct b43_wldev *dev, |
182 | u8 *_txhdr, | 182 | u8 *_txhdr, |
183 | const unsigned char *fragment_data, | 183 | struct sk_buff *skb_frag, |
184 | unsigned int fragment_len, | ||
185 | struct ieee80211_tx_info *info, | 184 | struct ieee80211_tx_info *info, |
186 | u16 cookie) | 185 | u16 cookie) |
187 | { | 186 | { |
187 | const unsigned char *fragment_data = skb_frag->data; | ||
188 | unsigned int fragment_len = skb_frag->len; | ||
188 | struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; | 189 | struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; |
189 | const struct b43_phy *phy = &dev->phy; | 190 | const struct b43_phy *phy = &dev->phy; |
190 | const struct ieee80211_hdr *wlhdr = | 191 | const struct ieee80211_hdr *wlhdr = |
@@ -258,9 +259,26 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
258 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & | 259 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & |
259 | B43_TXH_MAC_KEYALG; | 260 | B43_TXH_MAC_KEYALG; |
260 | wlhdr_len = ieee80211_hdrlen(fctl); | 261 | wlhdr_len = ieee80211_hdrlen(fctl); |
261 | iv_len = min((size_t) info->control.hw_key->iv_len, | 262 | if (key->algorithm == B43_SEC_ALGO_TKIP) { |
262 | ARRAY_SIZE(txhdr->iv)); | 263 | u16 phase1key[5]; |
263 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); | 264 | int i; |
265 | /* we give the phase1key and iv16 here, the key is stored in | ||
266 | * shm. With that the hardware can do phase 2 and encryption. | ||
267 | */ | ||
268 | ieee80211_get_tkip_key(info->control.hw_key, skb_frag, | ||
269 | IEEE80211_TKIP_P1_KEY, (u8*)phase1key); | ||
270 | /* phase1key is in host endian */ | ||
271 | for (i = 0; i < 5; i++) | ||
272 | phase1key[i] = cpu_to_le16(phase1key[i]); | ||
273 | |||
274 | memcpy(txhdr->iv, phase1key, 10); | ||
275 | /* iv16 */ | ||
276 | memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3); | ||
277 | } else { | ||
278 | iv_len = min((size_t) info->control.hw_key->iv_len, | ||
279 | ARRAY_SIZE(txhdr->iv)); | ||
280 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); | ||
281 | } | ||
264 | } | 282 | } |
265 | if (b43_is_old_txhdr_format(dev)) { | 283 | if (b43_is_old_txhdr_format(dev)) { |
266 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), | 284 | b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), |
@@ -655,6 +673,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) | |||
655 | status.freq = chanid + 2400; | 673 | status.freq = chanid + 2400; |
656 | break; | 674 | break; |
657 | case B43_PHYTYPE_N: | 675 | case B43_PHYTYPE_N: |
676 | case B43_PHYTYPE_LP: | ||
658 | /* chanid is the SHM channel cookie. Which is the plain | 677 | /* chanid is the SHM channel cookie. Which is the plain |
659 | * channel number in b43. */ | 678 | * channel number in b43. */ |
660 | if (chanstat & B43_RX_CHAN_5GHZ) { | 679 | if (chanstat & B43_RX_CHAN_5GHZ) { |
diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h index 4fb2a190f7a7..3530de871873 100644 --- a/drivers/net/wireless/b43/xmit.h +++ b/drivers/net/wireless/b43/xmit.h | |||
@@ -176,8 +176,7 @@ size_t b43_txhdr_size(struct b43_wldev *dev) | |||
176 | 176 | ||
177 | int b43_generate_txhdr(struct b43_wldev *dev, | 177 | int b43_generate_txhdr(struct b43_wldev *dev, |
178 | u8 * txhdr, | 178 | u8 * txhdr, |
179 | const unsigned char *fragment_data, | 179 | struct sk_buff *skb_frag, |
180 | unsigned int fragment_len, | ||
181 | struct ieee80211_tx_info *txctl, u16 cookie); | 180 | struct ieee80211_tx_info *txctl, u16 cookie); |
182 | 181 | ||
183 | /* Transmit Status */ | 182 | /* Transmit Status */ |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index b1435594921a..b166a6f9f055 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2836,9 +2836,7 @@ static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, | |||
2836 | 2836 | ||
2837 | static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, | 2837 | static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, |
2838 | unsigned int changed, | 2838 | unsigned int changed, |
2839 | unsigned int *fflags, | 2839 | unsigned int *fflags,u64 multicast) |
2840 | int mc_count, | ||
2841 | struct dev_addr_list *mc_list) | ||
2842 | { | 2840 | { |
2843 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); | 2841 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
2844 | struct b43legacy_wldev *dev = wl->current_dev; | 2842 | struct b43legacy_wldev *dev = wl->current_dev; |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index 742432388ca3..dee50ed0897d 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -185,7 +185,7 @@ MODULE_AUTHOR(DRV_COPYRIGHT); | |||
185 | MODULE_LICENSE("GPL"); | 185 | MODULE_LICENSE("GPL"); |
186 | 186 | ||
187 | static int debug = 0; | 187 | static int debug = 0; |
188 | static int mode = 0; | 188 | static int network_mode = 0; |
189 | static int channel = 0; | 189 | static int channel = 0; |
190 | static int associate = 0; | 190 | static int associate = 0; |
191 | static int disable = 0; | 191 | static int disable = 0; |
@@ -195,7 +195,7 @@ static struct ipw2100_fw ipw2100_firmware; | |||
195 | 195 | ||
196 | #include <linux/moduleparam.h> | 196 | #include <linux/moduleparam.h> |
197 | module_param(debug, int, 0444); | 197 | module_param(debug, int, 0444); |
198 | module_param(mode, int, 0444); | 198 | module_param_named(mode, network_mode, int, 0444); |
199 | module_param(channel, int, 0444); | 199 | module_param(channel, int, 0444); |
200 | module_param(associate, int, 0444); | 200 | module_param(associate, int, 0444); |
201 | module_param(disable, int, 0444); | 201 | module_param(disable, int, 0444); |
@@ -2844,7 +2844,7 @@ static int __ipw2100_tx_process(struct ipw2100_priv *priv) | |||
2844 | 2844 | ||
2845 | #ifdef CONFIG_IPW2100_DEBUG | 2845 | #ifdef CONFIG_IPW2100_DEBUG |
2846 | { | 2846 | { |
2847 | int i = txq->oldest; | 2847 | i = txq->oldest; |
2848 | IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, | 2848 | IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, |
2849 | &txq->drv[i], | 2849 | &txq->drv[i], |
2850 | (u32) (txq->nic + i * sizeof(struct ipw2100_bd)), | 2850 | (u32) (txq->nic + i * sizeof(struct ipw2100_bd)), |
@@ -6076,7 +6076,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6076 | priv->ieee->ieee802_1x = 1; | 6076 | priv->ieee->ieee802_1x = 1; |
6077 | 6077 | ||
6078 | /* Set module parameters */ | 6078 | /* Set module parameters */ |
6079 | switch (mode) { | 6079 | switch (network_mode) { |
6080 | case 1: | 6080 | case 1: |
6081 | priv->ieee->iw_mode = IW_MODE_ADHOC; | 6081 | priv->ieee->iw_mode = IW_MODE_ADHOC; |
6082 | break; | 6082 | break; |
@@ -8179,10 +8179,11 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) | |||
8179 | int rssi_qual; | 8179 | int rssi_qual; |
8180 | int tx_qual; | 8180 | int tx_qual; |
8181 | int beacon_qual; | 8181 | int beacon_qual; |
8182 | int quality; | ||
8182 | 8183 | ||
8183 | struct ipw2100_priv *priv = ieee80211_priv(dev); | 8184 | struct ipw2100_priv *priv = ieee80211_priv(dev); |
8184 | struct iw_statistics *wstats; | 8185 | struct iw_statistics *wstats; |
8185 | u32 rssi, quality, tx_retries, missed_beacons, tx_failures; | 8186 | u32 rssi, tx_retries, missed_beacons, tx_failures; |
8186 | u32 ord_len = sizeof(u32); | 8187 | u32 ord_len = sizeof(u32); |
8187 | 8188 | ||
8188 | if (!priv) | 8189 | if (!priv) |
@@ -8265,7 +8266,8 @@ static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) | |||
8265 | beacon_qual = (20 - missed_beacons) * | 8266 | beacon_qual = (20 - missed_beacons) * |
8266 | (PERFECT - VERY_GOOD) / 20 + VERY_GOOD; | 8267 | (PERFECT - VERY_GOOD) / 20 + VERY_GOOD; |
8267 | 8268 | ||
8268 | quality = min(beacon_qual, min(tx_qual, rssi_qual)); | 8269 | quality = min(tx_qual, rssi_qual); |
8270 | quality = min(beacon_qual, quality); | ||
8269 | 8271 | ||
8270 | #ifdef CONFIG_IPW2100_DEBUG | 8272 | #ifdef CONFIG_IPW2100_DEBUG |
8271 | if (beacon_qual == quality) | 8273 | if (beacon_qual == quality) |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 07f171c4d30e..8e18d5348350 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -83,13 +83,13 @@ MODULE_LICENSE("GPL"); | |||
83 | 83 | ||
84 | static int cmdlog = 0; | 84 | static int cmdlog = 0; |
85 | static int debug = 0; | 85 | static int debug = 0; |
86 | static int channel = 0; | 86 | static int default_channel = 0; |
87 | static int mode = 0; | 87 | static int network_mode = 0; |
88 | 88 | ||
89 | static u32 ipw_debug_level; | 89 | static u32 ipw_debug_level; |
90 | static int associate; | 90 | static int associate; |
91 | static int auto_create = 1; | 91 | static int auto_create = 1; |
92 | static int led = 0; | 92 | static int led_support = 0; |
93 | static int disable = 0; | 93 | static int disable = 0; |
94 | static int bt_coexist = 0; | 94 | static int bt_coexist = 0; |
95 | static int hwcrypto = 0; | 95 | static int hwcrypto = 0; |
@@ -4265,9 +4265,10 @@ static void ipw_gather_stats(struct ipw_priv *priv) | |||
4265 | IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", | 4265 | IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", |
4266 | signal_quality, rssi); | 4266 | signal_quality, rssi); |
4267 | 4267 | ||
4268 | quality = min(beacon_quality, | 4268 | quality = min(rx_quality, signal_quality); |
4269 | min(rate_quality, | 4269 | quality = min(tx_quality, quality); |
4270 | min(tx_quality, min(rx_quality, signal_quality)))); | 4270 | quality = min(rate_quality, quality); |
4271 | quality = min(beacon_quality, quality); | ||
4271 | if (quality == beacon_quality) | 4272 | if (quality == beacon_quality) |
4272 | IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n", | 4273 | IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n", |
4273 | quality); | 4274 | quality); |
@@ -4411,7 +4412,6 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4411 | { | 4412 | { |
4412 | DECLARE_SSID_BUF(ssid); | 4413 | DECLARE_SSID_BUF(ssid); |
4413 | u16 size = le16_to_cpu(notif->size); | 4414 | u16 size = le16_to_cpu(notif->size); |
4414 | notif->size = le16_to_cpu(notif->size); | ||
4415 | 4415 | ||
4416 | IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); | 4416 | IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); |
4417 | 4417 | ||
@@ -6101,11 +6101,10 @@ static void ipw_debug_config(struct ipw_priv *priv) | |||
6101 | static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) | 6101 | static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) |
6102 | { | 6102 | { |
6103 | /* TODO: Verify that this works... */ | 6103 | /* TODO: Verify that this works... */ |
6104 | struct ipw_fixed_rate fr = { | 6104 | struct ipw_fixed_rate fr; |
6105 | .tx_rates = priv->rates_mask | ||
6106 | }; | ||
6107 | u32 reg; | 6105 | u32 reg; |
6108 | u16 mask = 0; | 6106 | u16 mask = 0; |
6107 | u16 new_tx_rates = priv->rates_mask; | ||
6109 | 6108 | ||
6110 | /* Identify 'current FW band' and match it with the fixed | 6109 | /* Identify 'current FW band' and match it with the fixed |
6111 | * Tx rates */ | 6110 | * Tx rates */ |
@@ -6117,54 +6116,56 @@ static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) | |||
6117 | /* Invalid fixed rate mask */ | 6116 | /* Invalid fixed rate mask */ |
6118 | IPW_DEBUG_WX | 6117 | IPW_DEBUG_WX |
6119 | ("invalid fixed rate mask in ipw_set_fixed_rate\n"); | 6118 | ("invalid fixed rate mask in ipw_set_fixed_rate\n"); |
6120 | fr.tx_rates = 0; | 6119 | new_tx_rates = 0; |
6121 | break; | 6120 | break; |
6122 | } | 6121 | } |
6123 | 6122 | ||
6124 | fr.tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A; | 6123 | new_tx_rates >>= IEEE80211_OFDM_SHIFT_MASK_A; |
6125 | break; | 6124 | break; |
6126 | 6125 | ||
6127 | default: /* 2.4Ghz or Mixed */ | 6126 | default: /* 2.4Ghz or Mixed */ |
6128 | /* IEEE_B */ | 6127 | /* IEEE_B */ |
6129 | if (mode == IEEE_B) { | 6128 | if (mode == IEEE_B) { |
6130 | if (fr.tx_rates & ~IEEE80211_CCK_RATES_MASK) { | 6129 | if (new_tx_rates & ~IEEE80211_CCK_RATES_MASK) { |
6131 | /* Invalid fixed rate mask */ | 6130 | /* Invalid fixed rate mask */ |
6132 | IPW_DEBUG_WX | 6131 | IPW_DEBUG_WX |
6133 | ("invalid fixed rate mask in ipw_set_fixed_rate\n"); | 6132 | ("invalid fixed rate mask in ipw_set_fixed_rate\n"); |
6134 | fr.tx_rates = 0; | 6133 | new_tx_rates = 0; |
6135 | } | 6134 | } |
6136 | break; | 6135 | break; |
6137 | } | 6136 | } |
6138 | 6137 | ||
6139 | /* IEEE_G */ | 6138 | /* IEEE_G */ |
6140 | if (fr.tx_rates & ~(IEEE80211_CCK_RATES_MASK | | 6139 | if (new_tx_rates & ~(IEEE80211_CCK_RATES_MASK | |
6141 | IEEE80211_OFDM_RATES_MASK)) { | 6140 | IEEE80211_OFDM_RATES_MASK)) { |
6142 | /* Invalid fixed rate mask */ | 6141 | /* Invalid fixed rate mask */ |
6143 | IPW_DEBUG_WX | 6142 | IPW_DEBUG_WX |
6144 | ("invalid fixed rate mask in ipw_set_fixed_rate\n"); | 6143 | ("invalid fixed rate mask in ipw_set_fixed_rate\n"); |
6145 | fr.tx_rates = 0; | 6144 | new_tx_rates = 0; |
6146 | break; | 6145 | break; |
6147 | } | 6146 | } |
6148 | 6147 | ||
6149 | if (IEEE80211_OFDM_RATE_6MB_MASK & fr.tx_rates) { | 6148 | if (IEEE80211_OFDM_RATE_6MB_MASK & new_tx_rates) { |
6150 | mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1); | 6149 | mask |= (IEEE80211_OFDM_RATE_6MB_MASK >> 1); |
6151 | fr.tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK; | 6150 | new_tx_rates &= ~IEEE80211_OFDM_RATE_6MB_MASK; |
6152 | } | 6151 | } |
6153 | 6152 | ||
6154 | if (IEEE80211_OFDM_RATE_9MB_MASK & fr.tx_rates) { | 6153 | if (IEEE80211_OFDM_RATE_9MB_MASK & new_tx_rates) { |
6155 | mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1); | 6154 | mask |= (IEEE80211_OFDM_RATE_9MB_MASK >> 1); |
6156 | fr.tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK; | 6155 | new_tx_rates &= ~IEEE80211_OFDM_RATE_9MB_MASK; |
6157 | } | 6156 | } |
6158 | 6157 | ||
6159 | if (IEEE80211_OFDM_RATE_12MB_MASK & fr.tx_rates) { | 6158 | if (IEEE80211_OFDM_RATE_12MB_MASK & new_tx_rates) { |
6160 | mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1); | 6159 | mask |= (IEEE80211_OFDM_RATE_12MB_MASK >> 1); |
6161 | fr.tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK; | 6160 | new_tx_rates &= ~IEEE80211_OFDM_RATE_12MB_MASK; |
6162 | } | 6161 | } |
6163 | 6162 | ||
6164 | fr.tx_rates |= mask; | 6163 | new_tx_rates |= mask; |
6165 | break; | 6164 | break; |
6166 | } | 6165 | } |
6167 | 6166 | ||
6167 | fr.tx_rates = cpu_to_le16(new_tx_rates); | ||
6168 | |||
6168 | reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE); | 6169 | reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE); |
6169 | ipw_write_reg32(priv, reg, *(u32 *) & fr); | 6170 | ipw_write_reg32(priv, reg, *(u32 *) & fr); |
6170 | } | 6171 | } |
@@ -7850,7 +7851,7 @@ static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, | |||
7850 | 7851 | ||
7851 | /* Convert signal to DBM */ | 7852 | /* Convert signal to DBM */ |
7852 | ipw_rt->rt_dbmsignal = antsignal; | 7853 | ipw_rt->rt_dbmsignal = antsignal; |
7853 | ipw_rt->rt_dbmnoise = frame->noise; | 7854 | ipw_rt->rt_dbmnoise = (s8) le16_to_cpu(frame->noise); |
7854 | 7855 | ||
7855 | /* Convert the channel data and set the flags */ | 7856 | /* Convert the channel data and set the flags */ |
7856 | ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); | 7857 | ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); |
@@ -7964,7 +7965,7 @@ static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, | |||
7964 | u16 channel = frame->received_channel; | 7965 | u16 channel = frame->received_channel; |
7965 | u8 phy_flags = frame->antennaAndPhy; | 7966 | u8 phy_flags = frame->antennaAndPhy; |
7966 | s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; | 7967 | s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; |
7967 | s8 noise = frame->noise; | 7968 | s8 noise = (s8) le16_to_cpu(frame->noise); |
7968 | u8 rate = frame->rate; | 7969 | u8 rate = frame->rate; |
7969 | short len = le16_to_cpu(pkt->u.frame.length); | 7970 | short len = le16_to_cpu(pkt->u.frame.length); |
7970 | struct sk_buff *skb; | 7971 | struct sk_buff *skb; |
@@ -8335,7 +8336,7 @@ static void ipw_rx(struct ipw_priv *priv) | |||
8335 | .rssi = pkt->u.frame.rssi_dbm - | 8336 | .rssi = pkt->u.frame.rssi_dbm - |
8336 | IPW_RSSI_TO_DBM, | 8337 | IPW_RSSI_TO_DBM, |
8337 | .signal = | 8338 | .signal = |
8338 | le16_to_cpu(pkt->u.frame.rssi_dbm) - | 8339 | pkt->u.frame.rssi_dbm - |
8339 | IPW_RSSI_TO_DBM + 0x100, | 8340 | IPW_RSSI_TO_DBM + 0x100, |
8340 | .noise = | 8341 | .noise = |
8341 | le16_to_cpu(pkt->u.frame.noise), | 8342 | le16_to_cpu(pkt->u.frame.noise), |
@@ -8517,7 +8518,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
8517 | 8518 | ||
8518 | /* We default to disabling the LED code as right now it causes | 8519 | /* We default to disabling the LED code as right now it causes |
8519 | * too many systems to lock up... */ | 8520 | * too many systems to lock up... */ |
8520 | if (!led) | 8521 | if (!led_support) |
8521 | priv->config |= CFG_NO_LED; | 8522 | priv->config |= CFG_NO_LED; |
8522 | 8523 | ||
8523 | if (associate) | 8524 | if (associate) |
@@ -8539,10 +8540,10 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
8539 | IPW_DEBUG_INFO("Radio disabled.\n"); | 8540 | IPW_DEBUG_INFO("Radio disabled.\n"); |
8540 | } | 8541 | } |
8541 | 8542 | ||
8542 | if (channel != 0) { | 8543 | if (default_channel != 0) { |
8543 | priv->config |= CFG_STATIC_CHANNEL; | 8544 | priv->config |= CFG_STATIC_CHANNEL; |
8544 | priv->channel = channel; | 8545 | priv->channel = default_channel; |
8545 | IPW_DEBUG_INFO("Bind to static channel %d\n", channel); | 8546 | IPW_DEBUG_INFO("Bind to static channel %d\n", default_channel); |
8546 | /* TODO: Validate that provided channel is in range */ | 8547 | /* TODO: Validate that provided channel is in range */ |
8547 | } | 8548 | } |
8548 | #ifdef CONFIG_IPW2200_QOS | 8549 | #ifdef CONFIG_IPW2200_QOS |
@@ -8550,7 +8551,7 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
8550 | burst_duration_CCK, burst_duration_OFDM); | 8551 | burst_duration_CCK, burst_duration_OFDM); |
8551 | #endif /* CONFIG_IPW2200_QOS */ | 8552 | #endif /* CONFIG_IPW2200_QOS */ |
8552 | 8553 | ||
8553 | switch (mode) { | 8554 | switch (network_mode) { |
8554 | case 1: | 8555 | case 1: |
8555 | priv->ieee->iw_mode = IW_MODE_ADHOC; | 8556 | priv->ieee->iw_mode = IW_MODE_ADHOC; |
8556 | priv->net_dev->type = ARPHRD_ETHER; | 8557 | priv->net_dev->type = ARPHRD_ETHER; |
@@ -10181,7 +10182,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
10181 | #endif | 10182 | #endif |
10182 | struct clx2_queue *q = &txq->q; | 10183 | struct clx2_queue *q = &txq->q; |
10183 | u8 id, hdr_len, unicast; | 10184 | u8 id, hdr_len, unicast; |
10184 | u16 remaining_bytes; | ||
10185 | int fc; | 10185 | int fc; |
10186 | 10186 | ||
10187 | if (!(priv->status & STATUS_ASSOCIATED)) | 10187 | if (!(priv->status & STATUS_ASSOCIATED)) |
@@ -10220,7 +10220,6 @@ static int ipw_tx_skb(struct ipw_priv *priv, struct ieee80211_txb *txb, | |||
10220 | 10220 | ||
10221 | tfd->u.data.cmd_id = DINO_CMD_TX; | 10221 | tfd->u.data.cmd_id = DINO_CMD_TX; |
10222 | tfd->u.data.len = cpu_to_le16(txb->payload_size); | 10222 | tfd->u.data.len = cpu_to_le16(txb->payload_size); |
10223 | remaining_bytes = txb->payload_size; | ||
10224 | 10223 | ||
10225 | if (priv->assoc_request.ieee_mode == IPW_B_MODE) | 10224 | if (priv->assoc_request.ieee_mode == IPW_B_MODE) |
10226 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; | 10225 | tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; |
@@ -11946,13 +11945,13 @@ MODULE_PARM_DESC(associate, "auto associate when scanning (default off)"); | |||
11946 | module_param(auto_create, int, 0444); | 11945 | module_param(auto_create, int, 0444); |
11947 | MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); | 11946 | MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); |
11948 | 11947 | ||
11949 | module_param(led, int, 0444); | 11948 | module_param_named(led, led_support, int, 0444); |
11950 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); | 11949 | MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); |
11951 | 11950 | ||
11952 | module_param(debug, int, 0444); | 11951 | module_param(debug, int, 0444); |
11953 | MODULE_PARM_DESC(debug, "debug output mask"); | 11952 | MODULE_PARM_DESC(debug, "debug output mask"); |
11954 | 11953 | ||
11955 | module_param(channel, int, 0444); | 11954 | module_param_named(channel, default_channel, int, 0444); |
11956 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); | 11955 | MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); |
11957 | 11956 | ||
11958 | #ifdef CONFIG_IPW2200_PROMISCUOUS | 11957 | #ifdef CONFIG_IPW2200_PROMISCUOUS |
@@ -11978,10 +11977,10 @@ MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); | |||
11978 | #endif /* CONFIG_IPW2200_QOS */ | 11977 | #endif /* CONFIG_IPW2200_QOS */ |
11979 | 11978 | ||
11980 | #ifdef CONFIG_IPW2200_MONITOR | 11979 | #ifdef CONFIG_IPW2200_MONITOR |
11981 | module_param(mode, int, 0444); | 11980 | module_param_named(mode, network_mode, int, 0444); |
11982 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); | 11981 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); |
11983 | #else | 11982 | #else |
11984 | module_param(mode, int, 0444); | 11983 | module_param_named(mode, network_mode, int, 0444); |
11985 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); | 11984 | MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); |
11986 | #endif | 11985 | #endif |
11987 | 11986 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 191718a0c545..a95caa014143 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -149,12 +149,15 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
149 | .ucode_api_min = IWL1000_UCODE_API_MIN, | 149 | .ucode_api_min = IWL1000_UCODE_API_MIN, |
150 | .sku = IWL_SKU_G|IWL_SKU_N, | 150 | .sku = IWL_SKU_G|IWL_SKU_N, |
151 | .ops = &iwl1000_ops, | 151 | .ops = &iwl1000_ops, |
152 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 152 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
153 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 153 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
154 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 154 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
155 | .mod_params = &iwl50_mod_params, | 155 | .mod_params = &iwl50_mod_params, |
156 | .valid_tx_ant = ANT_A, | 156 | .valid_tx_ant = ANT_A, |
157 | .valid_rx_ant = ANT_AB, | 157 | .valid_rx_ant = ANT_AB, |
158 | .need_pll_cfg = true, | 158 | .need_pll_cfg = true, |
159 | .max_ll_items = OTP_MAX_LL_ITEMS_1000, | ||
160 | .shadow_ram_support = false, | ||
161 | .ht_greenfield_support = true, | ||
159 | }; | 162 | }; |
160 | 163 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index ba5ef832d770..e9a685d8e3a1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -349,12 +349,13 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv, | |||
349 | * | 349 | * |
350 | *****************************************************************************/ | 350 | *****************************************************************************/ |
351 | 351 | ||
352 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) | 352 | void iwl3945_hw_rx_statistics(struct iwl_priv *priv, |
353 | struct iwl_rx_mem_buffer *rxb) | ||
353 | { | 354 | { |
354 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 355 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; |
355 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 356 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
356 | (int)sizeof(struct iwl3945_notif_statistics), | 357 | (int)sizeof(struct iwl3945_notif_statistics), |
357 | le32_to_cpu(pkt->len)); | 358 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); |
358 | 359 | ||
359 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); | 360 | memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); |
360 | 361 | ||
@@ -2889,7 +2890,8 @@ static struct iwl_cfg iwl3945_bg_cfg = { | |||
2889 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2890 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2890 | .ops = &iwl3945_ops, | 2891 | .ops = &iwl3945_ops, |
2891 | .mod_params = &iwl3945_mod_params, | 2892 | .mod_params = &iwl3945_mod_params, |
2892 | .use_isr_legacy = true | 2893 | .use_isr_legacy = true, |
2894 | .ht_greenfield_support = false, | ||
2893 | }; | 2895 | }; |
2894 | 2896 | ||
2895 | static struct iwl_cfg iwl3945_abg_cfg = { | 2897 | static struct iwl_cfg iwl3945_abg_cfg = { |
@@ -2902,7 +2904,8 @@ static struct iwl_cfg iwl3945_abg_cfg = { | |||
2902 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, | 2904 | .eeprom_ver = EEPROM_3945_EEPROM_VERSION, |
2903 | .ops = &iwl3945_ops, | 2905 | .ops = &iwl3945_ops, |
2904 | .mod_params = &iwl3945_mod_params, | 2906 | .mod_params = &iwl3945_mod_params, |
2905 | .use_isr_legacy = true | 2907 | .use_isr_legacy = true, |
2908 | .ht_greenfield_support = false, | ||
2906 | }; | 2909 | }; |
2907 | 2910 | ||
2908 | struct pci_device_id iwl3945_hw_card_ids[] = { | 2911 | struct 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 e427a8937ed8..6a13bfbc9d98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2344,7 +2344,8 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2344 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, | 2344 | .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, |
2345 | .ops = &iwl4965_ops, | 2345 | .ops = &iwl4965_ops, |
2346 | .mod_params = &iwl4965_mod_params, | 2346 | .mod_params = &iwl4965_mod_params, |
2347 | .use_isr_legacy = true | 2347 | .use_isr_legacy = true, |
2348 | .ht_greenfield_support = false, | ||
2348 | }; | 2349 | }; |
2349 | 2350 | ||
2350 | /* Module firmware */ | 2351 | /* Module firmware */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 755c184b3ecb..1d539e3b8db1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -494,7 +494,7 @@ static void iwl5000_rx_calib_result(struct iwl_priv *priv, | |||
494 | { | 494 | { |
495 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; | 495 | struct iwl_rx_packet *pkt = (void *)rxb->skb->data; |
496 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; | 496 | struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; |
497 | int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK; | 497 | int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
498 | int index; | 498 | int index; |
499 | 499 | ||
500 | /* reduce the size of the length field itself */ | 500 | /* reduce the size of the length field itself */ |
@@ -1411,6 +1411,7 @@ static void iwl5150_temperature(struct iwl_priv *priv) | |||
1411 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | 1411 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; |
1412 | /* now vt hold the temperature in Kelvin */ | 1412 | /* now vt hold the temperature in Kelvin */ |
1413 | priv->temperature = KELVIN_TO_CELSIUS(vt); | 1413 | priv->temperature = KELVIN_TO_CELSIUS(vt); |
1414 | iwl_tt_handler(priv); | ||
1414 | } | 1415 | } |
1415 | 1416 | ||
1416 | /* Calc max signal level (dBm) among 3 possible receivers */ | 1417 | /* Calc max signal level (dBm) among 3 possible receivers */ |
@@ -1652,6 +1653,7 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1652 | .valid_tx_ant = ANT_ABC, | 1653 | .valid_tx_ant = ANT_ABC, |
1653 | .valid_rx_ant = ANT_ABC, | 1654 | .valid_rx_ant = ANT_ABC, |
1654 | .need_pll_cfg = true, | 1655 | .need_pll_cfg = true, |
1656 | .ht_greenfield_support = true, | ||
1655 | }; | 1657 | }; |
1656 | 1658 | ||
1657 | struct iwl_cfg iwl5100_bg_cfg = { | 1659 | struct iwl_cfg iwl5100_bg_cfg = { |
@@ -1668,6 +1670,7 @@ struct iwl_cfg iwl5100_bg_cfg = { | |||
1668 | .valid_tx_ant = ANT_B, | 1670 | .valid_tx_ant = ANT_B, |
1669 | .valid_rx_ant = ANT_AB, | 1671 | .valid_rx_ant = ANT_AB, |
1670 | .need_pll_cfg = true, | 1672 | .need_pll_cfg = true, |
1673 | .ht_greenfield_support = true, | ||
1671 | }; | 1674 | }; |
1672 | 1675 | ||
1673 | struct iwl_cfg iwl5100_abg_cfg = { | 1676 | struct iwl_cfg iwl5100_abg_cfg = { |
@@ -1684,6 +1687,7 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1684 | .valid_tx_ant = ANT_B, | 1687 | .valid_tx_ant = ANT_B, |
1685 | .valid_rx_ant = ANT_AB, | 1688 | .valid_rx_ant = ANT_AB, |
1686 | .need_pll_cfg = true, | 1689 | .need_pll_cfg = true, |
1690 | .ht_greenfield_support = true, | ||
1687 | }; | 1691 | }; |
1688 | 1692 | ||
1689 | struct iwl_cfg iwl5100_agn_cfg = { | 1693 | struct iwl_cfg iwl5100_agn_cfg = { |
@@ -1700,6 +1704,7 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1700 | .valid_tx_ant = ANT_B, | 1704 | .valid_tx_ant = ANT_B, |
1701 | .valid_rx_ant = ANT_AB, | 1705 | .valid_rx_ant = ANT_AB, |
1702 | .need_pll_cfg = true, | 1706 | .need_pll_cfg = true, |
1707 | .ht_greenfield_support = true, | ||
1703 | }; | 1708 | }; |
1704 | 1709 | ||
1705 | struct iwl_cfg iwl5350_agn_cfg = { | 1710 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1716,6 +1721,7 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1716 | .valid_tx_ant = ANT_ABC, | 1721 | .valid_tx_ant = ANT_ABC, |
1717 | .valid_rx_ant = ANT_ABC, | 1722 | .valid_rx_ant = ANT_ABC, |
1718 | .need_pll_cfg = true, | 1723 | .need_pll_cfg = true, |
1724 | .ht_greenfield_support = true, | ||
1719 | }; | 1725 | }; |
1720 | 1726 | ||
1721 | struct iwl_cfg iwl5150_agn_cfg = { | 1727 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1732,6 +1738,7 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1732 | .valid_tx_ant = ANT_A, | 1738 | .valid_tx_ant = ANT_A, |
1733 | .valid_rx_ant = ANT_AB, | 1739 | .valid_rx_ant = ANT_AB, |
1734 | .need_pll_cfg = true, | 1740 | .need_pll_cfg = true, |
1741 | .ht_greenfield_support = true, | ||
1735 | }; | 1742 | }; |
1736 | 1743 | ||
1737 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 1744 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c3ec6c20cc94..383177db7de7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -161,7 +161,7 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
161 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 161 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
162 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 162 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
163 | .ops = &iwl6000_ops, | 163 | .ops = &iwl6000_ops, |
164 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 164 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
165 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 165 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
166 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 166 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
167 | .mod_params = &iwl50_mod_params, | 167 | .mod_params = &iwl50_mod_params, |
@@ -169,6 +169,9 @@ struct iwl_cfg iwl6000h_2agn_cfg = { | |||
169 | .valid_rx_ant = ANT_AB, | 169 | .valid_rx_ant = ANT_AB, |
170 | .need_pll_cfg = false, | 170 | .need_pll_cfg = false, |
171 | .pa_type = IWL_PA_HYBRID, | 171 | .pa_type = IWL_PA_HYBRID, |
172 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
173 | .shadow_ram_support = true, | ||
174 | .ht_greenfield_support = true, | ||
172 | }; | 175 | }; |
173 | 176 | ||
174 | /* | 177 | /* |
@@ -181,7 +184,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
181 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 184 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
182 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 185 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
183 | .ops = &iwl6000_ops, | 186 | .ops = &iwl6000_ops, |
184 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 187 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
185 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 188 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
186 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 189 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
187 | .mod_params = &iwl50_mod_params, | 190 | .mod_params = &iwl50_mod_params, |
@@ -189,6 +192,9 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
189 | .valid_rx_ant = ANT_BC, | 192 | .valid_rx_ant = ANT_BC, |
190 | .need_pll_cfg = false, | 193 | .need_pll_cfg = false, |
191 | .pa_type = IWL_PA_INTERNAL, | 194 | .pa_type = IWL_PA_INTERNAL, |
195 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
196 | .shadow_ram_support = true, | ||
197 | .ht_greenfield_support = true, | ||
192 | }; | 198 | }; |
193 | 199 | ||
194 | struct iwl_cfg iwl6050_2agn_cfg = { | 200 | struct iwl_cfg iwl6050_2agn_cfg = { |
@@ -198,7 +204,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
198 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 204 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
199 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 205 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
200 | .ops = &iwl6000_ops, | 206 | .ops = &iwl6000_ops, |
201 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 207 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
202 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 208 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
203 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 209 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
204 | .mod_params = &iwl50_mod_params, | 210 | .mod_params = &iwl50_mod_params, |
@@ -206,6 +212,9 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
206 | .valid_rx_ant = ANT_AB, | 212 | .valid_rx_ant = ANT_AB, |
207 | .need_pll_cfg = false, | 213 | .need_pll_cfg = false, |
208 | .pa_type = IWL_PA_SYSTEM, | 214 | .pa_type = IWL_PA_SYSTEM, |
215 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
216 | .shadow_ram_support = true, | ||
217 | .ht_greenfield_support = true, | ||
209 | }; | 218 | }; |
210 | 219 | ||
211 | struct iwl_cfg iwl6000_3agn_cfg = { | 220 | struct iwl_cfg iwl6000_3agn_cfg = { |
@@ -215,7 +224,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
215 | .ucode_api_min = IWL6000_UCODE_API_MIN, | 224 | .ucode_api_min = IWL6000_UCODE_API_MIN, |
216 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 225 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
217 | .ops = &iwl6000_ops, | 226 | .ops = &iwl6000_ops, |
218 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 227 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
219 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 228 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
220 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 229 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
221 | .mod_params = &iwl50_mod_params, | 230 | .mod_params = &iwl50_mod_params, |
@@ -223,6 +232,9 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
223 | .valid_rx_ant = ANT_ABC, | 232 | .valid_rx_ant = ANT_ABC, |
224 | .need_pll_cfg = false, | 233 | .need_pll_cfg = false, |
225 | .pa_type = IWL_PA_SYSTEM, | 234 | .pa_type = IWL_PA_SYSTEM, |
235 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
236 | .shadow_ram_support = true, | ||
237 | .ht_greenfield_support = true, | ||
226 | }; | 238 | }; |
227 | 239 | ||
228 | struct iwl_cfg iwl6050_3agn_cfg = { | 240 | struct iwl_cfg iwl6050_3agn_cfg = { |
@@ -232,7 +244,7 @@ struct iwl_cfg iwl6050_3agn_cfg = { | |||
232 | .ucode_api_min = IWL6050_UCODE_API_MIN, | 244 | .ucode_api_min = IWL6050_UCODE_API_MIN, |
233 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | 245 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, |
234 | .ops = &iwl6000_ops, | 246 | .ops = &iwl6000_ops, |
235 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 247 | .eeprom_size = OTP_LOW_IMAGE_SIZE, |
236 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 248 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
237 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | 249 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, |
238 | .mod_params = &iwl50_mod_params, | 250 | .mod_params = &iwl50_mod_params, |
@@ -240,6 +252,9 @@ struct iwl_cfg iwl6050_3agn_cfg = { | |||
240 | .valid_rx_ant = ANT_ABC, | 252 | .valid_rx_ant = ANT_ABC, |
241 | .need_pll_cfg = false, | 253 | .need_pll_cfg = false, |
242 | .pa_type = IWL_PA_SYSTEM, | 254 | .pa_type = IWL_PA_SYSTEM, |
255 | .max_ll_items = OTP_MAX_LL_ITEMS_6x00, | ||
256 | .shadow_ram_support = true, | ||
257 | .ht_greenfield_support = true, | ||
243 | }; | 258 | }; |
244 | 259 | ||
245 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 260 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 21331552ff2c..fee110de5c6a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -332,6 +332,9 @@ static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, | |||
332 | } else | 332 | } else |
333 | return MAX_TID_COUNT; | 333 | return MAX_TID_COUNT; |
334 | 334 | ||
335 | if (unlikely(tid >= TID_MAX_LOAD_COUNT)) | ||
336 | return MAX_TID_COUNT; | ||
337 | |||
335 | tl = &lq_data->load[tid]; | 338 | tl = &lq_data->load[tid]; |
336 | 339 | ||
337 | curr_time -= curr_time % TID_ROUND_VALUE; | 340 | curr_time -= curr_time % TID_ROUND_VALUE; |
@@ -654,19 +657,15 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, | |||
654 | return 1; | 657 | return 1; |
655 | } | 658 | } |
656 | 659 | ||
657 | /* in 4965 we don't use greenfield at all */ | 660 | /** |
658 | static inline u8 rs_use_green(struct iwl_priv *priv, | 661 | * Green-field mode is valid if the station supports it and |
659 | struct ieee80211_conf *conf) | 662 | * there are no non-GF stations present in the BSS. |
663 | */ | ||
664 | static inline u8 rs_use_green(struct ieee80211_sta *sta, | ||
665 | struct iwl_ht_info *ht_conf) | ||
660 | { | 666 | { |
661 | u8 is_green; | 667 | return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && |
662 | 668 | !(ht_conf->non_GF_STA_present); | |
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; | ||
670 | } | 669 | } |
671 | 670 | ||
672 | /** | 671 | /** |
@@ -1222,18 +1221,6 @@ static int rs_switch_to_mimo2(struct iwl_priv *priv, | |||
1222 | else | 1221 | else |
1223 | tbl->is_ht40 = 0; | 1222 | tbl->is_ht40 = 0; |
1224 | 1223 | ||
1225 | /* FIXME: - don't toggle SGI here | ||
1226 | if (tbl->is_ht40) { | ||
1227 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) | ||
1228 | tbl->is_SGI = 1; | ||
1229 | else | ||
1230 | tbl->is_SGI = 0; | ||
1231 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) | ||
1232 | tbl->is_SGI = 1; | ||
1233 | else | ||
1234 | tbl->is_SGI = 0; | ||
1235 | */ | ||
1236 | |||
1237 | rs_set_expected_tpt_table(lq_sta, tbl); | 1224 | rs_set_expected_tpt_table(lq_sta, tbl); |
1238 | 1225 | ||
1239 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); | 1226 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); |
@@ -1288,18 +1275,6 @@ static int rs_switch_to_mimo3(struct iwl_priv *priv, | |||
1288 | else | 1275 | else |
1289 | tbl->is_ht40 = 0; | 1276 | tbl->is_ht40 = 0; |
1290 | 1277 | ||
1291 | /* FIXME: - don't toggle SGI here | ||
1292 | if (tbl->is_ht40) { | ||
1293 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) | ||
1294 | tbl->is_SGI = 1; | ||
1295 | else | ||
1296 | tbl->is_SGI = 0; | ||
1297 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) | ||
1298 | tbl->is_SGI = 1; | ||
1299 | else | ||
1300 | tbl->is_SGI = 0; | ||
1301 | */ | ||
1302 | |||
1303 | rs_set_expected_tpt_table(lq_sta, tbl); | 1278 | rs_set_expected_tpt_table(lq_sta, tbl); |
1304 | 1279 | ||
1305 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); | 1280 | rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); |
@@ -1347,18 +1322,6 @@ static int rs_switch_to_siso(struct iwl_priv *priv, | |||
1347 | else | 1322 | else |
1348 | tbl->is_ht40 = 0; | 1323 | tbl->is_ht40 = 0; |
1349 | 1324 | ||
1350 | /* FIXME: - don't toggle SGI here | ||
1351 | if (tbl->is_ht40) { | ||
1352 | if (priv->current_ht_config.sgf & HT_SHORT_GI_40MHZ_ONLY) | ||
1353 | tbl->is_SGI = 1; | ||
1354 | else | ||
1355 | tbl->is_SGI = 0; | ||
1356 | } else if (priv->current_ht_config.sgf & HT_SHORT_GI_20MHZ_ONLY) | ||
1357 | tbl->is_SGI = 1; | ||
1358 | else | ||
1359 | tbl->is_SGI = 0; | ||
1360 | */ | ||
1361 | |||
1362 | if (is_green) | 1325 | if (is_green) |
1363 | tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ | 1326 | tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ |
1364 | 1327 | ||
@@ -1527,6 +1490,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1527 | struct iwl_scale_tbl_info *search_tbl = | 1490 | struct iwl_scale_tbl_info *search_tbl = |
1528 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1491 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1529 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1492 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1493 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
1530 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1494 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1531 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1495 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1532 | u8 start_action = tbl->action; | 1496 | u8 start_action = tbl->action; |
@@ -1586,13 +1550,11 @@ static int rs_move_siso_to_other(struct iwl_priv *priv, | |||
1586 | goto out; | 1550 | goto out; |
1587 | break; | 1551 | break; |
1588 | case IWL_SISO_SWITCH_GI: | 1552 | case IWL_SISO_SWITCH_GI: |
1589 | if (!tbl->is_ht40 && | 1553 | if (!tbl->is_ht40 && !(ht_cap->cap & |
1590 | !(priv->current_ht_config.sgf & | 1554 | IEEE80211_HT_CAP_SGI_20)) |
1591 | HT_SHORT_GI_20MHZ)) | ||
1592 | break; | 1555 | break; |
1593 | if (tbl->is_ht40 && | 1556 | if (tbl->is_ht40 && !(ht_cap->cap & |
1594 | !(priv->current_ht_config.sgf & | 1557 | IEEE80211_HT_CAP_SGI_40)) |
1595 | HT_SHORT_GI_40MHZ)) | ||
1596 | break; | 1558 | break; |
1597 | 1559 | ||
1598 | IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n"); | 1560 | IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n"); |
@@ -1666,6 +1628,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1666 | struct iwl_scale_tbl_info *search_tbl = | 1628 | struct iwl_scale_tbl_info *search_tbl = |
1667 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1629 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1668 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1630 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1631 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
1669 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1632 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1670 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1633 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1671 | u8 start_action = tbl->action; | 1634 | u8 start_action = tbl->action; |
@@ -1726,13 +1689,11 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv, | |||
1726 | break; | 1689 | break; |
1727 | 1690 | ||
1728 | case IWL_MIMO2_SWITCH_GI: | 1691 | case IWL_MIMO2_SWITCH_GI: |
1729 | if (!tbl->is_ht40 && | 1692 | if (!tbl->is_ht40 && !(ht_cap->cap & |
1730 | !(priv->current_ht_config.sgf & | 1693 | IEEE80211_HT_CAP_SGI_20)) |
1731 | HT_SHORT_GI_20MHZ)) | ||
1732 | break; | 1694 | break; |
1733 | if (tbl->is_ht40 && | 1695 | if (tbl->is_ht40 && !(ht_cap->cap & |
1734 | !(priv->current_ht_config.sgf & | 1696 | IEEE80211_HT_CAP_SGI_40)) |
1735 | HT_SHORT_GI_40MHZ)) | ||
1736 | break; | 1697 | break; |
1737 | 1698 | ||
1738 | IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); | 1699 | IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); |
@@ -1808,6 +1769,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1808 | struct iwl_scale_tbl_info *search_tbl = | 1769 | struct iwl_scale_tbl_info *search_tbl = |
1809 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); | 1770 | &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); |
1810 | struct iwl_rate_scale_data *window = &(tbl->win[index]); | 1771 | struct iwl_rate_scale_data *window = &(tbl->win[index]); |
1772 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
1811 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - | 1773 | u32 sz = (sizeof(struct iwl_scale_tbl_info) - |
1812 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); | 1774 | (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); |
1813 | u8 start_action = tbl->action; | 1775 | u8 start_action = tbl->action; |
@@ -1890,13 +1852,11 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv, | |||
1890 | break; | 1852 | break; |
1891 | 1853 | ||
1892 | case IWL_MIMO3_SWITCH_GI: | 1854 | case IWL_MIMO3_SWITCH_GI: |
1893 | if (!tbl->is_ht40 && | 1855 | if (!tbl->is_ht40 && !(ht_cap->cap & |
1894 | !(priv->current_ht_config.sgf & | 1856 | IEEE80211_HT_CAP_SGI_20)) |
1895 | HT_SHORT_GI_20MHZ)) | ||
1896 | break; | 1857 | break; |
1897 | if (tbl->is_ht40 && | 1858 | if (tbl->is_ht40 && !(ht_cap->cap & |
1898 | !(priv->current_ht_config.sgf & | 1859 | IEEE80211_HT_CAP_SGI_40)) |
1899 | HT_SHORT_GI_40MHZ)) | ||
1900 | break; | 1860 | break; |
1901 | 1861 | ||
1902 | IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); | 1862 | IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); |
@@ -2108,7 +2068,7 @@ static void rs_rate_scale_perform(struct iwl_priv *priv, | |||
2108 | if (is_legacy(tbl->lq_type)) | 2068 | if (is_legacy(tbl->lq_type)) |
2109 | lq_sta->is_green = 0; | 2069 | lq_sta->is_green = 0; |
2110 | else | 2070 | else |
2111 | lq_sta->is_green = rs_use_green(priv, conf); | 2071 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); |
2112 | is_green = lq_sta->is_green; | 2072 | is_green = lq_sta->is_green; |
2113 | 2073 | ||
2114 | /* current tx rate */ | 2074 | /* current tx rate */ |
@@ -2466,7 +2426,7 @@ static void rs_initialize_lq(struct iwl_priv *priv, | |||
2466 | int rate_idx; | 2426 | int rate_idx; |
2467 | int i; | 2427 | int i; |
2468 | u32 rate; | 2428 | u32 rate; |
2469 | u8 use_green = rs_use_green(priv, conf); | 2429 | u8 use_green = rs_use_green(sta, &priv->current_ht_config); |
2470 | u8 active_tbl = 0; | 2430 | u8 active_tbl = 0; |
2471 | u8 valid_tx_ant; | 2431 | u8 valid_tx_ant; |
2472 | 2432 | ||
@@ -2519,6 +2479,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2519 | struct ieee80211_supported_band *sband = txrc->sband; | 2479 | struct ieee80211_supported_band *sband = txrc->sband; |
2520 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2480 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2521 | struct ieee80211_conf *conf = &priv->hw->conf; | 2481 | struct ieee80211_conf *conf = &priv->hw->conf; |
2482 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2522 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 2483 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
2523 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 2484 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
2524 | struct iwl_lq_sta *lq_sta = priv_sta; | 2485 | struct iwl_lq_sta *lq_sta = priv_sta; |
@@ -2551,7 +2512,7 @@ static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, | |||
2551 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", | 2512 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", |
2552 | hdr->addr1); | 2513 | hdr->addr1); |
2553 | sta_id = iwl_add_station(priv, hdr->addr1, | 2514 | sta_id = iwl_add_station(priv, hdr->addr1, |
2554 | false, CMD_ASYNC, NULL); | 2515 | false, CMD_ASYNC, ht_cap); |
2555 | } | 2516 | } |
2556 | if ((sta_id != IWL_INVALID_STATION)) { | 2517 | if ((sta_id != IWL_INVALID_STATION)) { |
2557 | lq_sta->lq.sta_id = sta_id; | 2518 | lq_sta->lq.sta_id = sta_id; |
@@ -2620,6 +2581,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2620 | int i, j; | 2581 | int i, j; |
2621 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2582 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2622 | struct ieee80211_conf *conf = &priv->hw->conf; | 2583 | struct ieee80211_conf *conf = &priv->hw->conf; |
2584 | struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; | ||
2623 | struct iwl_lq_sta *lq_sta = priv_sta; | 2585 | struct iwl_lq_sta *lq_sta = priv_sta; |
2624 | u16 mask_bit = 0; | 2586 | u16 mask_bit = 0; |
2625 | int count; | 2587 | int count; |
@@ -2648,7 +2610,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2648 | if (sta_id == IWL_INVALID_STATION) { | 2610 | if (sta_id == IWL_INVALID_STATION) { |
2649 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); | 2611 | IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); |
2650 | sta_id = iwl_add_station(priv, sta->addr, false, | 2612 | sta_id = iwl_add_station(priv, sta->addr, false, |
2651 | CMD_ASYNC, NULL); | 2613 | CMD_ASYNC, ht_cap); |
2652 | } | 2614 | } |
2653 | if ((sta_id != IWL_INVALID_STATION)) { | 2615 | if ((sta_id != IWL_INVALID_STATION)) { |
2654 | lq_sta->lq.sta_id = sta_id; | 2616 | lq_sta->lq.sta_id = sta_id; |
@@ -2661,7 +2623,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2661 | lq_sta->is_dup = 0; | 2623 | lq_sta->is_dup = 0; |
2662 | lq_sta->max_rate_idx = -1; | 2624 | lq_sta->max_rate_idx = -1; |
2663 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; | 2625 | lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; |
2664 | lq_sta->is_green = rs_use_green(priv, conf); | 2626 | lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); |
2665 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2627 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); |
2666 | lq_sta->active_rate_basic = priv->active_rate_basic; | 2628 | lq_sta->active_rate_basic = priv->active_rate_basic; |
2667 | lq_sta->band = priv->band; | 2629 | lq_sta->band = priv->band; |
@@ -2669,19 +2631,19 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2669 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), | 2631 | * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), |
2670 | * supp_rates[] does not; shift to convert format, force 9 MBits off. | 2632 | * supp_rates[] does not; shift to convert format, force 9 MBits off. |
2671 | */ | 2633 | */ |
2672 | lq_sta->active_siso_rate = sta->ht_cap.mcs.rx_mask[0] << 1; | 2634 | lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; |
2673 | lq_sta->active_siso_rate |= sta->ht_cap.mcs.rx_mask[0] & 0x1; | 2635 | lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; |
2674 | lq_sta->active_siso_rate &= ~((u16)0x2); | 2636 | lq_sta->active_siso_rate &= ~((u16)0x2); |
2675 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; | 2637 | lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; |
2676 | 2638 | ||
2677 | /* Same here */ | 2639 | /* Same here */ |
2678 | lq_sta->active_mimo2_rate = sta->ht_cap.mcs.rx_mask[1] << 1; | 2640 | lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; |
2679 | lq_sta->active_mimo2_rate |= sta->ht_cap.mcs.rx_mask[1] & 0x1; | 2641 | lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; |
2680 | lq_sta->active_mimo2_rate &= ~((u16)0x2); | 2642 | lq_sta->active_mimo2_rate &= ~((u16)0x2); |
2681 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; | 2643 | lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; |
2682 | 2644 | ||
2683 | lq_sta->active_mimo3_rate = sta->ht_cap.mcs.rx_mask[2] << 1; | 2645 | lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1; |
2684 | lq_sta->active_mimo3_rate |= sta->ht_cap.mcs.rx_mask[2] & 0x1; | 2646 | lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1; |
2685 | lq_sta->active_mimo3_rate &= ~((u16)0x2); | 2647 | lq_sta->active_mimo3_rate &= ~((u16)0x2); |
2686 | lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; | 2648 | lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; |
2687 | 2649 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 68d7719071f7..f4303843ff9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1156,6 +1156,7 @@ struct iwl_wep_cmd { | |||
1156 | #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) | 1156 | #define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) |
1157 | #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) | 1157 | #define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) |
1158 | #define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0) | 1158 | #define RX_RES_PHY_FLAGS_ANTENNA_MSK cpu_to_le16(0xf0) |
1159 | #define RX_RES_PHY_FLAGS_ANTENNA_POS 4 | ||
1159 | 1160 | ||
1160 | #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) | 1161 | #define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) |
1161 | #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) | 1162 | #define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) |
@@ -3481,7 +3482,7 @@ struct iwl_wimax_coex_cmd { | |||
3481 | *****************************************************************************/ | 3482 | *****************************************************************************/ |
3482 | 3483 | ||
3483 | struct iwl_rx_packet { | 3484 | struct iwl_rx_packet { |
3484 | __le32 len; | 3485 | __le32 len_n_flags; |
3485 | struct iwl_cmd_header hdr; | 3486 | struct iwl_cmd_header hdr; |
3486 | union { | 3487 | union { |
3487 | struct iwl3945_rx_frame rx_frame; | 3488 | struct iwl3945_rx_frame rx_frame; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index af735128333a..f1f6dabd8fbd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -394,7 +394,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
394 | 394 | ||
395 | ht_info->ht_supported = true; | 395 | ht_info->ht_supported = true; |
396 | 396 | ||
397 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 397 | if (priv->cfg->ht_greenfield_support) |
398 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | ||
398 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 399 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
399 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & | 400 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & |
400 | (WLAN_HT_CAP_SM_PS_DISABLED << 2)); | 401 | (WLAN_HT_CAP_SM_PS_DISABLED << 2)); |
@@ -1513,7 +1514,7 @@ EXPORT_SYMBOL(iwl_irq_handle_error); | |||
1513 | void iwl_configure_filter(struct ieee80211_hw *hw, | 1514 | void iwl_configure_filter(struct ieee80211_hw *hw, |
1514 | unsigned int changed_flags, | 1515 | unsigned int changed_flags, |
1515 | unsigned int *total_flags, | 1516 | unsigned int *total_flags, |
1516 | int mc_count, struct dev_addr_list *mc_list) | 1517 | u64 multicast) |
1517 | { | 1518 | { |
1518 | struct iwl_priv *priv = hw->priv; | 1519 | struct iwl_priv *priv = hw->priv; |
1519 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; | 1520 | __le32 *filter_flags = &priv->staging_rxon.filter_flags; |
@@ -1579,6 +1580,12 @@ int iwl_setup_mac(struct iwl_priv *priv) | |||
1579 | /* Firmware does not support this */ | 1580 | /* Firmware does not support this */ |
1580 | hw->wiphy->disable_beacon_hints = true; | 1581 | hw->wiphy->disable_beacon_hints = true; |
1581 | 1582 | ||
1583 | /* | ||
1584 | * For now, disable PS by default because it affects | ||
1585 | * RX performance significantly. | ||
1586 | */ | ||
1587 | hw->wiphy->ps_default = false; | ||
1588 | |||
1582 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 1589 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
1583 | /* we create the 802.11 header and a zero-length SSID element */ | 1590 | /* we create the 802.11 header and a zero-length SSID element */ |
1584 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; | 1591 | hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; |
@@ -2293,10 +2300,11 @@ void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, | |||
2293 | struct iwl_rx_mem_buffer *rxb) | 2300 | struct iwl_rx_mem_buffer *rxb) |
2294 | { | 2301 | { |
2295 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 2302 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; |
2303 | u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
2296 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " | 2304 | IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " |
2297 | "notification for %s:\n", | 2305 | "notification for %s:\n", len, |
2298 | le32_to_cpu(pkt->len), get_cmd_string(pkt->hdr.cmd)); | 2306 | get_cmd_string(pkt->hdr.cmd)); |
2299 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, le32_to_cpu(pkt->len)); | 2307 | iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); |
2300 | } | 2308 | } |
2301 | EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); | 2309 | EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); |
2302 | 2310 | ||
@@ -2391,39 +2399,10 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
2391 | } | 2399 | } |
2392 | ht_conf = &sta->ht_cap; | 2400 | ht_conf = &sta->ht_cap; |
2393 | 2401 | ||
2394 | if (ht_conf->cap & IEEE80211_HT_CAP_SGI_20) | ||
2395 | iwl_conf->sgf |= HT_SHORT_GI_20MHZ; | ||
2396 | if (ht_conf->cap & IEEE80211_HT_CAP_SGI_40) | ||
2397 | iwl_conf->sgf |= HT_SHORT_GI_40MHZ; | ||
2398 | |||
2399 | iwl_conf->is_green_field = !!(ht_conf->cap & IEEE80211_HT_CAP_GRN_FLD); | ||
2400 | iwl_conf->max_amsdu_size = | ||
2401 | !!(ht_conf->cap & IEEE80211_HT_CAP_MAX_AMSDU); | ||
2402 | |||
2403 | iwl_conf->supported_chan_width = | ||
2404 | !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); | ||
2405 | |||
2406 | /* | ||
2407 | * XXX: The HT configuration needs to be moved into iwl_mac_config() | ||
2408 | * to be done there correctly. | ||
2409 | */ | ||
2410 | |||
2411 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
2412 | if (conf_is_ht40_minus(&priv->hw->conf)) | ||
2413 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
2414 | else if (conf_is_ht40_plus(&priv->hw->conf)) | ||
2415 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
2416 | |||
2417 | /* If no above or below channel supplied disable HT40 channel */ | ||
2418 | if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && | ||
2419 | iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
2420 | iwl_conf->supported_chan_width = 0; | ||
2421 | |||
2422 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); | 2402 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); |
2423 | 2403 | ||
2424 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); | 2404 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); |
2425 | 2405 | ||
2426 | iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; | ||
2427 | iwl_conf->ht_protection = | 2406 | iwl_conf->ht_protection = |
2428 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | 2407 | bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
2429 | iwl_conf->non_GF_STA_present = | 2408 | iwl_conf->non_GF_STA_present = |
@@ -2736,6 +2715,7 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2736 | struct iwl_priv *priv = hw->priv; | 2715 | struct iwl_priv *priv = hw->priv; |
2737 | const struct iwl_channel_info *ch_info; | 2716 | const struct iwl_channel_info *ch_info; |
2738 | struct ieee80211_conf *conf = &hw->conf; | 2717 | struct ieee80211_conf *conf = &hw->conf; |
2718 | struct iwl_ht_info *ht_conf = &priv->current_ht_config; | ||
2739 | unsigned long flags = 0; | 2719 | unsigned long flags = 0; |
2740 | int ret = 0; | 2720 | int ret = 0; |
2741 | u16 ch; | 2721 | u16 ch; |
@@ -2777,10 +2757,32 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) | |||
2777 | goto set_ch_out; | 2757 | goto set_ch_out; |
2778 | } | 2758 | } |
2779 | 2759 | ||
2780 | priv->current_ht_config.is_ht = conf_is_ht(conf); | ||
2781 | |||
2782 | spin_lock_irqsave(&priv->lock, flags); | 2760 | spin_lock_irqsave(&priv->lock, flags); |
2783 | 2761 | ||
2762 | /* Configure HT40 channels */ | ||
2763 | ht_conf->is_ht = conf_is_ht(conf); | ||
2764 | if (ht_conf->is_ht) { | ||
2765 | if (conf_is_ht40_minus(conf)) { | ||
2766 | ht_conf->extension_chan_offset = | ||
2767 | IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
2768 | ht_conf->supported_chan_width = | ||
2769 | IWL_CHANNEL_WIDTH_40MHZ; | ||
2770 | } else if (conf_is_ht40_plus(conf)) { | ||
2771 | ht_conf->extension_chan_offset = | ||
2772 | IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
2773 | ht_conf->supported_chan_width = | ||
2774 | IWL_CHANNEL_WIDTH_40MHZ; | ||
2775 | } else { | ||
2776 | ht_conf->extension_chan_offset = | ||
2777 | IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
2778 | ht_conf->supported_chan_width = | ||
2779 | IWL_CHANNEL_WIDTH_20MHZ; | ||
2780 | } | ||
2781 | } else | ||
2782 | ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ; | ||
2783 | /* Default to no protection. Protection mode will later be set | ||
2784 | * from BSS config in iwl_ht_conf */ | ||
2785 | ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | ||
2784 | 2786 | ||
2785 | /* if we are switching from ht to 2.4 clear flags | 2787 | /* if we are switching from ht to 2.4 clear flags |
2786 | * from any ht related info since 2.4 does not | 2788 | * from any ht related info since 2.4 does not |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 32750f4f1ce1..62d90364b61d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -209,6 +209,8 @@ struct iwl_mod_params { | |||
209 | * @ucode_api_max: Highest version of uCode API supported by driver. | 209 | * @ucode_api_max: Highest version of uCode API supported by driver. |
210 | * @ucode_api_min: Lowest version of uCode API supported by driver. | 210 | * @ucode_api_min: Lowest version of uCode API supported by driver. |
211 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier | 211 | * @pa_type: used by 6000 series only to identify the type of Power Amplifier |
212 | * @max_ll_items: max number of OTP blocks | ||
213 | * @shadow_ram_support: shadow support for OTP memory | ||
212 | * | 214 | * |
213 | * We enable the driver to be backward compatible wrt API version. The | 215 | * We enable the driver to be backward compatible wrt API version. The |
214 | * driver specifies which APIs it supports (with @ucode_api_max being the | 216 | * driver specifies which APIs it supports (with @ucode_api_max being the |
@@ -247,6 +249,9 @@ struct iwl_cfg { | |||
247 | bool need_pll_cfg; | 249 | bool need_pll_cfg; |
248 | bool use_isr_legacy; | 250 | bool use_isr_legacy; |
249 | enum iwl_pa_type pa_type; | 251 | enum iwl_pa_type pa_type; |
252 | const u16 max_ll_items; | ||
253 | const bool shadow_ram_support; | ||
254 | const bool ht_greenfield_support; | ||
250 | }; | 255 | }; |
251 | 256 | ||
252 | /*************************** | 257 | /*************************** |
@@ -277,8 +282,7 @@ int iwl_set_decrypted_flag(struct iwl_priv *priv, | |||
277 | void iwl_irq_handle_error(struct iwl_priv *priv); | 282 | void iwl_irq_handle_error(struct iwl_priv *priv); |
278 | void iwl_configure_filter(struct ieee80211_hw *hw, | 283 | void iwl_configure_filter(struct ieee80211_hw *hw, |
279 | unsigned int changed_flags, | 284 | unsigned int changed_flags, |
280 | unsigned int *total_flags, | 285 | unsigned int *total_flags, u64 multicast); |
281 | int mc_count, struct dev_addr_list *mc_list); | ||
282 | int iwl_hw_nic_init(struct iwl_priv *priv); | 286 | int iwl_hw_nic_init(struct iwl_priv *priv); |
283 | int iwl_setup_mac(struct iwl_priv *priv); | 287 | int iwl_setup_mac(struct iwl_priv *priv); |
284 | int iwl_set_hw_params(struct iwl_priv *priv); | 288 | int iwl_set_hw_params(struct iwl_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index b96c3c9e92a9..0178734499f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -507,15 +507,9 @@ struct iwl_ht_info { | |||
507 | u8 is_ht; | 507 | u8 is_ht; |
508 | u8 supported_chan_width; | 508 | u8 supported_chan_width; |
509 | u8 sm_ps; | 509 | u8 sm_ps; |
510 | u8 is_green_field; | ||
511 | u8 sgf; /* HT_SHORT_GI_* short guard interval */ | ||
512 | u8 max_amsdu_size; | ||
513 | u8 ampdu_factor; | ||
514 | u8 mpdu_density; | ||
515 | struct ieee80211_mcs_info mcs; | 510 | struct ieee80211_mcs_info mcs; |
516 | /* BSS related data */ | 511 | /* BSS related data */ |
517 | u8 extension_chan_offset; | 512 | u8 extension_chan_offset; |
518 | u8 tx_chan_width; | ||
519 | u8 ht_protection; | 513 | u8 ht_protection; |
520 | u8 non_GF_STA_present; | 514 | u8 non_GF_STA_present; |
521 | }; | 515 | }; |
@@ -732,9 +726,6 @@ struct iwl_dma_ptr { | |||
732 | size_t size; | 726 | size_t size; |
733 | }; | 727 | }; |
734 | 728 | ||
735 | #define HT_SHORT_GI_20MHZ (1 << 0) | ||
736 | #define HT_SHORT_GI_40MHZ (1 << 1) | ||
737 | |||
738 | #define IWL_CHANNEL_WIDTH_20MHZ 0 | 729 | #define IWL_CHANNEL_WIDTH_20MHZ 0 |
739 | #define IWL_CHANNEL_WIDTH_40MHZ 1 | 730 | #define IWL_CHANNEL_WIDTH_40MHZ 1 |
740 | 731 | ||
@@ -888,6 +879,17 @@ enum iwl_nvm_type { | |||
888 | NVM_DEVICE_TYPE_OTP, | 879 | NVM_DEVICE_TYPE_OTP, |
889 | }; | 880 | }; |
890 | 881 | ||
882 | /* | ||
883 | * Two types of OTP memory access modes | ||
884 | * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, | ||
885 | * based on physical memory addressing | ||
886 | * IWL_OTP_ACCESS_RELATIVE - relative address mode, | ||
887 | * based on logical memory addressing | ||
888 | */ | ||
889 | enum iwl_access_mode { | ||
890 | IWL_OTP_ACCESS_ABSOLUTE, | ||
891 | IWL_OTP_ACCESS_RELATIVE, | ||
892 | }; | ||
891 | 893 | ||
892 | /** | 894 | /** |
893 | * enum iwl_pa_type - Power Amplifier type | 895 | * enum iwl_pa_type - Power Amplifier type |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 78c4a324a3b5..01b95e89009a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -152,6 +152,19 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) | |||
152 | } | 152 | } |
153 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); | 153 | EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); |
154 | 154 | ||
155 | static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) | ||
156 | { | ||
157 | u32 otpgp; | ||
158 | |||
159 | otpgp = iwl_read32(priv, CSR_OTP_GP_REG); | ||
160 | if (mode == IWL_OTP_ACCESS_ABSOLUTE) | ||
161 | iwl_clear_bit(priv, CSR_OTP_GP_REG, | ||
162 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
163 | else | ||
164 | iwl_set_bit(priv, CSR_OTP_GP_REG, | ||
165 | CSR_OTP_GP_REG_OTP_ACCESS_MODE); | ||
166 | } | ||
167 | |||
155 | static int iwlcore_get_nvm_type(struct iwl_priv *priv) | 168 | static int iwlcore_get_nvm_type(struct iwl_priv *priv) |
156 | { | 169 | { |
157 | u32 otpgp; | 170 | u32 otpgp; |
@@ -252,6 +265,124 @@ static int iwl_init_otp_access(struct iwl_priv *priv) | |||
252 | return ret; | 265 | return ret; |
253 | } | 266 | } |
254 | 267 | ||
268 | static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, u16 *eeprom_data) | ||
269 | { | ||
270 | int ret = 0; | ||
271 | u32 r; | ||
272 | u32 otpgp; | ||
273 | |||
274 | _iwl_write32(priv, CSR_EEPROM_REG, | ||
275 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
276 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | ||
277 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
278 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
279 | if (ret < 0) { | ||
280 | IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); | ||
281 | return ret; | ||
282 | } | ||
283 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); | ||
284 | /* check for ECC errors: */ | ||
285 | otpgp = iwl_read32(priv, CSR_OTP_GP_REG); | ||
286 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | ||
287 | /* stop in this case */ | ||
288 | /* set the uncorrectable OTP ECC bit for acknowledgement */ | ||
289 | iwl_set_bit(priv, CSR_OTP_GP_REG, | ||
290 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | ||
291 | IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); | ||
292 | return -EINVAL; | ||
293 | } | ||
294 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | ||
295 | /* continue in this case */ | ||
296 | /* set the correctable OTP ECC bit for acknowledgement */ | ||
297 | iwl_set_bit(priv, CSR_OTP_GP_REG, | ||
298 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
299 | IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); | ||
300 | } | ||
301 | *eeprom_data = le16_to_cpu((__force __le16)(r >> 16)); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * iwl_is_otp_empty: check for empty OTP | ||
307 | */ | ||
308 | static bool iwl_is_otp_empty(struct iwl_priv *priv) | ||
309 | { | ||
310 | u16 next_link_addr = 0, link_value; | ||
311 | bool is_empty = false; | ||
312 | |||
313 | /* locate the beginning of OTP link list */ | ||
314 | if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) { | ||
315 | if (!link_value) { | ||
316 | IWL_ERR(priv, "OTP is empty\n"); | ||
317 | is_empty = true; | ||
318 | } | ||
319 | } else { | ||
320 | IWL_ERR(priv, "Unable to read first block of OTP list.\n"); | ||
321 | is_empty = true; | ||
322 | } | ||
323 | |||
324 | return is_empty; | ||
325 | } | ||
326 | |||
327 | |||
328 | /* | ||
329 | * iwl_find_otp_image: find EEPROM image in OTP | ||
330 | * finding the OTP block that contains the EEPROM image. | ||
331 | * the last valid block on the link list (the block _before_ the last block) | ||
332 | * is the block we should read and used to configure the device. | ||
333 | * If all the available OTP blocks are full, the last block will be the block | ||
334 | * we should read and used to configure the device. | ||
335 | * only perform this operation if shadow RAM is disabled | ||
336 | */ | ||
337 | static int iwl_find_otp_image(struct iwl_priv *priv, | ||
338 | u16 *validblockaddr) | ||
339 | { | ||
340 | u16 next_link_addr = 0, link_value = 0, valid_addr; | ||
341 | int ret = 0; | ||
342 | int usedblocks = 0; | ||
343 | |||
344 | /* set addressing mode to absolute to traverse the link list */ | ||
345 | iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE); | ||
346 | |||
347 | /* checking for empty OTP or error */ | ||
348 | if (iwl_is_otp_empty(priv)) | ||
349 | return -EINVAL; | ||
350 | |||
351 | /* | ||
352 | * start traverse link list | ||
353 | * until reach the max number of OTP blocks | ||
354 | * different devices have different number of OTP blocks | ||
355 | */ | ||
356 | do { | ||
357 | /* save current valid block address | ||
358 | * check for more block on the link list | ||
359 | */ | ||
360 | valid_addr = next_link_addr; | ||
361 | next_link_addr = link_value; | ||
362 | IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", | ||
363 | usedblocks, next_link_addr); | ||
364 | if (iwl_read_otp_word(priv, next_link_addr, &link_value)) | ||
365 | return -EINVAL; | ||
366 | if (!link_value) { | ||
367 | /* | ||
368 | * reach the end of link list, | ||
369 | * set address point to the starting address | ||
370 | * of the image | ||
371 | */ | ||
372 | goto done; | ||
373 | } | ||
374 | /* more in the link list, continue */ | ||
375 | usedblocks++; | ||
376 | } while (usedblocks < priv->cfg->max_ll_items); | ||
377 | /* OTP full, use last block */ | ||
378 | IWL_DEBUG_INFO(priv, "OTP is full, use last block\n"); | ||
379 | done: | ||
380 | *validblockaddr = valid_addr; | ||
381 | /* skip first 2 bytes (link list pointer) */ | ||
382 | *validblockaddr += 2; | ||
383 | return ret; | ||
384 | } | ||
385 | |||
255 | /** | 386 | /** |
256 | * iwl_eeprom_init - read EEPROM contents | 387 | * iwl_eeprom_init - read EEPROM contents |
257 | * | 388 | * |
@@ -266,15 +397,14 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
266 | int sz; | 397 | int sz; |
267 | int ret; | 398 | int ret; |
268 | u16 addr; | 399 | u16 addr; |
269 | u32 otpgp; | 400 | u16 validblockaddr = 0; |
401 | u16 cache_addr = 0; | ||
270 | 402 | ||
271 | priv->nvm_device_type = iwlcore_get_nvm_type(priv); | 403 | priv->nvm_device_type = iwlcore_get_nvm_type(priv); |
272 | if (priv->nvm_device_type == -ENOENT) | 404 | if (priv->nvm_device_type == -ENOENT) |
273 | return -ENOENT; | 405 | return -ENOENT; |
274 | /* allocate eeprom */ | 406 | /* allocate eeprom */ |
275 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) | 407 | IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size); |
276 | priv->cfg->eeprom_size = | ||
277 | OTP_BLOCK_SIZE * OTP_LOWER_BLOCKS_TOTAL; | ||
278 | sz = priv->cfg->eeprom_size; | 408 | sz = priv->cfg->eeprom_size; |
279 | priv->eeprom = kzalloc(sz, GFP_KERNEL); | 409 | priv->eeprom = kzalloc(sz, GFP_KERNEL); |
280 | if (!priv->eeprom) { | 410 | if (!priv->eeprom) { |
@@ -302,46 +432,31 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
302 | if (ret) { | 432 | if (ret) { |
303 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); | 433 | IWL_ERR(priv, "Failed to initialize OTP access.\n"); |
304 | ret = -ENOENT; | 434 | ret = -ENOENT; |
305 | goto err; | 435 | goto done; |
306 | } | 436 | } |
307 | _iwl_write32(priv, CSR_EEPROM_GP, | 437 | _iwl_write32(priv, CSR_EEPROM_GP, |
308 | iwl_read32(priv, CSR_EEPROM_GP) & | 438 | iwl_read32(priv, CSR_EEPROM_GP) & |
309 | ~CSR_EEPROM_GP_IF_OWNER_MSK); | 439 | ~CSR_EEPROM_GP_IF_OWNER_MSK); |
310 | /* clear */ | 440 | |
311 | _iwl_write32(priv, CSR_OTP_GP_REG, | 441 | iwl_set_bit(priv, CSR_OTP_GP_REG, |
312 | iwl_read32(priv, CSR_OTP_GP_REG) | | ||
313 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | | 442 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | |
314 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); | 443 | CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); |
315 | 444 | /* traversing the linked list if no shadow ram supported */ | |
316 | for (addr = 0; addr < sz; addr += sizeof(u16)) { | 445 | if (!priv->cfg->shadow_ram_support) { |
317 | u32 r; | 446 | if (iwl_find_otp_image(priv, &validblockaddr)) { |
318 | 447 | ret = -ENOENT; | |
319 | _iwl_write32(priv, CSR_EEPROM_REG, | ||
320 | CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); | ||
321 | |||
322 | ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, | ||
323 | CSR_EEPROM_REG_READ_VALID_MSK, | ||
324 | IWL_EEPROM_ACCESS_TIMEOUT); | ||
325 | if (ret < 0) { | ||
326 | IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); | ||
327 | goto done; | 448 | goto done; |
328 | } | 449 | } |
329 | r = _iwl_read_direct32(priv, CSR_EEPROM_REG); | 450 | } |
330 | /* check for ECC errors: */ | 451 | for (addr = validblockaddr; addr < validblockaddr + sz; |
331 | otpgp = iwl_read32(priv, CSR_OTP_GP_REG); | 452 | addr += sizeof(u16)) { |
332 | if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { | 453 | u16 eeprom_data; |
333 | /* stop in this case */ | 454 | |
334 | IWL_ERR(priv, "Uncorrectable OTP ECC error, Abort OTP read\n"); | 455 | ret = iwl_read_otp_word(priv, addr, &eeprom_data); |
456 | if (ret) | ||
335 | goto done; | 457 | goto done; |
336 | } | 458 | e[cache_addr / 2] = eeprom_data; |
337 | if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { | 459 | cache_addr += sizeof(u16); |
338 | /* continue in this case */ | ||
339 | _iwl_write32(priv, CSR_OTP_GP_REG, | ||
340 | iwl_read32(priv, CSR_OTP_GP_REG) | | ||
341 | CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); | ||
342 | IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); | ||
343 | } | ||
344 | e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); | ||
345 | } | 460 | } |
346 | } else { | 461 | } else { |
347 | /* eeprom is an array of 16bit values */ | 462 | /* eeprom is an array of 16bit values */ |
@@ -484,14 +599,14 @@ static void iwl_init_band_reference(const struct iwl_priv *priv, | |||
484 | ? # x " " : "") | 599 | ? # x " " : "") |
485 | 600 | ||
486 | /** | 601 | /** |
487 | * iwl_set_ht40_chan_info - Copy ht40 channel info into driver's priv. | 602 | * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. |
488 | * | 603 | * |
489 | * Does not set up a command, or touch hardware. | 604 | * Does not set up a command, or touch hardware. |
490 | */ | 605 | */ |
491 | static int iwl_set_ht40_chan_info(struct iwl_priv *priv, | 606 | static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, |
492 | enum ieee80211_band band, u16 channel, | 607 | enum ieee80211_band band, u16 channel, |
493 | const struct iwl_eeprom_channel *eeprom_ch, | 608 | const struct iwl_eeprom_channel *eeprom_ch, |
494 | u8 ht40_extension_channel) | 609 | u8 clear_ht40_extension_channel) |
495 | { | 610 | { |
496 | struct iwl_channel_info *ch_info; | 611 | struct iwl_channel_info *ch_info; |
497 | 612 | ||
@@ -523,7 +638,7 @@ static int iwl_set_ht40_chan_info(struct iwl_priv *priv, | |||
523 | ch_info->ht40_min_power = 0; | 638 | ch_info->ht40_min_power = 0; |
524 | ch_info->ht40_scan_power = eeprom_ch->max_power_avg; | 639 | ch_info->ht40_scan_power = eeprom_ch->max_power_avg; |
525 | ch_info->ht40_flags = eeprom_ch->flags; | 640 | ch_info->ht40_flags = eeprom_ch->flags; |
526 | ch_info->ht40_extension_channel = ht40_extension_channel; | 641 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; |
527 | 642 | ||
528 | return 0; | 643 | return 0; |
529 | } | 644 | } |
@@ -592,8 +707,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
592 | /* First write that ht40 is not enabled, and then enable | 707 | /* First write that ht40 is not enabled, and then enable |
593 | * one by one */ | 708 | * one by one */ |
594 | ch_info->ht40_extension_channel = | 709 | ch_info->ht40_extension_channel = |
595 | (IEEE80211_CHAN_NO_HT40PLUS | | 710 | IEEE80211_CHAN_NO_HT40; |
596 | IEEE80211_CHAN_NO_HT40MINUS); | ||
597 | 711 | ||
598 | if (!(is_channel_valid(ch_info))) { | 712 | if (!(is_channel_valid(ch_info))) { |
599 | IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " | 713 | IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " |
@@ -652,7 +766,6 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
652 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ | 766 | /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ |
653 | for (band = 6; band <= 7; band++) { | 767 | for (band = 6; band <= 7; band++) { |
654 | enum ieee80211_band ieeeband; | 768 | enum ieee80211_band ieeeband; |
655 | u8 ht40_extension_chan; | ||
656 | 769 | ||
657 | iwl_init_band_reference(priv, band, &eeprom_ch_count, | 770 | iwl_init_band_reference(priv, band, &eeprom_ch_count, |
658 | &eeprom_ch_info, &eeprom_ch_index); | 771 | &eeprom_ch_info, &eeprom_ch_index); |
@@ -663,28 +776,17 @@ int iwl_init_channel_map(struct iwl_priv *priv) | |||
663 | 776 | ||
664 | /* Loop through each band adding each of the channels */ | 777 | /* Loop through each band adding each of the channels */ |
665 | for (ch = 0; ch < eeprom_ch_count; ch++) { | 778 | for (ch = 0; ch < eeprom_ch_count; ch++) { |
666 | |||
667 | if ((band == 6) && | ||
668 | ((eeprom_ch_index[ch] == 5) || | ||
669 | (eeprom_ch_index[ch] == 6) || | ||
670 | (eeprom_ch_index[ch] == 7))) | ||
671 | /* both are allowed: above and below */ | ||
672 | ht40_extension_chan = 0; | ||
673 | else | ||
674 | ht40_extension_chan = | ||
675 | IEEE80211_CHAN_NO_HT40MINUS; | ||
676 | |||
677 | /* Set up driver's info for lower half */ | 779 | /* Set up driver's info for lower half */ |
678 | iwl_set_ht40_chan_info(priv, ieeeband, | 780 | iwl_mod_ht40_chan_info(priv, ieeeband, |
679 | eeprom_ch_index[ch], | 781 | eeprom_ch_index[ch], |
680 | &(eeprom_ch_info[ch]), | 782 | &eeprom_ch_info[ch], |
681 | ht40_extension_chan); | 783 | IEEE80211_CHAN_NO_HT40PLUS); |
682 | 784 | ||
683 | /* Set up driver's info for upper half */ | 785 | /* Set up driver's info for upper half */ |
684 | iwl_set_ht40_chan_info(priv, ieeeband, | 786 | iwl_mod_ht40_chan_info(priv, ieeeband, |
685 | (eeprom_ch_index[ch] + 4), | 787 | eeprom_ch_index[ch] + 4, |
686 | &(eeprom_ch_info[ch]), | 788 | &eeprom_ch_info[ch], |
687 | IEEE80211_CHAN_NO_HT40PLUS); | 789 | IEEE80211_CHAN_NO_HT40MINUS); |
688 | } | 790 | } |
689 | } | 791 | } |
690 | 792 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 05d4fc4451dc..ca7920a8f52f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -180,8 +180,14 @@ struct iwl_eeprom_channel { | |||
180 | #define EEPROM_5050_EEPROM_VERSION (0x21E) | 180 | #define EEPROM_5050_EEPROM_VERSION (0x21E) |
181 | 181 | ||
182 | /* OTP */ | 182 | /* OTP */ |
183 | #define OTP_LOWER_BLOCKS_TOTAL (3) | 183 | /* lower blocks contain EEPROM image and calibration data */ |
184 | #define OTP_BLOCK_SIZE (0x400) | 184 | #define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ |
185 | /* high blocks contain PAPD data */ | ||
186 | #define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */ | ||
187 | #define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */ | ||
188 | #define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ | ||
189 | #define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ | ||
190 | #define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ | ||
185 | 191 | ||
186 | /* 2.4 GHz */ | 192 | /* 2.4 GHz */ |
187 | extern const u8 iwl_eeprom_band_1[14]; | 193 | extern const u8 iwl_eeprom_band_1[14]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 43b2fce4cbf0..353d9a2ddbca 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -539,7 +539,8 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
539 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 539 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; |
540 | 540 | ||
541 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 541 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
542 | (int)sizeof(priv->statistics), pkt->len); | 542 | (int)sizeof(priv->statistics), |
543 | le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); | ||
543 | 544 | ||
544 | change = ((priv->statistics.general.temperature != | 545 | change = ((priv->statistics.general.temperature != |
545 | pkt->u.stats.general.temperature) || | 546 | pkt->u.stats.general.temperature) || |
@@ -853,61 +854,12 @@ static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) | |||
853 | } | 854 | } |
854 | 855 | ||
855 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | 856 | static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, |
856 | int include_phy, | 857 | struct ieee80211_hdr *hdr, |
857 | struct iwl_rx_mem_buffer *rxb, | 858 | u16 len, |
858 | struct ieee80211_rx_status *stats) | 859 | u32 ampdu_status, |
860 | struct iwl_rx_mem_buffer *rxb, | ||
861 | struct ieee80211_rx_status *stats) | ||
859 | { | 862 | { |
860 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | ||
861 | struct iwl_rx_phy_res *rx_start = (include_phy) ? | ||
862 | (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : NULL; | ||
863 | struct ieee80211_hdr *hdr; | ||
864 | u16 len; | ||
865 | __le32 *rx_end; | ||
866 | unsigned int skblen; | ||
867 | u32 ampdu_status; | ||
868 | u32 ampdu_status_legacy; | ||
869 | |||
870 | if (!include_phy && priv->last_phy_res[0]) | ||
871 | rx_start = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
872 | |||
873 | if (!rx_start) { | ||
874 | IWL_ERR(priv, "MPDU frame without a PHY data\n"); | ||
875 | return; | ||
876 | } | ||
877 | if (include_phy) { | ||
878 | hdr = (struct ieee80211_hdr *)((u8 *) &rx_start[1] + | ||
879 | rx_start->cfg_phy_cnt); | ||
880 | |||
881 | len = le16_to_cpu(rx_start->byte_count); | ||
882 | |||
883 | rx_end = (__le32 *)((u8 *) &pkt->u.raw[0] + | ||
884 | sizeof(struct iwl_rx_phy_res) + | ||
885 | rx_start->cfg_phy_cnt + len); | ||
886 | |||
887 | } else { | ||
888 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
889 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
890 | |||
891 | hdr = (struct ieee80211_hdr *)(pkt->u.raw + | ||
892 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
893 | len = le16_to_cpu(amsdu->byte_count); | ||
894 | rx_start->byte_count = amsdu->byte_count; | ||
895 | rx_end = (__le32 *) (((u8 *) hdr) + len); | ||
896 | } | ||
897 | |||
898 | ampdu_status = le32_to_cpu(*rx_end); | ||
899 | skblen = ((u8 *) rx_end - (u8 *) &pkt->u.raw[0]) + sizeof(u32); | ||
900 | |||
901 | if (!include_phy) { | ||
902 | /* New status scheme, need to translate */ | ||
903 | ampdu_status_legacy = ampdu_status; | ||
904 | ampdu_status = iwl_translate_rx_status(priv, ampdu_status); | ||
905 | } | ||
906 | |||
907 | /* start from MAC */ | ||
908 | skb_reserve(rxb->skb, (void *)hdr - (void *)pkt); | ||
909 | skb_put(rxb->skb, len); /* end where data ends */ | ||
910 | |||
911 | /* We only process data packets if the interface is open */ | 863 | /* We only process data packets if the interface is open */ |
912 | if (unlikely(!priv->is_open)) { | 864 | if (unlikely(!priv->is_open)) { |
913 | IWL_DEBUG_DROP_LIMIT(priv, | 865 | IWL_DEBUG_DROP_LIMIT(priv, |
@@ -915,13 +867,15 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, | |||
915 | return; | 867 | return; |
916 | } | 868 | } |
917 | 869 | ||
918 | hdr = (struct ieee80211_hdr *)rxb->skb->data; | 870 | /* In case of HW accelerated crypto and bad decryption, drop */ |
919 | |||
920 | /* in case of HW accelerated crypto and bad decryption, drop */ | ||
921 | if (!priv->cfg->mod_params->sw_crypto && | 871 | if (!priv->cfg->mod_params->sw_crypto && |
922 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) | 872 | iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) |
923 | return; | 873 | return; |
924 | 874 | ||
875 | /* Resize SKB from mac header to end of packet */ | ||
876 | skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data); | ||
877 | skb_put(rxb->skb, len); | ||
878 | |||
925 | iwl_update_stats(priv, false, hdr->frame_control, len); | 879 | iwl_update_stats(priv, false, hdr->frame_control, len); |
926 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); | 880 | memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); |
927 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); | 881 | ieee80211_rx_irqsafe(priv->hw, rxb->skb); |
@@ -955,25 +909,66 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
955 | struct ieee80211_hdr *header; | 909 | struct ieee80211_hdr *header; |
956 | struct ieee80211_rx_status rx_status; | 910 | struct ieee80211_rx_status rx_status; |
957 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; | 911 | struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; |
958 | /* Use phy data (Rx signal strength, etc.) contained within | 912 | struct iwl_rx_phy_res *phy_res; |
959 | * this rx packet for legacy frames, | 913 | __le32 rx_pkt_status; |
960 | * or phy data cached from REPLY_RX_PHY_CMD for HT frames. */ | 914 | struct iwl4965_rx_mpdu_res_start *amsdu; |
961 | int include_phy = (pkt->hdr.cmd == REPLY_RX); | 915 | u32 len; |
962 | struct iwl_rx_phy_res *rx_start = (include_phy) ? | 916 | u32 ampdu_status; |
963 | (struct iwl_rx_phy_res *)&(pkt->u.raw[0]) : | ||
964 | (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
965 | __le32 *rx_end; | ||
966 | unsigned int len = 0; | ||
967 | u16 fc; | 917 | u16 fc; |
968 | u8 network_packet; | ||
969 | 918 | ||
970 | rx_status.mactime = le64_to_cpu(rx_start->timestamp); | 919 | /** |
920 | * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. | ||
921 | * REPLY_RX: physical layer info is in this buffer | ||
922 | * REPLY_RX_MPDU_CMD: physical layer info was sent in separate | ||
923 | * command and cached in priv->last_phy_res | ||
924 | * | ||
925 | * Here we set up local variables depending on which command is | ||
926 | * received. | ||
927 | */ | ||
928 | if (pkt->hdr.cmd == REPLY_RX) { | ||
929 | phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; | ||
930 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) | ||
931 | + phy_res->cfg_phy_cnt); | ||
932 | |||
933 | len = le16_to_cpu(phy_res->byte_count); | ||
934 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + | ||
935 | phy_res->cfg_phy_cnt + len); | ||
936 | ampdu_status = le32_to_cpu(rx_pkt_status); | ||
937 | } else { | ||
938 | if (!priv->last_phy_res[0]) { | ||
939 | IWL_ERR(priv, "MPDU frame without cached PHY data\n"); | ||
940 | return; | ||
941 | } | ||
942 | phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; | ||
943 | amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
944 | header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); | ||
945 | len = le16_to_cpu(amsdu->byte_count); | ||
946 | rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); | ||
947 | ampdu_status = iwl_translate_rx_status(priv, | ||
948 | le32_to_cpu(rx_pkt_status)); | ||
949 | } | ||
950 | |||
951 | if ((unlikely(phy_res->cfg_phy_cnt > 20))) { | ||
952 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
953 | phy_res->cfg_phy_cnt); | ||
954 | return; | ||
955 | } | ||
956 | |||
957 | if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
958 | !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
959 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
960 | le32_to_cpu(rx_pkt_status)); | ||
961 | return; | ||
962 | } | ||
963 | |||
964 | /* rx_status carries information about the packet to mac80211 */ | ||
965 | rx_status.mactime = le64_to_cpu(phy_res->timestamp); | ||
971 | rx_status.freq = | 966 | rx_status.freq = |
972 | ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); | 967 | ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); |
973 | rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? | 968 | rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? |
974 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; | 969 | IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; |
975 | rx_status.rate_idx = | 970 | rx_status.rate_idx = |
976 | iwl_hwrate_to_plcp_idx(le32_to_cpu(rx_start->rate_n_flags)); | 971 | iwl_hwrate_to_plcp_idx(le32_to_cpu(phy_res->rate_n_flags)); |
977 | if (rx_status.band == IEEE80211_BAND_5GHZ) | 972 | if (rx_status.band == IEEE80211_BAND_5GHZ) |
978 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; | 973 | rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; |
979 | 974 | ||
@@ -983,54 +978,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
983 | * this W/A doesn't propagate it to the mac80211 */ | 978 | * this W/A doesn't propagate it to the mac80211 */ |
984 | /*rx_status.flag |= RX_FLAG_TSFT;*/ | 979 | /*rx_status.flag |= RX_FLAG_TSFT;*/ |
985 | 980 | ||
986 | if ((unlikely(rx_start->cfg_phy_cnt > 20))) { | 981 | priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); |
987 | IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", | ||
988 | rx_start->cfg_phy_cnt); | ||
989 | return; | ||
990 | } | ||
991 | |||
992 | if (!include_phy) { | ||
993 | if (priv->last_phy_res[0]) | ||
994 | rx_start = (struct iwl_rx_phy_res *) | ||
995 | &priv->last_phy_res[1]; | ||
996 | else | ||
997 | rx_start = NULL; | ||
998 | } | ||
999 | |||
1000 | if (!rx_start) { | ||
1001 | IWL_ERR(priv, "MPDU frame without a PHY data\n"); | ||
1002 | return; | ||
1003 | } | ||
1004 | |||
1005 | if (include_phy) { | ||
1006 | header = (struct ieee80211_hdr *)((u8 *) &rx_start[1] | ||
1007 | + rx_start->cfg_phy_cnt); | ||
1008 | |||
1009 | len = le16_to_cpu(rx_start->byte_count); | ||
1010 | rx_end = (__le32 *)(pkt->u.raw + rx_start->cfg_phy_cnt + | ||
1011 | sizeof(struct iwl_rx_phy_res) + len); | ||
1012 | } else { | ||
1013 | struct iwl4965_rx_mpdu_res_start *amsdu = | ||
1014 | (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; | ||
1015 | |||
1016 | header = (void *)(pkt->u.raw + | ||
1017 | sizeof(struct iwl4965_rx_mpdu_res_start)); | ||
1018 | len = le16_to_cpu(amsdu->byte_count); | ||
1019 | rx_end = (__le32 *) (pkt->u.raw + | ||
1020 | sizeof(struct iwl4965_rx_mpdu_res_start) + len); | ||
1021 | } | ||
1022 | |||
1023 | if (!(*rx_end & RX_RES_STATUS_NO_CRC32_ERROR) || | ||
1024 | !(*rx_end & RX_RES_STATUS_NO_RXE_OVERFLOW)) { | ||
1025 | IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", | ||
1026 | le32_to_cpu(*rx_end)); | ||
1027 | return; | ||
1028 | } | ||
1029 | |||
1030 | priv->ucode_beacon_time = le32_to_cpu(rx_start->beacon_time_stamp); | ||
1031 | 982 | ||
1032 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ | 983 | /* Find max signal strength (dBm) among 3 antenna/receiver chains */ |
1033 | rx_status.signal = iwl_calc_rssi(priv, rx_start); | 984 | rx_status.signal = iwl_calc_rssi(priv, phy_res); |
1034 | 985 | ||
1035 | /* Meaningful noise values are available only from beacon statistics, | 986 | /* Meaningful noise values are available only from beacon statistics, |
1036 | * which are gathered only when associated, and indicate noise | 987 | * which are gathered only when associated, and indicate noise |
@@ -1050,10 +1001,10 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1050 | if (!iwl_is_associated(priv)) | 1001 | if (!iwl_is_associated(priv)) |
1051 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; | 1002 | priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; |
1052 | 1003 | ||
1053 | /* Set "1" to report good data frames in groups of 100 */ | ||
1054 | #ifdef CONFIG_IWLWIFI_DEBUG | 1004 | #ifdef CONFIG_IWLWIFI_DEBUG |
1005 | /* Set "1" to report good data frames in groups of 100 */ | ||
1055 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) | 1006 | if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) |
1056 | iwl_dbg_report_frame(priv, rx_start, len, header, 1); | 1007 | iwl_dbg_report_frame(priv, phy_res, len, header, 1); |
1057 | #endif | 1008 | #endif |
1058 | iwl_dbg_log_rx_data_frame(priv, len, header); | 1009 | iwl_dbg_log_rx_data_frame(priv, len, header); |
1059 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", | 1010 | IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", |
@@ -1073,18 +1024,18 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1073 | * new 802.11n radiotap field "RX chains" that is defined | 1024 | * new 802.11n radiotap field "RX chains" that is defined |
1074 | * as a bitmask. | 1025 | * as a bitmask. |
1075 | */ | 1026 | */ |
1076 | rx_status.antenna = le16_to_cpu(rx_start->phy_flags & | 1027 | rx_status.antenna = |
1077 | RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; | 1028 | le16_to_cpu(phy_res->phy_flags & RX_RES_PHY_FLAGS_ANTENNA_MSK) |
1029 | >> RX_RES_PHY_FLAGS_ANTENNA_POS; | ||
1078 | 1030 | ||
1079 | /* set the preamble flag if appropriate */ | 1031 | /* set the preamble flag if appropriate */ |
1080 | if (rx_start->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) | 1032 | if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) |
1081 | rx_status.flag |= RX_FLAG_SHORTPRE; | 1033 | rx_status.flag |= RX_FLAG_SHORTPRE; |
1082 | 1034 | ||
1083 | network_packet = iwl_is_network_packet(priv, header); | 1035 | if (iwl_is_network_packet(priv, header)) { |
1084 | if (network_packet) { | ||
1085 | priv->last_rx_rssi = rx_status.signal; | 1036 | priv->last_rx_rssi = rx_status.signal; |
1086 | priv->last_beacon_time = priv->ucode_beacon_time; | 1037 | priv->last_beacon_time = priv->ucode_beacon_time; |
1087 | priv->last_tsf = le64_to_cpu(rx_start->timestamp); | 1038 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); |
1088 | } | 1039 | } |
1089 | 1040 | ||
1090 | fc = le16_to_cpu(header->frame_control); | 1041 | fc = le16_to_cpu(header->frame_control); |
@@ -1096,8 +1047,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1096 | header->addr2); | 1047 | header->addr2); |
1097 | /* fall through */ | 1048 | /* fall through */ |
1098 | default: | 1049 | default: |
1099 | iwl_pass_packet_to_mac80211(priv, include_phy, rxb, | 1050 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1100 | &rx_status); | 1051 | rxb, &rx_status); |
1101 | break; | 1052 | break; |
1102 | 1053 | ||
1103 | } | 1054 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 9b76bd41f214..7686fc72eb89 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -745,6 +745,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
745 | if (ieee80211_is_data_qos(fc)) { | 745 | if (ieee80211_is_data_qos(fc)) { |
746 | qc = ieee80211_get_qos_ctl(hdr); | 746 | qc = ieee80211_get_qos_ctl(hdr); |
747 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 747 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
748 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
749 | goto drop_unlock; | ||
748 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | 750 | seq_number = priv->stations[sta_id].tid[tid].seq_number; |
749 | seq_number &= IEEE80211_SCTL_SEQ; | 751 | seq_number &= IEEE80211_SCTL_SEQ; |
750 | hdr->seq_ctrl = hdr->seq_ctrl & | 752 | hdr->seq_ctrl = hdr->seq_ctrl & |
@@ -1238,6 +1240,9 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1238 | return -EINVAL; | 1240 | return -EINVAL; |
1239 | } | 1241 | } |
1240 | 1242 | ||
1243 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
1244 | return -EINVAL; | ||
1245 | |||
1241 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) | 1246 | if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) |
1242 | tx_fifo_id = default_tid_to_tx_fifo[tid]; | 1247 | tx_fifo_id = default_tid_to_tx_fifo[tid]; |
1243 | else | 1248 | else |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index e617411d0c5e..f339c5bd1fde 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -544,6 +544,8 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
544 | if (ieee80211_is_data_qos(fc)) { | 544 | if (ieee80211_is_data_qos(fc)) { |
545 | qc = ieee80211_get_qos_ctl(hdr); | 545 | qc = ieee80211_get_qos_ctl(hdr); |
546 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 546 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
547 | if (unlikely(tid >= MAX_TID_COUNT)) | ||
548 | goto drop; | ||
547 | seq_number = priv->stations[sta_id].tid[tid].seq_number & | 549 | seq_number = priv->stations[sta_id].tid[tid].seq_number & |
548 | IEEE80211_SCTL_SEQ; | 550 | IEEE80211_SCTL_SEQ; |
549 | hdr->seq_ctrl = cpu_to_le16(seq_number) | | 551 | hdr->seq_ctrl = cpu_to_le16(seq_number) | |
diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c index 385b50f4b105..81f86ef26990 100644 --- a/drivers/net/wireless/libertas/assoc.c +++ b/drivers/net/wireless/libertas/assoc.c | |||
@@ -45,9 +45,14 @@ static int get_common_rates(struct lbs_private *priv, | |||
45 | u8 *card_rates = lbs_bg_rates; | 45 | u8 *card_rates = lbs_bg_rates; |
46 | size_t num_card_rates = sizeof(lbs_bg_rates); | 46 | size_t num_card_rates = sizeof(lbs_bg_rates); |
47 | int ret = 0, i, j; | 47 | int ret = 0, i, j; |
48 | u8 tmp[30]; | 48 | u8 *tmp; |
49 | size_t tmp_size = 0; | 49 | size_t tmp_size = 0; |
50 | 50 | ||
51 | tmp = kzalloc((ARRAY_SIZE(lbs_bg_rates) - 1) * (*rates_size - 1), | ||
52 | GFP_KERNEL); | ||
53 | if (!tmp) | ||
54 | return -1; | ||
55 | |||
51 | /* For each rate in card_rates that exists in rate1, copy to tmp */ | 56 | /* For each rate in card_rates that exists in rate1, copy to tmp */ |
52 | for (i = 0; card_rates[i] && (i < num_card_rates); i++) { | 57 | for (i = 0; card_rates[i] && (i < num_card_rates); i++) { |
53 | for (j = 0; rates[j] && (j < *rates_size); j++) { | 58 | for (j = 0; rates[j] && (j < *rates_size); j++) { |
@@ -77,6 +82,7 @@ done: | |||
77 | memset(rates, 0, *rates_size); | 82 | memset(rates, 0, *rates_size); |
78 | *rates_size = min_t(int, tmp_size, *rates_size); | 83 | *rates_size = min_t(int, tmp_size, *rates_size); |
79 | memcpy(rates, tmp, *rates_size); | 84 | memcpy(rates, tmp, *rates_size); |
85 | kfree(tmp); | ||
80 | return ret; | 86 | return ret; |
81 | } | 87 | } |
82 | 88 | ||
diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c index 4872345a2f61..019431d2f8a9 100644 --- a/drivers/net/wireless/libertas_tf/main.c +++ b/drivers/net/wireless/libertas_tf/main.c | |||
@@ -366,15 +366,35 @@ static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) | |||
366 | return 0; | 366 | return 0; |
367 | } | 367 | } |
368 | 368 | ||
369 | static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw, | ||
370 | int mc_count, struct dev_addr_list *mclist) | ||
371 | { | ||
372 | struct lbtf_private *priv = hw->priv; | ||
373 | int i; | ||
374 | |||
375 | if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) | ||
376 | return mc_count; | ||
377 | |||
378 | priv->nr_of_multicastmacaddr = mc_count; | ||
379 | for (i = 0; i < mc_count; i++) { | ||
380 | if (!mclist) | ||
381 | break; | ||
382 | memcpy(&priv->multicastlist[i], mclist->da_addr, | ||
383 | ETH_ALEN); | ||
384 | mclist = mclist->next; | ||
385 | } | ||
386 | |||
387 | return mc_count; | ||
388 | } | ||
389 | |||
369 | #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) | 390 | #define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) |
370 | static void lbtf_op_configure_filter(struct ieee80211_hw *hw, | 391 | static void lbtf_op_configure_filter(struct ieee80211_hw *hw, |
371 | unsigned int changed_flags, | 392 | unsigned int changed_flags, |
372 | unsigned int *new_flags, | 393 | unsigned int *new_flags, |
373 | int mc_count, struct dev_mc_list *mclist) | 394 | u64 multicast) |
374 | { | 395 | { |
375 | struct lbtf_private *priv = hw->priv; | 396 | struct lbtf_private *priv = hw->priv; |
376 | int old_mac_control = priv->mac_control; | 397 | int old_mac_control = priv->mac_control; |
377 | int i; | ||
378 | changed_flags &= SUPPORTED_FIF_FLAGS; | 398 | changed_flags &= SUPPORTED_FIF_FLAGS; |
379 | *new_flags &= SUPPORTED_FIF_FLAGS; | 399 | *new_flags &= SUPPORTED_FIF_FLAGS; |
380 | 400 | ||
@@ -386,20 +406,12 @@ static void lbtf_op_configure_filter(struct ieee80211_hw *hw, | |||
386 | else | 406 | else |
387 | priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; | 407 | priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; |
388 | if (*new_flags & (FIF_ALLMULTI) || | 408 | if (*new_flags & (FIF_ALLMULTI) || |
389 | mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) { | 409 | multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) { |
390 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | 410 | priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
391 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; | 411 | priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; |
392 | } else if (mc_count) { | 412 | } else if (multicast) { |
393 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; | 413 | priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; |
394 | priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; | 414 | priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; |
395 | priv->nr_of_multicastmacaddr = mc_count; | ||
396 | for (i = 0; i < mc_count; i++) { | ||
397 | if (!mclist) | ||
398 | break; | ||
399 | memcpy(&priv->multicastlist[i], mclist->da_addr, | ||
400 | ETH_ALEN); | ||
401 | mclist = mclist->next; | ||
402 | } | ||
403 | lbtf_cmd_set_mac_multicast_addr(priv); | 415 | lbtf_cmd_set_mac_multicast_addr(priv); |
404 | } else { | 416 | } else { |
405 | priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | | 417 | priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | |
@@ -461,6 +473,7 @@ static const struct ieee80211_ops lbtf_ops = { | |||
461 | .add_interface = lbtf_op_add_interface, | 473 | .add_interface = lbtf_op_add_interface, |
462 | .remove_interface = lbtf_op_remove_interface, | 474 | .remove_interface = lbtf_op_remove_interface, |
463 | .config = lbtf_op_config, | 475 | .config = lbtf_op_config, |
476 | .prepare_multicast = lbtf_op_prepare_multicast, | ||
464 | .configure_filter = lbtf_op_configure_filter, | 477 | .configure_filter = lbtf_op_configure_filter, |
465 | .bss_info_changed = lbtf_op_bss_info_changed, | 478 | .bss_info_changed = lbtf_op_bss_info_changed, |
466 | }; | 479 | }; |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 930f5c7da4a6..6f6cd43592c8 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -582,9 +582,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
582 | 582 | ||
583 | static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, | 583 | static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, |
584 | unsigned int changed_flags, | 584 | unsigned int changed_flags, |
585 | unsigned int *total_flags, | 585 | unsigned int *total_flags,u64 multicast) |
586 | int mc_count, | ||
587 | struct dev_addr_list *mc_list) | ||
588 | { | 586 | { |
589 | struct mac80211_hwsim_data *data = hw->priv; | 587 | struct mac80211_hwsim_data *data = hw->priv; |
590 | 588 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 8a6d3afe4122..41a708ce8730 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/net/wireless/mwl8k.c driver for Marvell TOPDOG 802.11 Wireless cards | 2 | * drivers/net/wireless/mwl8k.c |
3 | * Driver for Marvell TOPDOG 802.11 Wireless cards | ||
3 | * | 4 | * |
4 | * Copyright (C) 2008 Marvell Semiconductor Inc. | 5 | * Copyright (C) 2008-2009 Marvell Semiconductor Inc. |
5 | * | 6 | * |
6 | * This file is licensed under the terms of the GNU General Public | 7 | * This file is licensed under the terms of the GNU General Public |
7 | * License version 2. This program is licensed "as is" without any | 8 | * License version 2. This program is licensed "as is" without any |
@@ -24,7 +25,7 @@ | |||
24 | 25 | ||
25 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" | 26 | #define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" |
26 | #define MWL8K_NAME KBUILD_MODNAME | 27 | #define MWL8K_NAME KBUILD_MODNAME |
27 | #define MWL8K_VERSION "0.9.1" | 28 | #define MWL8K_VERSION "0.10" |
28 | 29 | ||
29 | MODULE_DESCRIPTION(MWL8K_DESC); | 30 | MODULE_DESCRIPTION(MWL8K_DESC); |
30 | MODULE_VERSION(MWL8K_VERSION); | 31 | MODULE_VERSION(MWL8K_VERSION); |
@@ -38,16 +39,14 @@ static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = { | |||
38 | }; | 39 | }; |
39 | MODULE_DEVICE_TABLE(pci, mwl8k_table); | 40 | MODULE_DEVICE_TABLE(pci, mwl8k_table); |
40 | 41 | ||
41 | #define IEEE80211_ADDR_LEN ETH_ALEN | ||
42 | |||
43 | /* Register definitions */ | 42 | /* Register definitions */ |
44 | #define MWL8K_HIU_GEN_PTR 0x00000c10 | 43 | #define MWL8K_HIU_GEN_PTR 0x00000c10 |
45 | #define MWL8K_MODE_STA 0x0000005a | 44 | #define MWL8K_MODE_STA 0x0000005a |
46 | #define MWL8K_MODE_AP 0x000000a5 | 45 | #define MWL8K_MODE_AP 0x000000a5 |
47 | #define MWL8K_HIU_INT_CODE 0x00000c14 | 46 | #define MWL8K_HIU_INT_CODE 0x00000c14 |
48 | #define MWL8K_FWSTA_READY 0xf0f1f2f4 | 47 | #define MWL8K_FWSTA_READY 0xf0f1f2f4 |
49 | #define MWL8K_FWAP_READY 0xf1f2f4a5 | 48 | #define MWL8K_FWAP_READY 0xf1f2f4a5 |
50 | #define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 | 49 | #define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 |
51 | #define MWL8K_HIU_SCRATCH 0x00000c40 | 50 | #define MWL8K_HIU_SCRATCH 0x00000c40 |
52 | 51 | ||
53 | /* Host->device communications */ | 52 | /* Host->device communications */ |
@@ -56,11 +55,10 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table); | |||
56 | #define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 | 55 | #define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 |
57 | #define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 | 56 | #define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 |
58 | #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 | 57 | #define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 |
59 | #define MWL8K_H2A_INT_DUMMY (1 << 20) | 58 | #define MWL8K_H2A_INT_DUMMY (1 << 20) |
60 | #define MWL8K_H2A_INT_RESET (1 << 15) | 59 | #define MWL8K_H2A_INT_RESET (1 << 15) |
61 | #define MWL8K_H2A_INT_PS (1 << 2) | 60 | #define MWL8K_H2A_INT_DOORBELL (1 << 1) |
62 | #define MWL8K_H2A_INT_DOORBELL (1 << 1) | 61 | #define MWL8K_H2A_INT_PPA_READY (1 << 0) |
63 | #define MWL8K_H2A_INT_PPA_READY (1 << 0) | ||
64 | 62 | ||
65 | /* Device->host communications */ | 63 | /* Device->host communications */ |
66 | #define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c | 64 | #define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c |
@@ -68,16 +66,16 @@ MODULE_DEVICE_TABLE(pci, mwl8k_table); | |||
68 | #define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 | 66 | #define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 |
69 | #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 | 67 | #define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 |
70 | #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c | 68 | #define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c |
71 | #define MWL8K_A2H_INT_DUMMY (1 << 20) | 69 | #define MWL8K_A2H_INT_DUMMY (1 << 20) |
72 | #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) | 70 | #define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) |
73 | #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) | 71 | #define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) |
74 | #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) | 72 | #define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) |
75 | #define MWL8K_A2H_INT_RADIO_ON (1 << 6) | 73 | #define MWL8K_A2H_INT_RADIO_ON (1 << 6) |
76 | #define MWL8K_A2H_INT_RADIO_OFF (1 << 5) | 74 | #define MWL8K_A2H_INT_RADIO_OFF (1 << 5) |
77 | #define MWL8K_A2H_INT_MAC_EVENT (1 << 3) | 75 | #define MWL8K_A2H_INT_MAC_EVENT (1 << 3) |
78 | #define MWL8K_A2H_INT_OPC_DONE (1 << 2) | 76 | #define MWL8K_A2H_INT_OPC_DONE (1 << 2) |
79 | #define MWL8K_A2H_INT_RX_READY (1 << 1) | 77 | #define MWL8K_A2H_INT_RX_READY (1 << 1) |
80 | #define MWL8K_A2H_INT_TX_DONE (1 << 0) | 78 | #define MWL8K_A2H_INT_TX_DONE (1 << 0) |
81 | 79 | ||
82 | #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ | 80 | #define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ |
83 | MWL8K_A2H_INT_CHNL_SWITCHED | \ | 81 | MWL8K_A2H_INT_CHNL_SWITCHED | \ |
@@ -113,17 +111,6 @@ struct mwl8k_rx_queue { | |||
113 | struct sk_buff **rx_skb; | 111 | struct sk_buff **rx_skb; |
114 | }; | 112 | }; |
115 | 113 | ||
116 | struct mwl8k_skb { | ||
117 | /* | ||
118 | * The DMA engine requires a modification to the payload. | ||
119 | * If the skbuff is shared/cloned, it needs to be unshared. | ||
120 | * This method is used to ensure the stack always gets back | ||
121 | * the skbuff it sent for transmission. | ||
122 | */ | ||
123 | struct sk_buff *clone; | ||
124 | struct sk_buff *skb; | ||
125 | }; | ||
126 | |||
127 | struct mwl8k_tx_queue { | 114 | struct mwl8k_tx_queue { |
128 | /* hw transmits here */ | 115 | /* hw transmits here */ |
129 | int tx_head; | 116 | int tx_head; |
@@ -134,7 +121,7 @@ struct mwl8k_tx_queue { | |||
134 | struct ieee80211_tx_queue_stats tx_stats; | 121 | struct ieee80211_tx_queue_stats tx_stats; |
135 | struct mwl8k_tx_desc *tx_desc_area; | 122 | struct mwl8k_tx_desc *tx_desc_area; |
136 | dma_addr_t tx_desc_dma; | 123 | dma_addr_t tx_desc_dma; |
137 | struct mwl8k_skb *tx_skb; | 124 | struct sk_buff **tx_skb; |
138 | }; | 125 | }; |
139 | 126 | ||
140 | /* Pointers to the firmware data and meta information about it. */ | 127 | /* Pointers to the firmware data and meta information about it. */ |
@@ -152,19 +139,22 @@ struct mwl8k_priv { | |||
152 | 139 | ||
153 | struct pci_dev *pdev; | 140 | struct pci_dev *pdev; |
154 | u8 name[16]; | 141 | u8 name[16]; |
155 | /* firmware access lock */ | ||
156 | spinlock_t fw_lock; | ||
157 | 142 | ||
158 | /* firmware files and meta data */ | 143 | /* firmware files and meta data */ |
159 | struct mwl8k_firmware fw; | 144 | struct mwl8k_firmware fw; |
160 | u32 part_num; | 145 | u32 part_num; |
161 | 146 | ||
147 | /* firmware access */ | ||
148 | struct mutex fw_mutex; | ||
149 | struct task_struct *fw_mutex_owner; | ||
150 | int fw_mutex_depth; | ||
151 | struct completion *tx_wait; | ||
152 | struct completion *hostcmd_wait; | ||
153 | |||
162 | /* lock held over TX and TX reap */ | 154 | /* lock held over TX and TX reap */ |
163 | spinlock_t tx_lock; | 155 | spinlock_t tx_lock; |
164 | u32 int_mask; | ||
165 | 156 | ||
166 | struct ieee80211_vif *vif; | 157 | struct ieee80211_vif *vif; |
167 | struct list_head vif_list; | ||
168 | 158 | ||
169 | struct ieee80211_channel *current_channel; | 159 | struct ieee80211_channel *current_channel; |
170 | 160 | ||
@@ -173,10 +163,8 @@ struct mwl8k_priv { | |||
173 | dma_addr_t cookie_dma; | 163 | dma_addr_t cookie_dma; |
174 | 164 | ||
175 | u16 num_mcaddrs; | 165 | u16 num_mcaddrs; |
176 | u16 region_code; | ||
177 | u8 hw_rev; | 166 | u8 hw_rev; |
178 | __le32 fw_rev; | 167 | __le32 fw_rev; |
179 | u32 wep_enabled; | ||
180 | 168 | ||
181 | /* | 169 | /* |
182 | * Running count of TX packets in flight, to avoid | 170 | * Running count of TX packets in flight, to avoid |
@@ -192,19 +180,13 @@ struct mwl8k_priv { | |||
192 | struct ieee80211_channel channels[14]; | 180 | struct ieee80211_channel channels[14]; |
193 | struct ieee80211_rate rates[12]; | 181 | struct ieee80211_rate rates[12]; |
194 | 182 | ||
195 | /* RF preamble: Short, Long or Auto */ | 183 | bool radio_on; |
196 | u8 radio_preamble; | 184 | bool radio_short_preamble; |
197 | u8 radio_state; | 185 | bool wmm_enabled; |
198 | |||
199 | /* WMM MODE 1 for enabled; 0 for disabled */ | ||
200 | bool wmm_mode; | ||
201 | |||
202 | /* Set if PHY config is in progress */ | ||
203 | bool inconfig; | ||
204 | 186 | ||
205 | /* XXX need to convert this to handle multiple interfaces */ | 187 | /* XXX need to convert this to handle multiple interfaces */ |
206 | bool capture_beacon; | 188 | bool capture_beacon; |
207 | u8 capture_bssid[IEEE80211_ADDR_LEN]; | 189 | u8 capture_bssid[ETH_ALEN]; |
208 | struct sk_buff *beacon_skb; | 190 | struct sk_buff *beacon_skb; |
209 | 191 | ||
210 | /* | 192 | /* |
@@ -220,14 +202,10 @@ struct mwl8k_priv { | |||
220 | 202 | ||
221 | /* Work thread to serialize configuration requests */ | 203 | /* Work thread to serialize configuration requests */ |
222 | struct workqueue_struct *config_wq; | 204 | struct workqueue_struct *config_wq; |
223 | struct completion *hostcmd_wait; | ||
224 | struct completion *tx_wait; | ||
225 | }; | 205 | }; |
226 | 206 | ||
227 | /* Per interface specific private data */ | 207 | /* Per interface specific private data */ |
228 | struct mwl8k_vif { | 208 | struct mwl8k_vif { |
229 | struct list_head node; | ||
230 | |||
231 | /* backpointer to parent config block */ | 209 | /* backpointer to parent config block */ |
232 | struct mwl8k_priv *priv; | 210 | struct mwl8k_priv *priv; |
233 | 211 | ||
@@ -235,8 +213,8 @@ struct mwl8k_vif { | |||
235 | struct ieee80211_bss_conf bss_info; | 213 | struct ieee80211_bss_conf bss_info; |
236 | 214 | ||
237 | /* BSSID of AP or IBSS */ | 215 | /* BSSID of AP or IBSS */ |
238 | u8 bssid[IEEE80211_ADDR_LEN]; | 216 | u8 bssid[ETH_ALEN]; |
239 | u8 mac_addr[IEEE80211_ADDR_LEN]; | 217 | u8 mac_addr[ETH_ALEN]; |
240 | 218 | ||
241 | /* | 219 | /* |
242 | * Subset of supported legacy rates. | 220 | * Subset of supported legacy rates. |
@@ -247,18 +225,11 @@ struct mwl8k_vif { | |||
247 | /* number of supported legacy rates */ | 225 | /* number of supported legacy rates */ |
248 | u8 legacy_nrates; | 226 | u8 legacy_nrates; |
249 | 227 | ||
250 | /* Number of supported MCS rates. Work in progress */ | ||
251 | u8 mcs_nrates; | ||
252 | |||
253 | /* Index into station database.Returned by update_sta_db call */ | 228 | /* Index into station database.Returned by update_sta_db call */ |
254 | u8 peer_id; | 229 | u8 peer_id; |
255 | 230 | ||
256 | /* Non AMPDU sequence number assigned by driver */ | 231 | /* Non AMPDU sequence number assigned by driver */ |
257 | u16 seqno; | 232 | u16 seqno; |
258 | |||
259 | /* Note:There is no channel info, | ||
260 | * refer to the master channel info in priv | ||
261 | */ | ||
262 | }; | 233 | }; |
263 | 234 | ||
264 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) | 235 | #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) |
@@ -292,28 +263,6 @@ static const struct ieee80211_rate mwl8k_rates[] = { | |||
292 | { .bitrate = 540, .hw_value = 108, }, | 263 | { .bitrate = 540, .hw_value = 108, }, |
293 | }; | 264 | }; |
294 | 265 | ||
295 | /* Radio settings */ | ||
296 | #define MWL8K_RADIO_FORCE 0x2 | ||
297 | #define MWL8K_RADIO_ENABLE 0x1 | ||
298 | #define MWL8K_RADIO_DISABLE 0x0 | ||
299 | #define MWL8K_RADIO_AUTO_PREAMBLE 0x0005 | ||
300 | #define MWL8K_RADIO_SHORT_PREAMBLE 0x0003 | ||
301 | #define MWL8K_RADIO_LONG_PREAMBLE 0x0001 | ||
302 | |||
303 | /* WMM */ | ||
304 | #define MWL8K_WMM_ENABLE 1 | ||
305 | #define MWL8K_WMM_DISABLE 0 | ||
306 | |||
307 | #define MWL8K_RADIO_DEFAULT_PREAMBLE MWL8K_RADIO_LONG_PREAMBLE | ||
308 | |||
309 | /* Slot time */ | ||
310 | |||
311 | /* Short Slot: 9us slot time */ | ||
312 | #define MWL8K_SHORT_SLOTTIME 1 | ||
313 | |||
314 | /* Long slot: 20us slot time */ | ||
315 | #define MWL8K_LONG_SLOTTIME 0 | ||
316 | |||
317 | /* Set or get info from Firmware */ | 266 | /* Set or get info from Firmware */ |
318 | #define MWL8K_CMD_SET 0x0001 | 267 | #define MWL8K_CMD_SET 0x0001 |
319 | #define MWL8K_CMD_GET 0x0000 | 268 | #define MWL8K_CMD_GET 0x0000 |
@@ -323,25 +272,23 @@ static const struct ieee80211_rate mwl8k_rates[] = { | |||
323 | #define MWL8K_CMD_GET_HW_SPEC 0x0003 | 272 | #define MWL8K_CMD_GET_HW_SPEC 0x0003 |
324 | #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 | 273 | #define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 |
325 | #define MWL8K_CMD_GET_STAT 0x0014 | 274 | #define MWL8K_CMD_GET_STAT 0x0014 |
326 | #define MWL8K_CMD_RADIO_CONTROL 0x001C | 275 | #define MWL8K_CMD_RADIO_CONTROL 0x001c |
327 | #define MWL8K_CMD_RF_TX_POWER 0x001E | 276 | #define MWL8K_CMD_RF_TX_POWER 0x001e |
328 | #define MWL8K_CMD_SET_PRE_SCAN 0x0107 | 277 | #define MWL8K_CMD_SET_PRE_SCAN 0x0107 |
329 | #define MWL8K_CMD_SET_POST_SCAN 0x0108 | 278 | #define MWL8K_CMD_SET_POST_SCAN 0x0108 |
330 | #define MWL8K_CMD_SET_RF_CHANNEL 0x010A | 279 | #define MWL8K_CMD_SET_RF_CHANNEL 0x010a |
280 | #define MWL8K_CMD_SET_AID 0x010d | ||
281 | #define MWL8K_CMD_SET_RATE 0x0110 | ||
282 | #define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 | ||
283 | #define MWL8K_CMD_RTS_THRESHOLD 0x0113 | ||
331 | #define MWL8K_CMD_SET_SLOT 0x0114 | 284 | #define MWL8K_CMD_SET_SLOT 0x0114 |
285 | #define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 | ||
286 | #define MWL8K_CMD_SET_WMM_MODE 0x0123 | ||
332 | #define MWL8K_CMD_MIMO_CONFIG 0x0125 | 287 | #define MWL8K_CMD_MIMO_CONFIG 0x0125 |
288 | #define MWL8K_CMD_USE_FIXED_RATE 0x0126 | ||
333 | #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 | 289 | #define MWL8K_CMD_ENABLE_SNIFFER 0x0150 |
334 | #define MWL8K_CMD_SET_WMM_MODE 0x0123 | ||
335 | #define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 | ||
336 | #define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 | ||
337 | #define MWL8K_CMD_UPDATE_STADB 0x1123 | ||
338 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 | 290 | #define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 |
339 | #define MWL8K_CMD_SET_LINKADAPT_MODE 0x0129 | 291 | #define MWL8K_CMD_UPDATE_STADB 0x1123 |
340 | #define MWL8K_CMD_SET_AID 0x010d | ||
341 | #define MWL8K_CMD_SET_RATE 0x0110 | ||
342 | #define MWL8K_CMD_USE_FIXED_RATE 0x0126 | ||
343 | #define MWL8K_CMD_RTS_THRESHOLD 0x0113 | ||
344 | #define MWL8K_CMD_ENCRYPTION 0x1122 | ||
345 | 292 | ||
346 | static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | 293 | static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) |
347 | { | 294 | { |
@@ -349,7 +296,7 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | |||
349 | snprintf(buf, bufsize, "%s", #x);\ | 296 | snprintf(buf, bufsize, "%s", #x);\ |
350 | return buf;\ | 297 | return buf;\ |
351 | } while (0) | 298 | } while (0) |
352 | switch (cmd & (~0x8000)) { | 299 | switch (cmd & ~0x8000) { |
353 | MWL8K_CMDNAME(CODE_DNLD); | 300 | MWL8K_CMDNAME(CODE_DNLD); |
354 | MWL8K_CMDNAME(GET_HW_SPEC); | 301 | MWL8K_CMDNAME(GET_HW_SPEC); |
355 | MWL8K_CMDNAME(MAC_MULTICAST_ADR); | 302 | MWL8K_CMDNAME(MAC_MULTICAST_ADR); |
@@ -359,20 +306,18 @@ static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) | |||
359 | MWL8K_CMDNAME(SET_PRE_SCAN); | 306 | MWL8K_CMDNAME(SET_PRE_SCAN); |
360 | MWL8K_CMDNAME(SET_POST_SCAN); | 307 | MWL8K_CMDNAME(SET_POST_SCAN); |
361 | MWL8K_CMDNAME(SET_RF_CHANNEL); | 308 | MWL8K_CMDNAME(SET_RF_CHANNEL); |
309 | MWL8K_CMDNAME(SET_AID); | ||
310 | MWL8K_CMDNAME(SET_RATE); | ||
311 | MWL8K_CMDNAME(SET_FINALIZE_JOIN); | ||
312 | MWL8K_CMDNAME(RTS_THRESHOLD); | ||
362 | MWL8K_CMDNAME(SET_SLOT); | 313 | MWL8K_CMDNAME(SET_SLOT); |
314 | MWL8K_CMDNAME(SET_EDCA_PARAMS); | ||
315 | MWL8K_CMDNAME(SET_WMM_MODE); | ||
363 | MWL8K_CMDNAME(MIMO_CONFIG); | 316 | MWL8K_CMDNAME(MIMO_CONFIG); |
317 | MWL8K_CMDNAME(USE_FIXED_RATE); | ||
364 | MWL8K_CMDNAME(ENABLE_SNIFFER); | 318 | MWL8K_CMDNAME(ENABLE_SNIFFER); |
365 | MWL8K_CMDNAME(SET_WMM_MODE); | ||
366 | MWL8K_CMDNAME(SET_EDCA_PARAMS); | ||
367 | MWL8K_CMDNAME(SET_FINALIZE_JOIN); | ||
368 | MWL8K_CMDNAME(UPDATE_STADB); | ||
369 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); | 319 | MWL8K_CMDNAME(SET_RATEADAPT_MODE); |
370 | MWL8K_CMDNAME(SET_LINKADAPT_MODE); | 320 | MWL8K_CMDNAME(UPDATE_STADB); |
371 | MWL8K_CMDNAME(SET_AID); | ||
372 | MWL8K_CMDNAME(SET_RATE); | ||
373 | MWL8K_CMDNAME(USE_FIXED_RATE); | ||
374 | MWL8K_CMDNAME(RTS_THRESHOLD); | ||
375 | MWL8K_CMDNAME(ENCRYPTION); | ||
376 | default: | 321 | default: |
377 | snprintf(buf, bufsize, "0x%x", cmd); | 322 | snprintf(buf, bufsize, "0x%x", cmd); |
378 | } | 323 | } |
@@ -466,7 +411,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | |||
466 | { | 411 | { |
467 | void __iomem *regs = priv->regs; | 412 | void __iomem *regs = priv->regs; |
468 | dma_addr_t dma_addr; | 413 | dma_addr_t dma_addr; |
469 | int rc; | ||
470 | int loops; | 414 | int loops; |
471 | 415 | ||
472 | dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); | 416 | dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); |
@@ -480,7 +424,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | |||
480 | iowrite32(MWL8K_H2A_INT_DUMMY, | 424 | iowrite32(MWL8K_H2A_INT_DUMMY, |
481 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | 425 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); |
482 | 426 | ||
483 | rc = -ETIMEDOUT; | ||
484 | loops = 1000; | 427 | loops = 1000; |
485 | do { | 428 | do { |
486 | u32 int_code; | 429 | u32 int_code; |
@@ -488,7 +431,6 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | |||
488 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); | 431 | int_code = ioread32(regs + MWL8K_HIU_INT_CODE); |
489 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { | 432 | if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { |
490 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); | 433 | iowrite32(0, regs + MWL8K_HIU_INT_CODE); |
491 | rc = 0; | ||
492 | break; | 434 | break; |
493 | } | 435 | } |
494 | 436 | ||
@@ -497,26 +439,7 @@ mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) | |||
497 | 439 | ||
498 | pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); | 440 | pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); |
499 | 441 | ||
500 | /* | 442 | return loops ? 0 : -ETIMEDOUT; |
501 | * Clear 'command done' interrupt bit. | ||
502 | */ | ||
503 | loops = 1000; | ||
504 | do { | ||
505 | u32 status; | ||
506 | |||
507 | status = ioread32(priv->regs + | ||
508 | MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
509 | if (status & MWL8K_A2H_INT_OPC_DONE) { | ||
510 | iowrite32(~MWL8K_A2H_INT_OPC_DONE, | ||
511 | priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
512 | ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | ||
513 | break; | ||
514 | } | ||
515 | |||
516 | udelay(1); | ||
517 | } while (--loops); | ||
518 | |||
519 | return rc; | ||
520 | } | 443 | } |
521 | 444 | ||
522 | static int mwl8k_load_fw_image(struct mwl8k_priv *priv, | 445 | static int mwl8k_load_fw_image(struct mwl8k_priv *priv, |
@@ -681,11 +604,9 @@ struct ewc_ht_info { | |||
681 | 604 | ||
682 | /* Peer Entry flags - used to define the type of the peer node */ | 605 | /* Peer Entry flags - used to define the type of the peer node */ |
683 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 | 606 | #define MWL8K_PEER_TYPE_ACCESSPOINT 2 |
684 | #define MWL8K_PEER_TYPE_ADHOC_STATION 4 | ||
685 | 607 | ||
686 | #define MWL8K_IEEE_LEGACY_DATA_RATES 12 | 608 | #define MWL8K_IEEE_LEGACY_DATA_RATES 12 |
687 | #define MWL8K_MCS_BITMAP_SIZE 16 | 609 | #define MWL8K_MCS_BITMAP_SIZE 16 |
688 | #define pad_size 16 | ||
689 | 610 | ||
690 | struct peer_capability_info { | 611 | struct peer_capability_info { |
691 | /* Peer type - AP vs. STA. */ | 612 | /* Peer type - AP vs. STA. */ |
@@ -707,7 +628,7 @@ struct peer_capability_info { | |||
707 | 628 | ||
708 | /* HT rate table. Intersection of our rates and peer rates. */ | 629 | /* HT rate table. Intersection of our rates and peer rates. */ |
709 | __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; | 630 | __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; |
710 | __u8 pad[pad_size]; | 631 | __u8 pad[16]; |
711 | 632 | ||
712 | /* If set, interoperability mode, no proprietary extensions. */ | 633 | /* If set, interoperability mode, no proprietary extensions. */ |
713 | __u8 interop; | 634 | __u8 interop; |
@@ -717,15 +638,6 @@ struct peer_capability_info { | |||
717 | } __attribute__((packed)); | 638 | } __attribute__((packed)); |
718 | 639 | ||
719 | /* Inline functions to manipulate QoS field in data descriptor. */ | 640 | /* Inline functions to manipulate QoS field in data descriptor. */ |
720 | static inline u16 mwl8k_qos_setbit_tid(u16 qos, u8 tid) | ||
721 | { | ||
722 | u16 val_mask = 0x000f; | ||
723 | u16 qos_mask = ~val_mask; | ||
724 | |||
725 | /* TID bits 0-3 */ | ||
726 | return (qos & qos_mask) | (tid & val_mask); | ||
727 | } | ||
728 | |||
729 | static inline u16 mwl8k_qos_setbit_eosp(u16 qos) | 641 | static inline u16 mwl8k_qos_setbit_eosp(u16 qos) |
730 | { | 642 | { |
731 | u16 val_mask = 1 << 4; | 643 | u16 val_mask = 1 << 4; |
@@ -769,12 +681,11 @@ struct mwl8k_dma_data { | |||
769 | } __attribute__((packed)); | 681 | } __attribute__((packed)); |
770 | 682 | ||
771 | /* Routines to add/remove DMA header from skb. */ | 683 | /* Routines to add/remove DMA header from skb. */ |
772 | static inline int mwl8k_remove_dma_header(struct sk_buff *skb) | 684 | static inline void mwl8k_remove_dma_header(struct sk_buff *skb) |
773 | { | 685 | { |
774 | struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)(skb->data); | 686 | struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data; |
775 | void *dst, *src = &tr->wh; | 687 | void *dst, *src = &tr->wh; |
776 | __le16 fc = tr->wh.frame_control; | 688 | int hdrlen = ieee80211_hdrlen(tr->wh.frame_control); |
777 | int hdrlen = ieee80211_hdrlen(fc); | ||
778 | u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; | 689 | u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; |
779 | 690 | ||
780 | dst = (void *)tr + space; | 691 | dst = (void *)tr + space; |
@@ -782,11 +693,9 @@ static inline int mwl8k_remove_dma_header(struct sk_buff *skb) | |||
782 | memmove(dst, src, hdrlen); | 693 | memmove(dst, src, hdrlen); |
783 | skb_pull(skb, space); | 694 | skb_pull(skb, space); |
784 | } | 695 | } |
785 | |||
786 | return 0; | ||
787 | } | 696 | } |
788 | 697 | ||
789 | static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) | 698 | static inline void mwl8k_add_dma_header(struct sk_buff *skb) |
790 | { | 699 | { |
791 | struct ieee80211_hdr *wh; | 700 | struct ieee80211_hdr *wh; |
792 | u32 hdrlen, pktlen; | 701 | u32 hdrlen, pktlen; |
@@ -810,7 +719,7 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) | |||
810 | memmove(&tr->wh, wh, hdrlen); | 719 | memmove(&tr->wh, wh, hdrlen); |
811 | 720 | ||
812 | /* Clear addr4 */ | 721 | /* Clear addr4 */ |
813 | memset(tr->wh.addr4, 0, IEEE80211_ADDR_LEN); | 722 | memset(tr->wh.addr4, 0, ETH_ALEN); |
814 | 723 | ||
815 | /* | 724 | /* |
816 | * Firmware length is the length of the fully formed "802.11 | 725 | * Firmware length is the length of the fully formed "802.11 |
@@ -818,17 +727,13 @@ static inline struct sk_buff *mwl8k_add_dma_header(struct sk_buff *skb) | |||
818 | * This includes all crypto material including the MIC. | 727 | * This includes all crypto material including the MIC. |
819 | */ | 728 | */ |
820 | tr->fwlen = cpu_to_le16(pktlen - hdrlen); | 729 | tr->fwlen = cpu_to_le16(pktlen - hdrlen); |
821 | |||
822 | return skb; | ||
823 | } | 730 | } |
824 | 731 | ||
825 | 732 | ||
826 | /* | 733 | /* |
827 | * Packet reception. | 734 | * Packet reception. |
828 | */ | 735 | */ |
829 | #define MWL8K_RX_CTRL_KEY_INDEX_MASK 0x30 | ||
830 | #define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 | 736 | #define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 |
831 | #define MWL8K_RX_CTRL_AMPDU 0x01 | ||
832 | 737 | ||
833 | struct mwl8k_rx_desc { | 738 | struct mwl8k_rx_desc { |
834 | __le16 pkt_len; | 739 | __le16 pkt_len; |
@@ -979,7 +884,7 @@ static inline void mwl8k_save_beacon(struct mwl8k_priv *priv, | |||
979 | struct sk_buff *skb) | 884 | struct sk_buff *skb) |
980 | { | 885 | { |
981 | priv->capture_beacon = false; | 886 | priv->capture_beacon = false; |
982 | memset(priv->capture_bssid, 0, IEEE80211_ADDR_LEN); | 887 | memset(priv->capture_bssid, 0, ETH_ALEN); |
983 | 888 | ||
984 | /* | 889 | /* |
985 | * Use GFP_ATOMIC as rxq_process is called from | 890 | * Use GFP_ATOMIC as rxq_process is called from |
@@ -1024,10 +929,7 @@ static int rxq_process(struct ieee80211_hw *hw, int index, int limit) | |||
1024 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); | 929 | MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); |
1025 | 930 | ||
1026 | skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); | 931 | skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); |
1027 | if (mwl8k_remove_dma_header(skb)) { | 932 | mwl8k_remove_dma_header(skb); |
1028 | dev_kfree_skb(skb); | ||
1029 | continue; | ||
1030 | } | ||
1031 | 933 | ||
1032 | wh = (struct ieee80211_hdr *)skb->data; | 934 | wh = (struct ieee80211_hdr *)skb->data; |
1033 | 935 | ||
@@ -1073,8 +975,6 @@ enum { | |||
1073 | 975 | ||
1074 | /* Transmit packet ACK policy */ | 976 | /* Transmit packet ACK policy */ |
1075 | #define MWL8K_TXD_ACK_POLICY_NORMAL 0 | 977 | #define MWL8K_TXD_ACK_POLICY_NORMAL 0 |
1076 | #define MWL8K_TXD_ACK_POLICY_NONE 1 | ||
1077 | #define MWL8K_TXD_ACK_POLICY_NO_EXPLICIT 2 | ||
1078 | #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 | 978 | #define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 |
1079 | 979 | ||
1080 | #define GET_TXQ(_ac) (\ | 980 | #define GET_TXQ(_ac) (\ |
@@ -1083,20 +983,11 @@ enum { | |||
1083 | ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ | 983 | ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ |
1084 | MWL8K_WME_AC_BE) | 984 | MWL8K_WME_AC_BE) |
1085 | 985 | ||
1086 | #define MWL8K_TXD_STATUS_IDLE 0x00000000 | ||
1087 | #define MWL8K_TXD_STATUS_USED 0x00000001 | ||
1088 | #define MWL8K_TXD_STATUS_OK 0x00000001 | 986 | #define MWL8K_TXD_STATUS_OK 0x00000001 |
1089 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 | 987 | #define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 |
1090 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 | 988 | #define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 |
1091 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 | 989 | #define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 |
1092 | #define MWL8K_TXD_STATUS_BROADCAST_TX 0x00000010 | ||
1093 | #define MWL8K_TXD_STATUS_FAILED_LINK_ERROR 0x00000020 | ||
1094 | #define MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT 0x00000040 | ||
1095 | #define MWL8K_TXD_STATUS_FAILED_AGING 0x00000080 | ||
1096 | #define MWL8K_TXD_STATUS_HOST_CMD 0x40000000 | ||
1097 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 | 990 | #define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 |
1098 | #define MWL8K_TXD_SOFTSTALE 0x80 | ||
1099 | #define MWL8K_TXD_SOFTSTALE_MGMT_RETRY 0x01 | ||
1100 | 991 | ||
1101 | struct mwl8k_tx_desc { | 992 | struct mwl8k_tx_desc { |
1102 | __le32 status; | 993 | __le32 status; |
@@ -1105,7 +996,7 @@ struct mwl8k_tx_desc { | |||
1105 | __le16 qos_control; | 996 | __le16 qos_control; |
1106 | __le32 pkt_phys_addr; | 997 | __le32 pkt_phys_addr; |
1107 | __le16 pkt_len; | 998 | __le16 pkt_len; |
1108 | __u8 dest_MAC_addr[IEEE80211_ADDR_LEN]; | 999 | __u8 dest_MAC_addr[ETH_ALEN]; |
1109 | __le32 next_tx_desc_phys_addr; | 1000 | __le32 next_tx_desc_phys_addr; |
1110 | __le32 reserved; | 1001 | __le32 reserved; |
1111 | __le16 rate_info; | 1002 | __le16 rate_info; |
@@ -1122,8 +1013,7 @@ static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) | |||
1122 | int size; | 1013 | int size; |
1123 | int i; | 1014 | int i; |
1124 | 1015 | ||
1125 | memset(&txq->tx_stats, 0, | 1016 | memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats)); |
1126 | sizeof(struct ieee80211_tx_queue_stats)); | ||
1127 | txq->tx_stats.limit = MWL8K_TX_DESCS; | 1017 | txq->tx_stats.limit = MWL8K_TX_DESCS; |
1128 | txq->tx_head = 0; | 1018 | txq->tx_head = 0; |
1129 | txq->tx_tail = 0; | 1019 | txq->tx_tail = 0; |
@@ -1190,17 +1080,17 @@ struct mwl8k_txq_info { | |||
1190 | }; | 1080 | }; |
1191 | 1081 | ||
1192 | static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, | 1082 | static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, |
1193 | struct mwl8k_txq_info txinfo[], | 1083 | struct mwl8k_txq_info *txinfo) |
1194 | u32 num_queues) | ||
1195 | { | 1084 | { |
1196 | int count, desc, status; | 1085 | int count, desc, status; |
1197 | struct mwl8k_tx_queue *txq; | 1086 | struct mwl8k_tx_queue *txq; |
1198 | struct mwl8k_tx_desc *tx_desc; | 1087 | struct mwl8k_tx_desc *tx_desc; |
1199 | int ndescs = 0; | 1088 | int ndescs = 0; |
1200 | 1089 | ||
1201 | memset(txinfo, 0, num_queues * sizeof(struct mwl8k_txq_info)); | 1090 | memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info)); |
1091 | |||
1202 | spin_lock_bh(&priv->tx_lock); | 1092 | spin_lock_bh(&priv->tx_lock); |
1203 | for (count = 0; count < num_queues; count++) { | 1093 | for (count = 0; count < MWL8K_TX_QUEUES; count++) { |
1204 | txq = priv->txq + count; | 1094 | txq = priv->txq + count; |
1205 | txinfo[count].len = txq->tx_stats.len; | 1095 | txinfo[count].len = txq->tx_stats.len; |
1206 | txinfo[count].head = txq->tx_head; | 1096 | txinfo[count].head = txq->tx_head; |
@@ -1223,34 +1113,34 @@ static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, | |||
1223 | return ndescs; | 1113 | return ndescs; |
1224 | } | 1114 | } |
1225 | 1115 | ||
1226 | static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) | 1116 | /* |
1117 | * Must be called with hw->fw_mutex held and tx queues stopped. | ||
1118 | */ | ||
1119 | static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) | ||
1227 | { | 1120 | { |
1228 | u32 count = 0; | ||
1229 | unsigned long timeout = 0; | ||
1230 | struct mwl8k_priv *priv = hw->priv; | 1121 | struct mwl8k_priv *priv = hw->priv; |
1231 | DECLARE_COMPLETION_ONSTACK(cmd_wait); | 1122 | DECLARE_COMPLETION_ONSTACK(cmd_wait); |
1123 | u32 count; | ||
1124 | unsigned long timeout; | ||
1232 | 1125 | ||
1233 | might_sleep(); | 1126 | might_sleep(); |
1234 | 1127 | ||
1235 | if (priv->tx_wait != NULL) | ||
1236 | printk(KERN_ERR "WARNING Previous TXWaitEmpty instance\n"); | ||
1237 | |||
1238 | spin_lock_bh(&priv->tx_lock); | 1128 | spin_lock_bh(&priv->tx_lock); |
1239 | count = mwl8k_txq_busy(priv); | 1129 | count = mwl8k_txq_busy(priv); |
1240 | if (count) { | 1130 | if (count) { |
1241 | priv->tx_wait = &cmd_wait; | 1131 | priv->tx_wait = &cmd_wait; |
1242 | if (priv->radio_state) | 1132 | if (priv->radio_on) |
1243 | mwl8k_tx_start(priv); | 1133 | mwl8k_tx_start(priv); |
1244 | } | 1134 | } |
1245 | spin_unlock_bh(&priv->tx_lock); | 1135 | spin_unlock_bh(&priv->tx_lock); |
1246 | 1136 | ||
1247 | if (count) { | 1137 | if (count) { |
1248 | struct mwl8k_txq_info txinfo[4]; | 1138 | struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES]; |
1249 | int index; | 1139 | int index; |
1250 | int newcount; | 1140 | int newcount; |
1251 | 1141 | ||
1252 | timeout = wait_for_completion_timeout(&cmd_wait, | 1142 | timeout = wait_for_completion_timeout(&cmd_wait, |
1253 | msecs_to_jiffies(delay_ms)); | 1143 | msecs_to_jiffies(5000)); |
1254 | if (timeout) | 1144 | if (timeout) |
1255 | return 0; | 1145 | return 0; |
1256 | 1146 | ||
@@ -1259,11 +1149,11 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) | |||
1259 | newcount = mwl8k_txq_busy(priv); | 1149 | newcount = mwl8k_txq_busy(priv); |
1260 | spin_unlock_bh(&priv->tx_lock); | 1150 | spin_unlock_bh(&priv->tx_lock); |
1261 | 1151 | ||
1262 | printk(KERN_ERR "%s(%u) TIMEDOUT:%ums Pend:%u-->%u\n", | 1152 | printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n", |
1263 | __func__, __LINE__, delay_ms, count, newcount); | 1153 | __func__, __LINE__, count, newcount); |
1264 | 1154 | ||
1265 | mwl8k_scan_tx_ring(priv, txinfo, 4); | 1155 | mwl8k_scan_tx_ring(priv, txinfo); |
1266 | for (index = 0 ; index < 4; index++) | 1156 | for (index = 0; index < MWL8K_TX_QUEUES; index++) |
1267 | printk(KERN_ERR | 1157 | printk(KERN_ERR |
1268 | "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", | 1158 | "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", |
1269 | index, | 1159 | index, |
@@ -1273,18 +1163,17 @@ static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw, u32 delay_ms) | |||
1273 | txinfo[index].fw_owned, | 1163 | txinfo[index].fw_owned, |
1274 | txinfo[index].drv_owned, | 1164 | txinfo[index].drv_owned, |
1275 | txinfo[index].unused); | 1165 | txinfo[index].unused); |
1166 | |||
1276 | return -ETIMEDOUT; | 1167 | return -ETIMEDOUT; |
1277 | } | 1168 | } |
1278 | 1169 | ||
1279 | return 0; | 1170 | return 0; |
1280 | } | 1171 | } |
1281 | 1172 | ||
1282 | #define MWL8K_TXD_OK (MWL8K_TXD_STATUS_OK | \ | 1173 | #define MWL8K_TXD_SUCCESS(status) \ |
1283 | MWL8K_TXD_STATUS_OK_RETRY | \ | 1174 | ((status) & (MWL8K_TXD_STATUS_OK | \ |
1284 | MWL8K_TXD_STATUS_OK_MORE_RETRY) | 1175 | MWL8K_TXD_STATUS_OK_RETRY | \ |
1285 | #define MWL8K_TXD_SUCCESS(stat) ((stat) & MWL8K_TXD_OK) | 1176 | MWL8K_TXD_STATUS_OK_MORE_RETRY)) |
1286 | #define MWL8K_TXD_FAIL_RETRY(stat) \ | ||
1287 | ((stat) & (MWL8K_TXD_STATUS_FAILED_EXCEED_LIMIT)) | ||
1288 | 1177 | ||
1289 | static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | 1178 | static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) |
1290 | { | 1179 | { |
@@ -1294,15 +1183,13 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | |||
1294 | 1183 | ||
1295 | while (txq->tx_stats.len > 0) { | 1184 | while (txq->tx_stats.len > 0) { |
1296 | int tx; | 1185 | int tx; |
1297 | int rc; | ||
1298 | struct mwl8k_tx_desc *tx_desc; | 1186 | struct mwl8k_tx_desc *tx_desc; |
1299 | unsigned long addr; | 1187 | unsigned long addr; |
1300 | size_t size; | 1188 | int size; |
1301 | struct sk_buff *skb; | 1189 | struct sk_buff *skb; |
1302 | struct ieee80211_tx_info *info; | 1190 | struct ieee80211_tx_info *info; |
1303 | u32 status; | 1191 | u32 status; |
1304 | 1192 | ||
1305 | rc = 0; | ||
1306 | tx = txq->tx_head; | 1193 | tx = txq->tx_head; |
1307 | tx_desc = txq->tx_desc_area + tx; | 1194 | tx_desc = txq->tx_desc_area + tx; |
1308 | 1195 | ||
@@ -1321,56 +1208,30 @@ static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) | |||
1321 | priv->pending_tx_pkts--; | 1208 | priv->pending_tx_pkts--; |
1322 | 1209 | ||
1323 | addr = le32_to_cpu(tx_desc->pkt_phys_addr); | 1210 | addr = le32_to_cpu(tx_desc->pkt_phys_addr); |
1324 | size = (u32)(le16_to_cpu(tx_desc->pkt_len)); | 1211 | size = le16_to_cpu(tx_desc->pkt_len); |
1325 | skb = txq->tx_skb[tx].skb; | 1212 | skb = txq->tx_skb[tx]; |
1326 | txq->tx_skb[tx].skb = NULL; | 1213 | txq->tx_skb[tx] = NULL; |
1327 | 1214 | ||
1328 | BUG_ON(skb == NULL); | 1215 | BUG_ON(skb == NULL); |
1329 | pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); | 1216 | pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); |
1330 | 1217 | ||
1331 | rc = mwl8k_remove_dma_header(skb); | 1218 | mwl8k_remove_dma_header(skb); |
1332 | 1219 | ||
1333 | /* Mark descriptor as unused */ | 1220 | /* Mark descriptor as unused */ |
1334 | tx_desc->pkt_phys_addr = 0; | 1221 | tx_desc->pkt_phys_addr = 0; |
1335 | tx_desc->pkt_len = 0; | 1222 | tx_desc->pkt_len = 0; |
1336 | 1223 | ||
1337 | if (txq->tx_skb[tx].clone) { | ||
1338 | /* Replace with original skb | ||
1339 | * before returning to stack | ||
1340 | * as buffer has been cloned | ||
1341 | */ | ||
1342 | dev_kfree_skb(skb); | ||
1343 | skb = txq->tx_skb[tx].clone; | ||
1344 | txq->tx_skb[tx].clone = NULL; | ||
1345 | } | ||
1346 | |||
1347 | if (rc) { | ||
1348 | /* Something has gone wrong here. | ||
1349 | * Failed to remove DMA header. | ||
1350 | * Print error message and drop packet. | ||
1351 | */ | ||
1352 | printk(KERN_ERR "%s: Error removing DMA header from " | ||
1353 | "tx skb 0x%p.\n", priv->name, skb); | ||
1354 | |||
1355 | dev_kfree_skb(skb); | ||
1356 | continue; | ||
1357 | } | ||
1358 | |||
1359 | info = IEEE80211_SKB_CB(skb); | 1224 | info = IEEE80211_SKB_CB(skb); |
1360 | ieee80211_tx_info_clear_status(info); | 1225 | ieee80211_tx_info_clear_status(info); |
1361 | 1226 | if (MWL8K_TXD_SUCCESS(status)) | |
1362 | /* Convert firmware status stuff into tx_status */ | ||
1363 | if (MWL8K_TXD_SUCCESS(status)) { | ||
1364 | /* Transmit OK */ | ||
1365 | info->flags |= IEEE80211_TX_STAT_ACK; | 1227 | info->flags |= IEEE80211_TX_STAT_ACK; |
1366 | } | ||
1367 | 1228 | ||
1368 | ieee80211_tx_status_irqsafe(hw, skb); | 1229 | ieee80211_tx_status_irqsafe(hw, skb); |
1369 | 1230 | ||
1370 | wake = !priv->inconfig && priv->radio_state; | 1231 | wake = 1; |
1371 | } | 1232 | } |
1372 | 1233 | ||
1373 | if (wake) | 1234 | if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) |
1374 | ieee80211_wake_queue(hw, index); | 1235 | ieee80211_wake_queue(hw, index); |
1375 | } | 1236 | } |
1376 | 1237 | ||
@@ -1396,56 +1257,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1396 | { | 1257 | { |
1397 | struct mwl8k_priv *priv = hw->priv; | 1258 | struct mwl8k_priv *priv = hw->priv; |
1398 | struct ieee80211_tx_info *tx_info; | 1259 | struct ieee80211_tx_info *tx_info; |
1260 | struct mwl8k_vif *mwl8k_vif; | ||
1399 | struct ieee80211_hdr *wh; | 1261 | struct ieee80211_hdr *wh; |
1400 | struct mwl8k_tx_queue *txq; | 1262 | struct mwl8k_tx_queue *txq; |
1401 | struct mwl8k_tx_desc *tx; | 1263 | struct mwl8k_tx_desc *tx; |
1402 | struct mwl8k_dma_data *tr; | ||
1403 | struct mwl8k_vif *mwl8k_vif; | ||
1404 | struct sk_buff *org_skb = skb; | ||
1405 | dma_addr_t dma; | 1264 | dma_addr_t dma; |
1406 | u16 qos = 0; | 1265 | u32 txstatus; |
1407 | bool qosframe = false, ampduframe = false; | 1266 | u8 txdatarate; |
1408 | bool mcframe = false, eapolframe = false; | 1267 | u16 qos; |
1409 | bool amsduframe = false; | ||
1410 | __le16 fc; | ||
1411 | 1268 | ||
1412 | txq = priv->txq + index; | 1269 | wh = (struct ieee80211_hdr *)skb->data; |
1413 | tx = txq->tx_desc_area + txq->tx_tail; | 1270 | if (ieee80211_is_data_qos(wh->frame_control)) |
1414 | 1271 | qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); | |
1415 | BUG_ON(txq->tx_skb[txq->tx_tail].skb != NULL); | 1272 | else |
1416 | 1273 | qos = 0; | |
1417 | /* | ||
1418 | * Append HW DMA header to start of packet. Drop packet if | ||
1419 | * there is not enough space or a failure to unshare/unclone | ||
1420 | * the skb. | ||
1421 | */ | ||
1422 | skb = mwl8k_add_dma_header(skb); | ||
1423 | 1274 | ||
1424 | if (skb == NULL) { | 1275 | mwl8k_add_dma_header(skb); |
1425 | printk(KERN_DEBUG "%s: failed to prepend HW DMA " | 1276 | wh = &((struct mwl8k_dma_data *)skb->data)->wh; |
1426 | "header, dropping TX frame.\n", priv->name); | ||
1427 | dev_kfree_skb(org_skb); | ||
1428 | return NETDEV_TX_OK; | ||
1429 | } | ||
1430 | 1277 | ||
1431 | tx_info = IEEE80211_SKB_CB(skb); | 1278 | tx_info = IEEE80211_SKB_CB(skb); |
1432 | mwl8k_vif = MWL8K_VIF(tx_info->control.vif); | 1279 | mwl8k_vif = MWL8K_VIF(tx_info->control.vif); |
1433 | tr = (struct mwl8k_dma_data *)skb->data; | ||
1434 | wh = &tr->wh; | ||
1435 | fc = wh->frame_control; | ||
1436 | qosframe = ieee80211_is_data_qos(fc); | ||
1437 | mcframe = is_multicast_ether_addr(wh->addr1); | ||
1438 | ampduframe = !!(tx_info->flags & IEEE80211_TX_CTL_AMPDU); | ||
1439 | 1280 | ||
1440 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 1281 | if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
1441 | u16 seqno = mwl8k_vif->seqno; | 1282 | u16 seqno = mwl8k_vif->seqno; |
1283 | |||
1442 | wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 1284 | wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
1443 | wh->seq_ctrl |= cpu_to_le16(seqno << 4); | 1285 | wh->seq_ctrl |= cpu_to_le16(seqno << 4); |
1444 | mwl8k_vif->seqno = seqno++ % 4096; | 1286 | mwl8k_vif->seqno = seqno++ % 4096; |
1445 | } | 1287 | } |
1446 | 1288 | ||
1447 | if (qosframe) | 1289 | /* Setup firmware control bit fields for each frame type. */ |
1448 | qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); | 1290 | txstatus = 0; |
1291 | txdatarate = 0; | ||
1292 | if (ieee80211_is_mgmt(wh->frame_control) || | ||
1293 | ieee80211_is_ctl(wh->frame_control)) { | ||
1294 | txdatarate = 0; | ||
1295 | qos = mwl8k_qos_setbit_eosp(qos); | ||
1296 | /* Set Queue size to unspecified */ | ||
1297 | qos = mwl8k_qos_setbit_qlen(qos, 0xff); | ||
1298 | } else if (ieee80211_is_data(wh->frame_control)) { | ||
1299 | txdatarate = 1; | ||
1300 | if (is_multicast_ether_addr(wh->addr1)) | ||
1301 | txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; | ||
1302 | |||
1303 | /* Send pkt in an aggregate if AMPDU frame. */ | ||
1304 | if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) | ||
1305 | qos = mwl8k_qos_setbit_ack(qos, | ||
1306 | MWL8K_TXD_ACK_POLICY_BLOCKACK); | ||
1307 | else | ||
1308 | qos = mwl8k_qos_setbit_ack(qos, | ||
1309 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1310 | |||
1311 | if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) | ||
1312 | qos = mwl8k_qos_setbit_amsdu(qos); | ||
1313 | } | ||
1449 | 1314 | ||
1450 | dma = pci_map_single(priv->pdev, skb->data, | 1315 | dma = pci_map_single(priv->pdev, skb->data, |
1451 | skb->len, PCI_DMA_TODEVICE); | 1316 | skb->len, PCI_DMA_TODEVICE); |
@@ -1453,99 +1318,40 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1453 | if (pci_dma_mapping_error(priv->pdev, dma)) { | 1318 | if (pci_dma_mapping_error(priv->pdev, dma)) { |
1454 | printk(KERN_DEBUG "%s: failed to dma map skb, " | 1319 | printk(KERN_DEBUG "%s: failed to dma map skb, " |
1455 | "dropping TX frame.\n", priv->name); | 1320 | "dropping TX frame.\n", priv->name); |
1456 | 1321 | dev_kfree_skb(skb); | |
1457 | if (org_skb != NULL) | ||
1458 | dev_kfree_skb(org_skb); | ||
1459 | if (skb != NULL) | ||
1460 | dev_kfree_skb(skb); | ||
1461 | return NETDEV_TX_OK; | 1322 | return NETDEV_TX_OK; |
1462 | } | 1323 | } |
1463 | 1324 | ||
1464 | /* Set desc header, cpu bit order. */ | 1325 | spin_lock_bh(&priv->tx_lock); |
1465 | tx->status = 0; | ||
1466 | tx->data_rate = 0; | ||
1467 | tx->tx_priority = index; | ||
1468 | tx->qos_control = 0; | ||
1469 | tx->rate_info = 0; | ||
1470 | tx->peer_id = mwl8k_vif->peer_id; | ||
1471 | |||
1472 | amsduframe = !!(qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); | ||
1473 | |||
1474 | /* Setup firmware control bit fields for each frame type. */ | ||
1475 | if (ieee80211_is_mgmt(fc) || ieee80211_is_ctl(fc)) { | ||
1476 | tx->data_rate = 0; | ||
1477 | qos = mwl8k_qos_setbit_eosp(qos); | ||
1478 | /* Set Queue size to unspecified */ | ||
1479 | qos = mwl8k_qos_setbit_qlen(qos, 0xff); | ||
1480 | } else if (ieee80211_is_data(fc)) { | ||
1481 | tx->data_rate = 1; | ||
1482 | if (mcframe) | ||
1483 | tx->status |= MWL8K_TXD_STATUS_MULTICAST_TX; | ||
1484 | 1326 | ||
1485 | /* | 1327 | txq = priv->txq + index; |
1486 | * Tell firmware to not send EAPOL pkts in an | ||
1487 | * aggregate. Verify against mac80211 tx path. If | ||
1488 | * stack turns off AMPDU for an EAPOL frame this | ||
1489 | * check will be removed. | ||
1490 | */ | ||
1491 | if (eapolframe) { | ||
1492 | qos = mwl8k_qos_setbit_ack(qos, | ||
1493 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1494 | } else { | ||
1495 | /* Send pkt in an aggregate if AMPDU frame. */ | ||
1496 | if (ampduframe) | ||
1497 | qos = mwl8k_qos_setbit_ack(qos, | ||
1498 | MWL8K_TXD_ACK_POLICY_BLOCKACK); | ||
1499 | else | ||
1500 | qos = mwl8k_qos_setbit_ack(qos, | ||
1501 | MWL8K_TXD_ACK_POLICY_NORMAL); | ||
1502 | 1328 | ||
1503 | if (amsduframe) | 1329 | BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); |
1504 | qos = mwl8k_qos_setbit_amsdu(qos); | 1330 | txq->tx_skb[txq->tx_tail] = skb; |
1505 | } | ||
1506 | } | ||
1507 | 1331 | ||
1508 | /* Convert to little endian */ | 1332 | tx = txq->tx_desc_area + txq->tx_tail; |
1333 | tx->data_rate = txdatarate; | ||
1334 | tx->tx_priority = index; | ||
1509 | tx->qos_control = cpu_to_le16(qos); | 1335 | tx->qos_control = cpu_to_le16(qos); |
1510 | tx->status = cpu_to_le32(tx->status); | ||
1511 | tx->pkt_phys_addr = cpu_to_le32(dma); | 1336 | tx->pkt_phys_addr = cpu_to_le32(dma); |
1512 | tx->pkt_len = cpu_to_le16(skb->len); | 1337 | tx->pkt_len = cpu_to_le16(skb->len); |
1513 | 1338 | tx->rate_info = 0; | |
1514 | txq->tx_skb[txq->tx_tail].skb = skb; | 1339 | tx->peer_id = mwl8k_vif->peer_id; |
1515 | txq->tx_skb[txq->tx_tail].clone = | ||
1516 | skb == org_skb ? NULL : org_skb; | ||
1517 | |||
1518 | spin_lock_bh(&priv->tx_lock); | ||
1519 | |||
1520 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_OK | | ||
1521 | MWL8K_TXD_STATUS_FW_OWNED); | ||
1522 | wmb(); | 1340 | wmb(); |
1341 | tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); | ||
1342 | |||
1343 | txq->tx_stats.count++; | ||
1523 | txq->tx_stats.len++; | 1344 | txq->tx_stats.len++; |
1524 | priv->pending_tx_pkts++; | 1345 | priv->pending_tx_pkts++; |
1525 | txq->tx_stats.count++; | ||
1526 | txq->tx_tail++; | ||
1527 | 1346 | ||
1347 | txq->tx_tail++; | ||
1528 | if (txq->tx_tail == MWL8K_TX_DESCS) | 1348 | if (txq->tx_tail == MWL8K_TX_DESCS) |
1529 | txq->tx_tail = 0; | 1349 | txq->tx_tail = 0; |
1350 | |||
1530 | if (txq->tx_head == txq->tx_tail) | 1351 | if (txq->tx_head == txq->tx_tail) |
1531 | ieee80211_stop_queue(hw, index); | 1352 | ieee80211_stop_queue(hw, index); |
1532 | 1353 | ||
1533 | if (priv->inconfig) { | 1354 | mwl8k_tx_start(priv); |
1534 | /* | ||
1535 | * Silently queue packet when we are in the middle of | ||
1536 | * a config cycle. Notify firmware only if we are | ||
1537 | * waiting for TXQs to empty. If a packet is sent | ||
1538 | * before .config() is complete, perhaps it is better | ||
1539 | * to drop the packet, as the channel is being changed | ||
1540 | * and the packet will end up on the wrong channel. | ||
1541 | */ | ||
1542 | printk(KERN_ERR "%s(): WARNING TX activity while " | ||
1543 | "in config\n", __func__); | ||
1544 | |||
1545 | if (priv->tx_wait != NULL) | ||
1546 | mwl8k_tx_start(priv); | ||
1547 | } else | ||
1548 | mwl8k_tx_start(priv); | ||
1549 | 1355 | ||
1550 | spin_unlock_bh(&priv->tx_lock); | 1356 | spin_unlock_bh(&priv->tx_lock); |
1551 | 1357 | ||
@@ -1554,6 +1360,60 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1554 | 1360 | ||
1555 | 1361 | ||
1556 | /* | 1362 | /* |
1363 | * Firmware access. | ||
1364 | * | ||
1365 | * We have the following requirements for issuing firmware commands: | ||
1366 | * - Some commands require that the packet transmit path is idle when | ||
1367 | * the command is issued. (For simplicity, we'll just quiesce the | ||
1368 | * transmit path for every command.) | ||
1369 | * - There are certain sequences of commands that need to be issued to | ||
1370 | * the hardware sequentially, with no other intervening commands. | ||
1371 | * | ||
1372 | * This leads to an implementation of a "firmware lock" as a mutex that | ||
1373 | * can be taken recursively, and which is taken by both the low-level | ||
1374 | * command submission function (mwl8k_post_cmd) as well as any users of | ||
1375 | * that function that require issuing of an atomic sequence of commands, | ||
1376 | * and quiesces the transmit path whenever it's taken. | ||
1377 | */ | ||
1378 | static int mwl8k_fw_lock(struct ieee80211_hw *hw) | ||
1379 | { | ||
1380 | struct mwl8k_priv *priv = hw->priv; | ||
1381 | |||
1382 | if (priv->fw_mutex_owner != current) { | ||
1383 | int rc; | ||
1384 | |||
1385 | mutex_lock(&priv->fw_mutex); | ||
1386 | ieee80211_stop_queues(hw); | ||
1387 | |||
1388 | rc = mwl8k_tx_wait_empty(hw); | ||
1389 | if (rc) { | ||
1390 | ieee80211_wake_queues(hw); | ||
1391 | mutex_unlock(&priv->fw_mutex); | ||
1392 | |||
1393 | return rc; | ||
1394 | } | ||
1395 | |||
1396 | priv->fw_mutex_owner = current; | ||
1397 | } | ||
1398 | |||
1399 | priv->fw_mutex_depth++; | ||
1400 | |||
1401 | return 0; | ||
1402 | } | ||
1403 | |||
1404 | static void mwl8k_fw_unlock(struct ieee80211_hw *hw) | ||
1405 | { | ||
1406 | struct mwl8k_priv *priv = hw->priv; | ||
1407 | |||
1408 | if (!--priv->fw_mutex_depth) { | ||
1409 | ieee80211_wake_queues(hw); | ||
1410 | priv->fw_mutex_owner = NULL; | ||
1411 | mutex_unlock(&priv->fw_mutex); | ||
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | |||
1416 | /* | ||
1557 | * Command processing. | 1417 | * Command processing. |
1558 | */ | 1418 | */ |
1559 | 1419 | ||
@@ -1568,7 +1428,6 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) | |||
1568 | dma_addr_t dma_addr; | 1428 | dma_addr_t dma_addr; |
1569 | unsigned int dma_size; | 1429 | unsigned int dma_size; |
1570 | int rc; | 1430 | int rc; |
1571 | u16 __iomem *result; | ||
1572 | unsigned long timeout = 0; | 1431 | unsigned long timeout = 0; |
1573 | u8 buf[32]; | 1432 | u8 buf[32]; |
1574 | 1433 | ||
@@ -1579,41 +1438,40 @@ static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) | |||
1579 | if (pci_dma_mapping_error(priv->pdev, dma_addr)) | 1438 | if (pci_dma_mapping_error(priv->pdev, dma_addr)) |
1580 | return -ENOMEM; | 1439 | return -ENOMEM; |
1581 | 1440 | ||
1582 | if (priv->hostcmd_wait != NULL) | 1441 | rc = mwl8k_fw_lock(hw); |
1583 | printk(KERN_ERR "WARNING host command in progress\n"); | 1442 | if (rc) |
1443 | return rc; | ||
1584 | 1444 | ||
1585 | spin_lock_irq(&priv->fw_lock); | ||
1586 | priv->hostcmd_wait = &cmd_wait; | 1445 | priv->hostcmd_wait = &cmd_wait; |
1587 | iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); | 1446 | iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); |
1588 | iowrite32(MWL8K_H2A_INT_DOORBELL, | 1447 | iowrite32(MWL8K_H2A_INT_DOORBELL, |
1589 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | 1448 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); |
1590 | iowrite32(MWL8K_H2A_INT_DUMMY, | 1449 | iowrite32(MWL8K_H2A_INT_DUMMY, |
1591 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); | 1450 | regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); |
1592 | spin_unlock_irq(&priv->fw_lock); | ||
1593 | 1451 | ||
1594 | timeout = wait_for_completion_timeout(&cmd_wait, | 1452 | timeout = wait_for_completion_timeout(&cmd_wait, |
1595 | msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); | 1453 | msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); |
1596 | 1454 | ||
1455 | priv->hostcmd_wait = NULL; | ||
1456 | |||
1457 | mwl8k_fw_unlock(hw); | ||
1458 | |||
1597 | pci_unmap_single(priv->pdev, dma_addr, dma_size, | 1459 | pci_unmap_single(priv->pdev, dma_addr, dma_size, |
1598 | PCI_DMA_BIDIRECTIONAL); | 1460 | PCI_DMA_BIDIRECTIONAL); |
1599 | 1461 | ||
1600 | result = &cmd->result; | ||
1601 | if (!timeout) { | 1462 | if (!timeout) { |
1602 | spin_lock_irq(&priv->fw_lock); | ||
1603 | priv->hostcmd_wait = NULL; | ||
1604 | spin_unlock_irq(&priv->fw_lock); | ||
1605 | printk(KERN_ERR "%s: Command %s timeout after %u ms\n", | 1463 | printk(KERN_ERR "%s: Command %s timeout after %u ms\n", |
1606 | priv->name, | 1464 | priv->name, |
1607 | mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), | 1465 | mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), |
1608 | MWL8K_CMD_TIMEOUT_MS); | 1466 | MWL8K_CMD_TIMEOUT_MS); |
1609 | rc = -ETIMEDOUT; | 1467 | rc = -ETIMEDOUT; |
1610 | } else { | 1468 | } else { |
1611 | rc = *result ? -EINVAL : 0; | 1469 | rc = cmd->result ? -EINVAL : 0; |
1612 | if (rc) | 1470 | if (rc) |
1613 | printk(KERN_ERR "%s: Command %s error 0x%x\n", | 1471 | printk(KERN_ERR "%s: Command %s error 0x%x\n", |
1614 | priv->name, | 1472 | priv->name, |
1615 | mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), | 1473 | mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), |
1616 | *result); | 1474 | cmd->result); |
1617 | } | 1475 | } |
1618 | 1476 | ||
1619 | return rc; | 1477 | return rc; |
@@ -1627,7 +1485,7 @@ struct mwl8k_cmd_get_hw_spec { | |||
1627 | __u8 hw_rev; | 1485 | __u8 hw_rev; |
1628 | __u8 host_interface; | 1486 | __u8 host_interface; |
1629 | __le16 num_mcaddrs; | 1487 | __le16 num_mcaddrs; |
1630 | __u8 perm_addr[IEEE80211_ADDR_LEN]; | 1488 | __u8 perm_addr[ETH_ALEN]; |
1631 | __le16 region_code; | 1489 | __le16 region_code; |
1632 | __le32 fw_rev; | 1490 | __le32 fw_rev; |
1633 | __le32 ps_cookie; | 1491 | __le32 ps_cookie; |
@@ -1671,7 +1529,6 @@ static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) | |||
1671 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); | 1529 | priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); |
1672 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); | 1530 | priv->fw_rev = le32_to_cpu(cmd->fw_rev); |
1673 | priv->hw_rev = cmd->hw_rev; | 1531 | priv->hw_rev = cmd->hw_rev; |
1674 | priv->region_code = le16_to_cpu(cmd->region_code); | ||
1675 | } | 1532 | } |
1676 | 1533 | ||
1677 | kfree(cmd); | 1534 | kfree(cmd); |
@@ -1685,41 +1542,44 @@ struct mwl8k_cmd_mac_multicast_adr { | |||
1685 | struct mwl8k_cmd_pkt header; | 1542 | struct mwl8k_cmd_pkt header; |
1686 | __le16 action; | 1543 | __le16 action; |
1687 | __le16 numaddr; | 1544 | __le16 numaddr; |
1688 | __u8 addr[1][IEEE80211_ADDR_LEN]; | 1545 | __u8 addr[0][ETH_ALEN]; |
1689 | }; | 1546 | }; |
1690 | 1547 | ||
1691 | #define MWL8K_ENABLE_RX_MULTICAST 0x000F | 1548 | #define MWL8K_ENABLE_RX_MULTICAST 0x000F |
1692 | static int mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, | 1549 | |
1693 | int mc_count, | 1550 | static struct mwl8k_cmd_pkt * |
1694 | struct dev_addr_list *mclist) | 1551 | __mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, |
1552 | int mc_count, struct dev_addr_list *mclist) | ||
1695 | { | 1553 | { |
1554 | struct mwl8k_priv *priv = hw->priv; | ||
1696 | struct mwl8k_cmd_mac_multicast_adr *cmd; | 1555 | struct mwl8k_cmd_mac_multicast_adr *cmd; |
1697 | int index = 0; | 1556 | int size; |
1698 | int rc; | 1557 | int i; |
1699 | int size = sizeof(*cmd) + ((mc_count - 1) * IEEE80211_ADDR_LEN); | 1558 | |
1700 | cmd = kzalloc(size, GFP_KERNEL); | 1559 | if (mc_count > priv->num_mcaddrs) |
1560 | mc_count = priv->num_mcaddrs; | ||
1561 | |||
1562 | size = sizeof(*cmd) + mc_count * ETH_ALEN; | ||
1563 | |||
1564 | cmd = kzalloc(size, GFP_ATOMIC); | ||
1701 | if (cmd == NULL) | 1565 | if (cmd == NULL) |
1702 | return -ENOMEM; | 1566 | return NULL; |
1703 | 1567 | ||
1704 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); | 1568 | cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); |
1705 | cmd->header.length = cpu_to_le16(size); | 1569 | cmd->header.length = cpu_to_le16(size); |
1706 | cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); | 1570 | cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); |
1707 | cmd->numaddr = cpu_to_le16(mc_count); | 1571 | cmd->numaddr = cpu_to_le16(mc_count); |
1708 | while ((index < mc_count) && mclist) { | 1572 | |
1709 | if (mclist->da_addrlen != IEEE80211_ADDR_LEN) { | 1573 | for (i = 0; i < mc_count && mclist; i++) { |
1710 | rc = -EINVAL; | 1574 | if (mclist->da_addrlen != ETH_ALEN) { |
1711 | goto mwl8k_cmd_mac_multicast_adr_exit; | 1575 | kfree(cmd); |
1576 | return NULL; | ||
1712 | } | 1577 | } |
1713 | memcpy(cmd->addr[index], mclist->da_addr, IEEE80211_ADDR_LEN); | 1578 | memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); |
1714 | index++; | ||
1715 | mclist = mclist->next; | 1579 | mclist = mclist->next; |
1716 | } | 1580 | } |
1717 | 1581 | ||
1718 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1582 | return &cmd->header; |
1719 | |||
1720 | mwl8k_cmd_mac_multicast_adr_exit: | ||
1721 | kfree(cmd); | ||
1722 | return rc; | ||
1723 | } | 1583 | } |
1724 | 1584 | ||
1725 | /* | 1585 | /* |
@@ -1776,18 +1636,16 @@ struct mwl8k_cmd_802_11_radio_control { | |||
1776 | __le16 radio_on; | 1636 | __le16 radio_on; |
1777 | } __attribute__((packed)); | 1637 | } __attribute__((packed)); |
1778 | 1638 | ||
1779 | static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable) | 1639 | static int |
1640 | mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) | ||
1780 | { | 1641 | { |
1781 | struct mwl8k_priv *priv = hw->priv; | 1642 | struct mwl8k_priv *priv = hw->priv; |
1782 | struct mwl8k_cmd_802_11_radio_control *cmd; | 1643 | struct mwl8k_cmd_802_11_radio_control *cmd; |
1783 | int rc; | 1644 | int rc; |
1784 | 1645 | ||
1785 | if (((enable & MWL8K_RADIO_ENABLE) == priv->radio_state) && | 1646 | if (enable == priv->radio_on && !force) |
1786 | !(enable & MWL8K_RADIO_FORCE)) | ||
1787 | return 0; | 1647 | return 0; |
1788 | 1648 | ||
1789 | enable &= MWL8K_RADIO_ENABLE; | ||
1790 | |||
1791 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 1649 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
1792 | if (cmd == NULL) | 1650 | if (cmd == NULL) |
1793 | return -ENOMEM; | 1651 | return -ENOMEM; |
@@ -1795,18 +1653,28 @@ static int mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, int enable) | |||
1795 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); | 1653 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); |
1796 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 1654 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
1797 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 1655 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
1798 | cmd->control = cpu_to_le16(priv->radio_preamble); | 1656 | cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1); |
1799 | cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); | 1657 | cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); |
1800 | 1658 | ||
1801 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1659 | rc = mwl8k_post_cmd(hw, &cmd->header); |
1802 | kfree(cmd); | 1660 | kfree(cmd); |
1803 | 1661 | ||
1804 | if (!rc) | 1662 | if (!rc) |
1805 | priv->radio_state = enable; | 1663 | priv->radio_on = enable; |
1806 | 1664 | ||
1807 | return rc; | 1665 | return rc; |
1808 | } | 1666 | } |
1809 | 1667 | ||
1668 | static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) | ||
1669 | { | ||
1670 | return mwl8k_cmd_802_11_radio_control(hw, 0, 0); | ||
1671 | } | ||
1672 | |||
1673 | static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) | ||
1674 | { | ||
1675 | return mwl8k_cmd_802_11_radio_control(hw, 1, 0); | ||
1676 | } | ||
1677 | |||
1810 | static int | 1678 | static int |
1811 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) | 1679 | mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) |
1812 | { | 1680 | { |
@@ -1816,12 +1684,9 @@ mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) | |||
1816 | return -EINVAL; | 1684 | return -EINVAL; |
1817 | priv = hw->priv; | 1685 | priv = hw->priv; |
1818 | 1686 | ||
1819 | priv->radio_preamble = (short_preamble ? | 1687 | priv->radio_short_preamble = short_preamble; |
1820 | MWL8K_RADIO_SHORT_PREAMBLE : | ||
1821 | MWL8K_RADIO_LONG_PREAMBLE); | ||
1822 | 1688 | ||
1823 | return mwl8k_cmd_802_11_radio_control(hw, | 1689 | return mwl8k_cmd_802_11_radio_control(hw, 1, 1); |
1824 | MWL8K_RADIO_ENABLE | MWL8K_RADIO_FORCE); | ||
1825 | } | 1690 | } |
1826 | 1691 | ||
1827 | /* | 1692 | /* |
@@ -1889,11 +1754,11 @@ static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) | |||
1889 | struct mwl8k_cmd_set_post_scan { | 1754 | struct mwl8k_cmd_set_post_scan { |
1890 | struct mwl8k_cmd_pkt header; | 1755 | struct mwl8k_cmd_pkt header; |
1891 | __le32 isibss; | 1756 | __le32 isibss; |
1892 | __u8 bssid[IEEE80211_ADDR_LEN]; | 1757 | __u8 bssid[ETH_ALEN]; |
1893 | } __attribute__((packed)); | 1758 | } __attribute__((packed)); |
1894 | 1759 | ||
1895 | static int | 1760 | static int |
1896 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN]) | 1761 | mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac) |
1897 | { | 1762 | { |
1898 | struct mwl8k_cmd_set_post_scan *cmd; | 1763 | struct mwl8k_cmd_set_post_scan *cmd; |
1899 | int rc; | 1764 | int rc; |
@@ -1905,7 +1770,7 @@ mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 mac[IEEE80211_ADDR_LEN]) | |||
1905 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); | 1770 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); |
1906 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 1771 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
1907 | cmd->isibss = 0; | 1772 | cmd->isibss = 0; |
1908 | memcpy(cmd->bssid, mac, IEEE80211_ADDR_LEN); | 1773 | memcpy(cmd->bssid, mac, ETH_ALEN); |
1909 | 1774 | ||
1910 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1775 | rc = mwl8k_post_cmd(hw, &cmd->header); |
1911 | kfree(cmd); | 1776 | kfree(cmd); |
@@ -1957,7 +1822,7 @@ struct mwl8k_cmd_set_slot { | |||
1957 | __u8 short_slot; | 1822 | __u8 short_slot; |
1958 | } __attribute__((packed)); | 1823 | } __attribute__((packed)); |
1959 | 1824 | ||
1960 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time) | 1825 | static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) |
1961 | { | 1826 | { |
1962 | struct mwl8k_cmd_set_slot *cmd; | 1827 | struct mwl8k_cmd_set_slot *cmd; |
1963 | int rc; | 1828 | int rc; |
@@ -1969,7 +1834,7 @@ static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, int slot_time) | |||
1969 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); | 1834 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); |
1970 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 1835 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
1971 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); | 1836 | cmd->action = cpu_to_le16(MWL8K_CMD_SET); |
1972 | cmd->short_slot = slot_time == MWL8K_SHORT_SLOTTIME ? 1 : 0; | 1837 | cmd->short_slot = short_slot_time; |
1973 | 1838 | ||
1974 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1839 | rc = mwl8k_post_cmd(hw, &cmd->header); |
1975 | kfree(cmd); | 1840 | kfree(cmd); |
@@ -2027,7 +1892,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | |||
2027 | 1892 | ||
2028 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); | 1893 | cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); |
2029 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 1894 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2030 | cmd->action = enable ? cpu_to_le32((u32)MWL8K_CMD_SET) : 0; | 1895 | cmd->action = cpu_to_le32(!!enable); |
2031 | 1896 | ||
2032 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1897 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2033 | kfree(cmd); | 1898 | kfree(cmd); |
@@ -2036,7 +1901,7 @@ static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) | |||
2036 | } | 1901 | } |
2037 | 1902 | ||
2038 | /* | 1903 | /* |
2039 | * CMD_SET_RATE_ADAPT_MODE. | 1904 | * CMD_SET_RATEADAPT_MODE. |
2040 | */ | 1905 | */ |
2041 | struct mwl8k_cmd_set_rate_adapt_mode { | 1906 | struct mwl8k_cmd_set_rate_adapt_mode { |
2042 | struct mwl8k_cmd_pkt header; | 1907 | struct mwl8k_cmd_pkt header; |
@@ -2084,13 +1949,13 @@ static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) | |||
2084 | 1949 | ||
2085 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); | 1950 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); |
2086 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 1951 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2087 | cmd->action = enable ? cpu_to_le16(MWL8K_CMD_SET) : 0; | 1952 | cmd->action = cpu_to_le16(!!enable); |
2088 | 1953 | ||
2089 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1954 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2090 | kfree(cmd); | 1955 | kfree(cmd); |
2091 | 1956 | ||
2092 | if (!rc) | 1957 | if (!rc) |
2093 | priv->wmm_mode = enable; | 1958 | priv->wmm_enabled = enable; |
2094 | 1959 | ||
2095 | return rc; | 1960 | return rc; |
2096 | } | 1961 | } |
@@ -2105,7 +1970,7 @@ struct mwl8k_cmd_rts_threshold { | |||
2105 | } __attribute__((packed)); | 1970 | } __attribute__((packed)); |
2106 | 1971 | ||
2107 | static int mwl8k_rts_threshold(struct ieee80211_hw *hw, | 1972 | static int mwl8k_rts_threshold(struct ieee80211_hw *hw, |
2108 | u16 action, u16 *threshold) | 1973 | u16 action, u16 threshold) |
2109 | { | 1974 | { |
2110 | struct mwl8k_cmd_rts_threshold *cmd; | 1975 | struct mwl8k_cmd_rts_threshold *cmd; |
2111 | int rc; | 1976 | int rc; |
@@ -2117,7 +1982,7 @@ static int mwl8k_rts_threshold(struct ieee80211_hw *hw, | |||
2117 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); | 1982 | cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); |
2118 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 1983 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2119 | cmd->action = cpu_to_le16(action); | 1984 | cmd->action = cpu_to_le16(action); |
2120 | cmd->threshold = cpu_to_le16(*threshold); | 1985 | cmd->threshold = cpu_to_le16(threshold); |
2121 | 1986 | ||
2122 | rc = mwl8k_post_cmd(hw, &cmd->header); | 1987 | rc = mwl8k_post_cmd(hw, &cmd->header); |
2123 | kfree(cmd); | 1988 | kfree(cmd); |
@@ -2150,7 +2015,6 @@ struct mwl8k_cmd_set_edca_params { | |||
2150 | __u8 txq; | 2015 | __u8 txq; |
2151 | } __attribute__((packed)); | 2016 | } __attribute__((packed)); |
2152 | 2017 | ||
2153 | #define MWL8K_GET_EDCA_ALL 0 | ||
2154 | #define MWL8K_SET_EDCA_CW 0x01 | 2018 | #define MWL8K_SET_EDCA_CW 0x01 |
2155 | #define MWL8K_SET_EDCA_TXOP 0x02 | 2019 | #define MWL8K_SET_EDCA_TXOP 0x02 |
2156 | #define MWL8K_SET_EDCA_AIFS 0x04 | 2020 | #define MWL8K_SET_EDCA_AIFS 0x04 |
@@ -2165,22 +2029,18 @@ mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, | |||
2165 | __u8 aifs, __u16 txop) | 2029 | __u8 aifs, __u16 txop) |
2166 | { | 2030 | { |
2167 | struct mwl8k_cmd_set_edca_params *cmd; | 2031 | struct mwl8k_cmd_set_edca_params *cmd; |
2168 | u32 log_cw_min, log_cw_max; | ||
2169 | int rc; | 2032 | int rc; |
2170 | 2033 | ||
2171 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); | 2034 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
2172 | if (cmd == NULL) | 2035 | if (cmd == NULL) |
2173 | return -ENOMEM; | 2036 | return -ENOMEM; |
2174 | 2037 | ||
2175 | log_cw_min = ilog2(cw_min+1); | ||
2176 | log_cw_max = ilog2(cw_max+1); | ||
2177 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); | 2038 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); |
2178 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2039 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2179 | |||
2180 | cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); | 2040 | cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); |
2181 | cmd->txop = cpu_to_le16(txop); | 2041 | cmd->txop = cpu_to_le16(txop); |
2182 | cmd->log_cw_max = (u8)log_cw_max; | 2042 | cmd->log_cw_max = (u8)ilog2(cw_max + 1); |
2183 | cmd->log_cw_min = (u8)log_cw_min; | 2043 | cmd->log_cw_min = (u8)ilog2(cw_min + 1); |
2184 | cmd->aifs = aifs; | 2044 | cmd->aifs = aifs; |
2185 | cmd->txq = qnum; | 2045 | cmd->txq = qnum; |
2186 | 2046 | ||
@@ -2221,11 +2081,7 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, | |||
2221 | 2081 | ||
2222 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); | 2082 | cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); |
2223 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2083 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2224 | 2084 | cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); | |
2225 | if (dtim) | ||
2226 | cmd->sleep_interval = cpu_to_le32(dtim); | ||
2227 | else | ||
2228 | cmd->sleep_interval = cpu_to_le32(1); | ||
2229 | 2085 | ||
2230 | hdrlen = ieee80211_hdrlen(payload->frame_control); | 2086 | hdrlen = ieee80211_hdrlen(payload->frame_control); |
2231 | 2087 | ||
@@ -2237,8 +2093,8 @@ static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, | |||
2237 | "sent to firmware. Sz=%u MAX=%u\n", __func__, | 2093 | "sent to firmware. Sz=%u MAX=%u\n", __func__, |
2238 | payload_len, MWL8K_FJ_BEACON_MAXLEN); | 2094 | payload_len, MWL8K_FJ_BEACON_MAXLEN); |
2239 | 2095 | ||
2240 | payload_len = payload_len > MWL8K_FJ_BEACON_MAXLEN ? | 2096 | if (payload_len > MWL8K_FJ_BEACON_MAXLEN) |
2241 | MWL8K_FJ_BEACON_MAXLEN : payload_len; | 2097 | payload_len = MWL8K_FJ_BEACON_MAXLEN; |
2242 | 2098 | ||
2243 | if (payload && payload_len) | 2099 | if (payload && payload_len) |
2244 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); | 2100 | memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); |
@@ -2258,7 +2114,7 @@ struct mwl8k_cmd_update_sta_db { | |||
2258 | __le32 action; | 2114 | __le32 action; |
2259 | 2115 | ||
2260 | /* Peer MAC address */ | 2116 | /* Peer MAC address */ |
2261 | __u8 peer_addr[IEEE80211_ADDR_LEN]; | 2117 | __u8 peer_addr[ETH_ALEN]; |
2262 | 2118 | ||
2263 | __le32 reserved; | 2119 | __le32 reserved; |
2264 | 2120 | ||
@@ -2286,7 +2142,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | |||
2286 | 2142 | ||
2287 | cmd->action = cpu_to_le32(action); | 2143 | cmd->action = cpu_to_le32(action); |
2288 | peer_info = &cmd->peer_info; | 2144 | peer_info = &cmd->peer_info; |
2289 | memcpy(cmd->peer_addr, mv_vif->bssid, IEEE80211_ADDR_LEN); | 2145 | memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); |
2290 | 2146 | ||
2291 | switch (action) { | 2147 | switch (action) { |
2292 | case MWL8K_STA_DB_ADD_ENTRY: | 2148 | case MWL8K_STA_DB_ADD_ENTRY: |
@@ -2298,7 +2154,7 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | |||
2298 | peer_info->amsdu_enabled = 0; | 2154 | peer_info->amsdu_enabled = 0; |
2299 | 2155 | ||
2300 | rates = peer_info->legacy_rates; | 2156 | rates = peer_info->legacy_rates; |
2301 | for (count = 0 ; count < mv_vif->legacy_nrates; count++) | 2157 | for (count = 0; count < mv_vif->legacy_nrates; count++) |
2302 | rates[count] = bitrates[count].hw_value; | 2158 | rates[count] = bitrates[count].hw_value; |
2303 | 2159 | ||
2304 | rc = mwl8k_post_cmd(hw, &cmd->header); | 2160 | rc = mwl8k_post_cmd(hw, &cmd->header); |
@@ -2323,25 +2179,19 @@ static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, | |||
2323 | /* | 2179 | /* |
2324 | * CMD_SET_AID. | 2180 | * CMD_SET_AID. |
2325 | */ | 2181 | */ |
2326 | #define IEEE80211_OPMODE_DISABLED 0x00 | ||
2327 | #define IEEE80211_OPMODE_NON_MEMBER_PROT_MODE 0x01 | ||
2328 | #define IEEE80211_OPMODE_ONE_20MHZ_STA_PROT_MODE 0x02 | ||
2329 | #define IEEE80211_OPMODE_HTMIXED_PROT_MODE 0x03 | ||
2330 | |||
2331 | #define MWL8K_RATE_INDEX_MAX_ARRAY 14 | 2182 | #define MWL8K_RATE_INDEX_MAX_ARRAY 14 |
2332 | 2183 | ||
2333 | #define MWL8K_FRAME_PROT_DISABLED 0x00 | 2184 | #define MWL8K_FRAME_PROT_DISABLED 0x00 |
2334 | #define MWL8K_FRAME_PROT_11G 0x07 | 2185 | #define MWL8K_FRAME_PROT_11G 0x07 |
2335 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 | 2186 | #define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 |
2336 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 | 2187 | #define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 |
2337 | #define MWL8K_FRAME_PROT_MASK 0x07 | ||
2338 | 2188 | ||
2339 | struct mwl8k_cmd_update_set_aid { | 2189 | struct mwl8k_cmd_update_set_aid { |
2340 | struct mwl8k_cmd_pkt header; | 2190 | struct mwl8k_cmd_pkt header; |
2341 | __le16 aid; | 2191 | __le16 aid; |
2342 | 2192 | ||
2343 | /* AP's MAC address (BSSID) */ | 2193 | /* AP's MAC address (BSSID) */ |
2344 | __u8 bssid[IEEE80211_ADDR_LEN]; | 2194 | __u8 bssid[ETH_ALEN]; |
2345 | __le16 protection_mode; | 2195 | __le16 protection_mode; |
2346 | __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; | 2196 | __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; |
2347 | } __attribute__((packed)); | 2197 | } __attribute__((packed)); |
@@ -2365,9 +2215,7 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | |||
2365 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); | 2215 | cmd->header.length = cpu_to_le16(sizeof(*cmd)); |
2366 | cmd->aid = cpu_to_le16(info->aid); | 2216 | cmd->aid = cpu_to_le16(info->aid); |
2367 | 2217 | ||
2368 | memcpy(cmd->bssid, mv_vif->bssid, IEEE80211_ADDR_LEN); | 2218 | memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); |
2369 | |||
2370 | prot_mode = MWL8K_FRAME_PROT_DISABLED; | ||
2371 | 2219 | ||
2372 | if (info->use_cts_prot) { | 2220 | if (info->use_cts_prot) { |
2373 | prot_mode = MWL8K_FRAME_PROT_11G; | 2221 | prot_mode = MWL8K_FRAME_PROT_11G; |
@@ -2385,7 +2233,6 @@ static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, | |||
2385 | break; | 2233 | break; |
2386 | } | 2234 | } |
2387 | } | 2235 | } |
2388 | |||
2389 | cmd->protection_mode = cpu_to_le16(prot_mode); | 2236 | cmd->protection_mode = cpu_to_le16(prot_mode); |
2390 | 2237 | ||
2391 | for (count = 0; count < mv_vif->legacy_nrates; count++) | 2238 | for (count = 0; count < mv_vif->legacy_nrates; count++) |
@@ -2439,10 +2286,6 @@ static int mwl8k_update_rateset(struct ieee80211_hw *hw, | |||
2439 | */ | 2286 | */ |
2440 | #define MWL8K_RATE_TABLE_SIZE 8 | 2287 | #define MWL8K_RATE_TABLE_SIZE 8 |
2441 | #define MWL8K_UCAST_RATE 0 | 2288 | #define MWL8K_UCAST_RATE 0 |
2442 | #define MWL8K_MCAST_RATE 1 | ||
2443 | #define MWL8K_BCAST_RATE 2 | ||
2444 | |||
2445 | #define MWL8K_USE_FIXED_RATE 0x0001 | ||
2446 | #define MWL8K_USE_AUTO_RATE 0x0002 | 2289 | #define MWL8K_USE_AUTO_RATE 0x0002 |
2447 | 2290 | ||
2448 | struct mwl8k_rate_entry { | 2291 | struct mwl8k_rate_entry { |
@@ -2535,7 +2378,6 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) | |||
2535 | status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | 2378 | status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); |
2536 | iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | 2379 | iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); |
2537 | 2380 | ||
2538 | status &= priv->int_mask; | ||
2539 | if (!status) | 2381 | if (!status) |
2540 | return IRQ_NONE; | 2382 | return IRQ_NONE; |
2541 | 2383 | ||
@@ -2548,17 +2390,14 @@ static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) | |||
2548 | } | 2390 | } |
2549 | 2391 | ||
2550 | if (status & MWL8K_A2H_INT_OPC_DONE) { | 2392 | if (status & MWL8K_A2H_INT_OPC_DONE) { |
2551 | if (priv->hostcmd_wait != NULL) { | 2393 | if (priv->hostcmd_wait != NULL) |
2552 | complete(priv->hostcmd_wait); | 2394 | complete(priv->hostcmd_wait); |
2553 | priv->hostcmd_wait = NULL; | ||
2554 | } | ||
2555 | } | 2395 | } |
2556 | 2396 | ||
2557 | if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { | 2397 | if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { |
2558 | if (!priv->inconfig && | 2398 | if (!mutex_is_locked(&priv->fw_mutex) && |
2559 | priv->radio_state && | 2399 | priv->radio_on && mwl8k_txq_busy(priv)) |
2560 | mwl8k_txq_busy(priv)) | 2400 | mwl8k_tx_start(priv); |
2561 | mwl8k_tx_start(priv); | ||
2562 | } | 2401 | } |
2563 | 2402 | ||
2564 | return IRQ_HANDLED; | 2403 | return IRQ_HANDLED; |
@@ -2586,365 +2425,68 @@ static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2586 | return rc; | 2425 | return rc; |
2587 | } | 2426 | } |
2588 | 2427 | ||
2589 | struct mwl8k_work_struct { | ||
2590 | /* Initialized by mwl8k_queue_work(). */ | ||
2591 | struct work_struct wt; | ||
2592 | |||
2593 | /* Required field passed in to mwl8k_queue_work(). */ | ||
2594 | struct ieee80211_hw *hw; | ||
2595 | |||
2596 | /* Required field passed in to mwl8k_queue_work(). */ | ||
2597 | int (*wfunc)(struct work_struct *w); | ||
2598 | |||
2599 | /* Initialized by mwl8k_queue_work(). */ | ||
2600 | struct completion *cmd_wait; | ||
2601 | |||
2602 | /* Result code. */ | ||
2603 | int rc; | ||
2604 | |||
2605 | /* | ||
2606 | * Optional field. Refer to explanation of MWL8K_WQ_XXX_XXX | ||
2607 | * flags for explanation. Defaults to MWL8K_WQ_DEFAULT_OPTIONS. | ||
2608 | */ | ||
2609 | u32 options; | ||
2610 | |||
2611 | /* Optional field. Defaults to MWL8K_CONFIG_TIMEOUT_MS. */ | ||
2612 | unsigned long timeout_ms; | ||
2613 | |||
2614 | /* Optional field. Defaults to MWL8K_WQ_TXWAIT_ATTEMPTS. */ | ||
2615 | u32 txwait_attempts; | ||
2616 | |||
2617 | /* Optional field. Defaults to MWL8K_TXWAIT_MS. */ | ||
2618 | u32 tx_timeout_ms; | ||
2619 | u32 step; | ||
2620 | }; | ||
2621 | |||
2622 | /* Flags controlling behavior of config queue requests */ | ||
2623 | |||
2624 | /* Caller spins while waiting for completion. */ | ||
2625 | #define MWL8K_WQ_SPIN 0x00000001 | ||
2626 | |||
2627 | /* Wait for TX queues to empty before proceeding with configuration. */ | ||
2628 | #define MWL8K_WQ_TX_WAIT_EMPTY 0x00000002 | ||
2629 | |||
2630 | /* Queue request and return immediately. */ | ||
2631 | #define MWL8K_WQ_POST_REQUEST 0x00000004 | ||
2632 | |||
2633 | /* | ||
2634 | * Caller sleeps and waits for task complete notification. | ||
2635 | * Do not use in atomic context. | ||
2636 | */ | ||
2637 | #define MWL8K_WQ_SLEEP 0x00000008 | ||
2638 | |||
2639 | /* Free work struct when task is done. */ | ||
2640 | #define MWL8K_WQ_FREE_WORKSTRUCT 0x00000010 | ||
2641 | |||
2642 | /* | ||
2643 | * Config request is queued and returns to caller imediately. Use | ||
2644 | * this in atomic context. Work struct is freed by mwl8k_queue_work() | ||
2645 | * when this flag is set. | ||
2646 | */ | ||
2647 | #define MWL8K_WQ_QUEUE_ONLY (MWL8K_WQ_POST_REQUEST | \ | ||
2648 | MWL8K_WQ_FREE_WORKSTRUCT) | ||
2649 | |||
2650 | /* Default work queue behavior is to sleep and wait for tx completion. */ | ||
2651 | #define MWL8K_WQ_DEFAULT_OPTIONS (MWL8K_WQ_SLEEP | MWL8K_WQ_TX_WAIT_EMPTY) | ||
2652 | |||
2653 | /* | ||
2654 | * Default config request timeout. Add adjustments to make sure the | ||
2655 | * config thread waits long enough for both tx wait and cmd wait before | ||
2656 | * timing out. | ||
2657 | */ | ||
2658 | |||
2659 | /* Time to wait for all TXQs to drain. TX Doorbell is pressed each time. */ | ||
2660 | #define MWL8K_TXWAIT_TIMEOUT_MS 1000 | ||
2661 | |||
2662 | /* Default number of TX wait attempts. */ | ||
2663 | #define MWL8K_WQ_TXWAIT_ATTEMPTS 4 | ||
2664 | |||
2665 | /* Total time to wait for TXQ to drain. */ | ||
2666 | #define MWL8K_TXWAIT_MS (MWL8K_TXWAIT_TIMEOUT_MS * \ | ||
2667 | MWL8K_WQ_TXWAIT_ATTEMPTS) | ||
2668 | |||
2669 | /* Scheduling slop. */ | ||
2670 | #define MWL8K_OS_SCHEDULE_OVERHEAD_MS 200 | ||
2671 | |||
2672 | #define MWL8K_CONFIG_TIMEOUT_MS (MWL8K_CMD_TIMEOUT_MS + \ | ||
2673 | MWL8K_TXWAIT_MS + \ | ||
2674 | MWL8K_OS_SCHEDULE_OVERHEAD_MS) | ||
2675 | |||
2676 | static void mwl8k_config_thread(struct work_struct *wt) | ||
2677 | { | ||
2678 | struct mwl8k_work_struct *worker = (struct mwl8k_work_struct *)wt; | ||
2679 | struct ieee80211_hw *hw = worker->hw; | ||
2680 | struct mwl8k_priv *priv = hw->priv; | ||
2681 | int rc = 0; | ||
2682 | |||
2683 | spin_lock_irq(&priv->tx_lock); | ||
2684 | priv->inconfig = true; | ||
2685 | spin_unlock_irq(&priv->tx_lock); | ||
2686 | |||
2687 | ieee80211_stop_queues(hw); | ||
2688 | |||
2689 | /* | ||
2690 | * Wait for host queues to drain before doing PHY | ||
2691 | * reconfiguration. This avoids interrupting any in-flight | ||
2692 | * DMA transfers to the hardware. | ||
2693 | */ | ||
2694 | if (worker->options & MWL8K_WQ_TX_WAIT_EMPTY) { | ||
2695 | u32 timeout; | ||
2696 | u32 time_remaining; | ||
2697 | u32 iter; | ||
2698 | u32 tx_wait_attempts = worker->txwait_attempts; | ||
2699 | |||
2700 | time_remaining = worker->tx_timeout_ms; | ||
2701 | if (!tx_wait_attempts) | ||
2702 | tx_wait_attempts = 1; | ||
2703 | |||
2704 | timeout = worker->tx_timeout_ms/tx_wait_attempts; | ||
2705 | if (!timeout) | ||
2706 | timeout = 1; | ||
2707 | |||
2708 | iter = tx_wait_attempts; | ||
2709 | do { | ||
2710 | int wait_time; | ||
2711 | |||
2712 | if (time_remaining > timeout) { | ||
2713 | time_remaining -= timeout; | ||
2714 | wait_time = timeout; | ||
2715 | } else | ||
2716 | wait_time = time_remaining; | ||
2717 | |||
2718 | if (!wait_time) | ||
2719 | wait_time = 1; | ||
2720 | |||
2721 | rc = mwl8k_tx_wait_empty(hw, wait_time); | ||
2722 | if (rc) | ||
2723 | printk(KERN_ERR "%s() txwait timeout=%ums " | ||
2724 | "Retry:%u/%u\n", __func__, timeout, | ||
2725 | tx_wait_attempts - iter + 1, | ||
2726 | tx_wait_attempts); | ||
2727 | |||
2728 | } while (rc && --iter); | ||
2729 | |||
2730 | rc = iter ? 0 : -ETIMEDOUT; | ||
2731 | } | ||
2732 | if (!rc) | ||
2733 | rc = worker->wfunc(wt); | ||
2734 | |||
2735 | spin_lock_irq(&priv->tx_lock); | ||
2736 | priv->inconfig = false; | ||
2737 | if (priv->pending_tx_pkts && priv->radio_state) | ||
2738 | mwl8k_tx_start(priv); | ||
2739 | spin_unlock_irq(&priv->tx_lock); | ||
2740 | ieee80211_wake_queues(hw); | ||
2741 | |||
2742 | worker->rc = rc; | ||
2743 | if (worker->options & MWL8K_WQ_SLEEP) | ||
2744 | complete(worker->cmd_wait); | ||
2745 | |||
2746 | if (worker->options & MWL8K_WQ_FREE_WORKSTRUCT) | ||
2747 | kfree(wt); | ||
2748 | } | ||
2749 | |||
2750 | static int mwl8k_queue_work(struct ieee80211_hw *hw, | ||
2751 | struct mwl8k_work_struct *worker, | ||
2752 | struct workqueue_struct *wqueue, | ||
2753 | int (*wfunc)(struct work_struct *w)) | ||
2754 | { | ||
2755 | unsigned long timeout = 0; | ||
2756 | int rc = 0; | ||
2757 | |||
2758 | DECLARE_COMPLETION_ONSTACK(cmd_wait); | ||
2759 | |||
2760 | if (!worker->timeout_ms) | ||
2761 | worker->timeout_ms = MWL8K_CONFIG_TIMEOUT_MS; | ||
2762 | |||
2763 | if (!worker->options) | ||
2764 | worker->options = MWL8K_WQ_DEFAULT_OPTIONS; | ||
2765 | |||
2766 | if (!worker->txwait_attempts) | ||
2767 | worker->txwait_attempts = MWL8K_WQ_TXWAIT_ATTEMPTS; | ||
2768 | |||
2769 | if (!worker->tx_timeout_ms) | ||
2770 | worker->tx_timeout_ms = MWL8K_TXWAIT_MS; | ||
2771 | |||
2772 | worker->hw = hw; | ||
2773 | worker->cmd_wait = &cmd_wait; | ||
2774 | worker->rc = 1; | ||
2775 | worker->wfunc = wfunc; | ||
2776 | |||
2777 | INIT_WORK(&worker->wt, mwl8k_config_thread); | ||
2778 | queue_work(wqueue, &worker->wt); | ||
2779 | |||
2780 | if (worker->options & MWL8K_WQ_POST_REQUEST) { | ||
2781 | rc = 0; | ||
2782 | } else { | ||
2783 | if (worker->options & MWL8K_WQ_SPIN) { | ||
2784 | timeout = worker->timeout_ms; | ||
2785 | while (timeout && (worker->rc > 0)) { | ||
2786 | mdelay(1); | ||
2787 | timeout--; | ||
2788 | } | ||
2789 | } else if (worker->options & MWL8K_WQ_SLEEP) | ||
2790 | timeout = wait_for_completion_timeout(&cmd_wait, | ||
2791 | msecs_to_jiffies(worker->timeout_ms)); | ||
2792 | |||
2793 | if (timeout) | ||
2794 | rc = worker->rc; | ||
2795 | else { | ||
2796 | cancel_work_sync(&worker->wt); | ||
2797 | rc = -ETIMEDOUT; | ||
2798 | } | ||
2799 | } | ||
2800 | |||
2801 | return rc; | ||
2802 | } | ||
2803 | |||
2804 | struct mwl8k_start_worker { | ||
2805 | struct mwl8k_work_struct header; | ||
2806 | }; | ||
2807 | |||
2808 | static int mwl8k_start_wt(struct work_struct *wt) | ||
2809 | { | ||
2810 | struct mwl8k_start_worker *worker = (struct mwl8k_start_worker *)wt; | ||
2811 | struct ieee80211_hw *hw = worker->header.hw; | ||
2812 | struct mwl8k_priv *priv = hw->priv; | ||
2813 | int rc = 0; | ||
2814 | |||
2815 | if (priv->vif != NULL) { | ||
2816 | rc = -EIO; | ||
2817 | goto mwl8k_start_exit; | ||
2818 | } | ||
2819 | |||
2820 | /* Turn on radio */ | ||
2821 | if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { | ||
2822 | rc = -EIO; | ||
2823 | goto mwl8k_start_exit; | ||
2824 | } | ||
2825 | |||
2826 | /* Purge TX/RX HW queues */ | ||
2827 | if (mwl8k_cmd_set_pre_scan(hw)) { | ||
2828 | rc = -EIO; | ||
2829 | goto mwl8k_start_exit; | ||
2830 | } | ||
2831 | |||
2832 | if (mwl8k_cmd_set_post_scan(hw, "\x00\x00\x00\x00\x00\x00")) { | ||
2833 | rc = -EIO; | ||
2834 | goto mwl8k_start_exit; | ||
2835 | } | ||
2836 | |||
2837 | /* Enable firmware rate adaptation */ | ||
2838 | if (mwl8k_cmd_setrateadaptmode(hw, 0)) { | ||
2839 | rc = -EIO; | ||
2840 | goto mwl8k_start_exit; | ||
2841 | } | ||
2842 | |||
2843 | /* Disable WMM. WMM gets enabled when stack sends WMM parms */ | ||
2844 | if (mwl8k_set_wmm(hw, MWL8K_WMM_DISABLE)) { | ||
2845 | rc = -EIO; | ||
2846 | goto mwl8k_start_exit; | ||
2847 | } | ||
2848 | |||
2849 | /* Disable sniffer mode */ | ||
2850 | if (mwl8k_enable_sniffer(hw, 0)) | ||
2851 | rc = -EIO; | ||
2852 | |||
2853 | mwl8k_start_exit: | ||
2854 | return rc; | ||
2855 | } | ||
2856 | |||
2857 | static int mwl8k_start(struct ieee80211_hw *hw) | 2428 | static int mwl8k_start(struct ieee80211_hw *hw) |
2858 | { | 2429 | { |
2859 | struct mwl8k_start_worker *worker; | ||
2860 | struct mwl8k_priv *priv = hw->priv; | 2430 | struct mwl8k_priv *priv = hw->priv; |
2861 | int rc; | 2431 | int rc; |
2862 | 2432 | ||
2863 | /* Enable tx reclaim tasklet */ | ||
2864 | tasklet_enable(&priv->tx_reclaim_task); | ||
2865 | |||
2866 | rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, | 2433 | rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, |
2867 | IRQF_SHARED, MWL8K_NAME, hw); | 2434 | IRQF_SHARED, MWL8K_NAME, hw); |
2868 | if (rc) { | 2435 | if (rc) { |
2869 | printk(KERN_ERR "%s: failed to register IRQ handler\n", | 2436 | printk(KERN_ERR "%s: failed to register IRQ handler\n", |
2870 | priv->name); | 2437 | priv->name); |
2871 | rc = -EIO; | 2438 | return -EIO; |
2872 | goto mwl8k_start_disable_tasklet; | ||
2873 | } | 2439 | } |
2874 | 2440 | ||
2875 | /* Enable interrupts */ | 2441 | /* Enable tx reclaim tasklet */ |
2876 | iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 2442 | tasklet_enable(&priv->tx_reclaim_task); |
2877 | |||
2878 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
2879 | if (worker == NULL) { | ||
2880 | rc = -ENOMEM; | ||
2881 | goto mwl8k_start_disable_irq; | ||
2882 | } | ||
2883 | 2443 | ||
2884 | rc = mwl8k_queue_work(hw, &worker->header, | 2444 | /* Enable interrupts */ |
2885 | priv->config_wq, mwl8k_start_wt); | 2445 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
2886 | kfree(worker); | ||
2887 | if (!rc) | ||
2888 | return rc; | ||
2889 | 2446 | ||
2890 | if (rc == -ETIMEDOUT) | 2447 | rc = mwl8k_fw_lock(hw); |
2891 | printk(KERN_ERR "%s() timed out\n", __func__); | 2448 | if (!rc) { |
2449 | rc = mwl8k_cmd_802_11_radio_enable(hw); | ||
2892 | 2450 | ||
2893 | rc = -EIO; | 2451 | if (!rc) |
2452 | rc = mwl8k_cmd_set_pre_scan(hw); | ||
2894 | 2453 | ||
2895 | mwl8k_start_disable_irq: | 2454 | if (!rc) |
2896 | spin_lock_irq(&priv->tx_lock); | 2455 | rc = mwl8k_cmd_set_post_scan(hw, |
2897 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 2456 | "\x00\x00\x00\x00\x00\x00"); |
2898 | spin_unlock_irq(&priv->tx_lock); | ||
2899 | free_irq(priv->pdev->irq, hw); | ||
2900 | 2457 | ||
2901 | mwl8k_start_disable_tasklet: | 2458 | if (!rc) |
2902 | tasklet_disable(&priv->tx_reclaim_task); | 2459 | rc = mwl8k_cmd_setrateadaptmode(hw, 0); |
2903 | 2460 | ||
2904 | return rc; | 2461 | if (!rc) |
2905 | } | 2462 | rc = mwl8k_set_wmm(hw, 0); |
2906 | 2463 | ||
2907 | struct mwl8k_stop_worker { | 2464 | if (!rc) |
2908 | struct mwl8k_work_struct header; | 2465 | rc = mwl8k_enable_sniffer(hw, 0); |
2909 | }; | ||
2910 | 2466 | ||
2911 | static int mwl8k_stop_wt(struct work_struct *wt) | 2467 | mwl8k_fw_unlock(hw); |
2912 | { | 2468 | } |
2913 | struct mwl8k_stop_worker *worker = (struct mwl8k_stop_worker *)wt; | ||
2914 | struct ieee80211_hw *hw = worker->header.hw; | ||
2915 | int rc; | ||
2916 | 2469 | ||
2917 | rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); | 2470 | if (rc) { |
2471 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
2472 | free_irq(priv->pdev->irq, hw); | ||
2473 | tasklet_disable(&priv->tx_reclaim_task); | ||
2474 | } | ||
2918 | 2475 | ||
2919 | return rc; | 2476 | return rc; |
2920 | } | 2477 | } |
2921 | 2478 | ||
2922 | static void mwl8k_stop(struct ieee80211_hw *hw) | 2479 | static void mwl8k_stop(struct ieee80211_hw *hw) |
2923 | { | 2480 | { |
2924 | int rc; | ||
2925 | struct mwl8k_stop_worker *worker; | ||
2926 | struct mwl8k_priv *priv = hw->priv; | 2481 | struct mwl8k_priv *priv = hw->priv; |
2927 | int i; | 2482 | int i; |
2928 | 2483 | ||
2929 | if (priv->vif != NULL) | 2484 | mwl8k_cmd_802_11_radio_disable(hw); |
2930 | return; | ||
2931 | 2485 | ||
2932 | ieee80211_stop_queues(hw); | 2486 | ieee80211_stop_queues(hw); |
2933 | 2487 | ||
2934 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
2935 | if (worker == NULL) | ||
2936 | return; | ||
2937 | |||
2938 | rc = mwl8k_queue_work(hw, &worker->header, | ||
2939 | priv->config_wq, mwl8k_stop_wt); | ||
2940 | kfree(worker); | ||
2941 | if (rc == -ETIMEDOUT) | ||
2942 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
2943 | |||
2944 | /* Disable interrupts */ | 2488 | /* Disable interrupts */ |
2945 | spin_lock_irq(&priv->tx_lock); | ||
2946 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 2489 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
2947 | spin_unlock_irq(&priv->tx_lock); | ||
2948 | free_irq(priv->pdev->irq, hw); | 2490 | free_irq(priv->pdev->irq, hw); |
2949 | 2491 | ||
2950 | /* Stop finalize join worker */ | 2492 | /* Stop finalize join worker */ |
@@ -2978,8 +2520,7 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2978 | /* | 2520 | /* |
2979 | * We only support managed interfaces for now. | 2521 | * We only support managed interfaces for now. |
2980 | */ | 2522 | */ |
2981 | if (conf->type != NL80211_IFTYPE_STATION && | 2523 | if (conf->type != NL80211_IFTYPE_STATION) |
2982 | conf->type != NL80211_IFTYPE_MONITOR) | ||
2983 | return -EINVAL; | 2524 | return -EINVAL; |
2984 | 2525 | ||
2985 | /* Clean out driver private area */ | 2526 | /* Clean out driver private area */ |
@@ -2987,13 +2528,13 @@ static int mwl8k_add_interface(struct ieee80211_hw *hw, | |||
2987 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); | 2528 | memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); |
2988 | 2529 | ||
2989 | /* Save the mac address */ | 2530 | /* Save the mac address */ |
2990 | memcpy(mwl8k_vif->mac_addr, conf->mac_addr, IEEE80211_ADDR_LEN); | 2531 | memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); |
2991 | 2532 | ||
2992 | /* Back pointer to parent config block */ | 2533 | /* Back pointer to parent config block */ |
2993 | mwl8k_vif->priv = priv; | 2534 | mwl8k_vif->priv = priv; |
2994 | 2535 | ||
2995 | /* Setup initial PHY parameters */ | 2536 | /* Setup initial PHY parameters */ |
2996 | memcpy(mwl8k_vif->legacy_rates , | 2537 | memcpy(mwl8k_vif->legacy_rates, |
2997 | priv->rates, sizeof(mwl8k_vif->legacy_rates)); | 2538 | priv->rates, sizeof(mwl8k_vif->legacy_rates)); |
2998 | mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); | 2539 | mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); |
2999 | 2540 | ||
@@ -3017,213 +2558,148 @@ static void mwl8k_remove_interface(struct ieee80211_hw *hw, | |||
3017 | priv->vif = NULL; | 2558 | priv->vif = NULL; |
3018 | } | 2559 | } |
3019 | 2560 | ||
3020 | struct mwl8k_config_worker { | 2561 | static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) |
3021 | struct mwl8k_work_struct header; | ||
3022 | u32 changed; | ||
3023 | }; | ||
3024 | |||
3025 | static int mwl8k_config_wt(struct work_struct *wt) | ||
3026 | { | 2562 | { |
3027 | struct mwl8k_config_worker *worker = | ||
3028 | (struct mwl8k_config_worker *)wt; | ||
3029 | struct ieee80211_hw *hw = worker->header.hw; | ||
3030 | struct ieee80211_conf *conf = &hw->conf; | 2563 | struct ieee80211_conf *conf = &hw->conf; |
3031 | struct mwl8k_priv *priv = hw->priv; | 2564 | struct mwl8k_priv *priv = hw->priv; |
3032 | int rc = 0; | 2565 | int rc; |
3033 | 2566 | ||
3034 | if (!conf->radio_enabled) { | 2567 | if (conf->flags & IEEE80211_CONF_IDLE) { |
3035 | mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); | 2568 | mwl8k_cmd_802_11_radio_disable(hw); |
3036 | priv->current_channel = NULL; | 2569 | priv->current_channel = NULL; |
3037 | rc = 0; | 2570 | return 0; |
3038 | goto mwl8k_config_exit; | ||
3039 | } | 2571 | } |
3040 | 2572 | ||
3041 | if (mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_ENABLE)) { | 2573 | rc = mwl8k_fw_lock(hw); |
3042 | rc = -EINVAL; | 2574 | if (rc) |
3043 | goto mwl8k_config_exit; | 2575 | return rc; |
3044 | } | ||
3045 | 2576 | ||
3046 | priv->current_channel = conf->channel; | 2577 | rc = mwl8k_cmd_802_11_radio_enable(hw); |
2578 | if (rc) | ||
2579 | goto out; | ||
3047 | 2580 | ||
3048 | if (mwl8k_cmd_set_rf_channel(hw, conf->channel)) { | 2581 | rc = mwl8k_cmd_set_rf_channel(hw, conf->channel); |
3049 | rc = -EINVAL; | 2582 | if (rc) |
3050 | goto mwl8k_config_exit; | 2583 | goto out; |
3051 | } | 2584 | |
2585 | priv->current_channel = conf->channel; | ||
3052 | 2586 | ||
3053 | if (conf->power_level > 18) | 2587 | if (conf->power_level > 18) |
3054 | conf->power_level = 18; | 2588 | conf->power_level = 18; |
3055 | if (mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level)) { | 2589 | rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); |
3056 | rc = -EINVAL; | 2590 | if (rc) |
3057 | goto mwl8k_config_exit; | 2591 | goto out; |
3058 | } | ||
3059 | 2592 | ||
3060 | if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) | 2593 | if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) |
3061 | rc = -EINVAL; | 2594 | rc = -EINVAL; |
3062 | 2595 | ||
3063 | mwl8k_config_exit: | 2596 | out: |
2597 | mwl8k_fw_unlock(hw); | ||
2598 | |||
3064 | return rc; | 2599 | return rc; |
3065 | } | 2600 | } |
3066 | 2601 | ||
3067 | static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) | 2602 | static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, |
2603 | struct ieee80211_vif *vif, | ||
2604 | struct ieee80211_bss_conf *info, | ||
2605 | u32 changed) | ||
3068 | { | 2606 | { |
3069 | int rc = 0; | ||
3070 | struct mwl8k_config_worker *worker; | ||
3071 | struct mwl8k_priv *priv = hw->priv; | 2607 | struct mwl8k_priv *priv = hw->priv; |
3072 | 2608 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | |
3073 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3074 | if (worker == NULL) | ||
3075 | return -ENOMEM; | ||
3076 | |||
3077 | worker->changed = changed; | ||
3078 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3079 | priv->config_wq, mwl8k_config_wt); | ||
3080 | if (rc == -ETIMEDOUT) { | ||
3081 | printk(KERN_ERR "%s() timed out.\n", __func__); | ||
3082 | rc = -EINVAL; | ||
3083 | } | ||
3084 | |||
3085 | kfree(worker); | ||
3086 | |||
3087 | /* | ||
3088 | * mac80211 will crash on anything other than -EINVAL on | ||
3089 | * error. Looks like wireless extensions which calls mac80211 | ||
3090 | * may be the actual culprit... | ||
3091 | */ | ||
3092 | return rc ? -EINVAL : 0; | ||
3093 | } | ||
3094 | |||
3095 | struct mwl8k_bss_info_changed_worker { | ||
3096 | struct mwl8k_work_struct header; | ||
3097 | struct ieee80211_vif *vif; | ||
3098 | struct ieee80211_bss_conf *info; | ||
3099 | u32 changed; | ||
3100 | }; | ||
3101 | |||
3102 | static int mwl8k_bss_info_changed_wt(struct work_struct *wt) | ||
3103 | { | ||
3104 | struct mwl8k_bss_info_changed_worker *worker = | ||
3105 | (struct mwl8k_bss_info_changed_worker *)wt; | ||
3106 | struct ieee80211_hw *hw = worker->header.hw; | ||
3107 | struct ieee80211_vif *vif = worker->vif; | ||
3108 | struct ieee80211_bss_conf *info = worker->info; | ||
3109 | u32 changed; | ||
3110 | int rc; | 2609 | int rc; |
3111 | 2610 | ||
3112 | struct mwl8k_priv *priv = hw->priv; | 2611 | if (changed & BSS_CHANGED_BSSID) |
3113 | struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); | 2612 | memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); |
2613 | |||
2614 | if ((changed & BSS_CHANGED_ASSOC) == 0) | ||
2615 | return; | ||
3114 | 2616 | ||
3115 | changed = worker->changed; | ||
3116 | priv->capture_beacon = false; | 2617 | priv->capture_beacon = false; |
3117 | 2618 | ||
2619 | rc = mwl8k_fw_lock(hw); | ||
2620 | if (!rc) | ||
2621 | return; | ||
2622 | |||
3118 | if (info->assoc) { | 2623 | if (info->assoc) { |
3119 | memcpy(&mwl8k_vif->bss_info, info, | 2624 | memcpy(&mwl8k_vif->bss_info, info, |
3120 | sizeof(struct ieee80211_bss_conf)); | 2625 | sizeof(struct ieee80211_bss_conf)); |
3121 | 2626 | ||
3122 | /* Install rates */ | 2627 | /* Install rates */ |
3123 | if (mwl8k_update_rateset(hw, vif)) | 2628 | rc = mwl8k_update_rateset(hw, vif); |
3124 | goto mwl8k_bss_info_changed_exit; | 2629 | if (rc) |
2630 | goto out; | ||
3125 | 2631 | ||
3126 | /* Turn on rate adaptation */ | 2632 | /* Turn on rate adaptation */ |
3127 | if (mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, | 2633 | rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, |
3128 | MWL8K_UCAST_RATE, NULL)) | 2634 | MWL8K_UCAST_RATE, NULL); |
3129 | goto mwl8k_bss_info_changed_exit; | 2635 | if (rc) |
2636 | goto out; | ||
3130 | 2637 | ||
3131 | /* Set radio preamble */ | 2638 | /* Set radio preamble */ |
3132 | if (mwl8k_set_radio_preamble(hw, | 2639 | rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); |
3133 | info->use_short_preamble)) | 2640 | if (rc) |
3134 | goto mwl8k_bss_info_changed_exit; | 2641 | goto out; |
3135 | 2642 | ||
3136 | /* Set slot time */ | 2643 | /* Set slot time */ |
3137 | if (mwl8k_cmd_set_slot(hw, info->use_short_slot ? | 2644 | rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); |
3138 | MWL8K_SHORT_SLOTTIME : MWL8K_LONG_SLOTTIME)) | 2645 | if (rc) |
3139 | goto mwl8k_bss_info_changed_exit; | 2646 | goto out; |
3140 | 2647 | ||
3141 | /* Update peer rate info */ | 2648 | /* Update peer rate info */ |
3142 | if (mwl8k_cmd_update_sta_db(hw, vif, | 2649 | rc = mwl8k_cmd_update_sta_db(hw, vif, |
3143 | MWL8K_STA_DB_MODIFY_ENTRY)) | 2650 | MWL8K_STA_DB_MODIFY_ENTRY); |
3144 | goto mwl8k_bss_info_changed_exit; | 2651 | if (rc) |
2652 | goto out; | ||
3145 | 2653 | ||
3146 | /* Set AID */ | 2654 | /* Set AID */ |
3147 | if (mwl8k_cmd_set_aid(hw, vif)) | 2655 | rc = mwl8k_cmd_set_aid(hw, vif); |
3148 | goto mwl8k_bss_info_changed_exit; | 2656 | if (rc) |
2657 | goto out; | ||
3149 | 2658 | ||
3150 | /* | 2659 | /* |
3151 | * Finalize the join. Tell rx handler to process | 2660 | * Finalize the join. Tell rx handler to process |
3152 | * next beacon from our BSSID. | 2661 | * next beacon from our BSSID. |
3153 | */ | 2662 | */ |
3154 | memcpy(priv->capture_bssid, | 2663 | memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); |
3155 | mwl8k_vif->bssid, IEEE80211_ADDR_LEN); | ||
3156 | priv->capture_beacon = true; | 2664 | priv->capture_beacon = true; |
3157 | } else { | 2665 | } else { |
3158 | mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); | 2666 | rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); |
3159 | memset(&mwl8k_vif->bss_info, 0, | 2667 | memset(&mwl8k_vif->bss_info, 0, |
3160 | sizeof(struct ieee80211_bss_conf)); | 2668 | sizeof(struct ieee80211_bss_conf)); |
3161 | memset(mwl8k_vif->bssid, 0, IEEE80211_ADDR_LEN); | 2669 | memset(mwl8k_vif->bssid, 0, ETH_ALEN); |
3162 | } | 2670 | } |
3163 | 2671 | ||
3164 | mwl8k_bss_info_changed_exit: | 2672 | out: |
3165 | rc = 0; | 2673 | mwl8k_fw_unlock(hw); |
3166 | return rc; | ||
3167 | } | 2674 | } |
3168 | 2675 | ||
3169 | static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, | 2676 | static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, |
3170 | struct ieee80211_vif *vif, | 2677 | int mc_count, struct dev_addr_list *mclist) |
3171 | struct ieee80211_bss_conf *info, | ||
3172 | u32 changed) | ||
3173 | { | 2678 | { |
3174 | struct mwl8k_bss_info_changed_worker *worker; | 2679 | struct mwl8k_cmd_pkt *cmd; |
3175 | struct mwl8k_priv *priv = hw->priv; | ||
3176 | struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); | ||
3177 | int rc; | ||
3178 | |||
3179 | if (changed & BSS_CHANGED_BSSID) | ||
3180 | memcpy(mv_vif->bssid, info->bssid, IEEE80211_ADDR_LEN); | ||
3181 | |||
3182 | if ((changed & BSS_CHANGED_ASSOC) == 0) | ||
3183 | return; | ||
3184 | |||
3185 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3186 | if (worker == NULL) | ||
3187 | return; | ||
3188 | 2680 | ||
3189 | worker->vif = vif; | 2681 | cmd = __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); |
3190 | worker->info = info; | ||
3191 | worker->changed = changed; | ||
3192 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3193 | priv->config_wq, | ||
3194 | mwl8k_bss_info_changed_wt); | ||
3195 | kfree(worker); | ||
3196 | if (rc == -ETIMEDOUT) | ||
3197 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3198 | } | ||
3199 | |||
3200 | struct mwl8k_configure_filter_worker { | ||
3201 | struct mwl8k_work_struct header; | ||
3202 | unsigned int changed_flags; | ||
3203 | unsigned int *total_flags; | ||
3204 | int mc_count; | ||
3205 | struct dev_addr_list *mclist; | ||
3206 | }; | ||
3207 | 2682 | ||
3208 | #define MWL8K_SUPPORTED_IF_FLAGS FIF_BCN_PRBRESP_PROMISC | 2683 | return (unsigned long)cmd; |
2684 | } | ||
3209 | 2685 | ||
3210 | static int mwl8k_configure_filter_wt(struct work_struct *wt) | 2686 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, |
2687 | unsigned int changed_flags, | ||
2688 | unsigned int *total_flags, | ||
2689 | u64 multicast) | ||
3211 | { | 2690 | { |
3212 | struct mwl8k_configure_filter_worker *worker = | 2691 | struct mwl8k_priv *priv = hw->priv; |
3213 | (struct mwl8k_configure_filter_worker *)wt; | 2692 | struct mwl8k_cmd_pkt *multicast_adr_cmd; |
3214 | 2693 | ||
3215 | struct ieee80211_hw *hw = worker->header.hw; | 2694 | /* Clear unsupported feature flags */ |
3216 | unsigned int changed_flags = worker->changed_flags; | 2695 | *total_flags &= FIF_BCN_PRBRESP_PROMISC; |
3217 | unsigned int *total_flags = worker->total_flags; | ||
3218 | int mc_count = worker->mc_count; | ||
3219 | struct dev_addr_list *mclist = worker->mclist; | ||
3220 | 2696 | ||
3221 | struct mwl8k_priv *priv = hw->priv; | 2697 | if (mwl8k_fw_lock(hw)) |
3222 | int rc = 0; | 2698 | return; |
3223 | 2699 | ||
3224 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { | 2700 | if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { |
3225 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) | 2701 | if (*total_flags & FIF_BCN_PRBRESP_PROMISC) |
3226 | rc = mwl8k_cmd_set_pre_scan(hw); | 2702 | mwl8k_cmd_set_pre_scan(hw); |
3227 | else { | 2703 | else { |
3228 | u8 *bssid; | 2704 | u8 *bssid; |
3229 | 2705 | ||
@@ -3231,151 +2707,45 @@ static int mwl8k_configure_filter_wt(struct work_struct *wt) | |||
3231 | if (priv->vif != NULL) | 2707 | if (priv->vif != NULL) |
3232 | bssid = MWL8K_VIF(priv->vif)->bssid; | 2708 | bssid = MWL8K_VIF(priv->vif)->bssid; |
3233 | 2709 | ||
3234 | rc = mwl8k_cmd_set_post_scan(hw, bssid); | 2710 | mwl8k_cmd_set_post_scan(hw, bssid); |
3235 | } | 2711 | } |
3236 | } | 2712 | } |
3237 | 2713 | ||
3238 | if (rc) | 2714 | multicast_adr_cmd = (void *)(unsigned long)multicast; |
3239 | goto mwl8k_configure_filter_exit; | 2715 | if (multicast_adr_cmd != NULL) { |
3240 | if (mc_count) { | 2716 | mwl8k_post_cmd(hw, multicast_adr_cmd); |
3241 | mc_count = mc_count < priv->num_mcaddrs ? | 2717 | kfree(multicast_adr_cmd); |
3242 | mc_count : priv->num_mcaddrs; | ||
3243 | rc = mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); | ||
3244 | if (rc) | ||
3245 | printk(KERN_ERR | ||
3246 | "%s()Error setting multicast addresses\n", | ||
3247 | __func__); | ||
3248 | } | 2718 | } |
3249 | 2719 | ||
3250 | mwl8k_configure_filter_exit: | 2720 | mwl8k_fw_unlock(hw); |
3251 | return rc; | ||
3252 | } | ||
3253 | |||
3254 | static void mwl8k_configure_filter(struct ieee80211_hw *hw, | ||
3255 | unsigned int changed_flags, | ||
3256 | unsigned int *total_flags, | ||
3257 | int mc_count, | ||
3258 | struct dev_addr_list *mclist) | ||
3259 | { | ||
3260 | |||
3261 | struct mwl8k_configure_filter_worker *worker; | ||
3262 | struct mwl8k_priv *priv = hw->priv; | ||
3263 | |||
3264 | /* Clear unsupported feature flags */ | ||
3265 | *total_flags &= MWL8K_SUPPORTED_IF_FLAGS; | ||
3266 | |||
3267 | if (!(changed_flags & MWL8K_SUPPORTED_IF_FLAGS) && !mc_count) | ||
3268 | return; | ||
3269 | |||
3270 | worker = kzalloc(sizeof(*worker), GFP_ATOMIC); | ||
3271 | if (worker == NULL) | ||
3272 | return; | ||
3273 | |||
3274 | worker->header.options = MWL8K_WQ_QUEUE_ONLY | MWL8K_WQ_TX_WAIT_EMPTY; | ||
3275 | worker->changed_flags = changed_flags; | ||
3276 | worker->total_flags = total_flags; | ||
3277 | worker->mc_count = mc_count; | ||
3278 | worker->mclist = mclist; | ||
3279 | |||
3280 | mwl8k_queue_work(hw, &worker->header, priv->config_wq, | ||
3281 | mwl8k_configure_filter_wt); | ||
3282 | } | ||
3283 | |||
3284 | struct mwl8k_set_rts_threshold_worker { | ||
3285 | struct mwl8k_work_struct header; | ||
3286 | u32 value; | ||
3287 | }; | ||
3288 | |||
3289 | static int mwl8k_set_rts_threshold_wt(struct work_struct *wt) | ||
3290 | { | ||
3291 | struct mwl8k_set_rts_threshold_worker *worker = | ||
3292 | (struct mwl8k_set_rts_threshold_worker *)wt; | ||
3293 | |||
3294 | struct ieee80211_hw *hw = worker->header.hw; | ||
3295 | u16 threshold = (u16)(worker->value); | ||
3296 | int rc; | ||
3297 | |||
3298 | rc = mwl8k_rts_threshold(hw, MWL8K_CMD_SET, &threshold); | ||
3299 | |||
3300 | return rc; | ||
3301 | } | 2721 | } |
3302 | 2722 | ||
3303 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | 2723 | static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) |
3304 | { | 2724 | { |
3305 | int rc; | 2725 | return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); |
3306 | struct mwl8k_set_rts_threshold_worker *worker; | ||
3307 | struct mwl8k_priv *priv = hw->priv; | ||
3308 | |||
3309 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3310 | if (worker == NULL) | ||
3311 | return -ENOMEM; | ||
3312 | |||
3313 | worker->value = value; | ||
3314 | |||
3315 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3316 | priv->config_wq, | ||
3317 | mwl8k_set_rts_threshold_wt); | ||
3318 | kfree(worker); | ||
3319 | |||
3320 | if (rc == -ETIMEDOUT) { | ||
3321 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3322 | rc = -EINVAL; | ||
3323 | } | ||
3324 | |||
3325 | return rc; | ||
3326 | } | ||
3327 | |||
3328 | struct mwl8k_conf_tx_worker { | ||
3329 | struct mwl8k_work_struct header; | ||
3330 | u16 queue; | ||
3331 | const struct ieee80211_tx_queue_params *params; | ||
3332 | }; | ||
3333 | |||
3334 | static int mwl8k_conf_tx_wt(struct work_struct *wt) | ||
3335 | { | ||
3336 | struct mwl8k_conf_tx_worker *worker = | ||
3337 | (struct mwl8k_conf_tx_worker *)wt; | ||
3338 | |||
3339 | struct ieee80211_hw *hw = worker->header.hw; | ||
3340 | u16 queue = worker->queue; | ||
3341 | const struct ieee80211_tx_queue_params *params = worker->params; | ||
3342 | |||
3343 | struct mwl8k_priv *priv = hw->priv; | ||
3344 | int rc = 0; | ||
3345 | |||
3346 | if (priv->wmm_mode == MWL8K_WMM_DISABLE) | ||
3347 | if (mwl8k_set_wmm(hw, MWL8K_WMM_ENABLE)) { | ||
3348 | rc = -EINVAL; | ||
3349 | goto mwl8k_conf_tx_exit; | ||
3350 | } | ||
3351 | |||
3352 | if (mwl8k_set_edca_params(hw, GET_TXQ(queue), params->cw_min, | ||
3353 | params->cw_max, params->aifs, params->txop)) | ||
3354 | rc = -EINVAL; | ||
3355 | mwl8k_conf_tx_exit: | ||
3356 | return rc; | ||
3357 | } | 2726 | } |
3358 | 2727 | ||
3359 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, | 2728 | static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, |
3360 | const struct ieee80211_tx_queue_params *params) | 2729 | const struct ieee80211_tx_queue_params *params) |
3361 | { | 2730 | { |
3362 | int rc; | ||
3363 | struct mwl8k_conf_tx_worker *worker; | ||
3364 | struct mwl8k_priv *priv = hw->priv; | 2731 | struct mwl8k_priv *priv = hw->priv; |
2732 | int rc; | ||
3365 | 2733 | ||
3366 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | 2734 | rc = mwl8k_fw_lock(hw); |
3367 | if (worker == NULL) | 2735 | if (!rc) { |
3368 | return -ENOMEM; | 2736 | if (!priv->wmm_enabled) |
2737 | rc = mwl8k_set_wmm(hw, 1); | ||
3369 | 2738 | ||
3370 | worker->queue = queue; | 2739 | if (!rc) |
3371 | worker->params = params; | 2740 | rc = mwl8k_set_edca_params(hw, queue, |
3372 | rc = mwl8k_queue_work(hw, &worker->header, | 2741 | params->cw_min, |
3373 | priv->config_wq, mwl8k_conf_tx_wt); | 2742 | params->cw_max, |
3374 | kfree(worker); | 2743 | params->aifs, |
3375 | if (rc == -ETIMEDOUT) { | 2744 | params->txop); |
3376 | printk(KERN_ERR "%s() timed out\n", __func__); | 2745 | |
3377 | rc = -EINVAL; | 2746 | mwl8k_fw_unlock(hw); |
3378 | } | 2747 | } |
2748 | |||
3379 | return rc; | 2749 | return rc; |
3380 | } | 2750 | } |
3381 | 2751 | ||
@@ -3393,44 +2763,14 @@ static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, | |||
3393 | sizeof(struct ieee80211_tx_queue_stats)); | 2763 | sizeof(struct ieee80211_tx_queue_stats)); |
3394 | } | 2764 | } |
3395 | spin_unlock_bh(&priv->tx_lock); | 2765 | spin_unlock_bh(&priv->tx_lock); |
3396 | return 0; | ||
3397 | } | ||
3398 | |||
3399 | struct mwl8k_get_stats_worker { | ||
3400 | struct mwl8k_work_struct header; | ||
3401 | struct ieee80211_low_level_stats *stats; | ||
3402 | }; | ||
3403 | |||
3404 | static int mwl8k_get_stats_wt(struct work_struct *wt) | ||
3405 | { | ||
3406 | struct mwl8k_get_stats_worker *worker = | ||
3407 | (struct mwl8k_get_stats_worker *)wt; | ||
3408 | 2766 | ||
3409 | return mwl8k_cmd_802_11_get_stat(worker->header.hw, worker->stats); | 2767 | return 0; |
3410 | } | 2768 | } |
3411 | 2769 | ||
3412 | static int mwl8k_get_stats(struct ieee80211_hw *hw, | 2770 | static int mwl8k_get_stats(struct ieee80211_hw *hw, |
3413 | struct ieee80211_low_level_stats *stats) | 2771 | struct ieee80211_low_level_stats *stats) |
3414 | { | 2772 | { |
3415 | int rc; | 2773 | return mwl8k_cmd_802_11_get_stat(hw, stats); |
3416 | struct mwl8k_get_stats_worker *worker; | ||
3417 | struct mwl8k_priv *priv = hw->priv; | ||
3418 | |||
3419 | worker = kzalloc(sizeof(*worker), GFP_KERNEL); | ||
3420 | if (worker == NULL) | ||
3421 | return -ENOMEM; | ||
3422 | |||
3423 | worker->stats = stats; | ||
3424 | rc = mwl8k_queue_work(hw, &worker->header, | ||
3425 | priv->config_wq, mwl8k_get_stats_wt); | ||
3426 | |||
3427 | kfree(worker); | ||
3428 | if (rc == -ETIMEDOUT) { | ||
3429 | printk(KERN_ERR "%s() timed out\n", __func__); | ||
3430 | rc = -EINVAL; | ||
3431 | } | ||
3432 | |||
3433 | return rc; | ||
3434 | } | 2774 | } |
3435 | 2775 | ||
3436 | static const struct ieee80211_ops mwl8k_ops = { | 2776 | static const struct ieee80211_ops mwl8k_ops = { |
@@ -3441,6 +2781,7 @@ static const struct ieee80211_ops mwl8k_ops = { | |||
3441 | .remove_interface = mwl8k_remove_interface, | 2781 | .remove_interface = mwl8k_remove_interface, |
3442 | .config = mwl8k_config, | 2782 | .config = mwl8k_config, |
3443 | .bss_info_changed = mwl8k_bss_info_changed, | 2783 | .bss_info_changed = mwl8k_bss_info_changed, |
2784 | .prepare_multicast = mwl8k_prepare_multicast, | ||
3444 | .configure_filter = mwl8k_configure_filter, | 2785 | .configure_filter = mwl8k_configure_filter, |
3445 | .set_rts_threshold = mwl8k_set_rts_threshold, | 2786 | .set_rts_threshold = mwl8k_set_rts_threshold, |
3446 | .conf_tx = mwl8k_conf_tx, | 2787 | .conf_tx = mwl8k_conf_tx, |
@@ -3458,12 +2799,9 @@ static void mwl8k_tx_reclaim_handler(unsigned long data) | |||
3458 | for (i = 0; i < MWL8K_TX_QUEUES; i++) | 2799 | for (i = 0; i < MWL8K_TX_QUEUES; i++) |
3459 | mwl8k_txq_reclaim(hw, i, 0); | 2800 | mwl8k_txq_reclaim(hw, i, 0); |
3460 | 2801 | ||
3461 | if (priv->tx_wait != NULL) { | 2802 | if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) { |
3462 | int count = mwl8k_txq_busy(priv); | 2803 | complete(priv->tx_wait); |
3463 | if (count == 0) { | 2804 | priv->tx_wait = NULL; |
3464 | complete(priv->tx_wait); | ||
3465 | priv->tx_wait = NULL; | ||
3466 | } | ||
3467 | } | 2805 | } |
3468 | spin_unlock_bh(&priv->tx_lock); | 2806 | spin_unlock_bh(&priv->tx_lock); |
3469 | } | 2807 | } |
@@ -3473,7 +2811,7 @@ static void mwl8k_finalize_join_worker(struct work_struct *work) | |||
3473 | struct mwl8k_priv *priv = | 2811 | struct mwl8k_priv *priv = |
3474 | container_of(work, struct mwl8k_priv, finalize_join_worker); | 2812 | container_of(work, struct mwl8k_priv, finalize_join_worker); |
3475 | struct sk_buff *skb = priv->beacon_skb; | 2813 | struct sk_buff *skb = priv->beacon_skb; |
3476 | u8 dtim = (MWL8K_VIF(priv->vif))->bss_info.dtim_period; | 2814 | u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; |
3477 | 2815 | ||
3478 | mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); | 2816 | mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); |
3479 | dev_kfree_skb(skb); | 2817 | dev_kfree_skb(skb); |
@@ -3516,16 +2854,10 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3516 | priv = hw->priv; | 2854 | priv = hw->priv; |
3517 | priv->hw = hw; | 2855 | priv->hw = hw; |
3518 | priv->pdev = pdev; | 2856 | priv->pdev = pdev; |
3519 | priv->hostcmd_wait = NULL; | 2857 | priv->wmm_enabled = false; |
3520 | priv->tx_wait = NULL; | ||
3521 | priv->inconfig = false; | ||
3522 | priv->wep_enabled = 0; | ||
3523 | priv->wmm_mode = false; | ||
3524 | priv->pending_tx_pkts = 0; | 2858 | priv->pending_tx_pkts = 0; |
3525 | strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); | 2859 | strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); |
3526 | 2860 | ||
3527 | spin_lock_init(&priv->fw_lock); | ||
3528 | |||
3529 | SET_IEEE80211_DEV(hw, &pdev->dev); | 2861 | SET_IEEE80211_DEV(hw, &pdev->dev); |
3530 | pci_set_drvdata(pdev, hw); | 2862 | pci_set_drvdata(pdev, hw); |
3531 | 2863 | ||
@@ -3557,17 +2889,16 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3557 | 2889 | ||
3558 | hw->queues = MWL8K_TX_QUEUES; | 2890 | hw->queues = MWL8K_TX_QUEUES; |
3559 | 2891 | ||
3560 | hw->wiphy->interface_modes = | 2892 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
3561 | BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_MONITOR); | ||
3562 | 2893 | ||
3563 | /* Set rssi and noise values to dBm */ | 2894 | /* Set rssi and noise values to dBm */ |
3564 | hw->flags |= (IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM); | 2895 | hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; |
3565 | hw->vif_data_size = sizeof(struct mwl8k_vif); | 2896 | hw->vif_data_size = sizeof(struct mwl8k_vif); |
3566 | priv->vif = NULL; | 2897 | priv->vif = NULL; |
3567 | 2898 | ||
3568 | /* Set default radio state and preamble */ | 2899 | /* Set default radio state and preamble */ |
3569 | priv->radio_preamble = MWL8K_RADIO_DEFAULT_PREAMBLE; | 2900 | priv->radio_on = 0; |
3570 | priv->radio_state = MWL8K_RADIO_DISABLE; | 2901 | priv->radio_short_preamble = 0; |
3571 | 2902 | ||
3572 | /* Finalize join worker */ | 2903 | /* Finalize join worker */ |
3573 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); | 2904 | INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); |
@@ -3592,6 +2923,12 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3592 | goto err_iounmap; | 2923 | goto err_iounmap; |
3593 | rxq_refill(hw, 0, INT_MAX); | 2924 | rxq_refill(hw, 0, INT_MAX); |
3594 | 2925 | ||
2926 | mutex_init(&priv->fw_mutex); | ||
2927 | priv->fw_mutex_owner = NULL; | ||
2928 | priv->fw_mutex_depth = 0; | ||
2929 | priv->tx_wait = NULL; | ||
2930 | priv->hostcmd_wait = NULL; | ||
2931 | |||
3595 | spin_lock_init(&priv->tx_lock); | 2932 | spin_lock_init(&priv->tx_lock); |
3596 | 2933 | ||
3597 | for (i = 0; i < MWL8K_TX_QUEUES; i++) { | 2934 | for (i = 0; i < MWL8K_TX_QUEUES; i++) { |
@@ -3601,8 +2938,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3601 | } | 2938 | } |
3602 | 2939 | ||
3603 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); | 2940 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); |
3604 | priv->int_mask = 0; | 2941 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3605 | iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
3606 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); | 2942 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); |
3607 | iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); | 2943 | iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); |
3608 | 2944 | ||
@@ -3639,9 +2975,7 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3639 | * commands use interrupts and avoids polling. Disable | 2975 | * commands use interrupts and avoids polling. Disable |
3640 | * interrupts when done. | 2976 | * interrupts when done. |
3641 | */ | 2977 | */ |
3642 | priv->int_mask |= MWL8K_A2H_EVENTS; | 2978 | iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3643 | |||
3644 | iowrite32(priv->int_mask, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | ||
3645 | 2979 | ||
3646 | /* Get config data, mac addrs etc */ | 2980 | /* Get config data, mac addrs etc */ |
3647 | rc = mwl8k_cmd_get_hw_spec(hw); | 2981 | rc = mwl8k_cmd_get_hw_spec(hw); |
@@ -3651,16 +2985,14 @@ static int __devinit mwl8k_probe(struct pci_dev *pdev, | |||
3651 | } | 2985 | } |
3652 | 2986 | ||
3653 | /* Turn radio off */ | 2987 | /* Turn radio off */ |
3654 | rc = mwl8k_cmd_802_11_radio_control(hw, MWL8K_RADIO_DISABLE); | 2988 | rc = mwl8k_cmd_802_11_radio_disable(hw); |
3655 | if (rc) { | 2989 | if (rc) { |
3656 | printk(KERN_ERR "%s: Cannot disable\n", priv->name); | 2990 | printk(KERN_ERR "%s: Cannot disable\n", priv->name); |
3657 | goto err_stop_firmware; | 2991 | goto err_stop_firmware; |
3658 | } | 2992 | } |
3659 | 2993 | ||
3660 | /* Disable interrupts */ | 2994 | /* Disable interrupts */ |
3661 | spin_lock_irq(&priv->tx_lock); | ||
3662 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 2995 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3663 | spin_unlock_irq(&priv->tx_lock); | ||
3664 | free_irq(priv->pdev->irq, hw); | 2996 | free_irq(priv->pdev->irq, hw); |
3665 | 2997 | ||
3666 | rc = ieee80211_register_hw(hw); | 2998 | rc = ieee80211_register_hw(hw); |
@@ -3684,9 +3016,7 @@ err_stop_firmware: | |||
3684 | mwl8k_release_firmware(priv); | 3016 | mwl8k_release_firmware(priv); |
3685 | 3017 | ||
3686 | err_free_irq: | 3018 | err_free_irq: |
3687 | spin_lock_irq(&priv->tx_lock); | ||
3688 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); | 3019 | iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); |
3689 | spin_unlock_irq(&priv->tx_lock); | ||
3690 | free_irq(priv->pdev->irq, hw); | 3020 | free_irq(priv->pdev->irq, hw); |
3691 | 3021 | ||
3692 | err_free_queues: | 3022 | err_free_queues: |
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c index 3e56f7643df5..7698fdd6a3a2 100644 --- a/drivers/net/wireless/orinoco/wext.c +++ b/drivers/net/wireless/orinoco/wext.c | |||
@@ -1291,7 +1291,7 @@ static int orinoco_ioctl_setibssport(struct net_device *dev, | |||
1291 | if (orinoco_lock(priv, &flags) != 0) | 1291 | if (orinoco_lock(priv, &flags) != 0) |
1292 | return -EBUSY; | 1292 | return -EBUSY; |
1293 | 1293 | ||
1294 | priv->ibss_port = val ; | 1294 | priv->ibss_port = val; |
1295 | 1295 | ||
1296 | /* Actually update the mode we are using */ | 1296 | /* Actually update the mode we are using */ |
1297 | set_port_type(priv); | 1297 | set_port_type(priv); |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 4a741df9c081..4d486bf9f725 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -302,7 +302,7 @@ out: | |||
302 | static void p54_configure_filter(struct ieee80211_hw *dev, | 302 | static void p54_configure_filter(struct ieee80211_hw *dev, |
303 | unsigned int changed_flags, | 303 | unsigned int changed_flags, |
304 | unsigned int *total_flags, | 304 | unsigned int *total_flags, |
305 | int mc_count, struct dev_mc_list *mclist) | 305 | u64 multicast) |
306 | { | 306 | { |
307 | struct p54_common *priv = dev->priv; | 307 | struct p54_common *priv = dev->priv; |
308 | 308 | ||
@@ -575,6 +575,12 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
575 | dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 + | 575 | dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 + |
576 | sizeof(struct p54_tx_data); | 576 | sizeof(struct p54_tx_data); |
577 | 577 | ||
578 | /* | ||
579 | * For now, disable PS by default because it affects | ||
580 | * link stability significantly. | ||
581 | */ | ||
582 | dev->wiphy->ps_default = false; | ||
583 | |||
578 | mutex_init(&priv->conf_mutex); | 584 | mutex_init(&priv->conf_mutex); |
579 | mutex_init(&priv->eeprom_mutex); | 585 | mutex_init(&priv->eeprom_mutex); |
580 | init_completion(&priv->eeprom_comp); | 586 | init_completion(&priv->eeprom_comp); |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 09a589432dab..b04f59bab3b0 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1874,7 +1874,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
1874 | */ | 1874 | */ |
1875 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); | 1875 | __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); |
1876 | __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); | 1876 | __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); |
1877 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); | ||
1878 | if (!modparam_nohwcrypt) { | 1877 | if (!modparam_nohwcrypt) { |
1879 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 1878 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
1880 | __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); | 1879 | __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 3856f06fdca7..639dc6cc04b9 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1463,6 +1463,10 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1463 | /* | 1463 | /* |
1464 | * ASIC will keep garbage value after boot, clear encryption keys. | 1464 | * ASIC will keep garbage value after boot, clear encryption keys. |
1465 | */ | 1465 | */ |
1466 | for (i = 0; i < 4; i++) | ||
1467 | rt2x00usb_register_write(rt2x00dev, | ||
1468 | SHARED_KEY_MODE_ENTRY(i), 0); | ||
1469 | |||
1466 | for (i = 0; i < 256; i++) { | 1470 | for (i = 0; i < 256; i++) { |
1467 | u32 wcid[2] = { 0xffffffff, 0x00ffffff }; | 1471 | u32 wcid[2] = { 0xffffffff, 0x00ffffff }; |
1468 | rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), | 1472 | rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), |
@@ -1472,10 +1476,6 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1472 | rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); | 1476 | rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); |
1473 | } | 1477 | } |
1474 | 1478 | ||
1475 | for (i = 0; i < 16; i++) | ||
1476 | rt2x00usb_register_write(rt2x00dev, | ||
1477 | SHARED_KEY_MODE_ENTRY(i), 0); | ||
1478 | |||
1479 | /* | 1479 | /* |
1480 | * Clear all beacons | 1480 | * Clear all beacons |
1481 | * For the Beacon base registers we only need to clear | 1481 | * For the Beacon base registers we only need to clear |
@@ -1520,7 +1520,7 @@ static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) | |||
1520 | rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); | 1520 | rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); |
1521 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); | 1521 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); |
1522 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); | 1522 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); |
1523 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 3); | 1523 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); |
1524 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); | 1524 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); |
1525 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); | 1525 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); |
1526 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); | 1526 | rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); |
@@ -1995,11 +1995,11 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, | |||
1995 | rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); | 1995 | rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); |
1996 | rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, | 1996 | rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, |
1997 | test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? | 1997 | test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? |
1998 | txdesc->key_idx : 0xff); | 1998 | (skbdesc->entry->entry_idx + 1) : 0xff); |
1999 | rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, | 1999 | rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, |
2000 | skb->len - txdesc->l2pad); | 2000 | skb->len - txdesc->l2pad); |
2001 | rt2x00_set_field32(&word, TXWI_W1_PACKETID, | 2001 | rt2x00_set_field32(&word, TXWI_W1_PACKETID, |
2002 | skbdesc->entry->entry_idx); | 2002 | skbdesc->entry->queue->qid + 1); |
2003 | rt2x00_desc_write(txwi, 1, word); | 2003 | rt2x00_desc_write(txwi, 1, word); |
2004 | 2004 | ||
2005 | /* | 2005 | /* |
@@ -2163,8 +2163,10 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, | |||
2163 | if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) | 2163 | if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) |
2164 | rxdesc->dev_flags |= RXDONE_MY_BSS; | 2164 | rxdesc->dev_flags |= RXDONE_MY_BSS; |
2165 | 2165 | ||
2166 | if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) | 2166 | if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) { |
2167 | rxdesc->dev_flags |= RXDONE_L2PAD; | 2167 | rxdesc->dev_flags |= RXDONE_L2PAD; |
2168 | skbdesc->flags |= SKBDESC_L2_PADDED; | ||
2169 | } | ||
2168 | 2170 | ||
2169 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) | 2171 | if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) |
2170 | rxdesc->flags |= RX_FLAG_SHORT_GI; | 2172 | rxdesc->flags |= RX_FLAG_SHORT_GI; |
@@ -2632,7 +2634,6 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2632 | * This device requires firmware. | 2634 | * This device requires firmware. |
2633 | */ | 2635 | */ |
2634 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 2636 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
2635 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); | ||
2636 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); | 2637 | __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); |
2637 | if (!modparam_nohwcrypt) | 2638 | if (!modparam_nohwcrypt) |
2638 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 2639 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h index 2d9dc3783361..4d9991c9a51c 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ b/drivers/net/wireless/rt2x00/rt2800usb.h | |||
@@ -36,6 +36,9 @@ | |||
36 | * RF2750 2.4G/5G 1T2R | 36 | * RF2750 2.4G/5G 1T2R |
37 | * RF3020 2.4G 1T1R | 37 | * RF3020 2.4G 1T1R |
38 | * RF2020 2.4G B/G | 38 | * RF2020 2.4G B/G |
39 | * RF3021 2.4G 1T2R | ||
40 | * RF3022 2.4G 2T2R | ||
41 | * RF3052 2.4G 2T2R | ||
39 | */ | 42 | */ |
40 | #define RF2820 0x0001 | 43 | #define RF2820 0x0001 |
41 | #define RF2850 0x0002 | 44 | #define RF2850 0x0002 |
@@ -43,6 +46,9 @@ | |||
43 | #define RF2750 0x0004 | 46 | #define RF2750 0x0004 |
44 | #define RF3020 0x0005 | 47 | #define RF3020 0x0005 |
45 | #define RF2020 0x0006 | 48 | #define RF2020 0x0006 |
49 | #define RF3021 0x0007 | ||
50 | #define RF3022 0x0008 | ||
51 | #define RF3052 0x0009 | ||
46 | 52 | ||
47 | /* | 53 | /* |
48 | * RT2870 version | 54 | * RT2870 version |
@@ -1300,8 +1306,8 @@ | |||
1300 | * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry | 1306 | * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry |
1301 | * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry | 1307 | * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry |
1302 | * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry | 1308 | * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry |
1303 | * SHARED_KEY_TABLE_BASE: 32-byte * 16-entry | 1309 | * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry |
1304 | * SHARED_KEY_MODE_BASE: 4-byte * 16-entry | 1310 | * SHARED_KEY_MODE_BASE: 4 bits * 32-entry |
1305 | */ | 1311 | */ |
1306 | #define MAC_WCID_BASE 0x1800 | 1312 | #define MAC_WCID_BASE 0x1800 |
1307 | #define PAIRWISE_KEY_TABLE_BASE 0x4000 | 1313 | #define PAIRWISE_KEY_TABLE_BASE 0x4000 |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 99e89596cef6..555a777db6df 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -350,8 +350,6 @@ struct rt2x00_intf { | |||
350 | */ | 350 | */ |
351 | unsigned int delayed_flags; | 351 | unsigned int delayed_flags; |
352 | #define DELAYED_UPDATE_BEACON 0x00000001 | 352 | #define DELAYED_UPDATE_BEACON 0x00000001 |
353 | #define DELAYED_CONFIG_ERP 0x00000002 | ||
354 | #define DELAYED_LED_ASSOC 0x00000004 | ||
355 | 353 | ||
356 | /* | 354 | /* |
357 | * Software sequence counter, this is only required | 355 | * Software sequence counter, this is only required |
@@ -614,7 +612,6 @@ enum rt2x00_flags { | |||
614 | DRIVER_REQUIRE_FIRMWARE, | 612 | DRIVER_REQUIRE_FIRMWARE, |
615 | DRIVER_REQUIRE_BEACON_GUARD, | 613 | DRIVER_REQUIRE_BEACON_GUARD, |
616 | DRIVER_REQUIRE_ATIM_QUEUE, | 614 | DRIVER_REQUIRE_ATIM_QUEUE, |
617 | DRIVER_REQUIRE_SCHEDULED, | ||
618 | DRIVER_REQUIRE_DMA, | 615 | DRIVER_REQUIRE_DMA, |
619 | DRIVER_REQUIRE_COPY_IV, | 616 | DRIVER_REQUIRE_COPY_IV, |
620 | DRIVER_REQUIRE_L2PAD, | 617 | DRIVER_REQUIRE_L2PAD, |
@@ -826,7 +823,6 @@ struct rt2x00_dev { | |||
826 | * due to RTNL locking requirements. | 823 | * due to RTNL locking requirements. |
827 | */ | 824 | */ |
828 | struct work_struct intf_work; | 825 | struct work_struct intf_work; |
829 | struct work_struct filter_work; | ||
830 | 826 | ||
831 | /* | 827 | /* |
832 | * Data queue arrays for RX, TX and Beacon. | 828 | * Data queue arrays for RX, TX and Beacon. |
@@ -978,7 +974,7 @@ int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); | |||
978 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 974 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
979 | unsigned int changed_flags, | 975 | unsigned int changed_flags, |
980 | unsigned int *total_flags, | 976 | unsigned int *total_flags, |
981 | int mc_count, struct dev_addr_list *mc_list); | 977 | u64 multicast); |
982 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 978 | int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
983 | bool set); | 979 | bool set); |
984 | #ifdef CONFIG_RT2X00_LIB_CRYPTO | 980 | #ifdef CONFIG_RT2X00_LIB_CRYPTO |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index b6676c6722fc..3f8c70ebe9ad 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -118,20 +118,11 @@ void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) | |||
118 | rt2x00link_start_tuner(rt2x00dev); | 118 | rt2x00link_start_tuner(rt2x00dev); |
119 | } | 119 | } |
120 | 120 | ||
121 | static void rt2x00lib_packetfilter_scheduled(struct work_struct *work) | ||
122 | { | ||
123 | struct rt2x00_dev *rt2x00dev = | ||
124 | container_of(work, struct rt2x00_dev, filter_work); | ||
125 | |||
126 | rt2x00dev->ops->lib->config_filter(rt2x00dev, rt2x00dev->packet_filter); | ||
127 | } | ||
128 | |||
129 | static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | 121 | static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, |
130 | struct ieee80211_vif *vif) | 122 | struct ieee80211_vif *vif) |
131 | { | 123 | { |
132 | struct rt2x00_dev *rt2x00dev = data; | 124 | struct rt2x00_dev *rt2x00dev = data; |
133 | struct rt2x00_intf *intf = vif_to_intf(vif); | 125 | struct rt2x00_intf *intf = vif_to_intf(vif); |
134 | struct ieee80211_bss_conf conf; | ||
135 | int delayed_flags; | 126 | int delayed_flags; |
136 | 127 | ||
137 | /* | 128 | /* |
@@ -141,7 +132,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
141 | */ | 132 | */ |
142 | spin_lock(&intf->lock); | 133 | spin_lock(&intf->lock); |
143 | 134 | ||
144 | memcpy(&conf, &vif->bss_conf, sizeof(conf)); | ||
145 | delayed_flags = intf->delayed_flags; | 135 | delayed_flags = intf->delayed_flags; |
146 | intf->delayed_flags = 0; | 136 | intf->delayed_flags = 0; |
147 | 137 | ||
@@ -158,12 +148,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, | |||
158 | 148 | ||
159 | if (delayed_flags & DELAYED_UPDATE_BEACON) | 149 | if (delayed_flags & DELAYED_UPDATE_BEACON) |
160 | rt2x00queue_update_beacon(rt2x00dev, vif, true); | 150 | rt2x00queue_update_beacon(rt2x00dev, vif, true); |
161 | |||
162 | if (delayed_flags & DELAYED_CONFIG_ERP) | ||
163 | rt2x00lib_config_erp(rt2x00dev, intf, &conf); | ||
164 | |||
165 | if (delayed_flags & DELAYED_LED_ASSOC) | ||
166 | rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); | ||
167 | } | 151 | } |
168 | 152 | ||
169 | static void rt2x00lib_intf_scheduled(struct work_struct *work) | 153 | static void rt2x00lib_intf_scheduled(struct work_struct *work) |
@@ -220,7 +204,8 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
220 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); | 204 | struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); |
221 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | 205 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); |
222 | unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | 206 | unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); |
223 | u8 rate_idx, rate_flags; | 207 | u8 rate_idx, rate_flags, retry_rates; |
208 | unsigned int i; | ||
224 | 209 | ||
225 | /* | 210 | /* |
226 | * Unmap the skb. | 211 | * Unmap the skb. |
@@ -259,16 +244,27 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
259 | 244 | ||
260 | rate_idx = skbdesc->tx_rate_idx; | 245 | rate_idx = skbdesc->tx_rate_idx; |
261 | rate_flags = skbdesc->tx_rate_flags; | 246 | rate_flags = skbdesc->tx_rate_flags; |
247 | retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ? | ||
248 | (txdesc->retry + 1) : 1; | ||
262 | 249 | ||
263 | /* | 250 | /* |
264 | * Initialize TX status | 251 | * Initialize TX status |
265 | */ | 252 | */ |
266 | memset(&tx_info->status, 0, sizeof(tx_info->status)); | 253 | memset(&tx_info->status, 0, sizeof(tx_info->status)); |
267 | tx_info->status.ack_signal = 0; | 254 | tx_info->status.ack_signal = 0; |
268 | tx_info->status.rates[0].idx = rate_idx; | 255 | |
269 | tx_info->status.rates[0].flags = rate_flags; | 256 | /* |
270 | tx_info->status.rates[0].count = txdesc->retry + 1; | 257 | * Frame was send with retries, hardware tried |
271 | tx_info->status.rates[1].idx = -1; /* terminate */ | 258 | * different rates to send out the frame, at each |
259 | * retry it lowered the rate 1 step. | ||
260 | */ | ||
261 | for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { | ||
262 | tx_info->status.rates[i].idx = rate_idx - i; | ||
263 | tx_info->status.rates[i].flags = rate_flags; | ||
264 | tx_info->status.rates[i].count = 1; | ||
265 | } | ||
266 | if (i < (IEEE80211_TX_MAX_RATES -1)) | ||
267 | tx_info->status.rates[i].idx = -1; /* terminate */ | ||
272 | 268 | ||
273 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { | 269 | if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { |
274 | if (test_bit(TXDONE_SUCCESS, &txdesc->flags) || | 270 | if (test_bit(TXDONE_SUCCESS, &txdesc->flags) || |
@@ -847,7 +843,6 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
847 | * Initialize configuration work. | 843 | * Initialize configuration work. |
848 | */ | 844 | */ |
849 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); | 845 | INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); |
850 | INIT_WORK(&rt2x00dev->filter_work, rt2x00lib_packetfilter_scheduled); | ||
851 | 846 | ||
852 | /* | 847 | /* |
853 | * Allocate queue array. | 848 | * Allocate queue array. |
@@ -895,7 +890,6 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
895 | /* | 890 | /* |
896 | * Stop all work. | 891 | * Stop all work. |
897 | */ | 892 | */ |
898 | cancel_work_sync(&rt2x00dev->filter_work); | ||
899 | cancel_work_sync(&rt2x00dev->intf_work); | 893 | cancel_work_sync(&rt2x00dev->intf_work); |
900 | 894 | ||
901 | /* | 895 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index cb7b6d459331..a91f316cd452 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -379,7 +379,7 @@ EXPORT_SYMBOL_GPL(rt2x00mac_config); | |||
379 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | 379 | void rt2x00mac_configure_filter(struct ieee80211_hw *hw, |
380 | unsigned int changed_flags, | 380 | unsigned int changed_flags, |
381 | unsigned int *total_flags, | 381 | unsigned int *total_flags, |
382 | int mc_count, struct dev_addr_list *mc_list) | 382 | u64 multicast) |
383 | { | 383 | { |
384 | struct rt2x00_dev *rt2x00dev = hw->priv; | 384 | struct rt2x00_dev *rt2x00dev = hw->priv; |
385 | 385 | ||
@@ -430,10 +430,7 @@ void rt2x00mac_configure_filter(struct ieee80211_hw *hw, | |||
430 | return; | 430 | return; |
431 | rt2x00dev->packet_filter = *total_flags; | 431 | rt2x00dev->packet_filter = *total_flags; |
432 | 432 | ||
433 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 433 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); |
434 | rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); | ||
435 | else | ||
436 | ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->filter_work); | ||
437 | } | 434 | } |
438 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); | 435 | EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); |
439 | 436 | ||
@@ -639,23 +636,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | |||
639 | else | 636 | else |
640 | rt2x00dev->intf_associated--; | 637 | rt2x00dev->intf_associated--; |
641 | 638 | ||
642 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 639 | rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); |
643 | rt2x00leds_led_assoc(rt2x00dev, | ||
644 | !!rt2x00dev->intf_associated); | ||
645 | else | ||
646 | delayed |= DELAYED_LED_ASSOC; | ||
647 | } | 640 | } |
648 | 641 | ||
649 | /* | 642 | /* |
650 | * When the erp information has changed, we should perform | 643 | * When the erp information has changed, we should perform |
651 | * additional configuration steps. For all other changes we are done. | 644 | * additional configuration steps. For all other changes we are done. |
652 | */ | 645 | */ |
653 | if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) { | 646 | if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) |
654 | if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags)) | 647 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); |
655 | rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); | ||
656 | else | ||
657 | delayed |= DELAYED_CONFIG_ERP; | ||
658 | } | ||
659 | 648 | ||
660 | spin_lock(&intf->lock); | 649 | spin_lock(&intf->lock); |
661 | if (delayed) { | 650 | if (delayed) { |
@@ -704,8 +693,8 @@ EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx); | |||
704 | void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) | 693 | void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) |
705 | { | 694 | { |
706 | struct rt2x00_dev *rt2x00dev = hw->priv; | 695 | struct rt2x00_dev *rt2x00dev = hw->priv; |
707 | bool blocked = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); | 696 | bool active = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); |
708 | 697 | ||
709 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); | 698 | wiphy_rfkill_set_hw_state(hw->wiphy, !active); |
710 | } | 699 | } |
711 | EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); | 700 | EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 47d175a13790..a5591fb2b191 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -214,6 +214,7 @@ struct rxdone_entry_desc { | |||
214 | * | 214 | * |
215 | * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. | 215 | * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. |
216 | * @TXDONE_SUCCESS: Frame was successfully send | 216 | * @TXDONE_SUCCESS: Frame was successfully send |
217 | * @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. | ||
217 | * @TXDONE_FAILURE: Frame was not successfully send | 218 | * @TXDONE_FAILURE: Frame was not successfully send |
218 | * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the | 219 | * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the |
219 | * frame transmission failed due to excessive retries. | 220 | * frame transmission failed due to excessive retries. |
@@ -221,6 +222,7 @@ struct rxdone_entry_desc { | |||
221 | enum txdone_entry_desc_flags { | 222 | enum txdone_entry_desc_flags { |
222 | TXDONE_UNKNOWN, | 223 | TXDONE_UNKNOWN, |
223 | TXDONE_SUCCESS, | 224 | TXDONE_SUCCESS, |
225 | TXDONE_FALLBACK, | ||
224 | TXDONE_FAILURE, | 226 | TXDONE_FAILURE, |
225 | TXDONE_EXCESSIVE_RETRY, | 227 | TXDONE_EXCESSIVE_RETRY, |
226 | }; | 228 | }; |
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 4d94b65943f1..90e117263051 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2151,7 +2151,6 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) | |||
2151 | * This device requires firmware. | 2151 | * This device requires firmware. |
2152 | */ | 2152 | */ |
2153 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); | 2153 | __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); |
2154 | __set_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags); | ||
2155 | if (!modparam_nohwcrypt) | 2154 | if (!modparam_nohwcrypt) |
2156 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); | 2155 | __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); |
2157 | 2156 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c index 09f46abc730a..16429c49139c 100644 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180_dev.c | |||
@@ -728,10 +728,16 @@ static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, | |||
728 | priv->rf->conf_erp(dev, info); | 728 | priv->rf->conf_erp(dev, info); |
729 | } | 729 | } |
730 | 730 | ||
731 | static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, | ||
732 | struct dev_addr_list *mc_list) | ||
733 | { | ||
734 | return mc_count; | ||
735 | } | ||
736 | |||
731 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, | 737 | static void rtl8180_configure_filter(struct ieee80211_hw *dev, |
732 | unsigned int changed_flags, | 738 | unsigned int changed_flags, |
733 | unsigned int *total_flags, | 739 | unsigned int *total_flags, |
734 | int mc_count, struct dev_addr_list *mclist) | 740 | u64 multicast) |
735 | { | 741 | { |
736 | struct rtl8180_priv *priv = dev->priv; | 742 | struct rtl8180_priv *priv = dev->priv; |
737 | 743 | ||
@@ -741,7 +747,7 @@ static void rtl8180_configure_filter(struct ieee80211_hw *dev, | |||
741 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; | 747 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; |
742 | if (changed_flags & FIF_OTHER_BSS) | 748 | if (changed_flags & FIF_OTHER_BSS) |
743 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; | 749 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; |
744 | if (*total_flags & FIF_ALLMULTI || mc_count > 0) | 750 | if (*total_flags & FIF_ALLMULTI || multicast > 0) |
745 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; | 751 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; |
746 | else | 752 | else |
747 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; | 753 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; |
@@ -768,6 +774,7 @@ static const struct ieee80211_ops rtl8180_ops = { | |||
768 | .remove_interface = rtl8180_remove_interface, | 774 | .remove_interface = rtl8180_remove_interface, |
769 | .config = rtl8180_config, | 775 | .config = rtl8180_config, |
770 | .bss_info_changed = rtl8180_bss_info_changed, | 776 | .bss_info_changed = rtl8180_bss_info_changed, |
777 | .prepare_multicast = rtl8180_prepare_multicast, | ||
771 | .configure_filter = rtl8180_configure_filter, | 778 | .configure_filter = rtl8180_configure_filter, |
772 | }; | 779 | }; |
773 | 780 | ||
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 53f57dc52226..90f38357393c 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -1192,10 +1192,16 @@ static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, | |||
1192 | info->use_short_preamble); | 1192 | info->use_short_preamble); |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, | ||
1196 | int mc_count, struct dev_addr_list *mc_list) | ||
1197 | { | ||
1198 | return mc_count; | ||
1199 | } | ||
1200 | |||
1195 | static void rtl8187_configure_filter(struct ieee80211_hw *dev, | 1201 | static void rtl8187_configure_filter(struct ieee80211_hw *dev, |
1196 | unsigned int changed_flags, | 1202 | unsigned int changed_flags, |
1197 | unsigned int *total_flags, | 1203 | unsigned int *total_flags, |
1198 | int mc_count, struct dev_addr_list *mclist) | 1204 | u64 multicast) |
1199 | { | 1205 | { |
1200 | struct rtl8187_priv *priv = dev->priv; | 1206 | struct rtl8187_priv *priv = dev->priv; |
1201 | 1207 | ||
@@ -1205,7 +1211,7 @@ static void rtl8187_configure_filter(struct ieee80211_hw *dev, | |||
1205 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; | 1211 | priv->rx_conf ^= RTL818X_RX_CONF_CTRL; |
1206 | if (changed_flags & FIF_OTHER_BSS) | 1212 | if (changed_flags & FIF_OTHER_BSS) |
1207 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; | 1213 | priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; |
1208 | if (*total_flags & FIF_ALLMULTI || mc_count > 0) | 1214 | if (*total_flags & FIF_ALLMULTI || multicast > 0) |
1209 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; | 1215 | priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; |
1210 | else | 1216 | else |
1211 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; | 1217 | priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; |
@@ -1268,6 +1274,7 @@ static const struct ieee80211_ops rtl8187_ops = { | |||
1268 | .remove_interface = rtl8187_remove_interface, | 1274 | .remove_interface = rtl8187_remove_interface, |
1269 | .config = rtl8187_config, | 1275 | .config = rtl8187_config, |
1270 | .bss_info_changed = rtl8187_bss_info_changed, | 1276 | .bss_info_changed = rtl8187_bss_info_changed, |
1277 | .prepare_multicast = rtl8187_prepare_multicast, | ||
1271 | .configure_filter = rtl8187_configure_filter, | 1278 | .configure_filter = rtl8187_configure_filter, |
1272 | .conf_tx = rtl8187_conf_tx | 1279 | .conf_tx = rtl8187_conf_tx |
1273 | }; | 1280 | }; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 592c3b5cc8f8..452d748e42c6 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -465,6 +465,9 @@ int wl1251_boot(struct wl1251 *wl) | |||
465 | int ret = 0, minor_minor_e2_ver; | 465 | int ret = 0, minor_minor_e2_ver; |
466 | u32 tmp, boot_data; | 466 | u32 tmp, boot_data; |
467 | 467 | ||
468 | /* halt embedded ARM CPU while loading firmware */ | ||
469 | wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT); | ||
470 | |||
468 | ret = wl1251_boot_soft_reset(wl); | 471 | ret = wl1251_boot_soft_reset(wl); |
469 | if (ret < 0) | 472 | if (ret < 0) |
470 | goto out; | 473 | goto out; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index 7148934e464d..5809ef5b18f8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -652,9 +652,7 @@ out: | |||
652 | 652 | ||
653 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, | 653 | static void wl1251_op_configure_filter(struct ieee80211_hw *hw, |
654 | unsigned int changed, | 654 | unsigned int changed, |
655 | unsigned int *total, | 655 | unsigned int *total,u64 multicast) |
656 | int mc_count, | ||
657 | struct dev_addr_list *mc_list) | ||
658 | { | 656 | { |
659 | struct wl1251 *wl = hw->priv; | 657 | struct wl1251 *wl = hw->priv; |
660 | 658 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index bdd561001dcb..06e1bd94a739 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h | |||
@@ -245,8 +245,8 @@ enum wl12xx_acx_int_reg { | |||
245 | ACX_REG_TABLE_LEN | 245 | ACX_REG_TABLE_LEN |
246 | }; | 246 | }; |
247 | 247 | ||
248 | #define ACX_SLV_SOFT_RESET_BIT BIT(1) | 248 | #define ACX_SLV_SOFT_RESET_BIT BIT(0) |
249 | #define ACX_REG_EEPROM_START_BIT BIT(1) | 249 | #define ACX_REG_EEPROM_START_BIT BIT(0) |
250 | 250 | ||
251 | /* Command/Information Mailbox Pointers */ | 251 | /* Command/Information Mailbox Pointers */ |
252 | 252 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c index 4102d590b798..d9169b47ac42 100644 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ b/drivers/net/wireless/wl12xx/wl1271_main.c | |||
@@ -605,11 +605,10 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, | |||
605 | struct ieee80211_if_init_conf *conf) | 605 | struct ieee80211_if_init_conf *conf) |
606 | { | 606 | { |
607 | struct wl1271 *wl = hw->priv; | 607 | struct wl1271 *wl = hw->priv; |
608 | DECLARE_MAC_BUF(mac); | ||
609 | int ret = 0; | 608 | int ret = 0; |
610 | 609 | ||
611 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %s", | 610 | wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", |
612 | conf->type, print_mac(mac, conf->mac_addr)); | 611 | conf->type, conf->mac_addr); |
613 | 612 | ||
614 | mutex_lock(&wl->mutex); | 613 | mutex_lock(&wl->mutex); |
615 | 614 | ||
@@ -793,9 +792,7 @@ out: | |||
793 | 792 | ||
794 | static void wl1271_op_configure_filter(struct ieee80211_hw *hw, | 793 | static void wl1271_op_configure_filter(struct ieee80211_hw *hw, |
795 | unsigned int changed, | 794 | unsigned int changed, |
796 | unsigned int *total, | 795 | unsigned int *total,u64 multicast) |
797 | int mc_count, | ||
798 | struct dev_addr_list *mc_list) | ||
799 | { | 796 | { |
800 | struct wl1271 *wl = hw->priv; | 797 | struct wl1271 *wl = hw->priv; |
801 | 798 | ||
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index 55b7fbdc85dc..6d666359a42f 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c | |||
@@ -796,18 +796,40 @@ static void set_rx_filter_handler(struct work_struct *work) | |||
796 | dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); | 796 | dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); |
797 | } | 797 | } |
798 | 798 | ||
799 | static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, | ||
800 | int mc_count, struct dev_addr_list *mclist) | ||
801 | { | ||
802 | struct zd_mac *mac = zd_hw_mac(hw); | ||
803 | struct zd_mc_hash hash; | ||
804 | int i; | ||
805 | |||
806 | zd_mc_clear(&hash); | ||
807 | |||
808 | for (i = 0; i < mc_count; i++) { | ||
809 | if (!mclist) | ||
810 | break; | ||
811 | dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr); | ||
812 | zd_mc_add_addr(&hash, mclist->dmi_addr); | ||
813 | mclist = mclist->next; | ||
814 | } | ||
815 | |||
816 | return hash.low | ((u64)hash.high << 32); | ||
817 | } | ||
818 | |||
799 | #define SUPPORTED_FIF_FLAGS \ | 819 | #define SUPPORTED_FIF_FLAGS \ |
800 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ | 820 | (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ |
801 | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) | 821 | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) |
802 | static void zd_op_configure_filter(struct ieee80211_hw *hw, | 822 | static void zd_op_configure_filter(struct ieee80211_hw *hw, |
803 | unsigned int changed_flags, | 823 | unsigned int changed_flags, |
804 | unsigned int *new_flags, | 824 | unsigned int *new_flags, |
805 | int mc_count, struct dev_mc_list *mclist) | 825 | u64 multicast) |
806 | { | 826 | { |
807 | struct zd_mc_hash hash; | 827 | struct zd_mc_hash hash = { |
828 | .low = multicast, | ||
829 | .high = multicast >> 32, | ||
830 | }; | ||
808 | struct zd_mac *mac = zd_hw_mac(hw); | 831 | struct zd_mac *mac = zd_hw_mac(hw); |
809 | unsigned long flags; | 832 | unsigned long flags; |
810 | int i; | ||
811 | 833 | ||
812 | /* Only deal with supported flags */ | 834 | /* Only deal with supported flags */ |
813 | changed_flags &= SUPPORTED_FIF_FLAGS; | 835 | changed_flags &= SUPPORTED_FIF_FLAGS; |
@@ -819,25 +841,16 @@ static void zd_op_configure_filter(struct ieee80211_hw *hw, | |||
819 | if (!changed_flags) | 841 | if (!changed_flags) |
820 | return; | 842 | return; |
821 | 843 | ||
822 | if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) { | 844 | if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) |
823 | zd_mc_add_all(&hash); | 845 | zd_mc_add_all(&hash); |
824 | } else { | ||
825 | zd_mc_clear(&hash); | ||
826 | for (i = 0; i < mc_count; i++) { | ||
827 | if (!mclist) | ||
828 | break; | ||
829 | dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", | ||
830 | mclist->dmi_addr); | ||
831 | zd_mc_add_addr(&hash, mclist->dmi_addr); | ||
832 | mclist = mclist->next; | ||
833 | } | ||
834 | } | ||
835 | 846 | ||
836 | spin_lock_irqsave(&mac->lock, flags); | 847 | spin_lock_irqsave(&mac->lock, flags); |
837 | mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); | 848 | mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); |
838 | mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); | 849 | mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); |
839 | mac->multicast_hash = hash; | 850 | mac->multicast_hash = hash; |
840 | spin_unlock_irqrestore(&mac->lock, flags); | 851 | spin_unlock_irqrestore(&mac->lock, flags); |
852 | |||
853 | /* XXX: these can be called here now, can sleep now! */ | ||
841 | queue_work(zd_workqueue, &mac->set_multicast_hash_work); | 854 | queue_work(zd_workqueue, &mac->set_multicast_hash_work); |
842 | 855 | ||
843 | if (changed_flags & FIF_CONTROL) | 856 | if (changed_flags & FIF_CONTROL) |
@@ -940,6 +953,7 @@ static const struct ieee80211_ops zd_ops = { | |||
940 | .add_interface = zd_op_add_interface, | 953 | .add_interface = zd_op_add_interface, |
941 | .remove_interface = zd_op_remove_interface, | 954 | .remove_interface = zd_op_remove_interface, |
942 | .config = zd_op_config, | 955 | .config = zd_op_config, |
956 | .prepare_multicast = zd_op_prepare_multicast, | ||
943 | .configure_filter = zd_op_configure_filter, | 957 | .configure_filter = zd_op_configure_filter, |
944 | .bss_info_changed = zd_op_bss_info_changed, | 958 | .bss_info_changed = zd_op_bss_info_changed, |
945 | .get_tsf = zd_op_get_tsf, | 959 | .get_tsf = zd_op_get_tsf, |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index 593fc618a2ea..f853d5600ca7 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -480,7 +480,7 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
480 | 480 | ||
481 | /* extract the MAC address */ | 481 | /* extract the MAC address */ |
482 | for (i = 0; i < 3; i++) { | 482 | for (i = 0; i < 3; i++) { |
483 | v = in[SPOFF(SSB_SPROM1_IL0MAC) + i]; | 483 | v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; |
484 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | 484 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); |
485 | } | 485 | } |
486 | SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); | 486 | SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 0b146bb2dd14..3d874c620219 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1325,6 +1325,8 @@ struct wireless_dev { | |||
1325 | 1325 | ||
1326 | struct mutex mtx; | 1326 | struct mutex mtx; |
1327 | 1327 | ||
1328 | struct work_struct cleanup_work; | ||
1329 | |||
1328 | /* currently used for IBSS and SME - might be rearranged later */ | 1330 | /* currently used for IBSS and SME - might be rearranged later */ |
1329 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 1331 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
1330 | u8 ssid_len; | 1332 | u8 ssid_len; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 76d43e12cc29..aac84d7bd46e 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -583,7 +583,6 @@ enum ieee80211_conf_flags { | |||
583 | /** | 583 | /** |
584 | * enum ieee80211_conf_changed - denotes which configuration changed | 584 | * enum ieee80211_conf_changed - denotes which configuration changed |
585 | * | 585 | * |
586 | * @_IEEE80211_CONF_CHANGE_RADIO_ENABLED: DEPRECATED | ||
587 | * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed | 586 | * @IEEE80211_CONF_CHANGE_LISTEN_INTERVAL: the listen interval changed |
588 | * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed | 587 | * @IEEE80211_CONF_CHANGE_RADIOTAP: the radiotap flag changed |
589 | * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed | 588 | * @IEEE80211_CONF_CHANGE_PS: the PS flag or dynamic PS timeout changed |
@@ -593,7 +592,6 @@ enum ieee80211_conf_flags { | |||
593 | * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed | 592 | * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed |
594 | */ | 593 | */ |
595 | enum ieee80211_conf_changed { | 594 | enum ieee80211_conf_changed { |
596 | _IEEE80211_CONF_CHANGE_RADIO_ENABLED = BIT(0), | ||
597 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), | 595 | IEEE80211_CONF_CHANGE_LISTEN_INTERVAL = BIT(2), |
598 | IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), | 596 | IEEE80211_CONF_CHANGE_RADIOTAP = BIT(3), |
599 | IEEE80211_CONF_CHANGE_PS = BIT(4), | 597 | IEEE80211_CONF_CHANGE_PS = BIT(4), |
@@ -603,14 +601,6 @@ enum ieee80211_conf_changed { | |||
603 | IEEE80211_CONF_CHANGE_IDLE = BIT(8), | 601 | IEEE80211_CONF_CHANGE_IDLE = BIT(8), |
604 | }; | 602 | }; |
605 | 603 | ||
606 | static inline __deprecated enum ieee80211_conf_changed | ||
607 | __IEEE80211_CONF_CHANGE_RADIO_ENABLED(void) | ||
608 | { | ||
609 | return _IEEE80211_CONF_CHANGE_RADIO_ENABLED; | ||
610 | } | ||
611 | #define IEEE80211_CONF_CHANGE_RADIO_ENABLED \ | ||
612 | __IEEE80211_CONF_CHANGE_RADIO_ENABLED() | ||
613 | |||
614 | /** | 604 | /** |
615 | * struct ieee80211_conf - configuration of the device | 605 | * struct ieee80211_conf - configuration of the device |
616 | * | 606 | * |
@@ -618,9 +608,6 @@ __IEEE80211_CONF_CHANGE_RADIO_ENABLED(void) | |||
618 | * | 608 | * |
619 | * @flags: configuration flags defined above | 609 | * @flags: configuration flags defined above |
620 | * | 610 | * |
621 | * @radio_enabled: when zero, driver is required to switch off the radio. | ||
622 | * @beacon_int: DEPRECATED, DO NOT USE | ||
623 | * | ||
624 | * @listen_interval: listen interval in units of beacon interval | 611 | * @listen_interval: listen interval in units of beacon interval |
625 | * @max_sleep_period: the maximum number of beacon intervals to sleep for | 612 | * @max_sleep_period: the maximum number of beacon intervals to sleep for |
626 | * before checking the beacon for a TIM bit (managed mode only); this | 613 | * before checking the beacon for a TIM bit (managed mode only); this |
@@ -644,13 +631,11 @@ __IEEE80211_CONF_CHANGE_RADIO_ENABLED(void) | |||
644 | * number of transmissions not the number of retries | 631 | * number of transmissions not the number of retries |
645 | */ | 632 | */ |
646 | struct ieee80211_conf { | 633 | struct ieee80211_conf { |
647 | int __deprecated beacon_int; | ||
648 | u32 flags; | 634 | u32 flags; |
649 | int power_level, dynamic_ps_timeout; | 635 | int power_level, dynamic_ps_timeout; |
650 | int max_sleep_period; | 636 | int max_sleep_period; |
651 | 637 | ||
652 | u16 listen_interval; | 638 | u16 listen_interval; |
653 | bool __deprecated radio_enabled; | ||
654 | 639 | ||
655 | u8 long_frame_max_tx_count, short_frame_max_tx_count; | 640 | u8 long_frame_max_tx_count, short_frame_max_tx_count; |
656 | 641 | ||
@@ -1219,10 +1204,13 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | |||
1219 | * the driver's configure_filter() function which frames should be | 1204 | * the driver's configure_filter() function which frames should be |
1220 | * passed to mac80211 and which should be filtered out. | 1205 | * passed to mac80211 and which should be filtered out. |
1221 | * | 1206 | * |
1222 | * The configure_filter() callback is invoked with the parameters | 1207 | * Before configure_filter() is invoked, the prepare_multicast() |
1223 | * @mc_count and @mc_list for the combined multicast address list | 1208 | * callback is invoked with the parameters @mc_count and @mc_list |
1224 | * of all virtual interfaces, @changed_flags telling which flags | 1209 | * for the combined multicast address list of all virtual interfaces. |
1225 | * were changed and @total_flags with the new flag states. | 1210 | * It's use is optional, and it returns a u64 that is passed to |
1211 | * configure_filter(). Additionally, configure_filter() has the | ||
1212 | * arguments @changed_flags telling which flags were changed and | ||
1213 | * @total_flags with the new flag states. | ||
1226 | * | 1214 | * |
1227 | * If your device has no multicast address filters your driver will | 1215 | * If your device has no multicast address filters your driver will |
1228 | * need to check both the %FIF_ALLMULTI flag and the @mc_count | 1216 | * need to check both the %FIF_ALLMULTI flag and the @mc_count |
@@ -1375,9 +1363,13 @@ enum ieee80211_ampdu_mlme_action { | |||
1375 | * for association indication. The @changed parameter indicates which | 1363 | * for association indication. The @changed parameter indicates which |
1376 | * of the bss parameters has changed when a call is made. | 1364 | * of the bss parameters has changed when a call is made. |
1377 | * | 1365 | * |
1366 | * @prepare_multicast: Prepare for multicast filter configuration. | ||
1367 | * This callback is optional, and its return value is passed | ||
1368 | * to configure_filter(). This callback must be atomic. | ||
1369 | * | ||
1378 | * @configure_filter: Configure the device's RX filter. | 1370 | * @configure_filter: Configure the device's RX filter. |
1379 | * See the section "Frame filtering" for more information. | 1371 | * See the section "Frame filtering" for more information. |
1380 | * This callback must be implemented and atomic. | 1372 | * This callback must be implemented. |
1381 | * | 1373 | * |
1382 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit | 1374 | * @set_tim: Set TIM bit. mac80211 calls this function when a TIM bit |
1383 | * must be set or cleared for a given STA. Must be atomic. | 1375 | * must be set or cleared for a given STA. Must be atomic. |
@@ -1479,10 +1471,12 @@ struct ieee80211_ops { | |||
1479 | struct ieee80211_vif *vif, | 1471 | struct ieee80211_vif *vif, |
1480 | struct ieee80211_bss_conf *info, | 1472 | struct ieee80211_bss_conf *info, |
1481 | u32 changed); | 1473 | u32 changed); |
1474 | u64 (*prepare_multicast)(struct ieee80211_hw *hw, | ||
1475 | int mc_count, struct dev_addr_list *mc_list); | ||
1482 | void (*configure_filter)(struct ieee80211_hw *hw, | 1476 | void (*configure_filter)(struct ieee80211_hw *hw, |
1483 | unsigned int changed_flags, | 1477 | unsigned int changed_flags, |
1484 | unsigned int *total_flags, | 1478 | unsigned int *total_flags, |
1485 | int mc_count, struct dev_addr_list *mc_list); | 1479 | u64 multicast); |
1486 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, | 1480 | int (*set_tim)(struct ieee80211_hw *hw, struct ieee80211_sta *sta, |
1487 | bool set); | 1481 | bool set); |
1488 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, | 1482 | int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd, |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index e9ec6cae2d39..61234e79022b 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -116,6 +116,8 @@ IEEE80211_IF_FILE(peer, u.wds.remote_addr, MAC); | |||
116 | 116 | ||
117 | #ifdef CONFIG_MAC80211_MESH | 117 | #ifdef CONFIG_MAC80211_MESH |
118 | /* Mesh stats attributes */ | 118 | /* Mesh stats attributes */ |
119 | IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC); | ||
120 | IEEE80211_IF_FILE(fwded_unicast, u.mesh.mshstats.fwded_unicast, DEC); | ||
119 | IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); | 121 | IEEE80211_IF_FILE(fwded_frames, u.mesh.mshstats.fwded_frames, DEC); |
120 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); | 122 | IEEE80211_IF_FILE(dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl, DEC); |
121 | IEEE80211_IF_FILE(dropped_frames_no_route, | 123 | IEEE80211_IF_FILE(dropped_frames_no_route, |
@@ -205,6 +207,8 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata) | |||
205 | { | 207 | { |
206 | sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats", | 208 | sdata->mesh_stats_dir = debugfs_create_dir("mesh_stats", |
207 | sdata->debugfsdir); | 209 | sdata->debugfsdir); |
210 | MESHSTATS_ADD(fwded_mcast); | ||
211 | MESHSTATS_ADD(fwded_unicast); | ||
208 | MESHSTATS_ADD(fwded_frames); | 212 | MESHSTATS_ADD(fwded_frames); |
209 | MESHSTATS_ADD(dropped_frames_ttl); | 213 | MESHSTATS_ADD(dropped_frames_ttl); |
210 | MESHSTATS_ADD(dropped_frames_no_route); | 214 | MESHSTATS_ADD(dropped_frames_no_route); |
@@ -327,6 +331,8 @@ static void del_monitor_files(struct ieee80211_sub_if_data *sdata) | |||
327 | 331 | ||
328 | static void del_mesh_stats(struct ieee80211_sub_if_data *sdata) | 332 | static void del_mesh_stats(struct ieee80211_sub_if_data *sdata) |
329 | { | 333 | { |
334 | MESHSTATS_DEL(fwded_mcast); | ||
335 | MESHSTATS_DEL(fwded_unicast); | ||
330 | MESHSTATS_DEL(fwded_frames); | 336 | MESHSTATS_DEL(fwded_frames); |
331 | MESHSTATS_DEL(dropped_frames_ttl); | 337 | MESHSTATS_DEL(dropped_frames_ttl); |
332 | MESHSTATS_DEL(dropped_frames_no_route); | 338 | MESHSTATS_DEL(dropped_frames_no_route); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 4100c361a99d..d231c9323ad1 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -55,16 +55,32 @@ static inline void drv_bss_info_changed(struct ieee80211_local *local, | |||
55 | trace_drv_bss_info_changed(local, vif, info, changed); | 55 | trace_drv_bss_info_changed(local, vif, info, changed); |
56 | } | 56 | } |
57 | 57 | ||
58 | static inline u64 drv_prepare_multicast(struct ieee80211_local *local, | ||
59 | int mc_count, | ||
60 | struct dev_addr_list *mc_list) | ||
61 | { | ||
62 | u64 ret = 0; | ||
63 | |||
64 | if (local->ops->prepare_multicast) | ||
65 | ret = local->ops->prepare_multicast(&local->hw, mc_count, | ||
66 | mc_list); | ||
67 | |||
68 | trace_drv_prepare_multicast(local, mc_count, ret); | ||
69 | |||
70 | return ret; | ||
71 | } | ||
72 | |||
58 | static inline void drv_configure_filter(struct ieee80211_local *local, | 73 | static inline void drv_configure_filter(struct ieee80211_local *local, |
59 | unsigned int changed_flags, | 74 | unsigned int changed_flags, |
60 | unsigned int *total_flags, | 75 | unsigned int *total_flags, |
61 | int mc_count, | 76 | u64 multicast) |
62 | struct dev_addr_list *mc_list) | ||
63 | { | 77 | { |
78 | might_sleep(); | ||
79 | |||
64 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, | 80 | local->ops->configure_filter(&local->hw, changed_flags, total_flags, |
65 | mc_count, mc_list); | 81 | multicast); |
66 | trace_drv_configure_filter(local, changed_flags, total_flags, | 82 | trace_drv_configure_filter(local, changed_flags, total_flags, |
67 | mc_count); | 83 | multicast); |
68 | } | 84 | } |
69 | 85 | ||
70 | static inline int drv_set_tim(struct ieee80211_local *local, | 86 | static inline int drv_set_tim(struct ieee80211_local *local, |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 5a10da2d70fd..37b9051afcf3 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -191,31 +191,55 @@ TRACE_EVENT(drv_bss_info_changed, | |||
191 | ) | 191 | ) |
192 | ); | 192 | ); |
193 | 193 | ||
194 | TRACE_EVENT(drv_prepare_multicast, | ||
195 | TP_PROTO(struct ieee80211_local *local, int mc_count, u64 ret), | ||
196 | |||
197 | TP_ARGS(local, mc_count, ret), | ||
198 | |||
199 | TP_STRUCT__entry( | ||
200 | LOCAL_ENTRY | ||
201 | __field(int, mc_count) | ||
202 | __field(u64, ret) | ||
203 | ), | ||
204 | |||
205 | TP_fast_assign( | ||
206 | LOCAL_ASSIGN; | ||
207 | __entry->mc_count = mc_count; | ||
208 | __entry->ret = ret; | ||
209 | ), | ||
210 | |||
211 | TP_printk( | ||
212 | LOCAL_PR_FMT " prepare mc (%d): %llx", | ||
213 | LOCAL_PR_ARG, __entry->mc_count, | ||
214 | (unsigned long long) __entry->ret | ||
215 | ) | ||
216 | ); | ||
217 | |||
194 | TRACE_EVENT(drv_configure_filter, | 218 | TRACE_EVENT(drv_configure_filter, |
195 | TP_PROTO(struct ieee80211_local *local, | 219 | TP_PROTO(struct ieee80211_local *local, |
196 | unsigned int changed_flags, | 220 | unsigned int changed_flags, |
197 | unsigned int *total_flags, | 221 | unsigned int *total_flags, |
198 | int mc_count), | 222 | u64 multicast), |
199 | 223 | ||
200 | TP_ARGS(local, changed_flags, total_flags, mc_count), | 224 | TP_ARGS(local, changed_flags, total_flags, multicast), |
201 | 225 | ||
202 | TP_STRUCT__entry( | 226 | TP_STRUCT__entry( |
203 | LOCAL_ENTRY | 227 | LOCAL_ENTRY |
204 | __field(unsigned int, changed) | 228 | __field(unsigned int, changed) |
205 | __field(unsigned int, total) | 229 | __field(unsigned int, total) |
206 | __field(int, mc) | 230 | __field(u64, multicast) |
207 | ), | 231 | ), |
208 | 232 | ||
209 | TP_fast_assign( | 233 | TP_fast_assign( |
210 | LOCAL_ASSIGN; | 234 | LOCAL_ASSIGN; |
211 | __entry->changed = changed_flags; | 235 | __entry->changed = changed_flags; |
212 | __entry->total = *total_flags; | 236 | __entry->total = *total_flags; |
213 | __entry->mc = mc_count; | 237 | __entry->multicast = multicast; |
214 | ), | 238 | ), |
215 | 239 | ||
216 | TP_printk( | 240 | TP_printk( |
217 | LOCAL_PR_FMT " changed:%#x total:%#x mc:%d", | 241 | LOCAL_PR_FMT " changed:%#x total:%#x", |
218 | LOCAL_PR_ARG, __entry->changed, __entry->total, __entry->mc | 242 | LOCAL_PR_ARG, __entry->changed, __entry->total |
219 | ) | 243 | ) |
220 | ); | 244 | ); |
221 | 245 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a6abc7dfd903..93e618a980d1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -212,7 +212,9 @@ struct ieee80211_if_vlan { | |||
212 | }; | 212 | }; |
213 | 213 | ||
214 | struct mesh_stats { | 214 | struct mesh_stats { |
215 | __u32 fwded_frames; /* Mesh forwarded frames */ | 215 | __u32 fwded_mcast; /* Mesh forwarded multicast frames */ |
216 | __u32 fwded_unicast; /* Mesh forwarded unicast frames */ | ||
217 | __u32 fwded_frames; /* Mesh total forwarded frames */ | ||
216 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ | 218 | __u32 dropped_frames_ttl; /* Not transmitted since mesh_ttl == 0*/ |
217 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ | 219 | __u32 dropped_frames_no_route; /* Not transmitted, no route found */ |
218 | atomic_t estab_plinks; | 220 | atomic_t estab_plinks; |
@@ -506,6 +508,8 @@ struct ieee80211_sub_if_data { | |||
506 | #ifdef CONFIG_MAC80211_MESH | 508 | #ifdef CONFIG_MAC80211_MESH |
507 | struct dentry *mesh_stats_dir; | 509 | struct dentry *mesh_stats_dir; |
508 | struct { | 510 | struct { |
511 | struct dentry *fwded_mcast; | ||
512 | struct dentry *fwded_unicast; | ||
509 | struct dentry *fwded_frames; | 513 | struct dentry *fwded_frames; |
510 | struct dentry *dropped_frames_ttl; | 514 | struct dentry *dropped_frames_ttl; |
511 | struct dentry *dropped_frames_no_route; | 515 | struct dentry *dropped_frames_no_route; |
@@ -636,6 +640,9 @@ struct ieee80211_local { | |||
636 | /* protects the aggregated multicast list and filter calls */ | 640 | /* protects the aggregated multicast list and filter calls */ |
637 | spinlock_t filter_lock; | 641 | spinlock_t filter_lock; |
638 | 642 | ||
643 | /* used for uploading changed mc list */ | ||
644 | struct work_struct reconfig_filter; | ||
645 | |||
639 | /* aggregated multicast list */ | 646 | /* aggregated multicast list */ |
640 | struct dev_addr_list *mc_list; | 647 | struct dev_addr_list *mc_list; |
641 | int mc_count; | 648 | int mc_count; |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index e8fb03b91a44..b161301056df 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -227,9 +227,7 @@ static int ieee80211_open(struct net_device *dev) | |||
227 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 227 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
228 | local->fif_other_bss++; | 228 | local->fif_other_bss++; |
229 | 229 | ||
230 | spin_lock_bh(&local->filter_lock); | ||
231 | ieee80211_configure_filter(local); | 230 | ieee80211_configure_filter(local); |
232 | spin_unlock_bh(&local->filter_lock); | ||
233 | break; | 231 | break; |
234 | default: | 232 | default: |
235 | conf.vif = &sdata->vif; | 233 | conf.vif = &sdata->vif; |
@@ -241,17 +239,13 @@ static int ieee80211_open(struct net_device *dev) | |||
241 | 239 | ||
242 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 240 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
243 | local->fif_other_bss++; | 241 | local->fif_other_bss++; |
244 | spin_lock_bh(&local->filter_lock); | ||
245 | ieee80211_configure_filter(local); | 242 | ieee80211_configure_filter(local); |
246 | spin_unlock_bh(&local->filter_lock); | ||
247 | 243 | ||
248 | ieee80211_start_mesh(sdata); | 244 | ieee80211_start_mesh(sdata); |
249 | } else if (sdata->vif.type == NL80211_IFTYPE_AP) { | 245 | } else if (sdata->vif.type == NL80211_IFTYPE_AP) { |
250 | local->fif_pspoll++; | 246 | local->fif_pspoll++; |
251 | 247 | ||
252 | spin_lock_bh(&local->filter_lock); | ||
253 | ieee80211_configure_filter(local); | 248 | ieee80211_configure_filter(local); |
254 | spin_unlock_bh(&local->filter_lock); | ||
255 | } | 249 | } |
256 | 250 | ||
257 | changed |= ieee80211_reset_erp_info(sdata); | 251 | changed |= ieee80211_reset_erp_info(sdata); |
@@ -404,10 +398,11 @@ static int ieee80211_stop(struct net_device *dev) | |||
404 | spin_lock_bh(&local->filter_lock); | 398 | spin_lock_bh(&local->filter_lock); |
405 | __dev_addr_unsync(&local->mc_list, &local->mc_count, | 399 | __dev_addr_unsync(&local->mc_list, &local->mc_count, |
406 | &dev->mc_list, &dev->mc_count); | 400 | &dev->mc_list, &dev->mc_count); |
407 | ieee80211_configure_filter(local); | ||
408 | spin_unlock_bh(&local->filter_lock); | 401 | spin_unlock_bh(&local->filter_lock); |
409 | netif_addr_unlock_bh(dev); | 402 | netif_addr_unlock_bh(dev); |
410 | 403 | ||
404 | ieee80211_configure_filter(local); | ||
405 | |||
411 | del_timer_sync(&local->dynamic_ps_timer); | 406 | del_timer_sync(&local->dynamic_ps_timer); |
412 | cancel_work_sync(&local->dynamic_ps_enable_work); | 407 | cancel_work_sync(&local->dynamic_ps_enable_work); |
413 | 408 | ||
@@ -458,9 +453,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
458 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) | 453 | if (sdata->u.mntr_flags & MONITOR_FLAG_OTHER_BSS) |
459 | local->fif_other_bss--; | 454 | local->fif_other_bss--; |
460 | 455 | ||
461 | spin_lock_bh(&local->filter_lock); | ||
462 | ieee80211_configure_filter(local); | 456 | ieee80211_configure_filter(local); |
463 | spin_unlock_bh(&local->filter_lock); | ||
464 | break; | 457 | break; |
465 | case NL80211_IFTYPE_STATION: | 458 | case NL80211_IFTYPE_STATION: |
466 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 459 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
@@ -503,9 +496,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
503 | local->fif_other_bss--; | 496 | local->fif_other_bss--; |
504 | atomic_dec(&local->iff_allmultis); | 497 | atomic_dec(&local->iff_allmultis); |
505 | 498 | ||
506 | spin_lock_bh(&local->filter_lock); | ||
507 | ieee80211_configure_filter(local); | 499 | ieee80211_configure_filter(local); |
508 | spin_unlock_bh(&local->filter_lock); | ||
509 | 500 | ||
510 | ieee80211_stop_mesh(sdata); | 501 | ieee80211_stop_mesh(sdata); |
511 | } | 502 | } |
@@ -622,8 +613,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
622 | spin_lock_bh(&local->filter_lock); | 613 | spin_lock_bh(&local->filter_lock); |
623 | __dev_addr_sync(&local->mc_list, &local->mc_count, | 614 | __dev_addr_sync(&local->mc_list, &local->mc_count, |
624 | &dev->mc_list, &dev->mc_count); | 615 | &dev->mc_list, &dev->mc_count); |
625 | ieee80211_configure_filter(local); | ||
626 | spin_unlock_bh(&local->filter_lock); | 616 | spin_unlock_bh(&local->filter_lock); |
617 | ieee80211_queue_work(&local->hw, &local->reconfig_filter); | ||
627 | } | 618 | } |
628 | 619 | ||
629 | /* | 620 | /* |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index b03fd84777fa..dd3b0816614d 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -50,9 +50,9 @@ struct ieee80211_tx_status_rtap_hdr { | |||
50 | } __attribute__ ((packed)); | 50 | } __attribute__ ((packed)); |
51 | 51 | ||
52 | 52 | ||
53 | /* must be called under mdev tx lock */ | ||
54 | void ieee80211_configure_filter(struct ieee80211_local *local) | 53 | void ieee80211_configure_filter(struct ieee80211_local *local) |
55 | { | 54 | { |
55 | u64 mc; | ||
56 | unsigned int changed_flags; | 56 | unsigned int changed_flags; |
57 | unsigned int new_flags = 0; | 57 | unsigned int new_flags = 0; |
58 | 58 | ||
@@ -62,7 +62,7 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
62 | if (atomic_read(&local->iff_allmultis)) | 62 | if (atomic_read(&local->iff_allmultis)) |
63 | new_flags |= FIF_ALLMULTI; | 63 | new_flags |= FIF_ALLMULTI; |
64 | 64 | ||
65 | if (local->monitors) | 65 | if (local->monitors || local->scanning) |
66 | new_flags |= FIF_BCN_PRBRESP_PROMISC; | 66 | new_flags |= FIF_BCN_PRBRESP_PROMISC; |
67 | 67 | ||
68 | if (local->fif_fcsfail) | 68 | if (local->fif_fcsfail) |
@@ -80,20 +80,30 @@ void ieee80211_configure_filter(struct ieee80211_local *local) | |||
80 | if (local->fif_pspoll) | 80 | if (local->fif_pspoll) |
81 | new_flags |= FIF_PSPOLL; | 81 | new_flags |= FIF_PSPOLL; |
82 | 82 | ||
83 | spin_lock_bh(&local->filter_lock); | ||
83 | changed_flags = local->filter_flags ^ new_flags; | 84 | changed_flags = local->filter_flags ^ new_flags; |
84 | 85 | ||
86 | mc = drv_prepare_multicast(local, local->mc_count, local->mc_list); | ||
87 | spin_unlock_bh(&local->filter_lock); | ||
88 | |||
85 | /* be a bit nasty */ | 89 | /* be a bit nasty */ |
86 | new_flags |= (1<<31); | 90 | new_flags |= (1<<31); |
87 | 91 | ||
88 | drv_configure_filter(local, changed_flags, &new_flags, | 92 | drv_configure_filter(local, changed_flags, &new_flags, mc); |
89 | local->mc_count, | ||
90 | local->mc_list); | ||
91 | 93 | ||
92 | WARN_ON(new_flags & (1<<31)); | 94 | WARN_ON(new_flags & (1<<31)); |
93 | 95 | ||
94 | local->filter_flags = new_flags & ~(1<<31); | 96 | local->filter_flags = new_flags & ~(1<<31); |
95 | } | 97 | } |
96 | 98 | ||
99 | static void ieee80211_reconfig_filter(struct work_struct *work) | ||
100 | { | ||
101 | struct ieee80211_local *local = | ||
102 | container_of(work, struct ieee80211_local, reconfig_filter); | ||
103 | |||
104 | ieee80211_configure_filter(local); | ||
105 | } | ||
106 | |||
97 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | 107 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) |
98 | { | 108 | { |
99 | struct ieee80211_channel *chan, *scan_chan; | 109 | struct ieee80211_channel *chan, *scan_chan; |
@@ -231,9 +241,6 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
231 | 241 | ||
232 | drv_bss_info_changed(local, &sdata->vif, | 242 | drv_bss_info_changed(local, &sdata->vif, |
233 | &sdata->vif.bss_conf, changed); | 243 | &sdata->vif.bss_conf, changed); |
234 | |||
235 | /* DEPRECATED */ | ||
236 | local->hw.conf.beacon_int = sdata->vif.bss_conf.beacon_int; | ||
237 | } | 244 | } |
238 | 245 | ||
239 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | 246 | u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) |
@@ -475,6 +482,8 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
475 | } | 482 | } |
476 | 483 | ||
477 | rate_control_tx_status(local, sband, sta, skb); | 484 | rate_control_tx_status(local, sband, sta, skb); |
485 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
486 | ieee80211s_update_metric(local, sta, skb); | ||
478 | } | 487 | } |
479 | 488 | ||
480 | rcu_read_unlock(); | 489 | rcu_read_unlock(); |
@@ -677,7 +686,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
677 | local->hw.max_rates = 1; | 686 | local->hw.max_rates = 1; |
678 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 687 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
679 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 688 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
680 | local->hw.conf.radio_enabled = true; | ||
681 | local->user_power_level = -1; | 689 | local->user_power_level = -1; |
682 | 690 | ||
683 | INIT_LIST_HEAD(&local->interfaces); | 691 | INIT_LIST_HEAD(&local->interfaces); |
@@ -692,6 +700,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
692 | 700 | ||
693 | INIT_WORK(&local->restart_work, ieee80211_restart_work); | 701 | INIT_WORK(&local->restart_work, ieee80211_restart_work); |
694 | 702 | ||
703 | INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter); | ||
704 | |||
695 | INIT_WORK(&local->dynamic_ps_enable_work, | 705 | INIT_WORK(&local->dynamic_ps_enable_work, |
696 | ieee80211_dynamic_ps_enable_work); | 706 | ieee80211_dynamic_ps_enable_work); |
697 | INIT_WORK(&local->dynamic_ps_disable_work, | 707 | INIT_WORK(&local->dynamic_ps_disable_work, |
@@ -920,7 +930,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
920 | fail_workqueue: | 930 | fail_workqueue: |
921 | wiphy_unregister(local->hw.wiphy); | 931 | wiphy_unregister(local->hw.wiphy); |
922 | fail_wiphy_register: | 932 | fail_wiphy_register: |
923 | kfree(local->int_scan_req->channels); | 933 | kfree(local->int_scan_req); |
924 | return result; | 934 | return result; |
925 | } | 935 | } |
926 | EXPORT_SYMBOL(ieee80211_register_hw); | 936 | EXPORT_SYMBOL(ieee80211_register_hw); |
@@ -946,6 +956,8 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw) | |||
946 | 956 | ||
947 | rtnl_unlock(); | 957 | rtnl_unlock(); |
948 | 958 | ||
959 | cancel_work_sync(&local->reconfig_filter); | ||
960 | |||
949 | ieee80211_clear_tx_pending(local); | 961 | ieee80211_clear_tx_pending(local); |
950 | sta_info_stop(local); | 962 | sta_info_stop(local); |
951 | rate_control_deinitialize(local); | 963 | rate_control_deinitialize(local); |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index eb23fc639b2b..dd1c19319f0a 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -226,6 +226,8 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, | |||
226 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); | 226 | void mesh_rmc_free(struct ieee80211_sub_if_data *sdata); |
227 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); | 227 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata); |
228 | void ieee80211s_init(void); | 228 | void ieee80211s_init(void); |
229 | void ieee80211s_update_metric(struct ieee80211_local *local, | ||
230 | struct sta_info *stainfo, struct sk_buff *skb); | ||
229 | void ieee80211s_stop(void); | 231 | void ieee80211s_stop(void); |
230 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); | 232 | void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata); |
231 | ieee80211_rx_result | 233 | ieee80211_rx_result |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index ef1efd362691..e12a786e26b8 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -201,6 +201,24 @@ int mesh_path_error_tx(u8 *dst, __le32 dst_dsn, u8 *ra, | |||
201 | return 0; | 201 | return 0; |
202 | } | 202 | } |
203 | 203 | ||
204 | void ieee80211s_update_metric(struct ieee80211_local *local, | ||
205 | struct sta_info *stainfo, struct sk_buff *skb) | ||
206 | { | ||
207 | struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); | ||
208 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
209 | int failed; | ||
210 | |||
211 | if (!ieee80211_is_data(hdr->frame_control)) | ||
212 | return; | ||
213 | |||
214 | failed = !(txinfo->flags & IEEE80211_TX_STAT_ACK); | ||
215 | |||
216 | /* moving average, scaled to 100 */ | ||
217 | stainfo->fail_avg = ((80 * stainfo->fail_avg + 5) / 100 + 20 * failed); | ||
218 | if (stainfo->fail_avg > 95) | ||
219 | mesh_plink_broken(stainfo); | ||
220 | } | ||
221 | |||
204 | static u32 airtime_link_metric_get(struct ieee80211_local *local, | 222 | static u32 airtime_link_metric_get(struct ieee80211_local *local, |
205 | struct sta_info *sta) | 223 | struct sta_info *sta) |
206 | { | 224 | { |
@@ -479,6 +497,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
479 | hopcount, ttl, cpu_to_le32(lifetime), | 497 | hopcount, ttl, cpu_to_le32(lifetime), |
480 | cpu_to_le32(metric), cpu_to_le32(preq_id), | 498 | cpu_to_le32(metric), cpu_to_le32(preq_id), |
481 | sdata); | 499 | sdata); |
500 | ifmsh->mshstats.fwded_mcast++; | ||
482 | ifmsh->mshstats.fwded_frames++; | 501 | ifmsh->mshstats.fwded_frames++; |
483 | } | 502 | } |
484 | } | 503 | } |
@@ -537,6 +556,8 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
537 | cpu_to_le32(lifetime), cpu_to_le32(metric), | 556 | cpu_to_le32(lifetime), cpu_to_le32(metric), |
538 | 0, sdata); | 557 | 0, sdata); |
539 | rcu_read_unlock(); | 558 | rcu_read_unlock(); |
559 | |||
560 | sdata->u.mesh.mshstats.fwded_unicast++; | ||
540 | sdata->u.mesh.mshstats.fwded_frames++; | 561 | sdata->u.mesh.mshstats.fwded_frames++; |
541 | return; | 562 | return; |
542 | 563 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 007164919e02..7c5142988bbb 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -51,7 +51,6 @@ | |||
51 | #include <linux/random.h> | 51 | #include <linux/random.h> |
52 | #include <linux/ieee80211.h> | 52 | #include <linux/ieee80211.h> |
53 | #include <net/mac80211.h> | 53 | #include <net/mac80211.h> |
54 | #include "mesh.h" | ||
55 | #include "rate.h" | 54 | #include "rate.h" |
56 | #include "rc80211_minstrel.h" | 55 | #include "rc80211_minstrel.h" |
57 | 56 | ||
@@ -156,16 +155,12 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
156 | struct sk_buff *skb) | 155 | struct sk_buff *skb) |
157 | { | 156 | { |
158 | struct minstrel_sta_info *mi = priv_sta; | 157 | struct minstrel_sta_info *mi = priv_sta; |
159 | struct minstrel_priv *mp = (struct minstrel_priv *)priv; | ||
160 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 158 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
161 | struct ieee80211_tx_rate *ar = info->status.rates; | 159 | struct ieee80211_tx_rate *ar = info->status.rates; |
162 | struct ieee80211_local *local = hw_to_local(mp->hw); | ||
163 | struct sta_info *si; | ||
164 | int i, ndx; | 160 | int i, ndx; |
165 | int success; | 161 | int success; |
166 | 162 | ||
167 | success = !!(info->flags & IEEE80211_TX_STAT_ACK); | 163 | success = !!(info->flags & IEEE80211_TX_STAT_ACK); |
168 | si = sta_info_get(local, sta->addr); | ||
169 | 164 | ||
170 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 165 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
171 | if (ar[i].idx < 0) | 166 | if (ar[i].idx < 0) |
@@ -177,17 +172,8 @@ minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
177 | 172 | ||
178 | mi->r[ndx].attempts += ar[i].count; | 173 | mi->r[ndx].attempts += ar[i].count; |
179 | 174 | ||
180 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) { | 175 | if ((i != IEEE80211_TX_MAX_RATES - 1) && (ar[i + 1].idx < 0)) |
181 | mi->r[ndx].success += success; | 176 | mi->r[ndx].success += success; |
182 | if (si) { | ||
183 | si->fail_avg = (18050 - mi->r[ndx].probability) | ||
184 | / 180; | ||
185 | WARN_ON(si->fail_avg > 100); | ||
186 | if (si->fail_avg == 100 && | ||
187 | ieee80211_vif_is_mesh(&si->sdata->vif)) | ||
188 | mesh_plink_broken(si); | ||
189 | } | ||
190 | } | ||
191 | } | 177 | } |
192 | 178 | ||
193 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) | 179 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 8c053be9dc24..699d3ed869c4 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
@@ -169,19 +169,9 @@ static void rate_control_pid_sample(struct rc_pid_info *pinfo, | |||
169 | * still a good measurement and copy it. */ | 169 | * still a good measurement and copy it. */ |
170 | if (unlikely(spinfo->tx_num_xmit == 0)) | 170 | if (unlikely(spinfo->tx_num_xmit == 0)) |
171 | pf = spinfo->last_pf; | 171 | pf = spinfo->last_pf; |
172 | else { | 172 | else |
173 | /* XXX: BAD HACK!!! */ | ||
174 | struct sta_info *si = container_of(sta, struct sta_info, sta); | ||
175 | |||
176 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | 173 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; |
177 | 174 | ||
178 | if (ieee80211_vif_is_mesh(&si->sdata->vif) && pf == 100) | ||
179 | mesh_plink_broken(si); | ||
180 | pf <<= RC_PID_ARITH_SHIFT; | ||
181 | si->fail_avg = ((pf + (spinfo->last_pf << 3)) / 9) | ||
182 | >> RC_PID_ARITH_SHIFT; | ||
183 | } | ||
184 | |||
185 | spinfo->tx_num_xmit = 0; | 175 | spinfo->tx_num_xmit = 0; |
186 | spinfo->tx_num_failed = 0; | 176 | spinfo->tx_num_failed = 0; |
187 | 177 | ||
@@ -311,7 +301,6 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
311 | struct rc_pid_sta_info *spinfo = priv_sta; | 301 | struct rc_pid_sta_info *spinfo = priv_sta; |
312 | struct rc_pid_info *pinfo = priv; | 302 | struct rc_pid_info *pinfo = priv; |
313 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | 303 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; |
314 | struct sta_info *si; | ||
315 | int i, j, tmp; | 304 | int i, j, tmp; |
316 | bool s; | 305 | bool s; |
317 | 306 | ||
@@ -348,9 +337,6 @@ rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
348 | } | 337 | } |
349 | 338 | ||
350 | spinfo->txrate_idx = rate_lowest_index(sband, sta); | 339 | spinfo->txrate_idx = rate_lowest_index(sband, sta); |
351 | /* HACK */ | ||
352 | si = container_of(sta, struct sta_info, sta); | ||
353 | si->fail_avg = 0; | ||
354 | } | 340 | } |
355 | 341 | ||
356 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, | 342 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 4cd9e45b1443..7065fd7e7ba2 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -1550,7 +1550,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1550 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1550 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
1551 | info->control.vif = &rx->sdata->vif; | 1551 | info->control.vif = &rx->sdata->vif; |
1552 | ieee80211_select_queue(local, fwd_skb); | 1552 | ieee80211_select_queue(local, fwd_skb); |
1553 | if (!is_multicast_ether_addr(fwd_hdr->addr1)) { | 1553 | if (is_multicast_ether_addr(fwd_hdr->addr1)) |
1554 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1555 | fwded_mcast); | ||
1556 | else { | ||
1554 | int err; | 1557 | int err; |
1555 | /* | 1558 | /* |
1556 | * Save TA to addr1 to send TA a path error if a | 1559 | * Save TA to addr1 to send TA a path error if a |
@@ -1564,6 +1567,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1564 | * later to the pending skb queue. */ | 1567 | * later to the pending skb queue. */ |
1565 | if (err) | 1568 | if (err) |
1566 | return RX_DROP_MONITOR; | 1569 | return RX_DROP_MONITOR; |
1570 | |||
1571 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | ||
1572 | fwded_unicast); | ||
1567 | } | 1573 | } |
1568 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, | 1574 | IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.mesh, |
1569 | fwded_frames); | 1575 | fwded_frames); |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index e091cbc3434f..1e04be6b9129 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -292,13 +292,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
292 | if (was_hw_scan) | 292 | if (was_hw_scan) |
293 | goto done; | 293 | goto done; |
294 | 294 | ||
295 | spin_lock_bh(&local->filter_lock); | 295 | ieee80211_configure_filter(local); |
296 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | ||
297 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | ||
298 | &local->filter_flags, | ||
299 | local->mc_count, | ||
300 | local->mc_list); | ||
301 | spin_unlock_bh(&local->filter_lock); | ||
302 | 296 | ||
303 | drv_sw_scan_complete(local); | 297 | drv_sw_scan_complete(local); |
304 | 298 | ||
@@ -376,13 +370,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
376 | local->next_scan_state = SCAN_DECISION; | 370 | local->next_scan_state = SCAN_DECISION; |
377 | local->scan_channel_idx = 0; | 371 | local->scan_channel_idx = 0; |
378 | 372 | ||
379 | spin_lock_bh(&local->filter_lock); | 373 | ieee80211_configure_filter(local); |
380 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
381 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | ||
382 | &local->filter_flags, | ||
383 | local->mc_count, | ||
384 | local->mc_list); | ||
385 | spin_unlock_bh(&local->filter_lock); | ||
386 | 374 | ||
387 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 375 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
388 | ieee80211_queue_delayed_work(&local->hw, | 376 | ieee80211_queue_delayed_work(&local->hw, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e55d57f559ec..5eb306377c63 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1076,9 +1076,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1076 | /* reconfigure hardware */ | 1076 | /* reconfigure hardware */ |
1077 | ieee80211_hw_config(local, ~0); | 1077 | ieee80211_hw_config(local, ~0); |
1078 | 1078 | ||
1079 | spin_lock_bh(&local->filter_lock); | ||
1080 | ieee80211_configure_filter(local); | 1079 | ieee80211_configure_filter(local); |
1081 | spin_unlock_bh(&local->filter_lock); | ||
1082 | 1080 | ||
1083 | /* Finally also reconfigure all the BSS information */ | 1081 | /* Finally also reconfigure all the BSS information */ |
1084 | list_for_each_entry(sdata, &local->interfaces, list) { | 1082 | list_for_each_entry(sdata, &local->interfaces, list) { |
diff --git a/net/wireless/core.c b/net/wireless/core.c index bc99e4ec7463..154e1e294cb9 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/debugfs.h> | 12 | #include <linux/debugfs.h> |
13 | #include <linux/notifier.h> | 13 | #include <linux/notifier.h> |
14 | #include <linux/device.h> | 14 | #include <linux/device.h> |
15 | #include <linux/etherdevice.h> | ||
15 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
16 | #include <net/genetlink.h> | 17 | #include <net/genetlink.h> |
17 | #include <net/cfg80211.h> | 18 | #include <net/cfg80211.h> |
@@ -309,7 +310,8 @@ static void cfg80211_process_events(struct wireless_dev *wdev) | |||
309 | switch (ev->type) { | 310 | switch (ev->type) { |
310 | case EVENT_CONNECT_RESULT: | 311 | case EVENT_CONNECT_RESULT: |
311 | __cfg80211_connect_result( | 312 | __cfg80211_connect_result( |
312 | wdev->netdev, ev->cr.bssid, | 313 | wdev->netdev, is_zero_ether_addr(ev->cr.bssid) ? |
314 | NULL : ev->cr.bssid, | ||
313 | ev->cr.req_ie, ev->cr.req_ie_len, | 315 | ev->cr.req_ie, ev->cr.req_ie_len, |
314 | ev->cr.resp_ie, ev->cr.resp_ie_len, | 316 | ev->cr.resp_ie, ev->cr.resp_ie_len, |
315 | ev->cr.status, | 317 | ev->cr.status, |
@@ -430,6 +432,8 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
430 | INIT_WORK(&rdev->conn_work, cfg80211_conn_work); | 432 | INIT_WORK(&rdev->conn_work, cfg80211_conn_work); |
431 | INIT_WORK(&rdev->event_work, cfg80211_event_work); | 433 | INIT_WORK(&rdev->event_work, cfg80211_event_work); |
432 | 434 | ||
435 | init_waitqueue_head(&rdev->dev_wait); | ||
436 | |||
433 | /* | 437 | /* |
434 | * Initialize wiphy parameters to IEEE 802.11 MIB default values. | 438 | * Initialize wiphy parameters to IEEE 802.11 MIB default values. |
435 | * Fragmentation and RTS threshold are disabled by default with the | 439 | * Fragmentation and RTS threshold are disabled by default with the |
@@ -574,7 +578,23 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
574 | /* protect the device list */ | 578 | /* protect the device list */ |
575 | mutex_lock(&cfg80211_mutex); | 579 | mutex_lock(&cfg80211_mutex); |
576 | 580 | ||
581 | wait_event(rdev->dev_wait, ({ | ||
582 | int __count; | ||
583 | mutex_lock(&rdev->devlist_mtx); | ||
584 | __count = rdev->opencount; | ||
585 | mutex_unlock(&rdev->devlist_mtx); | ||
586 | __count == 0;})); | ||
587 | |||
588 | mutex_lock(&rdev->devlist_mtx); | ||
577 | BUG_ON(!list_empty(&rdev->netdev_list)); | 589 | BUG_ON(!list_empty(&rdev->netdev_list)); |
590 | mutex_unlock(&rdev->devlist_mtx); | ||
591 | |||
592 | /* | ||
593 | * First remove the hardware from everywhere, this makes | ||
594 | * it impossible to find from userspace. | ||
595 | */ | ||
596 | cfg80211_debugfs_rdev_del(rdev); | ||
597 | list_del(&rdev->list); | ||
578 | 598 | ||
579 | /* | 599 | /* |
580 | * Try to grab rdev->mtx. If a command is still in progress, | 600 | * Try to grab rdev->mtx. If a command is still in progress, |
@@ -582,21 +602,18 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
582 | * down the device already. We wait for this command to complete | 602 | * down the device already. We wait for this command to complete |
583 | * before unlinking the item from the list. | 603 | * before unlinking the item from the list. |
584 | * Note: as codified by the BUG_ON above we cannot get here if | 604 | * Note: as codified by the BUG_ON above we cannot get here if |
585 | * a virtual interface is still associated. Hence, we can only | 605 | * a virtual interface is still present. Hence, we can only get |
586 | * get to lock contention here if userspace issues a command | 606 | * to lock contention here if userspace issues a command that |
587 | * that identified the hardware by wiphy index. | 607 | * identified the hardware by wiphy index. |
588 | */ | 608 | */ |
589 | mutex_lock(&rdev->mtx); | 609 | cfg80211_lock_rdev(rdev); |
590 | /* unlock again before freeing */ | 610 | /* nothing */ |
591 | mutex_unlock(&rdev->mtx); | 611 | cfg80211_unlock_rdev(rdev); |
592 | |||
593 | cfg80211_debugfs_rdev_del(rdev); | ||
594 | 612 | ||
595 | /* If this device got a regulatory hint tell core its | 613 | /* If this device got a regulatory hint tell core its |
596 | * free to listen now to a new shiny device regulatory hint */ | 614 | * free to listen now to a new shiny device regulatory hint */ |
597 | reg_device_remove(wiphy); | 615 | reg_device_remove(wiphy); |
598 | 616 | ||
599 | list_del(&rdev->list); | ||
600 | cfg80211_rdev_list_generation++; | 617 | cfg80211_rdev_list_generation++; |
601 | device_del(&rdev->wiphy.dev); | 618 | device_del(&rdev->wiphy.dev); |
602 | debugfs_remove(rdev->wiphy.debugfsdir); | 619 | debugfs_remove(rdev->wiphy.debugfsdir); |
@@ -605,7 +622,6 @@ void wiphy_unregister(struct wiphy *wiphy) | |||
605 | 622 | ||
606 | flush_work(&rdev->scan_done_wk); | 623 | flush_work(&rdev->scan_done_wk); |
607 | cancel_work_sync(&rdev->conn_work); | 624 | cancel_work_sync(&rdev->conn_work); |
608 | kfree(rdev->scan_req); | ||
609 | flush_work(&rdev->event_work); | 625 | flush_work(&rdev->event_work); |
610 | } | 626 | } |
611 | EXPORT_SYMBOL(wiphy_unregister); | 627 | EXPORT_SYMBOL(wiphy_unregister); |
@@ -636,6 +652,31 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked) | |||
636 | } | 652 | } |
637 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); | 653 | EXPORT_SYMBOL(wiphy_rfkill_set_hw_state); |
638 | 654 | ||
655 | static void wdev_cleanup_work(struct work_struct *work) | ||
656 | { | ||
657 | struct wireless_dev *wdev; | ||
658 | struct cfg80211_registered_device *rdev; | ||
659 | |||
660 | wdev = container_of(work, struct wireless_dev, cleanup_work); | ||
661 | rdev = wiphy_to_dev(wdev->wiphy); | ||
662 | |||
663 | cfg80211_lock_rdev(rdev); | ||
664 | |||
665 | if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == wdev->netdev)) { | ||
666 | rdev->scan_req->aborted = true; | ||
667 | ___cfg80211_scan_done(rdev); | ||
668 | } | ||
669 | |||
670 | cfg80211_unlock_rdev(rdev); | ||
671 | |||
672 | mutex_lock(&rdev->devlist_mtx); | ||
673 | rdev->opencount--; | ||
674 | mutex_unlock(&rdev->devlist_mtx); | ||
675 | wake_up(&rdev->dev_wait); | ||
676 | |||
677 | dev_put(wdev->netdev); | ||
678 | } | ||
679 | |||
639 | static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | 680 | static int cfg80211_netdev_notifier_call(struct notifier_block * nb, |
640 | unsigned long state, | 681 | unsigned long state, |
641 | void *ndev) | 682 | void *ndev) |
@@ -653,7 +694,13 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
653 | 694 | ||
654 | switch (state) { | 695 | switch (state) { |
655 | case NETDEV_REGISTER: | 696 | case NETDEV_REGISTER: |
697 | /* | ||
698 | * NB: cannot take rdev->mtx here because this may be | ||
699 | * called within code protected by it when interfaces | ||
700 | * are added with nl80211. | ||
701 | */ | ||
656 | mutex_init(&wdev->mtx); | 702 | mutex_init(&wdev->mtx); |
703 | INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work); | ||
657 | INIT_LIST_HEAD(&wdev->event_list); | 704 | INIT_LIST_HEAD(&wdev->event_list); |
658 | spin_lock_init(&wdev->event_lock); | 705 | spin_lock_init(&wdev->event_lock); |
659 | mutex_lock(&rdev->devlist_mtx); | 706 | mutex_lock(&rdev->devlist_mtx); |
@@ -708,8 +755,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
708 | default: | 755 | default: |
709 | break; | 756 | break; |
710 | } | 757 | } |
758 | dev_hold(dev); | ||
759 | schedule_work(&wdev->cleanup_work); | ||
711 | break; | 760 | break; |
712 | case NETDEV_UP: | 761 | case NETDEV_UP: |
762 | /* | ||
763 | * If we have a really quick DOWN/UP succession we may | ||
764 | * have this work still pending ... cancel it and see | ||
765 | * if it was pending, in which case we need to account | ||
766 | * for some of the work it would have done. | ||
767 | */ | ||
768 | if (cancel_work_sync(&wdev->cleanup_work)) { | ||
769 | mutex_lock(&rdev->devlist_mtx); | ||
770 | rdev->opencount--; | ||
771 | mutex_unlock(&rdev->devlist_mtx); | ||
772 | dev_put(dev); | ||
773 | } | ||
713 | #ifdef CONFIG_WIRELESS_EXT | 774 | #ifdef CONFIG_WIRELESS_EXT |
714 | cfg80211_lock_rdev(rdev); | 775 | cfg80211_lock_rdev(rdev); |
715 | mutex_lock(&rdev->devlist_mtx); | 776 | mutex_lock(&rdev->devlist_mtx); |
@@ -725,18 +786,17 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
725 | break; | 786 | break; |
726 | } | 787 | } |
727 | wdev_unlock(wdev); | 788 | wdev_unlock(wdev); |
789 | rdev->opencount++; | ||
728 | mutex_unlock(&rdev->devlist_mtx); | 790 | mutex_unlock(&rdev->devlist_mtx); |
729 | cfg80211_unlock_rdev(rdev); | 791 | cfg80211_unlock_rdev(rdev); |
730 | #endif | 792 | #endif |
731 | break; | 793 | break; |
732 | case NETDEV_UNREGISTER: | 794 | case NETDEV_UNREGISTER: |
733 | cfg80211_lock_rdev(rdev); | 795 | /* |
734 | 796 | * NB: cannot take rdev->mtx here because this may be | |
735 | if (WARN_ON(rdev->scan_req && rdev->scan_req->dev == dev)) { | 797 | * called within code protected by it when interfaces |
736 | rdev->scan_req->aborted = true; | 798 | * are removed with nl80211. |
737 | ___cfg80211_scan_done(rdev); | 799 | */ |
738 | } | ||
739 | |||
740 | mutex_lock(&rdev->devlist_mtx); | 800 | mutex_lock(&rdev->devlist_mtx); |
741 | /* | 801 | /* |
742 | * It is possible to get NETDEV_UNREGISTER | 802 | * It is possible to get NETDEV_UNREGISTER |
@@ -749,13 +809,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
749 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); | 809 | sysfs_remove_link(&dev->dev.kobj, "phy80211"); |
750 | list_del_init(&wdev->list); | 810 | list_del_init(&wdev->list); |
751 | rdev->devlist_generation++; | 811 | rdev->devlist_generation++; |
752 | mutex_destroy(&wdev->mtx); | ||
753 | #ifdef CONFIG_WIRELESS_EXT | 812 | #ifdef CONFIG_WIRELESS_EXT |
754 | kfree(wdev->wext.keys); | 813 | kfree(wdev->wext.keys); |
755 | #endif | 814 | #endif |
756 | } | 815 | } |
757 | mutex_unlock(&rdev->devlist_mtx); | 816 | mutex_unlock(&rdev->devlist_mtx); |
758 | cfg80211_unlock_rdev(rdev); | ||
759 | break; | 817 | break; |
760 | case NETDEV_PRE_UP: | 818 | case NETDEV_PRE_UP: |
761 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) | 819 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) |
diff --git a/net/wireless/core.h b/net/wireless/core.h index c603f5286326..f565432ae22f 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -50,6 +50,8 @@ struct cfg80211_registered_device { | |||
50 | struct mutex devlist_mtx; | 50 | struct mutex devlist_mtx; |
51 | struct list_head netdev_list; | 51 | struct list_head netdev_list; |
52 | int devlist_generation; | 52 | int devlist_generation; |
53 | int opencount; /* also protected by devlist_mtx */ | ||
54 | wait_queue_head_t dev_wait; | ||
53 | 55 | ||
54 | /* BSSes/scanning */ | 56 | /* BSSes/scanning */ |
55 | spinlock_t bss_lock; | 57 | spinlock_t bss_lock; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index da64071ceb84..79d2eec54cec 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -96,6 +96,15 @@ void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len) | |||
96 | WARN_ON(!bss); | 96 | WARN_ON(!bss); |
97 | } | 97 | } |
98 | 98 | ||
99 | if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) { | ||
100 | /* | ||
101 | * This is for the userspace SME, the CONNECTING | ||
102 | * state will be changed to CONNECTED by | ||
103 | * __cfg80211_connect_result() below. | ||
104 | */ | ||
105 | wdev->sme_state = CFG80211_SME_CONNECTING; | ||
106 | } | ||
107 | |||
99 | /* this consumes one bss reference (unless bss is NULL) */ | 108 | /* this consumes one bss reference (unless bss is NULL) */ |
100 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, | 109 | __cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs, |
101 | status_code, | 110 | status_code, |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 8e2ef54ea714..4a8289f9b4f0 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
@@ -351,15 +351,13 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
351 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) | 351 | if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) |
352 | return; | 352 | return; |
353 | 353 | ||
354 | if (wdev->sme_state == CFG80211_SME_CONNECTED) | 354 | if (WARN_ON(wdev->sme_state != CFG80211_SME_CONNECTING)) |
355 | nl80211_send_roamed(wiphy_to_dev(wdev->wiphy), dev, | 355 | return; |
356 | |||
357 | nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, | ||
356 | bssid, req_ie, req_ie_len, | 358 | bssid, req_ie, req_ie_len, |
357 | resp_ie, resp_ie_len, GFP_KERNEL); | 359 | resp_ie, resp_ie_len, |
358 | else | 360 | status, GFP_KERNEL); |
359 | nl80211_send_connect_result(wiphy_to_dev(wdev->wiphy), dev, | ||
360 | bssid, req_ie, req_ie_len, | ||
361 | resp_ie, resp_ie_len, | ||
362 | status, GFP_KERNEL); | ||
363 | 361 | ||
364 | #ifdef CONFIG_WIRELESS_EXT | 362 | #ifdef CONFIG_WIRELESS_EXT |
365 | if (wextev) { | 363 | if (wextev) { |
@@ -392,18 +390,13 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
392 | wdev->current_bss = NULL; | 390 | wdev->current_bss = NULL; |
393 | } | 391 | } |
394 | 392 | ||
395 | if (status == WLAN_STATUS_SUCCESS && | ||
396 | wdev->sme_state == CFG80211_SME_IDLE) | ||
397 | goto success; | ||
398 | |||
399 | if (wdev->sme_state != CFG80211_SME_CONNECTING) | ||
400 | return; | ||
401 | |||
402 | if (wdev->conn) | 393 | if (wdev->conn) |
403 | wdev->conn->state = CFG80211_CONN_IDLE; | 394 | wdev->conn->state = CFG80211_CONN_IDLE; |
404 | 395 | ||
405 | if (status != WLAN_STATUS_SUCCESS) { | 396 | if (status != WLAN_STATUS_SUCCESS) { |
406 | wdev->sme_state = CFG80211_SME_IDLE; | 397 | wdev->sme_state = CFG80211_SME_IDLE; |
398 | if (wdev->conn) | ||
399 | kfree(wdev->conn->ie); | ||
407 | kfree(wdev->conn); | 400 | kfree(wdev->conn); |
408 | wdev->conn = NULL; | 401 | wdev->conn = NULL; |
409 | kfree(wdev->connect_keys); | 402 | kfree(wdev->connect_keys); |
@@ -412,7 +405,6 @@ void __cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
412 | return; | 405 | return; |
413 | } | 406 | } |
414 | 407 | ||
415 | success: | ||
416 | if (!bss) | 408 | if (!bss) |
417 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 409 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, |
418 | wdev->ssid, wdev->ssid_len, | 410 | wdev->ssid, wdev->ssid_len, |
@@ -458,7 +450,8 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid, | |||
458 | return; | 450 | return; |
459 | 451 | ||
460 | ev->type = EVENT_CONNECT_RESULT; | 452 | ev->type = EVENT_CONNECT_RESULT; |
461 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | 453 | if (bssid) |
454 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | ||
462 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); | 455 | ev->cr.req_ie = ((u8 *)ev) + sizeof(*ev); |
463 | ev->cr.req_ie_len = req_ie_len; | 456 | ev->cr.req_ie_len = req_ie_len; |
464 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); | 457 | memcpy((void *)ev->cr.req_ie, req_ie, req_ie_len); |
@@ -789,6 +782,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, | |||
789 | } | 782 | } |
790 | } | 783 | } |
791 | if (err) { | 784 | if (err) { |
785 | kfree(wdev->conn->ie); | ||
792 | kfree(wdev->conn); | 786 | kfree(wdev->conn); |
793 | wdev->conn = NULL; | 787 | wdev->conn = NULL; |
794 | wdev->sme_state = CFG80211_SME_IDLE; | 788 | wdev->sme_state = CFG80211_SME_IDLE; |
@@ -858,6 +852,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, | |||
858 | (wdev->conn->state == CFG80211_CONN_SCANNING || | 852 | (wdev->conn->state == CFG80211_CONN_SCANNING || |
859 | wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) { | 853 | wdev->conn->state == CFG80211_CONN_SCAN_AGAIN)) { |
860 | wdev->sme_state = CFG80211_SME_IDLE; | 854 | wdev->sme_state = CFG80211_SME_IDLE; |
855 | kfree(wdev->conn->ie); | ||
861 | kfree(wdev->conn); | 856 | kfree(wdev->conn); |
862 | wdev->conn = NULL; | 857 | wdev->conn = NULL; |
863 | wdev->ssid_len = 0; | 858 | wdev->ssid_len = 0; |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index c44917492210..c12029b1def0 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -771,6 +771,7 @@ int cfg80211_wext_siwfreq(struct net_device *dev, | |||
771 | return err; | 771 | return err; |
772 | } | 772 | } |
773 | } | 773 | } |
774 | EXPORT_SYMBOL_GPL(cfg80211_wext_siwfreq); | ||
774 | 775 | ||
775 | int cfg80211_wext_giwfreq(struct net_device *dev, | 776 | int cfg80211_wext_giwfreq(struct net_device *dev, |
776 | struct iw_request_info *info, | 777 | struct iw_request_info *info, |