diff options
author | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-24 18:01:29 -0500 |
commit | 4ba3eb034fb6fd1990ccc5a6d71d5abcda37b905 (patch) | |
tree | 0789ba36d96dba330416a1e6a9a68e891a78802a | |
parent | 35700212b45ea9f98fa682cfc1bc1a67c9ccc34b (diff) | |
parent | 18b6c9a2213d3b6e0212e8b225abf95f7564206a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
125 files changed, 3163 insertions, 1936 deletions
diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 7e59b82e64d3..f9d6db8d013e 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c | |||
@@ -850,6 +850,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, | |||
850 | } | 850 | } |
851 | break; | 851 | break; |
852 | 852 | ||
853 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | ||
853 | case AR9170_RX_STATUS_MODULATION_OFDM: | 854 | case AR9170_RX_STATUS_MODULATION_OFDM: |
854 | switch (head->plcp[0] & 0xf) { | 855 | switch (head->plcp[0] & 0xf) { |
855 | case 0xb: | 856 | case 0xb: |
@@ -897,8 +898,7 @@ static int ar9170_rx_mac_status(struct ar9170 *ar, | |||
897 | status->flag |= RX_FLAG_HT; | 898 | status->flag |= RX_FLAG_HT; |
898 | break; | 899 | break; |
899 | 900 | ||
900 | case AR9170_RX_STATUS_MODULATION_DUPOFDM: | 901 | default: |
901 | /* XXX */ | ||
902 | if (ar9170_nag_limiter(ar)) | 902 | if (ar9170_nag_limiter(ar)) |
903 | printk(KERN_ERR "%s: invalid modulation\n", | 903 | printk(KERN_ERR "%s: invalid modulation\n", |
904 | wiphy_name(ar->hw->wiphy)); | 904 | wiphy_name(ar->hw->wiphy)); |
@@ -2441,6 +2441,7 @@ static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, | |||
2441 | } | 2441 | } |
2442 | 2442 | ||
2443 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, | 2443 | static int ar9170_ampdu_action(struct ieee80211_hw *hw, |
2444 | struct ieee80211_vif *vif, | ||
2444 | enum ieee80211_ampdu_mlme_action action, | 2445 | enum ieee80211_ampdu_mlme_action action, |
2445 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2446 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2446 | { | 2447 | { |
@@ -2470,7 +2471,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2470 | tid_info->state = AR9170_TID_STATE_PROGRESS; | 2471 | tid_info->state = AR9170_TID_STATE_PROGRESS; |
2471 | tid_info->active = false; | 2472 | tid_info->active = false; |
2472 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | 2473 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); |
2473 | ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2474 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
2474 | break; | 2475 | break; |
2475 | 2476 | ||
2476 | case IEEE80211_AMPDU_TX_STOP: | 2477 | case IEEE80211_AMPDU_TX_STOP: |
@@ -2480,7 +2481,7 @@ static int ar9170_ampdu_action(struct ieee80211_hw *hw, | |||
2480 | tid_info->active = false; | 2481 | tid_info->active = false; |
2481 | skb_queue_purge(&tid_info->queue); | 2482 | skb_queue_purge(&tid_info->queue); |
2482 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); | 2483 | spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); |
2483 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 2484 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
2484 | break; | 2485 | break; |
2485 | 2486 | ||
2486 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 2487 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 6bdcdf6d1cc0..e0799d924057 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
@@ -68,8 +68,10 @@ static struct usb_device_id ar9170_usb_ids[] = { | |||
68 | { USB_DEVICE(0x0cf3, 0x1002) }, | 68 | { USB_DEVICE(0x0cf3, 0x1002) }, |
69 | /* Cace Airpcap NX */ | 69 | /* Cace Airpcap NX */ |
70 | { USB_DEVICE(0xcace, 0x0300) }, | 70 | { USB_DEVICE(0xcace, 0x0300) }, |
71 | /* D-Link DWA 160A */ | 71 | /* D-Link DWA 160 A1 */ |
72 | { USB_DEVICE(0x07d1, 0x3c10) }, | 72 | { USB_DEVICE(0x07d1, 0x3c10) }, |
73 | /* D-Link DWA 160 A2 */ | ||
74 | { USB_DEVICE(0x07d1, 0x3a09) }, | ||
73 | /* Netgear WNDA3100 */ | 75 | /* Netgear WNDA3100 */ |
74 | { USB_DEVICE(0x0846, 0x9010) }, | 76 | { USB_DEVICE(0x0846, 0x9010) }, |
75 | /* Netgear WN111 v2 */ | 77 | /* Netgear WN111 v2 */ |
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 721ec5ee381d..bbfdcd5e7cb1 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c | |||
@@ -1399,7 +1399,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1399 | if (i_coffd == 0 || q_coffd == 0) | 1399 | if (i_coffd == 0 || q_coffd == 0) |
1400 | goto done; | 1400 | goto done; |
1401 | 1401 | ||
1402 | i_coff = ((-iq_corr) / i_coffd) & 0x3f; | 1402 | i_coff = ((-iq_corr) / i_coffd); |
1403 | 1403 | ||
1404 | /* Boundary check */ | 1404 | /* Boundary check */ |
1405 | if (i_coff > 31) | 1405 | if (i_coff > 31) |
@@ -1407,7 +1407,7 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, | |||
1407 | if (i_coff < -32) | 1407 | if (i_coff < -32) |
1408 | i_coff = -32; | 1408 | i_coff = -32; |
1409 | 1409 | ||
1410 | q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; | 1410 | q_coff = (((s32)i_pwr / q_coffd) - 128); |
1411 | 1411 | ||
1412 | /* Boundary check */ | 1412 | /* Boundary check */ |
1413 | if (q_coff > 15) | 1413 | if (q_coff > 15) |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index d9bcc3abb425..2a40fa2cd914 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -198,18 +198,8 @@ struct ath_txq { | |||
198 | struct list_head axq_q; | 198 | struct list_head axq_q; |
199 | spinlock_t axq_lock; | 199 | spinlock_t axq_lock; |
200 | u32 axq_depth; | 200 | u32 axq_depth; |
201 | u8 axq_aggr_depth; | ||
202 | bool stopped; | 201 | bool stopped; |
203 | bool axq_tx_inprogress; | 202 | bool axq_tx_inprogress; |
204 | struct ath_buf *axq_linkbuf; | ||
205 | |||
206 | /* first desc of the last descriptor that contains CTS */ | ||
207 | struct ath_desc *axq_lastdsWithCTS; | ||
208 | |||
209 | /* final desc of the gating desc that determines whether | ||
210 | lastdsWithCTS has been DMA'ed or not */ | ||
211 | struct ath_desc *axq_gatingds; | ||
212 | |||
213 | struct list_head axq_acq; | 203 | struct list_head axq_acq; |
214 | }; | 204 | }; |
215 | 205 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index 2f1e1612e2ad..4a13632e3e4d 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -231,26 +231,35 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | |||
231 | { | 231 | { |
232 | struct ath_hw *ah = common->ah; | 232 | struct ath_hw *ah = common->ah; |
233 | struct ieee80211_hdr *hdr; | 233 | struct ieee80211_hdr *hdr; |
234 | int hdrlen, padsize; | 234 | int hdrlen, padpos, padsize; |
235 | u8 keyix; | 235 | u8 keyix; |
236 | __le16 fc; | 236 | __le16 fc; |
237 | 237 | ||
238 | /* see if any padding is done by the hw and remove it */ | 238 | /* see if any padding is done by the hw and remove it */ |
239 | hdr = (struct ieee80211_hdr *) skb->data; | 239 | hdr = (struct ieee80211_hdr *) skb->data; |
240 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 240 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
241 | padpos = 24; | ||
241 | fc = hdr->frame_control; | 242 | fc = hdr->frame_control; |
243 | if ((fc & cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) == | ||
244 | cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) { | ||
245 | padpos += 6; /* ETH_ALEN */ | ||
246 | } | ||
247 | if ((fc & cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FCTL_FTYPE)) == | ||
248 | cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) { | ||
249 | padpos += 2; | ||
250 | } | ||
242 | 251 | ||
243 | /* The MAC header is padded to have 32-bit boundary if the | 252 | /* The MAC header is padded to have 32-bit boundary if the |
244 | * packet payload is non-zero. The general calculation for | 253 | * packet payload is non-zero. The general calculation for |
245 | * padsize would take into account odd header lengths: | 254 | * padsize would take into account odd header lengths: |
246 | * padsize = (4 - hdrlen % 4) % 4; However, since only | 255 | * padsize = (4 - padpos % 4) % 4; However, since only |
247 | * even-length headers are used, padding can only be 0 or 2 | 256 | * even-length headers are used, padding can only be 0 or 2 |
248 | * bytes and we can optimize this a bit. In addition, we must | 257 | * bytes and we can optimize this a bit. In addition, we must |
249 | * not try to remove padding from short control frames that do | 258 | * not try to remove padding from short control frames that do |
250 | * not have payload. */ | 259 | * not have payload. */ |
251 | padsize = hdrlen & 3; | 260 | padsize = padpos & 3; |
252 | if (padsize && hdrlen >= 24) { | 261 | if (padsize && skb->len>=padpos+padsize+FCS_LEN) { |
253 | memmove(skb->data + padsize, skb->data, hdrlen); | 262 | memmove(skb->data + padsize, skb->data, padpos); |
254 | skb_pull(skb, padsize); | 263 | skb_pull(skb, padsize); |
255 | } | 264 | } |
256 | 265 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 292e3d860c0e..4e1176029356 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -81,6 +81,7 @@ struct ath_buf { | |||
81 | u16 bf_flags; | 81 | u16 bf_flags; |
82 | struct ath_buf_state bf_state; | 82 | struct ath_buf_state bf_state; |
83 | dma_addr_t bf_dmacontext; | 83 | dma_addr_t bf_dmacontext; |
84 | struct ath_wiphy *aphy; | ||
84 | }; | 85 | }; |
85 | 86 | ||
86 | struct ath_atx_tid { | 87 | struct ath_atx_tid { |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 84f44269de47..06f1fcfb03e9 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -257,14 +257,17 @@ static const struct file_operations fops_interrupt = { | |||
257 | 257 | ||
258 | void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) | 258 | void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) |
259 | { | 259 | { |
260 | struct ath_tx_info_priv *tx_info_priv = NULL; | ||
261 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 260 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
262 | struct ieee80211_tx_rate *rates = tx_info->status.rates; | 261 | struct ieee80211_tx_rate *rates = tx_info->status.rates; |
263 | int final_ts_idx, idx; | 262 | int final_ts_idx = 0, idx, i; |
264 | struct ath_rc_stats *stats; | 263 | struct ath_rc_stats *stats; |
265 | 264 | ||
266 | tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 265 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
267 | final_ts_idx = tx_info_priv->tx.ts_rateindex; | 266 | if (!rates[i].count) |
267 | break; | ||
268 | |||
269 | final_ts_idx = i; | ||
270 | } | ||
268 | idx = rates[final_ts_idx].idx; | 271 | idx = rates[final_ts_idx].idx; |
269 | stats = &sc->debug.stats.rcstats[idx]; | 272 | stats = &sc->debug.stats.rcstats[idx]; |
270 | stats->success++; | 273 | stats->success++; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index b25eedf67e0b..53a7b980d8f6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -390,8 +390,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah) | |||
390 | ah->config.cck_trig_high = 200; | 390 | ah->config.cck_trig_high = 200; |
391 | ah->config.cck_trig_low = 100; | 391 | ah->config.cck_trig_low = 100; |
392 | ah->config.enable_ani = 1; | 392 | ah->config.enable_ani = 1; |
393 | ah->config.diversity_control = ATH9K_ANT_VARIABLE; | ||
394 | ah->config.antenna_switch_swap = 0; | ||
395 | 393 | ||
396 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { | 394 | for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { |
397 | ah->config.spurchans[i][0] = AR_NO_SPUR; | 395 | ah->config.spurchans[i][0] = AR_NO_SPUR; |
@@ -446,9 +444,6 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah) | |||
446 | ah->acktimeout = (u32) -1; | 444 | ah->acktimeout = (u32) -1; |
447 | ah->ctstimeout = (u32) -1; | 445 | ah->ctstimeout = (u32) -1; |
448 | ah->globaltxtimeout = (u32) -1; | 446 | ah->globaltxtimeout = (u32) -1; |
449 | |||
450 | ah->gbeacon_rate = 0; | ||
451 | |||
452 | ah->power_mode = ATH9K_PM_UNDEFINED; | 447 | ah->power_mode = ATH9K_PM_UNDEFINED; |
453 | } | 448 | } |
454 | 449 | ||
@@ -1151,7 +1146,7 @@ static void ath9k_hw_init_chain_masks(struct ath_hw *ah) | |||
1151 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 1146 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
1152 | AR_PHY_SWAP_ALT_CHAIN); | 1147 | AR_PHY_SWAP_ALT_CHAIN); |
1153 | case 0x3: | 1148 | case 0x3: |
1154 | if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) { | 1149 | if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) { |
1155 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); | 1150 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); |
1156 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); | 1151 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); |
1157 | break; | 1152 | break; |
@@ -2056,9 +2051,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
2056 | ah->ath9k_hw_spur_mitigate_freq(ah, chan); | 2051 | ah->ath9k_hw_spur_mitigate_freq(ah, chan); |
2057 | ah->eep_ops->set_board_values(ah, chan); | 2052 | ah->eep_ops->set_board_values(ah, chan); |
2058 | 2053 | ||
2059 | if (AR_SREV_5416(ah)) | ||
2060 | ath9k_hw_decrease_chain_power(ah, chan); | ||
2061 | |||
2062 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); | 2054 | REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr)); |
2063 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) | 2055 | REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(common->macaddr + 4) |
2064 | | macStaId1 | 2056 | | macStaId1 |
@@ -3518,51 +3510,6 @@ void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) | |||
3518 | } | 3510 | } |
3519 | EXPORT_SYMBOL(ath9k_hw_setantenna); | 3511 | EXPORT_SYMBOL(ath9k_hw_setantenna); |
3520 | 3512 | ||
3521 | bool ath9k_hw_setantennaswitch(struct ath_hw *ah, | ||
3522 | enum ath9k_ant_setting settings, | ||
3523 | struct ath9k_channel *chan, | ||
3524 | u8 *tx_chainmask, | ||
3525 | u8 *rx_chainmask, | ||
3526 | u8 *antenna_cfgd) | ||
3527 | { | ||
3528 | static u8 tx_chainmask_cfg, rx_chainmask_cfg; | ||
3529 | |||
3530 | if (AR_SREV_9280(ah)) { | ||
3531 | if (!tx_chainmask_cfg) { | ||
3532 | |||
3533 | tx_chainmask_cfg = *tx_chainmask; | ||
3534 | rx_chainmask_cfg = *rx_chainmask; | ||
3535 | } | ||
3536 | |||
3537 | switch (settings) { | ||
3538 | case ATH9K_ANT_FIXED_A: | ||
3539 | *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK; | ||
3540 | *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK; | ||
3541 | *antenna_cfgd = true; | ||
3542 | break; | ||
3543 | case ATH9K_ANT_FIXED_B: | ||
3544 | if (ah->caps.tx_chainmask > | ||
3545 | ATH9K_ANTENNA1_CHAINMASK) { | ||
3546 | *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK; | ||
3547 | } | ||
3548 | *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK; | ||
3549 | *antenna_cfgd = true; | ||
3550 | break; | ||
3551 | case ATH9K_ANT_VARIABLE: | ||
3552 | *tx_chainmask = tx_chainmask_cfg; | ||
3553 | *rx_chainmask = rx_chainmask_cfg; | ||
3554 | *antenna_cfgd = true; | ||
3555 | break; | ||
3556 | default: | ||
3557 | break; | ||
3558 | } | ||
3559 | } else { | ||
3560 | ah->config.diversity_control = settings; | ||
3561 | } | ||
3562 | |||
3563 | return true; | ||
3564 | } | ||
3565 | |||
3566 | /*********************/ | 3513 | /*********************/ |
3567 | /* General Operation */ | 3514 | /* General Operation */ |
3568 | /*********************/ | 3515 | /*********************/ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index abaa2f09a3bc..f8f5e997162c 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -148,21 +148,6 @@ enum wireless_mode { | |||
148 | ATH9K_MODE_MAX, | 148 | ATH9K_MODE_MAX, |
149 | }; | 149 | }; |
150 | 150 | ||
151 | /** | ||
152 | * ath9k_ant_setting - transmit antenna settings | ||
153 | * | ||
154 | * Configures the antenna setting to use for transmit. | ||
155 | * | ||
156 | * @ATH9K_ANT_VARIABLE: this means transmit on all active antennas | ||
157 | * @ATH9K_ANT_FIXED_A: this means transmit on the first antenna only | ||
158 | * @ATH9K_ANT_FIXED_B: this means transmit on the second antenna only | ||
159 | */ | ||
160 | enum ath9k_ant_setting { | ||
161 | ATH9K_ANT_VARIABLE = 0, | ||
162 | ATH9K_ANT_FIXED_A, | ||
163 | ATH9K_ANT_FIXED_B | ||
164 | }; | ||
165 | |||
166 | enum ath9k_hw_caps { | 151 | enum ath9k_hw_caps { |
167 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), | 152 | ATH9K_HW_CAP_MIC_AESCCM = BIT(0), |
168 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), | 153 | ATH9K_HW_CAP_MIC_CKIP = BIT(1), |
@@ -226,8 +211,6 @@ struct ath9k_ops_config { | |||
226 | u32 cck_trig_high; | 211 | u32 cck_trig_high; |
227 | u32 cck_trig_low; | 212 | u32 cck_trig_low; |
228 | u32 enable_ani; | 213 | u32 enable_ani; |
229 | enum ath9k_ant_setting diversity_control; | ||
230 | u16 antenna_switch_swap; | ||
231 | int serialize_regmode; | 214 | int serialize_regmode; |
232 | bool intr_mitigation; | 215 | bool intr_mitigation; |
233 | #define SPUR_DISABLE 0 | 216 | #define SPUR_DISABLE 0 |
@@ -572,7 +555,6 @@ struct ath_hw { | |||
572 | u32 acktimeout; | 555 | u32 acktimeout; |
573 | u32 ctstimeout; | 556 | u32 ctstimeout; |
574 | u32 globaltxtimeout; | 557 | u32 globaltxtimeout; |
575 | u8 gbeacon_rate; | ||
576 | 558 | ||
577 | /* ANI */ | 559 | /* ANI */ |
578 | u32 proc_phyerr; | 560 | u32 proc_phyerr; |
@@ -659,11 +641,6 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, | |||
659 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); | 641 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); |
660 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); | 642 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); |
661 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); | 643 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); |
662 | bool ath9k_hw_setantennaswitch(struct ath_hw *ah, | ||
663 | enum ath9k_ant_setting settings, | ||
664 | struct ath9k_channel *chan, | ||
665 | u8 *tx_chainmask, u8 *rx_chainmask, | ||
666 | u8 *antenna_cfgd); | ||
667 | 644 | ||
668 | /* General Operation */ | 645 | /* General Operation */ |
669 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 646 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 3c02b977a613..cbf5d2a1bb26 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -1893,6 +1893,8 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
1893 | BIT(NL80211_IFTYPE_ADHOC) | | 1893 | BIT(NL80211_IFTYPE_ADHOC) | |
1894 | BIT(NL80211_IFTYPE_MESH_POINT); | 1894 | BIT(NL80211_IFTYPE_MESH_POINT); |
1895 | 1895 | ||
1896 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
1897 | |||
1896 | hw->queues = 4; | 1898 | hw->queues = 4; |
1897 | hw->max_rates = 4; | 1899 | hw->max_rates = 4; |
1898 | hw->channel_change_time = 5000; | 1900 | hw->channel_change_time = 5000; |
@@ -2956,90 +2958,62 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2956 | struct ath_hw *ah = sc->sc_ah; | 2958 | struct ath_hw *ah = sc->sc_ah; |
2957 | struct ath_common *common = ath9k_hw_common(ah); | 2959 | struct ath_common *common = ath9k_hw_common(ah); |
2958 | struct ath_vif *avp = (void *)vif->drv_priv; | 2960 | struct ath_vif *avp = (void *)vif->drv_priv; |
2959 | u32 rfilt = 0; | 2961 | int error; |
2960 | int error, i; | ||
2961 | 2962 | ||
2962 | mutex_lock(&sc->mutex); | 2963 | mutex_lock(&sc->mutex); |
2963 | 2964 | ||
2964 | /* | 2965 | if (changed & BSS_CHANGED_BSSID) { |
2965 | * TODO: Need to decide which hw opmode to use for | 2966 | /* Set BSSID */ |
2966 | * multi-interface cases | 2967 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); |
2967 | * XXX: This belongs into add_interface! | 2968 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); |
2968 | */ | ||
2969 | if (vif->type == NL80211_IFTYPE_AP && | ||
2970 | ah->opmode != NL80211_IFTYPE_AP) { | ||
2971 | ah->opmode = NL80211_IFTYPE_STATION; | ||
2972 | ath9k_hw_setopmode(ah); | ||
2973 | memcpy(common->curbssid, common->macaddr, ETH_ALEN); | ||
2974 | common->curaid = 0; | 2969 | common->curaid = 0; |
2975 | ath9k_hw_write_associd(ah); | 2970 | ath9k_hw_write_associd(ah); |
2976 | /* Request full reset to get hw opmode changed properly */ | ||
2977 | sc->sc_flags |= SC_OP_FULL_RESET; | ||
2978 | } | ||
2979 | 2971 | ||
2980 | if ((changed & BSS_CHANGED_BSSID) && | 2972 | /* Set aggregation protection mode parameters */ |
2981 | !is_zero_ether_addr(bss_conf->bssid)) { | 2973 | sc->config.ath_aggr_prot = 0; |
2982 | switch (vif->type) { | ||
2983 | case NL80211_IFTYPE_STATION: | ||
2984 | case NL80211_IFTYPE_ADHOC: | ||
2985 | case NL80211_IFTYPE_MESH_POINT: | ||
2986 | /* Set BSSID */ | ||
2987 | memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); | ||
2988 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); | ||
2989 | common->curaid = 0; | ||
2990 | ath9k_hw_write_associd(ah); | ||
2991 | 2974 | ||
2992 | /* Set aggregation protection mode parameters */ | 2975 | /* Only legacy IBSS for now */ |
2993 | sc->config.ath_aggr_prot = 0; | 2976 | if (vif->type == NL80211_IFTYPE_ADHOC) |
2977 | ath_update_chainmask(sc, 0); | ||
2994 | 2978 | ||
2995 | ath_print(common, ATH_DBG_CONFIG, | 2979 | ath_print(common, ATH_DBG_CONFIG, |
2996 | "RX filter 0x%x bssid %pM aid 0x%x\n", | 2980 | "BSSID: %pM aid: 0x%x\n", |
2997 | rfilt, common->curbssid, common->curaid); | 2981 | common->curbssid, common->curaid); |
2998 | 2982 | ||
2999 | /* need to reconfigure the beacon */ | 2983 | /* need to reconfigure the beacon */ |
3000 | sc->sc_flags &= ~SC_OP_BEACONS ; | 2984 | sc->sc_flags &= ~SC_OP_BEACONS ; |
2985 | } | ||
3001 | 2986 | ||
3002 | break; | 2987 | /* Enable transmission of beacons (AP, IBSS, MESH) */ |
3003 | default: | 2988 | if ((changed & BSS_CHANGED_BEACON) || |
3004 | break; | 2989 | ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { |
3005 | } | 2990 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
2991 | error = ath_beacon_alloc(aphy, vif); | ||
2992 | if (!error) | ||
2993 | ath_beacon_config(sc, vif); | ||
3006 | } | 2994 | } |
3007 | 2995 | ||
3008 | if ((vif->type == NL80211_IFTYPE_ADHOC) || | 2996 | /* Disable transmission of beacons */ |
3009 | (vif->type == NL80211_IFTYPE_AP) || | 2997 | if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) |
3010 | (vif->type == NL80211_IFTYPE_MESH_POINT)) { | 2998 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); |
3011 | if ((changed & BSS_CHANGED_BEACON) || | ||
3012 | (changed & BSS_CHANGED_BEACON_ENABLED && | ||
3013 | bss_conf->enable_beacon)) { | ||
3014 | /* | ||
3015 | * Allocate and setup the beacon frame. | ||
3016 | * | ||
3017 | * Stop any previous beacon DMA. This may be | ||
3018 | * necessary, for example, when an ibss merge | ||
3019 | * causes reconfiguration; we may be called | ||
3020 | * with beacon transmission active. | ||
3021 | */ | ||
3022 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
3023 | 2999 | ||
3000 | if (changed & BSS_CHANGED_BEACON_INT) { | ||
3001 | sc->beacon_interval = bss_conf->beacon_int; | ||
3002 | /* | ||
3003 | * In case of AP mode, the HW TSF has to be reset | ||
3004 | * when the beacon interval changes. | ||
3005 | */ | ||
3006 | if (vif->type == NL80211_IFTYPE_AP) { | ||
3007 | sc->sc_flags |= SC_OP_TSF_RESET; | ||
3008 | ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); | ||
3024 | error = ath_beacon_alloc(aphy, vif); | 3009 | error = ath_beacon_alloc(aphy, vif); |
3025 | if (!error) | 3010 | if (!error) |
3026 | ath_beacon_config(sc, vif); | 3011 | ath_beacon_config(sc, vif); |
3012 | } else { | ||
3013 | ath_beacon_config(sc, vif); | ||
3027 | } | 3014 | } |
3028 | } | 3015 | } |
3029 | 3016 | ||
3030 | /* Check for WLAN_CAPABILITY_PRIVACY ? */ | ||
3031 | if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { | ||
3032 | for (i = 0; i < IEEE80211_WEP_NKID; i++) | ||
3033 | if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) | ||
3034 | ath9k_hw_keysetmac(sc->sc_ah, | ||
3035 | (u16)i, | ||
3036 | common->curbssid); | ||
3037 | } | ||
3038 | |||
3039 | /* Only legacy IBSS for now */ | ||
3040 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3041 | ath_update_chainmask(sc, 0); | ||
3042 | |||
3043 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { | 3017 | if (changed & BSS_CHANGED_ERP_PREAMBLE) { |
3044 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", | 3018 | ath_print(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", |
3045 | bss_conf->use_short_preamble); | 3019 | bss_conf->use_short_preamble); |
@@ -3065,18 +3039,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
3065 | ath9k_bss_assoc_info(sc, vif, bss_conf); | 3039 | ath9k_bss_assoc_info(sc, vif, bss_conf); |
3066 | } | 3040 | } |
3067 | 3041 | ||
3068 | /* | ||
3069 | * The HW TSF has to be reset when the beacon interval changes. | ||
3070 | * We set the flag here, and ath_beacon_config_ap() would take this | ||
3071 | * into account when it gets called through the subsequent | ||
3072 | * config_interface() call - with IFCC_BEACON in the changed field. | ||
3073 | */ | ||
3074 | |||
3075 | if (changed & BSS_CHANGED_BEACON_INT) { | ||
3076 | sc->sc_flags |= SC_OP_TSF_RESET; | ||
3077 | sc->beacon_interval = bss_conf->beacon_int; | ||
3078 | } | ||
3079 | |||
3080 | mutex_unlock(&sc->mutex); | 3042 | mutex_unlock(&sc->mutex); |
3081 | } | 3043 | } |
3082 | 3044 | ||
@@ -3118,6 +3080,7 @@ static void ath9k_reset_tsf(struct ieee80211_hw *hw) | |||
3118 | } | 3080 | } |
3119 | 3081 | ||
3120 | static int ath9k_ampdu_action(struct ieee80211_hw *hw, | 3082 | static int ath9k_ampdu_action(struct ieee80211_hw *hw, |
3083 | struct ieee80211_vif *vif, | ||
3121 | enum ieee80211_ampdu_mlme_action action, | 3084 | enum ieee80211_ampdu_mlme_action action, |
3122 | struct ieee80211_sta *sta, | 3085 | struct ieee80211_sta *sta, |
3123 | u16 tid, u16 *ssn) | 3086 | u16 tid, u16 *ssn) |
@@ -3135,11 +3098,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
3135 | break; | 3098 | break; |
3136 | case IEEE80211_AMPDU_TX_START: | 3099 | case IEEE80211_AMPDU_TX_START: |
3137 | ath_tx_aggr_start(sc, sta, tid, ssn); | 3100 | ath_tx_aggr_start(sc, sta, tid, ssn); |
3138 | ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 3101 | ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
3139 | break; | 3102 | break; |
3140 | case IEEE80211_AMPDU_TX_STOP: | 3103 | case IEEE80211_AMPDU_TX_STOP: |
3141 | ath_tx_aggr_stop(sc, sta, tid); | 3104 | ath_tx_aggr_stop(sc, sta, tid); |
3142 | ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); | 3105 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
3143 | break; | 3106 | break; |
3144 | case IEEE80211_AMPDU_TX_OPERATIONAL: | 3107 | case IEEE80211_AMPDU_TX_OPERATIONAL: |
3145 | ath_tx_aggr_resume(sc, sta, tid); | 3108 | ath_tx_aggr_resume(sc, sta, tid); |
diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c index 13ab4d7eb7aa..c3b59390fe38 100644 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ b/drivers/net/wireless/ath/ath9k/phy.c | |||
@@ -528,95 +528,6 @@ static void ath9k_hw_force_bias(struct ath_hw *ah, u16 synth_freq) | |||
528 | } | 528 | } |
529 | 529 | ||
530 | /** | 530 | /** |
531 | * ath9k_hw_decrease_chain_power() | ||
532 | * | ||
533 | * @ah: atheros hardware structure | ||
534 | * @chan: | ||
535 | * | ||
536 | * Only used on the AR5416 and AR5418 with the external AR2133/AR5133 radios. | ||
537 | * | ||
538 | * Sets a chain internal RF path to the lowest output power. Any | ||
539 | * further writes to bank6 after this setting will override these | ||
540 | * changes. Thus this function must be the last function in the | ||
541 | * sequence to modify bank 6. | ||
542 | * | ||
543 | * This function must be called after ar5416SetRfRegs() which is | ||
544 | * called from ath9k_hw_process_ini() due to swizzling of bank 6. | ||
545 | * Depends on ah->analogBank6Data being initialized by | ||
546 | * ath9k_hw_set_rf_regs() | ||
547 | * | ||
548 | * Additional additive reduction in power - | ||
549 | * change chain's switch table so chain's tx state is actually the rx | ||
550 | * state value. May produce different results in 2GHz/5GHz as well as | ||
551 | * board to board but in general should be a reduction. | ||
552 | * | ||
553 | * Activated by #ifdef ALTER_SWITCH. Not tried yet. If so, must be | ||
554 | * called after ah->eep_ops->set_board_values() due to RMW of | ||
555 | * PHY_SWITCH_CHAIN_0. | ||
556 | */ | ||
557 | void ath9k_hw_decrease_chain_power(struct ath_hw *ah, | ||
558 | struct ath9k_channel *chan) | ||
559 | { | ||
560 | int i, regWrites = 0; | ||
561 | u32 bank6SelMask; | ||
562 | u32 *bank6Temp = ah->bank6Temp; | ||
563 | |||
564 | BUG_ON(AR_SREV_9280_10_OR_LATER(ah)); | ||
565 | |||
566 | switch (ah->config.diversity_control) { | ||
567 | case ATH9K_ANT_FIXED_A: | ||
568 | bank6SelMask = | ||
569 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? | ||
570 | REDUCE_CHAIN_0 : /* swapped, reduce chain 0 */ | ||
571 | REDUCE_CHAIN_1; /* normal, select chain 1/2 to reduce */ | ||
572 | break; | ||
573 | case ATH9K_ANT_FIXED_B: | ||
574 | bank6SelMask = | ||
575 | (ah->config.antenna_switch_swap & ANTSWAP_AB) ? | ||
576 | REDUCE_CHAIN_1 : /* swapped, reduce chain 1/2 */ | ||
577 | REDUCE_CHAIN_0; /* normal, select chain 0 to reduce */ | ||
578 | break; | ||
579 | case ATH9K_ANT_VARIABLE: | ||
580 | return; /* do not change anything */ | ||
581 | break; | ||
582 | default: | ||
583 | return; /* do not change anything */ | ||
584 | break; | ||
585 | } | ||
586 | |||
587 | for (i = 0; i < ah->iniBank6.ia_rows; i++) | ||
588 | bank6Temp[i] = ah->analogBank6Data[i]; | ||
589 | |||
590 | /* Write Bank 5 to switch Bank 6 write to selected chain only */ | ||
591 | REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); | ||
592 | |||
593 | /* | ||
594 | * Modify Bank6 selected chain to use lowest amplification. | ||
595 | * Modifies the parameters to a value of 1. | ||
596 | * Depends on existing bank 6 values to be cached in | ||
597 | * ah->analogBank6Data | ||
598 | */ | ||
599 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); | ||
600 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); | ||
601 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); | ||
602 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); | ||
603 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); | ||
604 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); | ||
605 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); | ||
606 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); | ||
607 | ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); | ||
608 | |||
609 | REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); | ||
610 | |||
611 | REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); | ||
612 | #ifdef ALTER_SWITCH | ||
613 | REG_WRITE(ah, PHY_SWITCH_CHAIN_0, | ||
614 | (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) | ||
615 | | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); | ||
616 | #endif | ||
617 | } | ||
618 | |||
619 | /** | ||
620 | * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios | 531 | * ath9k_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios |
621 | * @ah: atheros hardware stucture | 532 | * @ah: atheros hardware stucture |
622 | * @chan: | 533 | * @chan: |
@@ -687,7 +598,6 @@ int ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) | |||
687 | } | 598 | } |
688 | 599 | ||
689 | ath9k_hw_force_bias(ah, freq); | 600 | ath9k_hw_force_bias(ah, freq); |
690 | ath9k_hw_decrease_chain_power(ah, chan); | ||
691 | 601 | ||
692 | reg32 = | 602 | reg32 = |
693 | (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | | 603 | (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | |
diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h index dc145a135dc7..31de27dc0c4a 100644 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ b/drivers/net/wireless/ath/ath9k/phy.h | |||
@@ -35,9 +35,6 @@ bool ath9k_hw_set_rf_regs(struct ath_hw *ah, | |||
35 | struct ath9k_channel *chan, | 35 | struct ath9k_channel *chan, |
36 | u16 modesIndex); | 36 | u16 modesIndex); |
37 | 37 | ||
38 | void ath9k_hw_decrease_chain_power(struct ath_hw *ah, | ||
39 | struct ath9k_channel *chan); | ||
40 | |||
41 | #define AR_PHY_BASE 0x9800 | 38 | #define AR_PHY_BASE 0x9800 |
42 | #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) | 39 | #define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) |
43 | 40 | ||
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index bb72b46567f9..1d96777b4cd2 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c | |||
@@ -859,12 +859,12 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
859 | static bool ath_rc_update_per(struct ath_softc *sc, | 859 | static bool ath_rc_update_per(struct ath_softc *sc, |
860 | const struct ath_rate_table *rate_table, | 860 | const struct ath_rate_table *rate_table, |
861 | struct ath_rate_priv *ath_rc_priv, | 861 | struct ath_rate_priv *ath_rc_priv, |
862 | struct ath_tx_info_priv *tx_info_priv, | 862 | struct ieee80211_tx_info *tx_info, |
863 | int tx_rate, int xretries, int retries, | 863 | int tx_rate, int xretries, int retries, |
864 | u32 now_msec) | 864 | u32 now_msec) |
865 | { | 865 | { |
866 | bool state_change = false; | 866 | bool state_change = false; |
867 | int count; | 867 | int count, n_bad_frames; |
868 | u8 last_per; | 868 | u8 last_per; |
869 | static u32 nretry_to_per_lookup[10] = { | 869 | static u32 nretry_to_per_lookup[10] = { |
870 | 100 * 0 / 1, | 870 | 100 * 0 / 1, |
@@ -880,6 +880,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
880 | }; | 880 | }; |
881 | 881 | ||
882 | last_per = ath_rc_priv->per[tx_rate]; | 882 | last_per = ath_rc_priv->per[tx_rate]; |
883 | n_bad_frames = tx_info->status.ampdu_len - tx_info->status.ampdu_ack_len; | ||
883 | 884 | ||
884 | if (xretries) { | 885 | if (xretries) { |
885 | if (xretries == 1) { | 886 | if (xretries == 1) { |
@@ -907,7 +908,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
907 | if (retries >= count) | 908 | if (retries >= count) |
908 | retries = count - 1; | 909 | retries = count - 1; |
909 | 910 | ||
910 | if (tx_info_priv->n_bad_frames) { | 911 | if (n_bad_frames) { |
911 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) | 912 | /* new_PER = 7/8*old_PER + 1/8*(currentPER) |
912 | * Assuming that n_frames is not 0. The current PER | 913 | * Assuming that n_frames is not 0. The current PER |
913 | * from the retries is 100 * retries / (retries+1), | 914 | * from the retries is 100 * retries / (retries+1), |
@@ -920,14 +921,14 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
920 | * the above PER. The expression below is a | 921 | * the above PER. The expression below is a |
921 | * simplified version of the sum of these two terms. | 922 | * simplified version of the sum of these two terms. |
922 | */ | 923 | */ |
923 | if (tx_info_priv->n_frames > 0) { | 924 | if (tx_info->status.ampdu_len > 0) { |
924 | int n_frames, n_bad_frames; | 925 | int n_frames, n_bad_tries; |
925 | u8 cur_per, new_per; | 926 | u8 cur_per, new_per; |
926 | 927 | ||
927 | n_bad_frames = retries * tx_info_priv->n_frames + | 928 | n_bad_tries = retries * tx_info->status.ampdu_len + |
928 | tx_info_priv->n_bad_frames; | 929 | n_bad_frames; |
929 | n_frames = tx_info_priv->n_frames * (retries + 1); | 930 | n_frames = tx_info->status.ampdu_len * (retries + 1); |
930 | cur_per = (100 * n_bad_frames / n_frames) >> 3; | 931 | cur_per = (100 * n_bad_tries / n_frames) >> 3; |
931 | new_per = (u8)(last_per - (last_per >> 3) + cur_per); | 932 | new_per = (u8)(last_per - (last_per >> 3) + cur_per); |
932 | ath_rc_priv->per[tx_rate] = new_per; | 933 | ath_rc_priv->per[tx_rate] = new_per; |
933 | } | 934 | } |
@@ -943,8 +944,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
943 | * this was a probe. Otherwise, ignore the probe. | 944 | * this was a probe. Otherwise, ignore the probe. |
944 | */ | 945 | */ |
945 | if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { | 946 | if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { |
946 | if (retries > 0 || 2 * tx_info_priv->n_bad_frames > | 947 | if (retries > 0 || 2 * n_bad_frames > tx_info->status.ampdu_len) { |
947 | tx_info_priv->n_frames) { | ||
948 | /* | 948 | /* |
949 | * Since we probed with just a single attempt, | 949 | * Since we probed with just a single attempt, |
950 | * any retries means the probe failed. Also, | 950 | * any retries means the probe failed. Also, |
@@ -1003,7 +1003,7 @@ static bool ath_rc_update_per(struct ath_softc *sc, | |||
1003 | 1003 | ||
1004 | static void ath_rc_update_ht(struct ath_softc *sc, | 1004 | static void ath_rc_update_ht(struct ath_softc *sc, |
1005 | struct ath_rate_priv *ath_rc_priv, | 1005 | struct ath_rate_priv *ath_rc_priv, |
1006 | struct ath_tx_info_priv *tx_info_priv, | 1006 | struct ieee80211_tx_info *tx_info, |
1007 | int tx_rate, int xretries, int retries) | 1007 | int tx_rate, int xretries, int retries) |
1008 | { | 1008 | { |
1009 | u32 now_msec = jiffies_to_msecs(jiffies); | 1009 | u32 now_msec = jiffies_to_msecs(jiffies); |
@@ -1020,7 +1020,7 @@ static void ath_rc_update_ht(struct ath_softc *sc, | |||
1020 | 1020 | ||
1021 | /* Update PER first */ | 1021 | /* Update PER first */ |
1022 | state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, | 1022 | state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, |
1023 | tx_info_priv, tx_rate, xretries, | 1023 | tx_info, tx_rate, xretries, |
1024 | retries, now_msec); | 1024 | retries, now_msec); |
1025 | 1025 | ||
1026 | /* | 1026 | /* |
@@ -1098,7 +1098,6 @@ static void ath_rc_tx_status(struct ath_softc *sc, | |||
1098 | struct ieee80211_tx_info *tx_info, | 1098 | struct ieee80211_tx_info *tx_info, |
1099 | int final_ts_idx, int xretries, int long_retry) | 1099 | int final_ts_idx, int xretries, int long_retry) |
1100 | { | 1100 | { |
1101 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
1102 | const struct ath_rate_table *rate_table; | 1101 | const struct ath_rate_table *rate_table; |
1103 | struct ieee80211_tx_rate *rates = tx_info->status.rates; | 1102 | struct ieee80211_tx_rate *rates = tx_info->status.rates; |
1104 | u8 flags; | 1103 | u8 flags; |
@@ -1124,9 +1123,8 @@ static void ath_rc_tx_status(struct ath_softc *sc, | |||
1124 | return; | 1123 | return; |
1125 | 1124 | ||
1126 | rix = ath_rc_get_rateindex(rate_table, &rates[i]); | 1125 | rix = ath_rc_get_rateindex(rate_table, &rates[i]); |
1127 | ath_rc_update_ht(sc, ath_rc_priv, | 1126 | ath_rc_update_ht(sc, ath_rc_priv, tx_info, |
1128 | tx_info_priv, rix, | 1127 | rix, xretries ? 1 : 2, |
1129 | xretries ? 1 : 2, | ||
1130 | rates[i].count); | 1128 | rates[i].count); |
1131 | } | 1129 | } |
1132 | } | 1130 | } |
@@ -1149,8 +1147,7 @@ static void ath_rc_tx_status(struct ath_softc *sc, | |||
1149 | return; | 1147 | return; |
1150 | 1148 | ||
1151 | rix = ath_rc_get_rateindex(rate_table, &rates[i]); | 1149 | rix = ath_rc_get_rateindex(rate_table, &rates[i]); |
1152 | ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, | 1150 | ath_rc_update_ht(sc, ath_rc_priv, tx_info, rix, xretries, long_retry); |
1153 | xretries, long_retry); | ||
1154 | } | 1151 | } |
1155 | 1152 | ||
1156 | static const | 1153 | static const |
@@ -1301,23 +1298,30 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1301 | { | 1298 | { |
1302 | struct ath_softc *sc = priv; | 1299 | struct ath_softc *sc = priv; |
1303 | struct ath_rate_priv *ath_rc_priv = priv_sta; | 1300 | struct ath_rate_priv *ath_rc_priv = priv_sta; |
1304 | struct ath_tx_info_priv *tx_info_priv = NULL; | ||
1305 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1301 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1306 | struct ieee80211_hdr *hdr; | 1302 | struct ieee80211_hdr *hdr; |
1307 | int final_ts_idx, tx_status = 0, is_underrun = 0; | 1303 | int final_ts_idx = 0, tx_status = 0, is_underrun = 0; |
1304 | int long_retry = 0; | ||
1308 | __le16 fc; | 1305 | __le16 fc; |
1306 | int i; | ||
1309 | 1307 | ||
1310 | hdr = (struct ieee80211_hdr *)skb->data; | 1308 | hdr = (struct ieee80211_hdr *)skb->data; |
1311 | fc = hdr->frame_control; | 1309 | fc = hdr->frame_control; |
1312 | tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 1310 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
1313 | final_ts_idx = tx_info_priv->tx.ts_rateindex; | 1311 | struct ieee80211_tx_rate *rate = &tx_info->status.rates[i]; |
1312 | if (!rate->count) | ||
1313 | break; | ||
1314 | |||
1315 | final_ts_idx = i; | ||
1316 | long_retry = rate->count - 1; | ||
1317 | } | ||
1314 | 1318 | ||
1315 | if (!priv_sta || !ieee80211_is_data(fc) || | 1319 | if (!priv_sta || !ieee80211_is_data(fc) || |
1316 | !tx_info_priv->update_rc) | 1320 | !(tx_info->pad[0] & ATH_TX_INFO_UPDATE_RC)) |
1317 | goto exit; | 1321 | return; |
1318 | 1322 | ||
1319 | if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT) | 1323 | if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) |
1320 | goto exit; | 1324 | return; |
1321 | 1325 | ||
1322 | /* | 1326 | /* |
1323 | * If underrun error is seen assume it as an excessive retry only | 1327 | * If underrun error is seen assume it as an excessive retry only |
@@ -1325,20 +1329,17 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1325 | * Adjust the long retry as if the frame was tried hw->max_rate_tries | 1329 | * Adjust the long retry as if the frame was tried hw->max_rate_tries |
1326 | * times. This affects how ratectrl updates PER for the failed rate. | 1330 | * times. This affects how ratectrl updates PER for the failed rate. |
1327 | */ | 1331 | */ |
1328 | if (tx_info_priv->tx.ts_flags & | 1332 | if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) && |
1329 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && | 1333 | (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) { |
1330 | ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) { | ||
1331 | tx_status = 1; | 1334 | tx_status = 1; |
1332 | is_underrun = 1; | 1335 | is_underrun = 1; |
1333 | } | 1336 | } |
1334 | 1337 | ||
1335 | if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || | 1338 | if (tx_info->pad[0] & ATH_TX_INFO_XRETRY) |
1336 | (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) | ||
1337 | tx_status = 1; | 1339 | tx_status = 1; |
1338 | 1340 | ||
1339 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, | 1341 | ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, |
1340 | (is_underrun) ? sc->hw->max_rate_tries : | 1342 | (is_underrun) ? sc->hw->max_rate_tries : long_retry); |
1341 | tx_info_priv->tx.ts_longretry); | ||
1342 | 1343 | ||
1343 | /* Check if aggregation has to be enabled for this tid */ | 1344 | /* Check if aggregation has to be enabled for this tid */ |
1344 | if (conf_is_ht(&sc->hw->conf) && | 1345 | if (conf_is_ht(&sc->hw->conf) && |
@@ -1352,13 +1353,11 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
1352 | an = (struct ath_node *)sta->drv_priv; | 1353 | an = (struct ath_node *)sta->drv_priv; |
1353 | 1354 | ||
1354 | if(ath_tx_aggr_check(sc, an, tid)) | 1355 | if(ath_tx_aggr_check(sc, an, tid)) |
1355 | ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); | 1356 | ieee80211_start_tx_ba_session(sta, tid); |
1356 | } | 1357 | } |
1357 | } | 1358 | } |
1358 | 1359 | ||
1359 | ath_debug_stat_rc(sc, skb); | 1360 | ath_debug_stat_rc(sc, skb); |
1360 | exit: | ||
1361 | kfree(tx_info_priv); | ||
1362 | } | 1361 | } |
1363 | 1362 | ||
1364 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, | 1363 | static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, |
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 94cb9f8d2446..51f85ecbe88d 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h | |||
@@ -167,24 +167,18 @@ struct ath_rate_priv { | |||
167 | struct ath_rate_softc *asc; | 167 | struct ath_rate_softc *asc; |
168 | }; | 168 | }; |
169 | 169 | ||
170 | #define ATH_TX_INFO_FRAME_TYPE_INTERNAL (1 << 0) | ||
171 | #define ATH_TX_INFO_FRAME_TYPE_PAUSE (1 << 1) | ||
172 | #define ATH_TX_INFO_UPDATE_RC (1 << 2) | ||
173 | #define ATH_TX_INFO_XRETRY (1 << 3) | ||
174 | #define ATH_TX_INFO_UNDERRUN (1 << 4) | ||
175 | |||
170 | enum ath9k_internal_frame_type { | 176 | enum ath9k_internal_frame_type { |
171 | ATH9K_NOT_INTERNAL, | 177 | ATH9K_NOT_INTERNAL, |
172 | ATH9K_INT_PAUSE, | 178 | ATH9K_INT_PAUSE, |
173 | ATH9K_INT_UNPAUSE | 179 | ATH9K_INT_UNPAUSE |
174 | }; | 180 | }; |
175 | 181 | ||
176 | struct ath_tx_info_priv { | ||
177 | struct ath_wiphy *aphy; | ||
178 | struct ath_tx_status tx; | ||
179 | int n_frames; | ||
180 | int n_bad_frames; | ||
181 | bool update_rc; | ||
182 | enum ath9k_internal_frame_type frame_type; | ||
183 | }; | ||
184 | |||
185 | #define ATH_TX_INFO_PRIV(tx_info) \ | ||
186 | ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0])) | ||
187 | |||
188 | void ath_rate_attach(struct ath_softc *sc); | 182 | void ath_rate_attach(struct ath_softc *sc); |
189 | u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); | 183 | u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); |
190 | int ath_rate_control_register(void); | 184 | int ath_rate_control_register(void); |
diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c index 0a36b572294c..cd26caaf44e7 100644 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ b/drivers/net/wireless/ath/ath9k/virtual.c | |||
@@ -338,13 +338,11 @@ void ath9k_wiphy_chan_work(struct work_struct *work) | |||
338 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 338 | void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) |
339 | { | 339 | { |
340 | struct ath_wiphy *aphy = hw->priv; | 340 | struct ath_wiphy *aphy = hw->priv; |
341 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
342 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 341 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
343 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
344 | 342 | ||
345 | if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE && | 343 | if ((tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_PAUSE) && |
346 | aphy->state == ATH_WIPHY_PAUSING) { | 344 | aphy->state == ATH_WIPHY_PAUSING) { |
347 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) { | 345 | if (!(tx_info->flags & IEEE80211_TX_STAT_ACK)) { |
348 | printk(KERN_DEBUG "ath9k: %s: no ACK for pause " | 346 | printk(KERN_DEBUG "ath9k: %s: no ACK for pause " |
349 | "frame\n", wiphy_name(hw->wiphy)); | 347 | "frame\n", wiphy_name(hw->wiphy)); |
350 | /* | 348 | /* |
@@ -363,9 +361,6 @@ void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
363 | } | 361 | } |
364 | } | 362 | } |
365 | 363 | ||
366 | kfree(tx_info_priv); | ||
367 | tx_info->rate_driver_data[0] = NULL; | ||
368 | |||
369 | dev_kfree_skb(skb); | 364 | dev_kfree_skb(skb); |
370 | } | 365 | } |
371 | 366 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 86b54ddd01cb..745d91995d78 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -251,6 +251,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) | |||
251 | 251 | ||
252 | ATH_TXBUF_RESET(tbf); | 252 | ATH_TXBUF_RESET(tbf); |
253 | 253 | ||
254 | tbf->aphy = bf->aphy; | ||
254 | tbf->bf_mpdu = bf->bf_mpdu; | 255 | tbf->bf_mpdu = bf->bf_mpdu; |
255 | tbf->bf_buf_addr = bf->bf_buf_addr; | 256 | tbf->bf_buf_addr = bf->bf_buf_addr; |
256 | *(tbf->bf_desc) = *(bf->bf_desc); | 257 | *(tbf->bf_desc) = *(bf->bf_desc); |
@@ -270,7 +271,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
270 | struct ieee80211_hw *hw; | 271 | struct ieee80211_hw *hw; |
271 | struct ieee80211_hdr *hdr; | 272 | struct ieee80211_hdr *hdr; |
272 | struct ieee80211_tx_info *tx_info; | 273 | struct ieee80211_tx_info *tx_info; |
273 | struct ath_tx_info_priv *tx_info_priv; | ||
274 | struct ath_atx_tid *tid = NULL; | 274 | struct ath_atx_tid *tid = NULL; |
275 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; | 275 | struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; |
276 | struct ath_desc *ds = bf_last->bf_desc; | 276 | struct ath_desc *ds = bf_last->bf_desc; |
@@ -284,8 +284,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
284 | hdr = (struct ieee80211_hdr *)skb->data; | 284 | hdr = (struct ieee80211_hdr *)skb->data; |
285 | 285 | ||
286 | tx_info = IEEE80211_SKB_CB(skb); | 286 | tx_info = IEEE80211_SKB_CB(skb); |
287 | tx_info_priv = (struct ath_tx_info_priv *) tx_info->rate_driver_data[0]; | 287 | hw = bf->aphy->hw; |
288 | hw = tx_info_priv->aphy->hw; | ||
289 | 288 | ||
290 | rcu_read_lock(); | 289 | rcu_read_lock(); |
291 | 290 | ||
@@ -464,7 +463,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
464 | struct sk_buff *skb; | 463 | struct sk_buff *skb; |
465 | struct ieee80211_tx_info *tx_info; | 464 | struct ieee80211_tx_info *tx_info; |
466 | struct ieee80211_tx_rate *rates; | 465 | struct ieee80211_tx_rate *rates; |
467 | struct ath_tx_info_priv *tx_info_priv; | ||
468 | u32 max_4ms_framelen, frmlen; | 466 | u32 max_4ms_framelen, frmlen; |
469 | u16 aggr_limit, legacy = 0; | 467 | u16 aggr_limit, legacy = 0; |
470 | int i; | 468 | int i; |
@@ -472,7 +470,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, | |||
472 | skb = bf->bf_mpdu; | 470 | skb = bf->bf_mpdu; |
473 | tx_info = IEEE80211_SKB_CB(skb); | 471 | tx_info = IEEE80211_SKB_CB(skb); |
474 | rates = tx_info->control.rates; | 472 | rates = tx_info->control.rates; |
475 | tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; | ||
476 | 473 | ||
477 | /* | 474 | /* |
478 | * Find the lowest frame length among the rate series that will have a | 475 | * Find the lowest frame length among the rate series that will have a |
@@ -702,7 +699,6 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
702 | /* anchor last desc of aggregate */ | 699 | /* anchor last desc of aggregate */ |
703 | ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); | 700 | ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); |
704 | 701 | ||
705 | txq->axq_aggr_depth++; | ||
706 | ath_tx_txqaddbuf(sc, txq, &bf_q); | 702 | ath_tx_txqaddbuf(sc, txq, &bf_q); |
707 | TX_STAT_INC(txq->axq_qnum, a_aggr); | 703 | TX_STAT_INC(txq->axq_qnum, a_aggr); |
708 | 704 | ||
@@ -878,8 +874,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
878 | INIT_LIST_HEAD(&txq->axq_acq); | 874 | INIT_LIST_HEAD(&txq->axq_acq); |
879 | spin_lock_init(&txq->axq_lock); | 875 | spin_lock_init(&txq->axq_lock); |
880 | txq->axq_depth = 0; | 876 | txq->axq_depth = 0; |
881 | txq->axq_aggr_depth = 0; | ||
882 | txq->axq_linkbuf = NULL; | ||
883 | txq->axq_tx_inprogress = false; | 877 | txq->axq_tx_inprogress = false; |
884 | sc->tx.txqsetup |= 1<<qnum; | 878 | sc->tx.txqsetup |= 1<<qnum; |
885 | } | 879 | } |
@@ -1014,7 +1008,6 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) | |||
1014 | 1008 | ||
1015 | if (list_empty(&txq->axq_q)) { | 1009 | if (list_empty(&txq->axq_q)) { |
1016 | txq->axq_link = NULL; | 1010 | txq->axq_link = NULL; |
1017 | txq->axq_linkbuf = NULL; | ||
1018 | spin_unlock_bh(&txq->axq_lock); | 1011 | spin_unlock_bh(&txq->axq_lock); |
1019 | break; | 1012 | break; |
1020 | } | 1013 | } |
@@ -1199,7 +1192,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, | |||
1199 | 1192 | ||
1200 | list_splice_tail_init(head, &txq->axq_q); | 1193 | list_splice_tail_init(head, &txq->axq_q); |
1201 | txq->axq_depth++; | 1194 | txq->axq_depth++; |
1202 | txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); | ||
1203 | 1195 | ||
1204 | ath_print(common, ATH_DBG_QUEUE, | 1196 | ath_print(common, ATH_DBG_QUEUE, |
1205 | "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); | 1197 | "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); |
@@ -1560,21 +1552,26 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1560 | struct ath_softc *sc = aphy->sc; | 1552 | struct ath_softc *sc = aphy->sc; |
1561 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1553 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1562 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1554 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1563 | struct ath_tx_info_priv *tx_info_priv; | ||
1564 | int hdrlen; | 1555 | int hdrlen; |
1565 | __le16 fc; | 1556 | __le16 fc; |
1566 | 1557 | ||
1567 | tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); | 1558 | tx_info->pad[0] = 0; |
1568 | if (unlikely(!tx_info_priv)) | 1559 | switch (txctl->frame_type) { |
1569 | return -ENOMEM; | 1560 | case ATH9K_NOT_INTERNAL: |
1570 | tx_info->rate_driver_data[0] = tx_info_priv; | 1561 | break; |
1571 | tx_info_priv->aphy = aphy; | 1562 | case ATH9K_INT_PAUSE: |
1572 | tx_info_priv->frame_type = txctl->frame_type; | 1563 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_PAUSE; |
1564 | /* fall through */ | ||
1565 | case ATH9K_INT_UNPAUSE: | ||
1566 | tx_info->pad[0] |= ATH_TX_INFO_FRAME_TYPE_INTERNAL; | ||
1567 | break; | ||
1568 | } | ||
1573 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1569 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1574 | fc = hdr->frame_control; | 1570 | fc = hdr->frame_control; |
1575 | 1571 | ||
1576 | ATH_TXBUF_RESET(bf); | 1572 | ATH_TXBUF_RESET(bf); |
1577 | 1573 | ||
1574 | bf->aphy = aphy; | ||
1578 | bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); | 1575 | bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); |
1579 | 1576 | ||
1580 | if (conf_is_ht(&hw->conf) && !is_pae(skb)) | 1577 | if (conf_is_ht(&hw->conf) && !is_pae(skb)) |
@@ -1599,8 +1596,6 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, | |||
1599 | skb->len, DMA_TO_DEVICE); | 1596 | skb->len, DMA_TO_DEVICE); |
1600 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { | 1597 | if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { |
1601 | bf->bf_mpdu = NULL; | 1598 | bf->bf_mpdu = NULL; |
1602 | kfree(tx_info_priv); | ||
1603 | tx_info->rate_driver_data[0] = NULL; | ||
1604 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, | 1599 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
1605 | "dma_mapping_error() on TX\n"); | 1600 | "dma_mapping_error() on TX\n"); |
1606 | return -ENOMEM; | 1601 | return -ENOMEM; |
@@ -1781,27 +1776,17 @@ exit: | |||
1781 | /*****************/ | 1776 | /*****************/ |
1782 | 1777 | ||
1783 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | 1778 | static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, |
1784 | int tx_flags) | 1779 | struct ath_wiphy *aphy, int tx_flags) |
1785 | { | 1780 | { |
1786 | struct ieee80211_hw *hw = sc->hw; | 1781 | struct ieee80211_hw *hw = sc->hw; |
1787 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1782 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1788 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | ||
1789 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1783 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1790 | int hdrlen, padsize; | 1784 | int hdrlen, padsize; |
1791 | int frame_type = ATH9K_NOT_INTERNAL; | ||
1792 | 1785 | ||
1793 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1786 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1794 | 1787 | ||
1795 | if (tx_info_priv) { | 1788 | if (aphy) |
1796 | hw = tx_info_priv->aphy->hw; | 1789 | hw = aphy->hw; |
1797 | frame_type = tx_info_priv->frame_type; | ||
1798 | } | ||
1799 | |||
1800 | if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || | ||
1801 | tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
1802 | kfree(tx_info_priv); | ||
1803 | tx_info->rate_driver_data[0] = NULL; | ||
1804 | } | ||
1805 | 1790 | ||
1806 | if (tx_flags & ATH_TX_BAR) | 1791 | if (tx_flags & ATH_TX_BAR) |
1807 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 1792 | tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
@@ -1833,10 +1818,10 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1833 | SC_OP_WAIT_FOR_TX_ACK)); | 1818 | SC_OP_WAIT_FOR_TX_ACK)); |
1834 | } | 1819 | } |
1835 | 1820 | ||
1836 | if (frame_type == ATH9K_NOT_INTERNAL) | 1821 | if (unlikely(tx_info->pad[0] & ATH_TX_INFO_FRAME_TYPE_INTERNAL)) |
1837 | ieee80211_tx_status(hw, skb); | ||
1838 | else | ||
1839 | ath9k_tx_status(hw, skb); | 1822 | ath9k_tx_status(hw, skb); |
1823 | else | ||
1824 | ieee80211_tx_status(hw, skb); | ||
1840 | } | 1825 | } |
1841 | 1826 | ||
1842 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | 1827 | static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, |
@@ -1859,7 +1844,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, | |||
1859 | } | 1844 | } |
1860 | 1845 | ||
1861 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); | 1846 | dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); |
1862 | ath_tx_complete(sc, skb, tx_flags); | 1847 | ath_tx_complete(sc, skb, bf->aphy, tx_flags); |
1863 | ath_debug_stat_tx(sc, txq, bf); | 1848 | ath_debug_stat_tx(sc, txq, bf); |
1864 | 1849 | ||
1865 | /* | 1850 | /* |
@@ -1907,8 +1892,7 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | |||
1907 | struct sk_buff *skb = bf->bf_mpdu; | 1892 | struct sk_buff *skb = bf->bf_mpdu; |
1908 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 1893 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
1909 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1894 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1910 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 1895 | struct ieee80211_hw *hw = bf->aphy->hw; |
1911 | struct ieee80211_hw *hw = tx_info_priv->aphy->hw; | ||
1912 | u8 i, tx_rateindex; | 1896 | u8 i, tx_rateindex; |
1913 | 1897 | ||
1914 | if (txok) | 1898 | if (txok) |
@@ -1917,17 +1901,22 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, | |||
1917 | tx_rateindex = ds->ds_txstat.ts_rateindex; | 1901 | tx_rateindex = ds->ds_txstat.ts_rateindex; |
1918 | WARN_ON(tx_rateindex >= hw->max_rates); | 1902 | WARN_ON(tx_rateindex >= hw->max_rates); |
1919 | 1903 | ||
1920 | tx_info_priv->update_rc = update_rc; | 1904 | if (update_rc) |
1905 | tx_info->pad[0] |= ATH_TX_INFO_UPDATE_RC; | ||
1921 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) | 1906 | if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) |
1922 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; | 1907 | tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; |
1923 | 1908 | ||
1924 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && | 1909 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && |
1925 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { | 1910 | (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { |
1926 | if (ieee80211_is_data(hdr->frame_control)) { | 1911 | if (ieee80211_is_data(hdr->frame_control)) { |
1927 | memcpy(&tx_info_priv->tx, &ds->ds_txstat, | 1912 | if (ds->ds_txstat.ts_flags & |
1928 | sizeof(tx_info_priv->tx)); | 1913 | (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN)) |
1929 | tx_info_priv->n_frames = bf->bf_nframes; | 1914 | tx_info->pad[0] |= ATH_TX_INFO_UNDERRUN; |
1930 | tx_info_priv->n_bad_frames = nbad; | 1915 | if ((ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) || |
1916 | (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)) | ||
1917 | tx_info->pad[0] |= ATH_TX_INFO_XRETRY; | ||
1918 | tx_info->status.ampdu_len = bf->bf_nframes; | ||
1919 | tx_info->status.ampdu_ack_len = bf->bf_nframes - nbad; | ||
1931 | } | 1920 | } |
1932 | } | 1921 | } |
1933 | 1922 | ||
@@ -1971,7 +1960,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
1971 | spin_lock_bh(&txq->axq_lock); | 1960 | spin_lock_bh(&txq->axq_lock); |
1972 | if (list_empty(&txq->axq_q)) { | 1961 | if (list_empty(&txq->axq_q)) { |
1973 | txq->axq_link = NULL; | 1962 | txq->axq_link = NULL; |
1974 | txq->axq_linkbuf = NULL; | ||
1975 | spin_unlock_bh(&txq->axq_lock); | 1963 | spin_unlock_bh(&txq->axq_lock); |
1976 | break; | 1964 | break; |
1977 | } | 1965 | } |
@@ -2005,10 +1993,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2005 | spin_unlock_bh(&txq->axq_lock); | 1993 | spin_unlock_bh(&txq->axq_lock); |
2006 | break; | 1994 | break; |
2007 | } | 1995 | } |
2008 | if (bf->bf_desc == txq->axq_lastdsWithCTS) | ||
2009 | txq->axq_lastdsWithCTS = NULL; | ||
2010 | if (ds == txq->axq_gatingds) | ||
2011 | txq->axq_gatingds = NULL; | ||
2012 | 1996 | ||
2013 | /* | 1997 | /* |
2014 | * Remove ath_buf's of the same transmit unit from txq, | 1998 | * Remove ath_buf's of the same transmit unit from txq, |
@@ -2022,9 +2006,6 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) | |||
2022 | &txq->axq_q, lastbf->list.prev); | 2006 | &txq->axq_q, lastbf->list.prev); |
2023 | 2007 | ||
2024 | txq->axq_depth--; | 2008 | txq->axq_depth--; |
2025 | if (bf_isaggr(bf)) | ||
2026 | txq->axq_aggr_depth--; | ||
2027 | |||
2028 | txok = (ds->ds_txstat.ts_status == 0); | 2009 | txok = (ds->ds_txstat.ts_status == 0); |
2029 | txq->axq_tx_inprogress = false; | 2010 | txq->axq_tx_inprogress = false; |
2030 | spin_unlock_bh(&txq->axq_lock); | 2011 | spin_unlock_bh(&txq->axq_lock); |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 077bcc142cde..039ac490465c 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -450,7 +450,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
450 | const struct ieee80211_regdomain *regd; | 450 | const struct ieee80211_regdomain *regd; |
451 | 451 | ||
452 | wiphy->reg_notifier = reg_notifier; | 452 | wiphy->reg_notifier = reg_notifier; |
453 | wiphy->strict_regulatory = true; | 453 | wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; |
454 | 454 | ||
455 | if (ath_is_world_regd(reg)) { | 455 | if (ath_is_world_regd(reg)) { |
456 | /* | 456 | /* |
@@ -458,8 +458,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, | |||
458 | * saved on the wiphy orig_* parameters | 458 | * saved on the wiphy orig_* parameters |
459 | */ | 459 | */ |
460 | regd = ath_world_regdomain(reg); | 460 | regd = ath_world_regdomain(reg); |
461 | wiphy->custom_regulatory = true; | 461 | wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
462 | wiphy->strict_regulatory = false; | ||
463 | } else { | 462 | } else { |
464 | /* | 463 | /* |
465 | * This gets applied in the case of the absense of CRDA, | 464 | * This gets applied in the case of the absense of CRDA, |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index b5cd7f57055b..027be275e035 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -383,44 +383,160 @@ static inline | |||
383 | } | 383 | } |
384 | } | 384 | } |
385 | 385 | ||
386 | /* Check if a DMA region fits the device constraints. | ||
387 | * Returns true, if the region is OK for usage with this device. */ | ||
388 | static inline bool b43_dma_address_ok(struct b43_dmaring *ring, | ||
389 | dma_addr_t addr, size_t size) | ||
390 | { | ||
391 | switch (ring->type) { | ||
392 | case B43_DMA_30BIT: | ||
393 | if ((u64)addr + size > (1ULL << 30)) | ||
394 | return 0; | ||
395 | break; | ||
396 | case B43_DMA_32BIT: | ||
397 | if ((u64)addr + size > (1ULL << 32)) | ||
398 | return 0; | ||
399 | break; | ||
400 | case B43_DMA_64BIT: | ||
401 | /* Currently we can't have addresses beyond | ||
402 | * 64bit in the kernel. */ | ||
403 | break; | ||
404 | } | ||
405 | return 1; | ||
406 | } | ||
407 | |||
408 | #define is_4k_aligned(addr) (((u64)(addr) & 0x0FFFull) == 0) | ||
409 | #define is_8k_aligned(addr) (((u64)(addr) & 0x1FFFull) == 0) | ||
410 | |||
411 | static void b43_unmap_and_free_ringmem(struct b43_dmaring *ring, void *base, | ||
412 | dma_addr_t dmaaddr, size_t size) | ||
413 | { | ||
414 | ssb_dma_unmap_single(ring->dev->dev, dmaaddr, size, DMA_TO_DEVICE); | ||
415 | free_pages((unsigned long)base, get_order(size)); | ||
416 | } | ||
417 | |||
418 | static void * __b43_get_and_map_ringmem(struct b43_dmaring *ring, | ||
419 | dma_addr_t *dmaaddr, size_t size, | ||
420 | gfp_t gfp_flags) | ||
421 | { | ||
422 | void *base; | ||
423 | |||
424 | base = (void *)__get_free_pages(gfp_flags, get_order(size)); | ||
425 | if (!base) | ||
426 | return NULL; | ||
427 | memset(base, 0, size); | ||
428 | *dmaaddr = ssb_dma_map_single(ring->dev->dev, base, size, | ||
429 | DMA_TO_DEVICE); | ||
430 | if (ssb_dma_mapping_error(ring->dev->dev, *dmaaddr)) { | ||
431 | free_pages((unsigned long)base, get_order(size)); | ||
432 | return NULL; | ||
433 | } | ||
434 | |||
435 | return base; | ||
436 | } | ||
437 | |||
438 | static void * b43_get_and_map_ringmem(struct b43_dmaring *ring, | ||
439 | dma_addr_t *dmaaddr, size_t size) | ||
440 | { | ||
441 | void *base; | ||
442 | |||
443 | base = __b43_get_and_map_ringmem(ring, dmaaddr, size, | ||
444 | GFP_KERNEL); | ||
445 | if (!base) { | ||
446 | b43err(ring->dev->wl, "Failed to allocate or map pages " | ||
447 | "for DMA ringmemory\n"); | ||
448 | return NULL; | ||
449 | } | ||
450 | if (!b43_dma_address_ok(ring, *dmaaddr, size)) { | ||
451 | /* The memory does not fit our device constraints. | ||
452 | * Retry with GFP_DMA set to get lower memory. */ | ||
453 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
454 | base = __b43_get_and_map_ringmem(ring, dmaaddr, size, | ||
455 | GFP_KERNEL | GFP_DMA); | ||
456 | if (!base) { | ||
457 | b43err(ring->dev->wl, "Failed to allocate or map pages " | ||
458 | "in the GFP_DMA region for DMA ringmemory\n"); | ||
459 | return NULL; | ||
460 | } | ||
461 | if (!b43_dma_address_ok(ring, *dmaaddr, size)) { | ||
462 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
463 | b43err(ring->dev->wl, "Failed to allocate DMA " | ||
464 | "ringmemory that fits device constraints\n"); | ||
465 | return NULL; | ||
466 | } | ||
467 | } | ||
468 | /* We expect the memory to be 4k aligned, at least. */ | ||
469 | if (B43_WARN_ON(!is_4k_aligned(*dmaaddr))) { | ||
470 | b43_unmap_and_free_ringmem(ring, base, *dmaaddr, size); | ||
471 | return NULL; | ||
472 | } | ||
473 | |||
474 | return base; | ||
475 | } | ||
476 | |||
386 | static int alloc_ringmemory(struct b43_dmaring *ring) | 477 | static int alloc_ringmemory(struct b43_dmaring *ring) |
387 | { | 478 | { |
388 | gfp_t flags = GFP_KERNEL; | 479 | unsigned int required; |
389 | 480 | void *base; | |
390 | /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K | 481 | dma_addr_t dmaaddr; |
391 | * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing | 482 | |
392 | * has shown that 4K is sufficient for the latter as long as the buffer | 483 | /* There are several requirements to the descriptor ring memory: |
393 | * does not cross an 8K boundary. | 484 | * - The memory region needs to fit the address constraints for the |
394 | * | 485 | * device (same as for frame buffers). |
395 | * For unknown reasons - possibly a hardware error - the BCM4311 rev | 486 | * - For 30/32bit DMA devices, the descriptor ring must be 4k aligned. |
396 | * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, | 487 | * - For 64bit DMA devices, the descriptor ring must be 8k aligned. |
397 | * which accounts for the GFP_DMA flag below. | ||
398 | * | ||
399 | * The flags here must match the flags in free_ringmemory below! | ||
400 | */ | 488 | */ |
489 | |||
401 | if (ring->type == B43_DMA_64BIT) | 490 | if (ring->type == B43_DMA_64BIT) |
402 | flags |= GFP_DMA; | 491 | required = ring->nr_slots * sizeof(struct b43_dmadesc64); |
403 | ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, | 492 | else |
404 | B43_DMA_RINGMEMSIZE, | 493 | required = ring->nr_slots * sizeof(struct b43_dmadesc32); |
405 | &(ring->dmabase), flags); | 494 | if (B43_WARN_ON(required > 0x1000)) |
406 | if (!ring->descbase) { | 495 | return -ENOMEM; |
407 | b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); | 496 | |
497 | ring->alloc_descsize = 0x1000; | ||
498 | base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); | ||
499 | if (!base) | ||
500 | return -ENOMEM; | ||
501 | ring->alloc_descbase = base; | ||
502 | ring->alloc_dmabase = dmaaddr; | ||
503 | |||
504 | if ((ring->type != B43_DMA_64BIT) || is_8k_aligned(dmaaddr)) { | ||
505 | /* We're on <=32bit DMA, or we already got 8k aligned memory. | ||
506 | * That's all we need, so we're fine. */ | ||
507 | ring->descbase = base; | ||
508 | ring->dmabase = dmaaddr; | ||
509 | return 0; | ||
510 | } | ||
511 | b43_unmap_and_free_ringmem(ring, base, dmaaddr, ring->alloc_descsize); | ||
512 | |||
513 | /* Ok, we failed at the 8k alignment requirement. | ||
514 | * Try to force-align the memory region now. */ | ||
515 | ring->alloc_descsize = 0x2000; | ||
516 | base = b43_get_and_map_ringmem(ring, &dmaaddr, ring->alloc_descsize); | ||
517 | if (!base) | ||
408 | return -ENOMEM; | 518 | return -ENOMEM; |
519 | ring->alloc_descbase = base; | ||
520 | ring->alloc_dmabase = dmaaddr; | ||
521 | |||
522 | if (is_8k_aligned(dmaaddr)) { | ||
523 | /* We're already 8k aligned. That Ok, too. */ | ||
524 | ring->descbase = base; | ||
525 | ring->dmabase = dmaaddr; | ||
526 | return 0; | ||
409 | } | 527 | } |
410 | memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); | 528 | /* Force-align it to 8k */ |
529 | ring->descbase = (void *)((u8 *)base + 0x1000); | ||
530 | ring->dmabase = dmaaddr + 0x1000; | ||
531 | B43_WARN_ON(!is_8k_aligned(ring->dmabase)); | ||
411 | 532 | ||
412 | return 0; | 533 | return 0; |
413 | } | 534 | } |
414 | 535 | ||
415 | static void free_ringmemory(struct b43_dmaring *ring) | 536 | static void free_ringmemory(struct b43_dmaring *ring) |
416 | { | 537 | { |
417 | gfp_t flags = GFP_KERNEL; | 538 | b43_unmap_and_free_ringmem(ring, ring->alloc_descbase, |
418 | 539 | ring->alloc_dmabase, ring->alloc_descsize); | |
419 | if (ring->type == B43_DMA_64BIT) | ||
420 | flags |= GFP_DMA; | ||
421 | |||
422 | ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, | ||
423 | ring->descbase, ring->dmabase, flags); | ||
424 | } | 540 | } |
425 | 541 | ||
426 | /* Reset the RX DMA channel */ | 542 | /* Reset the RX DMA channel */ |
@@ -530,29 +646,14 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring, | |||
530 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) | 646 | if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) |
531 | return 1; | 647 | return 1; |
532 | 648 | ||
533 | switch (ring->type) { | 649 | if (!b43_dma_address_ok(ring, addr, buffersize)) { |
534 | case B43_DMA_30BIT: | 650 | /* We can't support this address. Unmap it again. */ |
535 | if ((u64)addr + buffersize > (1ULL << 30)) | 651 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); |
536 | goto address_error; | 652 | return 1; |
537 | break; | ||
538 | case B43_DMA_32BIT: | ||
539 | if ((u64)addr + buffersize > (1ULL << 32)) | ||
540 | goto address_error; | ||
541 | break; | ||
542 | case B43_DMA_64BIT: | ||
543 | /* Currently we can't have addresses beyond | ||
544 | * 64bit in the kernel. */ | ||
545 | break; | ||
546 | } | 653 | } |
547 | 654 | ||
548 | /* The address is OK. */ | 655 | /* The address is OK. */ |
549 | return 0; | 656 | return 0; |
550 | |||
551 | address_error: | ||
552 | /* We can't support this address. Unmap it again. */ | ||
553 | unmap_descbuffer(ring, addr, buffersize, dma_to_device); | ||
554 | |||
555 | return 1; | ||
556 | } | 657 | } |
557 | 658 | ||
558 | static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) | 659 | static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) |
@@ -614,6 +715,9 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring, | |||
614 | meta->dmaaddr = dmaaddr; | 715 | meta->dmaaddr = dmaaddr; |
615 | ring->ops->fill_descriptor(ring, desc, dmaaddr, | 716 | ring->ops->fill_descriptor(ring, desc, dmaaddr, |
616 | ring->rx_buffersize, 0, 0, 0); | 717 | ring->rx_buffersize, 0, 0, 0); |
718 | ssb_dma_sync_single_for_device(ring->dev->dev, | ||
719 | ring->alloc_dmabase, | ||
720 | ring->alloc_descsize, DMA_TO_DEVICE); | ||
617 | 721 | ||
618 | return 0; | 722 | return 0; |
619 | } | 723 | } |
@@ -770,7 +874,7 @@ static void free_all_descbuffers(struct b43_dmaring *ring) | |||
770 | for (i = 0; i < ring->nr_slots; i++) { | 874 | for (i = 0; i < ring->nr_slots; i++) { |
771 | desc = ring->ops->idx2desc(ring, i, &meta); | 875 | desc = ring->ops->idx2desc(ring, i, &meta); |
772 | 876 | ||
773 | if (!meta->skb) { | 877 | if (!meta->skb || b43_dma_ptr_is_poisoned(meta->skb)) { |
774 | B43_WARN_ON(!ring->tx); | 878 | B43_WARN_ON(!ring->tx); |
775 | continue; | 879 | continue; |
776 | } | 880 | } |
@@ -822,7 +926,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
822 | enum b43_dmatype type) | 926 | enum b43_dmatype type) |
823 | { | 927 | { |
824 | struct b43_dmaring *ring; | 928 | struct b43_dmaring *ring; |
825 | int err; | 929 | int i, err; |
826 | dma_addr_t dma_test; | 930 | dma_addr_t dma_test; |
827 | 931 | ||
828 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); | 932 | ring = kzalloc(sizeof(*ring), GFP_KERNEL); |
@@ -837,6 +941,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, | |||
837 | GFP_KERNEL); | 941 | GFP_KERNEL); |
838 | if (!ring->meta) | 942 | if (!ring->meta) |
839 | goto err_kfree_ring; | 943 | goto err_kfree_ring; |
944 | for (i = 0; i < ring->nr_slots; i++) | ||
945 | ring->meta->skb = B43_DMA_PTR_POISON; | ||
840 | 946 | ||
841 | ring->type = type; | 947 | ring->type = type; |
842 | ring->dev = dev; | 948 | ring->dev = dev; |
@@ -1147,11 +1253,13 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) | |||
1147 | case 0x5000: | 1253 | case 0x5000: |
1148 | ring = dma->tx_ring_mcast; | 1254 | ring = dma->tx_ring_mcast; |
1149 | break; | 1255 | break; |
1150 | default: | ||
1151 | B43_WARN_ON(1); | ||
1152 | } | 1256 | } |
1153 | *slot = (cookie & 0x0FFF); | 1257 | *slot = (cookie & 0x0FFF); |
1154 | B43_WARN_ON(!(ring && *slot >= 0 && *slot < ring->nr_slots)); | 1258 | if (unlikely(!ring || *slot < 0 || *slot >= ring->nr_slots)) { |
1259 | b43dbg(dev->wl, "TX-status contains " | ||
1260 | "invalid cookie: 0x%04X\n", cookie); | ||
1261 | return NULL; | ||
1262 | } | ||
1155 | 1263 | ||
1156 | return ring; | 1264 | return ring; |
1157 | } | 1265 | } |
@@ -1246,6 +1354,9 @@ static int dma_tx_fragment(struct b43_dmaring *ring, | |||
1246 | } | 1354 | } |
1247 | /* Now transfer the whole frame. */ | 1355 | /* Now transfer the whole frame. */ |
1248 | wmb(); | 1356 | wmb(); |
1357 | ssb_dma_sync_single_for_device(ring->dev->dev, | ||
1358 | ring->alloc_dmabase, | ||
1359 | ring->alloc_descsize, DMA_TO_DEVICE); | ||
1249 | ops->poke_tx(ring, next_slot(ring, slot)); | 1360 | ops->poke_tx(ring, next_slot(ring, slot)); |
1250 | return 0; | 1361 | return 0; |
1251 | 1362 | ||
@@ -1387,19 +1498,40 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1387 | struct b43_dmaring *ring; | 1498 | struct b43_dmaring *ring; |
1388 | struct b43_dmadesc_generic *desc; | 1499 | struct b43_dmadesc_generic *desc; |
1389 | struct b43_dmadesc_meta *meta; | 1500 | struct b43_dmadesc_meta *meta; |
1390 | int slot; | 1501 | int slot, firstused; |
1391 | bool frame_succeed; | 1502 | bool frame_succeed; |
1392 | 1503 | ||
1393 | ring = parse_cookie(dev, status->cookie, &slot); | 1504 | ring = parse_cookie(dev, status->cookie, &slot); |
1394 | if (unlikely(!ring)) | 1505 | if (unlikely(!ring)) |
1395 | return; | 1506 | return; |
1396 | |||
1397 | B43_WARN_ON(!ring->tx); | 1507 | B43_WARN_ON(!ring->tx); |
1508 | |||
1509 | /* Sanity check: TX packets are processed in-order on one ring. | ||
1510 | * Check if the slot deduced from the cookie really is the first | ||
1511 | * used slot. */ | ||
1512 | firstused = ring->current_slot - ring->used_slots + 1; | ||
1513 | if (firstused < 0) | ||
1514 | firstused = ring->nr_slots + firstused; | ||
1515 | if (unlikely(slot != firstused)) { | ||
1516 | /* This possibly is a firmware bug and will result in | ||
1517 | * malfunction, memory leaks and/or stall of DMA functionality. */ | ||
1518 | b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. " | ||
1519 | "Expected %d, but got %d\n", | ||
1520 | ring->index, firstused, slot); | ||
1521 | return; | ||
1522 | } | ||
1523 | |||
1398 | ops = ring->ops; | 1524 | ops = ring->ops; |
1399 | while (1) { | 1525 | while (1) { |
1400 | B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); | 1526 | B43_WARN_ON(slot < 0 || slot >= ring->nr_slots); |
1401 | desc = ops->idx2desc(ring, slot, &meta); | 1527 | desc = ops->idx2desc(ring, slot, &meta); |
1402 | 1528 | ||
1529 | if (b43_dma_ptr_is_poisoned(meta->skb)) { | ||
1530 | b43dbg(dev->wl, "Poisoned TX slot %d (first=%d) " | ||
1531 | "on ring %d\n", | ||
1532 | slot, firstused, ring->index); | ||
1533 | break; | ||
1534 | } | ||
1403 | if (meta->skb) { | 1535 | if (meta->skb) { |
1404 | struct b43_private_tx_info *priv_info = | 1536 | struct b43_private_tx_info *priv_info = |
1405 | b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); | 1537 | b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); |
@@ -1415,7 +1547,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1415 | if (meta->is_last_fragment) { | 1547 | if (meta->is_last_fragment) { |
1416 | struct ieee80211_tx_info *info; | 1548 | struct ieee80211_tx_info *info; |
1417 | 1549 | ||
1418 | BUG_ON(!meta->skb); | 1550 | if (unlikely(!meta->skb)) { |
1551 | /* This is a scatter-gather fragment of a frame, so | ||
1552 | * the skb pointer must not be NULL. */ | ||
1553 | b43dbg(dev->wl, "TX status unexpected NULL skb " | ||
1554 | "at slot %d (first=%d) on ring %d\n", | ||
1555 | slot, firstused, ring->index); | ||
1556 | break; | ||
1557 | } | ||
1419 | 1558 | ||
1420 | info = IEEE80211_SKB_CB(meta->skb); | 1559 | info = IEEE80211_SKB_CB(meta->skb); |
1421 | 1560 | ||
@@ -1433,20 +1572,29 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, | |||
1433 | #endif /* DEBUG */ | 1572 | #endif /* DEBUG */ |
1434 | ieee80211_tx_status(dev->wl->hw, meta->skb); | 1573 | ieee80211_tx_status(dev->wl->hw, meta->skb); |
1435 | 1574 | ||
1436 | /* skb is freed by ieee80211_tx_status() */ | 1575 | /* skb will be freed by ieee80211_tx_status(). |
1437 | meta->skb = NULL; | 1576 | * Poison our pointer. */ |
1577 | meta->skb = B43_DMA_PTR_POISON; | ||
1438 | } else { | 1578 | } else { |
1439 | /* No need to call free_descriptor_buffer here, as | 1579 | /* No need to call free_descriptor_buffer here, as |
1440 | * this is only the txhdr, which is not allocated. | 1580 | * this is only the txhdr, which is not allocated. |
1441 | */ | 1581 | */ |
1442 | B43_WARN_ON(meta->skb); | 1582 | if (unlikely(meta->skb)) { |
1583 | b43dbg(dev->wl, "TX status unexpected non-NULL skb " | ||
1584 | "at slot %d (first=%d) on ring %d\n", | ||
1585 | slot, firstused, ring->index); | ||
1586 | break; | ||
1587 | } | ||
1443 | } | 1588 | } |
1444 | 1589 | ||
1445 | /* Everything unmapped and free'd. So it's not used anymore. */ | 1590 | /* Everything unmapped and free'd. So it's not used anymore. */ |
1446 | ring->used_slots--; | 1591 | ring->used_slots--; |
1447 | 1592 | ||
1448 | if (meta->is_last_fragment) | 1593 | if (meta->is_last_fragment) { |
1594 | /* This is the last scatter-gather | ||
1595 | * fragment of the frame. We are done. */ | ||
1449 | break; | 1596 | break; |
1597 | } | ||
1450 | slot = next_slot(ring, slot); | 1598 | slot = next_slot(ring, slot); |
1451 | } | 1599 | } |
1452 | if (ring->stopped) { | 1600 | if (ring->stopped) { |
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index f0b0838fb5ba..e607b392314c 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h | |||
@@ -1,7 +1,7 @@ | |||
1 | #ifndef B43_DMA_H_ | 1 | #ifndef B43_DMA_H_ |
2 | #define B43_DMA_H_ | 2 | #define B43_DMA_H_ |
3 | 3 | ||
4 | #include <linux/ieee80211.h> | 4 | #include <linux/err.h> |
5 | 5 | ||
6 | #include "b43.h" | 6 | #include "b43.h" |
7 | 7 | ||
@@ -157,7 +157,6 @@ struct b43_dmadesc_generic { | |||
157 | } __attribute__ ((__packed__)); | 157 | } __attribute__ ((__packed__)); |
158 | 158 | ||
159 | /* Misc DMA constants */ | 159 | /* Misc DMA constants */ |
160 | #define B43_DMA_RINGMEMSIZE PAGE_SIZE | ||
161 | #define B43_DMA0_RX_FRAMEOFFSET 30 | 160 | #define B43_DMA0_RX_FRAMEOFFSET 30 |
162 | 161 | ||
163 | /* DMA engine tuning knobs */ | 162 | /* DMA engine tuning knobs */ |
@@ -165,6 +164,10 @@ struct b43_dmadesc_generic { | |||
165 | #define B43_RXRING_SLOTS 64 | 164 | #define B43_RXRING_SLOTS 64 |
166 | #define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN | 165 | #define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN |
167 | 166 | ||
167 | /* Pointer poison */ | ||
168 | #define B43_DMA_PTR_POISON ((void *)ERR_PTR(-ENOMEM)) | ||
169 | #define b43_dma_ptr_is_poisoned(ptr) (unlikely((ptr) == B43_DMA_PTR_POISON)) | ||
170 | |||
168 | 171 | ||
169 | struct sk_buff; | 172 | struct sk_buff; |
170 | struct b43_private; | 173 | struct b43_private; |
@@ -243,6 +246,12 @@ struct b43_dmaring { | |||
243 | /* The QOS priority assigned to this ring. Only used for TX rings. | 246 | /* The QOS priority assigned to this ring. Only used for TX rings. |
244 | * This is the mac80211 "queue" value. */ | 247 | * This is the mac80211 "queue" value. */ |
245 | u8 queue_prio; | 248 | u8 queue_prio; |
249 | /* Pointers and size of the originally allocated and mapped memory | ||
250 | * region for the descriptor ring. */ | ||
251 | void *alloc_descbase; | ||
252 | dma_addr_t alloc_dmabase; | ||
253 | unsigned int alloc_descsize; | ||
254 | /* Pointer to our wireless device. */ | ||
246 | struct b43_wldev *dev; | 255 | struct b43_wldev *dev; |
247 | #ifdef CONFIG_B43_DEBUG | 256 | #ifdef CONFIG_B43_DEBUG |
248 | /* Maximum number of used slots. */ | 257 | /* Maximum number of used slots. */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index b7408370cf82..6c836c892e43 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -296,6 +296,33 @@ static const char *command_types[] = { | |||
296 | }; | 296 | }; |
297 | #endif | 297 | #endif |
298 | 298 | ||
299 | #define WEXT_USECHANNELS 1 | ||
300 | |||
301 | static const long ipw2100_frequencies[] = { | ||
302 | 2412, 2417, 2422, 2427, | ||
303 | 2432, 2437, 2442, 2447, | ||
304 | 2452, 2457, 2462, 2467, | ||
305 | 2472, 2484 | ||
306 | }; | ||
307 | |||
308 | #define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies) | ||
309 | |||
310 | static const long ipw2100_rates_11b[] = { | ||
311 | 1000000, | ||
312 | 2000000, | ||
313 | 5500000, | ||
314 | 11000000 | ||
315 | }; | ||
316 | |||
317 | static struct ieee80211_rate ipw2100_bg_rates[] = { | ||
318 | { .bitrate = 10 }, | ||
319 | { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
320 | { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
321 | { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
322 | }; | ||
323 | |||
324 | #define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b) | ||
325 | |||
299 | /* Pre-decl until we get the code solid and then we can clean it up */ | 326 | /* Pre-decl until we get the code solid and then we can clean it up */ |
300 | static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); | 327 | static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); |
301 | static void ipw2100_tx_send_data(struct ipw2100_priv *priv); | 328 | static void ipw2100_tx_send_data(struct ipw2100_priv *priv); |
@@ -1141,6 +1168,7 @@ static int rf_kill_active(struct ipw2100_priv *priv) | |||
1141 | int i; | 1168 | int i; |
1142 | 1169 | ||
1143 | if (!(priv->hw_features & HW_FEATURE_RFKILL)) { | 1170 | if (!(priv->hw_features & HW_FEATURE_RFKILL)) { |
1171 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false); | ||
1144 | priv->status &= ~STATUS_RF_KILL_HW; | 1172 | priv->status &= ~STATUS_RF_KILL_HW; |
1145 | return 0; | 1173 | return 0; |
1146 | } | 1174 | } |
@@ -1151,10 +1179,13 @@ static int rf_kill_active(struct ipw2100_priv *priv) | |||
1151 | value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1); | 1179 | value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1); |
1152 | } | 1180 | } |
1153 | 1181 | ||
1154 | if (value == 0) | 1182 | if (value == 0) { |
1183 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true); | ||
1155 | priv->status |= STATUS_RF_KILL_HW; | 1184 | priv->status |= STATUS_RF_KILL_HW; |
1156 | else | 1185 | } else { |
1186 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false); | ||
1157 | priv->status &= ~STATUS_RF_KILL_HW; | 1187 | priv->status &= ~STATUS_RF_KILL_HW; |
1188 | } | ||
1158 | 1189 | ||
1159 | return (value == 0); | 1190 | return (value == 0); |
1160 | } | 1191 | } |
@@ -1814,13 +1845,6 @@ static int ipw2100_up(struct ipw2100_priv *priv, int deferred) | |||
1814 | return rc; | 1845 | return rc; |
1815 | } | 1846 | } |
1816 | 1847 | ||
1817 | /* Called by register_netdev() */ | ||
1818 | static int ipw2100_net_init(struct net_device *dev) | ||
1819 | { | ||
1820 | struct ipw2100_priv *priv = libipw_priv(dev); | ||
1821 | return ipw2100_up(priv, 1); | ||
1822 | } | ||
1823 | |||
1824 | static void ipw2100_down(struct ipw2100_priv *priv) | 1848 | static void ipw2100_down(struct ipw2100_priv *priv) |
1825 | { | 1849 | { |
1826 | unsigned long flags; | 1850 | unsigned long flags; |
@@ -1875,6 +1899,64 @@ static void ipw2100_down(struct ipw2100_priv *priv) | |||
1875 | netif_stop_queue(priv->net_dev); | 1899 | netif_stop_queue(priv->net_dev); |
1876 | } | 1900 | } |
1877 | 1901 | ||
1902 | /* Called by register_netdev() */ | ||
1903 | static int ipw2100_net_init(struct net_device *dev) | ||
1904 | { | ||
1905 | struct ipw2100_priv *priv = libipw_priv(dev); | ||
1906 | const struct libipw_geo *geo = libipw_get_geo(priv->ieee); | ||
1907 | struct wireless_dev *wdev = &priv->ieee->wdev; | ||
1908 | int ret; | ||
1909 | int i; | ||
1910 | |||
1911 | ret = ipw2100_up(priv, 1); | ||
1912 | if (ret) | ||
1913 | return ret; | ||
1914 | |||
1915 | memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); | ||
1916 | |||
1917 | /* fill-out priv->ieee->bg_band */ | ||
1918 | if (geo->bg_channels) { | ||
1919 | struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band; | ||
1920 | |||
1921 | bg_band->band = IEEE80211_BAND_2GHZ; | ||
1922 | bg_band->n_channels = geo->bg_channels; | ||
1923 | bg_band->channels = | ||
1924 | kzalloc(geo->bg_channels * | ||
1925 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
1926 | /* translate geo->bg to bg_band.channels */ | ||
1927 | for (i = 0; i < geo->bg_channels; i++) { | ||
1928 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; | ||
1929 | bg_band->channels[i].center_freq = geo->bg[i].freq; | ||
1930 | bg_band->channels[i].hw_value = geo->bg[i].channel; | ||
1931 | bg_band->channels[i].max_power = geo->bg[i].max_power; | ||
1932 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) | ||
1933 | bg_band->channels[i].flags |= | ||
1934 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
1935 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) | ||
1936 | bg_band->channels[i].flags |= | ||
1937 | IEEE80211_CHAN_NO_IBSS; | ||
1938 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) | ||
1939 | bg_band->channels[i].flags |= | ||
1940 | IEEE80211_CHAN_RADAR; | ||
1941 | /* No equivalent for LIBIPW_CH_80211H_RULES, | ||
1942 | LIBIPW_CH_UNIFORM_SPREADING, or | ||
1943 | LIBIPW_CH_B_ONLY... */ | ||
1944 | } | ||
1945 | /* point at bitrate info */ | ||
1946 | bg_band->bitrates = ipw2100_bg_rates; | ||
1947 | bg_band->n_bitrates = RATE_COUNT; | ||
1948 | |||
1949 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; | ||
1950 | } | ||
1951 | |||
1952 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); | ||
1953 | if (wiphy_register(wdev->wiphy)) { | ||
1954 | ipw2100_down(priv); | ||
1955 | return -EIO; | ||
1956 | } | ||
1957 | return 0; | ||
1958 | } | ||
1959 | |||
1878 | static void ipw2100_reset_adapter(struct work_struct *work) | 1960 | static void ipw2100_reset_adapter(struct work_struct *work) |
1879 | { | 1961 | { |
1880 | struct ipw2100_priv *priv = | 1962 | struct ipw2100_priv *priv = |
@@ -2090,6 +2172,7 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) | |||
2090 | priv->net_dev->name); | 2172 | priv->net_dev->name); |
2091 | 2173 | ||
2092 | /* RF_KILL is now enabled (else we wouldn't be here) */ | 2174 | /* RF_KILL is now enabled (else we wouldn't be here) */ |
2175 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true); | ||
2093 | priv->status |= STATUS_RF_KILL_HW; | 2176 | priv->status |= STATUS_RF_KILL_HW; |
2094 | 2177 | ||
2095 | /* Make sure the RF Kill check timer is running */ | 2178 | /* Make sure the RF Kill check timer is running */ |
@@ -6029,7 +6112,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6029 | struct ipw2100_priv *priv; | 6112 | struct ipw2100_priv *priv; |
6030 | struct net_device *dev; | 6113 | struct net_device *dev; |
6031 | 6114 | ||
6032 | dev = alloc_ieee80211(sizeof(struct ipw2100_priv)); | 6115 | dev = alloc_ieee80211(sizeof(struct ipw2100_priv), 0); |
6033 | if (!dev) | 6116 | if (!dev) |
6034 | return NULL; | 6117 | return NULL; |
6035 | priv = libipw_priv(dev); | 6118 | priv = libipw_priv(dev); |
@@ -6342,7 +6425,7 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev, | |||
6342 | sysfs_remove_group(&pci_dev->dev.kobj, | 6425 | sysfs_remove_group(&pci_dev->dev.kobj, |
6343 | &ipw2100_attribute_group); | 6426 | &ipw2100_attribute_group); |
6344 | 6427 | ||
6345 | free_ieee80211(dev); | 6428 | free_ieee80211(dev, 0); |
6346 | pci_set_drvdata(pci_dev, NULL); | 6429 | pci_set_drvdata(pci_dev, NULL); |
6347 | } | 6430 | } |
6348 | 6431 | ||
@@ -6400,7 +6483,10 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) | |||
6400 | if (dev->base_addr) | 6483 | if (dev->base_addr) |
6401 | iounmap((void __iomem *)dev->base_addr); | 6484 | iounmap((void __iomem *)dev->base_addr); |
6402 | 6485 | ||
6403 | free_ieee80211(dev); | 6486 | /* wiphy_unregister needs to be here, before free_ieee80211 */ |
6487 | wiphy_unregister(priv->ieee->wdev.wiphy); | ||
6488 | kfree(priv->ieee->bg_band.channels); | ||
6489 | free_ieee80211(dev, 0); | ||
6404 | } | 6490 | } |
6405 | 6491 | ||
6406 | pci_release_regions(pci_dev); | 6492 | pci_release_regions(pci_dev); |
@@ -6601,26 +6687,6 @@ static void __exit ipw2100_exit(void) | |||
6601 | module_init(ipw2100_init); | 6687 | module_init(ipw2100_init); |
6602 | module_exit(ipw2100_exit); | 6688 | module_exit(ipw2100_exit); |
6603 | 6689 | ||
6604 | #define WEXT_USECHANNELS 1 | ||
6605 | |||
6606 | static const long ipw2100_frequencies[] = { | ||
6607 | 2412, 2417, 2422, 2427, | ||
6608 | 2432, 2437, 2442, 2447, | ||
6609 | 2452, 2457, 2462, 2467, | ||
6610 | 2472, 2484 | ||
6611 | }; | ||
6612 | |||
6613 | #define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies) | ||
6614 | |||
6615 | static const long ipw2100_rates_11b[] = { | ||
6616 | 1000000, | ||
6617 | 2000000, | ||
6618 | 5500000, | ||
6619 | 11000000 | ||
6620 | }; | ||
6621 | |||
6622 | #define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b) | ||
6623 | |||
6624 | static int ipw2100_wx_get_name(struct net_device *dev, | 6690 | static int ipw2100_wx_get_name(struct net_device *dev, |
6625 | struct iw_request_info *info, | 6691 | struct iw_request_info *info, |
6626 | union iwreq_data *wrqu, char *extra) | 6692 | union iwreq_data *wrqu, char *extra) |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 9fe0e8078a88..c28984ae46ff 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -109,6 +109,25 @@ static int antenna = CFG_SYS_ANTENNA_BOTH; | |||
109 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ | 109 | static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ |
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | static struct ieee80211_rate ipw2200_rates[] = { | ||
113 | { .bitrate = 10 }, | ||
114 | { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
115 | { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
116 | { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, | ||
117 | { .bitrate = 60 }, | ||
118 | { .bitrate = 90 }, | ||
119 | { .bitrate = 120 }, | ||
120 | { .bitrate = 180 }, | ||
121 | { .bitrate = 240 }, | ||
122 | { .bitrate = 360 }, | ||
123 | { .bitrate = 480 }, | ||
124 | { .bitrate = 540 } | ||
125 | }; | ||
126 | |||
127 | #define ipw2200_a_rates (ipw2200_rates + 4) | ||
128 | #define ipw2200_num_a_rates 8 | ||
129 | #define ipw2200_bg_rates (ipw2200_rates + 0) | ||
130 | #define ipw2200_num_bg_rates 12 | ||
112 | 131 | ||
113 | #ifdef CONFIG_IPW2200_QOS | 132 | #ifdef CONFIG_IPW2200_QOS |
114 | static int qos_enable = 0; | 133 | static int qos_enable = 0; |
@@ -1739,10 +1758,13 @@ static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, | |||
1739 | 1758 | ||
1740 | static int rf_kill_active(struct ipw_priv *priv) | 1759 | static int rf_kill_active(struct ipw_priv *priv) |
1741 | { | 1760 | { |
1742 | if (0 == (ipw_read32(priv, 0x30) & 0x10000)) | 1761 | if (0 == (ipw_read32(priv, 0x30) & 0x10000)) { |
1743 | priv->status |= STATUS_RF_KILL_HW; | 1762 | priv->status |= STATUS_RF_KILL_HW; |
1744 | else | 1763 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true); |
1764 | } else { | ||
1745 | priv->status &= ~STATUS_RF_KILL_HW; | 1765 | priv->status &= ~STATUS_RF_KILL_HW; |
1766 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, false); | ||
1767 | } | ||
1746 | 1768 | ||
1747 | return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0; | 1769 | return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0; |
1748 | } | 1770 | } |
@@ -2025,6 +2047,7 @@ static void ipw_irq_tasklet(struct ipw_priv *priv) | |||
2025 | if (inta & IPW_INTA_BIT_RF_KILL_DONE) { | 2047 | if (inta & IPW_INTA_BIT_RF_KILL_DONE) { |
2026 | IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); | 2048 | IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); |
2027 | priv->status |= STATUS_RF_KILL_HW; | 2049 | priv->status |= STATUS_RF_KILL_HW; |
2050 | wiphy_rfkill_set_hw_state(priv->ieee->wdev.wiphy, true); | ||
2028 | wake_up_interruptible(&priv->wait_command_queue); | 2051 | wake_up_interruptible(&priv->wait_command_queue); |
2029 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); | 2052 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); |
2030 | cancel_delayed_work(&priv->request_scan); | 2053 | cancel_delayed_work(&priv->request_scan); |
@@ -8660,24 +8683,6 @@ static int ipw_sw_reset(struct ipw_priv *priv, int option) | |||
8660 | * | 8683 | * |
8661 | */ | 8684 | */ |
8662 | 8685 | ||
8663 | static int ipw_wx_get_name(struct net_device *dev, | ||
8664 | struct iw_request_info *info, | ||
8665 | union iwreq_data *wrqu, char *extra) | ||
8666 | { | ||
8667 | struct ipw_priv *priv = libipw_priv(dev); | ||
8668 | mutex_lock(&priv->mutex); | ||
8669 | if (priv->status & STATUS_RF_KILL_MASK) | ||
8670 | strcpy(wrqu->name, "radio off"); | ||
8671 | else if (!(priv->status & STATUS_ASSOCIATED)) | ||
8672 | strcpy(wrqu->name, "unassociated"); | ||
8673 | else | ||
8674 | snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", | ||
8675 | ipw_modes[priv->assoc_request.ieee_mode]); | ||
8676 | IPW_DEBUG_WX("Name: %s\n", wrqu->name); | ||
8677 | mutex_unlock(&priv->mutex); | ||
8678 | return 0; | ||
8679 | } | ||
8680 | |||
8681 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) | 8686 | static int ipw_set_channel(struct ipw_priv *priv, u8 channel) |
8682 | { | 8687 | { |
8683 | if (channel == 0) { | 8688 | if (channel == 0) { |
@@ -9977,7 +9982,7 @@ static int ipw_wx_sw_reset(struct net_device *dev, | |||
9977 | /* Rebase the WE IOCTLs to zero for the handler array */ | 9982 | /* Rebase the WE IOCTLs to zero for the handler array */ |
9978 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] | 9983 | #define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] |
9979 | static iw_handler ipw_wx_handlers[] = { | 9984 | static iw_handler ipw_wx_handlers[] = { |
9980 | IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name, | 9985 | IW_IOCTL(SIOCGIWNAME) = (iw_handler) cfg80211_wext_giwname, |
9981 | IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, | 9986 | IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, |
9982 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, | 9987 | IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, |
9983 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, | 9988 | IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, |
@@ -11422,16 +11427,100 @@ static void ipw_bg_down(struct work_struct *work) | |||
11422 | /* Called by register_netdev() */ | 11427 | /* Called by register_netdev() */ |
11423 | static int ipw_net_init(struct net_device *dev) | 11428 | static int ipw_net_init(struct net_device *dev) |
11424 | { | 11429 | { |
11430 | int i, rc = 0; | ||
11425 | struct ipw_priv *priv = libipw_priv(dev); | 11431 | struct ipw_priv *priv = libipw_priv(dev); |
11432 | const struct libipw_geo *geo = libipw_get_geo(priv->ieee); | ||
11433 | struct wireless_dev *wdev = &priv->ieee->wdev; | ||
11426 | mutex_lock(&priv->mutex); | 11434 | mutex_lock(&priv->mutex); |
11427 | 11435 | ||
11428 | if (ipw_up(priv)) { | 11436 | if (ipw_up(priv)) { |
11429 | mutex_unlock(&priv->mutex); | 11437 | rc = -EIO; |
11430 | return -EIO; | 11438 | goto out; |
11439 | } | ||
11440 | |||
11441 | memcpy(wdev->wiphy->perm_addr, priv->mac_addr, ETH_ALEN); | ||
11442 | |||
11443 | /* fill-out priv->ieee->bg_band */ | ||
11444 | if (geo->bg_channels) { | ||
11445 | struct ieee80211_supported_band *bg_band = &priv->ieee->bg_band; | ||
11446 | |||
11447 | bg_band->band = IEEE80211_BAND_2GHZ; | ||
11448 | bg_band->n_channels = geo->bg_channels; | ||
11449 | bg_band->channels = | ||
11450 | kzalloc(geo->bg_channels * | ||
11451 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
11452 | /* translate geo->bg to bg_band.channels */ | ||
11453 | for (i = 0; i < geo->bg_channels; i++) { | ||
11454 | bg_band->channels[i].band = IEEE80211_BAND_2GHZ; | ||
11455 | bg_band->channels[i].center_freq = geo->bg[i].freq; | ||
11456 | bg_band->channels[i].hw_value = geo->bg[i].channel; | ||
11457 | bg_band->channels[i].max_power = geo->bg[i].max_power; | ||
11458 | if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) | ||
11459 | bg_band->channels[i].flags |= | ||
11460 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
11461 | if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS) | ||
11462 | bg_band->channels[i].flags |= | ||
11463 | IEEE80211_CHAN_NO_IBSS; | ||
11464 | if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT) | ||
11465 | bg_band->channels[i].flags |= | ||
11466 | IEEE80211_CHAN_RADAR; | ||
11467 | /* No equivalent for LIBIPW_CH_80211H_RULES, | ||
11468 | LIBIPW_CH_UNIFORM_SPREADING, or | ||
11469 | LIBIPW_CH_B_ONLY... */ | ||
11470 | } | ||
11471 | /* point at bitrate info */ | ||
11472 | bg_band->bitrates = ipw2200_bg_rates; | ||
11473 | bg_band->n_bitrates = ipw2200_num_bg_rates; | ||
11474 | |||
11475 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; | ||
11431 | } | 11476 | } |
11432 | 11477 | ||
11478 | /* fill-out priv->ieee->a_band */ | ||
11479 | if (geo->a_channels) { | ||
11480 | struct ieee80211_supported_band *a_band = &priv->ieee->a_band; | ||
11481 | |||
11482 | a_band->band = IEEE80211_BAND_5GHZ; | ||
11483 | a_band->n_channels = geo->a_channels; | ||
11484 | a_band->channels = | ||
11485 | kzalloc(geo->a_channels * | ||
11486 | sizeof(struct ieee80211_channel), GFP_KERNEL); | ||
11487 | /* translate geo->bg to a_band.channels */ | ||
11488 | for (i = 0; i < geo->a_channels; i++) { | ||
11489 | a_band->channels[i].band = IEEE80211_BAND_2GHZ; | ||
11490 | a_band->channels[i].center_freq = geo->a[i].freq; | ||
11491 | a_band->channels[i].hw_value = geo->a[i].channel; | ||
11492 | a_band->channels[i].max_power = geo->a[i].max_power; | ||
11493 | if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) | ||
11494 | a_band->channels[i].flags |= | ||
11495 | IEEE80211_CHAN_PASSIVE_SCAN; | ||
11496 | if (geo->a[i].flags & LIBIPW_CH_NO_IBSS) | ||
11497 | a_band->channels[i].flags |= | ||
11498 | IEEE80211_CHAN_NO_IBSS; | ||
11499 | if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT) | ||
11500 | a_band->channels[i].flags |= | ||
11501 | IEEE80211_CHAN_RADAR; | ||
11502 | /* No equivalent for LIBIPW_CH_80211H_RULES, | ||
11503 | LIBIPW_CH_UNIFORM_SPREADING, or | ||
11504 | LIBIPW_CH_B_ONLY... */ | ||
11505 | } | ||
11506 | /* point at bitrate info */ | ||
11507 | a_band->bitrates = ipw2200_a_rates; | ||
11508 | a_band->n_bitrates = ipw2200_num_a_rates; | ||
11509 | |||
11510 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; | ||
11511 | } | ||
11512 | |||
11513 | set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); | ||
11514 | |||
11515 | /* With that information in place, we can now register the wiphy... */ | ||
11516 | if (wiphy_register(wdev->wiphy)) { | ||
11517 | rc = -EIO; | ||
11518 | goto out; | ||
11519 | } | ||
11520 | |||
11521 | out: | ||
11433 | mutex_unlock(&priv->mutex); | 11522 | mutex_unlock(&priv->mutex); |
11434 | return 0; | 11523 | return rc; |
11435 | } | 11524 | } |
11436 | 11525 | ||
11437 | /* PCI driver stuff */ | 11526 | /* PCI driver stuff */ |
@@ -11562,7 +11651,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) | |||
11562 | if (priv->prom_net_dev) | 11651 | if (priv->prom_net_dev) |
11563 | return -EPERM; | 11652 | return -EPERM; |
11564 | 11653 | ||
11565 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); | 11654 | priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv), 1); |
11566 | if (priv->prom_net_dev == NULL) | 11655 | if (priv->prom_net_dev == NULL) |
11567 | return -ENOMEM; | 11656 | return -ENOMEM; |
11568 | 11657 | ||
@@ -11581,7 +11670,7 @@ static int ipw_prom_alloc(struct ipw_priv *priv) | |||
11581 | 11670 | ||
11582 | rc = register_netdev(priv->prom_net_dev); | 11671 | rc = register_netdev(priv->prom_net_dev); |
11583 | if (rc) { | 11672 | if (rc) { |
11584 | free_ieee80211(priv->prom_net_dev); | 11673 | free_ieee80211(priv->prom_net_dev, 1); |
11585 | priv->prom_net_dev = NULL; | 11674 | priv->prom_net_dev = NULL; |
11586 | return rc; | 11675 | return rc; |
11587 | } | 11676 | } |
@@ -11595,7 +11684,7 @@ static void ipw_prom_free(struct ipw_priv *priv) | |||
11595 | return; | 11684 | return; |
11596 | 11685 | ||
11597 | unregister_netdev(priv->prom_net_dev); | 11686 | unregister_netdev(priv->prom_net_dev); |
11598 | free_ieee80211(priv->prom_net_dev); | 11687 | free_ieee80211(priv->prom_net_dev, 1); |
11599 | 11688 | ||
11600 | priv->prom_net_dev = NULL; | 11689 | priv->prom_net_dev = NULL; |
11601 | } | 11690 | } |
@@ -11623,7 +11712,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
11623 | struct ipw_priv *priv; | 11712 | struct ipw_priv *priv; |
11624 | int i; | 11713 | int i; |
11625 | 11714 | ||
11626 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); | 11715 | net_dev = alloc_ieee80211(sizeof(struct ipw_priv), 0); |
11627 | if (net_dev == NULL) { | 11716 | if (net_dev == NULL) { |
11628 | err = -ENOMEM; | 11717 | err = -ENOMEM; |
11629 | goto out; | 11718 | goto out; |
@@ -11771,7 +11860,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev, | |||
11771 | pci_disable_device(pdev); | 11860 | pci_disable_device(pdev); |
11772 | pci_set_drvdata(pdev, NULL); | 11861 | pci_set_drvdata(pdev, NULL); |
11773 | out_free_ieee80211: | 11862 | out_free_ieee80211: |
11774 | free_ieee80211(priv->net_dev); | 11863 | free_ieee80211(priv->net_dev, 0); |
11775 | out: | 11864 | out: |
11776 | return err; | 11865 | return err; |
11777 | } | 11866 | } |
@@ -11838,7 +11927,11 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev) | |||
11838 | pci_release_regions(pdev); | 11927 | pci_release_regions(pdev); |
11839 | pci_disable_device(pdev); | 11928 | pci_disable_device(pdev); |
11840 | pci_set_drvdata(pdev, NULL); | 11929 | pci_set_drvdata(pdev, NULL); |
11841 | free_ieee80211(priv->net_dev); | 11930 | /* wiphy_unregister needs to be here, before free_ieee80211 */ |
11931 | wiphy_unregister(priv->ieee->wdev.wiphy); | ||
11932 | kfree(priv->ieee->a_band.channels); | ||
11933 | kfree(priv->ieee->bg_band.channels); | ||
11934 | free_ieee80211(priv->net_dev, 0); | ||
11842 | free_firmware(); | 11935 | free_firmware(); |
11843 | } | 11936 | } |
11844 | 11937 | ||
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 1e334ff6bd52..bf45391172f3 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/ieee80211.h> | 31 | #include <linux/ieee80211.h> |
32 | 32 | ||
33 | #include <net/lib80211.h> | 33 | #include <net/lib80211.h> |
34 | #include <net/cfg80211.h> | ||
34 | 35 | ||
35 | #define LIBIPW_VERSION "git-1.1.13" | 36 | #define LIBIPW_VERSION "git-1.1.13" |
36 | 37 | ||
@@ -783,12 +784,15 @@ struct libipw_geo { | |||
783 | 784 | ||
784 | struct libipw_device { | 785 | struct libipw_device { |
785 | struct net_device *dev; | 786 | struct net_device *dev; |
787 | struct wireless_dev wdev; | ||
786 | struct libipw_security sec; | 788 | struct libipw_security sec; |
787 | 789 | ||
788 | /* Bookkeeping structures */ | 790 | /* Bookkeeping structures */ |
789 | struct libipw_stats ieee_stats; | 791 | struct libipw_stats ieee_stats; |
790 | 792 | ||
791 | struct libipw_geo geo; | 793 | struct libipw_geo geo; |
794 | struct ieee80211_supported_band bg_band; | ||
795 | struct ieee80211_supported_band a_band; | ||
792 | 796 | ||
793 | /* Probe / Beacon management */ | 797 | /* Probe / Beacon management */ |
794 | struct list_head network_free_list; | 798 | struct list_head network_free_list; |
@@ -1014,8 +1018,8 @@ static inline int libipw_is_cck_rate(u8 rate) | |||
1014 | } | 1018 | } |
1015 | 1019 | ||
1016 | /* ieee80211.c */ | 1020 | /* ieee80211.c */ |
1017 | extern void free_ieee80211(struct net_device *dev); | 1021 | extern void free_ieee80211(struct net_device *dev, int monitor); |
1018 | extern struct net_device *alloc_ieee80211(int sizeof_priv); | 1022 | extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor); |
1019 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); | 1023 | extern int libipw_change_mtu(struct net_device *dev, int new_mtu); |
1020 | 1024 | ||
1021 | extern void libipw_networks_age(struct libipw_device *ieee, | 1025 | extern void libipw_networks_age(struct libipw_device *ieee, |
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index eb2b60834c17..e8a1ac5f8e11 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c | |||
@@ -62,6 +62,9 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION); | |||
62 | MODULE_AUTHOR(DRV_COPYRIGHT); | 62 | MODULE_AUTHOR(DRV_COPYRIGHT); |
63 | MODULE_LICENSE("GPL"); | 63 | MODULE_LICENSE("GPL"); |
64 | 64 | ||
65 | struct cfg80211_ops libipw_config_ops = { }; | ||
66 | void *libipw_wiphy_privid = &libipw_wiphy_privid; | ||
67 | |||
65 | static int libipw_networks_allocate(struct libipw_device *ieee) | 68 | static int libipw_networks_allocate(struct libipw_device *ieee) |
66 | { | 69 | { |
67 | if (ieee->networks) | 70 | if (ieee->networks) |
@@ -140,7 +143,7 @@ int libipw_change_mtu(struct net_device *dev, int new_mtu) | |||
140 | } | 143 | } |
141 | EXPORT_SYMBOL(libipw_change_mtu); | 144 | EXPORT_SYMBOL(libipw_change_mtu); |
142 | 145 | ||
143 | struct net_device *alloc_ieee80211(int sizeof_priv) | 146 | struct net_device *alloc_ieee80211(int sizeof_priv, int monitor) |
144 | { | 147 | { |
145 | struct libipw_device *ieee; | 148 | struct libipw_device *ieee; |
146 | struct net_device *dev; | 149 | struct net_device *dev; |
@@ -157,10 +160,31 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
157 | 160 | ||
158 | ieee->dev = dev; | 161 | ieee->dev = dev; |
159 | 162 | ||
163 | if (!monitor) { | ||
164 | ieee->wdev.wiphy = wiphy_new(&libipw_config_ops, 0); | ||
165 | if (!ieee->wdev.wiphy) { | ||
166 | LIBIPW_ERROR("Unable to allocate wiphy.\n"); | ||
167 | goto failed_free_netdev; | ||
168 | } | ||
169 | |||
170 | ieee->dev->ieee80211_ptr = &ieee->wdev; | ||
171 | ieee->wdev.iftype = NL80211_IFTYPE_STATION; | ||
172 | |||
173 | /* Fill-out wiphy structure bits we know... Not enough info | ||
174 | here to call set_wiphy_dev or set MAC address or channel info | ||
175 | -- have to do that in ->ndo_init... */ | ||
176 | ieee->wdev.wiphy->privid = libipw_wiphy_privid; | ||
177 | |||
178 | ieee->wdev.wiphy->max_scan_ssids = 1; | ||
179 | ieee->wdev.wiphy->max_scan_ie_len = 0; | ||
180 | ieee->wdev.wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | ||
181 | | BIT(NL80211_IFTYPE_ADHOC); | ||
182 | } | ||
183 | |||
160 | err = libipw_networks_allocate(ieee); | 184 | err = libipw_networks_allocate(ieee); |
161 | if (err) { | 185 | if (err) { |
162 | LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); | 186 | LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); |
163 | goto failed_free_netdev; | 187 | goto failed_free_wiphy; |
164 | } | 188 | } |
165 | libipw_networks_initialize(ieee); | 189 | libipw_networks_initialize(ieee); |
166 | 190 | ||
@@ -193,19 +217,27 @@ struct net_device *alloc_ieee80211(int sizeof_priv) | |||
193 | 217 | ||
194 | return dev; | 218 | return dev; |
195 | 219 | ||
220 | failed_free_wiphy: | ||
221 | if (!monitor) | ||
222 | wiphy_free(ieee->wdev.wiphy); | ||
196 | failed_free_netdev: | 223 | failed_free_netdev: |
197 | free_netdev(dev); | 224 | free_netdev(dev); |
198 | failed: | 225 | failed: |
199 | return NULL; | 226 | return NULL; |
200 | } | 227 | } |
201 | 228 | ||
202 | void free_ieee80211(struct net_device *dev) | 229 | void free_ieee80211(struct net_device *dev, int monitor) |
203 | { | 230 | { |
204 | struct libipw_device *ieee = netdev_priv(dev); | 231 | struct libipw_device *ieee = netdev_priv(dev); |
205 | 232 | ||
206 | lib80211_crypt_info_free(&ieee->crypt_info); | 233 | lib80211_crypt_info_free(&ieee->crypt_info); |
207 | 234 | ||
208 | libipw_networks_free(ieee); | 235 | libipw_networks_free(ieee); |
236 | |||
237 | /* free cfg80211 resources */ | ||
238 | if (!monitor) | ||
239 | wiphy_free(ieee->wdev.wiphy); | ||
240 | |||
209 | free_netdev(dev); | 241 | free_netdev(dev); |
210 | } | 242 | } |
211 | 243 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 8f82537045bf..8414178bcff4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -173,6 +173,7 @@ struct iwl_cfg iwl1000_bgn_cfg = { | |||
173 | .use_rts_for_ht = true, /* use rts/cts protection */ | 173 | .use_rts_for_ht = true, /* use rts/cts protection */ |
174 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 174 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
175 | .support_ct_kill_exit = true, | 175 | .support_ct_kill_exit = true, |
176 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
176 | }; | 177 | }; |
177 | 178 | ||
178 | struct iwl_cfg iwl1000_bg_cfg = { | 179 | struct iwl_cfg iwl1000_bg_cfg = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 2b0d65c5780a..ecc23ec1f6a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -221,22 +221,13 @@ struct iwl3945_ibss_seq { | |||
221 | * for use by iwl-*.c | 221 | * for use by iwl-*.c |
222 | * | 222 | * |
223 | *****************************************************************************/ | 223 | *****************************************************************************/ |
224 | extern int iwl3945_power_init_handle(struct iwl_priv *priv); | ||
225 | extern int iwl3945_eeprom_init(struct iwl_priv *priv); | ||
226 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); | 224 | extern int iwl3945_calc_db_from_ratio(int sig_ratio); |
227 | extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); | 225 | extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); |
228 | extern int iwl3945_tx_queue_init(struct iwl_priv *priv, | ||
229 | struct iwl_tx_queue *txq, int count, u32 id); | ||
230 | extern void iwl3945_rx_replenish(void *data); | 226 | extern void iwl3945_rx_replenish(void *data); |
231 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); | 227 | extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); |
232 | extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq); | ||
233 | extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, | ||
234 | const void *data); | ||
235 | extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, | ||
236 | struct iwl_host_cmd *cmd); | ||
237 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, | 228 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, |
238 | struct ieee80211_hdr *hdr,int left); | 229 | struct ieee80211_hdr *hdr,int left); |
239 | extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv); | 230 | extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log); |
240 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); | 231 | extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); |
241 | 232 | ||
242 | /* | 233 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index cc3942448703..386513b601f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -1818,8 +1818,9 @@ static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | |||
1818 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; | 1818 | addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; |
1819 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; | 1819 | addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; |
1820 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; | 1820 | addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; |
1821 | addsta->sleep_tx_count = cmd->sleep_tx_count; | ||
1821 | addsta->reserved1 = cpu_to_le16(0); | 1822 | addsta->reserved1 = cpu_to_le16(0); |
1822 | addsta->reserved2 = cpu_to_le32(0); | 1823 | addsta->reserved2 = cpu_to_le16(0); |
1823 | 1824 | ||
1824 | return (u16)sizeof(struct iwl4965_addsta_cmd); | 1825 | return (u16)sizeof(struct iwl4965_addsta_cmd); |
1825 | } | 1826 | } |
@@ -1865,8 +1866,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, | |||
1865 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 1866 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
1866 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1867 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1867 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 1868 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
1868 | info->flags |= iwl_is_tx_success(status) ? | 1869 | info->flags |= iwl_tx_status_to_mac80211(status); |
1869 | IEEE80211_TX_STAT_ACK : 0; | ||
1870 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 1870 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
1871 | /* FIXME: code repetition end */ | 1871 | /* FIXME: code repetition end */ |
1872 | 1872 | ||
@@ -2021,8 +2021,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv, | |||
2021 | } | 2021 | } |
2022 | } else { | 2022 | } else { |
2023 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 2023 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
2024 | info->flags |= iwl_is_tx_success(status) ? | 2024 | info->flags |= iwl_tx_status_to_mac80211(status); |
2025 | IEEE80211_TX_STAT_ACK : 0; | ||
2026 | iwl_hwrate_to_tx_control(priv, | 2025 | iwl_hwrate_to_tx_control(priv, |
2027 | le32_to_cpu(tx_resp->rate_n_flags), | 2026 | le32_to_cpu(tx_resp->rate_n_flags), |
2028 | info); | 2027 | info); |
@@ -2240,6 +2239,7 @@ struct iwl_cfg iwl4965_agn_cfg = { | |||
2240 | .broken_powersave = true, | 2239 | .broken_powersave = true, |
2241 | .led_compensation = 61, | 2240 | .led_compensation = 61, |
2242 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, | 2241 | .chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS, |
2242 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
2243 | }; | 2243 | }; |
2244 | 2244 | ||
2245 | /* Module firmware */ | 2245 | /* Module firmware */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index e23d301e816f..e2f8615c8c9b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -994,8 +994,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, | |||
994 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); | 994 | info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); |
995 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 995 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
996 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | 996 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; |
997 | info->flags |= iwl_is_tx_success(status) ? | 997 | info->flags |= iwl_tx_status_to_mac80211(status); |
998 | IEEE80211_TX_STAT_ACK : 0; | ||
999 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); | 998 | iwl_hwrate_to_tx_control(priv, rate_n_flags, info); |
1000 | 999 | ||
1001 | /* FIXME: code repetition end */ | 1000 | /* FIXME: code repetition end */ |
@@ -1140,8 +1139,7 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv, | |||
1140 | BUG_ON(txq_id != txq->swq_id); | 1139 | BUG_ON(txq_id != txq->swq_id); |
1141 | 1140 | ||
1142 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1141 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1143 | info->flags |= iwl_is_tx_success(status) ? | 1142 | info->flags |= iwl_tx_status_to_mac80211(status); |
1144 | IEEE80211_TX_STAT_ACK : 0; | ||
1145 | iwl_hwrate_to_tx_control(priv, | 1143 | iwl_hwrate_to_tx_control(priv, |
1146 | le32_to_cpu(tx_resp->rate_n_flags), | 1144 | le32_to_cpu(tx_resp->rate_n_flags), |
1147 | info); | 1145 | info); |
@@ -1251,6 +1249,22 @@ int iwl5000_send_tx_power(struct iwl_priv *priv) | |||
1251 | 1249 | ||
1252 | /* half dBm need to multiply */ | 1250 | /* half dBm need to multiply */ |
1253 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); | 1251 | tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); |
1252 | |||
1253 | if (priv->tx_power_lmt_in_half_dbm && | ||
1254 | priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) { | ||
1255 | /* | ||
1256 | * For the newer devices which using enhanced/extend tx power | ||
1257 | * table in EEPROM, the format is in half dBm. driver need to | ||
1258 | * convert to dBm format before report to mac80211. | ||
1259 | * By doing so, there is a possibility of 1/2 dBm resolution | ||
1260 | * lost. driver will perform "round-up" operation before | ||
1261 | * reporting, but it will cause 1/2 dBm tx power over the | ||
1262 | * regulatory limit. Perform the checking here, if the | ||
1263 | * "tx_power_user_lmt" is higher than EEPROM value (in | ||
1264 | * half-dBm format), lower the tx power based on EEPROM | ||
1265 | */ | ||
1266 | tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm; | ||
1267 | } | ||
1254 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; | 1268 | tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; |
1255 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; | 1269 | tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; |
1256 | 1270 | ||
@@ -1584,14 +1598,15 @@ struct iwl_cfg iwl5300_agn_cfg = { | |||
1584 | .ht_greenfield_support = true, | 1598 | .ht_greenfield_support = true, |
1585 | .led_compensation = 51, | 1599 | .led_compensation = 51, |
1586 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1600 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1601 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1587 | }; | 1602 | }; |
1588 | 1603 | ||
1589 | struct iwl_cfg iwl5100_bg_cfg = { | 1604 | struct iwl_cfg iwl5100_bgn_cfg = { |
1590 | .name = "5100BG", | 1605 | .name = "5100BGN", |
1591 | .fw_name_pre = IWL5000_FW_PRE, | 1606 | .fw_name_pre = IWL5000_FW_PRE, |
1592 | .ucode_api_max = IWL5000_UCODE_API_MAX, | 1607 | .ucode_api_max = IWL5000_UCODE_API_MAX, |
1593 | .ucode_api_min = IWL5000_UCODE_API_MIN, | 1608 | .ucode_api_min = IWL5000_UCODE_API_MIN, |
1594 | .sku = IWL_SKU_G, | 1609 | .sku = IWL_SKU_G|IWL_SKU_N, |
1595 | .ops = &iwl5000_ops, | 1610 | .ops = &iwl5000_ops, |
1596 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | 1611 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, |
1597 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, | 1612 | .eeprom_ver = EEPROM_5000_EEPROM_VERSION, |
@@ -1627,7 +1642,6 @@ struct iwl_cfg iwl5100_abg_cfg = { | |||
1627 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | 1642 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, |
1628 | .set_l0s = true, | 1643 | .set_l0s = true, |
1629 | .use_bsm = false, | 1644 | .use_bsm = false, |
1630 | .ht_greenfield_support = true, | ||
1631 | .led_compensation = 51, | 1645 | .led_compensation = 51, |
1632 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1646 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1633 | }; | 1647 | }; |
@@ -1653,6 +1667,7 @@ struct iwl_cfg iwl5100_agn_cfg = { | |||
1653 | .ht_greenfield_support = true, | 1667 | .ht_greenfield_support = true, |
1654 | .led_compensation = 51, | 1668 | .led_compensation = 51, |
1655 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1669 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1670 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1656 | }; | 1671 | }; |
1657 | 1672 | ||
1658 | struct iwl_cfg iwl5350_agn_cfg = { | 1673 | struct iwl_cfg iwl5350_agn_cfg = { |
@@ -1676,6 +1691,7 @@ struct iwl_cfg iwl5350_agn_cfg = { | |||
1676 | .ht_greenfield_support = true, | 1691 | .ht_greenfield_support = true, |
1677 | .led_compensation = 51, | 1692 | .led_compensation = 51, |
1678 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1693 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1694 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1679 | }; | 1695 | }; |
1680 | 1696 | ||
1681 | struct iwl_cfg iwl5150_agn_cfg = { | 1697 | struct iwl_cfg iwl5150_agn_cfg = { |
@@ -1699,6 +1715,29 @@ struct iwl_cfg iwl5150_agn_cfg = { | |||
1699 | .ht_greenfield_support = true, | 1715 | .ht_greenfield_support = true, |
1700 | .led_compensation = 51, | 1716 | .led_compensation = 51, |
1701 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | 1717 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, |
1718 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
1719 | }; | ||
1720 | |||
1721 | struct iwl_cfg iwl5150_abg_cfg = { | ||
1722 | .name = "5150ABG", | ||
1723 | .fw_name_pre = IWL5150_FW_PRE, | ||
1724 | .ucode_api_max = IWL5150_UCODE_API_MAX, | ||
1725 | .ucode_api_min = IWL5150_UCODE_API_MIN, | ||
1726 | .sku = IWL_SKU_A|IWL_SKU_G, | ||
1727 | .ops = &iwl5150_ops, | ||
1728 | .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, | ||
1729 | .eeprom_ver = EEPROM_5050_EEPROM_VERSION, | ||
1730 | .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, | ||
1731 | .num_of_queues = IWL50_NUM_QUEUES, | ||
1732 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
1733 | .mod_params = &iwl50_mod_params, | ||
1734 | .valid_tx_ant = ANT_A, | ||
1735 | .valid_rx_ant = ANT_AB, | ||
1736 | .pll_cfg_val = CSR50_ANA_PLL_CFG_VAL, | ||
1737 | .set_l0s = true, | ||
1738 | .use_bsm = false, | ||
1739 | .led_compensation = 51, | ||
1740 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
1702 | }; | 1741 | }; |
1703 | 1742 | ||
1704 | MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); | 1743 | 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 f732f6d194a0..74e571049273 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -306,6 +306,7 @@ struct iwl_cfg iwl6000i_2agn_cfg = { | |||
306 | .supports_idle = true, | 306 | .supports_idle = true, |
307 | .adv_thermal_throttle = true, | 307 | .adv_thermal_throttle = true, |
308 | .support_ct_kill_exit = true, | 308 | .support_ct_kill_exit = true, |
309 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, | ||
309 | }; | 310 | }; |
310 | 311 | ||
311 | struct iwl_cfg iwl6000i_2abg_cfg = { | 312 | struct iwl_cfg iwl6000i_2abg_cfg = { |
@@ -394,8 +395,7 @@ struct iwl_cfg iwl6050_2agn_cfg = { | |||
394 | .supports_idle = true, | 395 | .supports_idle = true, |
395 | .adv_thermal_throttle = true, | 396 | .adv_thermal_throttle = true, |
396 | .support_ct_kill_exit = true, | 397 | .support_ct_kill_exit = true, |
397 | .support_sm_ps = true, | 398 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DYNAMIC, |
398 | .support_wimax_coexist = true, | ||
399 | }; | 399 | }; |
400 | 400 | ||
401 | struct iwl_cfg iwl6050_2abg_cfg = { | 401 | struct iwl_cfg iwl6050_2abg_cfg = { |
@@ -425,7 +425,6 @@ struct iwl_cfg iwl6050_2abg_cfg = { | |||
425 | .supports_idle = true, | 425 | .supports_idle = true, |
426 | .adv_thermal_throttle = true, | 426 | .adv_thermal_throttle = true, |
427 | .support_ct_kill_exit = true, | 427 | .support_ct_kill_exit = true, |
428 | .support_wimax_coexist = true, | ||
429 | }; | 428 | }; |
430 | 429 | ||
431 | struct iwl_cfg iwl6000_3agn_cfg = { | 430 | struct iwl_cfg iwl6000_3agn_cfg = { |
@@ -456,38 +455,7 @@ struct iwl_cfg iwl6000_3agn_cfg = { | |||
456 | .supports_idle = true, | 455 | .supports_idle = true, |
457 | .adv_thermal_throttle = true, | 456 | .adv_thermal_throttle = true, |
458 | .support_ct_kill_exit = true, | 457 | .support_ct_kill_exit = true, |
459 | }; | 458 | .sm_ps_mode = WLAN_HT_CAP_SM_PS_DISABLED, |
460 | |||
461 | struct iwl_cfg iwl6050_3agn_cfg = { | ||
462 | .name = "6050 Series 3x3 AGN", | ||
463 | .fw_name_pre = IWL6050_FW_PRE, | ||
464 | .ucode_api_max = IWL6050_UCODE_API_MAX, | ||
465 | .ucode_api_min = IWL6050_UCODE_API_MIN, | ||
466 | .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, | ||
467 | .ops = &iwl6050_ops, | ||
468 | .eeprom_size = OTP_LOW_IMAGE_SIZE, | ||
469 | .eeprom_ver = EEPROM_6050_EEPROM_VERSION, | ||
470 | .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, | ||
471 | .num_of_queues = IWL50_NUM_QUEUES, | ||
472 | .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, | ||
473 | .mod_params = &iwl50_mod_params, | ||
474 | .valid_tx_ant = ANT_ABC, | ||
475 | .valid_rx_ant = ANT_ABC, | ||
476 | .pll_cfg_val = 0, | ||
477 | .set_l0s = true, | ||
478 | .use_bsm = false, | ||
479 | .pa_type = IWL_PA_SYSTEM, | ||
480 | .max_ll_items = OTP_MAX_LL_ITEMS_6x50, | ||
481 | .shadow_ram_support = true, | ||
482 | .ht_greenfield_support = true, | ||
483 | .led_compensation = 51, | ||
484 | .use_rts_for_ht = true, /* use rts/cts protection */ | ||
485 | .chain_noise_num_beacons = IWL_CAL_NUM_BEACONS, | ||
486 | .supports_idle = true, | ||
487 | .adv_thermal_throttle = true, | ||
488 | .support_ct_kill_exit = true, | ||
489 | .support_sm_ps = true, | ||
490 | .support_wimax_coexist = true, | ||
491 | }; | 459 | }; |
492 | 460 | ||
493 | MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); | 461 | 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 43edd8fd4405..fe511cbf012e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -301,7 +301,7 @@ static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, | |||
301 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { | 301 | if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { |
302 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", | 302 | IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", |
303 | sta->addr, tid); | 303 | sta->addr, tid); |
304 | ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); | 304 | ieee80211_start_tx_ba_session(sta, tid); |
305 | } | 305 | } |
306 | } | 306 | } |
307 | 307 | ||
@@ -2964,16 +2964,16 @@ static void rs_add_debugfs(void *priv, void *priv_sta, | |||
2964 | { | 2964 | { |
2965 | struct iwl_lq_sta *lq_sta = priv_sta; | 2965 | struct iwl_lq_sta *lq_sta = priv_sta; |
2966 | lq_sta->rs_sta_dbgfs_scale_table_file = | 2966 | lq_sta->rs_sta_dbgfs_scale_table_file = |
2967 | debugfs_create_file("rate_scale_table", 0600, dir, | 2967 | debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir, |
2968 | lq_sta, &rs_sta_dbgfs_scale_table_ops); | 2968 | lq_sta, &rs_sta_dbgfs_scale_table_ops); |
2969 | lq_sta->rs_sta_dbgfs_stats_table_file = | 2969 | lq_sta->rs_sta_dbgfs_stats_table_file = |
2970 | debugfs_create_file("rate_stats_table", 0600, dir, | 2970 | debugfs_create_file("rate_stats_table", S_IRUSR, dir, |
2971 | lq_sta, &rs_sta_dbgfs_stats_table_ops); | 2971 | lq_sta, &rs_sta_dbgfs_stats_table_ops); |
2972 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = | 2972 | lq_sta->rs_sta_dbgfs_rate_scale_data_file = |
2973 | debugfs_create_file("rate_scale_data", 0600, dir, | 2973 | debugfs_create_file("rate_scale_data", S_IRUSR, dir, |
2974 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); | 2974 | lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); |
2975 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = | 2975 | lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = |
2976 | debugfs_create_u8("tx_agg_tid_enable", 0600, dir, | 2976 | debugfs_create_u8("tx_agg_tid_enable", S_IRUSR | S_IWUSR, dir, |
2977 | &lq_sta->tx_agg_tid_en); | 2977 | &lq_sta->tx_agg_tid_en); |
2978 | 2978 | ||
2979 | } | 2979 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 29f7510ecdd7..c96513bddb10 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -311,7 +311,7 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) | |||
311 | list_add(&frame->list, &priv->free_frames); | 311 | list_add(&frame->list, &priv->free_frames); |
312 | } | 312 | } |
313 | 313 | ||
314 | static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | 314 | static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, |
315 | struct ieee80211_hdr *hdr, | 315 | struct ieee80211_hdr *hdr, |
316 | int left) | 316 | int left) |
317 | { | 317 | { |
@@ -328,34 +328,74 @@ static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | |||
328 | return priv->ibss_beacon->len; | 328 | return priv->ibss_beacon->len; |
329 | } | 329 | } |
330 | 330 | ||
331 | /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ | ||
332 | static void iwl_set_beacon_tim(struct iwl_priv *priv, | ||
333 | struct iwl_tx_beacon_cmd *tx_beacon_cmd, | ||
334 | u8 *beacon, u32 frame_size) | ||
335 | { | ||
336 | u16 tim_idx; | ||
337 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon; | ||
338 | |||
339 | /* | ||
340 | * The index is relative to frame start but we start looking at the | ||
341 | * variable-length part of the beacon. | ||
342 | */ | ||
343 | tim_idx = mgmt->u.beacon.variable - beacon; | ||
344 | |||
345 | /* Parse variable-length elements of beacon to find WLAN_EID_TIM */ | ||
346 | while ((tim_idx < (frame_size - 2)) && | ||
347 | (beacon[tim_idx] != WLAN_EID_TIM)) | ||
348 | tim_idx += beacon[tim_idx+1] + 2; | ||
349 | |||
350 | /* If TIM field was found, set variables */ | ||
351 | if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) { | ||
352 | tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx); | ||
353 | tx_beacon_cmd->tim_size = beacon[tim_idx+1]; | ||
354 | } else | ||
355 | IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); | ||
356 | } | ||
357 | |||
331 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | 358 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, |
332 | struct iwl_frame *frame, u8 rate) | 359 | struct iwl_frame *frame) |
333 | { | 360 | { |
334 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 361 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
335 | unsigned int frame_size; | 362 | u32 frame_size; |
363 | u32 rate_flags; | ||
364 | u32 rate; | ||
365 | /* | ||
366 | * We have to set up the TX command, the TX Beacon command, and the | ||
367 | * beacon contents. | ||
368 | */ | ||
336 | 369 | ||
370 | /* Initialize memory */ | ||
337 | tx_beacon_cmd = &frame->u.beacon; | 371 | tx_beacon_cmd = &frame->u.beacon; |
338 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 372 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); |
339 | 373 | ||
340 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | 374 | /* Set up TX beacon contents */ |
341 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
342 | |||
343 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, | 375 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, |
344 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | 376 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); |
377 | if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE)) | ||
378 | return 0; | ||
345 | 379 | ||
346 | BUG_ON(frame_size > MAX_MPDU_SIZE); | 380 | /* Set up TX command fields */ |
347 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 381 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
382 | tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; | ||
383 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | ||
384 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | ||
385 | TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK; | ||
348 | 386 | ||
349 | if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) | 387 | /* Set up TX beacon command fields */ |
350 | tx_beacon_cmd->tx.rate_n_flags = | 388 | iwl_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame, |
351 | iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); | 389 | frame_size); |
352 | else | ||
353 | tx_beacon_cmd->tx.rate_n_flags = | ||
354 | iwl_hw_set_rate_n_flags(rate, 0); | ||
355 | 390 | ||
356 | tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | | 391 | /* Set up packet rate and flags */ |
357 | TX_CMD_FLG_TSF_MSK | | 392 | rate = iwl_rate_get_lowest_plcp(priv); |
358 | TX_CMD_FLG_STA_RATE_MSK; | 393 | priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); |
394 | rate_flags = iwl_ant_idx_to_flags(priv->mgmt_tx_ant); | ||
395 | if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE)) | ||
396 | rate_flags |= RATE_MCS_CCK_MSK; | ||
397 | tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, | ||
398 | rate_flags); | ||
359 | 399 | ||
360 | return sizeof(*tx_beacon_cmd) + frame_size; | 400 | return sizeof(*tx_beacon_cmd) + frame_size; |
361 | } | 401 | } |
@@ -364,19 +404,20 @@ static int iwl_send_beacon_cmd(struct iwl_priv *priv) | |||
364 | struct iwl_frame *frame; | 404 | struct iwl_frame *frame; |
365 | unsigned int frame_size; | 405 | unsigned int frame_size; |
366 | int rc; | 406 | int rc; |
367 | u8 rate; | ||
368 | 407 | ||
369 | frame = iwl_get_free_frame(priv); | 408 | frame = iwl_get_free_frame(priv); |
370 | |||
371 | if (!frame) { | 409 | if (!frame) { |
372 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " | 410 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " |
373 | "command.\n"); | 411 | "command.\n"); |
374 | return -ENOMEM; | 412 | return -ENOMEM; |
375 | } | 413 | } |
376 | 414 | ||
377 | rate = iwl_rate_get_lowest_plcp(priv); | 415 | frame_size = iwl_hw_get_beacon_cmd(priv, frame); |
378 | 416 | if (!frame_size) { | |
379 | frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate); | 417 | IWL_ERR(priv, "Error configuring the beacon command\n"); |
418 | iwl_free_frame(priv, frame); | ||
419 | return -EINVAL; | ||
420 | } | ||
380 | 421 | ||
381 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, | 422 | rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, |
382 | &frame->u.cmd[0]); | 423 | &frame->u.cmd[0]); |
@@ -613,7 +654,7 @@ static void iwl_bg_statistics_periodic(unsigned long data) | |||
613 | if (!iwl_is_ready_rf(priv)) | 654 | if (!iwl_is_ready_rf(priv)) |
614 | return; | 655 | return; |
615 | 656 | ||
616 | iwl_send_statistics_request(priv, CMD_ASYNC); | 657 | iwl_send_statistics_request(priv, CMD_ASYNC, false); |
617 | } | 658 | } |
618 | 659 | ||
619 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, | 660 | static void iwl_rx_beacon_notif(struct iwl_priv *priv, |
@@ -730,7 +771,7 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
730 | * statistics request from the host as well as for the periodic | 771 | * statistics request from the host as well as for the periodic |
731 | * statistics notifications (after received beacons) from the uCode. | 772 | * statistics notifications (after received beacons) from the uCode. |
732 | */ | 773 | */ |
733 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; | 774 | priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics; |
734 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; | 775 | priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; |
735 | 776 | ||
736 | iwl_setup_spectrum_handlers(priv); | 777 | iwl_setup_spectrum_handlers(priv); |
@@ -1038,7 +1079,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) | |||
1038 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { | 1079 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { |
1039 | iwl_rx_handle(priv); | 1080 | iwl_rx_handle(priv); |
1040 | priv->isr_stats.rx++; | 1081 | priv->isr_stats.rx++; |
1041 | iwl_leds_background(priv); | ||
1042 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); | 1082 | handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); |
1043 | } | 1083 | } |
1044 | 1084 | ||
@@ -1226,19 +1266,27 @@ static void iwl_irq_tasklet(struct iwl_priv *priv) | |||
1226 | * 3- update RX shared data to indicate last write index. | 1266 | * 3- update RX shared data to indicate last write index. |
1227 | * 4- send interrupt. | 1267 | * 4- send interrupt. |
1228 | * This could lead to RX race, driver could receive RX interrupt | 1268 | * This could lead to RX race, driver could receive RX interrupt |
1229 | * but the shared data changes does not reflect this. | 1269 | * but the shared data changes does not reflect this; |
1230 | * this could lead to RX race, RX periodic will solve this race | 1270 | * periodic interrupt will detect any dangling Rx activity. |
1231 | */ | 1271 | */ |
1232 | iwl_write32(priv, CSR_INT_PERIODIC_REG, | 1272 | |
1273 | /* Disable periodic interrupt; we use it as just a one-shot. */ | ||
1274 | iwl_write8(priv, CSR_INT_PERIODIC_REG, | ||
1233 | CSR_INT_PERIODIC_DIS); | 1275 | CSR_INT_PERIODIC_DIS); |
1234 | iwl_rx_handle(priv); | 1276 | iwl_rx_handle(priv); |
1235 | /* Only set RX periodic if real RX is received. */ | 1277 | |
1278 | /* | ||
1279 | * Enable periodic interrupt in 8 msec only if we received | ||
1280 | * real RX interrupt (instead of just periodic int), to catch | ||
1281 | * any dangling Rx interrupt. If it was just the periodic | ||
1282 | * interrupt, there was no dangling Rx activity, and no need | ||
1283 | * to extend the periodic interrupt; one-shot is enough. | ||
1284 | */ | ||
1236 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) | 1285 | if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) |
1237 | iwl_write32(priv, CSR_INT_PERIODIC_REG, | 1286 | iwl_write8(priv, CSR_INT_PERIODIC_REG, |
1238 | CSR_INT_PERIODIC_ENA); | 1287 | CSR_INT_PERIODIC_ENA); |
1239 | 1288 | ||
1240 | priv->isr_stats.rx++; | 1289 | priv->isr_stats.rx++; |
1241 | iwl_leds_background(priv); | ||
1242 | } | 1290 | } |
1243 | 1291 | ||
1244 | /* This "Tx" DMA channel is used only for loading uCode */ | 1292 | /* This "Tx" DMA channel is used only for loading uCode */ |
@@ -1557,7 +1605,6 @@ static int iwl_read_ucode(struct iwl_priv *priv) | |||
1557 | return ret; | 1605 | return ret; |
1558 | } | 1606 | } |
1559 | 1607 | ||
1560 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1561 | static const char *desc_lookup_text[] = { | 1608 | static const char *desc_lookup_text[] = { |
1562 | "OK", | 1609 | "OK", |
1563 | "FAIL", | 1610 | "FAIL", |
@@ -1710,10 +1757,42 @@ static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1710 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1757 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1711 | } | 1758 | } |
1712 | 1759 | ||
1760 | /** | ||
1761 | * iwl_print_last_event_logs - Dump the newest # of event log to syslog | ||
1762 | */ | ||
1763 | static void iwl_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1764 | u32 num_wraps, u32 next_entry, | ||
1765 | u32 size, u32 mode) | ||
1766 | { | ||
1767 | /* | ||
1768 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1769 | * i.e the entries just before the next ont that uCode would fill. | ||
1770 | */ | ||
1771 | if (num_wraps) { | ||
1772 | if (next_entry < size) { | ||
1773 | iwl_print_event_log(priv, | ||
1774 | capacity - (size - next_entry), | ||
1775 | size - next_entry, mode); | ||
1776 | iwl_print_event_log(priv, 0, | ||
1777 | next_entry, mode); | ||
1778 | } else | ||
1779 | iwl_print_event_log(priv, next_entry - size, | ||
1780 | size, mode); | ||
1781 | } else { | ||
1782 | if (next_entry < size) | ||
1783 | iwl_print_event_log(priv, 0, next_entry, mode); | ||
1784 | else | ||
1785 | iwl_print_event_log(priv, next_entry - size, | ||
1786 | size, mode); | ||
1787 | } | ||
1788 | } | ||
1789 | |||
1713 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1790 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
1714 | #define MAX_EVENT_LOG_SIZE (512) | 1791 | #define MAX_EVENT_LOG_SIZE (512) |
1715 | 1792 | ||
1716 | void iwl_dump_nic_event_log(struct iwl_priv *priv) | 1793 | #define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20) |
1794 | |||
1795 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | ||
1717 | { | 1796 | { |
1718 | u32 base; /* SRAM byte address of event log header */ | 1797 | u32 base; /* SRAM byte address of event log header */ |
1719 | u32 capacity; /* event log capacity in # entries */ | 1798 | u32 capacity; /* event log capacity in # entries */ |
@@ -1758,19 +1837,37 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv) | |||
1758 | return; | 1837 | return; |
1759 | } | 1838 | } |
1760 | 1839 | ||
1761 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | 1840 | #ifdef CONFIG_IWLWIFI_DEBUG |
1762 | size, num_wraps); | 1841 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)) |
1763 | 1842 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) | |
1764 | /* if uCode has wrapped back to top of log, start at the oldest entry, | 1843 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
1765 | * i.e the next one that uCode would fill. */ | 1844 | #else |
1766 | if (num_wraps) | 1845 | size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES) |
1767 | iwl_print_event_log(priv, next_entry, | 1846 | ? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size; |
1768 | capacity - next_entry, mode); | 1847 | #endif |
1769 | /* (then/else) start at top of log */ | 1848 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n", |
1770 | iwl_print_event_log(priv, 0, next_entry, mode); | 1849 | size); |
1771 | 1850 | ||
1772 | } | 1851 | #ifdef CONFIG_IWLWIFI_DEBUG |
1852 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | ||
1853 | /* | ||
1854 | * if uCode has wrapped back to top of log, | ||
1855 | * start at the oldest entry, | ||
1856 | * i.e the next one that uCode would fill. | ||
1857 | */ | ||
1858 | if (num_wraps) | ||
1859 | iwl_print_event_log(priv, next_entry, | ||
1860 | capacity - next_entry, mode); | ||
1861 | /* (then/else) start at top of log */ | ||
1862 | iwl_print_event_log(priv, 0, next_entry, mode); | ||
1863 | } else | ||
1864 | iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
1865 | next_entry, size, mode); | ||
1866 | #else | ||
1867 | iwl_print_last_event_logs(priv, capacity, num_wraps, | ||
1868 | next_entry, size, mode); | ||
1773 | #endif | 1869 | #endif |
1870 | } | ||
1774 | 1871 | ||
1775 | /** | 1872 | /** |
1776 | * iwl_alive_start - called after REPLY_ALIVE notification received | 1873 | * iwl_alive_start - called after REPLY_ALIVE notification received |
@@ -2360,16 +2457,14 @@ static int iwl_setup_mac(struct iwl_priv *priv) | |||
2360 | BIT(NL80211_IFTYPE_STATION) | | 2457 | BIT(NL80211_IFTYPE_STATION) | |
2361 | BIT(NL80211_IFTYPE_ADHOC); | 2458 | BIT(NL80211_IFTYPE_ADHOC); |
2362 | 2459 | ||
2363 | hw->wiphy->custom_regulatory = true; | 2460 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY | |
2364 | 2461 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | |
2365 | /* Firmware does not support this */ | ||
2366 | hw->wiphy->disable_beacon_hints = true; | ||
2367 | 2462 | ||
2368 | /* | 2463 | /* |
2369 | * For now, disable PS by default because it affects | 2464 | * For now, disable PS by default because it affects |
2370 | * RX performance significantly. | 2465 | * RX performance significantly. |
2371 | */ | 2466 | */ |
2372 | hw->wiphy->ps_default = false; | 2467 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
2373 | 2468 | ||
2374 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 2469 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
2375 | /* we create the 802.11 header and a zero-length SSID element */ | 2470 | /* we create the 802.11 header and a zero-length SSID element */ |
@@ -2523,6 +2618,10 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2523 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " | 2618 | IWL_WARN(priv, "REPLY_RXON_TIMING failed - " |
2524 | "Attempting to continue.\n"); | 2619 | "Attempting to continue.\n"); |
2525 | 2620 | ||
2621 | /* AP has all antennas */ | ||
2622 | priv->chain_noise_data.active_chains = | ||
2623 | priv->hw_params.valid_rx_ant; | ||
2624 | iwl_set_rxon_ht(priv, &priv->current_ht_config); | ||
2526 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 2625 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
2527 | priv->cfg->ops->hcmd->set_rxon_chain(priv); | 2626 | priv->cfg->ops->hcmd->set_rxon_chain(priv); |
2528 | 2627 | ||
@@ -2551,6 +2650,7 @@ void iwl_config_ap(struct iwl_priv *priv) | |||
2551 | /* restore RXON assoc */ | 2650 | /* restore RXON assoc */ |
2552 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 2651 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
2553 | iwlcore_commit_rxon(priv); | 2652 | iwlcore_commit_rxon(priv); |
2653 | iwl_reset_qos(priv); | ||
2554 | spin_lock_irqsave(&priv->lock, flags); | 2654 | spin_lock_irqsave(&priv->lock, flags); |
2555 | iwl_activate_qos(priv, 1); | 2655 | iwl_activate_qos(priv, 1); |
2556 | spin_unlock_irqrestore(&priv->lock, flags); | 2656 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -2646,6 +2746,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
2646 | } | 2746 | } |
2647 | 2747 | ||
2648 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, | 2748 | static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, |
2749 | struct ieee80211_vif *vif, | ||
2649 | enum ieee80211_ampdu_mlme_action action, | 2750 | enum ieee80211_ampdu_mlme_action action, |
2650 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) | 2751 | struct ieee80211_sta *sta, u16 tid, u16 *ssn) |
2651 | { | 2752 | { |
@@ -2699,6 +2800,45 @@ static int iwl_mac_get_stats(struct ieee80211_hw *hw, | |||
2699 | return 0; | 2800 | return 0; |
2700 | } | 2801 | } |
2701 | 2802 | ||
2803 | static void iwl_mac_sta_notify(struct ieee80211_hw *hw, | ||
2804 | struct ieee80211_vif *vif, | ||
2805 | enum sta_notify_cmd cmd, | ||
2806 | struct ieee80211_sta *sta) | ||
2807 | { | ||
2808 | struct iwl_priv *priv = hw->priv; | ||
2809 | struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; | ||
2810 | int sta_id; | ||
2811 | |||
2812 | /* | ||
2813 | * TODO: We really should use this callback to | ||
2814 | * actually maintain the station table in | ||
2815 | * the device. | ||
2816 | */ | ||
2817 | |||
2818 | switch (cmd) { | ||
2819 | case STA_NOTIFY_ADD: | ||
2820 | atomic_set(&sta_priv->pending_frames, 0); | ||
2821 | if (vif->type == NL80211_IFTYPE_AP) | ||
2822 | sta_priv->client = true; | ||
2823 | break; | ||
2824 | case STA_NOTIFY_SLEEP: | ||
2825 | WARN_ON(!sta_priv->client); | ||
2826 | sta_priv->asleep = true; | ||
2827 | if (atomic_read(&sta_priv->pending_frames) > 0) | ||
2828 | ieee80211_sta_block_awake(hw, sta, true); | ||
2829 | break; | ||
2830 | case STA_NOTIFY_AWAKE: | ||
2831 | WARN_ON(!sta_priv->client); | ||
2832 | sta_priv->asleep = false; | ||
2833 | sta_id = iwl_find_station(priv, sta->addr); | ||
2834 | if (sta_id != IWL_INVALID_STATION) | ||
2835 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
2836 | break; | ||
2837 | default: | ||
2838 | break; | ||
2839 | } | ||
2840 | } | ||
2841 | |||
2702 | /***************************************************************************** | 2842 | /***************************************************************************** |
2703 | * | 2843 | * |
2704 | * sysfs attributes | 2844 | * sysfs attributes |
@@ -2893,7 +3033,7 @@ static ssize_t show_statistics(struct device *d, | |||
2893 | return -EAGAIN; | 3033 | return -EAGAIN; |
2894 | 3034 | ||
2895 | mutex_lock(&priv->mutex); | 3035 | mutex_lock(&priv->mutex); |
2896 | rc = iwl_send_statistics_request(priv, 0); | 3036 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); |
2897 | mutex_unlock(&priv->mutex); | 3037 | mutex_unlock(&priv->mutex); |
2898 | 3038 | ||
2899 | if (rc) { | 3039 | if (rc) { |
@@ -3045,10 +3185,6 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3045 | priv->band = IEEE80211_BAND_2GHZ; | 3185 | priv->band = IEEE80211_BAND_2GHZ; |
3046 | 3186 | ||
3047 | priv->iw_mode = NL80211_IFTYPE_STATION; | 3187 | priv->iw_mode = NL80211_IFTYPE_STATION; |
3048 | if (priv->cfg->support_sm_ps) | ||
3049 | priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DYNAMIC; | ||
3050 | else | ||
3051 | priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; | ||
3052 | 3188 | ||
3053 | /* Choose which receivers/antennas to use */ | 3189 | /* Choose which receivers/antennas to use */ |
3054 | if (priv->cfg->ops->hcmd->set_rxon_chain) | 3190 | if (priv->cfg->ops->hcmd->set_rxon_chain) |
@@ -3130,7 +3266,8 @@ static struct ieee80211_ops iwl_hw_ops = { | |||
3130 | .reset_tsf = iwl_mac_reset_tsf, | 3266 | .reset_tsf = iwl_mac_reset_tsf, |
3131 | .bss_info_changed = iwl_bss_info_changed, | 3267 | .bss_info_changed = iwl_bss_info_changed, |
3132 | .ampdu_action = iwl_mac_ampdu_action, | 3268 | .ampdu_action = iwl_mac_ampdu_action, |
3133 | .hw_scan = iwl_mac_hw_scan | 3269 | .hw_scan = iwl_mac_hw_scan, |
3270 | .sta_notify = iwl_mac_sta_notify, | ||
3134 | }; | 3271 | }; |
3135 | 3272 | ||
3136 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 3273 | static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
@@ -3454,23 +3591,63 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3454 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, | 3591 | {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, |
3455 | #endif /* CONFIG_IWL4965 */ | 3592 | #endif /* CONFIG_IWL4965 */ |
3456 | #ifdef CONFIG_IWL5000 | 3593 | #ifdef CONFIG_IWL5000 |
3457 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)}, | 3594 | /* 5100 Series WiFi */ |
3458 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)}, | 3595 | {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ |
3459 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, | 3596 | {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3460 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, | 3597 | {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ |
3461 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, | 3598 | {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3462 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, | 3599 | {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */ |
3463 | {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)}, | 3600 | {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3464 | {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)}, | 3601 | {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */ |
3465 | {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)}, | 3602 | {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3466 | {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)}, | 3603 | {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */ |
3467 | /* 5350 WiFi/WiMax */ | 3604 | {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3468 | {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, | 3605 | {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */ |
3469 | {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, | 3606 | {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */ |
3470 | {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, | 3607 | {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */ |
3471 | /* 5150 Wifi/WiMax */ | 3608 | {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */ |
3472 | {IWL_PCI_DEVICE(0x423C, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3609 | {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */ |
3473 | {IWL_PCI_DEVICE(0x423D, PCI_ANY_ID, iwl5150_agn_cfg)}, | 3610 | {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */ |
3611 | {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */ | ||
3612 | {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */ | ||
3613 | {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */ | ||
3614 | {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */ | ||
3615 | {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */ | ||
3616 | {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */ | ||
3617 | {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */ | ||
3618 | {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */ | ||
3619 | |||
3620 | /* 5300 Series WiFi */ | ||
3621 | {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3622 | {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3623 | {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3624 | {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3625 | {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3626 | {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3627 | {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3628 | {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3629 | {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3630 | {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3631 | {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */ | ||
3632 | {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */ | ||
3633 | |||
3634 | /* 5350 Series WiFi/WiMax */ | ||
3635 | {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3636 | {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3637 | {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */ | ||
3638 | |||
3639 | /* 5150 Series Wifi/WiMax */ | ||
3640 | {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3641 | {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3642 | {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */ | ||
3643 | {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ | ||
3644 | {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3645 | {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3646 | |||
3647 | {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ | ||
3648 | {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ | ||
3649 | {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */ | ||
3650 | {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */ | ||
3474 | 3651 | ||
3475 | /* 6x00 Series */ | 3652 | /* 6x00 Series */ |
3476 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, | 3653 | {IWL_PCI_DEVICE(0x422B, 0x1101, iwl6000_3agn_cfg)}, |
@@ -3485,13 +3662,10 @@ static struct pci_device_id iwl_hw_card_ids[] = { | |||
3485 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, | 3662 | {IWL_PCI_DEVICE(0x4239, 0x1316, iwl6000i_2abg_cfg)}, |
3486 | 3663 | ||
3487 | /* 6x50 WiFi/WiMax Series */ | 3664 | /* 6x50 WiFi/WiMax Series */ |
3488 | {IWL_PCI_DEVICE(0x0086, 0x1101, iwl6050_3agn_cfg)}, | ||
3489 | {IWL_PCI_DEVICE(0x0086, 0x1121, iwl6050_3agn_cfg)}, | ||
3490 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, | 3665 | {IWL_PCI_DEVICE(0x0087, 0x1301, iwl6050_2agn_cfg)}, |
3491 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, | 3666 | {IWL_PCI_DEVICE(0x0087, 0x1306, iwl6050_2abg_cfg)}, |
3492 | {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, | 3667 | {IWL_PCI_DEVICE(0x0087, 0x1321, iwl6050_2agn_cfg)}, |
3493 | {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, | 3668 | {IWL_PCI_DEVICE(0x0087, 0x1326, iwl6050_2abg_cfg)}, |
3494 | {IWL_PCI_DEVICE(0x0088, 0x1111, iwl6050_3agn_cfg)}, | ||
3495 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, | 3669 | {IWL_PCI_DEVICE(0x0089, 0x1311, iwl6050_2agn_cfg)}, |
3496 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, | 3670 | {IWL_PCI_DEVICE(0x0089, 0x1316, iwl6050_2abg_cfg)}, |
3497 | 3671 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index d994de7438d8..95a57b36a7ea 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -900,7 +900,7 @@ void iwl_reset_run_time_calib(struct iwl_priv *priv) | |||
900 | 900 | ||
901 | /* Ask for statistics now, the uCode will send notification | 901 | /* Ask for statistics now, the uCode will send notification |
902 | * periodically after association */ | 902 | * periodically after association */ |
903 | iwl_send_statistics_request(priv, CMD_ASYNC); | 903 | iwl_send_statistics_request(priv, CMD_ASYNC, true); |
904 | } | 904 | } |
905 | EXPORT_SYMBOL(iwl_reset_run_time_calib); | 905 | EXPORT_SYMBOL(iwl_reset_run_time_calib); |
906 | 906 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 2857287be4fd..e91507531923 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -977,6 +977,7 @@ struct iwl_qosparam_cmd { | |||
977 | #define STA_MODIFY_TX_RATE_MSK 0x04 | 977 | #define STA_MODIFY_TX_RATE_MSK 0x04 |
978 | #define STA_MODIFY_ADDBA_TID_MSK 0x08 | 978 | #define STA_MODIFY_ADDBA_TID_MSK 0x08 |
979 | #define STA_MODIFY_DELBA_TID_MSK 0x10 | 979 | #define STA_MODIFY_DELBA_TID_MSK 0x10 |
980 | #define STA_MODIFY_SLEEP_TX_COUNT_MSK 0x20 | ||
980 | 981 | ||
981 | /* Receiver address (actually, Rx station's index into station table), | 982 | /* Receiver address (actually, Rx station's index into station table), |
982 | * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ | 983 | * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ |
@@ -1107,7 +1108,14 @@ struct iwl4965_addsta_cmd { | |||
1107 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ | 1108 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ |
1108 | __le16 add_immediate_ba_ssn; | 1109 | __le16 add_immediate_ba_ssn; |
1109 | 1110 | ||
1110 | __le32 reserved2; | 1111 | /* |
1112 | * Number of packets OK to transmit to station even though | ||
1113 | * it is asleep -- used to synchronise PS-poll and u-APSD | ||
1114 | * responses while ucode keeps track of STA sleep state. | ||
1115 | */ | ||
1116 | __le16 sleep_tx_count; | ||
1117 | |||
1118 | __le16 reserved2; | ||
1111 | } __attribute__ ((packed)); | 1119 | } __attribute__ ((packed)); |
1112 | 1120 | ||
1113 | /* 5000 */ | 1121 | /* 5000 */ |
@@ -1138,7 +1146,14 @@ struct iwl_addsta_cmd { | |||
1138 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ | 1146 | * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ |
1139 | __le16 add_immediate_ba_ssn; | 1147 | __le16 add_immediate_ba_ssn; |
1140 | 1148 | ||
1141 | __le32 reserved2; | 1149 | /* |
1150 | * Number of packets OK to transmit to station even though | ||
1151 | * it is asleep -- used to synchronise PS-poll and u-APSD | ||
1152 | * responses while ucode keeps track of STA sleep state. | ||
1153 | */ | ||
1154 | __le16 sleep_tx_count; | ||
1155 | |||
1156 | __le16 reserved2; | ||
1142 | } __attribute__ ((packed)); | 1157 | } __attribute__ ((packed)); |
1143 | 1158 | ||
1144 | 1159 | ||
@@ -1690,6 +1705,21 @@ enum { | |||
1690 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ | 1705 | TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ |
1691 | }; | 1706 | }; |
1692 | 1707 | ||
1708 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | ||
1709 | { | ||
1710 | status &= TX_STATUS_MSK; | ||
1711 | |||
1712 | switch (status) { | ||
1713 | case TX_STATUS_SUCCESS: | ||
1714 | case TX_STATUS_DIRECT_DONE: | ||
1715 | return IEEE80211_TX_STAT_ACK; | ||
1716 | case TX_STATUS_FAIL_DEST_PS: | ||
1717 | return IEEE80211_TX_STAT_TX_FILTERED; | ||
1718 | default: | ||
1719 | return 0; | ||
1720 | } | ||
1721 | } | ||
1722 | |||
1693 | static inline bool iwl_is_tx_success(u32 status) | 1723 | static inline bool iwl_is_tx_success(u32 status) |
1694 | { | 1724 | { |
1695 | status &= TX_STATUS_MSK; | 1725 | status &= TX_STATUS_MSK; |
@@ -3071,6 +3101,10 @@ struct statistics_general { | |||
3071 | __le32 reserved3; | 3101 | __le32 reserved3; |
3072 | } __attribute__ ((packed)); | 3102 | } __attribute__ ((packed)); |
3073 | 3103 | ||
3104 | #define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0) | ||
3105 | #define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1) | ||
3106 | #define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2) | ||
3107 | |||
3074 | /* | 3108 | /* |
3075 | * REPLY_STATISTICS_CMD = 0x9c, | 3109 | * REPLY_STATISTICS_CMD = 0x9c, |
3076 | * 3945 and 4965 identical. | 3110 | * 3945 and 4965 identical. |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 6b18aab8fa9b..574d36658702 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -209,6 +209,7 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) | |||
209 | } | 209 | } |
210 | return ant; | 210 | return ant; |
211 | } | 211 | } |
212 | EXPORT_SYMBOL(iwl_toggle_tx_ant); | ||
212 | 213 | ||
213 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; | 214 | const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; |
214 | EXPORT_SYMBOL(iwl_bcast_addr); | 215 | EXPORT_SYMBOL(iwl_bcast_addr); |
@@ -255,7 +256,10 @@ int iwl_hw_nic_init(struct iwl_priv *priv) | |||
255 | /* nic_init */ | 256 | /* nic_init */ |
256 | spin_lock_irqsave(&priv->lock, flags); | 257 | spin_lock_irqsave(&priv->lock, flags); |
257 | priv->cfg->ops->lib->apm_ops.init(priv); | 258 | priv->cfg->ops->lib->apm_ops.init(priv); |
258 | iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); | 259 | |
260 | /* Set interrupt coalescing timer to 512 usecs */ | ||
261 | iwl_write8(priv, CSR_INT_COALESCING, 512 / 32); | ||
262 | |||
259 | spin_unlock_irqrestore(&priv->lock, flags); | 263 | spin_unlock_irqrestore(&priv->lock, flags); |
260 | 264 | ||
261 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); | 265 | ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); |
@@ -446,13 +450,8 @@ static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, | |||
446 | if (priv->cfg->ht_greenfield_support) | 450 | if (priv->cfg->ht_greenfield_support) |
447 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; | 451 | ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; |
448 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; | 452 | ht_info->cap |= IEEE80211_HT_CAP_SGI_20; |
449 | if (priv->cfg->support_sm_ps) | 453 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & |
450 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & | 454 | (priv->cfg->sm_ps_mode << 2)); |
451 | (WLAN_HT_CAP_SM_PS_DYNAMIC << 2)); | ||
452 | else | ||
453 | ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & | ||
454 | (WLAN_HT_CAP_SM_PS_DISABLED << 2)); | ||
455 | |||
456 | max_bit_rate = MAX_BIT_RATE_20_MHZ; | 455 | max_bit_rate = MAX_BIT_RATE_20_MHZ; |
457 | if (priv->hw_params.ht40_channel & BIT(band)) { | 456 | if (priv->hw_params.ht40_channel & BIT(band)) { |
458 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 457 | ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
@@ -1007,25 +1006,23 @@ static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) | |||
1007 | int idle_cnt = active_cnt; | 1006 | int idle_cnt = active_cnt; |
1008 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); | 1007 | bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); |
1009 | 1008 | ||
1010 | if (priv->cfg->support_sm_ps) { | 1009 | /* # Rx chains when idling and maybe trying to save power */ |
1011 | /* # Rx chains when idling and maybe trying to save power */ | 1010 | switch (priv->cfg->sm_ps_mode) { |
1012 | switch (priv->current_ht_config.sm_ps) { | 1011 | case WLAN_HT_CAP_SM_PS_STATIC: |
1013 | case WLAN_HT_CAP_SM_PS_STATIC: | 1012 | idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; |
1014 | case WLAN_HT_CAP_SM_PS_DYNAMIC: | 1013 | break; |
1015 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : | 1014 | case WLAN_HT_CAP_SM_PS_DYNAMIC: |
1016 | IWL_NUM_IDLE_CHAINS_SINGLE; | 1015 | idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : |
1017 | break; | 1016 | IWL_NUM_IDLE_CHAINS_SINGLE; |
1018 | case WLAN_HT_CAP_SM_PS_DISABLED: | 1017 | break; |
1019 | idle_cnt = (is_cam) ? active_cnt : | 1018 | case WLAN_HT_CAP_SM_PS_DISABLED: |
1020 | IWL_NUM_IDLE_CHAINS_SINGLE; | 1019 | break; |
1021 | break; | 1020 | case WLAN_HT_CAP_SM_PS_INVALID: |
1022 | case WLAN_HT_CAP_SM_PS_INVALID: | 1021 | default: |
1023 | default: | 1022 | IWL_ERR(priv, "invalid sm_ps mode %u\n", |
1024 | IWL_ERR(priv, "invalid sm_ps mode %d\n", | 1023 | priv->cfg->sm_ps_mode); |
1025 | priv->current_ht_config.sm_ps); | 1024 | WARN_ON(1); |
1026 | WARN_ON(1); | 1025 | break; |
1027 | break; | ||
1028 | } | ||
1029 | } | 1026 | } |
1030 | return idle_cnt; | 1027 | return idle_cnt; |
1031 | } | 1028 | } |
@@ -1365,12 +1362,11 @@ void iwl_irq_handle_error(struct iwl_priv *priv) | |||
1365 | /* Cancel currently queued command. */ | 1362 | /* Cancel currently queued command. */ |
1366 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); | 1363 | clear_bit(STATUS_HCMD_ACTIVE, &priv->status); |
1367 | 1364 | ||
1365 | priv->cfg->ops->lib->dump_nic_error_log(priv); | ||
1366 | priv->cfg->ops->lib->dump_nic_event_log(priv, false); | ||
1368 | #ifdef CONFIG_IWLWIFI_DEBUG | 1367 | #ifdef CONFIG_IWLWIFI_DEBUG |
1369 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) { | 1368 | if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) |
1370 | priv->cfg->ops->lib->dump_nic_error_log(priv); | ||
1371 | priv->cfg->ops->lib->dump_nic_event_log(priv); | ||
1372 | iwl_print_rx_config_cmd(priv); | 1369 | iwl_print_rx_config_cmd(priv); |
1373 | } | ||
1374 | #endif | 1370 | #endif |
1375 | 1371 | ||
1376 | wake_up_interruptible(&priv->wait_command_queue); | 1372 | wake_up_interruptible(&priv->wait_command_queue); |
@@ -1991,16 +1987,21 @@ int iwl_send_bt_config(struct iwl_priv *priv) | |||
1991 | } | 1987 | } |
1992 | EXPORT_SYMBOL(iwl_send_bt_config); | 1988 | EXPORT_SYMBOL(iwl_send_bt_config); |
1993 | 1989 | ||
1994 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) | 1990 | int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear) |
1995 | { | 1991 | { |
1996 | u32 stat_flags = 0; | 1992 | struct iwl_statistics_cmd statistics_cmd = { |
1997 | struct iwl_host_cmd cmd = { | 1993 | .configuration_flags = |
1998 | .id = REPLY_STATISTICS_CMD, | 1994 | clear ? IWL_STATS_CONF_CLEAR_STATS : 0, |
1999 | .flags = flags, | ||
2000 | .len = sizeof(stat_flags), | ||
2001 | .data = (u8 *) &stat_flags, | ||
2002 | }; | 1995 | }; |
2003 | return iwl_send_cmd(priv, &cmd); | 1996 | |
1997 | if (flags & CMD_ASYNC) | ||
1998 | return iwl_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD, | ||
1999 | sizeof(struct iwl_statistics_cmd), | ||
2000 | &statistics_cmd, NULL); | ||
2001 | else | ||
2002 | return iwl_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, | ||
2003 | sizeof(struct iwl_statistics_cmd), | ||
2004 | &statistics_cmd); | ||
2004 | } | 2005 | } |
2005 | EXPORT_SYMBOL(iwl_send_statistics_request); | 2006 | EXPORT_SYMBOL(iwl_send_statistics_request); |
2006 | 2007 | ||
@@ -2477,6 +2478,16 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2477 | } else { | 2478 | } else { |
2478 | priv->assoc_id = 0; | 2479 | priv->assoc_id = 0; |
2479 | iwl_led_disassociate(priv); | 2480 | iwl_led_disassociate(priv); |
2481 | |||
2482 | /* | ||
2483 | * inform the ucode that there is no longer an | ||
2484 | * association and that no more packets should be | ||
2485 | * send | ||
2486 | */ | ||
2487 | priv->staging_rxon.filter_flags &= | ||
2488 | ~RXON_FILTER_ASSOC_MSK; | ||
2489 | priv->staging_rxon.assoc_id = 0; | ||
2490 | iwlcore_commit_rxon(priv); | ||
2480 | } | 2491 | } |
2481 | } | 2492 | } |
2482 | 2493 | ||
@@ -2492,6 +2503,14 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, | |||
2492 | } | 2503 | } |
2493 | } | 2504 | } |
2494 | 2505 | ||
2506 | if ((changes & BSS_CHANGED_BEACON_ENABLED) && | ||
2507 | vif->bss_conf.enable_beacon) { | ||
2508 | memcpy(priv->staging_rxon.bssid_addr, | ||
2509 | bss_conf->bssid, ETH_ALEN); | ||
2510 | memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); | ||
2511 | iwlcore_config_ap(priv); | ||
2512 | } | ||
2513 | |||
2495 | mutex_unlock(&priv->mutex); | 2514 | mutex_unlock(&priv->mutex); |
2496 | 2515 | ||
2497 | IWL_DEBUG_MAC80211(priv, "leave\n"); | 2516 | IWL_DEBUG_MAC80211(priv, "leave\n"); |
@@ -3070,15 +3089,11 @@ const char *get_ctrl_string(int cmd) | |||
3070 | } | 3089 | } |
3071 | } | 3090 | } |
3072 | 3091 | ||
3073 | void iwl_clear_tx_stats(struct iwl_priv *priv) | 3092 | void iwl_clear_traffic_stats(struct iwl_priv *priv) |
3074 | { | 3093 | { |
3075 | memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); | 3094 | memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); |
3076 | |||
3077 | } | ||
3078 | |||
3079 | void iwl_clear_rx_stats(struct iwl_priv *priv) | ||
3080 | { | ||
3081 | memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); | 3095 | memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); |
3096 | priv->led_tpt = 0; | ||
3082 | } | 3097 | } |
3083 | 3098 | ||
3084 | /* | 3099 | /* |
@@ -3171,6 +3186,7 @@ void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) | |||
3171 | stats->data_cnt++; | 3186 | stats->data_cnt++; |
3172 | stats->data_bytes += len; | 3187 | stats->data_bytes += len; |
3173 | } | 3188 | } |
3189 | iwl_leds_background(priv); | ||
3174 | } | 3190 | } |
3175 | EXPORT_SYMBOL(iwl_update_stats); | 3191 | EXPORT_SYMBOL(iwl_update_stats); |
3176 | #endif | 3192 | #endif |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 3f97036ac29b..cf7d3df0744e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -167,7 +167,7 @@ struct iwl_lib_ops { | |||
167 | int (*is_valid_rtc_data_addr)(u32 addr); | 167 | int (*is_valid_rtc_data_addr)(u32 addr); |
168 | /* 1st ucode load */ | 168 | /* 1st ucode load */ |
169 | int (*load_ucode)(struct iwl_priv *priv); | 169 | int (*load_ucode)(struct iwl_priv *priv); |
170 | void (*dump_nic_event_log)(struct iwl_priv *priv); | 170 | void (*dump_nic_event_log)(struct iwl_priv *priv, bool full_log); |
171 | void (*dump_nic_error_log)(struct iwl_priv *priv); | 171 | void (*dump_nic_error_log)(struct iwl_priv *priv); |
172 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); | 172 | int (*set_channel_switch)(struct iwl_priv *priv, u16 channel); |
173 | /* power management */ | 173 | /* power management */ |
@@ -228,7 +228,7 @@ struct iwl_mod_params { | |||
228 | * @chain_noise_num_beacons: number of beacons used to compute chain noise | 228 | * @chain_noise_num_beacons: number of beacons used to compute chain noise |
229 | * @adv_thermal_throttle: support advance thermal throttle | 229 | * @adv_thermal_throttle: support advance thermal throttle |
230 | * @support_ct_kill_exit: support ct kill exit condition | 230 | * @support_ct_kill_exit: support ct kill exit condition |
231 | * @support_sm_ps: support spatial multiplexing power save | 231 | * @sm_ps_mode: spatial multiplexing power save mode |
232 | * @support_wimax_coexist: support wimax/wifi co-exist | 232 | * @support_wimax_coexist: support wimax/wifi co-exist |
233 | * | 233 | * |
234 | * We enable the driver to be backward compatible wrt API version. The | 234 | * We enable the driver to be backward compatible wrt API version. The |
@@ -285,7 +285,7 @@ struct iwl_cfg { | |||
285 | const bool supports_idle; | 285 | const bool supports_idle; |
286 | bool adv_thermal_throttle; | 286 | bool adv_thermal_throttle; |
287 | bool support_ct_kill_exit; | 287 | bool support_ct_kill_exit; |
288 | bool support_sm_ps; | 288 | u8 sm_ps_mode; |
289 | const bool support_wimax_coexist; | 289 | const bool support_wimax_coexist; |
290 | }; | 290 | }; |
291 | 291 | ||
@@ -353,8 +353,7 @@ void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, | |||
353 | u16 length, struct ieee80211_hdr *header); | 353 | u16 length, struct ieee80211_hdr *header); |
354 | const char *get_mgmt_string(int cmd); | 354 | const char *get_mgmt_string(int cmd); |
355 | const char *get_ctrl_string(int cmd); | 355 | const char *get_ctrl_string(int cmd); |
356 | void iwl_clear_tx_stats(struct iwl_priv *priv); | 356 | void iwl_clear_traffic_stats(struct iwl_priv *priv); |
357 | void iwl_clear_rx_stats(struct iwl_priv *priv); | ||
358 | void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, | 357 | void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, |
359 | u16 len); | 358 | u16 len); |
360 | #else | 359 | #else |
@@ -390,6 +389,7 @@ static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, | |||
390 | /* data */ | 389 | /* data */ |
391 | stats->data_bytes += len; | 390 | stats->data_bytes += len; |
392 | } | 391 | } |
392 | iwl_leds_background(priv); | ||
393 | } | 393 | } |
394 | #endif | 394 | #endif |
395 | /***************************************************** | 395 | /***************************************************** |
@@ -425,6 +425,8 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, | |||
425 | struct iwl_rx_mem_buffer *rxb); | 425 | struct iwl_rx_mem_buffer *rxb); |
426 | void iwl_rx_statistics(struct iwl_priv *priv, | 426 | void iwl_rx_statistics(struct iwl_priv *priv, |
427 | struct iwl_rx_mem_buffer *rxb); | 427 | struct iwl_rx_mem_buffer *rxb); |
428 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
429 | struct iwl_rx_mem_buffer *rxb); | ||
428 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); | 430 | void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); |
429 | 431 | ||
430 | /* TX helpers */ | 432 | /* TX helpers */ |
@@ -576,19 +578,11 @@ int iwl_pci_resume(struct pci_dev *pdev); | |||
576 | /***************************************************** | 578 | /***************************************************** |
577 | * Error Handling Debugging | 579 | * Error Handling Debugging |
578 | ******************************************************/ | 580 | ******************************************************/ |
579 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
580 | void iwl_dump_nic_event_log(struct iwl_priv *priv); | ||
581 | void iwl_dump_nic_error_log(struct iwl_priv *priv); | 581 | void iwl_dump_nic_error_log(struct iwl_priv *priv); |
582 | void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log); | ||
583 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
582 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); | 584 | void iwl_print_rx_config_cmd(struct iwl_priv *priv); |
583 | #else | 585 | #else |
584 | static inline void iwl_dump_nic_event_log(struct iwl_priv *priv) | ||
585 | { | ||
586 | } | ||
587 | |||
588 | static inline void iwl_dump_nic_error_log(struct iwl_priv *priv) | ||
589 | { | ||
590 | } | ||
591 | |||
592 | static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv) | 586 | static inline void iwl_print_rx_config_cmd(struct iwl_priv *priv) |
593 | { | 587 | { |
594 | } | 588 | } |
@@ -669,7 +663,8 @@ static inline int iwl_is_ready_rf(struct iwl_priv *priv) | |||
669 | 663 | ||
670 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); | 664 | extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); |
671 | extern int iwl_send_bt_config(struct iwl_priv *priv); | 665 | extern int iwl_send_bt_config(struct iwl_priv *priv); |
672 | extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); | 666 | extern int iwl_send_statistics_request(struct iwl_priv *priv, |
667 | u8 flags, bool clear); | ||
673 | extern int iwl_verify_ucode(struct iwl_priv *priv); | 668 | extern int iwl_verify_ucode(struct iwl_priv *priv); |
674 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, | 669 | extern int iwl_send_lq_cmd(struct iwl_priv *priv, |
675 | struct iwl_link_quality_cmd *lq, u8 flags); | 670 | struct iwl_link_quality_cmd *lq, u8 flags); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h index b6ed5a3147a1..a7bfae01f19b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ b/drivers/net/wireless/iwlwifi/iwl-csr.h | |||
@@ -62,11 +62,29 @@ | |||
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | #ifndef __iwl_csr_h__ | 63 | #ifndef __iwl_csr_h__ |
64 | #define __iwl_csr_h__ | 64 | #define __iwl_csr_h__ |
65 | /*=== CSR (control and status registers) ===*/ | 65 | /* |
66 | * CSR (control and status registers) | ||
67 | * | ||
68 | * CSR registers are mapped directly into PCI bus space, and are accessible | ||
69 | * whenever platform supplies power to device, even when device is in | ||
70 | * low power states due to driver-invoked device resets | ||
71 | * (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes. | ||
72 | * | ||
73 | * Use iwl_write32() and iwl_read32() family to access these registers; | ||
74 | * these provide simple PCI bus access, without waking up the MAC. | ||
75 | * Do not use iwl_write_direct32() family for these registers; | ||
76 | * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ. | ||
77 | * The MAC (uCode processor, etc.) does not need to be powered up for accessing | ||
78 | * the CSR registers. | ||
79 | * | ||
80 | * NOTE: Newer devices using one-time-programmable (OTP) memory | ||
81 | * require device to be awake in order to read this memory | ||
82 | * via CSR_EEPROM and CSR_OTP registers | ||
83 | */ | ||
66 | #define CSR_BASE (0x000) | 84 | #define CSR_BASE (0x000) |
67 | 85 | ||
68 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ | 86 | #define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ |
69 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ | 87 | #define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ |
70 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ | 88 | #define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ |
71 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ | 89 | #define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ |
72 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ | 90 | #define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ |
@@ -74,42 +92,65 @@ | |||
74 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ | 92 | #define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ |
75 | #define CSR_GP_CNTRL (CSR_BASE+0x024) | 93 | #define CSR_GP_CNTRL (CSR_BASE+0x024) |
76 | 94 | ||
95 | /* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */ | ||
96 | #define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) | ||
97 | |||
77 | /* | 98 | /* |
78 | * Hardware revision info | 99 | * Hardware revision info |
79 | * Bit fields: | 100 | * Bit fields: |
80 | * 31-8: Reserved | 101 | * 31-8: Reserved |
81 | * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 | 102 | * 7-4: Type of device: see CSR_HW_REV_TYPE_xxx definitions |
82 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D | 103 | * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D |
83 | * 1-0: "Dash" value, as in A-1, etc. | 104 | * 1-0: "Dash" (-) value, as in A-1, etc. |
84 | * | 105 | * |
85 | * NOTE: Revision step affects calculation of CCK txpower for 4965. | 106 | * NOTE: Revision step affects calculation of CCK txpower for 4965. |
107 | * NOTE: See also CSR_HW_REV_WA_REG (work-around for bug in 4965). | ||
86 | */ | 108 | */ |
87 | #define CSR_HW_REV (CSR_BASE+0x028) | 109 | #define CSR_HW_REV (CSR_BASE+0x028) |
88 | 110 | ||
89 | /* EEPROM reads */ | 111 | /* |
112 | * EEPROM and OTP (one-time-programmable) memory reads | ||
113 | * | ||
114 | * NOTE: For (newer) devices using OTP, device must be awake, initialized via | ||
115 | * apm_ops.init() in order to read. Older devices (3945/4965/5000) | ||
116 | * use EEPROM and do not require this. | ||
117 | */ | ||
90 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) | 118 | #define CSR_EEPROM_REG (CSR_BASE+0x02c) |
91 | #define CSR_EEPROM_GP (CSR_BASE+0x030) | 119 | #define CSR_EEPROM_GP (CSR_BASE+0x030) |
92 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) | 120 | #define CSR_OTP_GP_REG (CSR_BASE+0x034) |
121 | |||
93 | #define CSR_GIO_REG (CSR_BASE+0x03C) | 122 | #define CSR_GIO_REG (CSR_BASE+0x03C) |
94 | #define CSR_GP_UCODE_REG (CSR_BASE+0x048) | 123 | #define CSR_GP_UCODE_REG (CSR_BASE+0x048) |
95 | #define CSR_GP_DRIVER_REG (CSR_BASE+0x050) | 124 | #define CSR_GP_DRIVER_REG (CSR_BASE+0x050) |
125 | |||
126 | /* | ||
127 | * UCODE-DRIVER GP (general purpose) mailbox registers. | ||
128 | * SET/CLR registers set/clear bit(s) if "1" is written. | ||
129 | */ | ||
96 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) | 130 | #define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) |
97 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) | 131 | #define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) |
98 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) | 132 | #define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) |
99 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) | 133 | #define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) |
134 | |||
100 | #define CSR_LED_REG (CSR_BASE+0x094) | 135 | #define CSR_LED_REG (CSR_BASE+0x094) |
101 | #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) | 136 | #define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) |
137 | |||
138 | /* GIO Chicken Bits (PCI Express bus link power management) */ | ||
102 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) | 139 | #define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) |
103 | 140 | ||
104 | #define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) | ||
105 | /* Analog phase-lock-loop configuration */ | 141 | /* Analog phase-lock-loop configuration */ |
106 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) | 142 | #define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) |
143 | |||
107 | /* | 144 | /* |
108 | * Indicates hardware rev, to determine CCK backoff for txpower calculation. | 145 | * CSR Hardware Revision Workaround Register. Indicates hardware rev; |
146 | * "step" determines CCK backoff for txpower calculation. Used for 4965 only. | ||
147 | * See also CSR_HW_REV register. | ||
109 | * Bit fields: | 148 | * Bit fields: |
110 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step | 149 | * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step |
150 | * 1-0: "Dash" (-) value, as in C-1, etc. | ||
111 | */ | 151 | */ |
112 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) | 152 | #define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) |
153 | |||
113 | #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) | 154 | #define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) |
114 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) | 155 | #define CSR_DBG_LINK_PWR_MGMT_REG (CSR_BASE+0x250) |
115 | 156 | ||
@@ -126,14 +167,14 @@ | |||
126 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) | 167 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) |
127 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) | 168 | #define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) |
128 | 169 | ||
129 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) | 170 | #define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) |
130 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) | 171 | #define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) |
131 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) | 172 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */ |
132 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) | 173 | #define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */ |
133 | #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) | 174 | #define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */ |
134 | 175 | ||
135 | #define CSR_INT_PERIODIC_DIS (0x00) | 176 | #define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/ |
136 | #define CSR_INT_PERIODIC_ENA (0xFF) | 177 | #define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/ |
137 | 178 | ||
138 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), | 179 | /* interrupt flags in INTA, set by uCode or hardware (e.g. dma), |
139 | * acknowledged (reset) by host writing "1" to flagged bits. */ | 180 | * acknowledged (reset) by host writing "1" to flagged bits. */ |
@@ -198,7 +239,44 @@ | |||
198 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) | 239 | #define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) |
199 | #define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000) | 240 | #define CSR_RESET_LINK_PWR_MGMT_DISABLED (0x80000000) |
200 | 241 | ||
201 | /* GP (general purpose) CONTROL */ | 242 | /* |
243 | * GP (general purpose) CONTROL REGISTER | ||
244 | * Bit fields: | ||
245 | * 27: HW_RF_KILL_SW | ||
246 | * Indicates state of (platform's) hardware RF-Kill switch | ||
247 | * 26-24: POWER_SAVE_TYPE | ||
248 | * Indicates current power-saving mode: | ||
249 | * 000 -- No power saving | ||
250 | * 001 -- MAC power-down | ||
251 | * 010 -- PHY (radio) power-down | ||
252 | * 011 -- Error | ||
253 | * 9-6: SYS_CONFIG | ||
254 | * Indicates current system configuration, reflecting pins on chip | ||
255 | * as forced high/low by device circuit board. | ||
256 | * 4: GOING_TO_SLEEP | ||
257 | * Indicates MAC is entering a power-saving sleep power-down. | ||
258 | * Not a good time to access device-internal resources. | ||
259 | * 3: MAC_ACCESS_REQ | ||
260 | * Host sets this to request and maintain MAC wakeup, to allow host | ||
261 | * access to device-internal resources. Host must wait for | ||
262 | * MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR | ||
263 | * device registers. | ||
264 | * 2: INIT_DONE | ||
265 | * Host sets this to put device into fully operational D0 power mode. | ||
266 | * Host resets this after SW_RESET to put device into low power mode. | ||
267 | * 0: MAC_CLOCK_READY | ||
268 | * Indicates MAC (ucode processor, etc.) is powered up and can run. | ||
269 | * Internal resources are accessible. | ||
270 | * NOTE: This does not indicate that the processor is actually running. | ||
271 | * NOTE: This does not indicate that 4965 or 3945 has completed | ||
272 | * init or post-power-down restore of internal SRAM memory. | ||
273 | * Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that | ||
274 | * SRAM is restored and uCode is in normal operation mode. | ||
275 | * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and | ||
276 | * do not need to save/restore it. | ||
277 | * NOTE: After device reset, this bit remains "0" until host sets | ||
278 | * INIT_DONE | ||
279 | */ | ||
202 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) | 280 | #define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) |
203 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) | 281 | #define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) |
204 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) | 282 | #define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) |
@@ -231,28 +309,58 @@ | |||
231 | #define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000) | 309 | #define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000) |
232 | 310 | ||
233 | /* EEPROM GP */ | 311 | /* EEPROM GP */ |
234 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) | 312 | #define CSR_EEPROM_GP_VALID_MSK (0x00000007) /* signature */ |
235 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) | 313 | #define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) |
314 | #define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000) | ||
315 | #define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001) | ||
316 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002) | ||
317 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004) | ||
318 | |||
319 | /* One-time-programmable memory general purpose reg */ | ||
236 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ | 320 | #define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ |
237 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ | 321 | #define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ |
238 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ | 322 | #define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ |
239 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ | 323 | #define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ |
324 | |||
325 | /* GP REG */ | ||
240 | #define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */ | 326 | #define CSR_GP_REG_POWER_SAVE_STATUS_MSK (0x03000000) /* bit 24/25 */ |
241 | #define CSR_GP_REG_NO_POWER_SAVE (0x00000000) | 327 | #define CSR_GP_REG_NO_POWER_SAVE (0x00000000) |
242 | #define CSR_GP_REG_MAC_POWER_SAVE (0x01000000) | 328 | #define CSR_GP_REG_MAC_POWER_SAVE (0x01000000) |
243 | #define CSR_GP_REG_PHY_POWER_SAVE (0x02000000) | 329 | #define CSR_GP_REG_PHY_POWER_SAVE (0x02000000) |
244 | #define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000) | 330 | #define CSR_GP_REG_POWER_SAVE_ERROR (0x03000000) |
245 | 331 | ||
246 | /* EEPROM signature */ | ||
247 | #define CSR_EEPROM_GP_BAD_SIGNATURE_BOTH_EEP_AND_OTP (0x00000000) | ||
248 | #define CSR_EEPROM_GP_BAD_SIG_EEP_GOOD_SIG_OTP (0x00000001) | ||
249 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K (0x00000002) | ||
250 | #define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K (0x00000004) | ||
251 | 332 | ||
252 | /* CSR GIO */ | 333 | /* CSR GIO */ |
253 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) | 334 | #define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) |
254 | 335 | ||
255 | /* UCODE DRV GP */ | 336 | /* |
337 | * UCODE-DRIVER GP (general purpose) mailbox register 1 | ||
338 | * Host driver and uCode write and/or read this register to communicate with | ||
339 | * each other. | ||
340 | * Bit fields: | ||
341 | * 4: UCODE_DISABLE | ||
342 | * Host sets this to request permanent halt of uCode, same as | ||
343 | * sending CARD_STATE command with "halt" bit set. | ||
344 | * 3: CT_KILL_EXIT | ||
345 | * Host sets this to request exit from CT_KILL state, i.e. host thinks | ||
346 | * device temperature is low enough to continue normal operation. | ||
347 | * 2: CMD_BLOCKED | ||
348 | * Host sets this during RF KILL power-down sequence (HW, SW, CT KILL) | ||
349 | * to release uCode to clear all Tx and command queues, enter | ||
350 | * unassociated mode, and power down. | ||
351 | * NOTE: Some devices also use HBUS_TARG_MBX_C register for this bit. | ||
352 | * 1: SW_BIT_RFKILL | ||
353 | * Host sets this when issuing CARD_STATE command to request | ||
354 | * device sleep. | ||
355 | * 0: MAC_SLEEP | ||
356 | * uCode sets this when preparing a power-saving power-down. | ||
357 | * uCode resets this when power-up is complete and SRAM is sane. | ||
358 | * NOTE: 3945/4965 saves internal SRAM data to host when powering down, | ||
359 | * and must restore this data after powering back up. | ||
360 | * MAC_SLEEP is the best indication that restore is complete. | ||
361 | * Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and | ||
362 | * do not need to save/restore it. | ||
363 | */ | ||
256 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) | 364 | #define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) |
257 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) | 365 | #define CSR_UCODE_SW_BIT_RFKILL (0x00000002) |
258 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) | 366 | #define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) |
@@ -265,7 +373,7 @@ | |||
265 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) | 373 | #define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) |
266 | 374 | ||
267 | 375 | ||
268 | /* GI Chicken Bits */ | 376 | /* GIO Chicken Bits (PCI Express bus link power management) */ |
269 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) | 377 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) |
270 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) | 378 | #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) |
271 | 379 | ||
@@ -285,8 +393,23 @@ | |||
285 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) | 393 | #define CSR_DRAM_INT_TBL_ENABLE (1 << 31) |
286 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) | 394 | #define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) |
287 | 395 | ||
288 | /*=== HBUS (Host-side Bus) ===*/ | 396 | /* |
397 | * HBUS (Host-side Bus) | ||
398 | * | ||
399 | * HBUS registers are mapped directly into PCI bus space, but are used | ||
400 | * to indirectly access device's internal memory or registers that | ||
401 | * may be powered-down. | ||
402 | * | ||
403 | * Use iwl_write_direct32()/iwl_read_direct32() family for these registers; | ||
404 | * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ | ||
405 | * to make sure the MAC (uCode processor, etc.) is powered up for accessing | ||
406 | * internal resources. | ||
407 | * | ||
408 | * Do not use iwl_write32()/iwl_read32() family to access these registers; | ||
409 | * these provide only simple PCI bus access, without waking up the MAC. | ||
410 | */ | ||
289 | #define HBUS_BASE (0x400) | 411 | #define HBUS_BASE (0x400) |
412 | |||
290 | /* | 413 | /* |
291 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM | 414 | * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM |
292 | * structures, error log, event log, verifying uCode load). | 415 | * structures, error log, event log, verifying uCode load). |
@@ -301,6 +424,10 @@ | |||
301 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) | 424 | #define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) |
302 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) | 425 | #define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) |
303 | 426 | ||
427 | /* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */ | ||
428 | #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) | ||
429 | #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) | ||
430 | |||
304 | /* | 431 | /* |
305 | * Registers for accessing device's internal peripheral registers | 432 | * Registers for accessing device's internal peripheral registers |
306 | * (e.g. SCD, BSM, etc.). First write to address register, | 433 | * (e.g. SCD, BSM, etc.). First write to address register, |
@@ -315,16 +442,12 @@ | |||
315 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) | 442 | #define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) |
316 | 443 | ||
317 | /* | 444 | /* |
318 | * Per-Tx-queue write pointer (index, really!) (3945 and 4965). | 445 | * Per-Tx-queue write pointer (index, really!) |
319 | * Indicates index to next TFD that driver will fill (1 past latest filled). | 446 | * Indicates index to next TFD that driver will fill (1 past latest filled). |
320 | * Bit usage: | 447 | * Bit usage: |
321 | * 0-7: queue write index | 448 | * 0-7: queue write index |
322 | * 11-8: queue selector | 449 | * 11-8: queue selector |
323 | */ | 450 | */ |
324 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) | 451 | #define HBUS_TARG_WRPTR (HBUS_BASE+0x060) |
325 | #define HBUS_TARG_MBX_C (HBUS_BASE+0x030) | ||
326 | |||
327 | #define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) | ||
328 | |||
329 | 452 | ||
330 | #endif /* !__iwl_csr_h__ */ | 453 | #endif /* !__iwl_csr_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index 96c92eab692a..d61293ab67c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -107,6 +107,8 @@ struct iwl_debugfs { | |||
107 | struct dentry *file_chain_noise; | 107 | struct dentry *file_chain_noise; |
108 | struct dentry *file_tx_power; | 108 | struct dentry *file_tx_power; |
109 | struct dentry *file_power_save_status; | 109 | struct dentry *file_power_save_status; |
110 | struct dentry *file_clear_ucode_statistics; | ||
111 | struct dentry *file_clear_traffic_statistics; | ||
110 | } dbgfs_debug_files; | 112 | } dbgfs_debug_files; |
111 | u32 sram_offset; | 113 | u32 sram_offset; |
112 | u32 sram_len; | 114 | u32 sram_len; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c index 8784911fd56e..21e0f6699daf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c | |||
@@ -47,9 +47,9 @@ | |||
47 | goto err; \ | 47 | goto err; \ |
48 | } while (0) | 48 | } while (0) |
49 | 49 | ||
50 | #define DEBUGFS_ADD_FILE(name, parent) do { \ | 50 | #define DEBUGFS_ADD_FILE(name, parent, mode) do { \ |
51 | dbgfs->dbgfs_##parent##_files.file_##name = \ | 51 | dbgfs->dbgfs_##parent##_files.file_##name = \ |
52 | debugfs_create_file(#name, S_IWUSR | S_IRUSR, \ | 52 | debugfs_create_file(#name, mode, \ |
53 | dbgfs->dir_##parent, priv, \ | 53 | dbgfs->dir_##parent, priv, \ |
54 | &iwl_dbgfs_##name##_ops); \ | 54 | &iwl_dbgfs_##name##_ops); \ |
55 | if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ | 55 | if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ |
@@ -131,21 +131,22 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | |||
131 | 131 | ||
132 | int cnt; | 132 | int cnt; |
133 | ssize_t ret; | 133 | ssize_t ret; |
134 | const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX); | 134 | const size_t bufsz = 100 + |
135 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); | ||
135 | buf = kzalloc(bufsz, GFP_KERNEL); | 136 | buf = kzalloc(bufsz, GFP_KERNEL); |
136 | if (!buf) | 137 | if (!buf) |
137 | return -ENOMEM; | 138 | return -ENOMEM; |
138 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 139 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); |
139 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 140 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { |
140 | pos += scnprintf(buf + pos, bufsz - pos, | 141 | pos += scnprintf(buf + pos, bufsz - pos, |
141 | "\t%s\t\t: %u\n", | 142 | "\t%25s\t\t: %u\n", |
142 | get_mgmt_string(cnt), | 143 | get_mgmt_string(cnt), |
143 | priv->tx_stats.mgmt[cnt]); | 144 | priv->tx_stats.mgmt[cnt]); |
144 | } | 145 | } |
145 | pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); | 146 | pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); |
146 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 147 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { |
147 | pos += scnprintf(buf + pos, bufsz - pos, | 148 | pos += scnprintf(buf + pos, bufsz - pos, |
148 | "\t%s\t\t: %u\n", | 149 | "\t%25s\t\t: %u\n", |
149 | get_ctrl_string(cnt), | 150 | get_ctrl_string(cnt), |
150 | priv->tx_stats.ctrl[cnt]); | 151 | priv->tx_stats.ctrl[cnt]); |
151 | } | 152 | } |
@@ -159,7 +160,7 @@ static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, | |||
159 | return ret; | 160 | return ret; |
160 | } | 161 | } |
161 | 162 | ||
162 | static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file, | 163 | static ssize_t iwl_dbgfs_clear_traffic_statistics_write(struct file *file, |
163 | const char __user *user_buf, | 164 | const char __user *user_buf, |
164 | size_t count, loff_t *ppos) | 165 | size_t count, loff_t *ppos) |
165 | { | 166 | { |
@@ -174,8 +175,7 @@ static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file, | |||
174 | return -EFAULT; | 175 | return -EFAULT; |
175 | if (sscanf(buf, "%x", &clear_flag) != 1) | 176 | if (sscanf(buf, "%x", &clear_flag) != 1) |
176 | return -EFAULT; | 177 | return -EFAULT; |
177 | if (clear_flag == 1) | 178 | iwl_clear_traffic_stats(priv); |
178 | iwl_clear_tx_stats(priv); | ||
179 | 179 | ||
180 | return count; | 180 | return count; |
181 | } | 181 | } |
@@ -190,7 +190,7 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
190 | int cnt; | 190 | int cnt; |
191 | ssize_t ret; | 191 | ssize_t ret; |
192 | const size_t bufsz = 100 + | 192 | const size_t bufsz = 100 + |
193 | sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX); | 193 | sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX); |
194 | buf = kzalloc(bufsz, GFP_KERNEL); | 194 | buf = kzalloc(bufsz, GFP_KERNEL); |
195 | if (!buf) | 195 | if (!buf) |
196 | return -ENOMEM; | 196 | return -ENOMEM; |
@@ -198,14 +198,14 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
198 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); | 198 | pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); |
199 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { | 199 | for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { |
200 | pos += scnprintf(buf + pos, bufsz - pos, | 200 | pos += scnprintf(buf + pos, bufsz - pos, |
201 | "\t%s\t\t: %u\n", | 201 | "\t%25s\t\t: %u\n", |
202 | get_mgmt_string(cnt), | 202 | get_mgmt_string(cnt), |
203 | priv->rx_stats.mgmt[cnt]); | 203 | priv->rx_stats.mgmt[cnt]); |
204 | } | 204 | } |
205 | pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); | 205 | pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); |
206 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { | 206 | for (cnt = 0; cnt < CONTROL_MAX; cnt++) { |
207 | pos += scnprintf(buf + pos, bufsz - pos, | 207 | pos += scnprintf(buf + pos, bufsz - pos, |
208 | "\t%s\t\t: %u\n", | 208 | "\t%25s\t\t: %u\n", |
209 | get_ctrl_string(cnt), | 209 | get_ctrl_string(cnt), |
210 | priv->rx_stats.ctrl[cnt]); | 210 | priv->rx_stats.ctrl[cnt]); |
211 | } | 211 | } |
@@ -220,26 +220,6 @@ static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, | |||
220 | return ret; | 220 | return ret; |
221 | } | 221 | } |
222 | 222 | ||
223 | static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file, | ||
224 | const char __user *user_buf, | ||
225 | size_t count, loff_t *ppos) | ||
226 | { | ||
227 | struct iwl_priv *priv = file->private_data; | ||
228 | u32 clear_flag; | ||
229 | char buf[8]; | ||
230 | int buf_size; | ||
231 | |||
232 | memset(buf, 0, sizeof(buf)); | ||
233 | buf_size = min(count, sizeof(buf) - 1); | ||
234 | if (copy_from_user(buf, user_buf, buf_size)) | ||
235 | return -EFAULT; | ||
236 | if (sscanf(buf, "%x", &clear_flag) != 1) | ||
237 | return -EFAULT; | ||
238 | if (clear_flag == 1) | ||
239 | iwl_clear_rx_stats(priv); | ||
240 | return count; | ||
241 | } | ||
242 | |||
243 | #define BYTE1_MASK 0x000000ff; | 223 | #define BYTE1_MASK 0x000000ff; |
244 | #define BYTE2_MASK 0x0000ffff; | 224 | #define BYTE2_MASK 0x0000ffff; |
245 | #define BYTE3_MASK 0x00ffffff; | 225 | #define BYTE3_MASK 0x00ffffff; |
@@ -248,13 +228,29 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
248 | size_t count, loff_t *ppos) | 228 | size_t count, loff_t *ppos) |
249 | { | 229 | { |
250 | u32 val; | 230 | u32 val; |
251 | char buf[1024]; | 231 | char *buf; |
252 | ssize_t ret; | 232 | ssize_t ret; |
253 | int i; | 233 | int i; |
254 | int pos = 0; | 234 | int pos = 0; |
255 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; | 235 | struct iwl_priv *priv = (struct iwl_priv *)file->private_data; |
256 | const size_t bufsz = sizeof(buf); | 236 | size_t bufsz; |
257 | 237 | ||
238 | /* default is to dump the entire data segment */ | ||
239 | if (!priv->dbgfs->sram_offset && !priv->dbgfs->sram_len) { | ||
240 | priv->dbgfs->sram_offset = 0x800000; | ||
241 | if (priv->ucode_type == UCODE_INIT) | ||
242 | priv->dbgfs->sram_len = priv->ucode_init_data.len; | ||
243 | else | ||
244 | priv->dbgfs->sram_len = priv->ucode_data.len; | ||
245 | } | ||
246 | bufsz = 30 + priv->dbgfs->sram_len * sizeof(char) * 10; | ||
247 | buf = kmalloc(bufsz, GFP_KERNEL); | ||
248 | if (!buf) | ||
249 | return -ENOMEM; | ||
250 | pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n", | ||
251 | priv->dbgfs->sram_len); | ||
252 | pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n", | ||
253 | priv->dbgfs->sram_offset); | ||
258 | for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { | 254 | for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { |
259 | val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ | 255 | val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ |
260 | priv->dbgfs->sram_len - i); | 256 | priv->dbgfs->sram_len - i); |
@@ -271,11 +267,14 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file, | |||
271 | break; | 267 | break; |
272 | } | 268 | } |
273 | } | 269 | } |
270 | if (!(i % 16)) | ||
271 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | ||
274 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); | 272 | pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); |
275 | } | 273 | } |
276 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); | 274 | pos += scnprintf(buf + pos, bufsz - pos, "\n"); |
277 | 275 | ||
278 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 276 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
277 | kfree(buf); | ||
279 | return ret; | 278 | return ret; |
280 | } | 279 | } |
281 | 280 | ||
@@ -335,8 +334,6 @@ static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, | |||
335 | pos += scnprintf(buf + pos, bufsz - pos, | 334 | pos += scnprintf(buf + pos, bufsz - pos, |
336 | "flags: 0x%x\n", | 335 | "flags: 0x%x\n", |
337 | station->sta.station_flags_msk); | 336 | station->sta.station_flags_msk); |
338 | pos += scnprintf(buf + pos, bufsz - pos, | ||
339 | "ps_status: %u\n", station->ps_status); | ||
340 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); | 337 | pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); |
341 | pos += scnprintf(buf + pos, bufsz - pos, | 338 | pos += scnprintf(buf + pos, bufsz - pos, |
342 | "seq_num\t\ttxq_id"); | 339 | "seq_num\t\ttxq_id"); |
@@ -439,7 +436,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, | |||
439 | if (sscanf(buf, "%d", &event_log_flag) != 1) | 436 | if (sscanf(buf, "%d", &event_log_flag) != 1) |
440 | return -EFAULT; | 437 | return -EFAULT; |
441 | if (event_log_flag == 1) | 438 | if (event_log_flag == 1) |
442 | priv->cfg->ops->lib->dump_nic_event_log(priv); | 439 | priv->cfg->ops->lib->dump_nic_event_log(priv, true); |
443 | 440 | ||
444 | return count; | 441 | return count; |
445 | } | 442 | } |
@@ -986,7 +983,7 @@ static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, | |||
986 | int pos = 0; | 983 | int pos = 0; |
987 | int cnt; | 984 | int cnt; |
988 | int ret; | 985 | int ret; |
989 | const size_t bufsz = sizeof(char) * 60 * priv->cfg->num_of_queues; | 986 | const size_t bufsz = sizeof(char) * 64 * priv->cfg->num_of_queues; |
990 | 987 | ||
991 | if (!priv->txq) { | 988 | if (!priv->txq) { |
992 | IWL_ERR(priv, "txq not ready\n"); | 989 | IWL_ERR(priv, "txq not ready\n"); |
@@ -1042,10 +1039,6 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, | |||
1042 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1039 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1043 | } | 1040 | } |
1044 | 1041 | ||
1045 | #define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0) | ||
1046 | #define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1) | ||
1047 | #define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2) | ||
1048 | |||
1049 | static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, | 1042 | static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, |
1050 | int bufsz) | 1043 | int bufsz) |
1051 | { | 1044 | { |
@@ -1092,7 +1085,7 @@ static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, | |||
1092 | 1085 | ||
1093 | /* make request to uCode to retrieve statistics information */ | 1086 | /* make request to uCode to retrieve statistics information */ |
1094 | mutex_lock(&priv->mutex); | 1087 | mutex_lock(&priv->mutex); |
1095 | ret = iwl_send_statistics_request(priv, 0); | 1088 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); |
1096 | mutex_unlock(&priv->mutex); | 1089 | mutex_unlock(&priv->mutex); |
1097 | 1090 | ||
1098 | if (ret) { | 1091 | if (ret) { |
@@ -1398,7 +1391,7 @@ static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, | |||
1398 | 1391 | ||
1399 | /* make request to uCode to retrieve statistics information */ | 1392 | /* make request to uCode to retrieve statistics information */ |
1400 | mutex_lock(&priv->mutex); | 1393 | mutex_lock(&priv->mutex); |
1401 | ret = iwl_send_statistics_request(priv, 0); | 1394 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); |
1402 | mutex_unlock(&priv->mutex); | 1395 | mutex_unlock(&priv->mutex); |
1403 | 1396 | ||
1404 | if (ret) { | 1397 | if (ret) { |
@@ -1542,7 +1535,7 @@ static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, | |||
1542 | 1535 | ||
1543 | /* make request to uCode to retrieve statistics information */ | 1536 | /* make request to uCode to retrieve statistics information */ |
1544 | mutex_lock(&priv->mutex); | 1537 | mutex_lock(&priv->mutex); |
1545 | ret = iwl_send_statistics_request(priv, 0); | 1538 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); |
1546 | mutex_unlock(&priv->mutex); | 1539 | mutex_unlock(&priv->mutex); |
1547 | 1540 | ||
1548 | if (ret) { | 1541 | if (ret) { |
@@ -1770,7 +1763,7 @@ static ssize_t iwl_dbgfs_tx_power_read(struct file *file, | |||
1770 | else { | 1763 | else { |
1771 | /* make request to uCode to retrieve statistics information */ | 1764 | /* make request to uCode to retrieve statistics information */ |
1772 | mutex_lock(&priv->mutex); | 1765 | mutex_lock(&priv->mutex); |
1773 | ret = iwl_send_statistics_request(priv, 0); | 1766 | ret = iwl_send_statistics_request(priv, CMD_SYNC, false); |
1774 | mutex_unlock(&priv->mutex); | 1767 | mutex_unlock(&priv->mutex); |
1775 | 1768 | ||
1776 | if (ret) { | 1769 | if (ret) { |
@@ -1828,8 +1821,32 @@ static ssize_t iwl_dbgfs_power_save_status_read(struct file *file, | |||
1828 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); | 1821 | return simple_read_from_buffer(user_buf, count, ppos, buf, pos); |
1829 | } | 1822 | } |
1830 | 1823 | ||
1831 | DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics); | 1824 | static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file, |
1832 | DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics); | 1825 | const char __user *user_buf, |
1826 | size_t count, loff_t *ppos) | ||
1827 | { | ||
1828 | struct iwl_priv *priv = file->private_data; | ||
1829 | char buf[8]; | ||
1830 | int buf_size; | ||
1831 | int clear; | ||
1832 | |||
1833 | memset(buf, 0, sizeof(buf)); | ||
1834 | buf_size = min(count, sizeof(buf) - 1); | ||
1835 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1836 | return -EFAULT; | ||
1837 | if (sscanf(buf, "%d", &clear) != 1) | ||
1838 | return -EFAULT; | ||
1839 | |||
1840 | /* make request to uCode to retrieve statistics information */ | ||
1841 | mutex_lock(&priv->mutex); | ||
1842 | iwl_send_statistics_request(priv, CMD_SYNC, true); | ||
1843 | mutex_unlock(&priv->mutex); | ||
1844 | |||
1845 | return count; | ||
1846 | } | ||
1847 | |||
1848 | DEBUGFS_READ_FILE_OPS(rx_statistics); | ||
1849 | DEBUGFS_READ_FILE_OPS(tx_statistics); | ||
1833 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); | 1850 | DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); |
1834 | DEBUGFS_READ_FILE_OPS(rx_queue); | 1851 | DEBUGFS_READ_FILE_OPS(rx_queue); |
1835 | DEBUGFS_READ_FILE_OPS(tx_queue); | 1852 | DEBUGFS_READ_FILE_OPS(tx_queue); |
@@ -1840,6 +1857,8 @@ DEBUGFS_READ_FILE_OPS(sensitivity); | |||
1840 | DEBUGFS_READ_FILE_OPS(chain_noise); | 1857 | DEBUGFS_READ_FILE_OPS(chain_noise); |
1841 | DEBUGFS_READ_FILE_OPS(tx_power); | 1858 | DEBUGFS_READ_FILE_OPS(tx_power); |
1842 | DEBUGFS_READ_FILE_OPS(power_save_status); | 1859 | DEBUGFS_READ_FILE_OPS(power_save_status); |
1860 | DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics); | ||
1861 | DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics); | ||
1843 | 1862 | ||
1844 | /* | 1863 | /* |
1845 | * Create the debugfs files and directories | 1864 | * Create the debugfs files and directories |
@@ -1868,32 +1887,34 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) | |||
1868 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); | 1887 | DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); |
1869 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); | 1888 | DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); |
1870 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); | 1889 | DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); |
1871 | DEBUGFS_ADD_FILE(nvm, data); | 1890 | DEBUGFS_ADD_FILE(nvm, data, S_IRUSR); |
1872 | DEBUGFS_ADD_FILE(sram, data); | 1891 | DEBUGFS_ADD_FILE(sram, data, S_IWUSR | S_IRUSR); |
1873 | DEBUGFS_ADD_FILE(log_event, data); | 1892 | DEBUGFS_ADD_FILE(log_event, data, S_IWUSR); |
1874 | DEBUGFS_ADD_FILE(stations, data); | 1893 | DEBUGFS_ADD_FILE(stations, data, S_IRUSR); |
1875 | DEBUGFS_ADD_FILE(channels, data); | 1894 | DEBUGFS_ADD_FILE(channels, data, S_IRUSR); |
1876 | DEBUGFS_ADD_FILE(status, data); | 1895 | DEBUGFS_ADD_FILE(status, data, S_IRUSR); |
1877 | DEBUGFS_ADD_FILE(interrupt, data); | 1896 | DEBUGFS_ADD_FILE(interrupt, data, S_IWUSR | S_IRUSR); |
1878 | DEBUGFS_ADD_FILE(qos, data); | 1897 | DEBUGFS_ADD_FILE(qos, data, S_IRUSR); |
1879 | DEBUGFS_ADD_FILE(led, data); | 1898 | DEBUGFS_ADD_FILE(led, data, S_IRUSR); |
1880 | DEBUGFS_ADD_FILE(sleep_level_override, data); | 1899 | DEBUGFS_ADD_FILE(sleep_level_override, data, S_IWUSR | S_IRUSR); |
1881 | DEBUGFS_ADD_FILE(current_sleep_command, data); | 1900 | DEBUGFS_ADD_FILE(current_sleep_command, data, S_IRUSR); |
1882 | DEBUGFS_ADD_FILE(thermal_throttling, data); | 1901 | DEBUGFS_ADD_FILE(thermal_throttling, data, S_IRUSR); |
1883 | DEBUGFS_ADD_FILE(disable_ht40, data); | 1902 | DEBUGFS_ADD_FILE(disable_ht40, data, S_IWUSR | S_IRUSR); |
1884 | DEBUGFS_ADD_FILE(rx_statistics, debug); | 1903 | DEBUGFS_ADD_FILE(rx_statistics, debug, S_IRUSR); |
1885 | DEBUGFS_ADD_FILE(tx_statistics, debug); | 1904 | DEBUGFS_ADD_FILE(tx_statistics, debug, S_IRUSR); |
1886 | DEBUGFS_ADD_FILE(traffic_log, debug); | 1905 | DEBUGFS_ADD_FILE(traffic_log, debug, S_IWUSR | S_IRUSR); |
1887 | DEBUGFS_ADD_FILE(rx_queue, debug); | 1906 | DEBUGFS_ADD_FILE(rx_queue, debug, S_IRUSR); |
1888 | DEBUGFS_ADD_FILE(tx_queue, debug); | 1907 | DEBUGFS_ADD_FILE(tx_queue, debug, S_IRUSR); |
1889 | DEBUGFS_ADD_FILE(tx_power, debug); | 1908 | DEBUGFS_ADD_FILE(tx_power, debug, S_IRUSR); |
1890 | DEBUGFS_ADD_FILE(power_save_status, debug); | 1909 | DEBUGFS_ADD_FILE(power_save_status, debug, S_IRUSR); |
1910 | DEBUGFS_ADD_FILE(clear_ucode_statistics, debug, S_IWUSR); | ||
1911 | DEBUGFS_ADD_FILE(clear_traffic_statistics, debug, S_IWUSR); | ||
1891 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 1912 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1892 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug); | 1913 | DEBUGFS_ADD_FILE(ucode_rx_stats, debug, S_IRUSR); |
1893 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug); | 1914 | DEBUGFS_ADD_FILE(ucode_tx_stats, debug, S_IRUSR); |
1894 | DEBUGFS_ADD_FILE(ucode_general_stats, debug); | 1915 | DEBUGFS_ADD_FILE(ucode_general_stats, debug, S_IRUSR); |
1895 | DEBUGFS_ADD_FILE(sensitivity, debug); | 1916 | DEBUGFS_ADD_FILE(sensitivity, debug, S_IRUSR); |
1896 | DEBUGFS_ADD_FILE(chain_noise, debug); | 1917 | DEBUGFS_ADD_FILE(chain_noise, debug, S_IRUSR); |
1897 | } | 1918 | } |
1898 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); | 1919 | DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); |
1899 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, | 1920 | DEBUGFS_ADD_BOOL(disable_chain_noise, rf, |
@@ -1941,6 +1962,10 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
1941 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); | 1962 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); |
1942 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); | 1963 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); |
1943 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status); | 1964 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_power_save_status); |
1965 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1966 | file_clear_ucode_statistics); | ||
1967 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | ||
1968 | file_clear_traffic_statistics); | ||
1944 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { | 1969 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { |
1945 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. | 1970 | DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. |
1946 | file_ucode_rx_stats); | 1971 | file_ucode_rx_stats); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index 9dea8fa08c0e..2673e9a4db92 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -52,19 +52,16 @@ extern struct iwl_cfg iwl4965_agn_cfg; | |||
52 | extern struct iwl_cfg iwl5300_agn_cfg; | 52 | extern struct iwl_cfg iwl5300_agn_cfg; |
53 | extern struct iwl_cfg iwl5100_agn_cfg; | 53 | extern struct iwl_cfg iwl5100_agn_cfg; |
54 | extern struct iwl_cfg iwl5350_agn_cfg; | 54 | extern struct iwl_cfg iwl5350_agn_cfg; |
55 | extern struct iwl_cfg iwl5100_bg_cfg; | 55 | extern struct iwl_cfg iwl5100_bgn_cfg; |
56 | extern struct iwl_cfg iwl5100_abg_cfg; | 56 | extern struct iwl_cfg iwl5100_abg_cfg; |
57 | extern struct iwl_cfg iwl5150_agn_cfg; | 57 | extern struct iwl_cfg iwl5150_agn_cfg; |
58 | extern struct iwl_cfg iwl6000h_2agn_cfg; | 58 | extern struct iwl_cfg iwl5150_abg_cfg; |
59 | extern struct iwl_cfg iwl6000h_2abg_cfg; | ||
60 | extern struct iwl_cfg iwl6000h_2bg_cfg; | ||
61 | extern struct iwl_cfg iwl6000i_2agn_cfg; | 59 | extern struct iwl_cfg iwl6000i_2agn_cfg; |
62 | extern struct iwl_cfg iwl6000i_2abg_cfg; | 60 | extern struct iwl_cfg iwl6000i_2abg_cfg; |
63 | extern struct iwl_cfg iwl6000i_2bg_cfg; | 61 | extern struct iwl_cfg iwl6000i_2bg_cfg; |
64 | extern struct iwl_cfg iwl6000_3agn_cfg; | 62 | extern struct iwl_cfg iwl6000_3agn_cfg; |
65 | extern struct iwl_cfg iwl6050_2agn_cfg; | 63 | extern struct iwl_cfg iwl6050_2agn_cfg; |
66 | extern struct iwl_cfg iwl6050_2abg_cfg; | 64 | extern struct iwl_cfg iwl6050_2abg_cfg; |
67 | extern struct iwl_cfg iwl6050_3agn_cfg; | ||
68 | extern struct iwl_cfg iwl1000_bgn_cfg; | 65 | extern struct iwl_cfg iwl1000_bgn_cfg; |
69 | extern struct iwl_cfg iwl1000_bg_cfg; | 66 | extern struct iwl_cfg iwl1000_bg_cfg; |
70 | 67 | ||
@@ -295,9 +292,6 @@ struct iwl_channel_info { | |||
295 | 292 | ||
296 | /* HT40 channel info */ | 293 | /* HT40 channel info */ |
297 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ | 294 | s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ |
298 | s8 ht40_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ | ||
299 | s8 ht40_min_power; /* always 0 */ | ||
300 | s8 ht40_scan_power; /* (dBm) eeprom, direct scans, any rate */ | ||
301 | u8 ht40_flags; /* flags copied from EEPROM */ | 295 | u8 ht40_flags; /* flags copied from EEPROM */ |
302 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ | 296 | u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ |
303 | 297 | ||
@@ -518,7 +512,6 @@ struct iwl_ht_config { | |||
518 | bool is_ht; | 512 | bool is_ht; |
519 | bool is_40mhz; | 513 | bool is_40mhz; |
520 | bool single_chain_sufficient; | 514 | bool single_chain_sufficient; |
521 | u8 sm_ps; | ||
522 | /* BSS related data */ | 515 | /* BSS related data */ |
523 | u8 extension_chan_offset; | 516 | u8 extension_chan_offset; |
524 | u8 ht_protection; | 517 | u8 ht_protection; |
@@ -552,23 +545,10 @@ struct iwl_qos_info { | |||
552 | struct iwl_qosparam_cmd def_qos_parm; | 545 | struct iwl_qosparam_cmd def_qos_parm; |
553 | }; | 546 | }; |
554 | 547 | ||
555 | #define STA_PS_STATUS_WAKE 0 | ||
556 | #define STA_PS_STATUS_SLEEP 1 | ||
557 | |||
558 | |||
559 | struct iwl3945_station_entry { | ||
560 | struct iwl3945_addsta_cmd sta; | ||
561 | struct iwl_tid_data tid[MAX_TID_COUNT]; | ||
562 | u8 used; | ||
563 | u8 ps_status; | ||
564 | struct iwl_hw_key keyinfo; | ||
565 | }; | ||
566 | |||
567 | struct iwl_station_entry { | 548 | struct iwl_station_entry { |
568 | struct iwl_addsta_cmd sta; | 549 | struct iwl_addsta_cmd sta; |
569 | struct iwl_tid_data tid[MAX_TID_COUNT]; | 550 | struct iwl_tid_data tid[MAX_TID_COUNT]; |
570 | u8 used; | 551 | u8 used; |
571 | u8 ps_status; | ||
572 | struct iwl_hw_key keyinfo; | 552 | struct iwl_hw_key keyinfo; |
573 | }; | 553 | }; |
574 | 554 | ||
@@ -578,11 +558,12 @@ struct iwl_station_entry { | |||
578 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) | 558 | * When mac80211 creates a station it reserves some space (hw->sta_data_size) |
579 | * in the structure for use by driver. This structure is places in that | 559 | * in the structure for use by driver. This structure is places in that |
580 | * space. | 560 | * space. |
581 | * | ||
582 | * At the moment use it for the station's rate scaling information. | ||
583 | */ | 561 | */ |
584 | struct iwl_station_priv { | 562 | struct iwl_station_priv { |
585 | struct iwl_lq_sta lq_sta; | 563 | struct iwl_lq_sta lq_sta; |
564 | atomic_t pending_frames; | ||
565 | bool client; | ||
566 | bool asleep; | ||
586 | }; | 567 | }; |
587 | 568 | ||
588 | /* one for each uCode image (inst/data, boot/init/runtime) */ | 569 | /* one for each uCode image (inst/data, boot/init/runtime) */ |
@@ -1254,6 +1235,7 @@ struct iwl_priv { | |||
1254 | /* TX Power */ | 1235 | /* TX Power */ |
1255 | s8 tx_power_user_lmt; | 1236 | s8 tx_power_user_lmt; |
1256 | s8 tx_power_device_lmt; | 1237 | s8 tx_power_device_lmt; |
1238 | s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ | ||
1257 | 1239 | ||
1258 | 1240 | ||
1259 | #ifdef CONFIG_IWLWIFI_DEBUG | 1241 | #ifdef CONFIG_IWLWIFI_DEBUG |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.c b/drivers/net/wireless/iwlwifi/iwl-devtrace.c index 4ef5acaa556d..e7d88d1da15d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.c +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.c | |||
@@ -5,6 +5,7 @@ | |||
5 | #define CREATE_TRACE_POINTS | 5 | #define CREATE_TRACE_POINTS |
6 | #include "iwl-devtrace.h" | 6 | #include "iwl-devtrace.h" |
7 | 7 | ||
8 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite8); | ||
8 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); | 9 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_ioread32); |
9 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); | 10 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_iowrite32); |
10 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); | 11 | EXPORT_TRACEPOINT_SYMBOL(iwlwifi_dev_rx); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 8c7159208da1..21361968ab7e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -14,7 +14,7 @@ static inline void trace_ ## name(proto) {} | |||
14 | #define PRIV_ASSIGN __entry->priv = priv | 14 | #define PRIV_ASSIGN __entry->priv = priv |
15 | 15 | ||
16 | #undef TRACE_SYSTEM | 16 | #undef TRACE_SYSTEM |
17 | #define TRACE_SYSTEM iwlwifi | 17 | #define TRACE_SYSTEM iwlwifi_io |
18 | 18 | ||
19 | TRACE_EVENT(iwlwifi_dev_ioread32, | 19 | TRACE_EVENT(iwlwifi_dev_ioread32, |
20 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), | 20 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), |
@@ -32,6 +32,22 @@ TRACE_EVENT(iwlwifi_dev_ioread32, | |||
32 | TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val) | 32 | TP_printk("[%p] read io[%#x] = %#x", __entry->priv, __entry->offs, __entry->val) |
33 | ); | 33 | ); |
34 | 34 | ||
35 | TRACE_EVENT(iwlwifi_dev_iowrite8, | ||
36 | TP_PROTO(struct iwl_priv *priv, u32 offs, u8 val), | ||
37 | TP_ARGS(priv, offs, val), | ||
38 | TP_STRUCT__entry( | ||
39 | PRIV_ENTRY | ||
40 | __field(u32, offs) | ||
41 | __field(u8, val) | ||
42 | ), | ||
43 | TP_fast_assign( | ||
44 | PRIV_ASSIGN; | ||
45 | __entry->offs = offs; | ||
46 | __entry->val = val; | ||
47 | ), | ||
48 | TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) | ||
49 | ); | ||
50 | |||
35 | TRACE_EVENT(iwlwifi_dev_iowrite32, | 51 | TRACE_EVENT(iwlwifi_dev_iowrite32, |
36 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), | 52 | TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val), |
37 | TP_ARGS(priv, offs, val), | 53 | TP_ARGS(priv, offs, val), |
@@ -48,6 +64,9 @@ TRACE_EVENT(iwlwifi_dev_iowrite32, | |||
48 | TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) | 64 | TP_printk("[%p] write io[%#x] = %#x)", __entry->priv, __entry->offs, __entry->val) |
49 | ); | 65 | ); |
50 | 66 | ||
67 | #undef TRACE_SYSTEM | ||
68 | #define TRACE_SYSTEM iwlwifi | ||
69 | |||
51 | TRACE_EVENT(iwlwifi_dev_hcmd, | 70 | TRACE_EVENT(iwlwifi_dev_hcmd, |
52 | TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), | 71 | TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags), |
53 | TP_ARGS(priv, hcmd, len, flags), | 72 | TP_ARGS(priv, hcmd, len, flags), |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 8a0709e81a9f..3946e5c03f81 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c | |||
@@ -518,6 +518,11 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
518 | } | 518 | } |
519 | e = (u16 *)priv->eeprom; | 519 | e = (u16 *)priv->eeprom; |
520 | 520 | ||
521 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | ||
522 | /* OTP reads require powered-up chip */ | ||
523 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
524 | } | ||
525 | |||
521 | ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); | 526 | ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); |
522 | if (ret < 0) { | 527 | if (ret < 0) { |
523 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); | 528 | IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); |
@@ -532,10 +537,8 @@ int iwl_eeprom_init(struct iwl_priv *priv) | |||
532 | ret = -ENOENT; | 537 | ret = -ENOENT; |
533 | goto err; | 538 | goto err; |
534 | } | 539 | } |
535 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { | ||
536 | 540 | ||
537 | /* OTP reads require powered-up chip */ | 541 | if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { |
538 | priv->cfg->ops->lib->apm_ops.init(priv); | ||
539 | 542 | ||
540 | ret = iwl_init_otp_access(priv); | 543 | ret = iwl_init_otp_access(priv); |
541 | if (ret) { | 544 | if (ret) { |
@@ -751,9 +754,6 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | |||
751 | 754 | ||
752 | ch_info->ht40_eeprom = *eeprom_ch; | 755 | ch_info->ht40_eeprom = *eeprom_ch; |
753 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; | 756 | ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; |
754 | ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg; | ||
755 | ch_info->ht40_min_power = 0; | ||
756 | ch_info->ht40_scan_power = eeprom_ch->max_power_avg; | ||
757 | ch_info->ht40_flags = eeprom_ch->flags; | 757 | ch_info->ht40_flags = eeprom_ch->flags; |
758 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; | 758 | ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; |
759 | 759 | ||
@@ -765,7 +765,8 @@ static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, | |||
765 | * find the highest tx power from all chains for the channel | 765 | * find the highest tx power from all chains for the channel |
766 | */ | 766 | */ |
767 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | 767 | static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, |
768 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element) | 768 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
769 | int element, s8 *max_txpower_in_half_dbm) | ||
769 | { | 770 | { |
770 | s8 max_txpower_avg = 0; /* (dBm) */ | 771 | s8 max_txpower_avg = 0; /* (dBm) */ |
771 | 772 | ||
@@ -797,10 +798,14 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | |||
797 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) | 798 | (enhanced_txpower[element].mimo3_max > max_txpower_avg)) |
798 | max_txpower_avg = enhanced_txpower[element].mimo3_max; | 799 | max_txpower_avg = enhanced_txpower[element].mimo3_max; |
799 | 800 | ||
800 | /* max. tx power in EEPROM is in 1/2 dBm format | 801 | /* |
801 | * convert from 1/2 dBm to dBm | 802 | * max. tx power in EEPROM is in 1/2 dBm format |
803 | * convert from 1/2 dBm to dBm (round-up convert) | ||
804 | * but we also do not want to loss 1/2 dBm resolution which | ||
805 | * will impact performance | ||
802 | */ | 806 | */ |
803 | return max_txpower_avg >> 1; | 807 | *max_txpower_in_half_dbm = max_txpower_avg; |
808 | return (max_txpower_avg & 0x01) + (max_txpower_avg >> 1); | ||
804 | } | 809 | } |
805 | 810 | ||
806 | /** | 811 | /** |
@@ -809,7 +814,7 @@ static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, | |||
809 | */ | 814 | */ |
810 | static s8 iwl_update_common_txpower(struct iwl_priv *priv, | 815 | static s8 iwl_update_common_txpower(struct iwl_priv *priv, |
811 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | 816 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
812 | int section, int element) | 817 | int section, int element, s8 *max_txpower_in_half_dbm) |
813 | { | 818 | { |
814 | struct iwl_channel_info *ch_info; | 819 | struct iwl_channel_info *ch_info; |
815 | int ch; | 820 | int ch; |
@@ -823,25 +828,25 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv, | |||
823 | if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) | 828 | if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) |
824 | is_ht40 = true; | 829 | is_ht40 = true; |
825 | max_txpower_avg = | 830 | max_txpower_avg = |
826 | iwl_get_max_txpower_avg(priv, enhanced_txpower, element); | 831 | iwl_get_max_txpower_avg(priv, enhanced_txpower, |
832 | element, max_txpower_in_half_dbm); | ||
833 | |||
827 | ch_info = priv->channel_info; | 834 | ch_info = priv->channel_info; |
828 | 835 | ||
829 | for (ch = 0; ch < priv->channel_count; ch++) { | 836 | for (ch = 0; ch < priv->channel_count; ch++) { |
830 | /* find matching band and update tx power if needed */ | 837 | /* find matching band and update tx power if needed */ |
831 | if ((ch_info->band == enhinfo[section].band) && | 838 | if ((ch_info->band == enhinfo[section].band) && |
832 | (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) { | 839 | (ch_info->max_power_avg < max_txpower_avg) && |
840 | (!is_ht40)) { | ||
833 | /* Update regulatory-based run-time data */ | 841 | /* Update regulatory-based run-time data */ |
834 | ch_info->max_power_avg = ch_info->curr_txpow = | 842 | ch_info->max_power_avg = ch_info->curr_txpow = |
835 | max_txpower_avg; | 843 | max_txpower_avg; |
836 | ch_info->scan_power = max_txpower_avg; | 844 | ch_info->scan_power = max_txpower_avg; |
837 | } | 845 | } |
838 | if ((ch_info->band == enhinfo[section].band) && is_ht40 && | 846 | if ((ch_info->band == enhinfo[section].band) && is_ht40 && |
839 | ch_info->ht40_max_power_avg && | ||
840 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | 847 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { |
841 | /* Update regulatory-based run-time data */ | 848 | /* Update regulatory-based run-time data */ |
842 | ch_info->ht40_max_power_avg = max_txpower_avg; | 849 | ch_info->ht40_max_power_avg = max_txpower_avg; |
843 | ch_info->ht40_curr_txpow = max_txpower_avg; | ||
844 | ch_info->ht40_scan_power = max_txpower_avg; | ||
845 | } | 850 | } |
846 | ch_info++; | 851 | ch_info++; |
847 | } | 852 | } |
@@ -854,7 +859,7 @@ static s8 iwl_update_common_txpower(struct iwl_priv *priv, | |||
854 | */ | 859 | */ |
855 | static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | 860 | static s8 iwl_update_channel_txpower(struct iwl_priv *priv, |
856 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, | 861 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, |
857 | int section, int element) | 862 | int section, int element, s8 *max_txpower_in_half_dbm) |
858 | { | 863 | { |
859 | struct iwl_channel_info *ch_info; | 864 | struct iwl_channel_info *ch_info; |
860 | int ch; | 865 | int ch; |
@@ -863,7 +868,8 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | |||
863 | 868 | ||
864 | channel = enhinfo[section].iwl_eeprom_section_channel[element]; | 869 | channel = enhinfo[section].iwl_eeprom_section_channel[element]; |
865 | max_txpower_avg = | 870 | max_txpower_avg = |
866 | iwl_get_max_txpower_avg(priv, enhanced_txpower, element); | 871 | iwl_get_max_txpower_avg(priv, enhanced_txpower, |
872 | element, max_txpower_in_half_dbm); | ||
867 | 873 | ||
868 | ch_info = priv->channel_info; | 874 | ch_info = priv->channel_info; |
869 | for (ch = 0; ch < priv->channel_count; ch++) { | 875 | for (ch = 0; ch < priv->channel_count; ch++) { |
@@ -877,12 +883,9 @@ static s8 iwl_update_channel_txpower(struct iwl_priv *priv, | |||
877 | ch_info->scan_power = max_txpower_avg; | 883 | ch_info->scan_power = max_txpower_avg; |
878 | } | 884 | } |
879 | if ((enhinfo[section].is_ht40) && | 885 | if ((enhinfo[section].is_ht40) && |
880 | (ch_info->ht40_max_power_avg) && | ||
881 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { | 886 | (ch_info->ht40_max_power_avg < max_txpower_avg)) { |
882 | /* Update regulatory-based run-time data */ | 887 | /* Update regulatory-based run-time data */ |
883 | ch_info->ht40_max_power_avg = max_txpower_avg; | 888 | ch_info->ht40_max_power_avg = max_txpower_avg; |
884 | ch_info->ht40_curr_txpow = max_txpower_avg; | ||
885 | ch_info->ht40_scan_power = max_txpower_avg; | ||
886 | } | 889 | } |
887 | break; | 890 | break; |
888 | } | 891 | } |
@@ -901,6 +904,7 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
901 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; | 904 | struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; |
902 | u32 offset; | 905 | u32 offset; |
903 | s8 max_txpower_avg; /* (dBm) */ | 906 | s8 max_txpower_avg; /* (dBm) */ |
907 | s8 max_txpower_in_half_dbm; /* (half-dBm) */ | ||
904 | 908 | ||
905 | /* Loop through all the sections | 909 | /* Loop through all the sections |
906 | * adjust bands and channel's max tx power | 910 | * adjust bands and channel's max tx power |
@@ -913,20 +917,43 @@ void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) | |||
913 | enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) | 917 | enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) |
914 | iwl_eeprom_query_addr(priv, offset); | 918 | iwl_eeprom_query_addr(priv, offset); |
915 | 919 | ||
920 | /* | ||
921 | * check for valid entry - | ||
922 | * different version of EEPROM might contain different set | ||
923 | * of enhanced tx power table | ||
924 | * always check for valid entry before process | ||
925 | * the information | ||
926 | */ | ||
927 | if (!enhanced_txpower->common || enhanced_txpower->reserved) | ||
928 | continue; | ||
929 | |||
916 | for (element = 0; element < eeprom_section_count; element++) { | 930 | for (element = 0; element < eeprom_section_count; element++) { |
917 | if (enhinfo[section].is_common) | 931 | if (enhinfo[section].is_common) |
918 | max_txpower_avg = | 932 | max_txpower_avg = |
919 | iwl_update_common_txpower(priv, | 933 | iwl_update_common_txpower(priv, |
920 | enhanced_txpower, section, element); | 934 | enhanced_txpower, section, |
935 | element, | ||
936 | &max_txpower_in_half_dbm); | ||
921 | else | 937 | else |
922 | max_txpower_avg = | 938 | max_txpower_avg = |
923 | iwl_update_channel_txpower(priv, | 939 | iwl_update_channel_txpower(priv, |
924 | enhanced_txpower, section, element); | 940 | enhanced_txpower, section, |
941 | element, | ||
942 | &max_txpower_in_half_dbm); | ||
925 | 943 | ||
926 | /* Update the tx_power_user_lmt to the highest power | 944 | /* Update the tx_power_user_lmt to the highest power |
927 | * supported by any channel */ | 945 | * supported by any channel */ |
928 | if (max_txpower_avg > priv->tx_power_user_lmt) | 946 | if (max_txpower_avg > priv->tx_power_user_lmt) |
929 | priv->tx_power_user_lmt = max_txpower_avg; | 947 | priv->tx_power_user_lmt = max_txpower_avg; |
948 | |||
949 | /* | ||
950 | * Update the tx_power_lmt_in_half_dbm to | ||
951 | * the highest power supported by any channel | ||
952 | */ | ||
953 | if (max_txpower_in_half_dbm > | ||
954 | priv->tx_power_lmt_in_half_dbm) | ||
955 | priv->tx_power_lmt_in_half_dbm = | ||
956 | max_txpower_in_half_dbm; | ||
930 | } | 957 | } |
931 | } | 958 | } |
932 | } | 959 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h index 5ba5a4e9e49a..5cd2b66bbe45 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h | |||
@@ -127,19 +127,21 @@ struct iwl_eeprom_channel { | |||
127 | * Enhanced regulatory tx power portion of eeprom image can be broken down | 127 | * Enhanced regulatory tx power portion of eeprom image can be broken down |
128 | * into individual structures; each one is 8 bytes in size and contain the | 128 | * into individual structures; each one is 8 bytes in size and contain the |
129 | * following information | 129 | * following information |
130 | * @common: (desc + channel) not used by driver, should _NOT_ be "zero" | ||
130 | * @chain_a_max_pwr: chain a max power in 1/2 dBm | 131 | * @chain_a_max_pwr: chain a max power in 1/2 dBm |
131 | * @chain_b_max_pwr: chain b max power in 1/2 dBm | 132 | * @chain_b_max_pwr: chain b max power in 1/2 dBm |
132 | * @chain_c_max_pwr: chain c max power in 1/2 dBm | 133 | * @chain_c_max_pwr: chain c max power in 1/2 dBm |
134 | * @reserved: not used, should be "zero" | ||
133 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm | 135 | * @mimo2_max_pwr: mimo2 max power in 1/2 dBm |
134 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm | 136 | * @mimo3_max_pwr: mimo3 max power in 1/2 dBm |
135 | * | 137 | * |
136 | */ | 138 | */ |
137 | struct iwl_eeprom_enhanced_txpwr { | 139 | struct iwl_eeprom_enhanced_txpwr { |
138 | u16 reserved; | 140 | u16 common; |
139 | s8 chain_a_max; | 141 | s8 chain_a_max; |
140 | s8 chain_b_max; | 142 | s8 chain_b_max; |
141 | s8 chain_c_max; | 143 | s8 chain_c_max; |
142 | s8 reserved1; | 144 | s8 reserved; |
143 | s8 mimo2_max; | 145 | s8 mimo2_max; |
144 | s8 mimo3_max; | 146 | s8 mimo3_max; |
145 | } __attribute__ ((packed)); | 147 | } __attribute__ ((packed)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index d0a358c9d96b..e552d4c4bdbe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -62,6 +62,26 @@ | |||
62 | * | 62 | * |
63 | */ | 63 | */ |
64 | 64 | ||
65 | static inline void _iwl_write8(struct iwl_priv *priv, u32 ofs, u8 val) | ||
66 | { | ||
67 | trace_iwlwifi_dev_iowrite8(priv, ofs, val); | ||
68 | iowrite8(val, priv->hw_base + ofs); | ||
69 | } | ||
70 | |||
71 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
72 | static inline void __iwl_write8(const char *f, u32 l, struct iwl_priv *priv, | ||
73 | u32 ofs, u8 val) | ||
74 | { | ||
75 | IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l); | ||
76 | _iwl_write8(priv, ofs, val); | ||
77 | } | ||
78 | #define iwl_write8(priv, ofs, val) \ | ||
79 | __iwl_write8(__FILE__, __LINE__, priv, ofs, val) | ||
80 | #else | ||
81 | #define iwl_write8(priv, ofs, val) _iwl_write8(priv, ofs, val) | ||
82 | #endif | ||
83 | |||
84 | |||
65 | static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) | 85 | static inline void _iwl_write32(struct iwl_priv *priv, u32 ofs, u32 val) |
66 | { | 86 | { |
67 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); | 87 | trace_iwlwifi_dev_iowrite32(priv, ofs, val); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index 478c90511ebf..46c7a95b88f0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -219,7 +219,6 @@ EXPORT_SYMBOL(iwl_leds_background); | |||
219 | void iwl_leds_init(struct iwl_priv *priv) | 219 | void iwl_leds_init(struct iwl_priv *priv) |
220 | { | 220 | { |
221 | priv->last_blink_rate = 0; | 221 | priv->last_blink_rate = 0; |
222 | priv->led_tpt = 0; | ||
223 | priv->last_blink_time = 0; | 222 | priv->last_blink_time = 0; |
224 | priv->allow_blinking = 0; | 223 | priv->allow_blinking = 0; |
225 | } | 224 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 9bce2c1625e3..8ccc0bb1d9ed 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -506,7 +506,7 @@ static void iwl_prepare_ct_kill_task(struct iwl_priv *priv) | |||
506 | { | 506 | { |
507 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); | 507 | IWL_DEBUG_POWER(priv, "Prepare to enter IWL_TI_CT_KILL\n"); |
508 | /* make request to retrieve statistics information */ | 508 | /* make request to retrieve statistics information */ |
509 | iwl_send_statistics_request(priv, 0); | 509 | iwl_send_statistics_request(priv, CMD_SYNC, false); |
510 | /* Reschedule the ct_kill wait timer */ | 510 | /* Reschedule the ct_kill wait timer */ |
511 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, | 511 | mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm, |
512 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); | 512 | jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION)); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 61b3b0e6ed73..6090bc15a6d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -477,7 +477,8 @@ int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
477 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| | 477 | (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| |
478 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); | 478 | (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); |
479 | 479 | ||
480 | iwl_write32(priv, CSR_INT_COALESCING, 0x40); | 480 | /* Set interrupt coalescing timer to 64 x 32 = 2048 usecs */ |
481 | iwl_write8(priv, CSR_INT_COALESCING, 0x40); | ||
481 | 482 | ||
482 | return 0; | 483 | return 0; |
483 | } | 484 | } |
@@ -635,6 +636,24 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
635 | } | 636 | } |
636 | EXPORT_SYMBOL(iwl_rx_statistics); | 637 | EXPORT_SYMBOL(iwl_rx_statistics); |
637 | 638 | ||
639 | void iwl_reply_statistics(struct iwl_priv *priv, | ||
640 | struct iwl_rx_mem_buffer *rxb) | ||
641 | { | ||
642 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
643 | |||
644 | if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) { | ||
645 | memset(&priv->statistics, 0, | ||
646 | sizeof(struct iwl_notif_statistics)); | ||
647 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
648 | memset(&priv->accum_statistics, 0, | ||
649 | sizeof(struct iwl_notif_statistics)); | ||
650 | #endif | ||
651 | IWL_DEBUG_RX(priv, "Statistics have been cleared\n"); | ||
652 | } | ||
653 | iwl_rx_statistics(priv, rxb); | ||
654 | } | ||
655 | EXPORT_SYMBOL(iwl_reply_statistics); | ||
656 | |||
638 | #define PERFECT_RSSI (-20) /* dBm */ | 657 | #define PERFECT_RSSI (-20) /* dBm */ |
639 | #define WORST_RSSI (-95) /* dBm */ | 658 | #define WORST_RSSI (-95) /* dBm */ |
640 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) | 659 | #define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) |
@@ -1010,7 +1029,6 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1010 | struct iwl4965_rx_mpdu_res_start *amsdu; | 1029 | struct iwl4965_rx_mpdu_res_start *amsdu; |
1011 | u32 len; | 1030 | u32 len; |
1012 | u32 ampdu_status; | 1031 | u32 ampdu_status; |
1013 | u16 fc; | ||
1014 | u32 rate_n_flags; | 1032 | u32 rate_n_flags; |
1015 | 1033 | ||
1016 | /** | 1034 | /** |
@@ -1143,20 +1161,8 @@ void iwl_rx_reply_rx(struct iwl_priv *priv, | |||
1143 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); | 1161 | priv->last_tsf = le64_to_cpu(phy_res->timestamp); |
1144 | } | 1162 | } |
1145 | 1163 | ||
1146 | fc = le16_to_cpu(header->frame_control); | 1164 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, |
1147 | switch (fc & IEEE80211_FCTL_FTYPE) { | 1165 | rxb, &rx_status); |
1148 | case IEEE80211_FTYPE_MGMT: | ||
1149 | case IEEE80211_FTYPE_DATA: | ||
1150 | if (priv->iw_mode == NL80211_IFTYPE_AP) | ||
1151 | iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, | ||
1152 | header->addr2); | ||
1153 | /* fall through */ | ||
1154 | default: | ||
1155 | iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, | ||
1156 | rxb, &rx_status); | ||
1157 | break; | ||
1158 | |||
1159 | } | ||
1160 | } | 1166 | } |
1161 | EXPORT_SYMBOL(iwl_rx_reply_rx); | 1167 | EXPORT_SYMBOL(iwl_rx_reply_rx); |
1162 | 1168 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index eba36f737388..cd6a6901216e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -1216,7 +1216,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | |||
1216 | } | 1216 | } |
1217 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); | 1217 | EXPORT_SYMBOL(iwl_sta_rx_agg_stop); |
1218 | 1218 | ||
1219 | static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | 1219 | void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) |
1220 | { | 1220 | { |
1221 | unsigned long flags; | 1221 | unsigned long flags; |
1222 | 1222 | ||
@@ -1224,27 +1224,26 @@ static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) | |||
1224 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; | 1224 | priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; |
1225 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; | 1225 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; |
1226 | priv->stations[sta_id].sta.sta.modify_mask = 0; | 1226 | priv->stations[sta_id].sta.sta.modify_mask = 0; |
1227 | priv->stations[sta_id].sta.sleep_tx_count = 0; | ||
1227 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | 1228 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; |
1228 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1229 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1229 | 1230 | ||
1230 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); | 1231 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1231 | } | 1232 | } |
1233 | EXPORT_SYMBOL(iwl_sta_modify_ps_wake); | ||
1232 | 1234 | ||
1233 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) | 1235 | void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) |
1234 | { | 1236 | { |
1235 | /* FIXME: need locking over ps_status ??? */ | 1237 | unsigned long flags; |
1236 | u8 sta_id = iwl_find_station(priv, addr); | ||
1237 | 1238 | ||
1238 | if (sta_id != IWL_INVALID_STATION) { | 1239 | spin_lock_irqsave(&priv->sta_lock, flags); |
1239 | u8 sta_awake = priv->stations[sta_id]. | 1240 | priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK; |
1240 | ps_status == STA_PS_STATUS_WAKE; | 1241 | priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; |
1242 | priv->stations[sta_id].sta.sta.modify_mask = | ||
1243 | STA_MODIFY_SLEEP_TX_COUNT_MSK; | ||
1244 | priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt); | ||
1245 | priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; | ||
1246 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1241 | 1247 | ||
1242 | if (sta_awake && ps_bit) | 1248 | iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); |
1243 | priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; | ||
1244 | else if (!sta_awake && !ps_bit) { | ||
1245 | iwl_sta_modify_ps_wake(priv, sta_id); | ||
1246 | priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; | ||
1247 | } | ||
1248 | } | ||
1249 | } | 1249 | } |
1250 | |||
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 1c382de80d49..8d052de2d405 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -66,5 +66,6 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); | |||
66 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | 66 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, |
67 | const u8 *addr, int tid, u16 ssn); | 67 | const u8 *addr, int tid, u16 ssn); |
68 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); | 68 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); |
69 | void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr); | 69 | void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); |
70 | void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); | ||
70 | #endif /* __iwl_sta_h__ */ | 71 | #endif /* __iwl_sta_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 6199bf60d313..888a8e9fe9ef 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -710,6 +710,8 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
710 | { | 710 | { |
711 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 711 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
712 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 712 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
713 | struct ieee80211_sta *sta = info->control.sta; | ||
714 | struct iwl_station_priv *sta_priv = NULL; | ||
713 | struct iwl_tx_queue *txq; | 715 | struct iwl_tx_queue *txq; |
714 | struct iwl_queue *q; | 716 | struct iwl_queue *q; |
715 | struct iwl_device_cmd *out_cmd; | 717 | struct iwl_device_cmd *out_cmd; |
@@ -772,6 +774,24 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
772 | 774 | ||
773 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); | 775 | IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); |
774 | 776 | ||
777 | if (sta) | ||
778 | sta_priv = (void *)sta->drv_priv; | ||
779 | |||
780 | if (sta_priv && sta_id != priv->hw_params.bcast_sta_id && | ||
781 | sta_priv->asleep) { | ||
782 | WARN_ON(!(info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)); | ||
783 | /* | ||
784 | * This sends an asynchronous command to the device, | ||
785 | * but we can rely on it being processed before the | ||
786 | * next frame is processed -- and the next frame to | ||
787 | * this station is the one that will consume this | ||
788 | * counter. | ||
789 | * For now set the counter to just 1 since we do not | ||
790 | * support uAPSD yet. | ||
791 | */ | ||
792 | iwl_sta_modify_sleep_tx_count(priv, sta_id, 1); | ||
793 | } | ||
794 | |||
775 | txq_id = skb_get_queue_mapping(skb); | 795 | txq_id = skb_get_queue_mapping(skb); |
776 | if (ieee80211_is_data_qos(fc)) { | 796 | if (ieee80211_is_data_qos(fc)) { |
777 | qc = ieee80211_get_qos_ctl(hdr); | 797 | qc = ieee80211_get_qos_ctl(hdr); |
@@ -931,6 +951,17 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
931 | ret = iwl_txq_update_write_ptr(priv, txq); | 951 | ret = iwl_txq_update_write_ptr(priv, txq); |
932 | spin_unlock_irqrestore(&priv->lock, flags); | 952 | spin_unlock_irqrestore(&priv->lock, flags); |
933 | 953 | ||
954 | /* | ||
955 | * At this point the frame is "transmitted" successfully | ||
956 | * and we will get a TX status notification eventually, | ||
957 | * regardless of the value of ret. "ret" only indicates | ||
958 | * whether or not we should update the write pointer. | ||
959 | */ | ||
960 | |||
961 | /* avoid atomic ops if it isn't an associated client */ | ||
962 | if (sta_priv && sta_priv->client) | ||
963 | atomic_inc(&sta_priv->pending_frames); | ||
964 | |||
934 | if (ret) | 965 | if (ret) |
935 | return ret; | 966 | return ret; |
936 | 967 | ||
@@ -992,7 +1023,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
992 | } | 1023 | } |
993 | 1024 | ||
994 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { | 1025 | if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { |
995 | IWL_ERR(priv, "No space for Tx\n"); | 1026 | IWL_ERR(priv, "No space in command queue\n"); |
996 | if (iwl_within_ct_kill_margin(priv)) | 1027 | if (iwl_within_ct_kill_margin(priv)) |
997 | iwl_tt_enter_ct_kill(priv); | 1028 | iwl_tt_enter_ct_kill(priv); |
998 | else { | 1029 | else { |
@@ -1075,6 +1106,24 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
1075 | return ret ? ret : idx; | 1106 | return ret ? ret : idx; |
1076 | } | 1107 | } |
1077 | 1108 | ||
1109 | static void iwl_tx_status(struct iwl_priv *priv, struct sk_buff *skb) | ||
1110 | { | ||
1111 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1112 | struct ieee80211_sta *sta; | ||
1113 | struct iwl_station_priv *sta_priv; | ||
1114 | |||
1115 | sta = ieee80211_find_sta(priv->vif, hdr->addr1); | ||
1116 | if (sta) { | ||
1117 | sta_priv = (void *)sta->drv_priv; | ||
1118 | /* avoid atomic ops if this isn't a client */ | ||
1119 | if (sta_priv->client && | ||
1120 | atomic_dec_return(&sta_priv->pending_frames) == 0) | ||
1121 | ieee80211_sta_block_awake(priv->hw, sta, false); | ||
1122 | } | ||
1123 | |||
1124 | ieee80211_tx_status_irqsafe(priv->hw, skb); | ||
1125 | } | ||
1126 | |||
1078 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | 1127 | int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) |
1079 | { | 1128 | { |
1080 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 1129 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
@@ -1094,7 +1143,7 @@ int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1094 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | 1143 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { |
1095 | 1144 | ||
1096 | tx_info = &txq->txb[txq->q.read_ptr]; | 1145 | tx_info = &txq->txb[txq->q.read_ptr]; |
1097 | ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); | 1146 | iwl_tx_status(priv, tx_info->skb[0]); |
1098 | tx_info->skb[0] = NULL; | 1147 | tx_info->skb[0] = NULL; |
1099 | 1148 | ||
1100 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | 1149 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) |
@@ -1264,7 +1313,7 @@ int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) | |||
1264 | if (tid_data->tfds_in_queue == 0) { | 1313 | if (tid_data->tfds_in_queue == 0) { |
1265 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); | 1314 | IWL_DEBUG_HT(priv, "HW queue is empty\n"); |
1266 | tid_data->agg.state = IWL_AGG_ON; | 1315 | tid_data->agg.state = IWL_AGG_ON; |
1267 | ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); | 1316 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1268 | } else { | 1317 | } else { |
1269 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", | 1318 | IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", |
1270 | tid_data->tfds_in_queue); | 1319 | tid_data->tfds_in_queue); |
@@ -1329,7 +1378,7 @@ int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) | |||
1329 | if (ret) | 1378 | if (ret) |
1330 | return ret; | 1379 | return ret; |
1331 | 1380 | ||
1332 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); | 1381 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, ra, tid); |
1333 | 1382 | ||
1334 | return 0; | 1383 | return 0; |
1335 | } | 1384 | } |
@@ -1353,7 +1402,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | |||
1353 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, | 1402 | priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, |
1354 | ssn, tx_fifo); | 1403 | ssn, tx_fifo); |
1355 | tid_data->agg.state = IWL_AGG_OFF; | 1404 | tid_data->agg.state = IWL_AGG_OFF; |
1356 | ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); | 1405 | ieee80211_stop_tx_ba_cb_irqsafe(priv->vif, addr, tid); |
1357 | } | 1406 | } |
1358 | break; | 1407 | break; |
1359 | case IWL_EMPTYING_HW_QUEUE_ADDBA: | 1408 | case IWL_EMPTYING_HW_QUEUE_ADDBA: |
@@ -1361,7 +1410,7 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) | |||
1361 | if (tid_data->tfds_in_queue == 0) { | 1410 | if (tid_data->tfds_in_queue == 0) { |
1362 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); | 1411 | IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); |
1363 | tid_data->agg.state = IWL_AGG_ON; | 1412 | tid_data->agg.state = IWL_AGG_ON; |
1364 | ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); | 1413 | ieee80211_start_tx_ba_cb_irqsafe(priv->vif, addr, tid); |
1365 | } | 1414 | } |
1366 | break; | 1415 | break; |
1367 | } | 1416 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 5d26330b43e8..0db9b79a69a6 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -1483,7 +1483,6 @@ static inline void iwl_synchronize_irq(struct iwl_priv *priv) | |||
1483 | tasklet_kill(&priv->irq_tasklet); | 1483 | tasklet_kill(&priv->irq_tasklet); |
1484 | } | 1484 | } |
1485 | 1485 | ||
1486 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
1487 | static const char *desc_lookup(int i) | 1486 | static const char *desc_lookup(int i) |
1488 | { | 1487 | { |
1489 | switch (i) { | 1488 | switch (i) { |
@@ -1614,10 +1613,42 @@ static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, | |||
1614 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); | 1613 | spin_unlock_irqrestore(&priv->reg_lock, reg_flags); |
1615 | } | 1614 | } |
1616 | 1615 | ||
1616 | /** | ||
1617 | * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog | ||
1618 | */ | ||
1619 | static void iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity, | ||
1620 | u32 num_wraps, u32 next_entry, | ||
1621 | u32 size, u32 mode) | ||
1622 | { | ||
1623 | /* | ||
1624 | * display the newest DEFAULT_LOG_ENTRIES entries | ||
1625 | * i.e the entries just before the next ont that uCode would fill. | ||
1626 | */ | ||
1627 | if (num_wraps) { | ||
1628 | if (next_entry < size) { | ||
1629 | iwl3945_print_event_log(priv, | ||
1630 | capacity - (size - next_entry), | ||
1631 | size - next_entry, mode); | ||
1632 | iwl3945_print_event_log(priv, 0, | ||
1633 | next_entry, mode); | ||
1634 | } else | ||
1635 | iwl3945_print_event_log(priv, next_entry - size, | ||
1636 | size, mode); | ||
1637 | } else { | ||
1638 | if (next_entry < size) | ||
1639 | iwl3945_print_event_log(priv, 0, next_entry, mode); | ||
1640 | else | ||
1641 | iwl3945_print_event_log(priv, next_entry - size, | ||
1642 | size, mode); | ||
1643 | } | ||
1644 | } | ||
1645 | |||
1617 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ | 1646 | /* For sanity check only. Actual size is determined by uCode, typ. 512 */ |
1618 | #define IWL3945_MAX_EVENT_LOG_SIZE (512) | 1647 | #define IWL3945_MAX_EVENT_LOG_SIZE (512) |
1619 | 1648 | ||
1620 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | 1649 | #define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20) |
1650 | |||
1651 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log) | ||
1621 | { | 1652 | { |
1622 | u32 base; /* SRAM byte address of event log header */ | 1653 | u32 base; /* SRAM byte address of event log header */ |
1623 | u32 capacity; /* event log capacity in # entries */ | 1654 | u32 capacity; /* event log capacity in # entries */ |
@@ -1658,8 +1689,17 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | |||
1658 | return; | 1689 | return; |
1659 | } | 1690 | } |
1660 | 1691 | ||
1661 | IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", | 1692 | #ifdef CONFIG_IWLWIFI_DEBUG |
1662 | size, num_wraps); | 1693 | if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS)) |
1694 | size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) | ||
1695 | ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; | ||
1696 | #else | ||
1697 | size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES) | ||
1698 | ? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size; | ||
1699 | #endif | ||
1700 | |||
1701 | IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n", | ||
1702 | size); | ||
1663 | 1703 | ||
1664 | /* if uCode has wrapped back to top of log, start at the oldest entry, | 1704 | /* if uCode has wrapped back to top of log, start at the oldest entry, |
1665 | * i.e the next one that uCode would fill. */ | 1705 | * i.e the next one that uCode would fill. */ |
@@ -1670,18 +1710,28 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | |||
1670 | /* (then/else) start at top of log */ | 1710 | /* (then/else) start at top of log */ |
1671 | iwl3945_print_event_log(priv, 0, next_entry, mode); | 1711 | iwl3945_print_event_log(priv, 0, next_entry, mode); |
1672 | 1712 | ||
1673 | } | 1713 | #ifdef CONFIG_IWLWIFI_DEBUG |
1714 | if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { | ||
1715 | /* if uCode has wrapped back to top of log, | ||
1716 | * start at the oldest entry, | ||
1717 | * i.e the next one that uCode would fill. | ||
1718 | */ | ||
1719 | if (num_wraps) | ||
1720 | iwl3945_print_event_log(priv, next_entry, | ||
1721 | capacity - next_entry, mode); | ||
1722 | |||
1723 | /* (then/else) start at top of log */ | ||
1724 | iwl3945_print_event_log(priv, 0, next_entry, mode); | ||
1725 | } else | ||
1726 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, | ||
1727 | next_entry, size, mode); | ||
1674 | #else | 1728 | #else |
1675 | void iwl3945_dump_nic_event_log(struct iwl_priv *priv) | 1729 | iwl3945_print_last_event_logs(priv, capacity, num_wraps, |
1676 | { | 1730 | next_entry, size, mode); |
1677 | } | 1731 | #endif |
1678 | 1732 | ||
1679 | void iwl3945_dump_nic_error_log(struct iwl_priv *priv) | ||
1680 | { | ||
1681 | } | 1733 | } |
1682 | 1734 | ||
1683 | #endif | ||
1684 | |||
1685 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) | 1735 | static void iwl3945_irq_tasklet(struct iwl_priv *priv) |
1686 | { | 1736 | { |
1687 | u32 inta, handled = 0; | 1737 | u32 inta, handled = 0; |
@@ -2494,7 +2544,7 @@ static void iwl3945_alive_start(struct iwl_priv *priv) | |||
2494 | priv->active_rate = priv->rates_mask; | 2544 | priv->active_rate = priv->rates_mask; |
2495 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; | 2545 | priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; |
2496 | 2546 | ||
2497 | iwl_power_update_mode(priv, false); | 2547 | iwl_power_update_mode(priv, true); |
2498 | 2548 | ||
2499 | if (iwl_is_associated(priv)) { | 2549 | if (iwl_is_associated(priv)) { |
2500 | struct iwl3945_rxon_cmd *active_rxon = | 2550 | struct iwl3945_rxon_cmd *active_rxon = |
@@ -3650,7 +3700,7 @@ static ssize_t show_statistics(struct device *d, | |||
3650 | return -EAGAIN; | 3700 | return -EAGAIN; |
3651 | 3701 | ||
3652 | mutex_lock(&priv->mutex); | 3702 | mutex_lock(&priv->mutex); |
3653 | rc = iwl_send_statistics_request(priv, 0); | 3703 | rc = iwl_send_statistics_request(priv, CMD_SYNC, false); |
3654 | mutex_unlock(&priv->mutex); | 3704 | mutex_unlock(&priv->mutex); |
3655 | 3705 | ||
3656 | if (rc) { | 3706 | if (rc) { |
@@ -3905,10 +3955,8 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) | |||
3905 | BIT(NL80211_IFTYPE_STATION) | | 3955 | BIT(NL80211_IFTYPE_STATION) | |
3906 | BIT(NL80211_IFTYPE_ADHOC); | 3956 | BIT(NL80211_IFTYPE_ADHOC); |
3907 | 3957 | ||
3908 | hw->wiphy->custom_regulatory = true; | 3958 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY | |
3909 | 3959 | WIPHY_FLAG_DISABLE_BEACON_HINTS; | |
3910 | /* Firmware does not support this */ | ||
3911 | hw->wiphy->disable_beacon_hints = true; | ||
3912 | 3960 | ||
3913 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; | 3961 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; |
3914 | /* we create the 802.11 header and a zero-length SSID element */ | 3962 | /* we create the 802.11 header and a zero-length SSID element */ |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fc4ec48eda12..88e41176e7fd 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -1146,46 +1146,46 @@ static int __init init_mac80211_hwsim(void) | |||
1146 | break; | 1146 | break; |
1147 | case HWSIM_REGTEST_WORLD_ROAM: | 1147 | case HWSIM_REGTEST_WORLD_ROAM: |
1148 | if (i == 0) { | 1148 | if (i == 0) { |
1149 | hw->wiphy->custom_regulatory = true; | 1149 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1150 | wiphy_apply_custom_regulatory(hw->wiphy, | 1150 | wiphy_apply_custom_regulatory(hw->wiphy, |
1151 | &hwsim_world_regdom_custom_01); | 1151 | &hwsim_world_regdom_custom_01); |
1152 | } | 1152 | } |
1153 | break; | 1153 | break; |
1154 | case HWSIM_REGTEST_CUSTOM_WORLD: | 1154 | case HWSIM_REGTEST_CUSTOM_WORLD: |
1155 | hw->wiphy->custom_regulatory = true; | 1155 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1156 | wiphy_apply_custom_regulatory(hw->wiphy, | 1156 | wiphy_apply_custom_regulatory(hw->wiphy, |
1157 | &hwsim_world_regdom_custom_01); | 1157 | &hwsim_world_regdom_custom_01); |
1158 | break; | 1158 | break; |
1159 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | 1159 | case HWSIM_REGTEST_CUSTOM_WORLD_2: |
1160 | if (i == 0) { | 1160 | if (i == 0) { |
1161 | hw->wiphy->custom_regulatory = true; | 1161 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1162 | wiphy_apply_custom_regulatory(hw->wiphy, | 1162 | wiphy_apply_custom_regulatory(hw->wiphy, |
1163 | &hwsim_world_regdom_custom_01); | 1163 | &hwsim_world_regdom_custom_01); |
1164 | } else if (i == 1) { | 1164 | } else if (i == 1) { |
1165 | hw->wiphy->custom_regulatory = true; | 1165 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1166 | wiphy_apply_custom_regulatory(hw->wiphy, | 1166 | wiphy_apply_custom_regulatory(hw->wiphy, |
1167 | &hwsim_world_regdom_custom_02); | 1167 | &hwsim_world_regdom_custom_02); |
1168 | } | 1168 | } |
1169 | break; | 1169 | break; |
1170 | case HWSIM_REGTEST_STRICT_ALL: | 1170 | case HWSIM_REGTEST_STRICT_ALL: |
1171 | hw->wiphy->strict_regulatory = true; | 1171 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; |
1172 | break; | 1172 | break; |
1173 | case HWSIM_REGTEST_STRICT_FOLLOW: | 1173 | case HWSIM_REGTEST_STRICT_FOLLOW: |
1174 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | 1174 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: |
1175 | if (i == 0) | 1175 | if (i == 0) |
1176 | hw->wiphy->strict_regulatory = true; | 1176 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; |
1177 | break; | 1177 | break; |
1178 | case HWSIM_REGTEST_ALL: | 1178 | case HWSIM_REGTEST_ALL: |
1179 | if (i == 0) { | 1179 | if (i == 0) { |
1180 | hw->wiphy->custom_regulatory = true; | 1180 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1181 | wiphy_apply_custom_regulatory(hw->wiphy, | 1181 | wiphy_apply_custom_regulatory(hw->wiphy, |
1182 | &hwsim_world_regdom_custom_01); | 1182 | &hwsim_world_regdom_custom_01); |
1183 | } else if (i == 1) { | 1183 | } else if (i == 1) { |
1184 | hw->wiphy->custom_regulatory = true; | 1184 | hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; |
1185 | wiphy_apply_custom_regulatory(hw->wiphy, | 1185 | wiphy_apply_custom_regulatory(hw->wiphy, |
1186 | &hwsim_world_regdom_custom_02); | 1186 | &hwsim_world_regdom_custom_02); |
1187 | } else if (i == 4) | 1187 | } else if (i == 4) |
1188 | hw->wiphy->strict_regulatory = true; | 1188 | hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; |
1189 | break; | 1189 | break; |
1190 | default: | 1190 | default: |
1191 | break; | 1191 | break; |
diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c index 4d486bf9f725..18012dbfb45d 100644 --- a/drivers/net/wireless/p54/main.c +++ b/drivers/net/wireless/p54/main.c | |||
@@ -579,7 +579,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
579 | * For now, disable PS by default because it affects | 579 | * For now, disable PS by default because it affects |
580 | * link stability significantly. | 580 | * link stability significantly. |
581 | */ | 581 | */ |
582 | dev->wiphy->ps_default = false; | 582 | dev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
583 | 583 | ||
584 | mutex_init(&priv->conf_mutex); | 584 | mutex_init(&priv->conf_mutex); |
585 | mutex_init(&priv->eeprom_mutex); | 585 | mutex_init(&priv->eeprom_mutex); |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index aa1880add186..2ecbedb26e15 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -83,11 +83,11 @@ MODULE_PARM_DESC(roamdelta, | |||
83 | "set roaming tendency: 0=aggressive, 1=moderate, " | 83 | "set roaming tendency: 0=aggressive, 1=moderate, " |
84 | "2=conservative (default: moderate)"); | 84 | "2=conservative (default: moderate)"); |
85 | 85 | ||
86 | static int modparam_workaround_interval = 500; | 86 | static int modparam_workaround_interval; |
87 | module_param_named(workaround_interval, modparam_workaround_interval, | 87 | module_param_named(workaround_interval, modparam_workaround_interval, |
88 | int, 0444); | 88 | int, 0444); |
89 | MODULE_PARM_DESC(workaround_interval, | 89 | MODULE_PARM_DESC(workaround_interval, |
90 | "set stall workaround interval in msecs (default: 500)"); | 90 | "set stall workaround interval in msecs (0=disabled) (default: 0)"); |
91 | 91 | ||
92 | 92 | ||
93 | /* various RNDIS OID defs */ | 93 | /* various RNDIS OID defs */ |
@@ -733,12 +733,13 @@ static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) | |||
733 | le32_to_cpu(u.get_c->status)); | 733 | le32_to_cpu(u.get_c->status)); |
734 | 734 | ||
735 | if (ret == 0) { | 735 | if (ret == 0) { |
736 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); | ||
737 | |||
736 | ret = le32_to_cpu(u.get_c->len); | 738 | ret = le32_to_cpu(u.get_c->len); |
737 | if (ret > *len) | 739 | if (ret > *len) |
738 | *len = ret; | 740 | *len = ret; |
739 | memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); | ||
740 | ret = rndis_error_status(u.get_c->status); | ||
741 | 741 | ||
742 | ret = rndis_error_status(u.get_c->status); | ||
742 | if (ret < 0) | 743 | if (ret < 0) |
743 | devdbg(dev, "rndis_query_oid(%s): device returned " | 744 | devdbg(dev, "rndis_query_oid(%s): device returned " |
744 | "error, 0x%08x (%d)", oid_to_string(oid), | 745 | "error, 0x%08x (%d)", oid_to_string(oid), |
@@ -2549,7 +2550,7 @@ static void rndis_device_poller(struct work_struct *work) | |||
2549 | /* Workaround transfer stalls on poor quality links. | 2550 | /* Workaround transfer stalls on poor quality links. |
2550 | * TODO: find right way to fix these stalls (as stalls do not happen | 2551 | * TODO: find right way to fix these stalls (as stalls do not happen |
2551 | * with ndiswrapper/windows driver). */ | 2552 | * with ndiswrapper/windows driver). */ |
2552 | if (priv->last_qual <= 25) { | 2553 | if (priv->param_workaround_interval > 0 && priv->last_qual <= 25) { |
2553 | /* Decrease stats worker interval to catch stalls. | 2554 | /* Decrease stats worker interval to catch stalls. |
2554 | * faster. Faster than 400-500ms causes packet loss, | 2555 | * faster. Faster than 400-500ms causes packet loss, |
2555 | * Slower doesn't catch stalls fast enough. | 2556 | * Slower doesn't catch stalls fast enough. |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index b1d63935f44d..9ab15c480701 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -824,17 +824,23 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
824 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, | 824 | { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, |
825 | /* Amit */ | 825 | /* Amit */ |
826 | { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | 826 | { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, |
827 | /* Askey */ | ||
828 | { USB_DEVICE(0x1690, 0x0740), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
829 | { USB_DEVICE(0x1690, 0x0744), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
830 | { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
827 | /* ASUS */ | 831 | /* ASUS */ |
828 | { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, | 832 | { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, |
829 | { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, | 833 | { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, |
830 | { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, | 834 | { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, |
831 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, | 835 | { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, |
832 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, | 836 | { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, |
837 | { USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
833 | /* AzureWave */ | 838 | /* AzureWave */ |
834 | { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, | 839 | { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, |
835 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, | 840 | { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, |
836 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, | 841 | { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, |
837 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, | 842 | { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, |
843 | { USB_DEVICE(0x13d3, 0x3305), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
838 | /* Belkin */ | 844 | /* Belkin */ |
839 | { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, | 845 | { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, |
840 | { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 846 | { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -843,6 +849,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
843 | /* Buffalo */ | 849 | /* Buffalo */ |
844 | { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, | 850 | { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, |
845 | { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 851 | { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
852 | /* Cisco */ | ||
853 | { USB_DEVICE(0x167b, 0x4001), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
846 | /* Conceptronic */ | 854 | /* Conceptronic */ |
847 | { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, | 855 | { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, |
848 | { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, | 856 | { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -858,6 +866,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
858 | { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 866 | { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
859 | { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 867 | { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
860 | { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 868 | { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
869 | { USB_DEVICE(0x07aa, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
870 | { USB_DEVICE(0x07aa, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
861 | { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, | 871 | { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, |
862 | { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, | 872 | { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, |
863 | /* D-Link */ | 873 | /* D-Link */ |
@@ -869,18 +879,24 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
869 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 879 | { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
870 | { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, | 880 | { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, |
871 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, | 881 | { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, |
882 | { USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
872 | /* Edimax */ | 883 | /* Edimax */ |
873 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, | 884 | { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, |
874 | { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, | 885 | { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, |
875 | { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, | 886 | { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, |
876 | /* Encore */ | 887 | /* Encore */ |
877 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, | 888 | { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, |
889 | { USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
890 | { USB_DEVICE(0x203d, 0x14a9), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
878 | /* EnGenius */ | 891 | /* EnGenius */ |
879 | { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, | 892 | { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, |
880 | { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, | 893 | { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, |
881 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, | 894 | { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, |
882 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, | 895 | { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, |
883 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, | 896 | { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, |
897 | { USB_DEVICE(0x1740, 0x9707), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
898 | { USB_DEVICE(0x1740, 0x9708), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
899 | { USB_DEVICE(0x1740, 0x9709), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
884 | { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, | 900 | { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, |
885 | /* Gemtek */ | 901 | /* Gemtek */ |
886 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, | 902 | { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -894,7 +910,10 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
894 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, | 910 | { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, |
895 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, | 911 | { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, |
896 | /* I-O DATA */ | 912 | /* I-O DATA */ |
913 | { USB_DEVICE(0x04bb, 0x0944), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
897 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, | 914 | { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, |
915 | { USB_DEVICE(0x04bb, 0x0947), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
916 | { USB_DEVICE(0x04bb, 0x0948), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
898 | /* LevelOne */ | 917 | /* LevelOne */ |
899 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, | 918 | { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, |
900 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, | 919 | { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -909,8 +928,18 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
909 | /* Motorola */ | 928 | /* Motorola */ |
910 | { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, | 929 | { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, |
911 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, | 930 | { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, |
931 | /* MSI */ | ||
932 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
933 | { USB_DEVICE(0x0db0, 0x3821), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
934 | { USB_DEVICE(0x0db0, 0x3870), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
935 | { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
936 | { USB_DEVICE(0x0db0, 0x821a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
937 | { USB_DEVICE(0x0db0, 0x870a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
938 | { USB_DEVICE(0x0db0, 0x899a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
912 | /* Ovislink */ | 939 | /* Ovislink */ |
913 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, | 940 | { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, |
941 | /* Para */ | ||
942 | { USB_DEVICE(0x20b8, 0x8888), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
914 | /* Pegatron */ | 943 | /* Pegatron */ |
915 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, | 944 | { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, |
916 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, | 945 | { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -926,8 +955,6 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
926 | /* Quanta */ | 955 | /* Quanta */ |
927 | { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, | 956 | { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, |
928 | /* Ralink */ | 957 | /* Ralink */ |
929 | { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
930 | { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
931 | { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, | 958 | { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, |
932 | { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, | 959 | { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, |
933 | { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, | 960 | { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -951,7 +978,12 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
951 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, | 978 | { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, |
952 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, | 979 | { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, |
953 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, | 980 | { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, |
981 | { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
954 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, | 982 | { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, |
983 | { USB_DEVICE(0x0df6, 0x0047), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
984 | { USB_DEVICE(0x0df6, 0x0048), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
985 | { USB_DEVICE(0x0df6, 0x004a), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
986 | { USB_DEVICE(0x0df6, 0x004d), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
955 | /* SMC */ | 987 | /* SMC */ |
956 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, | 988 | { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, |
957 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, | 989 | { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, |
@@ -960,6 +992,8 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
960 | { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 992 | { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
961 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, | 993 | { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, |
962 | { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, | 994 | { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, |
995 | { USB_DEVICE(0x083a, 0xa701), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
996 | { USB_DEVICE(0x083a, 0xa702), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
963 | { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 997 | { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
964 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, | 998 | { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, |
965 | /* Sparklan */ | 999 | /* Sparklan */ |
@@ -977,6 +1011,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
977 | { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1011 | { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, |
978 | { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1012 | { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, |
979 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1013 | { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, |
1014 | { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, | ||
980 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1015 | { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, |
981 | /* Zyxel */ | 1016 | /* Zyxel */ |
982 | { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, | 1017 | { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 6c6d0ac35549..4a4b7e42fe6e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -205,6 +205,7 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
205 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | 205 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); |
206 | unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); | 206 | unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); |
207 | u8 rate_idx, rate_flags, retry_rates; | 207 | u8 rate_idx, rate_flags, retry_rates; |
208 | u8 skbdesc_flags = skbdesc->flags; | ||
208 | unsigned int i; | 209 | unsigned int i; |
209 | bool success; | 210 | bool success; |
210 | 211 | ||
@@ -287,12 +288,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
287 | } | 288 | } |
288 | 289 | ||
289 | /* | 290 | /* |
290 | * Only send the status report to mac80211 when TX status was | 291 | * Only send the status report to mac80211 when it's a frame |
291 | * requested by it. If this was a extra frame coming through | 292 | * that originated in mac80211. If this was a extra frame coming |
292 | * a mac80211 library call (RTS/CTS) then we should not send the | 293 | * through a mac80211 library call (RTS/CTS) then we should not |
293 | * status report back. | 294 | * send the status report back. |
294 | */ | 295 | */ |
295 | if (tx_info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) | 296 | if (!(skbdesc_flags & SKBDESC_NOT_MAC80211)) |
296 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | 297 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); |
297 | else | 298 | else |
298 | dev_kfree_skb_irq(entry->skb); | 299 | dev_kfree_skb_irq(entry->skb); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h index c1f48acaee41..be2e37fb4071 100644 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ b/drivers/net/wireless/rt2x00/rt2x00lib.h | |||
@@ -162,8 +162,10 @@ void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length); | |||
162 | * rt2x00queue_write_tx_frame - Write TX frame to hardware | 162 | * rt2x00queue_write_tx_frame - Write TX frame to hardware |
163 | * @queue: Queue over which the frame should be send | 163 | * @queue: Queue over which the frame should be send |
164 | * @skb: The skb to send | 164 | * @skb: The skb to send |
165 | * @local: frame is not from mac80211 | ||
165 | */ | 166 | */ |
166 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); | 167 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, |
168 | bool local); | ||
167 | 169 | ||
168 | /** | 170 | /** |
169 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware | 171 | * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index eed093d34532..9c90ceb0ffcc 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -66,7 +66,6 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
66 | rts_info = IEEE80211_SKB_CB(skb); | 66 | rts_info = IEEE80211_SKB_CB(skb); |
67 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; | 67 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; |
68 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; | 68 | rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; |
69 | rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
70 | 69 | ||
71 | if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) | 70 | if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) |
72 | rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; | 71 | rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; |
@@ -91,7 +90,7 @@ static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, | |||
91 | frag_skb->data, data_length, tx_info, | 90 | frag_skb->data, data_length, tx_info, |
92 | (struct ieee80211_rts *)(skb->data)); | 91 | (struct ieee80211_rts *)(skb->data)); |
93 | 92 | ||
94 | retval = rt2x00queue_write_tx_frame(queue, skb); | 93 | retval = rt2x00queue_write_tx_frame(queue, skb, true); |
95 | if (retval) { | 94 | if (retval) { |
96 | dev_kfree_skb_any(skb); | 95 | dev_kfree_skb_any(skb); |
97 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); | 96 | WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); |
@@ -153,7 +152,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
153 | goto exit_fail; | 152 | goto exit_fail; |
154 | } | 153 | } |
155 | 154 | ||
156 | if (rt2x00queue_write_tx_frame(queue, skb)) | 155 | if (rt2x00queue_write_tx_frame(queue, skb, false)) |
157 | goto exit_fail; | 156 | goto exit_fail; |
158 | 157 | ||
159 | if (rt2x00queue_threshold(queue)) | 158 | if (rt2x00queue_threshold(queue)) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 02972a036bce..eaedee8c05c8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -454,7 +454,8 @@ static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, | |||
454 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); | 454 | rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); |
455 | } | 455 | } |
456 | 456 | ||
457 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | 457 | int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb, |
458 | bool local) | ||
458 | { | 459 | { |
459 | struct ieee80211_tx_info *tx_info; | 460 | struct ieee80211_tx_info *tx_info; |
460 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 461 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
@@ -495,6 +496,9 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
495 | skbdesc->tx_rate_idx = rate_idx; | 496 | skbdesc->tx_rate_idx = rate_idx; |
496 | skbdesc->tx_rate_flags = rate_flags; | 497 | skbdesc->tx_rate_flags = rate_flags; |
497 | 498 | ||
499 | if (local) | ||
500 | skbdesc->flags |= SKBDESC_NOT_MAC80211; | ||
501 | |||
498 | /* | 502 | /* |
499 | * When hardware encryption is supported, and this frame | 503 | * When hardware encryption is supported, and this frame |
500 | * is to be encrypted, we should strip the IV/EIV data from | 504 | * is to be encrypted, we should strip the IV/EIV data from |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index 97c7895c0ece..70775e5ba1ac 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h | |||
@@ -94,12 +94,15 @@ enum data_queue_qid { | |||
94 | * mac80211 but was stripped for processing by the driver. | 94 | * mac80211 but was stripped for processing by the driver. |
95 | * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, | 95 | * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, |
96 | * the padded bytes are located between header and payload. | 96 | * the padded bytes are located between header and payload. |
97 | * @SKBDESC_NOT_MAC80211: Frame didn't originate from mac80211, | ||
98 | * don't try to pass it back. | ||
97 | */ | 99 | */ |
98 | enum skb_frame_desc_flags { | 100 | enum skb_frame_desc_flags { |
99 | SKBDESC_DMA_MAPPED_RX = 1 << 0, | 101 | SKBDESC_DMA_MAPPED_RX = 1 << 0, |
100 | SKBDESC_DMA_MAPPED_TX = 1 << 1, | 102 | SKBDESC_DMA_MAPPED_TX = 1 << 1, |
101 | SKBDESC_IV_STRIPPED = 1 << 2, | 103 | SKBDESC_IV_STRIPPED = 1 << 2, |
102 | SKBDESC_L2_PADDED = 1 << 3 | 104 | SKBDESC_L2_PADDED = 1 << 3, |
105 | SKBDESC_NOT_MAC80211 = 1 << 4, | ||
103 | }; | 106 | }; |
104 | 107 | ||
105 | /** | 108 | /** |
diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h index 998e4b6252bd..054533f7a124 100644 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ b/drivers/net/wireless/wl12xx/wl1251.h | |||
@@ -269,6 +269,7 @@ struct wl1251 { | |||
269 | 269 | ||
270 | void (*set_power)(bool enable); | 270 | void (*set_power)(bool enable); |
271 | int irq; | 271 | int irq; |
272 | bool use_eeprom; | ||
272 | 273 | ||
273 | enum wl1251_state state; | 274 | enum wl1251_state state; |
274 | struct mutex mutex; | 275 | struct mutex mutex; |
@@ -354,6 +355,8 @@ struct wl1251 { | |||
354 | /* is firmware in elp mode */ | 355 | /* is firmware in elp mode */ |
355 | bool elp; | 356 | bool elp; |
356 | 357 | ||
358 | struct delayed_work elp_work; | ||
359 | |||
357 | /* we can be in psm, but not in elp, we have to differentiate */ | 360 | /* we can be in psm, but not in elp, we have to differentiate */ |
358 | bool psm; | 361 | bool psm; |
359 | 362 | ||
@@ -374,6 +377,8 @@ struct wl1251 { | |||
374 | u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; | 377 | u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; |
375 | struct wl1251_rx_descriptor *rx_descriptor; | 378 | struct wl1251_rx_descriptor *rx_descriptor; |
376 | 379 | ||
380 | struct ieee80211_vif *vif; | ||
381 | |||
377 | u32 chip_id; | 382 | u32 chip_id; |
378 | char fw_ver[21]; | 383 | char fw_ver[21]; |
379 | }; | 384 | }; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c index 10b26c4532c9..acfa086dbfc5 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ b/drivers/net/wireless/wl12xx/wl1251_acx.c | |||
@@ -494,7 +494,7 @@ out: | |||
494 | return ret; | 494 | return ret; |
495 | } | 495 | } |
496 | 496 | ||
497 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl) | 497 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter) |
498 | { | 498 | { |
499 | struct acx_beacon_filter_option *beacon_filter; | 499 | struct acx_beacon_filter_option *beacon_filter; |
500 | int ret; | 500 | int ret; |
@@ -507,7 +507,7 @@ int wl1251_acx_beacon_filter_opt(struct wl1251 *wl) | |||
507 | goto out; | 507 | goto out; |
508 | } | 508 | } |
509 | 509 | ||
510 | beacon_filter->enable = 0; | 510 | beacon_filter->enable = enable_filter; |
511 | beacon_filter->max_num_beacons = 0; | 511 | beacon_filter->max_num_beacons = 0; |
512 | 512 | ||
513 | ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT, | 513 | ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT, |
@@ -525,6 +525,7 @@ out: | |||
525 | int wl1251_acx_beacon_filter_table(struct wl1251 *wl) | 525 | int wl1251_acx_beacon_filter_table(struct wl1251 *wl) |
526 | { | 526 | { |
527 | struct acx_beacon_filter_ie_table *ie_table; | 527 | struct acx_beacon_filter_ie_table *ie_table; |
528 | int idx = 0; | ||
528 | int ret; | 529 | int ret; |
529 | 530 | ||
530 | wl1251_debug(DEBUG_ACX, "acx beacon filter table"); | 531 | wl1251_debug(DEBUG_ACX, "acx beacon filter table"); |
@@ -535,8 +536,10 @@ int wl1251_acx_beacon_filter_table(struct wl1251 *wl) | |||
535 | goto out; | 536 | goto out; |
536 | } | 537 | } |
537 | 538 | ||
538 | ie_table->num_ie = 0; | 539 | /* configure default beacon pass-through rules */ |
539 | memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); | 540 | ie_table->num_ie = 1; |
541 | ie_table->table[idx++] = BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN; | ||
542 | ie_table->table[idx++] = BEACON_RULE_PASS_ON_APPEARANCE; | ||
540 | 543 | ||
541 | ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, | 544 | ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, |
542 | ie_table, sizeof(*ie_table)); | 545 | ie_table, sizeof(*ie_table)); |
@@ -550,6 +553,35 @@ out: | |||
550 | return ret; | 553 | return ret; |
551 | } | 554 | } |
552 | 555 | ||
556 | int wl1251_acx_conn_monit_params(struct wl1251 *wl) | ||
557 | { | ||
558 | struct acx_conn_monit_params *acx; | ||
559 | int ret; | ||
560 | |||
561 | wl1251_debug(DEBUG_ACX, "acx connection monitor parameters"); | ||
562 | |||
563 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
564 | if (!acx) { | ||
565 | ret = -ENOMEM; | ||
566 | goto out; | ||
567 | } | ||
568 | |||
569 | acx->synch_fail_thold = SYNCH_FAIL_DEFAULT_THRESHOLD; | ||
570 | acx->bss_lose_timeout = NO_BEACON_DEFAULT_TIMEOUT; | ||
571 | |||
572 | ret = wl1251_cmd_configure(wl, ACX_CONN_MONIT_PARAMS, | ||
573 | acx, sizeof(*acx)); | ||
574 | if (ret < 0) { | ||
575 | wl1251_warning("failed to set connection monitor " | ||
576 | "parameters: %d", ret); | ||
577 | goto out; | ||
578 | } | ||
579 | |||
580 | out: | ||
581 | kfree(acx); | ||
582 | return ret; | ||
583 | } | ||
584 | |||
553 | int wl1251_acx_sg_enable(struct wl1251 *wl) | 585 | int wl1251_acx_sg_enable(struct wl1251 *wl) |
554 | { | 586 | { |
555 | struct acx_bt_wlan_coex *pta; | 587 | struct acx_bt_wlan_coex *pta; |
@@ -916,3 +948,31 @@ out: | |||
916 | kfree(mem_conf); | 948 | kfree(mem_conf); |
917 | return ret; | 949 | return ret; |
918 | } | 950 | } |
951 | |||
952 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim) | ||
953 | { | ||
954 | struct wl1251_acx_wr_tbtt_and_dtim *acx; | ||
955 | int ret; | ||
956 | |||
957 | wl1251_debug(DEBUG_ACX, "acx tbtt and dtim"); | ||
958 | |||
959 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
960 | if (!acx) { | ||
961 | ret = -ENOMEM; | ||
962 | goto out; | ||
963 | } | ||
964 | |||
965 | acx->tbtt = tbtt; | ||
966 | acx->dtim = dtim; | ||
967 | |||
968 | ret = wl1251_cmd_configure(wl, ACX_WR_TBTT_AND_DTIM, | ||
969 | acx, sizeof(*acx)); | ||
970 | if (ret < 0) { | ||
971 | wl1251_warning("failed to set tbtt and dtim: %d", ret); | ||
972 | goto out; | ||
973 | } | ||
974 | |||
975 | out: | ||
976 | kfree(acx); | ||
977 | return ret; | ||
978 | } | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h index cafb91459504..652371432cd8 100644 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ b/drivers/net/wireless/wl12xx/wl1251_acx.h | |||
@@ -450,6 +450,11 @@ struct acx_beacon_filter_option { | |||
450 | (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ | 450 | (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ |
451 | BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) | 451 | BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) |
452 | 452 | ||
453 | #define BEACON_RULE_PASS_ON_CHANGE BIT(0) | ||
454 | #define BEACON_RULE_PASS_ON_APPEARANCE BIT(1) | ||
455 | |||
456 | #define BEACON_FILTER_IE_ID_CHANNEL_SWITCH_ANN (37) | ||
457 | |||
453 | struct acx_beacon_filter_ie_table { | 458 | struct acx_beacon_filter_ie_table { |
454 | struct acx_header header; | 459 | struct acx_header header; |
455 | 460 | ||
@@ -458,6 +463,16 @@ struct acx_beacon_filter_ie_table { | |||
458 | u8 pad[3]; | 463 | u8 pad[3]; |
459 | } __attribute__ ((packed)); | 464 | } __attribute__ ((packed)); |
460 | 465 | ||
466 | #define SYNCH_FAIL_DEFAULT_THRESHOLD 10 /* number of beacons */ | ||
467 | #define NO_BEACON_DEFAULT_TIMEOUT (500) /* in microseconds */ | ||
468 | |||
469 | struct acx_conn_monit_params { | ||
470 | struct acx_header header; | ||
471 | |||
472 | u32 synch_fail_thold; /* number of beacons missed */ | ||
473 | u32 bss_lose_timeout; /* number of TU's from synch fail */ | ||
474 | }; | ||
475 | |||
461 | enum { | 476 | enum { |
462 | SG_ENABLE = 0, | 477 | SG_ENABLE = 0, |
463 | SG_DISABLE, | 478 | SG_DISABLE, |
@@ -1134,6 +1149,23 @@ struct wl1251_acx_mem_map { | |||
1134 | u32 num_rx_mem_blocks; | 1149 | u32 num_rx_mem_blocks; |
1135 | } __attribute__ ((packed)); | 1150 | } __attribute__ ((packed)); |
1136 | 1151 | ||
1152 | |||
1153 | struct wl1251_acx_wr_tbtt_and_dtim { | ||
1154 | |||
1155 | struct acx_header header; | ||
1156 | |||
1157 | /* Time in TUs between two consecutive beacons */ | ||
1158 | u16 tbtt; | ||
1159 | |||
1160 | /* | ||
1161 | * DTIM period | ||
1162 | * For BSS: Number of TBTTs in a DTIM period (range: 1-10) | ||
1163 | * For IBSS: value shall be set to 1 | ||
1164 | */ | ||
1165 | u8 dtim; | ||
1166 | u8 padding; | ||
1167 | } __attribute__ ((packed)); | ||
1168 | |||
1137 | /************************************************************************* | 1169 | /************************************************************************* |
1138 | 1170 | ||
1139 | Host Interrupt Register (WiLink -> Host) | 1171 | Host Interrupt Register (WiLink -> Host) |
@@ -1273,8 +1305,9 @@ int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time); | |||
1273 | int wl1251_acx_group_address_tbl(struct wl1251 *wl); | 1305 | int wl1251_acx_group_address_tbl(struct wl1251 *wl); |
1274 | int wl1251_acx_service_period_timeout(struct wl1251 *wl); | 1306 | int wl1251_acx_service_period_timeout(struct wl1251 *wl); |
1275 | int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); | 1307 | int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); |
1276 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl); | 1308 | int wl1251_acx_beacon_filter_opt(struct wl1251 *wl, bool enable_filter); |
1277 | int wl1251_acx_beacon_filter_table(struct wl1251 *wl); | 1309 | int wl1251_acx_beacon_filter_table(struct wl1251 *wl); |
1310 | int wl1251_acx_conn_monit_params(struct wl1251 *wl); | ||
1278 | int wl1251_acx_sg_enable(struct wl1251 *wl); | 1311 | int wl1251_acx_sg_enable(struct wl1251 *wl); |
1279 | int wl1251_acx_sg_cfg(struct wl1251 *wl); | 1312 | int wl1251_acx_sg_cfg(struct wl1251 *wl); |
1280 | int wl1251_acx_cca_threshold(struct wl1251 *wl); | 1313 | int wl1251_acx_cca_threshold(struct wl1251 *wl); |
@@ -1288,5 +1321,6 @@ int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats); | |||
1288 | int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); | 1321 | int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); |
1289 | int wl1251_acx_rate_policies(struct wl1251 *wl); | 1322 | int wl1251_acx_rate_policies(struct wl1251 *wl); |
1290 | int wl1251_acx_mem_cfg(struct wl1251 *wl); | 1323 | int wl1251_acx_mem_cfg(struct wl1251 *wl); |
1324 | int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim); | ||
1291 | 1325 | ||
1292 | #endif /* __WL1251_ACX_H__ */ | 1326 | #endif /* __WL1251_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c index 452d748e42c6..2e733e7bdfd4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ b/drivers/net/wireless/wl12xx/wl1251_boot.c | |||
@@ -296,8 +296,12 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
296 | WL1251_ACX_INTR_INIT_COMPLETE; | 296 | WL1251_ACX_INTR_INIT_COMPLETE; |
297 | wl1251_boot_target_enable_interrupts(wl); | 297 | wl1251_boot_target_enable_interrupts(wl); |
298 | 298 | ||
299 | /* unmask all mbox events */ | 299 | wl->event_mask = SCAN_COMPLETE_EVENT_ID | BSS_LOSE_EVENT_ID | |
300 | wl->event_mask = 0xffffffff; | 300 | SYNCHRONIZATION_TIMEOUT_EVENT_ID | |
301 | ROAMING_TRIGGER_LOW_RSSI_EVENT_ID | | ||
302 | ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID | | ||
303 | REGAINED_BSS_EVENT_ID | BT_PTA_SENSE_EVENT_ID | | ||
304 | BT_PTA_PREDICTION_EVENT_ID; | ||
301 | 305 | ||
302 | ret = wl1251_event_unmask(wl); | 306 | ret = wl1251_event_unmask(wl); |
303 | if (ret < 0) { | 307 | if (ret < 0) { |
@@ -314,8 +318,8 @@ int wl1251_boot_run_firmware(struct wl1251 *wl) | |||
314 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) | 318 | static int wl1251_boot_upload_firmware(struct wl1251 *wl) |
315 | { | 319 | { |
316 | int addr, chunk_num, partition_limit; | 320 | int addr, chunk_num, partition_limit; |
317 | size_t fw_data_len; | 321 | size_t fw_data_len, len; |
318 | u8 *p; | 322 | u8 *p, *buf; |
319 | 323 | ||
320 | /* whal_FwCtrl_LoadFwImageSm() */ | 324 | /* whal_FwCtrl_LoadFwImageSm() */ |
321 | 325 | ||
@@ -334,6 +338,12 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
334 | return -EIO; | 338 | return -EIO; |
335 | } | 339 | } |
336 | 340 | ||
341 | buf = kmalloc(CHUNK_SIZE, GFP_KERNEL); | ||
342 | if (!buf) { | ||
343 | wl1251_error("allocation for firmware upload chunk failed"); | ||
344 | return -ENOMEM; | ||
345 | } | ||
346 | |||
337 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, | 347 | wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, |
338 | WL1251_PART_DOWN_MEM_SIZE, | 348 | WL1251_PART_DOWN_MEM_SIZE, |
339 | WL1251_PART_DOWN_REG_START, | 349 | WL1251_PART_DOWN_REG_START, |
@@ -364,7 +374,11 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
364 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | 374 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; |
365 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", | 375 | wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", |
366 | p, addr); | 376 | p, addr); |
367 | wl1251_mem_write(wl, addr, p, CHUNK_SIZE); | 377 | |
378 | /* need to copy the chunk for dma */ | ||
379 | len = CHUNK_SIZE; | ||
380 | memcpy(buf, p, len); | ||
381 | wl1251_mem_write(wl, addr, buf, len); | ||
368 | 382 | ||
369 | chunk_num++; | 383 | chunk_num++; |
370 | } | 384 | } |
@@ -372,9 +386,16 @@ static int wl1251_boot_upload_firmware(struct wl1251 *wl) | |||
372 | /* 10.4 upload the last chunk */ | 386 | /* 10.4 upload the last chunk */ |
373 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; | 387 | addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; |
374 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; | 388 | p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; |
389 | |||
390 | /* need to copy the chunk for dma */ | ||
391 | len = fw_data_len % CHUNK_SIZE; | ||
392 | memcpy(buf, p, len); | ||
393 | |||
375 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", | 394 | wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", |
376 | fw_data_len % CHUNK_SIZE, p, addr); | 395 | len, p, addr); |
377 | wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); | 396 | wl1251_mem_write(wl, addr, buf, len); |
397 | |||
398 | kfree(buf); | ||
378 | 399 | ||
379 | return 0; | 400 | return 0; |
380 | } | 401 | } |
@@ -473,13 +494,19 @@ int wl1251_boot(struct wl1251 *wl) | |||
473 | goto out; | 494 | goto out; |
474 | 495 | ||
475 | /* 2. start processing NVS file */ | 496 | /* 2. start processing NVS file */ |
476 | ret = wl1251_boot_upload_nvs(wl); | 497 | if (wl->use_eeprom) { |
477 | if (ret < 0) | 498 | wl1251_reg_write32(wl, ACX_REG_EE_START, START_EEPROM_MGR); |
478 | goto out; | 499 | msleep(4000); |
479 | 500 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, USE_EEPROM); | |
480 | /* write firmware's last address (ie. it's length) to | 501 | } else { |
481 | * ACX_EEPROMLESS_IND_REG */ | 502 | ret = wl1251_boot_upload_nvs(wl); |
482 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); | 503 | if (ret < 0) |
504 | goto out; | ||
505 | |||
506 | /* write firmware's last address (ie. it's length) to | ||
507 | * ACX_EEPROMLESS_IND_REG */ | ||
508 | wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); | ||
509 | } | ||
483 | 510 | ||
484 | /* 6. read the EEPROM parameters */ | 511 | /* 6. read the EEPROM parameters */ |
485 | tmp = wl1251_reg_read32(wl, SCR_PAD2); | 512 | tmp = wl1251_reg_read32(wl, SCR_PAD2); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c index 00076c4a8a21..020d764f9c13 100644 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ b/drivers/net/wireless/wl12xx/wl1251_event.c | |||
@@ -79,6 +79,21 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) | |||
79 | } | 79 | } |
80 | } | 80 | } |
81 | 81 | ||
82 | if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) { | ||
83 | wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT"); | ||
84 | |||
85 | /* indicate to the stack, that beacons have been lost */ | ||
86 | ieee80211_beacon_loss(wl->vif); | ||
87 | } | ||
88 | |||
89 | if (vector & REGAINED_BSS_EVENT_ID) { | ||
90 | if (wl->psm_requested) { | ||
91 | ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); | ||
92 | if (ret < 0) | ||
93 | return ret; | ||
94 | } | ||
95 | } | ||
96 | |||
82 | return 0; | 97 | return 0; |
83 | } | 98 | } |
84 | 99 | ||
diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c index b2ee4f468fc4..5cb573383eeb 100644 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ b/drivers/net/wireless/wl12xx/wl1251_init.c | |||
@@ -147,7 +147,8 @@ int wl1251_hw_init_beacon_filter(struct wl1251 *wl) | |||
147 | { | 147 | { |
148 | int ret; | 148 | int ret; |
149 | 149 | ||
150 | ret = wl1251_acx_beacon_filter_opt(wl); | 150 | /* disable beacon filtering at this stage */ |
151 | ret = wl1251_acx_beacon_filter_opt(wl, false); | ||
151 | if (ret < 0) | 152 | if (ret < 0) |
152 | return ret; | 153 | return ret; |
153 | 154 | ||
@@ -364,6 +365,11 @@ int wl1251_hw_init(struct wl1251 *wl) | |||
364 | if (ret < 0) | 365 | if (ret < 0) |
365 | goto out_free_data_path; | 366 | goto out_free_data_path; |
366 | 367 | ||
368 | /* Initialize connection monitoring thresholds */ | ||
369 | ret = wl1251_acx_conn_monit_params(wl); | ||
370 | if (ret < 0) | ||
371 | goto out_free_data_path; | ||
372 | |||
367 | /* Beacon filtering */ | 373 | /* Beacon filtering */ |
368 | ret = wl1251_hw_init_beacon_filter(wl); | 374 | ret = wl1251_hw_init_beacon_filter(wl); |
369 | if (ret < 0) | 375 | if (ret < 0) |
diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c index d03a07e1be7c..ff4be7bf5d36 100644 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/drivers/net/wireless/wl12xx/wl1251_main.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/irq.h> | 28 | #include <linux/irq.h> |
29 | #include <linux/crc32.h> | 29 | #include <linux/crc32.h> |
30 | #include <linux/etherdevice.h> | 30 | #include <linux/etherdevice.h> |
31 | #include <linux/vmalloc.h> | ||
31 | 32 | ||
32 | #include "wl1251.h" | 33 | #include "wl1251.h" |
33 | #include "wl12xx_80211.h" | 34 | #include "wl12xx_80211.h" |
@@ -83,7 +84,7 @@ static int wl1251_fetch_firmware(struct wl1251 *wl) | |||
83 | } | 84 | } |
84 | 85 | ||
85 | wl->fw_len = fw->size; | 86 | wl->fw_len = fw->size; |
86 | wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); | 87 | wl->fw = vmalloc(wl->fw_len); |
87 | 88 | ||
88 | if (!wl->fw) { | 89 | if (!wl->fw) { |
89 | wl1251_error("could not allocate memory for the firmware"); | 90 | wl1251_error("could not allocate memory for the firmware"); |
@@ -211,9 +212,10 @@ out: | |||
211 | return ret; | 212 | return ret; |
212 | } | 213 | } |
213 | 214 | ||
215 | #define WL1251_IRQ_LOOP_COUNT 10 | ||
214 | static void wl1251_irq_work(struct work_struct *work) | 216 | static void wl1251_irq_work(struct work_struct *work) |
215 | { | 217 | { |
216 | u32 intr; | 218 | u32 intr, ctr = WL1251_IRQ_LOOP_COUNT; |
217 | struct wl1251 *wl = | 219 | struct wl1251 *wl = |
218 | container_of(work, struct wl1251, irq_work); | 220 | container_of(work, struct wl1251, irq_work); |
219 | int ret; | 221 | int ret; |
@@ -234,78 +236,86 @@ static void wl1251_irq_work(struct work_struct *work) | |||
234 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); | 236 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); |
235 | wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); | 237 | wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); |
236 | 238 | ||
237 | if (wl->data_path) { | 239 | do { |
238 | wl->rx_counter = | 240 | if (wl->data_path) { |
239 | wl1251_mem_read32(wl, wl->data_path->rx_control_addr); | 241 | wl->rx_counter = wl1251_mem_read32( |
240 | 242 | wl, wl->data_path->rx_control_addr); | |
241 | /* We handle a frmware bug here */ | 243 | |
242 | switch ((wl->rx_counter - wl->rx_handled) & 0xf) { | 244 | /* We handle a frmware bug here */ |
243 | case 0: | 245 | switch ((wl->rx_counter - wl->rx_handled) & 0xf) { |
244 | wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); | 246 | case 0: |
245 | intr &= ~WL1251_ACX_INTR_RX0_DATA; | 247 | wl1251_debug(DEBUG_IRQ, |
246 | intr &= ~WL1251_ACX_INTR_RX1_DATA; | 248 | "RX: FW and host in sync"); |
247 | break; | 249 | intr &= ~WL1251_ACX_INTR_RX0_DATA; |
248 | case 1: | 250 | intr &= ~WL1251_ACX_INTR_RX1_DATA; |
249 | wl1251_debug(DEBUG_IRQ, "RX: FW +1"); | 251 | break; |
250 | intr |= WL1251_ACX_INTR_RX0_DATA; | 252 | case 1: |
251 | intr &= ~WL1251_ACX_INTR_RX1_DATA; | 253 | wl1251_debug(DEBUG_IRQ, "RX: FW +1"); |
252 | break; | 254 | intr |= WL1251_ACX_INTR_RX0_DATA; |
253 | case 2: | 255 | intr &= ~WL1251_ACX_INTR_RX1_DATA; |
254 | wl1251_debug(DEBUG_IRQ, "RX: FW +2"); | 256 | break; |
255 | intr |= WL1251_ACX_INTR_RX0_DATA; | 257 | case 2: |
256 | intr |= WL1251_ACX_INTR_RX1_DATA; | 258 | wl1251_debug(DEBUG_IRQ, "RX: FW +2"); |
257 | break; | 259 | intr |= WL1251_ACX_INTR_RX0_DATA; |
258 | default: | 260 | intr |= WL1251_ACX_INTR_RX1_DATA; |
259 | wl1251_warning("RX: FW and host out of sync: %d", | 261 | break; |
260 | wl->rx_counter - wl->rx_handled); | 262 | default: |
261 | break; | 263 | wl1251_warning( |
262 | } | 264 | "RX: FW and host out of sync: %d", |
263 | 265 | wl->rx_counter - wl->rx_handled); | |
264 | wl->rx_handled = wl->rx_counter; | 266 | break; |
267 | } | ||
265 | 268 | ||
269 | wl->rx_handled = wl->rx_counter; | ||
266 | 270 | ||
267 | wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter); | 271 | wl1251_debug(DEBUG_IRQ, "RX counter: %d", |
268 | } | 272 | wl->rx_counter); |
273 | } | ||
269 | 274 | ||
270 | intr &= wl->intr_mask; | 275 | intr &= wl->intr_mask; |
271 | 276 | ||
272 | if (intr == 0) { | 277 | if (intr == 0) { |
273 | wl1251_debug(DEBUG_IRQ, "INTR is 0"); | 278 | wl1251_debug(DEBUG_IRQ, "INTR is 0"); |
274 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, | 279 | goto out_sleep; |
275 | ~(wl->intr_mask)); | 280 | } |
276 | 281 | ||
277 | goto out_sleep; | 282 | if (intr & WL1251_ACX_INTR_RX0_DATA) { |
278 | } | 283 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); |
284 | wl1251_rx(wl); | ||
285 | } | ||
279 | 286 | ||
280 | if (intr & WL1251_ACX_INTR_RX0_DATA) { | 287 | if (intr & WL1251_ACX_INTR_RX1_DATA) { |
281 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); | 288 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); |
282 | wl1251_rx(wl); | 289 | wl1251_rx(wl); |
283 | } | 290 | } |
284 | 291 | ||
285 | if (intr & WL1251_ACX_INTR_RX1_DATA) { | 292 | if (intr & WL1251_ACX_INTR_TX_RESULT) { |
286 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); | 293 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); |
287 | wl1251_rx(wl); | 294 | wl1251_tx_complete(wl); |
288 | } | 295 | } |
289 | 296 | ||
290 | if (intr & WL1251_ACX_INTR_TX_RESULT) { | 297 | if (intr & (WL1251_ACX_INTR_EVENT_A | |
291 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); | 298 | WL1251_ACX_INTR_EVENT_B)) { |
292 | wl1251_tx_complete(wl); | 299 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", |
293 | } | 300 | intr); |
301 | if (intr & WL1251_ACX_INTR_EVENT_A) | ||
302 | wl1251_event_handle(wl, 0); | ||
303 | else | ||
304 | wl1251_event_handle(wl, 1); | ||
305 | } | ||
294 | 306 | ||
295 | if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) { | 307 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) |
296 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr); | 308 | wl1251_debug(DEBUG_IRQ, |
297 | if (intr & WL1251_ACX_INTR_EVENT_A) | 309 | "WL1251_ACX_INTR_INIT_COMPLETE"); |
298 | wl1251_event_handle(wl, 0); | ||
299 | else | ||
300 | wl1251_event_handle(wl, 1); | ||
301 | } | ||
302 | 310 | ||
303 | if (intr & WL1251_ACX_INTR_INIT_COMPLETE) | 311 | if (--ctr == 0) |
304 | wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); | 312 | break; |
305 | 313 | ||
306 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); | 314 | intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); |
315 | } while (intr); | ||
307 | 316 | ||
308 | out_sleep: | 317 | out_sleep: |
318 | wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); | ||
309 | wl1251_ps_elp_sleep(wl); | 319 | wl1251_ps_elp_sleep(wl); |
310 | 320 | ||
311 | out: | 321 | out: |
@@ -509,6 +519,12 @@ static int wl1251_op_add_interface(struct ieee80211_hw *hw, | |||
509 | conf->type, conf->mac_addr); | 519 | conf->type, conf->mac_addr); |
510 | 520 | ||
511 | mutex_lock(&wl->mutex); | 521 | mutex_lock(&wl->mutex); |
522 | if (wl->vif) { | ||
523 | ret = -EBUSY; | ||
524 | goto out; | ||
525 | } | ||
526 | |||
527 | wl->vif = conf->vif; | ||
512 | 528 | ||
513 | switch (conf->type) { | 529 | switch (conf->type) { |
514 | case NL80211_IFTYPE_STATION: | 530 | case NL80211_IFTYPE_STATION: |
@@ -538,7 +554,12 @@ out: | |||
538 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, | 554 | static void wl1251_op_remove_interface(struct ieee80211_hw *hw, |
539 | struct ieee80211_if_init_conf *conf) | 555 | struct ieee80211_if_init_conf *conf) |
540 | { | 556 | { |
557 | struct wl1251 *wl = hw->priv; | ||
558 | |||
559 | mutex_lock(&wl->mutex); | ||
541 | wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); | 560 | wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); |
561 | wl->vif = NULL; | ||
562 | mutex_unlock(&wl->mutex); | ||
542 | } | 563 | } |
543 | 564 | ||
544 | static int wl1251_build_null_data(struct wl1251 *wl) | 565 | static int wl1251_build_null_data(struct wl1251 *wl) |
@@ -555,7 +576,8 @@ static int wl1251_build_null_data(struct wl1251 *wl) | |||
555 | 576 | ||
556 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); | 577 | memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); |
557 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | | 578 | template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | |
558 | IEEE80211_STYPE_NULLFUNC); | 579 | IEEE80211_STYPE_NULLFUNC | |
580 | IEEE80211_FCTL_TODS); | ||
559 | 581 | ||
560 | return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, | 582 | return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, |
561 | sizeof(template)); | 583 | sizeof(template)); |
@@ -568,7 +590,10 @@ static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid) | |||
568 | 590 | ||
569 | memcpy(template.bssid, wl->bssid, ETH_ALEN); | 591 | memcpy(template.bssid, wl->bssid, ETH_ALEN); |
570 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); | 592 | memcpy(template.ta, wl->mac_addr, ETH_ALEN); |
571 | template.aid = aid; | 593 | |
594 | /* aid in PS-Poll has its two MSBs each set to 1 */ | ||
595 | template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid); | ||
596 | |||
572 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); | 597 | template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); |
573 | 598 | ||
574 | return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, | 599 | return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, |
@@ -1090,8 +1115,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, | |||
1090 | wl->beacon_int = bss_conf->beacon_int; | 1115 | wl->beacon_int = bss_conf->beacon_int; |
1091 | wl->dtim_period = bss_conf->dtim_period; | 1116 | wl->dtim_period = bss_conf->dtim_period; |
1092 | 1117 | ||
1093 | /* FIXME: call join */ | 1118 | ret = wl1251_acx_wr_tbtt_and_dtim(wl, wl->beacon_int, |
1094 | 1119 | wl->dtim_period); | |
1095 | wl->aid = bss_conf->aid; | 1120 | wl->aid = bss_conf->aid; |
1096 | 1121 | ||
1097 | ret = wl1251_build_ps_poll(wl, wl->aid); | 1122 | ret = wl1251_build_ps_poll(wl, wl->aid); |
@@ -1312,7 +1337,8 @@ int wl1251_init_ieee80211(struct wl1251 *wl) | |||
1312 | 1337 | ||
1313 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | | 1338 | wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | |
1314 | IEEE80211_HW_NOISE_DBM | | 1339 | IEEE80211_HW_NOISE_DBM | |
1315 | IEEE80211_HW_SUPPORTS_PS; | 1340 | IEEE80211_HW_SUPPORTS_PS | |
1341 | IEEE80211_HW_BEACON_FILTER; | ||
1316 | 1342 | ||
1317 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | 1343 | wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); |
1318 | wl->hw->wiphy->max_scan_ssids = 1; | 1344 | wl->hw->wiphy->max_scan_ssids = 1; |
@@ -1355,6 +1381,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1355 | skb_queue_head_init(&wl->tx_queue); | 1381 | skb_queue_head_init(&wl->tx_queue); |
1356 | 1382 | ||
1357 | INIT_WORK(&wl->filter_work, wl1251_filter_work); | 1383 | INIT_WORK(&wl->filter_work, wl1251_filter_work); |
1384 | INIT_DELAYED_WORK(&wl->elp_work, wl1251_elp_work); | ||
1358 | wl->channel = WL1251_DEFAULT_CHANNEL; | 1385 | wl->channel = WL1251_DEFAULT_CHANNEL; |
1359 | wl->scanning = false; | 1386 | wl->scanning = false; |
1360 | wl->default_key = 0; | 1387 | wl->default_key = 0; |
@@ -1372,6 +1399,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void) | |||
1372 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; | 1399 | wl->power_level = WL1251_DEFAULT_POWER_LEVEL; |
1373 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; | 1400 | wl->beacon_int = WL1251_DEFAULT_BEACON_INT; |
1374 | wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; | 1401 | wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; |
1402 | wl->vif = NULL; | ||
1375 | 1403 | ||
1376 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) | 1404 | for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) |
1377 | wl->tx_frames[i] = NULL; | 1405 | wl->tx_frames[i] = NULL; |
@@ -1413,7 +1441,7 @@ int wl1251_free_hw(struct wl1251 *wl) | |||
1413 | 1441 | ||
1414 | kfree(wl->target_mem_map); | 1442 | kfree(wl->target_mem_map); |
1415 | kfree(wl->data_path); | 1443 | kfree(wl->data_path); |
1416 | kfree(wl->fw); | 1444 | vfree(wl->fw); |
1417 | wl->fw = NULL; | 1445 | wl->fw = NULL; |
1418 | kfree(wl->nvs); | 1446 | kfree(wl->nvs); |
1419 | wl->nvs = NULL; | 1447 | wl->nvs = NULL; |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c index c53e28727ed4..9931b197ff77 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ b/drivers/net/wireless/wl12xx/wl1251_ps.c | |||
@@ -28,17 +28,41 @@ | |||
28 | 28 | ||
29 | #define WL1251_WAKEUP_TIMEOUT 2000 | 29 | #define WL1251_WAKEUP_TIMEOUT 2000 |
30 | 30 | ||
31 | /* Routines to toggle sleep mode while in ELP */ | 31 | void wl1251_elp_work(struct work_struct *work) |
32 | void wl1251_ps_elp_sleep(struct wl1251 *wl) | ||
33 | { | 32 | { |
33 | struct delayed_work *dwork; | ||
34 | struct wl1251 *wl; | ||
35 | |||
36 | dwork = container_of(work, struct delayed_work, work); | ||
37 | wl = container_of(dwork, struct wl1251, elp_work); | ||
38 | |||
39 | wl1251_debug(DEBUG_PSM, "elp work"); | ||
40 | |||
41 | mutex_lock(&wl->mutex); | ||
42 | |||
34 | if (wl->elp || !wl->psm) | 43 | if (wl->elp || !wl->psm) |
35 | return; | 44 | goto out; |
36 | 45 | ||
37 | wl1251_debug(DEBUG_PSM, "chip to elp"); | 46 | wl1251_debug(DEBUG_PSM, "chip to elp"); |
38 | |||
39 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); | 47 | wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); |
40 | |||
41 | wl->elp = true; | 48 | wl->elp = true; |
49 | |||
50 | out: | ||
51 | mutex_unlock(&wl->mutex); | ||
52 | } | ||
53 | |||
54 | #define ELP_ENTRY_DELAY 5 | ||
55 | |||
56 | /* Routines to toggle sleep mode while in ELP */ | ||
57 | void wl1251_ps_elp_sleep(struct wl1251 *wl) | ||
58 | { | ||
59 | unsigned long delay; | ||
60 | |||
61 | if (wl->psm) { | ||
62 | cancel_delayed_work(&wl->elp_work); | ||
63 | delay = msecs_to_jiffies(ELP_ENTRY_DELAY); | ||
64 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); | ||
65 | } | ||
42 | } | 66 | } |
43 | 67 | ||
44 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) | 68 | int wl1251_ps_elp_wakeup(struct wl1251 *wl) |
@@ -119,6 +143,11 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) | |||
119 | case STATION_POWER_SAVE_MODE: | 143 | case STATION_POWER_SAVE_MODE: |
120 | wl1251_debug(DEBUG_PSM, "entering psm"); | 144 | wl1251_debug(DEBUG_PSM, "entering psm"); |
121 | 145 | ||
146 | /* enable beacon filtering */ | ||
147 | ret = wl1251_acx_beacon_filter_opt(wl, true); | ||
148 | if (ret < 0) | ||
149 | return ret; | ||
150 | |||
122 | ret = wl1251_acx_wake_up_conditions(wl, | 151 | ret = wl1251_acx_wake_up_conditions(wl, |
123 | WAKE_UP_EVENT_DTIM_BITMAP, | 152 | WAKE_UP_EVENT_DTIM_BITMAP, |
124 | wl->listen_int); | 153 | wl->listen_int); |
@@ -142,6 +171,11 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) | |||
142 | if (ret < 0) | 171 | if (ret < 0) |
143 | return ret; | 172 | return ret; |
144 | 173 | ||
174 | /* disable beacon filtering */ | ||
175 | ret = wl1251_acx_beacon_filter_opt(wl, false); | ||
176 | if (ret < 0) | ||
177 | return ret; | ||
178 | |||
145 | ret = wl1251_acx_wake_up_conditions(wl, | 179 | ret = wl1251_acx_wake_up_conditions(wl, |
146 | WAKE_UP_EVENT_DTIM_BITMAP, | 180 | WAKE_UP_EVENT_DTIM_BITMAP, |
147 | wl->listen_int); | 181 | wl->listen_int); |
diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h index db036fe12f25..c688ac57aee4 100644 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ b/drivers/net/wireless/wl12xx/wl1251_ps.h | |||
@@ -31,6 +31,7 @@ | |||
31 | int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); | 31 | int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); |
32 | void wl1251_ps_elp_sleep(struct wl1251 *wl); | 32 | void wl1251_ps_elp_sleep(struct wl1251 *wl); |
33 | int wl1251_ps_elp_wakeup(struct wl1251 *wl); | 33 | int wl1251_ps_elp_wakeup(struct wl1251 *wl); |
34 | void wl1251_elp_work(struct work_struct *work); | ||
34 | 35 | ||
35 | 36 | ||
36 | #endif /* __WL1251_PS_H__ */ | 37 | #endif /* __WL1251_PS_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h index 06e1bd94a739..0ca3b4326056 100644 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ b/drivers/net/wireless/wl12xx/wl1251_reg.h | |||
@@ -370,6 +370,7 @@ enum wl12xx_acx_int_reg { | |||
370 | EEPROM location specified in the EE_ADDR register. | 370 | EEPROM location specified in the EE_ADDR register. |
371 | The Wlan hardware hardware clears this bit automatically. | 371 | The Wlan hardware hardware clears this bit automatically. |
372 | *===============================================*/ | 372 | *===============================================*/ |
373 | #define EE_CTL (REGISTERS_BASE + 0x2000) | ||
373 | #define ACX_EE_CTL_REG EE_CTL | 374 | #define ACX_EE_CTL_REG EE_CTL |
374 | #define EE_WRITE 0x00000001ul | 375 | #define EE_WRITE 0x00000001ul |
375 | #define EE_READ 0x00000002ul | 376 | #define EE_READ 0x00000002ul |
@@ -380,6 +381,7 @@ enum wl12xx_acx_int_reg { | |||
380 | This register specifies the address | 381 | This register specifies the address |
381 | within the EEPROM from/to which to read/write data. | 382 | within the EEPROM from/to which to read/write data. |
382 | ===============================================*/ | 383 | ===============================================*/ |
384 | #define EE_ADDR (REGISTERS_BASE + 0x2008) | ||
383 | #define ACX_EE_ADDR_REG EE_ADDR | 385 | #define ACX_EE_ADDR_REG EE_ADDR |
384 | 386 | ||
385 | /*=============================================== | 387 | /*=============================================== |
@@ -389,8 +391,12 @@ enum wl12xx_acx_int_reg { | |||
389 | data from the EEPROM or the write data | 391 | data from the EEPROM or the write data |
390 | to be written to the EEPROM. | 392 | to be written to the EEPROM. |
391 | ===============================================*/ | 393 | ===============================================*/ |
394 | #define EE_DATA (REGISTERS_BASE + 0x2004) | ||
392 | #define ACX_EE_DATA_REG EE_DATA | 395 | #define ACX_EE_DATA_REG EE_DATA |
393 | 396 | ||
397 | #define EEPROM_ACCESS_TO 10000 /* timeout counter */ | ||
398 | #define START_EEPROM_MGR 0x00000001 | ||
399 | |||
394 | /*=============================================== | 400 | /*=============================================== |
395 | EEPROM Base Address - 32bit RW | 401 | EEPROM Base Address - 32bit RW |
396 | ------------------------------------------ | 402 | ------------------------------------------ |
diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c index 601fe0d67827..f84cc89cbffc 100644 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ b/drivers/net/wireless/wl12xx/wl1251_rx.c | |||
@@ -72,10 +72,6 @@ static void wl1251_rx_status(struct wl1251 *wl, | |||
72 | } | 72 | } |
73 | 73 | ||
74 | status->signal = desc->rssi; | 74 | status->signal = desc->rssi; |
75 | status->qual = (desc->rssi - WL1251_RX_MIN_RSSI) * 100 / | ||
76 | (WL1251_RX_MAX_RSSI - WL1251_RX_MIN_RSSI); | ||
77 | status->qual = min(status->qual, 100); | ||
78 | status->qual = max(status->qual, 0); | ||
79 | 75 | ||
80 | /* | 76 | /* |
81 | * FIXME: guessing that snr needs to be divided by two, otherwise | 77 | * FIXME: guessing that snr needs to be divided by two, otherwise |
diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c index 2cf8a2169d43..9cc8c323830f 100644 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ b/drivers/net/wireless/wl12xx/wl1251_spi.c | |||
@@ -270,6 +270,8 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) | |||
270 | return -ENODEV; | 270 | return -ENODEV; |
271 | } | 271 | } |
272 | 272 | ||
273 | wl->use_eeprom = pdata->use_eeprom; | ||
274 | |||
273 | ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); | 275 | ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); |
274 | if (ret < 0) { | 276 | if (ret < 0) { |
275 | wl1251_error("request_irq() failed: %d", ret); | 277 | wl1251_error("request_irq() failed: %d", ret); |
diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c index 4f1e0cfe609b..891bdab49887 100644 --- a/drivers/net/wireless/wl3501_cs.c +++ b/drivers/net/wireless/wl3501_cs.c | |||
@@ -381,7 +381,7 @@ static void wl3501_free_tx_buffer(struct wl3501_card *this, u16 ptr) | |||
381 | 381 | ||
382 | static int wl3501_esbq_req_test(struct wl3501_card *this) | 382 | static int wl3501_esbq_req_test(struct wl3501_card *this) |
383 | { | 383 | { |
384 | u8 tmp; | 384 | u8 tmp = 0; |
385 | 385 | ||
386 | wl3501_get_from_wla(this, this->esbq_req_head + 3, &tmp, sizeof(tmp)); | 386 | wl3501_get_from_wla(this, this->esbq_req_head + 3, &tmp, sizeof(tmp)); |
387 | return tmp & 0x80; | 387 | return tmp & 0x80; |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 579b114be412..5681ebed9c65 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -140,6 +140,19 @@ static void ssb_device_put(struct ssb_device *dev) | |||
140 | put_device(dev->dev); | 140 | put_device(dev->dev); |
141 | } | 141 | } |
142 | 142 | ||
143 | static inline struct ssb_driver *ssb_driver_get(struct ssb_driver *drv) | ||
144 | { | ||
145 | if (drv) | ||
146 | get_driver(&drv->drv); | ||
147 | return drv; | ||
148 | } | ||
149 | |||
150 | static inline void ssb_driver_put(struct ssb_driver *drv) | ||
151 | { | ||
152 | if (drv) | ||
153 | put_driver(&drv->drv); | ||
154 | } | ||
155 | |||
143 | static int ssb_device_resume(struct device *dev) | 156 | static int ssb_device_resume(struct device *dev) |
144 | { | 157 | { |
145 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); | 158 | struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); |
@@ -210,90 +223,81 @@ int ssb_bus_suspend(struct ssb_bus *bus) | |||
210 | EXPORT_SYMBOL(ssb_bus_suspend); | 223 | EXPORT_SYMBOL(ssb_bus_suspend); |
211 | 224 | ||
212 | #ifdef CONFIG_SSB_SPROM | 225 | #ifdef CONFIG_SSB_SPROM |
213 | int ssb_devices_freeze(struct ssb_bus *bus) | 226 | /** ssb_devices_freeze - Freeze all devices on the bus. |
227 | * | ||
228 | * After freezing no device driver will be handling a device | ||
229 | * on this bus anymore. ssb_devices_thaw() must be called after | ||
230 | * a successful freeze to reactivate the devices. | ||
231 | * | ||
232 | * @bus: The bus. | ||
233 | * @ctx: Context structure. Pass this to ssb_devices_thaw(). | ||
234 | */ | ||
235 | int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx) | ||
214 | { | 236 | { |
215 | struct ssb_device *dev; | 237 | struct ssb_device *sdev; |
216 | struct ssb_driver *drv; | 238 | struct ssb_driver *sdrv; |
217 | int err = 0; | 239 | unsigned int i; |
218 | int i; | 240 | |
219 | pm_message_t state = PMSG_FREEZE; | 241 | memset(ctx, 0, sizeof(*ctx)); |
242 | ctx->bus = bus; | ||
243 | SSB_WARN_ON(bus->nr_devices > ARRAY_SIZE(ctx->device_frozen)); | ||
220 | 244 | ||
221 | /* First check that we are capable to freeze all devices. */ | ||
222 | for (i = 0; i < bus->nr_devices; i++) { | 245 | for (i = 0; i < bus->nr_devices; i++) { |
223 | dev = &(bus->devices[i]); | 246 | sdev = ssb_device_get(&bus->devices[i]); |
224 | if (!dev->dev || | 247 | |
225 | !dev->dev->driver || | 248 | if (!sdev->dev || !sdev->dev->driver || |
226 | !device_is_registered(dev->dev)) | 249 | !device_is_registered(sdev->dev)) { |
227 | continue; | 250 | ssb_device_put(sdev); |
228 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
229 | if (!drv) | ||
230 | continue; | 251 | continue; |
231 | if (!drv->suspend) { | ||
232 | /* Nope, can't suspend this one. */ | ||
233 | return -EOPNOTSUPP; | ||
234 | } | 252 | } |
235 | } | 253 | sdrv = ssb_driver_get(drv_to_ssb_drv(sdev->dev->driver)); |
236 | /* Now suspend all devices */ | 254 | if (!sdrv || SSB_WARN_ON(!sdrv->remove)) { |
237 | for (i = 0; i < bus->nr_devices; i++) { | 255 | ssb_device_put(sdev); |
238 | dev = &(bus->devices[i]); | ||
239 | if (!dev->dev || | ||
240 | !dev->dev->driver || | ||
241 | !device_is_registered(dev->dev)) | ||
242 | continue; | ||
243 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
244 | if (!drv) | ||
245 | continue; | 256 | continue; |
246 | err = drv->suspend(dev, state); | ||
247 | if (err) { | ||
248 | ssb_printk(KERN_ERR PFX "Failed to freeze device %s\n", | ||
249 | dev_name(dev->dev)); | ||
250 | goto err_unwind; | ||
251 | } | 257 | } |
258 | sdrv->remove(sdev); | ||
259 | ctx->device_frozen[i] = 1; | ||
252 | } | 260 | } |
253 | 261 | ||
254 | return 0; | 262 | return 0; |
255 | err_unwind: | ||
256 | for (i--; i >= 0; i--) { | ||
257 | dev = &(bus->devices[i]); | ||
258 | if (!dev->dev || | ||
259 | !dev->dev->driver || | ||
260 | !device_is_registered(dev->dev)) | ||
261 | continue; | ||
262 | drv = drv_to_ssb_drv(dev->dev->driver); | ||
263 | if (!drv) | ||
264 | continue; | ||
265 | if (drv->resume) | ||
266 | drv->resume(dev); | ||
267 | } | ||
268 | return err; | ||
269 | } | 263 | } |
270 | 264 | ||
271 | int ssb_devices_thaw(struct ssb_bus *bus) | 265 | /** ssb_devices_thaw - Unfreeze all devices on the bus. |
266 | * | ||
267 | * This will re-attach the device drivers and re-init the devices. | ||
268 | * | ||
269 | * @ctx: The context structure from ssb_devices_freeze() | ||
270 | */ | ||
271 | int ssb_devices_thaw(struct ssb_freeze_context *ctx) | ||
272 | { | 272 | { |
273 | struct ssb_device *dev; | 273 | struct ssb_bus *bus = ctx->bus; |
274 | struct ssb_driver *drv; | 274 | struct ssb_device *sdev; |
275 | int err; | 275 | struct ssb_driver *sdrv; |
276 | int i; | 276 | unsigned int i; |
277 | int err, result = 0; | ||
277 | 278 | ||
278 | for (i = 0; i < bus->nr_devices; i++) { | 279 | for (i = 0; i < bus->nr_devices; i++) { |
279 | dev = &(bus->devices[i]); | 280 | if (!ctx->device_frozen[i]) |
280 | if (!dev->dev || | ||
281 | !dev->dev->driver || | ||
282 | !device_is_registered(dev->dev)) | ||
283 | continue; | 281 | continue; |
284 | drv = drv_to_ssb_drv(dev->dev->driver); | 282 | sdev = &bus->devices[i]; |
285 | if (!drv) | 283 | |
284 | if (SSB_WARN_ON(!sdev->dev || !sdev->dev->driver)) | ||
286 | continue; | 285 | continue; |
287 | if (SSB_WARN_ON(!drv->resume)) | 286 | sdrv = drv_to_ssb_drv(sdev->dev->driver); |
287 | if (SSB_WARN_ON(!sdrv || !sdrv->probe)) | ||
288 | continue; | 288 | continue; |
289 | err = drv->resume(dev); | 289 | |
290 | err = sdrv->probe(sdev, &sdev->id); | ||
290 | if (err) { | 291 | if (err) { |
291 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", | 292 | ssb_printk(KERN_ERR PFX "Failed to thaw device %s\n", |
292 | dev_name(dev->dev)); | 293 | dev_name(sdev->dev)); |
294 | result = err; | ||
293 | } | 295 | } |
296 | ssb_driver_put(sdrv); | ||
297 | ssb_device_put(sdev); | ||
294 | } | 298 | } |
295 | 299 | ||
296 | return 0; | 300 | return result; |
297 | } | 301 | } |
298 | #endif /* CONFIG_SSB_SPROM */ | 302 | #endif /* CONFIG_SSB_SPROM */ |
299 | 303 | ||
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index e8b89e8ac9bd..0d6c0280eb34 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -354,7 +354,7 @@ int ssb_bus_scan(struct ssb_bus *bus, | |||
354 | dev->bus = bus; | 354 | dev->bus = bus; |
355 | dev->ops = bus->ops; | 355 | dev->ops = bus->ops; |
356 | 356 | ||
357 | ssb_dprintk(KERN_INFO PFX | 357 | printk(KERN_DEBUG PFX |
358 | "Core %d found: %s " | 358 | "Core %d found: %s " |
359 | "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", | 359 | "(cc 0x%03X, rev 0x%02X, vendor 0x%04X)\n", |
360 | i, ssb_core_name(dev->id.coreid), | 360 | i, ssb_core_name(dev->id.coreid), |
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c index 8943015a3eef..d0e6762fec50 100644 --- a/drivers/ssb/sprom.c +++ b/drivers/ssb/sprom.c | |||
@@ -13,6 +13,8 @@ | |||
13 | 13 | ||
14 | #include "ssb_private.h" | 14 | #include "ssb_private.h" |
15 | 15 | ||
16 | #include <linux/ctype.h> | ||
17 | |||
16 | 18 | ||
17 | static const struct ssb_sprom *fallback_sprom; | 19 | static const struct ssb_sprom *fallback_sprom; |
18 | 20 | ||
@@ -33,17 +35,27 @@ static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len, | |||
33 | static int hex2sprom(u16 *sprom, const char *dump, size_t len, | 35 | static int hex2sprom(u16 *sprom, const char *dump, size_t len, |
34 | size_t sprom_size_words) | 36 | size_t sprom_size_words) |
35 | { | 37 | { |
36 | char tmp[5] = { 0 }; | 38 | char c, tmp[5] = { 0 }; |
37 | int cnt = 0; | 39 | int err, cnt = 0; |
38 | unsigned long parsed; | 40 | unsigned long parsed; |
39 | 41 | ||
40 | if (len < sprom_size_words * 2) | 42 | /* Strip whitespace at the end. */ |
43 | while (len) { | ||
44 | c = dump[len - 1]; | ||
45 | if (!isspace(c) && c != '\0') | ||
46 | break; | ||
47 | len--; | ||
48 | } | ||
49 | /* Length must match exactly. */ | ||
50 | if (len != sprom_size_words * 4) | ||
41 | return -EINVAL; | 51 | return -EINVAL; |
42 | 52 | ||
43 | while (cnt < sprom_size_words) { | 53 | while (cnt < sprom_size_words) { |
44 | memcpy(tmp, dump, 4); | 54 | memcpy(tmp, dump, 4); |
45 | dump += 4; | 55 | dump += 4; |
46 | parsed = simple_strtoul(tmp, NULL, 16); | 56 | err = strict_strtoul(tmp, 16, &parsed); |
57 | if (err) | ||
58 | return err; | ||
47 | sprom[cnt++] = swab16((u16)parsed); | 59 | sprom[cnt++] = swab16((u16)parsed); |
48 | } | 60 | } |
49 | 61 | ||
@@ -90,6 +102,7 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
90 | u16 *sprom; | 102 | u16 *sprom; |
91 | int res = 0, err = -ENOMEM; | 103 | int res = 0, err = -ENOMEM; |
92 | size_t sprom_size_words = bus->sprom_size; | 104 | size_t sprom_size_words = bus->sprom_size; |
105 | struct ssb_freeze_context freeze; | ||
93 | 106 | ||
94 | sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); | 107 | sprom = kcalloc(bus->sprom_size, sizeof(u16), GFP_KERNEL); |
95 | if (!sprom) | 108 | if (!sprom) |
@@ -111,18 +124,13 @@ ssize_t ssb_attr_sprom_store(struct ssb_bus *bus, | |||
111 | err = -ERESTARTSYS; | 124 | err = -ERESTARTSYS; |
112 | if (mutex_lock_interruptible(&bus->sprom_mutex)) | 125 | if (mutex_lock_interruptible(&bus->sprom_mutex)) |
113 | goto out_kfree; | 126 | goto out_kfree; |
114 | err = ssb_devices_freeze(bus); | 127 | err = ssb_devices_freeze(bus, &freeze); |
115 | if (err == -EOPNOTSUPP) { | ||
116 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze devices. " | ||
117 | "No suspend support. Is CONFIG_PM enabled?\n"); | ||
118 | goto out_unlock; | ||
119 | } | ||
120 | if (err) { | 128 | if (err) { |
121 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); | 129 | ssb_printk(KERN_ERR PFX "SPROM write: Could not freeze all devices\n"); |
122 | goto out_unlock; | 130 | goto out_unlock; |
123 | } | 131 | } |
124 | res = sprom_write(bus, sprom); | 132 | res = sprom_write(bus, sprom); |
125 | err = ssb_devices_thaw(bus); | 133 | err = ssb_devices_thaw(&freeze); |
126 | if (err) | 134 | if (err) |
127 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); | 135 | ssb_printk(KERN_ERR PFX "SPROM write: Could not thaw all devices\n"); |
128 | out_unlock: | 136 | out_unlock: |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 25433565dfda..56054be4d113 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -176,13 +176,21 @@ extern const struct ssb_sprom *ssb_get_fallback_sprom(void); | |||
176 | 176 | ||
177 | /* core.c */ | 177 | /* core.c */ |
178 | extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); | 178 | extern u32 ssb_calc_clock_rate(u32 plltype, u32 n, u32 m); |
179 | extern int ssb_devices_freeze(struct ssb_bus *bus); | ||
180 | extern int ssb_devices_thaw(struct ssb_bus *bus); | ||
181 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); | 179 | extern struct ssb_bus *ssb_pci_dev_to_bus(struct pci_dev *pdev); |
182 | int ssb_for_each_bus_call(unsigned long data, | 180 | int ssb_for_each_bus_call(unsigned long data, |
183 | int (*func)(struct ssb_bus *bus, unsigned long data)); | 181 | int (*func)(struct ssb_bus *bus, unsigned long data)); |
184 | extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev); | 182 | extern struct ssb_bus *ssb_pcmcia_dev_to_bus(struct pcmcia_device *pdev); |
185 | 183 | ||
184 | struct ssb_freeze_context { | ||
185 | /* Pointer to the bus */ | ||
186 | struct ssb_bus *bus; | ||
187 | /* Boolean list to indicate whether a device is frozen on this bus. */ | ||
188 | bool device_frozen[SSB_MAX_NR_CORES]; | ||
189 | }; | ||
190 | extern int ssb_devices_freeze(struct ssb_bus *bus, struct ssb_freeze_context *ctx); | ||
191 | extern int ssb_devices_thaw(struct ssb_freeze_context *ctx); | ||
192 | |||
193 | |||
186 | 194 | ||
187 | /* b43_pci_bridge.c */ | 195 | /* b43_pci_bridge.c */ |
188 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE | 196 | #ifdef CONFIG_SSB_B43_PCI_BRIDGE |
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 49b1abd2fe97..afa8e0ac27a7 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -115,7 +115,6 @@ | |||
115 | #define IEEE80211_MAX_SSID_LEN 32 | 115 | #define IEEE80211_MAX_SSID_LEN 32 |
116 | 116 | ||
117 | #define IEEE80211_MAX_MESH_ID_LEN 32 | 117 | #define IEEE80211_MAX_MESH_ID_LEN 32 |
118 | #define IEEE80211_MESH_CONFIG_LEN 7 | ||
119 | 118 | ||
120 | #define IEEE80211_QOS_CTL_LEN 2 | 119 | #define IEEE80211_QOS_CTL_LEN 2 |
121 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F | 120 | #define IEEE80211_QOS_CTL_TID_MASK 0x000F |
@@ -555,6 +554,21 @@ struct ieee80211_tim_ie { | |||
555 | } __attribute__ ((packed)); | 554 | } __attribute__ ((packed)); |
556 | 555 | ||
557 | /** | 556 | /** |
557 | * struct ieee80211_meshconf_ie | ||
558 | * | ||
559 | * This structure refers to "Mesh Configuration information element" | ||
560 | */ | ||
561 | struct ieee80211_meshconf_ie { | ||
562 | u8 meshconf_psel; | ||
563 | u8 meshconf_pmetric; | ||
564 | u8 meshconf_congest; | ||
565 | u8 meshconf_synch; | ||
566 | u8 meshconf_auth; | ||
567 | u8 meshconf_form; | ||
568 | u8 meshconf_cap; | ||
569 | } __attribute__ ((packed)); | ||
570 | |||
571 | /** | ||
558 | * struct ieee80211_rann_ie | 572 | * struct ieee80211_rann_ie |
559 | * | 573 | * |
560 | * This structure refers to "Root Announcement information element" | 574 | * This structure refers to "Root Announcement information element" |
diff --git a/include/linux/if.h b/include/linux/if.h index 3b2a46bf8f8d..3a9f410a296b 100644 --- a/include/linux/if.h +++ b/include/linux/if.h | |||
@@ -70,6 +70,7 @@ | |||
70 | #define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to | 70 | #define IFF_XMIT_DST_RELEASE 0x400 /* dev_hard_start_xmit() is allowed to |
71 | * release skb->dst | 71 | * release skb->dst |
72 | */ | 72 | */ |
73 | #define IFF_DONT_BRIDGE 0x800 /* disallow bridging this ether dev */ | ||
73 | 74 | ||
74 | #define IF_GET_IFACE 0x0001 /* for querying only */ | 75 | #define IF_GET_IFACE 0x0001 /* for querying only */ |
75 | #define IF_GET_PROTO 0x0002 | 76 | #define IF_GET_PROTO 0x0002 |
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h index 3392c59d2706..97059d08a626 100644 --- a/include/linux/rfkill.h +++ b/include/linux/rfkill.h | |||
@@ -35,6 +35,8 @@ | |||
35 | * @RFKILL_TYPE_UWB: switch is on a ultra wideband device. | 35 | * @RFKILL_TYPE_UWB: switch is on a ultra wideband device. |
36 | * @RFKILL_TYPE_WIMAX: switch is on a WiMAX device. | 36 | * @RFKILL_TYPE_WIMAX: switch is on a WiMAX device. |
37 | * @RFKILL_TYPE_WWAN: switch is on a wireless WAN device. | 37 | * @RFKILL_TYPE_WWAN: switch is on a wireless WAN device. |
38 | * @RFKILL_TYPE_GPS: switch is on a GPS device. | ||
39 | * @RFKILL_TYPE_FM: switch is on a FM radio device. | ||
38 | * @NUM_RFKILL_TYPES: number of defined rfkill types | 40 | * @NUM_RFKILL_TYPES: number of defined rfkill types |
39 | */ | 41 | */ |
40 | enum rfkill_type { | 42 | enum rfkill_type { |
@@ -45,6 +47,7 @@ enum rfkill_type { | |||
45 | RFKILL_TYPE_WIMAX, | 47 | RFKILL_TYPE_WIMAX, |
46 | RFKILL_TYPE_WWAN, | 48 | RFKILL_TYPE_WWAN, |
47 | RFKILL_TYPE_GPS, | 49 | RFKILL_TYPE_GPS, |
50 | RFKILL_TYPE_FM, | ||
48 | NUM_RFKILL_TYPES, | 51 | NUM_RFKILL_TYPES, |
49 | }; | 52 | }; |
50 | 53 | ||
diff --git a/include/linux/spi/wl12xx.h b/include/linux/spi/wl12xx.h index 11430cab2aad..aed64ed3dc8a 100644 --- a/include/linux/spi/wl12xx.h +++ b/include/linux/spi/wl12xx.h | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | struct wl12xx_platform_data { | 27 | struct wl12xx_platform_data { |
28 | void (*set_power)(bool enable); | 28 | void (*set_power)(bool enable); |
29 | bool use_eeprom; | ||
29 | }; | 30 | }; |
30 | 31 | ||
31 | #endif | 32 | #endif |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 21710fc17eaf..a6492e9bca97 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1108,27 +1108,50 @@ struct cfg80211_ops { | |||
1108 | */ | 1108 | */ |
1109 | 1109 | ||
1110 | /** | 1110 | /** |
1111 | * struct wiphy - wireless hardware description | 1111 | * enum wiphy_flags - wiphy capability flags |
1112 | * @idx: the wiphy index assigned to this item | 1112 | * |
1113 | * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name> | 1113 | * @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device |
1114 | * @custom_regulatory: tells us the driver for this device | ||
1115 | * has its own custom regulatory domain and cannot identify the | 1114 | * has its own custom regulatory domain and cannot identify the |
1116 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled | 1115 | * ISO / IEC 3166 alpha2 it belongs to. When this is enabled |
1117 | * we will disregard the first regulatory hint (when the | 1116 | * we will disregard the first regulatory hint (when the |
1118 | * initiator is %REGDOM_SET_BY_CORE). | 1117 | * initiator is %REGDOM_SET_BY_CORE). |
1119 | * @strict_regulatory: tells us the driver for this device will ignore | 1118 | * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will |
1120 | * regulatory domain settings until it gets its own regulatory domain | 1119 | * ignore regulatory domain settings until it gets its own regulatory |
1121 | * via its regulatory_hint(). After its gets its own regulatory domain | 1120 | * domain via its regulatory_hint(). After its gets its own regulatory |
1122 | * it will only allow further regulatory domain settings to further | 1121 | * domain it will only allow further regulatory domain settings to |
1123 | * enhance compliance. For example if channel 13 and 14 are disabled | 1122 | * further enhance compliance. For example if channel 13 and 14 are |
1124 | * by this regulatory domain no user regulatory domain can enable these | 1123 | * disabled by this regulatory domain no user regulatory domain can |
1125 | * channels at a later time. This can be used for devices which do not | 1124 | * enable these channels at a later time. This can be used for devices |
1126 | * have calibration information gauranteed for frequencies or settings | 1125 | * which do not have calibration information gauranteed for frequencies |
1127 | * outside of its regulatory domain. | 1126 | * or settings outside of its regulatory domain. |
1128 | * @disable_beacon_hints: enable this if your driver needs to ensure that | 1127 | * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure |
1129 | * passive scan flags and beaconing flags may not be lifted by cfg80211 | 1128 | * that passive scan flags and beaconing flags may not be lifted by |
1130 | * due to regulatory beacon hints. For more information on beacon | 1129 | * cfg80211 due to regulatory beacon hints. For more information on beacon |
1131 | * hints read the documenation for regulatory_hint_found_beacon() | 1130 | * hints read the documenation for regulatory_hint_found_beacon() |
1131 | * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this | ||
1132 | * wiphy at all | ||
1133 | * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled | ||
1134 | * by default -- this flag will be set depending on the kernel's default | ||
1135 | * on wiphy_new(), but can be changed by the driver if it has a good | ||
1136 | * reason to override the default | ||
1137 | * @WIPHY_FLAG_4ADDR_AP: supports 4addr mode even on AP (with a single station | ||
1138 | * on a VLAN interface) | ||
1139 | * @WIPHY_FLAG_4ADDR_STATION: supports 4addr mode even as a station | ||
1140 | */ | ||
1141 | enum wiphy_flags { | ||
1142 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), | ||
1143 | WIPHY_FLAG_STRICT_REGULATORY = BIT(1), | ||
1144 | WIPHY_FLAG_DISABLE_BEACON_HINTS = BIT(2), | ||
1145 | WIPHY_FLAG_NETNS_OK = BIT(3), | ||
1146 | WIPHY_FLAG_PS_ON_BY_DEFAULT = BIT(4), | ||
1147 | WIPHY_FLAG_4ADDR_AP = BIT(5), | ||
1148 | WIPHY_FLAG_4ADDR_STATION = BIT(6), | ||
1149 | }; | ||
1150 | |||
1151 | /** | ||
1152 | * struct wiphy - wireless hardware description | ||
1153 | * @idx: the wiphy index assigned to this item | ||
1154 | * @class_dev: the class device representing /sys/class/ieee80211/<wiphy-name> | ||
1132 | * @reg_notifier: the driver's regulatory notification callback | 1155 | * @reg_notifier: the driver's regulatory notification callback |
1133 | * @regd: the driver's regulatory domain, if one was requested via | 1156 | * @regd: the driver's regulatory domain, if one was requested via |
1134 | * the regulatory_hint() API. This can be used by the driver | 1157 | * the regulatory_hint() API. This can be used by the driver |
@@ -1143,11 +1166,6 @@ struct cfg80211_ops { | |||
1143 | * -1 = fragmentation disabled, only odd values >= 256 used | 1166 | * -1 = fragmentation disabled, only odd values >= 256 used |
1144 | * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled | 1167 | * @rts_threshold: RTS threshold (dot11RTSThreshold); -1 = RTS/CTS disabled |
1145 | * @net: the network namespace this wiphy currently lives in | 1168 | * @net: the network namespace this wiphy currently lives in |
1146 | * @netnsok: if set to false, do not allow changing the netns of this | ||
1147 | * wiphy at all | ||
1148 | * @ps_default: default for powersave, will be set depending on the | ||
1149 | * kernel's default on wiphy_new(), but can be changed by the | ||
1150 | * driver if it has a good reason to override the default | ||
1151 | */ | 1169 | */ |
1152 | struct wiphy { | 1170 | struct wiphy { |
1153 | /* assign these fields before you register the wiphy */ | 1171 | /* assign these fields before you register the wiphy */ |
@@ -1158,12 +1176,7 @@ struct wiphy { | |||
1158 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ | 1176 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ |
1159 | u16 interface_modes; | 1177 | u16 interface_modes; |
1160 | 1178 | ||
1161 | bool custom_regulatory; | 1179 | u32 flags; |
1162 | bool strict_regulatory; | ||
1163 | bool disable_beacon_hints; | ||
1164 | |||
1165 | bool netnsok; | ||
1166 | bool ps_default; | ||
1167 | 1180 | ||
1168 | enum cfg80211_signal_type signal_type; | 1181 | enum cfg80211_signal_type signal_type; |
1169 | 1182 | ||
@@ -1358,6 +1371,10 @@ struct cfg80211_cached_keys; | |||
1358 | * @ssid_len: (private) Used by the internal configuration code | 1371 | * @ssid_len: (private) Used by the internal configuration code |
1359 | * @wext: (private) Used by the internal wireless extensions compat code | 1372 | * @wext: (private) Used by the internal wireless extensions compat code |
1360 | * @wext_bssid: (private) Used by the internal wireless extensions compat code | 1373 | * @wext_bssid: (private) Used by the internal wireless extensions compat code |
1374 | * @use_4addr: indicates 4addr mode is used on this interface, must be | ||
1375 | * set by driver (if supported) on add_interface BEFORE registering the | ||
1376 | * netdev and may otherwise be used by driver read-only, will be update | ||
1377 | * by cfg80211 on change_interface | ||
1361 | */ | 1378 | */ |
1362 | struct wireless_dev { | 1379 | struct wireless_dev { |
1363 | struct wiphy *wiphy; | 1380 | struct wiphy *wiphy; |
@@ -1371,6 +1388,8 @@ struct wireless_dev { | |||
1371 | 1388 | ||
1372 | struct work_struct cleanup_work; | 1389 | struct work_struct cleanup_work; |
1373 | 1390 | ||
1391 | bool use_4addr; | ||
1392 | |||
1374 | /* currently used for IBSS and SME - might be rearranged later */ | 1393 | /* currently used for IBSS and SME - might be rearranged later */ |
1375 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | 1394 | u8 ssid[IEEE80211_MAX_SSID_LEN]; |
1376 | u8 ssid_len; | 1395 | u8 ssid_len; |
@@ -1820,6 +1839,18 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len); | |||
1820 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); | 1839 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr); |
1821 | 1840 | ||
1822 | /** | 1841 | /** |
1842 | * __cfg80211_auth_canceled - notify cfg80211 that authentication was canceled | ||
1843 | * @dev: network device | ||
1844 | * @addr: The MAC address of the device with which the authentication timed out | ||
1845 | * | ||
1846 | * When a pending authentication had no action yet, the driver may decide | ||
1847 | * to not send a deauth frame, but in that case must calls this function | ||
1848 | * to tell cfg80211 about this decision. It is only valid to call this | ||
1849 | * function within the deauth() callback. | ||
1850 | */ | ||
1851 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr); | ||
1852 | |||
1853 | /** | ||
1823 | * cfg80211_send_rx_assoc - notification of processed association | 1854 | * cfg80211_send_rx_assoc - notification of processed association |
1824 | * @dev: network device | 1855 | * @dev: network device |
1825 | * @buf: (re)association response frame (header + body) | 1856 | * @buf: (re)association response frame (header + body) |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 2c10eac637d8..3754ea405c88 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -219,7 +219,7 @@ struct ieee80211_bss_conf { | |||
219 | * | 219 | * |
220 | * These flags are used with the @flags member of &ieee80211_tx_info. | 220 | * These flags are used with the @flags member of &ieee80211_tx_info. |
221 | * | 221 | * |
222 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: request TX status callback for this frame. | 222 | * @IEEE80211_TX_CTL_REQ_TX_STATUS: require TX status callback for this frame. |
223 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence | 223 | * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence |
224 | * number to this frame, taking care of not overwriting the fragment | 224 | * number to this frame, taking care of not overwriting the fragment |
225 | * number and increasing the sequence number only when the | 225 | * number and increasing the sequence number only when the |
@@ -390,10 +390,12 @@ struct ieee80211_tx_rate { | |||
390 | * @control: union for control data | 390 | * @control: union for control data |
391 | * @status: union for status data | 391 | * @status: union for status data |
392 | * @driver_data: array of driver_data pointers | 392 | * @driver_data: array of driver_data pointers |
393 | * @ampdu_ack_len: number of aggregated frames. | 393 | * @ampdu_ack_len: number of acked aggregated frames. |
394 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | 394 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. |
395 | * @ampdu_ack_map: block ack bit map for the aggregation. | 395 | * @ampdu_ack_map: block ack bit map for the aggregation. |
396 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | 396 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. |
397 | * @ampdu_len: number of aggregated frames. | ||
398 | * relevant only if IEEE80211_TX_STATUS_AMPDU was set. | ||
397 | * @ack_signal: signal strength of the ACK frame | 399 | * @ack_signal: signal strength of the ACK frame |
398 | */ | 400 | */ |
399 | struct ieee80211_tx_info { | 401 | struct ieee80211_tx_info { |
@@ -428,7 +430,8 @@ struct ieee80211_tx_info { | |||
428 | u8 ampdu_ack_len; | 430 | u8 ampdu_ack_len; |
429 | u64 ampdu_ack_map; | 431 | u64 ampdu_ack_map; |
430 | int ack_signal; | 432 | int ack_signal; |
431 | /* 8 bytes free */ | 433 | u8 ampdu_len; |
434 | /* 7 bytes free */ | ||
432 | } status; | 435 | } status; |
433 | struct { | 436 | struct { |
434 | struct ieee80211_tx_rate driver_rates[ | 437 | struct ieee80211_tx_rate driver_rates[ |
@@ -852,6 +855,19 @@ enum ieee80211_tkip_key_type { | |||
852 | * any particular flags. There are some exceptions to this rule, | 855 | * any particular flags. There are some exceptions to this rule, |
853 | * however, so you are advised to review these flags carefully. | 856 | * however, so you are advised to review these flags carefully. |
854 | * | 857 | * |
858 | * @IEEE80211_HW_HAS_RATE_CONTROL: | ||
859 | * The hardware or firmware includes rate control, and cannot be | ||
860 | * controlled by the stack. As such, no rate control algorithm | ||
861 | * should be instantiated, and the TX rate reported to userspace | ||
862 | * will be taken from the TX status instead of the rate control | ||
863 | * algorithm. | ||
864 | * Note that this requires that the driver implement a number of | ||
865 | * callbacks so it has the correct information, it needs to have | ||
866 | * the @set_rts_threshold callback and must look at the BSS config | ||
867 | * @use_cts_prot for G/N protection, @use_short_slot for slot | ||
868 | * timing in 2.4 GHz and @use_short_preamble for preambles for | ||
869 | * CCK frames. | ||
870 | * | ||
855 | * @IEEE80211_HW_RX_INCLUDES_FCS: | 871 | * @IEEE80211_HW_RX_INCLUDES_FCS: |
856 | * Indicates that received frames passed to the stack include | 872 | * Indicates that received frames passed to the stack include |
857 | * the FCS at the end. | 873 | * the FCS at the end. |
@@ -910,6 +926,7 @@ enum ieee80211_tkip_key_type { | |||
910 | * avoid waking up cpu. | 926 | * avoid waking up cpu. |
911 | */ | 927 | */ |
912 | enum ieee80211_hw_flags { | 928 | enum ieee80211_hw_flags { |
929 | IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, | ||
913 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, | 930 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, |
914 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, | 931 | IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING = 1<<2, |
915 | IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, | 932 | IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE = 1<<3, |
@@ -1505,6 +1522,7 @@ struct ieee80211_ops { | |||
1505 | void (*reset_tsf)(struct ieee80211_hw *hw); | 1522 | void (*reset_tsf)(struct ieee80211_hw *hw); |
1506 | int (*tx_last_beacon)(struct ieee80211_hw *hw); | 1523 | int (*tx_last_beacon)(struct ieee80211_hw *hw); |
1507 | int (*ampdu_action)(struct ieee80211_hw *hw, | 1524 | int (*ampdu_action)(struct ieee80211_hw *hw, |
1525 | struct ieee80211_vif *vif, | ||
1508 | enum ieee80211_ampdu_mlme_action action, | 1526 | enum ieee80211_ampdu_mlme_action action, |
1509 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); | 1527 | struct ieee80211_sta *sta, u16 tid, u16 *ssn); |
1510 | 1528 | ||
@@ -2026,8 +2044,7 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | |||
2026 | 2044 | ||
2027 | /** | 2045 | /** |
2028 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. | 2046 | * ieee80211_start_tx_ba_session - Start a tx Block Ack session. |
2029 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 2047 | * @sta: the station for which to start a BA session |
2030 | * @ra: receiver address of the BA session recipient | ||
2031 | * @tid: the TID to BA on. | 2048 | * @tid: the TID to BA on. |
2032 | * | 2049 | * |
2033 | * Return: success if addBA request was sent, failure otherwise | 2050 | * Return: success if addBA request was sent, failure otherwise |
@@ -2036,22 +2053,22 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw, | |||
2036 | * the need to start aggregation on a certain RA/TID, the session level | 2053 | * the need to start aggregation on a certain RA/TID, the session level |
2037 | * will be managed by the mac80211. | 2054 | * will be managed by the mac80211. |
2038 | */ | 2055 | */ |
2039 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid); | 2056 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *sta, u16 tid); |
2040 | 2057 | ||
2041 | /** | 2058 | /** |
2042 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. | 2059 | * ieee80211_start_tx_ba_cb - low level driver ready to aggregate. |
2043 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 2060 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf |
2044 | * @ra: receiver address of the BA session recipient. | 2061 | * @ra: receiver address of the BA session recipient. |
2045 | * @tid: the TID to BA on. | 2062 | * @tid: the TID to BA on. |
2046 | * | 2063 | * |
2047 | * This function must be called by low level driver once it has | 2064 | * This function must be called by low level driver once it has |
2048 | * finished with preparations for the BA session. | 2065 | * finished with preparations for the BA session. |
2049 | */ | 2066 | */ |
2050 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); | 2067 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); |
2051 | 2068 | ||
2052 | /** | 2069 | /** |
2053 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. | 2070 | * ieee80211_start_tx_ba_cb_irqsafe - low level driver ready to aggregate. |
2054 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 2071 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf |
2055 | * @ra: receiver address of the BA session recipient. | 2072 | * @ra: receiver address of the BA session recipient. |
2056 | * @tid: the TID to BA on. | 2073 | * @tid: the TID to BA on. |
2057 | * | 2074 | * |
@@ -2059,13 +2076,12 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid); | |||
2059 | * finished with preparations for the BA session. | 2076 | * finished with preparations for the BA session. |
2060 | * This version of the function is IRQ-safe. | 2077 | * This version of the function is IRQ-safe. |
2061 | */ | 2078 | */ |
2062 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 2079 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, |
2063 | u16 tid); | 2080 | u16 tid); |
2064 | 2081 | ||
2065 | /** | 2082 | /** |
2066 | * ieee80211_stop_tx_ba_session - Stop a Block Ack session. | 2083 | * ieee80211_stop_tx_ba_session - Stop a Block Ack session. |
2067 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 2084 | * @sta: the station whose BA session to stop |
2068 | * @ra: receiver address of the BA session recipient | ||
2069 | * @tid: the TID to stop BA. | 2085 | * @tid: the TID to stop BA. |
2070 | * @initiator: if indicates initiator DELBA frame will be sent. | 2086 | * @initiator: if indicates initiator DELBA frame will be sent. |
2071 | * | 2087 | * |
@@ -2075,24 +2091,23 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | |||
2075 | * the need to stop aggregation on a certain RA/TID, the session level | 2091 | * the need to stop aggregation on a certain RA/TID, the session level |
2076 | * will be managed by the mac80211. | 2092 | * will be managed by the mac80211. |
2077 | */ | 2093 | */ |
2078 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | 2094 | int ieee80211_stop_tx_ba_session(struct ieee80211_sta *sta, u16 tid, |
2079 | u8 *ra, u16 tid, | ||
2080 | enum ieee80211_back_parties initiator); | 2095 | enum ieee80211_back_parties initiator); |
2081 | 2096 | ||
2082 | /** | 2097 | /** |
2083 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. | 2098 | * ieee80211_stop_tx_ba_cb - low level driver ready to stop aggregate. |
2084 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 2099 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf |
2085 | * @ra: receiver address of the BA session recipient. | 2100 | * @ra: receiver address of the BA session recipient. |
2086 | * @tid: the desired TID to BA on. | 2101 | * @tid: the desired TID to BA on. |
2087 | * | 2102 | * |
2088 | * This function must be called by low level driver once it has | 2103 | * This function must be called by low level driver once it has |
2089 | * finished with preparations for the BA session tear down. | 2104 | * finished with preparations for the BA session tear down. |
2090 | */ | 2105 | */ |
2091 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); | 2106 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); |
2092 | 2107 | ||
2093 | /** | 2108 | /** |
2094 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. | 2109 | * ieee80211_stop_tx_ba_cb_irqsafe - low level driver ready to stop aggregate. |
2095 | * @hw: pointer as obtained from ieee80211_alloc_hw(). | 2110 | * @vif: &struct ieee80211_vif pointer from &struct ieee80211_if_init_conf |
2096 | * @ra: receiver address of the BA session recipient. | 2111 | * @ra: receiver address of the BA session recipient. |
2097 | * @tid: the desired TID to BA on. | 2112 | * @tid: the desired TID to BA on. |
2098 | * | 2113 | * |
@@ -2100,7 +2115,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid); | |||
2100 | * finished with preparations for the BA session tear down. | 2115 | * finished with preparations for the BA session tear down. |
2101 | * This version of the function is IRQ-safe. | 2116 | * This version of the function is IRQ-safe. |
2102 | */ | 2117 | */ |
2103 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, const u8 *ra, | 2118 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, const u8 *ra, |
2104 | u16 tid); | 2119 | u16 tid); |
2105 | 2120 | ||
2106 | /** | 2121 | /** |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index a6f74b2b9571..a2cbe61f6e65 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -390,6 +390,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
390 | if (dev->br_port != NULL) | 390 | if (dev->br_port != NULL) |
391 | return -EBUSY; | 391 | return -EBUSY; |
392 | 392 | ||
393 | /* No bridging devices that dislike that (e.g. wireless) */ | ||
394 | if (dev->priv_flags & IFF_DONT_BRIDGE) | ||
395 | return -EOPNOTSUPP; | ||
396 | |||
393 | p = new_nbp(br, dev); | 397 | p = new_nbp(br, dev); |
394 | if (IS_ERR(p)) | 398 | if (IS_ERR(p)) |
395 | return PTR_ERR(p); | 399 | return PTR_ERR(p); |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 9f3cf7129324..298cfcc1bf8d 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -2,7 +2,7 @@ obj-$(CONFIG_MAC80211) += mac80211.o | |||
2 | 2 | ||
3 | # mac80211 objects | 3 | # mac80211 objects |
4 | mac80211-y := \ | 4 | mac80211-y := \ |
5 | main.o \ | 5 | main.o status.o \ |
6 | sta_info.o \ | 6 | sta_info.o \ |
7 | wep.o \ | 7 | wep.o \ |
8 | wpa.o \ | 8 | wpa.o \ |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index bc064d7933ff..7ed5fe664732 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -41,7 +41,8 @@ void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
41 | sta->sta.addr, tid); | 41 | sta->sta.addr, tid); |
42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 42 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
43 | 43 | ||
44 | if (drv_ampdu_action(local, IEEE80211_AMPDU_RX_STOP, | 44 | if (drv_ampdu_action(local, &sta->sdata->vif, |
45 | IEEE80211_AMPDU_RX_STOP, | ||
45 | &sta->sta, tid, NULL)) | 46 | &sta->sta, tid, NULL)) |
46 | printk(KERN_DEBUG "HW problem - can not stop rx " | 47 | printk(KERN_DEBUG "HW problem - can not stop rx " |
47 | "aggregation for tid %d\n", tid); | 48 | "aggregation for tid %d\n", tid); |
@@ -170,7 +171,7 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
170 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); | 171 | mgmt->u.action.u.addba_resp.timeout = cpu_to_le16(timeout); |
171 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); | 172 | mgmt->u.action.u.addba_resp.status = cpu_to_le16(status); |
172 | 173 | ||
173 | ieee80211_tx_skb(sdata, skb, 1); | 174 | ieee80211_tx_skb(sdata, skb); |
174 | } | 175 | } |
175 | 176 | ||
176 | void ieee80211_process_addba_request(struct ieee80211_local *local, | 177 | void ieee80211_process_addba_request(struct ieee80211_local *local, |
@@ -284,7 +285,8 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
284 | goto end; | 285 | goto end; |
285 | } | 286 | } |
286 | 287 | ||
287 | ret = drv_ampdu_action(local, IEEE80211_AMPDU_RX_START, | 288 | ret = drv_ampdu_action(local, &sta->sdata->vif, |
289 | IEEE80211_AMPDU_RX_START, | ||
288 | &sta->sta, tid, &start_seq_num); | 290 | &sta->sta, tid, &start_seq_num); |
289 | #ifdef CONFIG_MAC80211_HT_DEBUG | 291 | #ifdef CONFIG_MAC80211_HT_DEBUG |
290 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); | 292 | printk(KERN_DEBUG "Rx A-MPDU request on tid %d result %d\n", tid, ret); |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index b09948ceec4a..b50b2bc3b8c5 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -91,7 +91,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
91 | mgmt->u.action.u.addba_req.start_seq_num = | 91 | mgmt->u.action.u.addba_req.start_seq_num = |
92 | cpu_to_le16(start_seq_num << 4); | 92 | cpu_to_le16(start_seq_num << 4); |
93 | 93 | ||
94 | ieee80211_tx_skb(sdata, skb, 1); | 94 | ieee80211_tx_skb(sdata, skb); |
95 | } | 95 | } |
96 | 96 | ||
97 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | 97 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) |
@@ -120,7 +120,8 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
120 | bar->control = cpu_to_le16(bar_control); | 120 | bar->control = cpu_to_le16(bar_control); |
121 | bar->start_seq_num = cpu_to_le16(ssn); | 121 | bar->start_seq_num = cpu_to_le16(ssn); |
122 | 122 | ||
123 | ieee80211_tx_skb(sdata, skb, 0); | 123 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
124 | ieee80211_tx_skb(sdata, skb); | ||
124 | } | 125 | } |
125 | 126 | ||
126 | static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 127 | static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
@@ -138,7 +139,8 @@ static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
138 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | | 139 | *state = HT_AGG_STATE_REQ_STOP_BA_MSK | |
139 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); | 140 | (initiator << HT_AGG_STATE_INITIATOR_SHIFT); |
140 | 141 | ||
141 | ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_STOP, | 142 | ret = drv_ampdu_action(local, &sta->sdata->vif, |
143 | IEEE80211_AMPDU_TX_STOP, | ||
142 | &sta->sta, tid, NULL); | 144 | &sta->sta, tid, NULL); |
143 | 145 | ||
144 | /* HW shall not deny going back to legacy */ | 146 | /* HW shall not deny going back to legacy */ |
@@ -196,11 +198,11 @@ static inline int ieee80211_ac_from_tid(int tid) | |||
196 | return ieee802_1d_to_ac[tid & 7]; | 198 | return ieee802_1d_to_ac[tid & 7]; |
197 | } | 199 | } |
198 | 200 | ||
199 | int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | 201 | int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) |
200 | { | 202 | { |
201 | struct ieee80211_local *local = hw_to_local(hw); | 203 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
202 | struct sta_info *sta; | 204 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
203 | struct ieee80211_sub_if_data *sdata; | 205 | struct ieee80211_local *local = sdata->local; |
204 | u8 *state; | 206 | u8 *state; |
205 | int ret = 0; | 207 | int ret = 0; |
206 | u16 start_seq_num; | 208 | u16 start_seq_num; |
@@ -208,52 +210,37 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
208 | if (WARN_ON(!local->ops->ampdu_action)) | 210 | if (WARN_ON(!local->ops->ampdu_action)) |
209 | return -EINVAL; | 211 | return -EINVAL; |
210 | 212 | ||
211 | if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION)) | 213 | if ((tid >= STA_TID_NUM) || |
214 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) | ||
212 | return -EINVAL; | 215 | return -EINVAL; |
213 | 216 | ||
214 | #ifdef CONFIG_MAC80211_HT_DEBUG | 217 | #ifdef CONFIG_MAC80211_HT_DEBUG |
215 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", | 218 | printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n", |
216 | ra, tid); | 219 | pubsta->addr, tid); |
217 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 220 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
218 | 221 | ||
219 | rcu_read_lock(); | ||
220 | |||
221 | sta = sta_info_get(local, ra); | ||
222 | if (!sta) { | ||
223 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
224 | printk(KERN_DEBUG "Could not find the station\n"); | ||
225 | #endif | ||
226 | ret = -ENOENT; | ||
227 | goto unlock; | ||
228 | } | ||
229 | |||
230 | /* | 222 | /* |
231 | * The aggregation code is not prepared to handle | 223 | * The aggregation code is not prepared to handle |
232 | * anything but STA/AP due to the BSSID handling. | 224 | * anything but STA/AP due to the BSSID handling. |
233 | * IBSS could work in the code but isn't supported | 225 | * IBSS could work in the code but isn't supported |
234 | * by drivers or the standard. | 226 | * by drivers or the standard. |
235 | */ | 227 | */ |
236 | if (sta->sdata->vif.type != NL80211_IFTYPE_STATION && | 228 | if (sdata->vif.type != NL80211_IFTYPE_STATION && |
237 | sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | 229 | sdata->vif.type != NL80211_IFTYPE_AP_VLAN && |
238 | sta->sdata->vif.type != NL80211_IFTYPE_AP) { | 230 | sdata->vif.type != NL80211_IFTYPE_AP) |
239 | ret = -EINVAL; | 231 | return -EINVAL; |
240 | goto unlock; | ||
241 | } | ||
242 | 232 | ||
243 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { | 233 | if (test_sta_flags(sta, WLAN_STA_SUSPEND)) { |
244 | #ifdef CONFIG_MAC80211_HT_DEBUG | 234 | #ifdef CONFIG_MAC80211_HT_DEBUG |
245 | printk(KERN_DEBUG "Suspend in progress. " | 235 | printk(KERN_DEBUG "Suspend in progress. " |
246 | "Denying BA session request\n"); | 236 | "Denying BA session request\n"); |
247 | #endif | 237 | #endif |
248 | ret = -EINVAL; | 238 | return -EINVAL; |
249 | goto unlock; | ||
250 | } | 239 | } |
251 | 240 | ||
252 | spin_lock_bh(&sta->lock); | 241 | spin_lock_bh(&sta->lock); |
253 | spin_lock(&local->ampdu_lock); | 242 | spin_lock(&local->ampdu_lock); |
254 | 243 | ||
255 | sdata = sta->sdata; | ||
256 | |||
257 | /* we have tried too many times, receiver does not want A-MPDU */ | 244 | /* we have tried too many times, receiver does not want A-MPDU */ |
258 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { | 245 | if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) { |
259 | ret = -EBUSY; | 246 | ret = -EBUSY; |
@@ -310,8 +297,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
310 | 297 | ||
311 | start_seq_num = sta->tid_seq[tid]; | 298 | start_seq_num = sta->tid_seq[tid]; |
312 | 299 | ||
313 | ret = drv_ampdu_action(local, IEEE80211_AMPDU_TX_START, | 300 | ret = drv_ampdu_action(local, &sdata->vif, |
314 | &sta->sta, tid, &start_seq_num); | 301 | IEEE80211_AMPDU_TX_START, |
302 | pubsta, tid, &start_seq_num); | ||
315 | 303 | ||
316 | if (ret) { | 304 | if (ret) { |
317 | #ifdef CONFIG_MAC80211_HT_DEBUG | 305 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -336,7 +324,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
336 | sta->ampdu_mlme.dialog_token_allocator; | 324 | sta->ampdu_mlme.dialog_token_allocator; |
337 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; | 325 | sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num; |
338 | 326 | ||
339 | ieee80211_send_addba_request(sta->sdata, ra, tid, | 327 | ieee80211_send_addba_request(sdata, pubsta->addr, tid, |
340 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, | 328 | sta->ampdu_mlme.tid_tx[tid]->dialog_token, |
341 | sta->ampdu_mlme.tid_tx[tid]->ssn, | 329 | sta->ampdu_mlme.tid_tx[tid]->ssn, |
342 | 0x40, 5000); | 330 | 0x40, 5000); |
@@ -348,7 +336,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
348 | #ifdef CONFIG_MAC80211_HT_DEBUG | 336 | #ifdef CONFIG_MAC80211_HT_DEBUG |
349 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); | 337 | printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid); |
350 | #endif | 338 | #endif |
351 | goto unlock; | 339 | return 0; |
352 | 340 | ||
353 | err_free: | 341 | err_free: |
354 | kfree(sta->ampdu_mlme.tid_tx[tid]); | 342 | kfree(sta->ampdu_mlme.tid_tx[tid]); |
@@ -360,8 +348,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
360 | err_unlock_sta: | 348 | err_unlock_sta: |
361 | spin_unlock(&local->ampdu_lock); | 349 | spin_unlock(&local->ampdu_lock); |
362 | spin_unlock_bh(&sta->lock); | 350 | spin_unlock_bh(&sta->lock); |
363 | unlock: | ||
364 | rcu_read_unlock(); | ||
365 | return ret; | 351 | return ret; |
366 | } | 352 | } |
367 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | 353 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); |
@@ -428,13 +414,15 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
428 | ieee80211_agg_splice_finish(local, sta, tid); | 414 | ieee80211_agg_splice_finish(local, sta, tid); |
429 | spin_unlock(&local->ampdu_lock); | 415 | spin_unlock(&local->ampdu_lock); |
430 | 416 | ||
431 | drv_ampdu_action(local, IEEE80211_AMPDU_TX_OPERATIONAL, | 417 | drv_ampdu_action(local, &sta->sdata->vif, |
418 | IEEE80211_AMPDU_TX_OPERATIONAL, | ||
432 | &sta->sta, tid, NULL); | 419 | &sta->sta, tid, NULL); |
433 | } | 420 | } |
434 | 421 | ||
435 | void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | 422 | void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) |
436 | { | 423 | { |
437 | struct ieee80211_local *local = hw_to_local(hw); | 424 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
425 | struct ieee80211_local *local = sdata->local; | ||
438 | struct sta_info *sta; | 426 | struct sta_info *sta; |
439 | u8 *state; | 427 | u8 *state; |
440 | 428 | ||
@@ -483,10 +471,11 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid) | |||
483 | } | 471 | } |
484 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); | 472 | EXPORT_SYMBOL(ieee80211_start_tx_ba_cb); |
485 | 473 | ||
486 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | 474 | void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, |
487 | const u8 *ra, u16 tid) | 475 | const u8 *ra, u16 tid) |
488 | { | 476 | { |
489 | struct ieee80211_local *local = hw_to_local(hw); | 477 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
478 | struct ieee80211_local *local = sdata->local; | ||
490 | struct ieee80211_ra_tid *ra_tid; | 479 | struct ieee80211_ra_tid *ra_tid; |
491 | struct sk_buff *skb = dev_alloc_skb(0); | 480 | struct sk_buff *skb = dev_alloc_skb(0); |
492 | 481 | ||
@@ -501,6 +490,7 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | |||
501 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 490 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
502 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 491 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
503 | ra_tid->tid = tid; | 492 | ra_tid->tid = tid; |
493 | ra_tid->vif = vif; | ||
504 | 494 | ||
505 | skb->pkt_type = IEEE80211_ADDBA_MSG; | 495 | skb->pkt_type = IEEE80211_ADDBA_MSG; |
506 | skb_queue_tail(&local->skb_queue, skb); | 496 | skb_queue_tail(&local->skb_queue, skb); |
@@ -535,13 +525,12 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
535 | return ret; | 525 | return ret; |
536 | } | 526 | } |
537 | 527 | ||
538 | int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | 528 | int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, |
539 | u8 *ra, u16 tid, | ||
540 | enum ieee80211_back_parties initiator) | 529 | enum ieee80211_back_parties initiator) |
541 | { | 530 | { |
542 | struct ieee80211_local *local = hw_to_local(hw); | 531 | struct sta_info *sta = container_of(pubsta, struct sta_info, sta); |
543 | struct sta_info *sta; | 532 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
544 | int ret = 0; | 533 | struct ieee80211_local *local = sdata->local; |
545 | 534 | ||
546 | if (WARN_ON(!local->ops->ampdu_action)) | 535 | if (WARN_ON(!local->ops->ampdu_action)) |
547 | return -EINVAL; | 536 | return -EINVAL; |
@@ -549,22 +538,14 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw, | |||
549 | if (tid >= STA_TID_NUM) | 538 | if (tid >= STA_TID_NUM) |
550 | return -EINVAL; | 539 | return -EINVAL; |
551 | 540 | ||
552 | rcu_read_lock(); | 541 | return __ieee80211_stop_tx_ba_session(sta, tid, initiator); |
553 | sta = sta_info_get(local, ra); | ||
554 | if (!sta) { | ||
555 | rcu_read_unlock(); | ||
556 | return -ENOENT; | ||
557 | } | ||
558 | |||
559 | ret = __ieee80211_stop_tx_ba_session(sta, tid, initiator); | ||
560 | rcu_read_unlock(); | ||
561 | return ret; | ||
562 | } | 542 | } |
563 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); | 543 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); |
564 | 544 | ||
565 | void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | 545 | void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) |
566 | { | 546 | { |
567 | struct ieee80211_local *local = hw_to_local(hw); | 547 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
548 | struct ieee80211_local *local = sdata->local; | ||
568 | struct sta_info *sta; | 549 | struct sta_info *sta; |
569 | u8 *state; | 550 | u8 *state; |
570 | 551 | ||
@@ -627,10 +608,11 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid) | |||
627 | } | 608 | } |
628 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); | 609 | EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb); |
629 | 610 | ||
630 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | 611 | void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, |
631 | const u8 *ra, u16 tid) | 612 | const u8 *ra, u16 tid) |
632 | { | 613 | { |
633 | struct ieee80211_local *local = hw_to_local(hw); | 614 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
615 | struct ieee80211_local *local = sdata->local; | ||
634 | struct ieee80211_ra_tid *ra_tid; | 616 | struct ieee80211_ra_tid *ra_tid; |
635 | struct sk_buff *skb = dev_alloc_skb(0); | 617 | struct sk_buff *skb = dev_alloc_skb(0); |
636 | 618 | ||
@@ -645,6 +627,7 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw, | |||
645 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 627 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
646 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 628 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
647 | ra_tid->tid = tid; | 629 | ra_tid->tid = tid; |
630 | ra_tid->vif = vif; | ||
648 | 631 | ||
649 | skb->pkt_type = IEEE80211_DELBA_MSG; | 632 | skb->pkt_type = IEEE80211_DELBA_MSG; |
650 | skb_queue_tail(&local->skb_queue, skb); | 633 | skb_queue_tail(&local->skb_queue, skb); |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7f18c8fa1880..93ee1fd5c08d 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -42,15 +42,6 @@ static bool nl80211_params_check(enum nl80211_iftype type, | |||
42 | if (!nl80211_type_check(type)) | 42 | if (!nl80211_type_check(type)) |
43 | return false; | 43 | return false; |
44 | 44 | ||
45 | if (params->use_4addr > 0) { | ||
46 | switch(type) { | ||
47 | case NL80211_IFTYPE_AP_VLAN: | ||
48 | case NL80211_IFTYPE_STATION: | ||
49 | break; | ||
50 | default: | ||
51 | return false; | ||
52 | } | ||
53 | } | ||
54 | return true; | 45 | return true; |
55 | } | 46 | } |
56 | 47 | ||
@@ -107,12 +98,16 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
107 | params->mesh_id_len, | 98 | params->mesh_id_len, |
108 | params->mesh_id); | 99 | params->mesh_id); |
109 | 100 | ||
110 | if (params->use_4addr >= 0) | ||
111 | sdata->use_4addr = !!params->use_4addr; | ||
112 | |||
113 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) | 101 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags) |
114 | return 0; | 102 | return 0; |
115 | 103 | ||
104 | if (type == NL80211_IFTYPE_AP_VLAN && | ||
105 | params && params->use_4addr == 0) | ||
106 | rcu_assign_pointer(sdata->u.vlan.sta, NULL); | ||
107 | else if (type == NL80211_IFTYPE_STATION && | ||
108 | params && params->use_4addr >= 0) | ||
109 | sdata->u.mgd.use_4addr = params->use_4addr; | ||
110 | |||
116 | sdata->u.mntr_flags = *flags; | 111 | sdata->u.mntr_flags = *flags; |
117 | return 0; | 112 | return 0; |
118 | } | 113 | } |
@@ -398,13 +393,13 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
398 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 393 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
399 | int idx, u8 *mac, struct station_info *sinfo) | 394 | int idx, u8 *mac, struct station_info *sinfo) |
400 | { | 395 | { |
401 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 396 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
402 | struct sta_info *sta; | 397 | struct sta_info *sta; |
403 | int ret = -ENOENT; | 398 | int ret = -ENOENT; |
404 | 399 | ||
405 | rcu_read_lock(); | 400 | rcu_read_lock(); |
406 | 401 | ||
407 | sta = sta_info_get_by_idx(local, idx, dev); | 402 | sta = sta_info_get_by_idx(sdata, idx); |
408 | if (sta) { | 403 | if (sta) { |
409 | ret = 0; | 404 | ret = 0; |
410 | memcpy(mac, sta->sta.addr, ETH_ALEN); | 405 | memcpy(mac, sta->sta.addr, ETH_ALEN); |
@@ -827,9 +822,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
827 | return -EINVAL; | 822 | return -EINVAL; |
828 | } | 823 | } |
829 | 824 | ||
830 | if (vlansdata->use_4addr) { | 825 | if (params->vlan->ieee80211_ptr->use_4addr) { |
831 | if (vlansdata->u.vlan.sta) | 826 | if (vlansdata->u.vlan.sta) { |
827 | rcu_read_unlock(); | ||
832 | return -EBUSY; | 828 | return -EBUSY; |
829 | } | ||
833 | 830 | ||
834 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); | 831 | rcu_assign_pointer(vlansdata->u.vlan.sta, sta); |
835 | } | 832 | } |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 82c807723b6f..e4b54093d41b 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -52,7 +52,7 @@ DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", | |||
52 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", | 52 | DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", |
53 | local->wep_iv & 0xffffff); | 53 | local->wep_iv & 0xffffff); |
54 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", | 54 | DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s", |
55 | local->rate_ctrl ? local->rate_ctrl->ops->name : "<unset>"); | 55 | local->rate_ctrl ? local->rate_ctrl->ops->name : "hw/driver"); |
56 | 56 | ||
57 | static ssize_t tsf_read(struct file *file, char __user *user_buf, | 57 | static ssize_t tsf_read(struct file *file, char __user *user_buf, |
58 | size_t count, loff_t *ppos) | 58 | size_t count, loff_t *ppos) |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index f043c29070d7..3f41608c8081 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -157,6 +157,34 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
157 | } | 157 | } |
158 | STA_OPS(agg_status); | 158 | STA_OPS(agg_status); |
159 | 159 | ||
160 | static ssize_t sta_ht_capa_read(struct file *file, char __user *userbuf, | ||
161 | size_t count, loff_t *ppos) | ||
162 | { | ||
163 | char buf[200], *p = buf; | ||
164 | int i; | ||
165 | struct sta_info *sta = file->private_data; | ||
166 | struct ieee80211_sta_ht_cap *htc = &sta->sta.ht_cap; | ||
167 | |||
168 | p += scnprintf(p, sizeof(buf) + buf - p, "ht %ssupported\n", | ||
169 | htc->ht_supported ? "" : "not "); | ||
170 | if (htc->ht_supported) { | ||
171 | p += scnprintf(p, sizeof(buf)+buf-p, "cap: %#.2x\n", htc->cap); | ||
172 | p += scnprintf(p, sizeof(buf)+buf-p, "ampdu factor/density: %d/%d\n", | ||
173 | htc->ampdu_factor, htc->ampdu_density); | ||
174 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS mask:"); | ||
175 | for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) | ||
176 | p += scnprintf(p, sizeof(buf)+buf-p, " %.2x", | ||
177 | htc->mcs.rx_mask[i]); | ||
178 | p += scnprintf(p, sizeof(buf)+buf-p, "\nMCS rx highest: %d\n", | ||
179 | le16_to_cpu(htc->mcs.rx_highest)); | ||
180 | p += scnprintf(p, sizeof(buf)+buf-p, "MCS tx params: %x\n", | ||
181 | htc->mcs.tx_params); | ||
182 | } | ||
183 | |||
184 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | ||
185 | } | ||
186 | STA_OPS(ht_capa); | ||
187 | |||
160 | #define DEBUGFS_ADD(name) \ | 188 | #define DEBUGFS_ADD(name) \ |
161 | debugfs_create_file(#name, 0400, \ | 189 | debugfs_create_file(#name, 0400, \ |
162 | sta->debugfs.dir, sta, &sta_ ##name## _ops); | 190 | sta->debugfs.dir, sta, &sta_ ##name## _ops); |
@@ -207,6 +235,7 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
207 | DEBUGFS_ADD(last_signal); | 235 | DEBUGFS_ADD(last_signal); |
208 | DEBUGFS_ADD(last_noise); | 236 | DEBUGFS_ADD(last_noise); |
209 | DEBUGFS_ADD(wep_weak_iv_count); | 237 | DEBUGFS_ADD(wep_weak_iv_count); |
238 | DEBUGFS_ADD(ht_capa); | ||
210 | } | 239 | } |
211 | 240 | ||
212 | void ieee80211_sta_debugfs_remove(struct sta_info *sta) | 241 | void ieee80211_sta_debugfs_remove(struct sta_info *sta) |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 020a94a31106..921dd9c9ff62 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -239,15 +239,16 @@ static inline int drv_tx_last_beacon(struct ieee80211_local *local) | |||
239 | } | 239 | } |
240 | 240 | ||
241 | static inline int drv_ampdu_action(struct ieee80211_local *local, | 241 | static inline int drv_ampdu_action(struct ieee80211_local *local, |
242 | struct ieee80211_vif *vif, | ||
242 | enum ieee80211_ampdu_mlme_action action, | 243 | enum ieee80211_ampdu_mlme_action action, |
243 | struct ieee80211_sta *sta, u16 tid, | 244 | struct ieee80211_sta *sta, u16 tid, |
244 | u16 *ssn) | 245 | u16 *ssn) |
245 | { | 246 | { |
246 | int ret = -EOPNOTSUPP; | 247 | int ret = -EOPNOTSUPP; |
247 | if (local->ops->ampdu_action) | 248 | if (local->ops->ampdu_action) |
248 | ret = local->ops->ampdu_action(&local->hw, action, | 249 | ret = local->ops->ampdu_action(&local->hw, vif, action, |
249 | sta, tid, ssn); | 250 | sta, tid, ssn); |
250 | trace_drv_ampdu_action(local, action, sta, tid, ssn, ret); | 251 | trace_drv_ampdu_action(local, vif, action, sta, tid, ssn, ret); |
251 | return ret; | 252 | return ret; |
252 | } | 253 | } |
253 | 254 | ||
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 37b9051afcf3..b8fef1d11369 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -634,11 +634,12 @@ TRACE_EVENT(drv_tx_last_beacon, | |||
634 | 634 | ||
635 | TRACE_EVENT(drv_ampdu_action, | 635 | TRACE_EVENT(drv_ampdu_action, |
636 | TP_PROTO(struct ieee80211_local *local, | 636 | TP_PROTO(struct ieee80211_local *local, |
637 | struct ieee80211_vif *vif, | ||
637 | enum ieee80211_ampdu_mlme_action action, | 638 | enum ieee80211_ampdu_mlme_action action, |
638 | struct ieee80211_sta *sta, u16 tid, | 639 | struct ieee80211_sta *sta, u16 tid, |
639 | u16 *ssn, int ret), | 640 | u16 *ssn, int ret), |
640 | 641 | ||
641 | TP_ARGS(local, action, sta, tid, ssn, ret), | 642 | TP_ARGS(local, vif, action, sta, tid, ssn, ret), |
642 | 643 | ||
643 | TP_STRUCT__entry( | 644 | TP_STRUCT__entry( |
644 | LOCAL_ENTRY | 645 | LOCAL_ENTRY |
@@ -647,10 +648,12 @@ TRACE_EVENT(drv_ampdu_action, | |||
647 | __field(u16, tid) | 648 | __field(u16, tid) |
648 | __field(u16, ssn) | 649 | __field(u16, ssn) |
649 | __field(int, ret) | 650 | __field(int, ret) |
651 | VIF_ENTRY | ||
650 | ), | 652 | ), |
651 | 653 | ||
652 | TP_fast_assign( | 654 | TP_fast_assign( |
653 | LOCAL_ASSIGN; | 655 | LOCAL_ASSIGN; |
656 | VIF_ASSIGN; | ||
654 | STA_ASSIGN; | 657 | STA_ASSIGN; |
655 | __entry->ret = ret; | 658 | __entry->ret = ret; |
656 | __entry->action = action; | 659 | __entry->action = action; |
@@ -659,8 +662,8 @@ TRACE_EVENT(drv_ampdu_action, | |||
659 | ), | 662 | ), |
660 | 663 | ||
661 | TP_printk( | 664 | TP_printk( |
662 | LOCAL_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d", | 665 | LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " action:%d tid:%d ret:%d", |
663 | LOCAL_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | 666 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret |
664 | ) | 667 | ) |
665 | ); | 668 | ); |
666 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 669 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 48ef1a282b91..15c9d4f94cee 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -134,14 +134,13 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
134 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 134 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
135 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 135 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
136 | 136 | ||
137 | ieee80211_tx_skb(sdata, skb, 1); | 137 | ieee80211_tx_skb(sdata, skb); |
138 | } | 138 | } |
139 | 139 | ||
140 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 140 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
141 | struct sta_info *sta, | 141 | struct sta_info *sta, |
142 | struct ieee80211_mgmt *mgmt, size_t len) | 142 | struct ieee80211_mgmt *mgmt, size_t len) |
143 | { | 143 | { |
144 | struct ieee80211_local *local = sdata->local; | ||
145 | u16 tid, params; | 144 | u16 tid, params; |
146 | u16 initiator; | 145 | u16 initiator; |
147 | 146 | ||
@@ -164,7 +163,7 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | |||
164 | sta->ampdu_mlme.tid_state_tx[tid] = | 163 | sta->ampdu_mlme.tid_state_tx[tid] = |
165 | HT_AGG_STATE_OPERATIONAL; | 164 | HT_AGG_STATE_OPERATIONAL; |
166 | spin_unlock_bh(&sta->lock); | 165 | spin_unlock_bh(&sta->lock); |
167 | ieee80211_stop_tx_ba_session(&local->hw, sta->sta.addr, tid, | 166 | ieee80211_stop_tx_ba_session(&sta->sta, tid, |
168 | WLAN_BACK_RECIPIENT); | 167 | WLAN_BACK_RECIPIENT); |
169 | } | 168 | } |
170 | } | 169 | } |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index fbffce90edbc..10d13856f86c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -659,7 +659,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
659 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", | 659 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", |
660 | sdata->dev->name, resp->da); | 660 | sdata->dev->name, resp->da); |
661 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 661 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
662 | ieee80211_tx_skb(sdata, skb, 0); | 662 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
663 | ieee80211_tx_skb(sdata, skb); | ||
663 | } | 664 | } |
664 | 665 | ||
665 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, | 666 | static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b63b99fb2fd3..04093e84ebd7 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | #include <linux/etherdevice.h> | 25 | #include <linux/etherdevice.h> |
26 | #include <net/ieee80211_radiotap.h> | ||
26 | #include <net/cfg80211.h> | 27 | #include <net/cfg80211.h> |
27 | #include <net/mac80211.h> | 28 | #include <net/mac80211.h> |
28 | #include "key.h" | 29 | #include "key.h" |
@@ -167,13 +168,10 @@ typedef unsigned __bitwise__ ieee80211_rx_result; | |||
167 | 168 | ||
168 | struct ieee80211_rx_data { | 169 | struct ieee80211_rx_data { |
169 | struct sk_buff *skb; | 170 | struct sk_buff *skb; |
170 | struct net_device *dev; | ||
171 | struct ieee80211_local *local; | 171 | struct ieee80211_local *local; |
172 | struct ieee80211_sub_if_data *sdata; | 172 | struct ieee80211_sub_if_data *sdata; |
173 | struct sta_info *sta; | 173 | struct sta_info *sta; |
174 | struct ieee80211_key *key; | 174 | struct ieee80211_key *key; |
175 | struct ieee80211_rx_status *status; | ||
176 | struct ieee80211_rate *rate; | ||
177 | 175 | ||
178 | unsigned int flags; | 176 | unsigned int flags; |
179 | int queue; | 177 | int queue; |
@@ -314,6 +312,8 @@ struct ieee80211_if_managed { | |||
314 | } mfp; /* management frame protection */ | 312 | } mfp; /* management frame protection */ |
315 | 313 | ||
316 | int wmm_last_param_set; | 314 | int wmm_last_param_set; |
315 | |||
316 | u8 use_4addr; | ||
317 | }; | 317 | }; |
318 | 318 | ||
319 | enum ieee80211_ibss_request { | 319 | enum ieee80211_ibss_request { |
@@ -461,8 +461,6 @@ struct ieee80211_sub_if_data { | |||
461 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ | 461 | int force_unicast_rateidx; /* forced TX rateidx for unicast frames */ |
462 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ | 462 | int max_ratectrl_rateidx; /* max TX rateidx for rate control */ |
463 | 463 | ||
464 | bool use_4addr; /* use 4-address frames */ | ||
465 | |||
466 | union { | 464 | union { |
467 | struct ieee80211_if_ap ap; | 465 | struct ieee80211_if_ap ap; |
468 | struct ieee80211_if_wds wds; | 466 | struct ieee80211_if_wds wds; |
@@ -581,7 +579,6 @@ struct ieee80211_local { | |||
581 | /* number of interfaces with corresponding FIF_ flags */ | 579 | /* number of interfaces with corresponding FIF_ flags */ |
582 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; | 580 | int fif_fcsfail, fif_plcpfail, fif_control, fif_other_bss, fif_pspoll; |
583 | unsigned int filter_flags; /* FIF_* */ | 581 | unsigned int filter_flags; /* FIF_* */ |
584 | struct iw_statistics wstats; | ||
585 | 582 | ||
586 | /* protects the aggregated multicast list and filter calls */ | 583 | /* protects the aggregated multicast list and filter calls */ |
587 | spinlock_t filter_lock; | 584 | spinlock_t filter_lock; |
@@ -771,8 +768,9 @@ IEEE80211_DEV_TO_SUB_IF(struct net_device *dev) | |||
771 | return netdev_priv(dev); | 768 | return netdev_priv(dev); |
772 | } | 769 | } |
773 | 770 | ||
774 | /* this struct represents 802.11n's RA/TID combination */ | 771 | /* this struct represents 802.11n's RA/TID combination along with our vif */ |
775 | struct ieee80211_ra_tid { | 772 | struct ieee80211_ra_tid { |
773 | struct ieee80211_vif *vif; | ||
776 | u8 ra[ETH_ALEN]; | 774 | u8 ra[ETH_ALEN]; |
777 | u16 tid; | 775 | u16 tid; |
778 | }; | 776 | }; |
@@ -799,7 +797,7 @@ struct ieee802_11_elems { | |||
799 | u8 *wmm_param; | 797 | u8 *wmm_param; |
800 | struct ieee80211_ht_cap *ht_cap_elem; | 798 | struct ieee80211_ht_cap *ht_cap_elem; |
801 | struct ieee80211_ht_info *ht_info_elem; | 799 | struct ieee80211_ht_info *ht_info_elem; |
802 | u8 *mesh_config; | 800 | struct ieee80211_meshconf_ie *mesh_config; |
803 | u8 *mesh_id; | 801 | u8 *mesh_id; |
804 | u8 *peer_link; | 802 | u8 *peer_link; |
805 | u8 *preq; | 803 | u8 *preq; |
@@ -827,7 +825,6 @@ struct ieee802_11_elems { | |||
827 | u8 ext_supp_rates_len; | 825 | u8 ext_supp_rates_len; |
828 | u8 wmm_info_len; | 826 | u8 wmm_info_len; |
829 | u8 wmm_param_len; | 827 | u8 wmm_param_len; |
830 | u8 mesh_config_len; | ||
831 | u8 mesh_id_len; | 828 | u8 mesh_id_len; |
832 | u8 peer_link_len; | 829 | u8 peer_link_len; |
833 | u8 preq_len; | 830 | u8 preq_len; |
@@ -950,6 +947,18 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
950 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | 947 | netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, |
951 | struct net_device *dev); | 948 | struct net_device *dev); |
952 | 949 | ||
950 | /* | ||
951 | * radiotap header for status frames | ||
952 | */ | ||
953 | struct ieee80211_tx_status_rtap_hdr { | ||
954 | struct ieee80211_radiotap_header hdr; | ||
955 | u8 rate; | ||
956 | u8 padding_for_rate; | ||
957 | __le16 tx_flags; | ||
958 | u8 data_retries; | ||
959 | } __attribute__ ((packed)); | ||
960 | |||
961 | |||
953 | /* HT */ | 962 | /* HT */ |
954 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, | 963 | void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband, |
955 | struct ieee80211_ht_cap *ht_cap_ie, | 964 | struct ieee80211_ht_cap *ht_cap_ie, |
@@ -1017,8 +1026,7 @@ void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int ke | |||
1017 | struct ieee80211_hdr *hdr, const u8 *tsc, | 1026 | struct ieee80211_hdr *hdr, const u8 *tsc, |
1018 | gfp_t gfp); | 1027 | gfp_t gfp); |
1019 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); | 1028 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata); |
1020 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 1029 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); |
1021 | int encrypt); | ||
1022 | void ieee802_11_parse_elems(u8 *start, size_t len, | 1030 | void ieee802_11_parse_elems(u8 *start, size_t len, |
1023 | struct ieee802_11_elems *elems); | 1031 | struct ieee802_11_elems *elems); |
1024 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | 1032 | u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 1f02b0610e82..1bf12a26b45e 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -752,7 +752,8 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
752 | ieee80211_mandatory_rates(sdata->local, | 752 | ieee80211_mandatory_rates(sdata->local, |
753 | sdata->local->hw.conf.channel->band); | 753 | sdata->local->hw.conf.channel->band); |
754 | sdata->drop_unencrypted = 0; | 754 | sdata->drop_unencrypted = 0; |
755 | sdata->use_4addr = 0; | 755 | if (type == NL80211_IFTYPE_STATION) |
756 | sdata->u.mgd.use_4addr = false; | ||
756 | 757 | ||
757 | return 0; | 758 | return 0; |
758 | } | 759 | } |
@@ -810,6 +811,12 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
810 | /* setup type-dependent data */ | 811 | /* setup type-dependent data */ |
811 | ieee80211_setup_sdata(sdata, type); | 812 | ieee80211_setup_sdata(sdata, type); |
812 | 813 | ||
814 | if (params) { | ||
815 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; | ||
816 | if (type == NL80211_IFTYPE_STATION) | ||
817 | sdata->u.mgd.use_4addr = params->use_4addr; | ||
818 | } | ||
819 | |||
813 | ret = register_netdevice(ndev); | 820 | ret = register_netdevice(ndev); |
814 | if (ret) | 821 | if (ret) |
815 | goto fail; | 822 | goto fail; |
@@ -820,9 +827,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
820 | params->mesh_id_len, | 827 | params->mesh_id_len, |
821 | params->mesh_id); | 828 | params->mesh_id); |
822 | 829 | ||
823 | if (params && params->use_4addr >= 0) | ||
824 | sdata->use_4addr = !!params->use_4addr; | ||
825 | |||
826 | mutex_lock(&local->iflist_mtx); | 830 | mutex_lock(&local->iflist_mtx); |
827 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 831 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
828 | mutex_unlock(&local->iflist_mtx); | 832 | mutex_unlock(&local->iflist_mtx); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index beb8718d905e..dd8ec8d5e8b2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -9,7 +9,6 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <net/mac80211.h> | 11 | #include <net/mac80211.h> |
12 | #include <net/ieee80211_radiotap.h> | ||
13 | #include <linux/module.h> | 12 | #include <linux/module.h> |
14 | #include <linux/init.h> | 13 | #include <linux/init.h> |
15 | #include <linux/netdevice.h> | 14 | #include <linux/netdevice.h> |
@@ -30,26 +29,11 @@ | |||
30 | #include "rate.h" | 29 | #include "rate.h" |
31 | #include "mesh.h" | 30 | #include "mesh.h" |
32 | #include "wep.h" | 31 | #include "wep.h" |
33 | #include "wme.h" | ||
34 | #include "aes_ccm.h" | ||
35 | #include "led.h" | 32 | #include "led.h" |
36 | #include "cfg.h" | 33 | #include "cfg.h" |
37 | #include "debugfs.h" | 34 | #include "debugfs.h" |
38 | #include "debugfs_netdev.h" | 35 | #include "debugfs_netdev.h" |
39 | 36 | ||
40 | /* | ||
41 | * For seeing transmitted packets on monitor interfaces | ||
42 | * we have a radiotap header too. | ||
43 | */ | ||
44 | struct ieee80211_tx_status_rtap_hdr { | ||
45 | struct ieee80211_radiotap_header hdr; | ||
46 | u8 rate; | ||
47 | u8 padding_for_rate; | ||
48 | __le16 tx_flags; | ||
49 | u8 data_retries; | ||
50 | } __attribute__ ((packed)); | ||
51 | |||
52 | |||
53 | void ieee80211_configure_filter(struct ieee80211_local *local) | 37 | void ieee80211_configure_filter(struct ieee80211_local *local) |
54 | { | 38 | { |
55 | u64 mc; | 39 | u64 mc; |
@@ -253,28 +237,6 @@ u32 ieee80211_reset_erp_info(struct ieee80211_sub_if_data *sdata) | |||
253 | BSS_CHANGED_ERP_SLOT; | 237 | BSS_CHANGED_ERP_SLOT; |
254 | } | 238 | } |
255 | 239 | ||
256 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | ||
257 | struct sk_buff *skb) | ||
258 | { | ||
259 | struct ieee80211_local *local = hw_to_local(hw); | ||
260 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
261 | int tmp; | ||
262 | |||
263 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | ||
264 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? | ||
265 | &local->skb_queue : &local->skb_queue_unreliable, skb); | ||
266 | tmp = skb_queue_len(&local->skb_queue) + | ||
267 | skb_queue_len(&local->skb_queue_unreliable); | ||
268 | while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && | ||
269 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { | ||
270 | dev_kfree_skb_irq(skb); | ||
271 | tmp--; | ||
272 | I802_DEBUG_INC(local->tx_status_drop); | ||
273 | } | ||
274 | tasklet_schedule(&local->tasklet); | ||
275 | } | ||
276 | EXPORT_SYMBOL(ieee80211_tx_status_irqsafe); | ||
277 | |||
278 | static void ieee80211_tasklet_handler(unsigned long data) | 240 | static void ieee80211_tasklet_handler(unsigned long data) |
279 | { | 241 | { |
280 | struct ieee80211_local *local = (struct ieee80211_local *) data; | 242 | struct ieee80211_local *local = (struct ieee80211_local *) data; |
@@ -296,14 +258,14 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
296 | break; | 258 | break; |
297 | case IEEE80211_DELBA_MSG: | 259 | case IEEE80211_DELBA_MSG: |
298 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 260 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
299 | ieee80211_stop_tx_ba_cb(local_to_hw(local), | 261 | ieee80211_stop_tx_ba_cb(ra_tid->vif, ra_tid->ra, |
300 | ra_tid->ra, ra_tid->tid); | 262 | ra_tid->tid); |
301 | dev_kfree_skb(skb); | 263 | dev_kfree_skb(skb); |
302 | break; | 264 | break; |
303 | case IEEE80211_ADDBA_MSG: | 265 | case IEEE80211_ADDBA_MSG: |
304 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 266 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
305 | ieee80211_start_tx_ba_cb(local_to_hw(local), | 267 | ieee80211_start_tx_ba_cb(ra_tid->vif, ra_tid->ra, |
306 | ra_tid->ra, ra_tid->tid); | 268 | ra_tid->tid); |
307 | dev_kfree_skb(skb); | 269 | dev_kfree_skb(skb); |
308 | break ; | 270 | break ; |
309 | default: | 271 | default: |
@@ -315,299 +277,6 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
315 | } | 277 | } |
316 | } | 278 | } |
317 | 279 | ||
318 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | ||
319 | struct sta_info *sta, | ||
320 | struct sk_buff *skb) | ||
321 | { | ||
322 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
323 | |||
324 | /* | ||
325 | * XXX: This is temporary! | ||
326 | * | ||
327 | * The problem here is that when we get here, the driver will | ||
328 | * quite likely have pretty much overwritten info->control by | ||
329 | * using info->driver_data or info->rate_driver_data. Thus, | ||
330 | * when passing out the frame to the driver again, we would be | ||
331 | * passing completely bogus data since the driver would then | ||
332 | * expect a properly filled info->control. In mac80211 itself | ||
333 | * the same problem occurs, since we need info->control.vif | ||
334 | * internally. | ||
335 | * | ||
336 | * To fix this, we should send the frame through TX processing | ||
337 | * again. However, it's not that simple, since the frame will | ||
338 | * have been software-encrypted (if applicable) already, and | ||
339 | * encrypting it again doesn't do much good. So to properly do | ||
340 | * that, we not only have to skip the actual 'raw' encryption | ||
341 | * (key selection etc. still has to be done!) but also the | ||
342 | * sequence number assignment since that impacts the crypto | ||
343 | * encapsulation, of course. | ||
344 | * | ||
345 | * Hence, for now, fix the bug by just dropping the frame. | ||
346 | */ | ||
347 | goto drop; | ||
348 | |||
349 | sta->tx_filtered_count++; | ||
350 | |||
351 | /* | ||
352 | * Clear the TX filter mask for this STA when sending the next | ||
353 | * packet. If the STA went to power save mode, this will happen | ||
354 | * when it wakes up for the next time. | ||
355 | */ | ||
356 | set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); | ||
357 | |||
358 | /* | ||
359 | * This code races in the following way: | ||
360 | * | ||
361 | * (1) STA sends frame indicating it will go to sleep and does so | ||
362 | * (2) hardware/firmware adds STA to filter list, passes frame up | ||
363 | * (3) hardware/firmware processes TX fifo and suppresses a frame | ||
364 | * (4) we get TX status before having processed the frame and | ||
365 | * knowing that the STA has gone to sleep. | ||
366 | * | ||
367 | * This is actually quite unlikely even when both those events are | ||
368 | * processed from interrupts coming in quickly after one another or | ||
369 | * even at the same time because we queue both TX status events and | ||
370 | * RX frames to be processed by a tasklet and process them in the | ||
371 | * same order that they were received or TX status last. Hence, there | ||
372 | * is no race as long as the frame RX is processed before the next TX | ||
373 | * status, which drivers can ensure, see below. | ||
374 | * | ||
375 | * Note that this can only happen if the hardware or firmware can | ||
376 | * actually add STAs to the filter list, if this is done by the | ||
377 | * driver in response to set_tim() (which will only reduce the race | ||
378 | * this whole filtering tries to solve, not completely solve it) | ||
379 | * this situation cannot happen. | ||
380 | * | ||
381 | * To completely solve this race drivers need to make sure that they | ||
382 | * (a) don't mix the irq-safe/not irq-safe TX status/RX processing | ||
383 | * functions and | ||
384 | * (b) always process RX events before TX status events if ordering | ||
385 | * can be unknown, for example with different interrupt status | ||
386 | * bits. | ||
387 | */ | ||
388 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && | ||
389 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | ||
390 | skb_queue_tail(&sta->tx_filtered, skb); | ||
391 | return; | ||
392 | } | ||
393 | |||
394 | if (!test_sta_flags(sta, WLAN_STA_PS_STA) && | ||
395 | !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { | ||
396 | /* Software retry the packet once */ | ||
397 | info->flags |= IEEE80211_TX_INTFL_RETRIED; | ||
398 | ieee80211_add_pending_skb(local, skb); | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | drop: | ||
403 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
404 | if (net_ratelimit()) | ||
405 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " | ||
406 | "queue_len=%d PS=%d @%lu\n", | ||
407 | wiphy_name(local->hw.wiphy), | ||
408 | skb_queue_len(&sta->tx_filtered), | ||
409 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); | ||
410 | #endif | ||
411 | dev_kfree_skb(skb); | ||
412 | } | ||
413 | |||
414 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
415 | { | ||
416 | struct sk_buff *skb2; | ||
417 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
418 | struct ieee80211_local *local = hw_to_local(hw); | ||
419 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
420 | u16 frag, type; | ||
421 | __le16 fc; | ||
422 | struct ieee80211_supported_band *sband; | ||
423 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
424 | struct ieee80211_sub_if_data *sdata; | ||
425 | struct net_device *prev_dev = NULL; | ||
426 | struct sta_info *sta; | ||
427 | int retry_count = -1, i; | ||
428 | |||
429 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | ||
430 | /* the HW cannot have attempted that rate */ | ||
431 | if (i >= hw->max_rates) { | ||
432 | info->status.rates[i].idx = -1; | ||
433 | info->status.rates[i].count = 0; | ||
434 | } | ||
435 | |||
436 | retry_count += info->status.rates[i].count; | ||
437 | } | ||
438 | if (retry_count < 0) | ||
439 | retry_count = 0; | ||
440 | |||
441 | rcu_read_lock(); | ||
442 | |||
443 | sband = local->hw.wiphy->bands[info->band]; | ||
444 | |||
445 | sta = sta_info_get(local, hdr->addr1); | ||
446 | |||
447 | if (sta) { | ||
448 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
449 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | ||
450 | /* | ||
451 | * The STA is in power save mode, so assume | ||
452 | * that this TX packet failed because of that. | ||
453 | */ | ||
454 | ieee80211_handle_filtered_frame(local, sta, skb); | ||
455 | rcu_read_unlock(); | ||
456 | return; | ||
457 | } | ||
458 | |||
459 | fc = hdr->frame_control; | ||
460 | |||
461 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
462 | (ieee80211_is_data_qos(fc))) { | ||
463 | u16 tid, ssn; | ||
464 | u8 *qc; | ||
465 | |||
466 | qc = ieee80211_get_qos_ctl(hdr); | ||
467 | tid = qc[0] & 0xf; | ||
468 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) | ||
469 | & IEEE80211_SCTL_SEQ); | ||
470 | ieee80211_send_bar(sta->sdata, hdr->addr1, | ||
471 | tid, ssn); | ||
472 | } | ||
473 | |||
474 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
475 | ieee80211_handle_filtered_frame(local, sta, skb); | ||
476 | rcu_read_unlock(); | ||
477 | return; | ||
478 | } else { | ||
479 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) | ||
480 | sta->tx_retry_failed++; | ||
481 | sta->tx_retry_count += retry_count; | ||
482 | } | ||
483 | |||
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); | ||
487 | } | ||
488 | |||
489 | rcu_read_unlock(); | ||
490 | |||
491 | ieee80211_led_tx(local, 0); | ||
492 | |||
493 | /* SNMP counters | ||
494 | * Fragments are passed to low-level drivers as separate skbs, so these | ||
495 | * are actually fragments, not frames. Update frame counters only for | ||
496 | * the first fragment of the frame. */ | ||
497 | |||
498 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; | ||
499 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | ||
500 | |||
501 | if (info->flags & IEEE80211_TX_STAT_ACK) { | ||
502 | if (frag == 0) { | ||
503 | local->dot11TransmittedFrameCount++; | ||
504 | if (is_multicast_ether_addr(hdr->addr1)) | ||
505 | local->dot11MulticastTransmittedFrameCount++; | ||
506 | if (retry_count > 0) | ||
507 | local->dot11RetryCount++; | ||
508 | if (retry_count > 1) | ||
509 | local->dot11MultipleRetryCount++; | ||
510 | } | ||
511 | |||
512 | /* This counter shall be incremented for an acknowledged MPDU | ||
513 | * with an individual address in the address 1 field or an MPDU | ||
514 | * with a multicast address in the address 1 field of type Data | ||
515 | * or Management. */ | ||
516 | if (!is_multicast_ether_addr(hdr->addr1) || | ||
517 | type == IEEE80211_FTYPE_DATA || | ||
518 | type == IEEE80211_FTYPE_MGMT) | ||
519 | local->dot11TransmittedFragmentCount++; | ||
520 | } else { | ||
521 | if (frag == 0) | ||
522 | local->dot11FailedCount++; | ||
523 | } | ||
524 | |||
525 | /* this was a transmitted frame, but now we want to reuse it */ | ||
526 | skb_orphan(skb); | ||
527 | |||
528 | /* | ||
529 | * This is a bit racy but we can avoid a lot of work | ||
530 | * with this test... | ||
531 | */ | ||
532 | if (!local->monitors && !local->cooked_mntrs) { | ||
533 | dev_kfree_skb(skb); | ||
534 | return; | ||
535 | } | ||
536 | |||
537 | /* send frame to monitor interfaces now */ | ||
538 | |||
539 | if (skb_headroom(skb) < sizeof(*rthdr)) { | ||
540 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | ||
541 | dev_kfree_skb(skb); | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | rthdr = (struct ieee80211_tx_status_rtap_hdr *) | ||
546 | skb_push(skb, sizeof(*rthdr)); | ||
547 | |||
548 | memset(rthdr, 0, sizeof(*rthdr)); | ||
549 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
550 | rthdr->hdr.it_present = | ||
551 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
552 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | | ||
553 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
554 | |||
555 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
556 | !is_multicast_ether_addr(hdr->addr1)) | ||
557 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
558 | |||
559 | /* | ||
560 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
561 | * extensions proposal contains, we can actually report | ||
562 | * the whole set of tries we did. | ||
563 | */ | ||
564 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
565 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
566 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
567 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
568 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
569 | if (info->status.rates[0].idx >= 0 && | ||
570 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
571 | rthdr->rate = sband->bitrates[ | ||
572 | info->status.rates[0].idx].bitrate / 5; | ||
573 | |||
574 | /* for now report the total retry_count */ | ||
575 | rthdr->data_retries = retry_count; | ||
576 | |||
577 | /* XXX: is this sufficient for BPF? */ | ||
578 | skb_set_mac_header(skb, 0); | ||
579 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
580 | skb->pkt_type = PACKET_OTHERHOST; | ||
581 | skb->protocol = htons(ETH_P_802_2); | ||
582 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
583 | |||
584 | rcu_read_lock(); | ||
585 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
586 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | ||
587 | if (!netif_running(sdata->dev)) | ||
588 | continue; | ||
589 | |||
590 | if (prev_dev) { | ||
591 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
592 | if (skb2) { | ||
593 | skb2->dev = prev_dev; | ||
594 | netif_rx(skb2); | ||
595 | } | ||
596 | } | ||
597 | |||
598 | prev_dev = sdata->dev; | ||
599 | } | ||
600 | } | ||
601 | if (prev_dev) { | ||
602 | skb->dev = prev_dev; | ||
603 | netif_rx(skb); | ||
604 | skb = NULL; | ||
605 | } | ||
606 | rcu_read_unlock(); | ||
607 | dev_kfree_skb(skb); | ||
608 | } | ||
609 | EXPORT_SYMBOL(ieee80211_tx_status); | ||
610 | |||
611 | static void ieee80211_restart_work(struct work_struct *work) | 280 | static void ieee80211_restart_work(struct work_struct *work) |
612 | { | 281 | { |
613 | struct ieee80211_local *local = | 282 | struct ieee80211_local *local = |
@@ -659,7 +328,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
659 | if (!wiphy) | 328 | if (!wiphy) |
660 | return NULL; | 329 | return NULL; |
661 | 330 | ||
662 | wiphy->netnsok = true; | 331 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
332 | WIPHY_FLAG_4ADDR_AP | | ||
333 | WIPHY_FLAG_4ADDR_STATION; | ||
663 | wiphy->privid = mac80211_wiphy_privid; | 334 | wiphy->privid = mac80211_wiphy_privid; |
664 | 335 | ||
665 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ | 336 | /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index bbd56b087899..51adb1115215 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -16,12 +16,6 @@ | |||
16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) | 16 | #define IEEE80211_MESH_HOUSEKEEPING_INTERVAL (60 * HZ) |
17 | #define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) | 17 | #define IEEE80211_MESH_RANN_INTERVAL (1 * HZ) |
18 | 18 | ||
19 | #define MESHCONF_PP_OFFSET 0 /* Path Selection Protocol */ | ||
20 | #define MESHCONF_PM_OFFSET 1 /* Path Selection Metric */ | ||
21 | #define MESHCONF_CC_OFFSET 2 /* Congestion Control Mode */ | ||
22 | #define MESHCONF_SP_OFFSET 3 /* Synchronization Protocol */ | ||
23 | #define MESHCONF_AUTH_OFFSET 4 /* Authentication Protocol */ | ||
24 | #define MESHCONF_CAPAB_OFFSET 6 | ||
25 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 | 19 | #define MESHCONF_CAPAB_ACCEPT_PLINKS 0x01 |
26 | #define MESHCONF_CAPAB_FORWARDING 0x08 | 20 | #define MESHCONF_CAPAB_FORWARDING 0x08 |
27 | 21 | ||
@@ -87,12 +81,11 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
87 | */ | 81 | */ |
88 | if (ifmsh->mesh_id_len == ie->mesh_id_len && | 82 | if (ifmsh->mesh_id_len == ie->mesh_id_len && |
89 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && | 83 | memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 && |
90 | (ifmsh->mesh_pp_id == *(ie->mesh_config + MESHCONF_PP_OFFSET))&& | 84 | (ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) && |
91 | (ifmsh->mesh_pm_id == *(ie->mesh_config + MESHCONF_PM_OFFSET))&& | 85 | (ifmsh->mesh_pm_id == ie->mesh_config->meshconf_pmetric) && |
92 | (ifmsh->mesh_cc_id == *(ie->mesh_config + MESHCONF_CC_OFFSET))&& | 86 | (ifmsh->mesh_cc_id == ie->mesh_config->meshconf_congest) && |
93 | (ifmsh->mesh_sp_id == *(ie->mesh_config + MESHCONF_SP_OFFSET))&& | 87 | (ifmsh->mesh_sp_id == ie->mesh_config->meshconf_synch) && |
94 | (ifmsh->mesh_auth_id == *(ie->mesh_config + | 88 | (ifmsh->mesh_auth_id == ie->mesh_config->meshconf_auth)) |
95 | MESHCONF_AUTH_OFFSET))) | ||
96 | return true; | 89 | return true; |
97 | 90 | ||
98 | return false; | 91 | return false; |
@@ -105,7 +98,7 @@ bool mesh_matches_local(struct ieee802_11_elems *ie, struct ieee80211_sub_if_dat | |||
105 | */ | 98 | */ |
106 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 99 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
107 | { | 100 | { |
108 | return (*(ie->mesh_config + MESHCONF_CAPAB_OFFSET) & | 101 | return (ie->mesh_config->meshconf_cap & |
109 | MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | 102 | MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; |
110 | } | 103 | } |
111 | 104 | ||
@@ -262,9 +255,9 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
262 | if (sdata->u.mesh.mesh_id_len) | 255 | if (sdata->u.mesh.mesh_id_len) |
263 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); | 256 | memcpy(pos, sdata->u.mesh.mesh_id, sdata->u.mesh.mesh_id_len); |
264 | 257 | ||
265 | pos = skb_put(skb, 2 + IEEE80211_MESH_CONFIG_LEN); | 258 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_meshconf_ie)); |
266 | *pos++ = WLAN_EID_MESH_CONFIG; | 259 | *pos++ = WLAN_EID_MESH_CONFIG; |
267 | *pos++ = IEEE80211_MESH_CONFIG_LEN; | 260 | *pos++ = sizeof(struct ieee80211_meshconf_ie); |
268 | 261 | ||
269 | /* Active path selection protocol ID */ | 262 | /* Active path selection protocol ID */ |
270 | *pos++ = sdata->u.mesh.mesh_pp_id; | 263 | *pos++ = sdata->u.mesh.mesh_pp_id; |
@@ -394,8 +387,9 @@ void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh) | |||
394 | * | 387 | * |
395 | * Return the length of the 802.11 (does not include a mesh control header) | 388 | * Return the length of the 802.11 (does not include a mesh control header) |
396 | */ | 389 | */ |
397 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, char | 390 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
398 | *meshda, char *meshsa) { | 391 | const u8 *meshda, const u8 *meshsa) |
392 | { | ||
399 | if (is_multicast_ether_addr(meshda)) { | 393 | if (is_multicast_ether_addr(meshda)) { |
400 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); | 394 | *fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS); |
401 | /* DA TA SA */ | 395 | /* DA TA SA */ |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index bd0e1cbb9a1e..31e102541869 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -220,7 +220,7 @@ struct mesh_rmc { | |||
220 | /* Public interfaces */ | 220 | /* Public interfaces */ |
221 | /* Various */ | 221 | /* Various */ |
222 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 222 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
223 | char *da, char *sa); | 223 | const u8 *da, const u8 *sa); |
224 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | 224 | int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, |
225 | struct ieee80211_sub_if_data *sdata, char *addr4, | 225 | struct ieee80211_sub_if_data *sdata, char *addr4, |
226 | char *addr5, char *addr6); | 226 | char *addr5, char *addr6); |
@@ -284,7 +284,7 @@ u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, | |||
284 | struct mesh_table *tbl); | 284 | struct mesh_table *tbl); |
285 | /* Mesh paths */ | 285 | /* Mesh paths */ |
286 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, | 286 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, |
287 | u8 *ra, struct ieee80211_sub_if_data *sdata); | 287 | const u8 *ra, struct ieee80211_sub_if_data *sdata); |
288 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); | 288 | void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta); |
289 | void mesh_path_flush_pending(struct mesh_path *mpath); | 289 | void mesh_path_flush_pending(struct mesh_path *mpath); |
290 | void mesh_path_tx_pending(struct mesh_path *mpath); | 290 | void mesh_path_tx_pending(struct mesh_path *mpath); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 5c67e7b8790f..9aecf0207afc 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -101,10 +101,12 @@ enum mpath_frame_type { | |||
101 | MPATH_RANN | 101 | MPATH_RANN |
102 | }; | 102 | }; |
103 | 103 | ||
104 | static const u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
105 | |||
104 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | 106 | static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, |
105 | u8 *orig_addr, __le32 orig_sn, u8 target_flags, u8 *target, | 107 | u8 *orig_addr, __le32 orig_sn, u8 target_flags, u8 *target, |
106 | __le32 target_sn, u8 *da, u8 hop_count, u8 ttl,__le32 lifetime, | 108 | __le32 target_sn, const u8 *da, u8 hop_count, u8 ttl, |
107 | __le32 metric, __le32 preq_id, | 109 | __le32 lifetime, __le32 metric, __le32 preq_id, |
108 | struct ieee80211_sub_if_data *sdata) | 110 | struct ieee80211_sub_if_data *sdata) |
109 | { | 111 | { |
110 | struct ieee80211_local *local = sdata->local; | 112 | struct ieee80211_local *local = sdata->local; |
@@ -185,7 +187,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
185 | memcpy(pos, &target_sn, 4); | 187 | memcpy(pos, &target_sn, 4); |
186 | } | 188 | } |
187 | 189 | ||
188 | ieee80211_tx_skb(sdata, skb, 1); | 190 | ieee80211_tx_skb(sdata, skb); |
189 | return 0; | 191 | return 0; |
190 | } | 192 | } |
191 | 193 | ||
@@ -198,8 +200,8 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
198 | * @ra: node this frame is addressed to | 200 | * @ra: node this frame is addressed to |
199 | */ | 201 | */ |
200 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | 202 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, |
201 | __le16 target_rcode, u8 *ra, | 203 | __le16 target_rcode, const u8 *ra, |
202 | struct ieee80211_sub_if_data *sdata) | 204 | struct ieee80211_sub_if_data *sdata) |
203 | { | 205 | { |
204 | struct ieee80211_local *local = sdata->local; | 206 | struct ieee80211_local *local = sdata->local; |
205 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | 207 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); |
@@ -248,7 +250,7 @@ int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, | |||
248 | pos += 4; | 250 | pos += 4; |
249 | memcpy(pos, &target_rcode, 2); | 251 | memcpy(pos, &target_rcode, 2); |
250 | 252 | ||
251 | ieee80211_tx_skb(sdata, skb, 1); | 253 | ieee80211_tx_skb(sdata, skb); |
252 | return 0; | 254 | return 0; |
253 | } | 255 | } |
254 | 256 | ||
@@ -548,7 +550,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
548 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; | 550 | hopcount = PREQ_IE_HOPCOUNT(preq_elem) + 1; |
549 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, | 551 | mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr, |
550 | cpu_to_le32(orig_sn), target_flags, target_addr, | 552 | cpu_to_le32(orig_sn), target_flags, target_addr, |
551 | cpu_to_le32(target_sn), sdata->dev->broadcast, | 553 | cpu_to_le32(target_sn), broadcast_addr, |
552 | hopcount, ttl, cpu_to_le32(lifetime), | 554 | hopcount, ttl, cpu_to_le32(lifetime), |
553 | cpu_to_le32(metric), cpu_to_le32(preq_id), | 555 | cpu_to_le32(metric), cpu_to_le32(preq_id), |
554 | sdata); | 556 | sdata); |
@@ -660,7 +662,7 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
660 | spin_unlock_bh(&mpath->state_lock); | 662 | spin_unlock_bh(&mpath->state_lock); |
661 | mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), | 663 | mesh_path_error_tx(ttl, target_addr, cpu_to_le32(target_sn), |
662 | cpu_to_le16(target_rcode), | 664 | cpu_to_le16(target_rcode), |
663 | sdata->dev->broadcast, sdata); | 665 | broadcast_addr, sdata); |
664 | } else | 666 | } else |
665 | spin_unlock_bh(&mpath->state_lock); | 667 | spin_unlock_bh(&mpath->state_lock); |
666 | } | 668 | } |
@@ -709,7 +711,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, | |||
709 | if (mpath->sn < orig_sn) { | 711 | if (mpath->sn < orig_sn) { |
710 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, | 712 | mesh_path_sel_frame_tx(MPATH_RANN, flags, orig_addr, |
711 | cpu_to_le32(orig_sn), | 713 | cpu_to_le32(orig_sn), |
712 | 0, NULL, 0, sdata->dev->broadcast, | 714 | 0, NULL, 0, broadcast_addr, |
713 | hopcount, ttl, 0, | 715 | hopcount, ttl, 0, |
714 | cpu_to_le32(metric + mpath->metric), | 716 | cpu_to_le32(metric + mpath->metric), |
715 | 0, sdata); | 717 | 0, sdata); |
@@ -890,7 +892,7 @@ void mesh_path_start_discovery(struct ieee80211_sub_if_data *sdata) | |||
890 | spin_unlock_bh(&mpath->state_lock); | 892 | spin_unlock_bh(&mpath->state_lock); |
891 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, | 893 | mesh_path_sel_frame_tx(MPATH_PREQ, 0, sdata->dev->dev_addr, |
892 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, | 894 | cpu_to_le32(ifmsh->sn), target_flags, mpath->dst, |
893 | cpu_to_le32(mpath->sn), sdata->dev->broadcast, 0, | 895 | cpu_to_le32(mpath->sn), broadcast_addr, 0, |
894 | ttl, cpu_to_le32(lifetime), 0, | 896 | ttl, cpu_to_le32(lifetime), 0, |
895 | cpu_to_le32(ifmsh->preq_id++), sdata); | 897 | cpu_to_le32(ifmsh->preq_id++), sdata); |
896 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); | 898 | mod_timer(&mpath->timer, jiffies + mpath->discovery_timeout); |
@@ -1011,6 +1013,6 @@ mesh_path_tx_root_frame(struct ieee80211_sub_if_data *sdata) | |||
1011 | 1013 | ||
1012 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr, | 1014 | mesh_path_sel_frame_tx(MPATH_RANN, 0, sdata->dev->dev_addr, |
1013 | cpu_to_le32(++ifmsh->sn), | 1015 | cpu_to_le32(++ifmsh->sn), |
1014 | 0, NULL, 0, sdata->dev->broadcast, | 1016 | 0, NULL, 0, broadcast_addr, |
1015 | 0, MESH_TTL, 0, 0, 0, sdata); | 1017 | 0, MESH_TTL, 0, 0, 0, sdata); |
1016 | } | 1018 | } |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 5399e7a9ec6e..a8da23905c70 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -449,6 +449,7 @@ err_path_alloc: | |||
449 | */ | 449 | */ |
450 | void mesh_plink_broken(struct sta_info *sta) | 450 | void mesh_plink_broken(struct sta_info *sta) |
451 | { | 451 | { |
452 | static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
452 | struct mesh_path *mpath; | 453 | struct mesh_path *mpath; |
453 | struct mpath_node *node; | 454 | struct mpath_node *node; |
454 | struct hlist_node *p; | 455 | struct hlist_node *p; |
@@ -467,8 +468,8 @@ void mesh_plink_broken(struct sta_info *sta) | |||
467 | spin_unlock_bh(&mpath->state_lock); | 468 | spin_unlock_bh(&mpath->state_lock); |
468 | mesh_path_error_tx(MESH_TTL, mpath->dst, | 469 | mesh_path_error_tx(MESH_TTL, mpath->dst, |
469 | cpu_to_le32(mpath->sn), | 470 | cpu_to_le32(mpath->sn), |
470 | PERR_RCODE_DEST_UNREACH, | 471 | cpu_to_le16(PERR_RCODE_DEST_UNREACH), |
471 | sdata->dev->broadcast, sdata); | 472 | bcast, sdata); |
472 | } else | 473 | } else |
473 | spin_unlock_bh(&mpath->state_lock); | 474 | spin_unlock_bh(&mpath->state_lock); |
474 | } | 475 | } |
@@ -613,7 +614,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
613 | if (mpath) | 614 | if (mpath) |
614 | sn = ++mpath->sn; | 615 | sn = ++mpath->sn; |
615 | mesh_path_error_tx(MESH_TTL, skb->data, cpu_to_le32(sn), | 616 | mesh_path_error_tx(MESH_TTL, skb->data, cpu_to_le32(sn), |
616 | PERR_RCODE_NO_ROUTE, ra, sdata); | 617 | cpu_to_le16(PERR_RCODE_NO_ROUTE), ra, sdata); |
617 | } | 618 | } |
618 | 619 | ||
619 | kfree_skb(skb); | 620 | kfree_skb(skb); |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index f21329afdae3..0f7c6e6a4248 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -222,7 +222,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
222 | memcpy(pos, &reason, 2); | 222 | memcpy(pos, &reason, 2); |
223 | } | 223 | } |
224 | 224 | ||
225 | ieee80211_tx_skb(sdata, skb, 1); | 225 | ieee80211_tx_skb(sdata, skb); |
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | 228 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2af306f67d78..6dc7b5ad9a41 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -426,7 +426,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
426 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); | 426 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
427 | } | 427 | } |
428 | 428 | ||
429 | ieee80211_tx_skb(sdata, skb, 0); | 429 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
430 | ieee80211_tx_skb(sdata, skb); | ||
430 | } | 431 | } |
431 | 432 | ||
432 | 433 | ||
@@ -467,7 +468,9 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
467 | __cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | 468 | __cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); |
468 | else | 469 | else |
469 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); | 470 | cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len); |
470 | ieee80211_tx_skb(sdata, skb, ifmgd->flags & IEEE80211_STA_MFP_ENABLED); | 471 | if (!(ifmgd->flags & IEEE80211_STA_MFP_ENABLED)) |
472 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
473 | ieee80211_tx_skb(sdata, skb); | ||
471 | } | 474 | } |
472 | 475 | ||
473 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 476 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
@@ -498,7 +501,8 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
498 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); | 501 | memcpy(pspoll->bssid, ifmgd->bssid, ETH_ALEN); |
499 | memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); | 502 | memcpy(pspoll->ta, sdata->dev->dev_addr, ETH_ALEN); |
500 | 503 | ||
501 | ieee80211_tx_skb(sdata, skb, 0); | 504 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
505 | ieee80211_tx_skb(sdata, skb); | ||
502 | } | 506 | } |
503 | 507 | ||
504 | void ieee80211_send_nullfunc(struct ieee80211_local *local, | 508 | void ieee80211_send_nullfunc(struct ieee80211_local *local, |
@@ -531,7 +535,8 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, | |||
531 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); | 535 | memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); |
532 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); | 536 | memcpy(nullfunc->addr3, sdata->u.mgd.bssid, ETH_ALEN); |
533 | 537 | ||
534 | ieee80211_tx_skb(sdata, skb, 0); | 538 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
539 | ieee80211_tx_skb(sdata, skb); | ||
535 | } | 540 | } |
536 | 541 | ||
537 | /* spectrum management related things */ | 542 | /* spectrum management related things */ |
@@ -2503,6 +2508,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2503 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 2508 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
2504 | struct ieee80211_mgd_work *wk; | 2509 | struct ieee80211_mgd_work *wk; |
2505 | const u8 *bssid = NULL; | 2510 | const u8 *bssid = NULL; |
2511 | bool not_auth_yet = false; | ||
2506 | 2512 | ||
2507 | mutex_lock(&ifmgd->mtx); | 2513 | mutex_lock(&ifmgd->mtx); |
2508 | 2514 | ||
@@ -2512,6 +2518,8 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2512 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { | 2518 | } else list_for_each_entry(wk, &ifmgd->work_list, list) { |
2513 | if (&wk->bss->cbss == req->bss) { | 2519 | if (&wk->bss->cbss == req->bss) { |
2514 | bssid = req->bss->bssid; | 2520 | bssid = req->bss->bssid; |
2521 | if (wk->state == IEEE80211_MGD_STATE_PROBE) | ||
2522 | not_auth_yet = true; | ||
2515 | list_del(&wk->list); | 2523 | list_del(&wk->list); |
2516 | kfree(wk); | 2524 | kfree(wk); |
2517 | break; | 2525 | break; |
@@ -2519,6 +2527,20 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
2519 | } | 2527 | } |
2520 | 2528 | ||
2521 | /* | 2529 | /* |
2530 | * If somebody requests authentication and we haven't | ||
2531 | * sent out an auth frame yet there's no need to send | ||
2532 | * out a deauth frame either. If the state was PROBE, | ||
2533 | * then this is the case. If it's AUTH we have sent a | ||
2534 | * frame, and if it's IDLE we have completed the auth | ||
2535 | * process already. | ||
2536 | */ | ||
2537 | if (not_auth_yet) { | ||
2538 | mutex_unlock(&ifmgd->mtx); | ||
2539 | __cfg80211_auth_canceled(sdata->dev, bssid); | ||
2540 | return 0; | ||
2541 | } | ||
2542 | |||
2543 | /* | ||
2522 | * cfg80211 should catch this ... but it's racy since | 2544 | * cfg80211 should catch this ... but it's racy since |
2523 | * we can receive a deauth frame, process it, hand it | 2545 | * we can receive a deauth frame, process it, hand it |
2524 | * to cfg80211 while that's in a locked section already | 2546 | * to cfg80211 while that's in a locked section already |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index ccda7454fb17..b9007f80cb92 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -284,9 +284,16 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
284 | struct rate_control_ref *ref, *old; | 284 | struct rate_control_ref *ref, *old; |
285 | 285 | ||
286 | ASSERT_RTNL(); | 286 | ASSERT_RTNL(); |
287 | |||
287 | if (local->open_count) | 288 | if (local->open_count) |
288 | return -EBUSY; | 289 | return -EBUSY; |
289 | 290 | ||
291 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { | ||
292 | if (WARN_ON(!local->ops->set_rts_threshold)) | ||
293 | return -EINVAL; | ||
294 | return 0; | ||
295 | } | ||
296 | |||
290 | ref = rate_control_alloc(name, local); | 297 | ref = rate_control_alloc(name, local); |
291 | if (!ref) { | 298 | if (!ref) { |
292 | printk(KERN_WARNING "%s: Failed to select rate control " | 299 | printk(KERN_WARNING "%s: Failed to select rate control " |
@@ -305,7 +312,6 @@ int ieee80211_init_rate_ctrl_alg(struct ieee80211_local *local, | |||
305 | "algorithm '%s'\n", wiphy_name(local->hw.wiphy), | 312 | "algorithm '%s'\n", wiphy_name(local->hw.wiphy), |
306 | ref->ops->name); | 313 | ref->ops->name); |
307 | 314 | ||
308 | |||
309 | return 0; | 315 | return 0; |
310 | } | 316 | } |
311 | 317 | ||
@@ -314,6 +320,10 @@ void rate_control_deinitialize(struct ieee80211_local *local) | |||
314 | struct rate_control_ref *ref; | 320 | struct rate_control_ref *ref; |
315 | 321 | ||
316 | ref = local->rate_ctrl; | 322 | ref = local->rate_ctrl; |
323 | |||
324 | if (!ref) | ||
325 | return; | ||
326 | |||
317 | local->rate_ctrl = NULL; | 327 | local->rate_ctrl = NULL; |
318 | rate_control_put(ref); | 328 | rate_control_put(ref); |
319 | } | 329 | } |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 2ab5ad9e71ce..cb9bd1f65e27 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -59,6 +59,9 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
59 | void *priv_sta = sta->rate_ctrl_priv; | 59 | void *priv_sta = sta->rate_ctrl_priv; |
60 | struct ieee80211_supported_band *sband; | 60 | struct ieee80211_supported_band *sband; |
61 | 61 | ||
62 | if (!ref) | ||
63 | return; | ||
64 | |||
62 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 65 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
63 | 66 | ||
64 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 67 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
@@ -72,7 +75,7 @@ static inline void rate_control_rate_update(struct ieee80211_local *local, | |||
72 | struct ieee80211_sta *ista = &sta->sta; | 75 | struct ieee80211_sta *ista = &sta->sta; |
73 | void *priv_sta = sta->rate_ctrl_priv; | 76 | void *priv_sta = sta->rate_ctrl_priv; |
74 | 77 | ||
75 | if (ref->ops->rate_update) | 78 | if (ref && ref->ops->rate_update) |
76 | ref->ops->rate_update(ref->priv, sband, ista, | 79 | ref->ops->rate_update(ref->priv, sband, ista, |
77 | priv_sta, changed); | 80 | priv_sta, changed); |
78 | } | 81 | } |
@@ -97,7 +100,7 @@ static inline void rate_control_add_sta_debugfs(struct sta_info *sta) | |||
97 | { | 100 | { |
98 | #ifdef CONFIG_MAC80211_DEBUGFS | 101 | #ifdef CONFIG_MAC80211_DEBUGFS |
99 | struct rate_control_ref *ref = sta->rate_ctrl; | 102 | struct rate_control_ref *ref = sta->rate_ctrl; |
100 | if (sta->debugfs.dir && ref->ops->add_sta_debugfs) | 103 | if (ref && sta->debugfs.dir && ref->ops->add_sta_debugfs) |
101 | ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, | 104 | ref->ops->add_sta_debugfs(ref->priv, sta->rate_ctrl_priv, |
102 | sta->debugfs.dir); | 105 | sta->debugfs.dir); |
103 | #endif | 106 | #endif |
@@ -107,7 +110,7 @@ static inline void rate_control_remove_sta_debugfs(struct sta_info *sta) | |||
107 | { | 110 | { |
108 | #ifdef CONFIG_MAC80211_DEBUGFS | 111 | #ifdef CONFIG_MAC80211_DEBUGFS |
109 | struct rate_control_ref *ref = sta->rate_ctrl; | 112 | struct rate_control_ref *ref = sta->rate_ctrl; |
110 | if (ref->ops->remove_sta_debugfs) | 113 | if (ref && ref->ops->remove_sta_debugfs) |
111 | ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); | 114 | ref->ops->remove_sta_debugfs(ref->priv, sta->rate_ctrl_priv); |
112 | #endif | 115 | #endif |
113 | } | 116 | } |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 6bce97ee2534..96f13ad05d3c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -27,11 +27,10 @@ | |||
27 | #include "tkip.h" | 27 | #include "tkip.h" |
28 | #include "wme.h" | 28 | #include "wme.h" |
29 | 29 | ||
30 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 30 | static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, |
31 | struct tid_ampdu_rx *tid_agg_rx, | 31 | struct tid_ampdu_rx *tid_agg_rx, |
32 | struct sk_buff *skb, | 32 | u16 head_seq_num); |
33 | u16 mpdu_seq_num, | 33 | |
34 | int bar_req); | ||
35 | /* | 34 | /* |
36 | * monitor mode reception | 35 | * monitor mode reception |
37 | * | 36 | * |
@@ -164,6 +163,9 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
164 | if (status->band == IEEE80211_BAND_5GHZ) | 163 | if (status->band == IEEE80211_BAND_5GHZ) |
165 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, | 164 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, |
166 | pos); | 165 | pos); |
166 | else if (status->flag & RX_FLAG_HT) | ||
167 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | ||
168 | pos); | ||
167 | else if (rate->flags & IEEE80211_RATE_ERP_G) | 169 | else if (rate->flags & IEEE80211_RATE_ERP_G) |
168 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, | 170 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ, |
169 | pos); | 171 | pos); |
@@ -478,7 +480,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
478 | { | 480 | { |
479 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 481 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
480 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); | 482 | unsigned int hdrlen = ieee80211_hdrlen(hdr->frame_control); |
481 | char *dev_addr = rx->dev->dev_addr; | 483 | char *dev_addr = rx->sdata->dev->dev_addr; |
482 | 484 | ||
483 | if (ieee80211_is_data(hdr->frame_control)) { | 485 | if (ieee80211_is_data(hdr->frame_control)) { |
484 | if (is_multicast_ether_addr(hdr->addr1)) { | 486 | if (is_multicast_ether_addr(hdr->addr1)) { |
@@ -592,7 +594,9 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
592 | static ieee80211_rx_result debug_noinline | 594 | static ieee80211_rx_result debug_noinline |
593 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | 595 | ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) |
594 | { | 596 | { |
595 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 597 | struct sk_buff *skb = rx->skb; |
598 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
599 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
596 | int keyidx; | 600 | int keyidx; |
597 | int hdrlen; | 601 | int hdrlen; |
598 | ieee80211_rx_result result = RX_DROP_UNUSABLE; | 602 | ieee80211_rx_result result = RX_DROP_UNUSABLE; |
@@ -646,8 +650,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
646 | return RX_CONTINUE; | 650 | return RX_CONTINUE; |
647 | } else if (mmie_keyidx >= 0) { | 651 | } else if (mmie_keyidx >= 0) { |
648 | /* Broadcast/multicast robust management frame / BIP */ | 652 | /* Broadcast/multicast robust management frame / BIP */ |
649 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 653 | if ((status->flag & RX_FLAG_DECRYPTED) && |
650 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | 654 | (status->flag & RX_FLAG_IV_STRIPPED)) |
651 | return RX_CONTINUE; | 655 | return RX_CONTINUE; |
652 | 656 | ||
653 | if (mmie_keyidx < NUM_DEFAULT_KEYS || | 657 | if (mmie_keyidx < NUM_DEFAULT_KEYS || |
@@ -679,8 +683,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
679 | * we somehow allow the driver to tell us which key | 683 | * we somehow allow the driver to tell us which key |
680 | * the hardware used if this flag is set? | 684 | * the hardware used if this flag is set? |
681 | */ | 685 | */ |
682 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 686 | if ((status->flag & RX_FLAG_DECRYPTED) && |
683 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | 687 | (status->flag & RX_FLAG_IV_STRIPPED)) |
684 | return RX_CONTINUE; | 688 | return RX_CONTINUE; |
685 | 689 | ||
686 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 690 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
@@ -716,8 +720,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
716 | /* Check for weak IVs if possible */ | 720 | /* Check for weak IVs if possible */ |
717 | if (rx->sta && rx->key->conf.alg == ALG_WEP && | 721 | if (rx->sta && rx->key->conf.alg == ALG_WEP && |
718 | ieee80211_is_data(hdr->frame_control) && | 722 | ieee80211_is_data(hdr->frame_control) && |
719 | (!(rx->status->flag & RX_FLAG_IV_STRIPPED) || | 723 | (!(status->flag & RX_FLAG_IV_STRIPPED) || |
720 | !(rx->status->flag & RX_FLAG_DECRYPTED)) && | 724 | !(status->flag & RX_FLAG_DECRYPTED)) && |
721 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | 725 | ieee80211_wep_is_weak_iv(rx->skb, rx->key)) |
722 | rx->sta->wep_weak_iv_count++; | 726 | rx->sta->wep_weak_iv_count++; |
723 | 727 | ||
@@ -737,7 +741,7 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) | |||
737 | } | 741 | } |
738 | 742 | ||
739 | /* either the frame has been decrypted or will be dropped */ | 743 | /* either the frame has been decrypted or will be dropped */ |
740 | rx->status->flag |= RX_FLAG_DECRYPTED; | 744 | status->flag |= RX_FLAG_DECRYPTED; |
741 | 745 | ||
742 | return result; | 746 | return result; |
743 | } | 747 | } |
@@ -817,7 +821,9 @@ static ieee80211_rx_result debug_noinline | |||
817 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | 821 | ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) |
818 | { | 822 | { |
819 | struct sta_info *sta = rx->sta; | 823 | struct sta_info *sta = rx->sta; |
820 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 824 | struct sk_buff *skb = rx->skb; |
825 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
826 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
821 | 827 | ||
822 | if (!sta) | 828 | if (!sta) |
823 | return RX_CONTINUE; | 829 | return RX_CONTINUE; |
@@ -848,8 +854,8 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
848 | 854 | ||
849 | sta->rx_fragments++; | 855 | sta->rx_fragments++; |
850 | sta->rx_bytes += rx->skb->len; | 856 | sta->rx_bytes += rx->skb->len; |
851 | sta->last_signal = rx->status->signal; | 857 | sta->last_signal = status->signal; |
852 | sta->last_noise = rx->status->noise; | 858 | sta->last_noise = status->noise; |
853 | 859 | ||
854 | /* | 860 | /* |
855 | * Change STA power saving mode only at the end of a frame | 861 | * Change STA power saving mode only at the end of a frame |
@@ -1141,11 +1147,14 @@ ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx) | |||
1141 | static int | 1147 | static int |
1142 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | 1148 | ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) |
1143 | { | 1149 | { |
1150 | struct sk_buff *skb = rx->skb; | ||
1151 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
1152 | |||
1144 | /* | 1153 | /* |
1145 | * Pass through unencrypted frames if the hardware has | 1154 | * Pass through unencrypted frames if the hardware has |
1146 | * decrypted them already. | 1155 | * decrypted them already. |
1147 | */ | 1156 | */ |
1148 | if (rx->status->flag & RX_FLAG_DECRYPTED) | 1157 | if (status->flag & RX_FLAG_DECRYPTED) |
1149 | return 0; | 1158 | return 0; |
1150 | 1159 | ||
1151 | /* Drop unencrypted frames if key is set. */ | 1160 | /* Drop unencrypted frames if key is set. */ |
@@ -1179,14 +1188,17 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc) | |||
1179 | static int | 1188 | static int |
1180 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) | 1189 | __ieee80211_data_to_8023(struct ieee80211_rx_data *rx) |
1181 | { | 1190 | { |
1182 | struct net_device *dev = rx->dev; | 1191 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1183 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1192 | struct net_device *dev = sdata->dev; |
1184 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1193 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1185 | 1194 | ||
1186 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->use_4addr && | 1195 | if (ieee80211_has_a4(hdr->frame_control) && |
1187 | ieee80211_has_a4(hdr->frame_control)) | 1196 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) |
1188 | return -1; | 1197 | return -1; |
1189 | if (sdata->use_4addr && is_multicast_ether_addr(hdr->addr1)) | 1198 | |
1199 | if (is_multicast_ether_addr(hdr->addr1) && | ||
1200 | ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN && sdata->u.vlan.sta) || | ||
1201 | (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.use_4addr))) | ||
1190 | return -1; | 1202 | return -1; |
1191 | 1203 | ||
1192 | return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); | 1204 | return ieee80211_data_to_8023(rx->skb, dev->dev_addr, sdata->vif.type); |
@@ -1206,7 +1218,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | |||
1206 | * of whether the frame was encrypted or not. | 1218 | * of whether the frame was encrypted or not. |
1207 | */ | 1219 | */ |
1208 | if (ehdr->h_proto == htons(ETH_P_PAE) && | 1220 | if (ehdr->h_proto == htons(ETH_P_PAE) && |
1209 | (compare_ether_addr(ehdr->h_dest, rx->dev->dev_addr) == 0 || | 1221 | (compare_ether_addr(ehdr->h_dest, rx->sdata->dev->dev_addr) == 0 || |
1210 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) | 1222 | compare_ether_addr(ehdr->h_dest, pae_group_addr) == 0)) |
1211 | return true; | 1223 | return true; |
1212 | 1224 | ||
@@ -1223,10 +1235,10 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc) | |||
1223 | static void | 1235 | static void |
1224 | ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | 1236 | ieee80211_deliver_skb(struct ieee80211_rx_data *rx) |
1225 | { | 1237 | { |
1226 | struct net_device *dev = rx->dev; | 1238 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1239 | struct net_device *dev = sdata->dev; | ||
1227 | struct ieee80211_local *local = rx->local; | 1240 | struct ieee80211_local *local = rx->local; |
1228 | struct sk_buff *skb, *xmit_skb; | 1241 | struct sk_buff *skb, *xmit_skb; |
1229 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1230 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; | 1242 | struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; |
1231 | struct sta_info *dsta; | 1243 | struct sta_info *dsta; |
1232 | 1244 | ||
@@ -1236,7 +1248,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1236 | if ((sdata->vif.type == NL80211_IFTYPE_AP || | 1248 | if ((sdata->vif.type == NL80211_IFTYPE_AP || |
1237 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && | 1249 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
1238 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && | 1250 | !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && |
1239 | (rx->flags & IEEE80211_RX_RA_MATCH) && !rx->sdata->use_4addr) { | 1251 | (rx->flags & IEEE80211_RX_RA_MATCH) && |
1252 | (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) { | ||
1240 | if (is_multicast_ether_addr(ehdr->h_dest)) { | 1253 | if (is_multicast_ether_addr(ehdr->h_dest)) { |
1241 | /* | 1254 | /* |
1242 | * send multicast frames both to higher layers in | 1255 | * send multicast frames both to higher layers in |
@@ -1307,7 +1320,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
1307 | static ieee80211_rx_result debug_noinline | 1320 | static ieee80211_rx_result debug_noinline |
1308 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | 1321 | ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) |
1309 | { | 1322 | { |
1310 | struct net_device *dev = rx->dev; | 1323 | struct net_device *dev = rx->sdata->dev; |
1311 | struct ieee80211_local *local = rx->local; | 1324 | struct ieee80211_local *local = rx->local; |
1312 | u16 ethertype; | 1325 | u16 ethertype; |
1313 | u8 *payload; | 1326 | u8 *payload; |
@@ -1432,12 +1445,11 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1432 | unsigned int hdrlen; | 1445 | unsigned int hdrlen; |
1433 | struct sk_buff *skb = rx->skb, *fwd_skb; | 1446 | struct sk_buff *skb = rx->skb, *fwd_skb; |
1434 | struct ieee80211_local *local = rx->local; | 1447 | struct ieee80211_local *local = rx->local; |
1435 | struct ieee80211_sub_if_data *sdata; | 1448 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1436 | 1449 | ||
1437 | hdr = (struct ieee80211_hdr *) skb->data; | 1450 | hdr = (struct ieee80211_hdr *) skb->data; |
1438 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1451 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1439 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1452 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1440 | sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | ||
1441 | 1453 | ||
1442 | if (!ieee80211_is_data(hdr->frame_control)) | 1454 | if (!ieee80211_is_data(hdr->frame_control)) |
1443 | return RX_CONTINUE; | 1455 | return RX_CONTINUE; |
@@ -1475,7 +1487,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1475 | 1487 | ||
1476 | /* Frame has reached destination. Don't forward */ | 1488 | /* Frame has reached destination. Don't forward */ |
1477 | if (!is_multicast_ether_addr(hdr->addr1) && | 1489 | if (!is_multicast_ether_addr(hdr->addr1) && |
1478 | compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0) | 1490 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr3) == 0) |
1479 | return RX_CONTINUE; | 1491 | return RX_CONTINUE; |
1480 | 1492 | ||
1481 | mesh_hdr->ttl--; | 1493 | mesh_hdr->ttl--; |
@@ -1492,10 +1504,10 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1492 | 1504 | ||
1493 | if (!fwd_skb && net_ratelimit()) | 1505 | if (!fwd_skb && net_ratelimit()) |
1494 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", | 1506 | printk(KERN_DEBUG "%s: failed to clone mesh frame\n", |
1495 | rx->dev->name); | 1507 | sdata->dev->name); |
1496 | 1508 | ||
1497 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; | 1509 | fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data; |
1498 | memcpy(fwd_hdr->addr2, rx->dev->dev_addr, ETH_ALEN); | 1510 | memcpy(fwd_hdr->addr2, sdata->dev->dev_addr, ETH_ALEN); |
1499 | info = IEEE80211_SKB_CB(fwd_skb); | 1511 | info = IEEE80211_SKB_CB(fwd_skb); |
1500 | memset(info, 0, sizeof(*info)); | 1512 | memset(info, 0, sizeof(*info)); |
1501 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; | 1513 | info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING; |
@@ -1529,7 +1541,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1529 | } | 1541 | } |
1530 | 1542 | ||
1531 | if (is_multicast_ether_addr(hdr->addr1) || | 1543 | if (is_multicast_ether_addr(hdr->addr1) || |
1532 | rx->dev->flags & IFF_PROMISC) | 1544 | sdata->dev->flags & IFF_PROMISC) |
1533 | return RX_CONTINUE; | 1545 | return RX_CONTINUE; |
1534 | else | 1546 | else |
1535 | return RX_DROP_MONITOR; | 1547 | return RX_DROP_MONITOR; |
@@ -1539,9 +1551,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1539 | static ieee80211_rx_result debug_noinline | 1551 | static ieee80211_rx_result debug_noinline |
1540 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | 1552 | ieee80211_rx_h_data(struct ieee80211_rx_data *rx) |
1541 | { | 1553 | { |
1542 | struct net_device *dev = rx->dev; | 1554 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1555 | struct net_device *dev = sdata->dev; | ||
1543 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 1556 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; |
1544 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1545 | __le16 fc = hdr->frame_control; | 1557 | __le16 fc = hdr->frame_control; |
1546 | int err; | 1558 | int err; |
1547 | 1559 | ||
@@ -1592,11 +1604,11 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1592 | 1604 | ||
1593 | if (ieee80211_is_back_req(bar->frame_control)) { | 1605 | if (ieee80211_is_back_req(bar->frame_control)) { |
1594 | if (!rx->sta) | 1606 | if (!rx->sta) |
1595 | return RX_CONTINUE; | 1607 | return RX_DROP_MONITOR; |
1596 | tid = le16_to_cpu(bar->control) >> 12; | 1608 | tid = le16_to_cpu(bar->control) >> 12; |
1597 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] | 1609 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] |
1598 | != HT_AGG_STATE_OPERATIONAL) | 1610 | != HT_AGG_STATE_OPERATIONAL) |
1599 | return RX_CONTINUE; | 1611 | return RX_DROP_MONITOR; |
1600 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; | 1612 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1601 | 1613 | ||
1602 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; | 1614 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
@@ -1606,13 +1618,10 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) | |||
1606 | mod_timer(&tid_agg_rx->session_timer, | 1618 | mod_timer(&tid_agg_rx->session_timer, |
1607 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); | 1619 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
1608 | 1620 | ||
1609 | /* manage reordering buffer according to requested */ | 1621 | /* release stored frames up to start of BAR */ |
1610 | /* sequence number */ | 1622 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num); |
1611 | rcu_read_lock(); | 1623 | kfree_skb(skb); |
1612 | ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, | 1624 | return RX_QUEUED; |
1613 | start_seq_num, 1); | ||
1614 | rcu_read_unlock(); | ||
1615 | return RX_DROP_UNUSABLE; | ||
1616 | } | 1625 | } |
1617 | 1626 | ||
1618 | return RX_CONTINUE; | 1627 | return RX_CONTINUE; |
@@ -1661,14 +1670,14 @@ static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata, | |||
1661 | mgmt->u.action.u.sa_query.trans_id, | 1670 | mgmt->u.action.u.sa_query.trans_id, |
1662 | WLAN_SA_QUERY_TR_ID_LEN); | 1671 | WLAN_SA_QUERY_TR_ID_LEN); |
1663 | 1672 | ||
1664 | ieee80211_tx_skb(sdata, skb, 1); | 1673 | ieee80211_tx_skb(sdata, skb); |
1665 | } | 1674 | } |
1666 | 1675 | ||
1667 | static ieee80211_rx_result debug_noinline | 1676 | static ieee80211_rx_result debug_noinline |
1668 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | 1677 | ieee80211_rx_h_action(struct ieee80211_rx_data *rx) |
1669 | { | 1678 | { |
1670 | struct ieee80211_local *local = rx->local; | 1679 | struct ieee80211_local *local = rx->local; |
1671 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1680 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1672 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1681 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1673 | int len = rx->skb->len; | 1682 | int len = rx->skb->len; |
1674 | 1683 | ||
@@ -1780,7 +1789,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
1780 | static ieee80211_rx_result debug_noinline | 1789 | static ieee80211_rx_result debug_noinline |
1781 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) | 1790 | ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx) |
1782 | { | 1791 | { |
1783 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev); | 1792 | struct ieee80211_sub_if_data *sdata = rx->sdata; |
1784 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; | 1793 | struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data; |
1785 | 1794 | ||
1786 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) | 1795 | if (!(rx->flags & IEEE80211_RX_RA_MATCH)) |
@@ -1818,11 +1827,11 @@ static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, | |||
1818 | * Some hardware seem to generate incorrect Michael MIC | 1827 | * Some hardware seem to generate incorrect Michael MIC |
1819 | * reports; ignore them to avoid triggering countermeasures. | 1828 | * reports; ignore them to avoid triggering countermeasures. |
1820 | */ | 1829 | */ |
1821 | goto ignore; | 1830 | return; |
1822 | } | 1831 | } |
1823 | 1832 | ||
1824 | if (!ieee80211_has_protected(hdr->frame_control)) | 1833 | if (!ieee80211_has_protected(hdr->frame_control)) |
1825 | goto ignore; | 1834 | return; |
1826 | 1835 | ||
1827 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { | 1836 | if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) { |
1828 | /* | 1837 | /* |
@@ -1831,35 +1840,33 @@ static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr, | |||
1831 | * group keys and only the AP is sending real multicast | 1840 | * group keys and only the AP is sending real multicast |
1832 | * frames in the BSS. | 1841 | * frames in the BSS. |
1833 | */ | 1842 | */ |
1834 | goto ignore; | 1843 | return; |
1835 | } | 1844 | } |
1836 | 1845 | ||
1837 | if (!ieee80211_is_data(hdr->frame_control) && | 1846 | if (!ieee80211_is_data(hdr->frame_control) && |
1838 | !ieee80211_is_auth(hdr->frame_control)) | 1847 | !ieee80211_is_auth(hdr->frame_control)) |
1839 | goto ignore; | 1848 | return; |
1840 | 1849 | ||
1841 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL, | 1850 | mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL, |
1842 | GFP_ATOMIC); | 1851 | GFP_ATOMIC); |
1843 | ignore: | ||
1844 | dev_kfree_skb(rx->skb); | ||
1845 | rx->skb = NULL; | ||
1846 | } | 1852 | } |
1847 | 1853 | ||
1848 | /* TODO: use IEEE80211_RX_FRAGMENTED */ | 1854 | /* TODO: use IEEE80211_RX_FRAGMENTED */ |
1849 | static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | 1855 | static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx, |
1856 | struct ieee80211_rate *rate) | ||
1850 | { | 1857 | { |
1851 | struct ieee80211_sub_if_data *sdata; | 1858 | struct ieee80211_sub_if_data *sdata; |
1852 | struct ieee80211_local *local = rx->local; | 1859 | struct ieee80211_local *local = rx->local; |
1853 | struct ieee80211_rtap_hdr { | 1860 | struct ieee80211_rtap_hdr { |
1854 | struct ieee80211_radiotap_header hdr; | 1861 | struct ieee80211_radiotap_header hdr; |
1855 | u8 flags; | 1862 | u8 flags; |
1856 | u8 rate; | 1863 | u8 rate_or_pad; |
1857 | __le16 chan_freq; | 1864 | __le16 chan_freq; |
1858 | __le16 chan_flags; | 1865 | __le16 chan_flags; |
1859 | } __attribute__ ((packed)) *rthdr; | 1866 | } __attribute__ ((packed)) *rthdr; |
1860 | struct sk_buff *skb = rx->skb, *skb2; | 1867 | struct sk_buff *skb = rx->skb, *skb2; |
1861 | struct net_device *prev_dev = NULL; | 1868 | struct net_device *prev_dev = NULL; |
1862 | struct ieee80211_rx_status *status = rx->status; | 1869 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1863 | 1870 | ||
1864 | if (rx->flags & IEEE80211_RX_CMNTR_REPORTED) | 1871 | if (rx->flags & IEEE80211_RX_CMNTR_REPORTED) |
1865 | goto out_free_skb; | 1872 | goto out_free_skb; |
@@ -1873,10 +1880,13 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | |||
1873 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | 1880 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); |
1874 | rthdr->hdr.it_present = | 1881 | rthdr->hdr.it_present = |
1875 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | 1882 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
1876 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
1877 | (1 << IEEE80211_RADIOTAP_CHANNEL)); | 1883 | (1 << IEEE80211_RADIOTAP_CHANNEL)); |
1878 | 1884 | ||
1879 | rthdr->rate = rx->rate->bitrate / 5; | 1885 | if (rate) { |
1886 | rthdr->rate_or_pad = rate->bitrate / 5; | ||
1887 | rthdr->hdr.it_present |= | ||
1888 | cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE); | ||
1889 | } | ||
1880 | rthdr->chan_freq = cpu_to_le16(status->freq); | 1890 | rthdr->chan_freq = cpu_to_le16(status->freq); |
1881 | 1891 | ||
1882 | if (status->band == IEEE80211_BAND_5GHZ) | 1892 | if (status->band == IEEE80211_BAND_5GHZ) |
@@ -1929,13 +1939,13 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx) | |||
1929 | 1939 | ||
1930 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | 1940 | static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, |
1931 | struct ieee80211_rx_data *rx, | 1941 | struct ieee80211_rx_data *rx, |
1932 | struct sk_buff *skb) | 1942 | struct sk_buff *skb, |
1943 | struct ieee80211_rate *rate) | ||
1933 | { | 1944 | { |
1934 | ieee80211_rx_result res = RX_DROP_MONITOR; | 1945 | ieee80211_rx_result res = RX_DROP_MONITOR; |
1935 | 1946 | ||
1936 | rx->skb = skb; | 1947 | rx->skb = skb; |
1937 | rx->sdata = sdata; | 1948 | rx->sdata = sdata; |
1938 | rx->dev = sdata->dev; | ||
1939 | 1949 | ||
1940 | #define CALL_RXH(rxh) \ | 1950 | #define CALL_RXH(rxh) \ |
1941 | do { \ | 1951 | do { \ |
@@ -1974,7 +1984,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata, | |||
1974 | rx->sta->rx_dropped++; | 1984 | rx->sta->rx_dropped++; |
1975 | /* fall through */ | 1985 | /* fall through */ |
1976 | case RX_CONTINUE: | 1986 | case RX_CONTINUE: |
1977 | ieee80211_rx_cooked_monitor(rx); | 1987 | ieee80211_rx_cooked_monitor(rx, rate); |
1978 | break; | 1988 | break; |
1979 | case RX_DROP_UNUSABLE: | 1989 | case RX_DROP_UNUSABLE: |
1980 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); | 1990 | I802_DEBUG_INC(sdata->local->rx_handlers_drop); |
@@ -1994,12 +2004,14 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1994 | struct ieee80211_rx_data *rx, | 2004 | struct ieee80211_rx_data *rx, |
1995 | struct ieee80211_hdr *hdr) | 2005 | struct ieee80211_hdr *hdr) |
1996 | { | 2006 | { |
1997 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, sdata->vif.type); | 2007 | struct sk_buff *skb = rx->skb; |
2008 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
2009 | u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); | ||
1998 | int multicast = is_multicast_ether_addr(hdr->addr1); | 2010 | int multicast = is_multicast_ether_addr(hdr->addr1); |
1999 | 2011 | ||
2000 | switch (sdata->vif.type) { | 2012 | switch (sdata->vif.type) { |
2001 | case NL80211_IFTYPE_STATION: | 2013 | case NL80211_IFTYPE_STATION: |
2002 | if (!bssid && !sdata->use_4addr) | 2014 | if (!bssid && !sdata->u.mgd.use_4addr) |
2003 | return 0; | 2015 | return 0; |
2004 | if (!multicast && | 2016 | if (!multicast && |
2005 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { | 2017 | compare_ether_addr(sdata->dev->dev_addr, hdr->addr1) != 0) { |
@@ -2026,10 +2038,10 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2026 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 2038 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
2027 | } else if (!rx->sta) { | 2039 | } else if (!rx->sta) { |
2028 | int rate_idx; | 2040 | int rate_idx; |
2029 | if (rx->status->flag & RX_FLAG_HT) | 2041 | if (status->flag & RX_FLAG_HT) |
2030 | rate_idx = 0; /* TODO: HT rates */ | 2042 | rate_idx = 0; /* TODO: HT rates */ |
2031 | else | 2043 | else |
2032 | rate_idx = rx->status->rate_idx; | 2044 | rate_idx = status->rate_idx; |
2033 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, | 2045 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, |
2034 | BIT(rate_idx)); | 2046 | BIT(rate_idx)); |
2035 | } | 2047 | } |
@@ -2064,8 +2076,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
2064 | return 0; | 2076 | return 0; |
2065 | break; | 2077 | break; |
2066 | case NL80211_IFTYPE_MONITOR: | 2078 | case NL80211_IFTYPE_MONITOR: |
2067 | /* take everything */ | ||
2068 | break; | ||
2069 | case NL80211_IFTYPE_UNSPECIFIED: | 2079 | case NL80211_IFTYPE_UNSPECIFIED: |
2070 | case __NL80211_IFTYPE_AFTER_LAST: | 2080 | case __NL80211_IFTYPE_AFTER_LAST: |
2071 | /* should never get here */ | 2081 | /* should never get here */ |
@@ -2098,23 +2108,9 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2098 | rx.skb = skb; | 2108 | rx.skb = skb; |
2099 | rx.local = local; | 2109 | rx.local = local; |
2100 | 2110 | ||
2101 | rx.status = status; | ||
2102 | rx.rate = rate; | ||
2103 | |||
2104 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) | 2111 | if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control)) |
2105 | local->dot11ReceivedFragmentCount++; | 2112 | local->dot11ReceivedFragmentCount++; |
2106 | 2113 | ||
2107 | rx.sta = sta_info_get(local, hdr->addr2); | ||
2108 | if (rx.sta) { | ||
2109 | rx.sdata = rx.sta->sdata; | ||
2110 | rx.dev = rx.sta->sdata->dev; | ||
2111 | } | ||
2112 | |||
2113 | if ((status->flag & RX_FLAG_MMIC_ERROR)) { | ||
2114 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2115 | return; | ||
2116 | } | ||
2117 | |||
2118 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | 2114 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
2119 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | 2115 | test_bit(SCAN_OFF_CHANNEL, &local->scanning))) |
2120 | rx.flags |= IEEE80211_RX_IN_SCAN; | 2116 | rx.flags |= IEEE80211_RX_IN_SCAN; |
@@ -2122,13 +2118,20 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2122 | ieee80211_parse_qos(&rx); | 2118 | ieee80211_parse_qos(&rx); |
2123 | ieee80211_verify_alignment(&rx); | 2119 | ieee80211_verify_alignment(&rx); |
2124 | 2120 | ||
2125 | skb = rx.skb; | 2121 | rx.sta = sta_info_get(local, hdr->addr2); |
2122 | if (rx.sta) | ||
2123 | rx.sdata = rx.sta->sdata; | ||
2126 | 2124 | ||
2127 | if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { | 2125 | if (rx.sdata && ieee80211_is_data(hdr->frame_control)) { |
2128 | rx.flags |= IEEE80211_RX_RA_MATCH; | 2126 | rx.flags |= IEEE80211_RX_RA_MATCH; |
2129 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); | 2127 | prepares = prepare_for_handlers(rx.sdata, &rx, hdr); |
2130 | if (prepares) | 2128 | if (prepares) { |
2131 | prev = rx.sdata; | 2129 | if (status->flag & RX_FLAG_MMIC_ERROR) { |
2130 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2131 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2132 | } else | ||
2133 | prev = rx.sdata; | ||
2134 | } | ||
2132 | } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 2135 | } else list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
2133 | if (!netif_running(sdata->dev)) | 2136 | if (!netif_running(sdata->dev)) |
2134 | continue; | 2137 | continue; |
@@ -2143,6 +2146,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2143 | if (!prepares) | 2146 | if (!prepares) |
2144 | continue; | 2147 | continue; |
2145 | 2148 | ||
2149 | if (status->flag & RX_FLAG_MMIC_ERROR) { | ||
2150 | rx.sdata = sdata; | ||
2151 | if (rx.flags & IEEE80211_RX_RA_MATCH) | ||
2152 | ieee80211_rx_michael_mic_report(hdr, &rx); | ||
2153 | continue; | ||
2154 | } | ||
2155 | |||
2146 | /* | 2156 | /* |
2147 | * frame is destined for this interface, but if it's not | 2157 | * frame is destined for this interface, but if it's not |
2148 | * also for the previous one we handle that after the | 2158 | * also for the previous one we handle that after the |
@@ -2168,11 +2178,11 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2168 | prev->dev->name); | 2178 | prev->dev->name); |
2169 | continue; | 2179 | continue; |
2170 | } | 2180 | } |
2171 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new); | 2181 | ieee80211_invoke_rx_handlers(prev, &rx, skb_new, rate); |
2172 | prev = sdata; | 2182 | prev = sdata; |
2173 | } | 2183 | } |
2174 | if (prev) | 2184 | if (prev) |
2175 | ieee80211_invoke_rx_handlers(prev, &rx, skb); | 2185 | ieee80211_invoke_rx_handlers(prev, &rx, skb, rate); |
2176 | else | 2186 | else |
2177 | dev_kfree_skb(skb); | 2187 | dev_kfree_skb(skb); |
2178 | } | 2188 | } |
@@ -2201,7 +2211,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
2201 | int index) | 2211 | int index) |
2202 | { | 2212 | { |
2203 | struct ieee80211_supported_band *sband; | 2213 | struct ieee80211_supported_band *sband; |
2204 | struct ieee80211_rate *rate; | 2214 | struct ieee80211_rate *rate = NULL; |
2205 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 2215 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
2206 | struct ieee80211_rx_status *status; | 2216 | struct ieee80211_rx_status *status; |
2207 | 2217 | ||
@@ -2212,9 +2222,7 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
2212 | 2222 | ||
2213 | /* release the reordered frames to stack */ | 2223 | /* release the reordered frames to stack */ |
2214 | sband = hw->wiphy->bands[status->band]; | 2224 | sband = hw->wiphy->bands[status->band]; |
2215 | if (status->flag & RX_FLAG_HT) | 2225 | if (!(status->flag & RX_FLAG_HT)) |
2216 | rate = sband->bitrates; /* TODO: HT rates */ | ||
2217 | else | ||
2218 | rate = &sband->bitrates[status->rate_idx]; | 2226 | rate = &sband->bitrates[status->rate_idx]; |
2219 | __ieee80211_rx_handle_packet(hw, skb, rate); | 2227 | __ieee80211_rx_handle_packet(hw, skb, rate); |
2220 | tid_agg_rx->stored_mpdu_num--; | 2228 | tid_agg_rx->stored_mpdu_num--; |
@@ -2224,6 +2232,18 @@ no_frame: | |||
2224 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | 2232 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
2225 | } | 2233 | } |
2226 | 2234 | ||
2235 | static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | ||
2236 | struct tid_ampdu_rx *tid_agg_rx, | ||
2237 | u16 head_seq_num) | ||
2238 | { | ||
2239 | int index; | ||
2240 | |||
2241 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | ||
2242 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | ||
2243 | tid_agg_rx->buf_size; | ||
2244 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); | ||
2245 | } | ||
2246 | } | ||
2227 | 2247 | ||
2228 | /* | 2248 | /* |
2229 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If | 2249 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If |
@@ -2235,15 +2255,17 @@ no_frame: | |||
2235 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | 2255 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) |
2236 | 2256 | ||
2237 | /* | 2257 | /* |
2238 | * As it function blongs to Rx path it must be called with | 2258 | * As this function belongs to the RX path it must be under |
2239 | * the proper rcu_read_lock protection for its flow. | 2259 | * rcu_read_lock protection. It returns false if the frame |
2260 | * can be processed immediately, true if it was consumed. | ||
2240 | */ | 2261 | */ |
2241 | static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | 2262 | static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, |
2242 | struct tid_ampdu_rx *tid_agg_rx, | 2263 | struct tid_ampdu_rx *tid_agg_rx, |
2243 | struct sk_buff *skb, | 2264 | struct sk_buff *skb) |
2244 | u16 mpdu_seq_num, | ||
2245 | int bar_req) | ||
2246 | { | 2265 | { |
2266 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2267 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | ||
2268 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | ||
2247 | u16 head_seq_num, buf_size; | 2269 | u16 head_seq_num, buf_size; |
2248 | int index; | 2270 | int index; |
2249 | 2271 | ||
@@ -2253,47 +2275,37 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2253 | /* frame with out of date sequence number */ | 2275 | /* frame with out of date sequence number */ |
2254 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 2276 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
2255 | dev_kfree_skb(skb); | 2277 | dev_kfree_skb(skb); |
2256 | return 1; | 2278 | return true; |
2257 | } | 2279 | } |
2258 | 2280 | ||
2259 | /* if frame sequence number exceeds our buffering window size or | 2281 | /* |
2260 | * block Ack Request arrived - release stored frames */ | 2282 | * If frame the sequence number exceeds our buffering window |
2261 | if ((!seq_less(mpdu_seq_num, head_seq_num + buf_size)) || (bar_req)) { | 2283 | * size release some previous frames to make room for this one. |
2262 | /* new head to the ordering buffer */ | 2284 | */ |
2263 | if (bar_req) | 2285 | if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { |
2264 | head_seq_num = mpdu_seq_num; | 2286 | head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); |
2265 | else | ||
2266 | head_seq_num = | ||
2267 | seq_inc(seq_sub(mpdu_seq_num, buf_size)); | ||
2268 | /* release stored frames up to new head to stack */ | 2287 | /* release stored frames up to new head to stack */ |
2269 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 2288 | ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num); |
2270 | index = seq_sub(tid_agg_rx->head_seq_num, | ||
2271 | tid_agg_rx->ssn) | ||
2272 | % tid_agg_rx->buf_size; | ||
2273 | ieee80211_release_reorder_frame(hw, tid_agg_rx, | ||
2274 | index); | ||
2275 | } | ||
2276 | if (bar_req) | ||
2277 | return 1; | ||
2278 | } | 2289 | } |
2279 | 2290 | ||
2280 | /* now the new frame is always in the range of the reordering */ | 2291 | /* Now the new frame is always in the range of the reordering buffer */ |
2281 | /* buffer window */ | 2292 | |
2282 | index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) | 2293 | index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; |
2283 | % tid_agg_rx->buf_size; | 2294 | |
2284 | /* check if we already stored this frame */ | 2295 | /* check if we already stored this frame */ |
2285 | if (tid_agg_rx->reorder_buf[index]) { | 2296 | if (tid_agg_rx->reorder_buf[index]) { |
2286 | dev_kfree_skb(skb); | 2297 | dev_kfree_skb(skb); |
2287 | return 1; | 2298 | return true; |
2288 | } | 2299 | } |
2289 | 2300 | ||
2290 | /* if arrived mpdu is in the right order and nothing else stored */ | 2301 | /* |
2291 | /* release it immediately */ | 2302 | * If the current MPDU is in the right order and nothing else |
2303 | * is stored we can process it directly, no need to buffer it. | ||
2304 | */ | ||
2292 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 2305 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
2293 | tid_agg_rx->stored_mpdu_num == 0) { | 2306 | tid_agg_rx->stored_mpdu_num == 0) { |
2294 | tid_agg_rx->head_seq_num = | 2307 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
2295 | seq_inc(tid_agg_rx->head_seq_num); | 2308 | return false; |
2296 | return 0; | ||
2297 | } | 2309 | } |
2298 | 2310 | ||
2299 | /* put the frame in the reordering buffer */ | 2311 | /* put the frame in the reordering buffer */ |
@@ -2301,8 +2313,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2301 | tid_agg_rx->reorder_time[index] = jiffies; | 2313 | tid_agg_rx->reorder_time[index] = jiffies; |
2302 | tid_agg_rx->stored_mpdu_num++; | 2314 | tid_agg_rx->stored_mpdu_num++; |
2303 | /* release the buffer until next missing frame */ | 2315 | /* release the buffer until next missing frame */ |
2304 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2316 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
2305 | % tid_agg_rx->buf_size; | 2317 | tid_agg_rx->buf_size; |
2306 | if (!tid_agg_rx->reorder_buf[index] && | 2318 | if (!tid_agg_rx->reorder_buf[index] && |
2307 | tid_agg_rx->stored_mpdu_num > 1) { | 2319 | tid_agg_rx->stored_mpdu_num > 1) { |
2308 | /* | 2320 | /* |
@@ -2313,12 +2325,12 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2313 | int skipped = 1; | 2325 | int skipped = 1; |
2314 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | 2326 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
2315 | j = (j + 1) % tid_agg_rx->buf_size) { | 2327 | j = (j + 1) % tid_agg_rx->buf_size) { |
2316 | if (tid_agg_rx->reorder_buf[j] == NULL) { | 2328 | if (!tid_agg_rx->reorder_buf[j]) { |
2317 | skipped++; | 2329 | skipped++; |
2318 | continue; | 2330 | continue; |
2319 | } | 2331 | } |
2320 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | 2332 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + |
2321 | HZ / 10)) | 2333 | HT_RX_REORDER_BUF_TIMEOUT)) |
2322 | break; | 2334 | break; |
2323 | 2335 | ||
2324 | #ifdef CONFIG_MAC80211_HT_DEBUG | 2336 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -2334,51 +2346,56 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2334 | * Increment the head seq# also for the skipped slots. | 2346 | * Increment the head seq# also for the skipped slots. |
2335 | */ | 2347 | */ |
2336 | tid_agg_rx->head_seq_num = | 2348 | tid_agg_rx->head_seq_num = |
2337 | (tid_agg_rx->head_seq_num + skipped) & | 2349 | (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; |
2338 | SEQ_MASK; | ||
2339 | skipped = 0; | 2350 | skipped = 0; |
2340 | } | 2351 | } |
2341 | } else while (tid_agg_rx->reorder_buf[index]) { | 2352 | } else while (tid_agg_rx->reorder_buf[index]) { |
2342 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); | 2353 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
2343 | index = seq_sub(tid_agg_rx->head_seq_num, | 2354 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
2344 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 2355 | tid_agg_rx->buf_size; |
2345 | } | 2356 | } |
2346 | return 1; | 2357 | |
2358 | return true; | ||
2347 | } | 2359 | } |
2348 | 2360 | ||
2349 | static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | 2361 | /* |
2350 | struct sk_buff *skb) | 2362 | * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns |
2363 | * true if the MPDU was buffered, false if it should be processed. | ||
2364 | */ | ||
2365 | static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | ||
2366 | struct sk_buff *skb) | ||
2351 | { | 2367 | { |
2352 | struct ieee80211_hw *hw = &local->hw; | 2368 | struct ieee80211_hw *hw = &local->hw; |
2353 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 2369 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
2354 | struct sta_info *sta; | 2370 | struct sta_info *sta; |
2355 | struct tid_ampdu_rx *tid_agg_rx; | 2371 | struct tid_ampdu_rx *tid_agg_rx; |
2356 | u16 sc; | 2372 | u16 sc; |
2357 | u16 mpdu_seq_num; | ||
2358 | u8 ret = 0; | ||
2359 | int tid; | 2373 | int tid; |
2360 | 2374 | ||
2375 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
2376 | return false; | ||
2377 | |||
2378 | /* | ||
2379 | * filter the QoS data rx stream according to | ||
2380 | * STA/TID and check if this STA/TID is on aggregation | ||
2381 | */ | ||
2382 | |||
2361 | sta = sta_info_get(local, hdr->addr2); | 2383 | sta = sta_info_get(local, hdr->addr2); |
2362 | if (!sta) | 2384 | if (!sta) |
2363 | return ret; | 2385 | return false; |
2364 | |||
2365 | /* filter the QoS data rx stream according to | ||
2366 | * STA/TID and check if this STA/TID is on aggregation */ | ||
2367 | if (!ieee80211_is_data_qos(hdr->frame_control)) | ||
2368 | goto end_reorder; | ||
2369 | 2386 | ||
2370 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; | 2387 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
2371 | 2388 | ||
2372 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) | 2389 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2373 | goto end_reorder; | 2390 | return false; |
2374 | 2391 | ||
2375 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; | 2392 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
2376 | 2393 | ||
2377 | /* qos null data frames are excluded */ | 2394 | /* qos null data frames are excluded */ |
2378 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) | 2395 | if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) |
2379 | goto end_reorder; | 2396 | return false; |
2380 | 2397 | ||
2381 | /* new un-ordered ampdu frame - process it */ | 2398 | /* new, potentially un-ordered, ampdu frame - process it */ |
2382 | 2399 | ||
2383 | /* reset session timer */ | 2400 | /* reset session timer */ |
2384 | if (tid_agg_rx->timeout) | 2401 | if (tid_agg_rx->timeout) |
@@ -2390,16 +2407,11 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |||
2390 | if (sc & IEEE80211_SCTL_FRAG) { | 2407 | if (sc & IEEE80211_SCTL_FRAG) { |
2391 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, | 2408 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, |
2392 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); | 2409 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); |
2393 | ret = 1; | 2410 | dev_kfree_skb(skb); |
2394 | goto end_reorder; | 2411 | return true; |
2395 | } | 2412 | } |
2396 | 2413 | ||
2397 | /* according to mpdu sequence number deal with reordering buffer */ | 2414 | return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb); |
2398 | mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | ||
2399 | ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, | ||
2400 | mpdu_seq_num, 0); | ||
2401 | end_reorder: | ||
2402 | return ret; | ||
2403 | } | 2415 | } |
2404 | 2416 | ||
2405 | /* | 2417 | /* |
@@ -2457,10 +2469,6 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2457 | status->rate_idx, | 2469 | status->rate_idx, |
2458 | status->rate_idx)) | 2470 | status->rate_idx)) |
2459 | goto drop; | 2471 | goto drop; |
2460 | /* HT rates are not in the table - use the highest legacy rate | ||
2461 | * for now since other parts of mac80211 may not yet be fully | ||
2462 | * MCS aware. */ | ||
2463 | rate = &sband->bitrates[sband->n_bitrates - 1]; | ||
2464 | } else { | 2472 | } else { |
2465 | if (WARN_ON(status->rate_idx < 0 || | 2473 | if (WARN_ON(status->rate_idx < 0 || |
2466 | status->rate_idx >= sband->n_bitrates)) | 2474 | status->rate_idx >= sband->n_bitrates)) |
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c index 68953033403d..aa743a895cf9 100644 --- a/net/mac80211/spectmgmt.c +++ b/net/mac80211/spectmgmt.c | |||
@@ -65,7 +65,7 @@ static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_da | |||
65 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; | 65 | IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; |
66 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; | 66 | msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; |
67 | 67 | ||
68 | ieee80211_tx_skb(sdata, skb, 1); | 68 | ieee80211_tx_skb(sdata, skb); |
69 | } | 69 | } |
70 | 70 | ||
71 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, | 71 | void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 396a94806de9..71f370dd24bc 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -116,14 +116,15 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr) | |||
116 | return sta; | 116 | return sta; |
117 | } | 117 | } |
118 | 118 | ||
119 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 119 | struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, |
120 | struct net_device *dev) | 120 | int idx) |
121 | { | 121 | { |
122 | struct ieee80211_local *local = sdata->local; | ||
122 | struct sta_info *sta; | 123 | struct sta_info *sta; |
123 | int i = 0; | 124 | int i = 0; |
124 | 125 | ||
125 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 126 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
126 | if (dev && dev != sta->sdata->dev) | 127 | if (sdata != sta->sdata) |
127 | continue; | 128 | continue; |
128 | if (i < idx) { | 129 | if (i < idx) { |
129 | ++i; | 130 | ++i; |
@@ -147,8 +148,10 @@ struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | |||
147 | static void __sta_info_free(struct ieee80211_local *local, | 148 | static void __sta_info_free(struct ieee80211_local *local, |
148 | struct sta_info *sta) | 149 | struct sta_info *sta) |
149 | { | 150 | { |
150 | rate_control_free_sta(sta); | 151 | if (sta->rate_ctrl) { |
151 | rate_control_put(sta->rate_ctrl); | 152 | rate_control_free_sta(sta); |
153 | rate_control_put(sta->rate_ctrl); | ||
154 | } | ||
152 | 155 | ||
153 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 156 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
154 | printk(KERN_DEBUG "%s: Destroyed STA %pM\n", | 157 | printk(KERN_DEBUG "%s: Destroyed STA %pM\n", |
@@ -276,6 +279,23 @@ static void sta_unblock(struct work_struct *wk) | |||
276 | ieee80211_sta_ps_deliver_poll_response(sta); | 279 | ieee80211_sta_ps_deliver_poll_response(sta); |
277 | } | 280 | } |
278 | 281 | ||
282 | static int sta_prepare_rate_control(struct ieee80211_local *local, | ||
283 | struct sta_info *sta, gfp_t gfp) | ||
284 | { | ||
285 | if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) | ||
286 | return 0; | ||
287 | |||
288 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | ||
289 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | ||
290 | &sta->sta, gfp); | ||
291 | if (!sta->rate_ctrl_priv) { | ||
292 | rate_control_put(sta->rate_ctrl); | ||
293 | return -ENOMEM; | ||
294 | } | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
279 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | 299 | struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, |
280 | u8 *addr, gfp_t gfp) | 300 | u8 *addr, gfp_t gfp) |
281 | { | 301 | { |
@@ -295,11 +315,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
295 | sta->local = local; | 315 | sta->local = local; |
296 | sta->sdata = sdata; | 316 | sta->sdata = sdata; |
297 | 317 | ||
298 | sta->rate_ctrl = rate_control_get(local->rate_ctrl); | 318 | if (sta_prepare_rate_control(local, sta, gfp)) { |
299 | sta->rate_ctrl_priv = rate_control_alloc_sta(sta->rate_ctrl, | ||
300 | &sta->sta, gfp); | ||
301 | if (!sta->rate_ctrl_priv) { | ||
302 | rate_control_put(sta->rate_ctrl); | ||
303 | kfree(sta); | 319 | kfree(sta); |
304 | return NULL; | 320 | return NULL; |
305 | } | 321 | } |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4673454176ed..b4810f6aa94f 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -185,6 +185,7 @@ struct sta_ampdu_mlme { | |||
185 | * @lock: used for locking all fields that require locking, see comments | 185 | * @lock: used for locking all fields that require locking, see comments |
186 | * in the header file. | 186 | * in the header file. |
187 | * @flaglock: spinlock for flags accesses | 187 | * @flaglock: spinlock for flags accesses |
188 | * @drv_unblock_wk: used for driver PS unblocking | ||
188 | * @listen_interval: listen interval of this station, when we're acting as AP | 189 | * @listen_interval: listen interval of this station, when we're acting as AP |
189 | * @pin_status: used internally for pinning a STA struct into memory | 190 | * @pin_status: used internally for pinning a STA struct into memory |
190 | * @flags: STA flags, see &enum ieee80211_sta_info_flags | 191 | * @flags: STA flags, see &enum ieee80211_sta_info_flags |
@@ -225,7 +226,6 @@ struct sta_ampdu_mlme { | |||
225 | * @debugfs: debug filesystem info | 226 | * @debugfs: debug filesystem info |
226 | * @sta: station information we share with the driver | 227 | * @sta: station information we share with the driver |
227 | * @dead: set to true when sta is unlinked | 228 | * @dead: set to true when sta is unlinked |
228 | * @drv_unblock_wk used for driver PS unblocking | ||
229 | */ | 229 | */ |
230 | struct sta_info { | 230 | struct sta_info { |
231 | /* General information, mostly static */ | 231 | /* General information, mostly static */ |
@@ -409,8 +409,8 @@ struct sta_info *sta_info_get(struct ieee80211_local *local, const u8 *addr); | |||
409 | /* | 409 | /* |
410 | * Get STA info by index, BROKEN! | 410 | * Get STA info by index, BROKEN! |
411 | */ | 411 | */ |
412 | struct sta_info *sta_info_get_by_idx(struct ieee80211_local *local, int idx, | 412 | struct sta_info *sta_info_get_by_idx(struct ieee80211_sub_if_data *sdata, |
413 | struct net_device *dev); | 413 | int idx); |
414 | /* | 414 | /* |
415 | * Create a new STA info, caller owns returned structure | 415 | * Create a new STA info, caller owns returned structure |
416 | * until sta_info_insert(). | 416 | * until sta_info_insert(). |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c new file mode 100644 index 000000000000..9f91fd8e6efb --- /dev/null +++ b/net/mac80211/status.c | |||
@@ -0,0 +1,337 @@ | |||
1 | /* | ||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
3 | * Copyright 2005-2006, Devicescape Software, Inc. | ||
4 | * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> | ||
5 | * Copyright 2008-2009 Johannes Berg <johannes@sipsolutions.net> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <net/mac80211.h> | ||
13 | #include "ieee80211_i.h" | ||
14 | #include "rate.h" | ||
15 | #include "mesh.h" | ||
16 | #include "led.h" | ||
17 | |||
18 | |||
19 | void ieee80211_tx_status_irqsafe(struct ieee80211_hw *hw, | ||
20 | struct sk_buff *skb) | ||
21 | { | ||
22 | struct ieee80211_local *local = hw_to_local(hw); | ||
23 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
24 | int tmp; | ||
25 | |||
26 | skb->pkt_type = IEEE80211_TX_STATUS_MSG; | ||
27 | skb_queue_tail(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS ? | ||
28 | &local->skb_queue : &local->skb_queue_unreliable, skb); | ||
29 | tmp = skb_queue_len(&local->skb_queue) + | ||
30 | skb_queue_len(&local->skb_queue_unreliable); | ||
31 | while (tmp > IEEE80211_IRQSAFE_QUEUE_LIMIT && | ||
32 | (skb = skb_dequeue(&local->skb_queue_unreliable))) { | ||
33 | dev_kfree_skb_irq(skb); | ||
34 | tmp--; | ||
35 | I802_DEBUG_INC(local->tx_status_drop); | ||
36 | } | ||
37 | tasklet_schedule(&local->tasklet); | ||
38 | } | ||
39 | EXPORT_SYMBOL(ieee80211_tx_status_irqsafe); | ||
40 | |||
41 | static void ieee80211_handle_filtered_frame(struct ieee80211_local *local, | ||
42 | struct sta_info *sta, | ||
43 | struct sk_buff *skb) | ||
44 | { | ||
45 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
46 | |||
47 | /* | ||
48 | * XXX: This is temporary! | ||
49 | * | ||
50 | * The problem here is that when we get here, the driver will | ||
51 | * quite likely have pretty much overwritten info->control by | ||
52 | * using info->driver_data or info->rate_driver_data. Thus, | ||
53 | * when passing out the frame to the driver again, we would be | ||
54 | * passing completely bogus data since the driver would then | ||
55 | * expect a properly filled info->control. In mac80211 itself | ||
56 | * the same problem occurs, since we need info->control.vif | ||
57 | * internally. | ||
58 | * | ||
59 | * To fix this, we should send the frame through TX processing | ||
60 | * again. However, it's not that simple, since the frame will | ||
61 | * have been software-encrypted (if applicable) already, and | ||
62 | * encrypting it again doesn't do much good. So to properly do | ||
63 | * that, we not only have to skip the actual 'raw' encryption | ||
64 | * (key selection etc. still has to be done!) but also the | ||
65 | * sequence number assignment since that impacts the crypto | ||
66 | * encapsulation, of course. | ||
67 | * | ||
68 | * Hence, for now, fix the bug by just dropping the frame. | ||
69 | */ | ||
70 | goto drop; | ||
71 | |||
72 | sta->tx_filtered_count++; | ||
73 | |||
74 | /* | ||
75 | * Clear the TX filter mask for this STA when sending the next | ||
76 | * packet. If the STA went to power save mode, this will happen | ||
77 | * when it wakes up for the next time. | ||
78 | */ | ||
79 | set_sta_flags(sta, WLAN_STA_CLEAR_PS_FILT); | ||
80 | |||
81 | /* | ||
82 | * This code races in the following way: | ||
83 | * | ||
84 | * (1) STA sends frame indicating it will go to sleep and does so | ||
85 | * (2) hardware/firmware adds STA to filter list, passes frame up | ||
86 | * (3) hardware/firmware processes TX fifo and suppresses a frame | ||
87 | * (4) we get TX status before having processed the frame and | ||
88 | * knowing that the STA has gone to sleep. | ||
89 | * | ||
90 | * This is actually quite unlikely even when both those events are | ||
91 | * processed from interrupts coming in quickly after one another or | ||
92 | * even at the same time because we queue both TX status events and | ||
93 | * RX frames to be processed by a tasklet and process them in the | ||
94 | * same order that they were received or TX status last. Hence, there | ||
95 | * is no race as long as the frame RX is processed before the next TX | ||
96 | * status, which drivers can ensure, see below. | ||
97 | * | ||
98 | * Note that this can only happen if the hardware or firmware can | ||
99 | * actually add STAs to the filter list, if this is done by the | ||
100 | * driver in response to set_tim() (which will only reduce the race | ||
101 | * this whole filtering tries to solve, not completely solve it) | ||
102 | * this situation cannot happen. | ||
103 | * | ||
104 | * To completely solve this race drivers need to make sure that they | ||
105 | * (a) don't mix the irq-safe/not irq-safe TX status/RX processing | ||
106 | * functions and | ||
107 | * (b) always process RX events before TX status events if ordering | ||
108 | * can be unknown, for example with different interrupt status | ||
109 | * bits. | ||
110 | */ | ||
111 | if (test_sta_flags(sta, WLAN_STA_PS_STA) && | ||
112 | skb_queue_len(&sta->tx_filtered) < STA_MAX_TX_BUFFER) { | ||
113 | skb_queue_tail(&sta->tx_filtered, skb); | ||
114 | return; | ||
115 | } | ||
116 | |||
117 | if (!test_sta_flags(sta, WLAN_STA_PS_STA) && | ||
118 | !(info->flags & IEEE80211_TX_INTFL_RETRIED)) { | ||
119 | /* Software retry the packet once */ | ||
120 | info->flags |= IEEE80211_TX_INTFL_RETRIED; | ||
121 | ieee80211_add_pending_skb(local, skb); | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | drop: | ||
126 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | ||
127 | if (net_ratelimit()) | ||
128 | printk(KERN_DEBUG "%s: dropped TX filtered frame, " | ||
129 | "queue_len=%d PS=%d @%lu\n", | ||
130 | wiphy_name(local->hw.wiphy), | ||
131 | skb_queue_len(&sta->tx_filtered), | ||
132 | !!test_sta_flags(sta, WLAN_STA_PS_STA), jiffies); | ||
133 | #endif | ||
134 | dev_kfree_skb(skb); | ||
135 | } | ||
136 | |||
137 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
138 | { | ||
139 | struct sk_buff *skb2; | ||
140 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
141 | struct ieee80211_local *local = hw_to_local(hw); | ||
142 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
143 | u16 frag, type; | ||
144 | __le16 fc; | ||
145 | struct ieee80211_supported_band *sband; | ||
146 | struct ieee80211_tx_status_rtap_hdr *rthdr; | ||
147 | struct ieee80211_sub_if_data *sdata; | ||
148 | struct net_device *prev_dev = NULL; | ||
149 | struct sta_info *sta; | ||
150 | int retry_count = -1, i; | ||
151 | |||
152 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | ||
153 | /* the HW cannot have attempted that rate */ | ||
154 | if (i >= hw->max_rates) { | ||
155 | info->status.rates[i].idx = -1; | ||
156 | info->status.rates[i].count = 0; | ||
157 | } | ||
158 | |||
159 | retry_count += info->status.rates[i].count; | ||
160 | } | ||
161 | if (retry_count < 0) | ||
162 | retry_count = 0; | ||
163 | |||
164 | rcu_read_lock(); | ||
165 | |||
166 | sband = local->hw.wiphy->bands[info->band]; | ||
167 | |||
168 | sta = sta_info_get(local, hdr->addr1); | ||
169 | |||
170 | if (sta) { | ||
171 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
172 | test_sta_flags(sta, WLAN_STA_PS_STA)) { | ||
173 | /* | ||
174 | * The STA is in power save mode, so assume | ||
175 | * that this TX packet failed because of that. | ||
176 | */ | ||
177 | ieee80211_handle_filtered_frame(local, sta, skb); | ||
178 | rcu_read_unlock(); | ||
179 | return; | ||
180 | } | ||
181 | |||
182 | fc = hdr->frame_control; | ||
183 | |||
184 | if ((info->flags & IEEE80211_TX_STAT_AMPDU_NO_BACK) && | ||
185 | (ieee80211_is_data_qos(fc))) { | ||
186 | u16 tid, ssn; | ||
187 | u8 *qc; | ||
188 | |||
189 | qc = ieee80211_get_qos_ctl(hdr); | ||
190 | tid = qc[0] & 0xf; | ||
191 | ssn = ((le16_to_cpu(hdr->seq_ctrl) + 0x10) | ||
192 | & IEEE80211_SCTL_SEQ); | ||
193 | ieee80211_send_bar(sta->sdata, hdr->addr1, | ||
194 | tid, ssn); | ||
195 | } | ||
196 | |||
197 | if (info->flags & IEEE80211_TX_STAT_TX_FILTERED) { | ||
198 | ieee80211_handle_filtered_frame(local, sta, skb); | ||
199 | rcu_read_unlock(); | ||
200 | return; | ||
201 | } else { | ||
202 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) | ||
203 | sta->tx_retry_failed++; | ||
204 | sta->tx_retry_count += retry_count; | ||
205 | } | ||
206 | |||
207 | rate_control_tx_status(local, sband, sta, skb); | ||
208 | if (ieee80211_vif_is_mesh(&sta->sdata->vif)) | ||
209 | ieee80211s_update_metric(local, sta, skb); | ||
210 | } | ||
211 | |||
212 | rcu_read_unlock(); | ||
213 | |||
214 | ieee80211_led_tx(local, 0); | ||
215 | |||
216 | /* SNMP counters | ||
217 | * Fragments are passed to low-level drivers as separate skbs, so these | ||
218 | * are actually fragments, not frames. Update frame counters only for | ||
219 | * the first fragment of the frame. */ | ||
220 | |||
221 | frag = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG; | ||
222 | type = le16_to_cpu(hdr->frame_control) & IEEE80211_FCTL_FTYPE; | ||
223 | |||
224 | if (info->flags & IEEE80211_TX_STAT_ACK) { | ||
225 | if (frag == 0) { | ||
226 | local->dot11TransmittedFrameCount++; | ||
227 | if (is_multicast_ether_addr(hdr->addr1)) | ||
228 | local->dot11MulticastTransmittedFrameCount++; | ||
229 | if (retry_count > 0) | ||
230 | local->dot11RetryCount++; | ||
231 | if (retry_count > 1) | ||
232 | local->dot11MultipleRetryCount++; | ||
233 | } | ||
234 | |||
235 | /* This counter shall be incremented for an acknowledged MPDU | ||
236 | * with an individual address in the address 1 field or an MPDU | ||
237 | * with a multicast address in the address 1 field of type Data | ||
238 | * or Management. */ | ||
239 | if (!is_multicast_ether_addr(hdr->addr1) || | ||
240 | type == IEEE80211_FTYPE_DATA || | ||
241 | type == IEEE80211_FTYPE_MGMT) | ||
242 | local->dot11TransmittedFragmentCount++; | ||
243 | } else { | ||
244 | if (frag == 0) | ||
245 | local->dot11FailedCount++; | ||
246 | } | ||
247 | |||
248 | /* this was a transmitted frame, but now we want to reuse it */ | ||
249 | skb_orphan(skb); | ||
250 | |||
251 | /* | ||
252 | * This is a bit racy but we can avoid a lot of work | ||
253 | * with this test... | ||
254 | */ | ||
255 | if (!local->monitors && !local->cooked_mntrs) { | ||
256 | dev_kfree_skb(skb); | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | /* send frame to monitor interfaces now */ | ||
261 | |||
262 | if (skb_headroom(skb) < sizeof(*rthdr)) { | ||
263 | printk(KERN_ERR "ieee80211_tx_status: headroom too small\n"); | ||
264 | dev_kfree_skb(skb); | ||
265 | return; | ||
266 | } | ||
267 | |||
268 | rthdr = (struct ieee80211_tx_status_rtap_hdr *) | ||
269 | skb_push(skb, sizeof(*rthdr)); | ||
270 | |||
271 | memset(rthdr, 0, sizeof(*rthdr)); | ||
272 | rthdr->hdr.it_len = cpu_to_le16(sizeof(*rthdr)); | ||
273 | rthdr->hdr.it_present = | ||
274 | cpu_to_le32((1 << IEEE80211_RADIOTAP_TX_FLAGS) | | ||
275 | (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | | ||
276 | (1 << IEEE80211_RADIOTAP_RATE)); | ||
277 | |||
278 | if (!(info->flags & IEEE80211_TX_STAT_ACK) && | ||
279 | !is_multicast_ether_addr(hdr->addr1)) | ||
280 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_FAIL); | ||
281 | |||
282 | /* | ||
283 | * XXX: Once radiotap gets the bitmap reset thing the vendor | ||
284 | * extensions proposal contains, we can actually report | ||
285 | * the whole set of tries we did. | ||
286 | */ | ||
287 | if ((info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || | ||
288 | (info->status.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) | ||
289 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_CTS); | ||
290 | else if (info->status.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) | ||
291 | rthdr->tx_flags |= cpu_to_le16(IEEE80211_RADIOTAP_F_TX_RTS); | ||
292 | if (info->status.rates[0].idx >= 0 && | ||
293 | !(info->status.rates[0].flags & IEEE80211_TX_RC_MCS)) | ||
294 | rthdr->rate = sband->bitrates[ | ||
295 | info->status.rates[0].idx].bitrate / 5; | ||
296 | |||
297 | /* for now report the total retry_count */ | ||
298 | rthdr->data_retries = retry_count; | ||
299 | |||
300 | /* XXX: is this sufficient for BPF? */ | ||
301 | skb_set_mac_header(skb, 0); | ||
302 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
303 | skb->pkt_type = PACKET_OTHERHOST; | ||
304 | skb->protocol = htons(ETH_P_802_2); | ||
305 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
306 | |||
307 | rcu_read_lock(); | ||
308 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
309 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { | ||
310 | if (!netif_running(sdata->dev)) | ||
311 | continue; | ||
312 | |||
313 | if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && | ||
314 | !(info->flags & IEEE80211_TX_CTL_INJECTED) && | ||
315 | (type == IEEE80211_FTYPE_DATA)) | ||
316 | continue; | ||
317 | |||
318 | if (prev_dev) { | ||
319 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
320 | if (skb2) { | ||
321 | skb2->dev = prev_dev; | ||
322 | netif_rx(skb2); | ||
323 | } | ||
324 | } | ||
325 | |||
326 | prev_dev = sdata->dev; | ||
327 | } | ||
328 | } | ||
329 | if (prev_dev) { | ||
330 | skb->dev = prev_dev; | ||
331 | netif_rx(skb); | ||
332 | skb = NULL; | ||
333 | } | ||
334 | rcu_read_unlock(); | ||
335 | dev_kfree_skb(skb); | ||
336 | } | ||
337 | EXPORT_SYMBOL(ieee80211_tx_status); | ||
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 964b7faa7f17..4921d724b6c7 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -301,9 +301,9 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
301 | #endif | 301 | #endif |
302 | if (key->local->ops->update_tkip_key && | 302 | if (key->local->ops->update_tkip_key && |
303 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | 303 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { |
304 | u8 bcast[ETH_ALEN] = | 304 | static const u8 bcast[ETH_ALEN] = |
305 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 305 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
306 | u8 *sta_addr = key->sta->sta.addr; | 306 | const u8 *sta_addr = key->sta->sta.addr; |
307 | 307 | ||
308 | if (is_multicast_ether_addr(ra)) | 308 | if (is_multicast_ether_addr(ra)) |
309 | sta_addr = bcast; | 309 | sta_addr = bcast; |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 3ad053f6de12..943def2b07df 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1051,7 +1051,7 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1051 | 1051 | ||
1052 | hdr = (struct ieee80211_hdr *) skb->data; | 1052 | hdr = (struct ieee80211_hdr *) skb->data; |
1053 | 1053 | ||
1054 | if ((sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && sdata->use_4addr) | 1054 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1055 | tx->sta = rcu_dereference(sdata->u.vlan.sta); | 1055 | tx->sta = rcu_dereference(sdata->u.vlan.sta); |
1056 | if (!tx->sta) | 1056 | if (!tx->sta) |
1057 | tx->sta = sta_info_get(local, hdr->addr1); | 1057 | tx->sta = sta_info_get(local, hdr->addr1); |
@@ -1219,7 +1219,8 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) | |||
1219 | CALL_TXH(ieee80211_tx_h_ps_buf); | 1219 | CALL_TXH(ieee80211_tx_h_ps_buf); |
1220 | CALL_TXH(ieee80211_tx_h_select_key); | 1220 | CALL_TXH(ieee80211_tx_h_select_key); |
1221 | CALL_TXH(ieee80211_tx_h_michael_mic_add); | 1221 | CALL_TXH(ieee80211_tx_h_michael_mic_add); |
1222 | CALL_TXH(ieee80211_tx_h_rate_ctrl); | 1222 | if (!(tx->local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL)) |
1223 | CALL_TXH(ieee80211_tx_h_rate_ctrl); | ||
1223 | CALL_TXH(ieee80211_tx_h_misc); | 1224 | CALL_TXH(ieee80211_tx_h_misc); |
1224 | CALL_TXH(ieee80211_tx_h_sequence); | 1225 | CALL_TXH(ieee80211_tx_h_sequence); |
1225 | CALL_TXH(ieee80211_tx_h_fragment); | 1226 | CALL_TXH(ieee80211_tx_h_fragment); |
@@ -1430,8 +1431,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1430 | int headroom; | 1431 | int headroom; |
1431 | bool may_encrypt; | 1432 | bool may_encrypt; |
1432 | 1433 | ||
1433 | dev_hold(sdata->dev); | ||
1434 | |||
1435 | if (need_dynamic_ps(local)) { | 1434 | if (need_dynamic_ps(local)) { |
1436 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 1435 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
1437 | ieee80211_stop_queues_by_reason(&local->hw, | 1436 | ieee80211_stop_queues_by_reason(&local->hw, |
@@ -1444,7 +1443,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1444 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1443 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1445 | } | 1444 | } |
1446 | 1445 | ||
1447 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | 1446 | rcu_read_lock(); |
1448 | 1447 | ||
1449 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { | 1448 | if (unlikely(sdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1450 | int hdrlen; | 1449 | int hdrlen; |
@@ -1468,7 +1467,6 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1468 | * support we will need a different mechanism. | 1467 | * support we will need a different mechanism. |
1469 | */ | 1468 | */ |
1470 | 1469 | ||
1471 | rcu_read_lock(); | ||
1472 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, | 1470 | list_for_each_entry_rcu(tmp_sdata, &local->interfaces, |
1473 | list) { | 1471 | list) { |
1474 | if (!netif_running(tmp_sdata->dev)) | 1472 | if (!netif_running(tmp_sdata->dev)) |
@@ -1477,13 +1475,10 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1477 | continue; | 1475 | continue; |
1478 | if (compare_ether_addr(tmp_sdata->dev->dev_addr, | 1476 | if (compare_ether_addr(tmp_sdata->dev->dev_addr, |
1479 | hdr->addr2) == 0) { | 1477 | hdr->addr2) == 0) { |
1480 | dev_hold(tmp_sdata->dev); | ||
1481 | dev_put(sdata->dev); | ||
1482 | sdata = tmp_sdata; | 1478 | sdata = tmp_sdata; |
1483 | break; | 1479 | break; |
1484 | } | 1480 | } |
1485 | } | 1481 | } |
1486 | rcu_read_unlock(); | ||
1487 | } | 1482 | } |
1488 | } | 1483 | } |
1489 | 1484 | ||
@@ -1497,7 +1492,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1497 | 1492 | ||
1498 | if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { | 1493 | if (ieee80211_skb_resize(local, skb, headroom, may_encrypt)) { |
1499 | dev_kfree_skb(skb); | 1494 | dev_kfree_skb(skb); |
1500 | dev_put(sdata->dev); | 1495 | rcu_read_unlock(); |
1501 | return; | 1496 | return; |
1502 | } | 1497 | } |
1503 | 1498 | ||
@@ -1508,13 +1503,13 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, | |||
1508 | !is_multicast_ether_addr(hdr->addr1)) | 1503 | !is_multicast_ether_addr(hdr->addr1)) |
1509 | if (mesh_nexthop_lookup(skb, sdata)) { | 1504 | if (mesh_nexthop_lookup(skb, sdata)) { |
1510 | /* skb queued: don't free */ | 1505 | /* skb queued: don't free */ |
1511 | dev_put(sdata->dev); | 1506 | rcu_read_unlock(); |
1512 | return; | 1507 | return; |
1513 | } | 1508 | } |
1514 | 1509 | ||
1515 | ieee80211_select_queue(local, skb); | 1510 | ieee80211_select_queue(local, skb); |
1516 | ieee80211_tx(sdata, skb, false); | 1511 | ieee80211_tx(sdata, skb, false); |
1517 | dev_put(sdata->dev); | 1512 | rcu_read_unlock(); |
1518 | } | 1513 | } |
1519 | 1514 | ||
1520 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | 1515 | netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, |
@@ -1578,6 +1573,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1578 | 1573 | ||
1579 | memset(info, 0, sizeof(*info)); | 1574 | memset(info, 0, sizeof(*info)); |
1580 | 1575 | ||
1576 | info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS; | ||
1577 | |||
1581 | /* pass the radiotap header up to xmit */ | 1578 | /* pass the radiotap header up to xmit */ |
1582 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); | 1579 | ieee80211_xmit(IEEE80211_DEV_TO_SUB_IF(dev), skb); |
1583 | return NETDEV_TX_OK; | 1580 | return NETDEV_TX_OK; |
@@ -1635,8 +1632,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1635 | switch (sdata->vif.type) { | 1632 | switch (sdata->vif.type) { |
1636 | case NL80211_IFTYPE_AP_VLAN: | 1633 | case NL80211_IFTYPE_AP_VLAN: |
1637 | rcu_read_lock(); | 1634 | rcu_read_lock(); |
1638 | if (sdata->use_4addr) | 1635 | sta = rcu_dereference(sdata->u.vlan.sta); |
1639 | sta = rcu_dereference(sdata->u.vlan.sta); | ||
1640 | if (sta) { | 1636 | if (sta) { |
1641 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1637 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1642 | /* RA TA DA SA */ | 1638 | /* RA TA DA SA */ |
@@ -1687,21 +1683,25 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1687 | /* packet from other interface */ | 1683 | /* packet from other interface */ |
1688 | struct mesh_path *mppath; | 1684 | struct mesh_path *mppath; |
1689 | int is_mesh_mcast = 1; | 1685 | int is_mesh_mcast = 1; |
1690 | char *mesh_da; | 1686 | const u8 *mesh_da; |
1691 | 1687 | ||
1692 | rcu_read_lock(); | 1688 | rcu_read_lock(); |
1693 | if (is_multicast_ether_addr(skb->data)) | 1689 | if (is_multicast_ether_addr(skb->data)) |
1694 | /* DA TA mSA AE:SA */ | 1690 | /* DA TA mSA AE:SA */ |
1695 | mesh_da = skb->data; | 1691 | mesh_da = skb->data; |
1696 | else { | 1692 | else { |
1693 | static const u8 bcast[ETH_ALEN] = | ||
1694 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
1695 | |||
1697 | mppath = mpp_path_lookup(skb->data, sdata); | 1696 | mppath = mpp_path_lookup(skb->data, sdata); |
1698 | if (mppath) { | 1697 | if (mppath) { |
1699 | /* RA TA mDA mSA AE:DA SA */ | 1698 | /* RA TA mDA mSA AE:DA SA */ |
1700 | mesh_da = mppath->mpp; | 1699 | mesh_da = mppath->mpp; |
1701 | is_mesh_mcast = 0; | 1700 | is_mesh_mcast = 0; |
1702 | } else | 1701 | } else { |
1703 | /* DA TA mSA AE:SA */ | 1702 | /* DA TA mSA AE:SA */ |
1704 | mesh_da = dev->broadcast; | 1703 | mesh_da = bcast; |
1704 | } | ||
1705 | } | 1705 | } |
1706 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1706 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1707 | mesh_da, dev->dev_addr); | 1707 | mesh_da, dev->dev_addr); |
@@ -1726,7 +1726,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1726 | #endif | 1726 | #endif |
1727 | case NL80211_IFTYPE_STATION: | 1727 | case NL80211_IFTYPE_STATION: |
1728 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); | 1728 | memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN); |
1729 | if (sdata->use_4addr && ethertype != ETH_P_PAE) { | 1729 | if (sdata->u.mgd.use_4addr && ethertype != ETH_P_PAE) { |
1730 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1730 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
1731 | /* RA TA DA SA */ | 1731 | /* RA TA DA SA */ |
1732 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); | 1732 | memcpy(hdr.addr2, dev->dev_addr, ETH_ALEN); |
@@ -1964,12 +1964,10 @@ void ieee80211_tx_pending(unsigned long data) | |||
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | sdata = vif_to_sdata(info->control.vif); | 1966 | sdata = vif_to_sdata(info->control.vif); |
1967 | dev_hold(sdata->dev); | ||
1968 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | 1967 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, |
1969 | flags); | 1968 | flags); |
1970 | 1969 | ||
1971 | txok = ieee80211_tx_pending_skb(local, skb); | 1970 | txok = ieee80211_tx_pending_skb(local, skb); |
1972 | dev_put(sdata->dev); | ||
1973 | if (!txok) | 1971 | if (!txok) |
1974 | __skb_queue_head(&local->pending[i], skb); | 1972 | __skb_queue_head(&local->pending[i], skb); |
1975 | spin_lock_irqsave(&local->queue_stop_reason_lock, | 1973 | spin_lock_irqsave(&local->queue_stop_reason_lock, |
@@ -2282,17 +2280,12 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2282 | } | 2280 | } |
2283 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); | 2281 | EXPORT_SYMBOL(ieee80211_get_buffered_bc); |
2284 | 2282 | ||
2285 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 2283 | void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
2286 | int encrypt) | ||
2287 | { | 2284 | { |
2288 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2289 | skb_set_mac_header(skb, 0); | 2285 | skb_set_mac_header(skb, 0); |
2290 | skb_set_network_header(skb, 0); | 2286 | skb_set_network_header(skb, 0); |
2291 | skb_set_transport_header(skb, 0); | 2287 | skb_set_transport_header(skb, 0); |
2292 | 2288 | ||
2293 | if (!encrypt) | ||
2294 | info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||
2295 | |||
2296 | /* | 2289 | /* |
2297 | * The other path calling ieee80211_xmit is from the tasklet, | 2290 | * The other path calling ieee80211_xmit is from the tasklet, |
2298 | * and while we can handle concurrent transmissions locking | 2291 | * and while we can handle concurrent transmissions locking |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index da86e1592f8c..2fb0432ac830 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -666,8 +666,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
666 | elems->mesh_id_len = elen; | 666 | elems->mesh_id_len = elen; |
667 | break; | 667 | break; |
668 | case WLAN_EID_MESH_CONFIG: | 668 | case WLAN_EID_MESH_CONFIG: |
669 | elems->mesh_config = pos; | 669 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) |
670 | elems->mesh_config_len = elen; | 670 | elems->mesh_config = (void *)pos; |
671 | break; | 671 | break; |
672 | case WLAN_EID_PEER_LINK: | 672 | case WLAN_EID_PEER_LINK: |
673 | elems->peer_link = pos; | 673 | elems->peer_link = pos; |
@@ -872,7 +872,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata, | |||
872 | WARN_ON(err); | 872 | WARN_ON(err); |
873 | } | 873 | } |
874 | 874 | ||
875 | ieee80211_tx_skb(sdata, skb, 0); | 875 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
876 | ieee80211_tx_skb(sdata, skb); | ||
876 | } | 877 | } |
877 | 878 | ||
878 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 879 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
@@ -974,7 +975,8 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | |||
974 | skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len, | 975 | skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len, |
975 | local->hw.conf.channel->band)); | 976 | local->hw.conf.channel->band)); |
976 | 977 | ||
977 | ieee80211_tx_skb(sdata, skb, 0); | 978 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
979 | ieee80211_tx_skb(sdata, skb); | ||
978 | } | 980 | } |
979 | 981 | ||
980 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | 982 | u32 ieee80211_sta_get_rates(struct ieee80211_local *local, |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 8a980f136941..247123fe1a7a 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -281,16 +281,18 @@ bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, struct ieee80211_key *key) | |||
281 | ieee80211_rx_result | 281 | ieee80211_rx_result |
282 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | 282 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) |
283 | { | 283 | { |
284 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; | 284 | struct sk_buff *skb = rx->skb; |
285 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
286 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
285 | 287 | ||
286 | if (!ieee80211_is_data(hdr->frame_control) && | 288 | if (!ieee80211_is_data(hdr->frame_control) && |
287 | !ieee80211_is_auth(hdr->frame_control)) | 289 | !ieee80211_is_auth(hdr->frame_control)) |
288 | return RX_CONTINUE; | 290 | return RX_CONTINUE; |
289 | 291 | ||
290 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | 292 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
291 | if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) | 293 | if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) |
292 | return RX_DROP_UNUSABLE; | 294 | return RX_DROP_UNUSABLE; |
293 | } else if (!(rx->status->flag & RX_FLAG_IV_STRIPPED)) { | 295 | } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { |
294 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); | 296 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); |
295 | /* remove ICV */ | 297 | /* remove ICV */ |
296 | skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); | 298 | skb_trim(rx->skb, rx->skb->len - WEP_ICV_LEN); |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 70778694877b..5332014cb229 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -85,16 +85,16 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
85 | u8 *data, *key = NULL, key_offset; | 85 | u8 *data, *key = NULL, key_offset; |
86 | size_t data_len; | 86 | size_t data_len; |
87 | unsigned int hdrlen; | 87 | unsigned int hdrlen; |
88 | struct ieee80211_hdr *hdr; | ||
89 | u8 mic[MICHAEL_MIC_LEN]; | 88 | u8 mic[MICHAEL_MIC_LEN]; |
90 | struct sk_buff *skb = rx->skb; | 89 | struct sk_buff *skb = rx->skb; |
90 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
91 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
91 | int authenticator = 1, wpa_test = 0; | 92 | int authenticator = 1, wpa_test = 0; |
92 | 93 | ||
93 | /* No way to verify the MIC if the hardware stripped it */ | 94 | /* No way to verify the MIC if the hardware stripped it */ |
94 | if (rx->status->flag & RX_FLAG_MMIC_STRIPPED) | 95 | if (status->flag & RX_FLAG_MMIC_STRIPPED) |
95 | return RX_CONTINUE; | 96 | return RX_CONTINUE; |
96 | 97 | ||
97 | hdr = (struct ieee80211_hdr *)skb->data; | ||
98 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || | 98 | if (!rx->key || rx->key->conf.alg != ALG_TKIP || |
99 | !ieee80211_has_protected(hdr->frame_control) || | 99 | !ieee80211_has_protected(hdr->frame_control) || |
100 | !ieee80211_is_data_present(hdr->frame_control)) | 100 | !ieee80211_is_data_present(hdr->frame_control)) |
@@ -216,6 +216,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
216 | int hdrlen, res, hwaccel = 0, wpa_test = 0; | 216 | int hdrlen, res, hwaccel = 0, wpa_test = 0; |
217 | struct ieee80211_key *key = rx->key; | 217 | struct ieee80211_key *key = rx->key; |
218 | struct sk_buff *skb = rx->skb; | 218 | struct sk_buff *skb = rx->skb; |
219 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
219 | 220 | ||
220 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 221 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
221 | 222 | ||
@@ -225,8 +226,8 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
225 | if (!rx->sta || skb->len - hdrlen < 12) | 226 | if (!rx->sta || skb->len - hdrlen < 12) |
226 | return RX_DROP_UNUSABLE; | 227 | return RX_DROP_UNUSABLE; |
227 | 228 | ||
228 | if (rx->status->flag & RX_FLAG_DECRYPTED) { | 229 | if (status->flag & RX_FLAG_DECRYPTED) { |
229 | if (rx->status->flag & RX_FLAG_IV_STRIPPED) { | 230 | if (status->flag & RX_FLAG_IV_STRIPPED) { |
230 | /* | 231 | /* |
231 | * Hardware took care of all processing, including | 232 | * Hardware took care of all processing, including |
232 | * replay protection, and stripped the ICV/IV so | 233 | * replay protection, and stripped the ICV/IV so |
@@ -442,6 +443,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
442 | int hdrlen; | 443 | int hdrlen; |
443 | struct ieee80211_key *key = rx->key; | 444 | struct ieee80211_key *key = rx->key; |
444 | struct sk_buff *skb = rx->skb; | 445 | struct sk_buff *skb = rx->skb; |
446 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
445 | u8 pn[CCMP_PN_LEN]; | 447 | u8 pn[CCMP_PN_LEN]; |
446 | int data_len; | 448 | int data_len; |
447 | 449 | ||
@@ -455,8 +457,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
455 | if (!rx->sta || data_len < 0) | 457 | if (!rx->sta || data_len < 0) |
456 | return RX_DROP_UNUSABLE; | 458 | return RX_DROP_UNUSABLE; |
457 | 459 | ||
458 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 460 | if ((status->flag & RX_FLAG_DECRYPTED) && |
459 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | 461 | (status->flag & RX_FLAG_IV_STRIPPED)) |
460 | return RX_CONTINUE; | 462 | return RX_CONTINUE; |
461 | 463 | ||
462 | ccmp_hdr2pn(pn, skb->data + hdrlen); | 464 | ccmp_hdr2pn(pn, skb->data + hdrlen); |
@@ -466,7 +468,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
466 | return RX_DROP_UNUSABLE; | 468 | return RX_DROP_UNUSABLE; |
467 | } | 469 | } |
468 | 470 | ||
469 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | 471 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
470 | /* hardware didn't decrypt/verify MIC */ | 472 | /* hardware didn't decrypt/verify MIC */ |
471 | ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); | 473 | ccmp_special_blocks(skb, pn, key->u.ccmp.rx_crypto_buf, 1); |
472 | 474 | ||
@@ -563,6 +565,7 @@ ieee80211_rx_result | |||
563 | ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | 565 | ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) |
564 | { | 566 | { |
565 | struct sk_buff *skb = rx->skb; | 567 | struct sk_buff *skb = rx->skb; |
568 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
566 | struct ieee80211_key *key = rx->key; | 569 | struct ieee80211_key *key = rx->key; |
567 | struct ieee80211_mmie *mmie; | 570 | struct ieee80211_mmie *mmie; |
568 | u8 aad[20], mic[8], ipn[6]; | 571 | u8 aad[20], mic[8], ipn[6]; |
@@ -571,8 +574,8 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
571 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 574 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
572 | return RX_CONTINUE; | 575 | return RX_CONTINUE; |
573 | 576 | ||
574 | if ((rx->status->flag & RX_FLAG_DECRYPTED) && | 577 | if ((status->flag & RX_FLAG_DECRYPTED) && |
575 | (rx->status->flag & RX_FLAG_IV_STRIPPED)) | 578 | (status->flag & RX_FLAG_IV_STRIPPED)) |
576 | return RX_CONTINUE; | 579 | return RX_CONTINUE; |
577 | 580 | ||
578 | if (skb->len < 24 + sizeof(*mmie)) | 581 | if (skb->len < 24 + sizeof(*mmie)) |
@@ -591,7 +594,7 @@ ieee80211_crypto_aes_cmac_decrypt(struct ieee80211_rx_data *rx) | |||
591 | return RX_DROP_UNUSABLE; | 594 | return RX_DROP_UNUSABLE; |
592 | } | 595 | } |
593 | 596 | ||
594 | if (!(rx->status->flag & RX_FLAG_DECRYPTED)) { | 597 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
595 | /* hardware didn't decrypt/verify MIC */ | 598 | /* hardware didn't decrypt/verify MIC */ |
596 | bip_aad(skb, aad); | 599 | bip_aad(skb, aad); |
597 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, | 600 | ieee80211_aes_cmac(key->u.aes_cmac.tfm, |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index ba2efb960c60..09f4e161799b 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -592,11 +592,13 @@ static const char *rfkill_get_type_str(enum rfkill_type type) | |||
592 | return "wwan"; | 592 | return "wwan"; |
593 | case RFKILL_TYPE_GPS: | 593 | case RFKILL_TYPE_GPS: |
594 | return "gps"; | 594 | return "gps"; |
595 | case RFKILL_TYPE_FM: | ||
596 | return "fm"; | ||
595 | default: | 597 | default: |
596 | BUG(); | 598 | BUG(); |
597 | } | 599 | } |
598 | 600 | ||
599 | BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_GPS + 1); | 601 | BUILD_BUG_ON(NUM_RFKILL_TYPES != RFKILL_TYPE_FM + 1); |
600 | } | 602 | } |
601 | 603 | ||
602 | static ssize_t rfkill_type_show(struct device *dev, | 604 | static ssize_t rfkill_type_show(struct device *dev, |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 614bdcec1c80..90e93a5701aa 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -74,12 +74,6 @@ config CFG80211_REG_DEBUG | |||
74 | 74 | ||
75 | If unsure, say N. | 75 | If unsure, say N. |
76 | 76 | ||
77 | config CFG80211_DEFAULT_PS_VALUE | ||
78 | int | ||
79 | default 1 if CFG80211_DEFAULT_PS | ||
80 | default 0 | ||
81 | depends on CFG80211 | ||
82 | |||
83 | config CFG80211_DEFAULT_PS | 77 | config CFG80211_DEFAULT_PS |
84 | bool "enable powersave by default" | 78 | bool "enable powersave by default" |
85 | depends on CFG80211 | 79 | depends on CFG80211 |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 45bd63ad2eb2..fe6f402a22af 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -231,7 +231,7 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev, | |||
231 | struct wireless_dev *wdev; | 231 | struct wireless_dev *wdev; |
232 | int err = 0; | 232 | int err = 0; |
233 | 233 | ||
234 | if (!rdev->wiphy.netnsok) | 234 | if (!(rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK)) |
235 | return -EOPNOTSUPP; | 235 | return -EOPNOTSUPP; |
236 | 236 | ||
237 | list_for_each_entry(wdev, &rdev->netdev_list, list) { | 237 | list_for_each_entry(wdev, &rdev->netdev_list, list) { |
@@ -368,7 +368,9 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
368 | rdev->wiphy.dev.class = &ieee80211_class; | 368 | rdev->wiphy.dev.class = &ieee80211_class; |
369 | rdev->wiphy.dev.platform_data = rdev; | 369 | rdev->wiphy.dev.platform_data = rdev; |
370 | 370 | ||
371 | rdev->wiphy.ps_default = CONFIG_CFG80211_DEFAULT_PS_VALUE; | 371 | #ifdef CONFIG_CFG80211_DEFAULT_PS |
372 | rdev->wiphy.flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; | ||
373 | #endif | ||
372 | 374 | ||
373 | wiphy_net_set(&rdev->wiphy, &init_net); | 375 | wiphy_net_set(&rdev->wiphy, &init_net); |
374 | 376 | ||
@@ -483,7 +485,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
483 | if (IS_ERR(rdev->wiphy.debugfsdir)) | 485 | if (IS_ERR(rdev->wiphy.debugfsdir)) |
484 | rdev->wiphy.debugfsdir = NULL; | 486 | rdev->wiphy.debugfsdir = NULL; |
485 | 487 | ||
486 | if (wiphy->custom_regulatory) { | 488 | if (wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) { |
487 | struct regulatory_request request; | 489 | struct regulatory_request request; |
488 | 490 | ||
489 | request.wiphy_idx = get_wiphy_idx(wiphy); | 491 | request.wiphy_idx = get_wiphy_idx(wiphy); |
@@ -681,7 +683,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
681 | wdev->wext.default_key = -1; | 683 | wdev->wext.default_key = -1; |
682 | wdev->wext.default_mgmt_key = -1; | 684 | wdev->wext.default_mgmt_key = -1; |
683 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; | 685 | wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; |
684 | wdev->wext.ps = wdev->wiphy->ps_default; | 686 | if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) |
687 | wdev->wext.ps = true; | ||
688 | else | ||
689 | wdev->wext.ps = false; | ||
685 | wdev->wext.ps_timeout = 100; | 690 | wdev->wext.ps_timeout = 100; |
686 | if (rdev->ops->set_power_mgmt) | 691 | if (rdev->ops->set_power_mgmt) |
687 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, | 692 | if (rdev->ops->set_power_mgmt(wdev->wiphy, dev, |
@@ -693,6 +698,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
693 | #endif | 698 | #endif |
694 | if (!dev->ethtool_ops) | 699 | if (!dev->ethtool_ops) |
695 | dev->ethtool_ops = &cfg80211_ethtool_ops; | 700 | dev->ethtool_ops = &cfg80211_ethtool_ops; |
701 | |||
702 | if ((wdev->iftype == NL80211_IFTYPE_STATION || | ||
703 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) | ||
704 | dev->priv_flags |= IFF_DONT_BRIDGE; | ||
696 | break; | 705 | break; |
697 | case NETDEV_GOING_DOWN: | 706 | case NETDEV_GOING_DOWN: |
698 | switch (wdev->iftype) { | 707 | switch (wdev->iftype) { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 5aeebb9085f8..a9db9e6255bb 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -273,6 +273,8 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
273 | struct cfg80211_ibss_params *params, | 273 | struct cfg80211_ibss_params *params, |
274 | struct cfg80211_cached_keys *connkeys); | 274 | struct cfg80211_cached_keys *connkeys); |
275 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); | 275 | void cfg80211_clear_ibss(struct net_device *dev, bool nowext); |
276 | int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | ||
277 | struct net_device *dev, bool nowext); | ||
276 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 278 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
277 | struct net_device *dev, bool nowext); | 279 | struct net_device *dev, bool nowext); |
278 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); | 280 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); |
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index 39b6d92e2828..34dfc93fa713 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
@@ -169,8 +169,8 @@ void cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
169 | wdev_unlock(wdev); | 169 | wdev_unlock(wdev); |
170 | } | 170 | } |
171 | 171 | ||
172 | static int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 172 | int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
173 | struct net_device *dev, bool nowext) | 173 | struct net_device *dev, bool nowext) |
174 | { | 174 | { |
175 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 175 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
176 | int err; | 176 | int err; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 2610b746effa..1001db4912f7 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -243,21 +243,12 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len) | |||
243 | } | 243 | } |
244 | EXPORT_SYMBOL(cfg80211_send_disassoc); | 244 | EXPORT_SYMBOL(cfg80211_send_disassoc); |
245 | 245 | ||
246 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | 246 | static void __cfg80211_auth_remove(struct wireless_dev *wdev, const u8 *addr) |
247 | { | 247 | { |
248 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
249 | struct wiphy *wiphy = wdev->wiphy; | ||
250 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
251 | int i; | 248 | int i; |
252 | bool done = false; | 249 | bool done = false; |
253 | 250 | ||
254 | wdev_lock(wdev); | 251 | ASSERT_WDEV_LOCK(wdev); |
255 | |||
256 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); | ||
257 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | ||
258 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | ||
259 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
260 | false, NULL); | ||
261 | 252 | ||
262 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { | 253 | for (i = 0; addr && i < MAX_AUTH_BSSES; i++) { |
263 | if (wdev->authtry_bsses[i] && | 254 | if (wdev->authtry_bsses[i] && |
@@ -272,6 +263,29 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | |||
272 | } | 263 | } |
273 | 264 | ||
274 | WARN_ON(!done); | 265 | WARN_ON(!done); |
266 | } | ||
267 | |||
268 | void __cfg80211_auth_canceled(struct net_device *dev, const u8 *addr) | ||
269 | { | ||
270 | __cfg80211_auth_remove(dev->ieee80211_ptr, addr); | ||
271 | } | ||
272 | EXPORT_SYMBOL(__cfg80211_auth_canceled); | ||
273 | |||
274 | void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr) | ||
275 | { | ||
276 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
277 | struct wiphy *wiphy = wdev->wiphy; | ||
278 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
279 | |||
280 | wdev_lock(wdev); | ||
281 | |||
282 | nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL); | ||
283 | if (wdev->sme_state == CFG80211_SME_CONNECTING) | ||
284 | __cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0, | ||
285 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
286 | false, NULL); | ||
287 | |||
288 | __cfg80211_auth_remove(wdev, addr); | ||
275 | 289 | ||
276 | wdev_unlock(wdev); | 290 | wdev_unlock(wdev); |
277 | } | 291 | } |
@@ -446,12 +460,23 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
446 | struct cfg80211_assoc_request req; | 460 | struct cfg80211_assoc_request req; |
447 | struct cfg80211_internal_bss *bss; | 461 | struct cfg80211_internal_bss *bss; |
448 | int i, err, slot = -1; | 462 | int i, err, slot = -1; |
463 | bool was_connected = false; | ||
449 | 464 | ||
450 | ASSERT_WDEV_LOCK(wdev); | 465 | ASSERT_WDEV_LOCK(wdev); |
451 | 466 | ||
452 | memset(&req, 0, sizeof(req)); | 467 | memset(&req, 0, sizeof(req)); |
453 | 468 | ||
454 | if (wdev->current_bss) | 469 | if (wdev->current_bss && prev_bssid && |
470 | memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) { | ||
471 | /* | ||
472 | * Trying to reassociate: Allow this to proceed and let the old | ||
473 | * association to be dropped when the new one is completed. | ||
474 | */ | ||
475 | if (wdev->sme_state == CFG80211_SME_CONNECTED) { | ||
476 | was_connected = true; | ||
477 | wdev->sme_state = CFG80211_SME_CONNECTING; | ||
478 | } | ||
479 | } else if (wdev->current_bss) | ||
455 | return -EALREADY; | 480 | return -EALREADY; |
456 | 481 | ||
457 | req.ie = ie; | 482 | req.ie = ie; |
@@ -461,8 +486,11 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
461 | req.prev_bssid = prev_bssid; | 486 | req.prev_bssid = prev_bssid; |
462 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, | 487 | req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, |
463 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 488 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
464 | if (!req.bss) | 489 | if (!req.bss) { |
490 | if (was_connected) | ||
491 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
465 | return -ENOENT; | 492 | return -ENOENT; |
493 | } | ||
466 | 494 | ||
467 | bss = bss_from_pub(req.bss); | 495 | bss = bss_from_pub(req.bss); |
468 | 496 | ||
@@ -480,6 +508,8 @@ int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, | |||
480 | 508 | ||
481 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); | 509 | err = rdev->ops->assoc(&rdev->wiphy, dev, &req); |
482 | out: | 510 | out: |
511 | if (err && was_connected) | ||
512 | wdev->sme_state = CFG80211_SME_CONNECTED; | ||
483 | /* still a reference in wdev->auth_bsses[slot] */ | 513 | /* still a reference in wdev->auth_bsses[slot] */ |
484 | cfg80211_put_bss(req.bss); | 514 | cfg80211_put_bss(req.bss); |
485 | return err; | 515 | return err; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 37264d56bace..149539ade15e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -561,7 +561,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
561 | CMD(deauth, DEAUTHENTICATE); | 561 | CMD(deauth, DEAUTHENTICATE); |
562 | CMD(disassoc, DISASSOCIATE); | 562 | CMD(disassoc, DISASSOCIATE); |
563 | CMD(join_ibss, JOIN_IBSS); | 563 | CMD(join_ibss, JOIN_IBSS); |
564 | if (dev->wiphy.netnsok) { | 564 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
565 | i++; | 565 | i++; |
566 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 566 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
567 | } | 567 | } |
@@ -968,6 +968,32 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags) | |||
968 | return 0; | 968 | return 0; |
969 | } | 969 | } |
970 | 970 | ||
971 | static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev, | ||
972 | struct net_device *netdev, u8 use_4addr, | ||
973 | enum nl80211_iftype iftype) | ||
974 | { | ||
975 | if (!use_4addr) { | ||
976 | if (netdev && netdev->br_port) | ||
977 | return -EBUSY; | ||
978 | return 0; | ||
979 | } | ||
980 | |||
981 | switch (iftype) { | ||
982 | case NL80211_IFTYPE_AP_VLAN: | ||
983 | if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP) | ||
984 | return 0; | ||
985 | break; | ||
986 | case NL80211_IFTYPE_STATION: | ||
987 | if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION) | ||
988 | return 0; | ||
989 | break; | ||
990 | default: | ||
991 | break; | ||
992 | } | ||
993 | |||
994 | return -EOPNOTSUPP; | ||
995 | } | ||
996 | |||
971 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | 997 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) |
972 | { | 998 | { |
973 | struct cfg80211_registered_device *rdev; | 999 | struct cfg80211_registered_device *rdev; |
@@ -1011,6 +1037,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
1011 | if (info->attrs[NL80211_ATTR_4ADDR]) { | 1037 | if (info->attrs[NL80211_ATTR_4ADDR]) { |
1012 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); | 1038 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); |
1013 | change = true; | 1039 | change = true; |
1040 | err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype); | ||
1041 | if (err) | ||
1042 | goto unlock; | ||
1014 | } else { | 1043 | } else { |
1015 | params.use_4addr = -1; | 1044 | params.use_4addr = -1; |
1016 | } | 1045 | } |
@@ -1034,6 +1063,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
1034 | else | 1063 | else |
1035 | err = 0; | 1064 | err = 0; |
1036 | 1065 | ||
1066 | if (!err && params.use_4addr != -1) | ||
1067 | dev->ieee80211_ptr->use_4addr = params.use_4addr; | ||
1068 | |||
1037 | unlock: | 1069 | unlock: |
1038 | dev_put(dev); | 1070 | dev_put(dev); |
1039 | cfg80211_unlock_rdev(rdev); | 1071 | cfg80211_unlock_rdev(rdev); |
@@ -1081,8 +1113,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
1081 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 1113 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
1082 | } | 1114 | } |
1083 | 1115 | ||
1084 | if (info->attrs[NL80211_ATTR_4ADDR]) | 1116 | if (info->attrs[NL80211_ATTR_4ADDR]) { |
1085 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); | 1117 | params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]); |
1118 | err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type); | ||
1119 | if (err) | ||
1120 | goto unlock; | ||
1121 | } | ||
1086 | 1122 | ||
1087 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 1123 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
1088 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 1124 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f256dfffbf46..1f33017737fd 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -1008,7 +1008,7 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, | |||
1008 | 1008 | ||
1009 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1009 | if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
1010 | request_wiphy && request_wiphy == wiphy && | 1010 | request_wiphy && request_wiphy == wiphy && |
1011 | request_wiphy->strict_regulatory) { | 1011 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
1012 | /* | 1012 | /* |
1013 | * This gaurantees the driver's requested regulatory domain | 1013 | * This gaurantees the driver's requested regulatory domain |
1014 | * will always be used as a base for further regulatory | 1014 | * will always be used as a base for further regulatory |
@@ -1051,13 +1051,13 @@ static bool ignore_reg_update(struct wiphy *wiphy, | |||
1051 | if (!last_request) | 1051 | if (!last_request) |
1052 | return true; | 1052 | return true; |
1053 | if (initiator == NL80211_REGDOM_SET_BY_CORE && | 1053 | if (initiator == NL80211_REGDOM_SET_BY_CORE && |
1054 | wiphy->custom_regulatory) | 1054 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) |
1055 | return true; | 1055 | return true; |
1056 | /* | 1056 | /* |
1057 | * wiphy->regd will be set once the device has its own | 1057 | * wiphy->regd will be set once the device has its own |
1058 | * desired regulatory domain set | 1058 | * desired regulatory domain set |
1059 | */ | 1059 | */ |
1060 | if (wiphy->strict_regulatory && !wiphy->regd && | 1060 | if (wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY && !wiphy->regd && |
1061 | !is_world_regdom(last_request->alpha2)) | 1061 | !is_world_regdom(last_request->alpha2)) |
1062 | return true; | 1062 | return true; |
1063 | return false; | 1063 | return false; |
@@ -1093,7 +1093,7 @@ static void handle_reg_beacon(struct wiphy *wiphy, | |||
1093 | 1093 | ||
1094 | chan->beacon_found = true; | 1094 | chan->beacon_found = true; |
1095 | 1095 | ||
1096 | if (wiphy->disable_beacon_hints) | 1096 | if (wiphy->flags & WIPHY_FLAG_DISABLE_BEACON_HINTS) |
1097 | return; | 1097 | return; |
1098 | 1098 | ||
1099 | chan_before.center_freq = chan->center_freq; | 1099 | chan_before.center_freq = chan->center_freq; |
@@ -1164,7 +1164,7 @@ static bool reg_is_world_roaming(struct wiphy *wiphy) | |||
1164 | return true; | 1164 | return true; |
1165 | if (last_request && | 1165 | if (last_request && |
1166 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | 1166 | last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && |
1167 | wiphy->custom_regulatory) | 1167 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY) |
1168 | return true; | 1168 | return true; |
1169 | return false; | 1169 | return false; |
1170 | } | 1170 | } |
@@ -1591,7 +1591,8 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
1591 | 1591 | ||
1592 | r = __regulatory_hint(wiphy, reg_request); | 1592 | r = __regulatory_hint(wiphy, reg_request); |
1593 | /* This is required so that the orig_* parameters are saved */ | 1593 | /* This is required so that the orig_* parameters are saved */ |
1594 | if (r == -EALREADY && wiphy && wiphy->strict_regulatory) | 1594 | if (r == -EALREADY && wiphy && |
1595 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | ||
1595 | wiphy_update_regulatory(wiphy, reg_request->initiator); | 1596 | wiphy_update_regulatory(wiphy, reg_request->initiator); |
1596 | out: | 1597 | out: |
1597 | mutex_unlock(®_mutex); | 1598 | mutex_unlock(®_mutex); |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index e2d344ff6745..227d57b8dc41 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -217,7 +217,7 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
217 | a->len_information_elements); | 217 | a->len_information_elements); |
218 | if (!ie) | 218 | if (!ie) |
219 | return false; | 219 | return false; |
220 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | 220 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) |
221 | return false; | 221 | return false; |
222 | 222 | ||
223 | /* | 223 | /* |
@@ -225,7 +225,8 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
225 | * comparing since that may differ between stations taking | 225 | * comparing since that may differ between stations taking |
226 | * part in the same mesh. | 226 | * part in the same mesh. |
227 | */ | 227 | */ |
228 | return memcmp(ie + 2, meshcfg, IEEE80211_MESH_CONFIG_LEN - 2) == 0; | 228 | return memcmp(ie + 2, meshcfg, |
229 | sizeof(struct ieee80211_meshconf_ie) - 2) == 0; | ||
229 | } | 230 | } |
230 | 231 | ||
231 | static int cmp_bss(struct cfg80211_bss *a, | 232 | static int cmp_bss(struct cfg80211_bss *a, |
@@ -399,7 +400,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
399 | res->pub.information_elements, | 400 | res->pub.information_elements, |
400 | res->pub.len_information_elements); | 401 | res->pub.len_information_elements); |
401 | if (!meshid || !meshcfg || | 402 | if (!meshid || !meshcfg || |
402 | meshcfg[1] != IEEE80211_MESH_CONFIG_LEN) { | 403 | meshcfg[1] != sizeof(struct ieee80211_meshconf_ie)) { |
403 | /* bogus mesh */ | 404 | /* bogus mesh */ |
404 | kref_put(&res->ref, bss_release); | 405 | kref_put(&res->ref, bss_release); |
405 | return NULL; | 406 | return NULL; |
@@ -865,7 +866,7 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
865 | break; | 866 | break; |
866 | case WLAN_EID_MESH_CONFIG: | 867 | case WLAN_EID_MESH_CONFIG: |
867 | ismesh = true; | 868 | ismesh = true; |
868 | if (ie[1] != IEEE80211_MESH_CONFIG_LEN) | 869 | if (ie[1] != sizeof(struct ieee80211_meshconf_ie)) |
869 | break; | 870 | break; |
870 | buf = kmalloc(50, GFP_ATOMIC); | 871 | buf = kmalloc(50, GFP_ATOMIC); |
871 | if (!buf) | 872 | if (!buf) |
@@ -873,35 +874,40 @@ ieee80211_bss(struct wiphy *wiphy, struct iw_request_info *info, | |||
873 | cfg = ie + 2; | 874 | cfg = ie + 2; |
874 | memset(&iwe, 0, sizeof(iwe)); | 875 | memset(&iwe, 0, sizeof(iwe)); |
875 | iwe.cmd = IWEVCUSTOM; | 876 | iwe.cmd = IWEVCUSTOM; |
876 | sprintf(buf, "Mesh network (version %d)", cfg[0]); | 877 | sprintf(buf, "Mesh Network Path Selection Protocol ID: " |
878 | "0x%02X", cfg[0]); | ||
877 | iwe.u.data.length = strlen(buf); | 879 | iwe.u.data.length = strlen(buf); |
878 | current_ev = iwe_stream_add_point(info, current_ev, | 880 | current_ev = iwe_stream_add_point(info, current_ev, |
879 | end_buf, | 881 | end_buf, |
880 | &iwe, buf); | 882 | &iwe, buf); |
881 | sprintf(buf, "Path Selection Protocol ID: " | 883 | sprintf(buf, "Path Selection Metric ID: 0x%02X", |
882 | "0x%02X%02X%02X%02X", cfg[1], cfg[2], cfg[3], | 884 | cfg[1]); |
883 | cfg[4]); | ||
884 | iwe.u.data.length = strlen(buf); | 885 | iwe.u.data.length = strlen(buf); |
885 | current_ev = iwe_stream_add_point(info, current_ev, | 886 | current_ev = iwe_stream_add_point(info, current_ev, |
886 | end_buf, | 887 | end_buf, |
887 | &iwe, buf); | 888 | &iwe, buf); |
888 | sprintf(buf, "Path Selection Metric ID: " | 889 | sprintf(buf, "Congestion Control Mode ID: 0x%02X", |
889 | "0x%02X%02X%02X%02X", cfg[5], cfg[6], cfg[7], | 890 | cfg[2]); |
890 | cfg[8]); | ||
891 | iwe.u.data.length = strlen(buf); | 891 | iwe.u.data.length = strlen(buf); |
892 | current_ev = iwe_stream_add_point(info, current_ev, | 892 | current_ev = iwe_stream_add_point(info, current_ev, |
893 | end_buf, | 893 | end_buf, |
894 | &iwe, buf); | 894 | &iwe, buf); |
895 | sprintf(buf, "Congestion Control Mode ID: " | 895 | sprintf(buf, "Synchronization ID: 0x%02X", cfg[3]); |
896 | "0x%02X%02X%02X%02X", cfg[9], cfg[10], | ||
897 | cfg[11], cfg[12]); | ||
898 | iwe.u.data.length = strlen(buf); | 896 | iwe.u.data.length = strlen(buf); |
899 | current_ev = iwe_stream_add_point(info, current_ev, | 897 | current_ev = iwe_stream_add_point(info, current_ev, |
900 | end_buf, | 898 | end_buf, |
901 | &iwe, buf); | 899 | &iwe, buf); |
902 | sprintf(buf, "Channel Precedence: " | 900 | sprintf(buf, "Authentication ID: 0x%02X", cfg[4]); |
903 | "0x%02X%02X%02X%02X", cfg[13], cfg[14], | 901 | iwe.u.data.length = strlen(buf); |
904 | cfg[15], cfg[16]); | 902 | current_ev = iwe_stream_add_point(info, current_ev, |
903 | end_buf, | ||
904 | &iwe, buf); | ||
905 | sprintf(buf, "Formation Info: 0x%02X", cfg[5]); | ||
906 | iwe.u.data.length = strlen(buf); | ||
907 | current_ev = iwe_stream_add_point(info, current_ev, | ||
908 | end_buf, | ||
909 | &iwe, buf); | ||
910 | sprintf(buf, "Capabilities: 0x%02X", cfg[6]); | ||
905 | iwe.u.data.length = strlen(buf); | 911 | iwe.u.data.length = strlen(buf); |
906 | current_ev = iwe_stream_add_point(info, current_ev, | 912 | current_ev = iwe_stream_add_point(info, current_ev, |
907 | end_buf, | 913 | end_buf, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 5aa39f7cf9b9..59361fdcb5d0 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -658,7 +658,14 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
658 | !(rdev->wiphy.interface_modes & (1 << ntype))) | 658 | !(rdev->wiphy.interface_modes & (1 << ntype))) |
659 | return -EOPNOTSUPP; | 659 | return -EOPNOTSUPP; |
660 | 660 | ||
661 | /* if it's part of a bridge, reject changing type to station/ibss */ | ||
662 | if (dev->br_port && (ntype == NL80211_IFTYPE_ADHOC || | ||
663 | ntype == NL80211_IFTYPE_STATION)) | ||
664 | return -EBUSY; | ||
665 | |||
661 | if (ntype != otype) { | 666 | if (ntype != otype) { |
667 | dev->ieee80211_ptr->use_4addr = false; | ||
668 | |||
662 | switch (otype) { | 669 | switch (otype) { |
663 | case NL80211_IFTYPE_ADHOC: | 670 | case NL80211_IFTYPE_ADHOC: |
664 | cfg80211_leave_ibss(rdev, dev, false); | 671 | cfg80211_leave_ibss(rdev, dev, false); |
@@ -682,5 +689,34 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
682 | 689 | ||
683 | WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); | 690 | WARN_ON(!err && dev->ieee80211_ptr->iftype != ntype); |
684 | 691 | ||
692 | if (!err && params && params->use_4addr != -1) | ||
693 | dev->ieee80211_ptr->use_4addr = params->use_4addr; | ||
694 | |||
695 | if (!err) { | ||
696 | dev->priv_flags &= ~IFF_DONT_BRIDGE; | ||
697 | switch (ntype) { | ||
698 | case NL80211_IFTYPE_STATION: | ||
699 | if (dev->ieee80211_ptr->use_4addr) | ||
700 | break; | ||
701 | /* fall through */ | ||
702 | case NL80211_IFTYPE_ADHOC: | ||
703 | dev->priv_flags |= IFF_DONT_BRIDGE; | ||
704 | break; | ||
705 | case NL80211_IFTYPE_AP: | ||
706 | case NL80211_IFTYPE_AP_VLAN: | ||
707 | case NL80211_IFTYPE_WDS: | ||
708 | case NL80211_IFTYPE_MESH_POINT: | ||
709 | /* bridging OK */ | ||
710 | break; | ||
711 | case NL80211_IFTYPE_MONITOR: | ||
712 | /* monitor can't bridge anyway */ | ||
713 | break; | ||
714 | case NL80211_IFTYPE_UNSPECIFIED: | ||
715 | case __NL80211_IFTYPE_AFTER_LAST: | ||
716 | /* not happening */ | ||
717 | break; | ||
718 | } | ||
719 | } | ||
720 | |||
685 | return err; | 721 | return err; |
686 | } | 722 | } |
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c index 41abcbdc5fb9..29091ac9f989 100644 --- a/net/wireless/wext-compat.c +++ b/net/wireless/wext-compat.c | |||
@@ -437,6 +437,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
437 | { | 437 | { |
438 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 438 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
439 | int err, i; | 439 | int err, i; |
440 | bool rejoin = false; | ||
440 | 441 | ||
441 | if (!wdev->wext.keys) { | 442 | if (!wdev->wext.keys) { |
442 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), | 443 | wdev->wext.keys = kzalloc(sizeof(*wdev->wext.keys), |
@@ -466,8 +467,24 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
466 | 467 | ||
467 | if (remove) { | 468 | if (remove) { |
468 | err = 0; | 469 | err = 0; |
469 | if (wdev->current_bss) | 470 | if (wdev->current_bss) { |
471 | /* | ||
472 | * If removing the current TX key, we will need to | ||
473 | * join a new IBSS without the privacy bit clear. | ||
474 | */ | ||
475 | if (idx == wdev->wext.default_key && | ||
476 | wdev->iftype == NL80211_IFTYPE_ADHOC) { | ||
477 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | ||
478 | rejoin = true; | ||
479 | } | ||
470 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); | 480 | err = rdev->ops->del_key(&rdev->wiphy, dev, idx, addr); |
481 | } | ||
482 | /* | ||
483 | * Applications using wireless extensions expect to be | ||
484 | * able to delete keys that don't exist, so allow that. | ||
485 | */ | ||
486 | if (err == -ENOENT) | ||
487 | err = 0; | ||
471 | if (!err) { | 488 | if (!err) { |
472 | if (!addr) { | 489 | if (!addr) { |
473 | wdev->wext.keys->params[idx].key_len = 0; | 490 | wdev->wext.keys->params[idx].key_len = 0; |
@@ -478,12 +495,9 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
478 | else if (idx == wdev->wext.default_mgmt_key) | 495 | else if (idx == wdev->wext.default_mgmt_key) |
479 | wdev->wext.default_mgmt_key = -1; | 496 | wdev->wext.default_mgmt_key = -1; |
480 | } | 497 | } |
481 | /* | 498 | |
482 | * Applications using wireless extensions expect to be | 499 | if (!err && rejoin) |
483 | * able to delete keys that don't exist, so allow that. | 500 | err = cfg80211_ibss_wext_join(rdev, wdev); |
484 | */ | ||
485 | if (err == -ENOENT) | ||
486 | return 0; | ||
487 | 501 | ||
488 | return err; | 502 | return err; |
489 | } | 503 | } |
@@ -511,11 +525,25 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
511 | if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || | 525 | if ((params->cipher == WLAN_CIPHER_SUITE_WEP40 || |
512 | params->cipher == WLAN_CIPHER_SUITE_WEP104) && | 526 | params->cipher == WLAN_CIPHER_SUITE_WEP104) && |
513 | (tx_key || (!addr && wdev->wext.default_key == -1))) { | 527 | (tx_key || (!addr && wdev->wext.default_key == -1))) { |
514 | if (wdev->current_bss) | 528 | if (wdev->current_bss) { |
529 | /* | ||
530 | * If we are getting a new TX key from not having | ||
531 | * had one before we need to join a new IBSS with | ||
532 | * the privacy bit set. | ||
533 | */ | ||
534 | if (wdev->iftype == NL80211_IFTYPE_ADHOC && | ||
535 | wdev->wext.default_key == -1) { | ||
536 | __cfg80211_leave_ibss(rdev, wdev->netdev, true); | ||
537 | rejoin = true; | ||
538 | } | ||
515 | err = rdev->ops->set_default_key(&rdev->wiphy, | 539 | err = rdev->ops->set_default_key(&rdev->wiphy, |
516 | dev, idx); | 540 | dev, idx); |
517 | if (!err) | 541 | } |
542 | if (!err) { | ||
518 | wdev->wext.default_key = idx; | 543 | wdev->wext.default_key = idx; |
544 | if (rejoin) | ||
545 | err = cfg80211_ibss_wext_join(rdev, wdev); | ||
546 | } | ||
519 | return err; | 547 | return err; |
520 | } | 548 | } |
521 | 549 | ||
@@ -539,10 +567,13 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev, | |||
539 | { | 567 | { |
540 | int err; | 568 | int err; |
541 | 569 | ||
570 | /* devlist mutex needed for possible IBSS re-join */ | ||
571 | mutex_lock(&rdev->devlist_mtx); | ||
542 | wdev_lock(dev->ieee80211_ptr); | 572 | wdev_lock(dev->ieee80211_ptr); |
543 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, | 573 | err = __cfg80211_set_encryption(rdev, dev, addr, remove, |
544 | tx_key, idx, params); | 574 | tx_key, idx, params); |
545 | wdev_unlock(dev->ieee80211_ptr); | 575 | wdev_unlock(dev->ieee80211_ptr); |
576 | mutex_unlock(&rdev->devlist_mtx); | ||
546 | 577 | ||
547 | return err; | 578 | return err; |
548 | } | 579 | } |