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 | } |
