diff options
40 files changed, 1341 insertions, 176 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 7134c40d6a69..53ea439aff48 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -431,7 +431,9 @@ struct ath5k_tx_status { | |||
431 | u16 ts_seqnum; | 431 | u16 ts_seqnum; |
432 | u16 ts_tstamp; | 432 | u16 ts_tstamp; |
433 | u8 ts_status; | 433 | u8 ts_status; |
434 | u8 ts_rate; | 434 | u8 ts_rate[4]; |
435 | u8 ts_retry[4]; | ||
436 | u8 ts_final_idx; | ||
435 | s8 ts_rssi; | 437 | s8 ts_rssi; |
436 | u8 ts_shortretry; | 438 | u8 ts_shortretry; |
437 | u8 ts_longretry; | 439 | u8 ts_longretry; |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index c151588aa484..9b95c4049b31 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -541,6 +541,12 @@ ath5k_pci_probe(struct pci_dev *pdev, | |||
541 | goto err_irq; | 541 | goto err_irq; |
542 | } | 542 | } |
543 | 543 | ||
544 | /* set up multi-rate retry capabilities */ | ||
545 | if (sc->ah->ah_version == AR5K_AR5212) { | ||
546 | hw->max_altrates = 3; | ||
547 | hw->max_altrate_tries = 11; | ||
548 | } | ||
549 | |||
544 | /* Finish private driver data initialization */ | 550 | /* Finish private driver data initialization */ |
545 | ret = ath5k_attach(pdev, hw); | 551 | ret = ath5k_attach(pdev, hw); |
546 | if (ret) | 552 | if (ret) |
@@ -1173,7 +1179,9 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1173 | struct sk_buff *skb = bf->skb; | 1179 | struct sk_buff *skb = bf->skb; |
1174 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1180 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1175 | unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; | 1181 | unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; |
1176 | int ret; | 1182 | struct ieee80211_rate *rate; |
1183 | unsigned int mrr_rate[3], mrr_tries[3]; | ||
1184 | int i, ret; | ||
1177 | 1185 | ||
1178 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; | 1186 | flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; |
1179 | 1187 | ||
@@ -1188,7 +1196,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1188 | 1196 | ||
1189 | if (info->control.hw_key) { | 1197 | if (info->control.hw_key) { |
1190 | keyidx = info->control.hw_key->hw_key_idx; | 1198 | keyidx = info->control.hw_key->hw_key_idx; |
1191 | pktlen += info->control.icv_len; | 1199 | pktlen += info->control.hw_key->icv_len; |
1192 | } | 1200 | } |
1193 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, | 1201 | ret = ah->ah_setup_tx_desc(ah, ds, pktlen, |
1194 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, | 1202 | ieee80211_get_hdrlen_from_skb(skb), AR5K_PKT_TYPE_NORMAL, |
@@ -1198,6 +1206,22 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) | |||
1198 | if (ret) | 1206 | if (ret) |
1199 | goto err_unmap; | 1207 | goto err_unmap; |
1200 | 1208 | ||
1209 | memset(mrr_rate, 0, sizeof(mrr_rate)); | ||
1210 | memset(mrr_tries, 0, sizeof(mrr_tries)); | ||
1211 | for (i = 0; i < 3; i++) { | ||
1212 | rate = ieee80211_get_alt_retry_rate(sc->hw, info, i); | ||
1213 | if (!rate) | ||
1214 | break; | ||
1215 | |||
1216 | mrr_rate[i] = rate->hw_value; | ||
1217 | mrr_tries[i] = info->control.retries[i].limit; | ||
1218 | } | ||
1219 | |||
1220 | ah->ah_setup_mrr_tx_desc(ah, ds, | ||
1221 | mrr_rate[0], mrr_tries[0], | ||
1222 | mrr_rate[1], mrr_tries[1], | ||
1223 | mrr_rate[2], mrr_tries[2]); | ||
1224 | |||
1201 | ds->ds_link = 0; | 1225 | ds->ds_link = 0; |
1202 | ds->ds_data = bf->skbaddr; | 1226 | ds->ds_data = bf->skbaddr; |
1203 | 1227 | ||
@@ -1814,7 +1838,7 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1814 | struct ath5k_desc *ds; | 1838 | struct ath5k_desc *ds; |
1815 | struct sk_buff *skb; | 1839 | struct sk_buff *skb; |
1816 | struct ieee80211_tx_info *info; | 1840 | struct ieee80211_tx_info *info; |
1817 | int ret; | 1841 | int i, ret; |
1818 | 1842 | ||
1819 | spin_lock(&txq->lock); | 1843 | spin_lock(&txq->lock); |
1820 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { | 1844 | list_for_each_entry_safe(bf, bf0, &txq->q, list) { |
@@ -1836,7 +1860,25 @@ ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) | |||
1836 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, | 1860 | pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, |
1837 | PCI_DMA_TODEVICE); | 1861 | PCI_DMA_TODEVICE); |
1838 | 1862 | ||
1839 | info->status.retry_count = ts.ts_shortretry + ts.ts_longretry / 6; | 1863 | memset(&info->status, 0, sizeof(info->status)); |
1864 | info->tx_rate_idx = ath5k_hw_to_driver_rix(sc, | ||
1865 | ts.ts_rate[ts.ts_final_idx]); | ||
1866 | info->status.retry_count = ts.ts_longretry; | ||
1867 | |||
1868 | for (i = 0; i < 4; i++) { | ||
1869 | struct ieee80211_tx_altrate *r = | ||
1870 | &info->status.retries[i]; | ||
1871 | |||
1872 | if (ts.ts_rate[i]) { | ||
1873 | r->rate_idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); | ||
1874 | r->limit = ts.ts_retry[i]; | ||
1875 | } else { | ||
1876 | r->rate_idx = -1; | ||
1877 | r->limit = 0; | ||
1878 | } | ||
1879 | } | ||
1880 | |||
1881 | info->status.excessive_retries = 0; | ||
1840 | if (unlikely(ts.ts_status)) { | 1882 | if (unlikely(ts.ts_status)) { |
1841 | sc->ll_stats.dot11ACKFailureCount++; | 1883 | sc->ll_stats.dot11ACKFailureCount++; |
1842 | if (ts.ts_status & AR5K_TXERR_XRETRY) | 1884 | if (ts.ts_status & AR5K_TXERR_XRETRY) |
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c index d45b90a6e06c..dd1374052ba9 100644 --- a/drivers/net/wireless/ath5k/desc.c +++ b/drivers/net/wireless/ath5k/desc.c | |||
@@ -318,6 +318,15 @@ ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
318 | return 0; | 318 | return 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | /* no mrr support for cards older than 5212 */ | ||
322 | static int | ||
323 | ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, | ||
324 | unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, | ||
325 | u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) | ||
326 | { | ||
327 | return 0; | ||
328 | } | ||
329 | |||
321 | /* | 330 | /* |
322 | * Proccess the tx status descriptor on 5210/5211 | 331 | * Proccess the tx status descriptor on 5210/5211 |
323 | */ | 332 | */ |
@@ -352,8 +361,10 @@ static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, | |||
352 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); | 361 | AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); |
353 | ts->ts_antenna = 1; | 362 | ts->ts_antenna = 1; |
354 | ts->ts_status = 0; | 363 | ts->ts_status = 0; |
355 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_0, | 364 | ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, |
356 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); | 365 | AR5K_2W_TX_DESC_CTL0_XMIT_RATE); |
366 | ts->ts_retry[0] = ts->ts_longretry; | ||
367 | ts->ts_final_idx = 0; | ||
357 | 368 | ||
358 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { | 369 | if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { |
359 | if (tx_status->tx_status_0 & | 370 | if (tx_status->tx_status_0 & |
@@ -405,29 +416,43 @@ static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, | |||
405 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; | 416 | AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; |
406 | ts->ts_status = 0; | 417 | ts->ts_status = 0; |
407 | 418 | ||
408 | switch (AR5K_REG_MS(tx_status->tx_status_1, | 419 | ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, |
409 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX)) { | 420 | AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); |
410 | case 0: | 421 | |
411 | ts->ts_rate = tx_ctl->tx_control_3 & | 422 | /* The longretry counter has the number of un-acked retries |
412 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; | 423 | * for the final rate. To get the total number of retries |
413 | break; | 424 | * we have to add the retry counters for the other rates |
425 | * as well | ||
426 | */ | ||
427 | ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; | ||
428 | switch (ts->ts_final_idx) { | ||
429 | case 3: | ||
430 | ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
431 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
432 | |||
433 | ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
434 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
435 | ts->ts_longretry += ts->ts_retry[2]; | ||
436 | /* fall through */ | ||
437 | case 2: | ||
438 | ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
439 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | ||
440 | |||
441 | ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
442 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | ||
443 | ts->ts_longretry += ts->ts_retry[1]; | ||
444 | /* fall through */ | ||
414 | case 1: | 445 | case 1: |
415 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | 446 | ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, |
416 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); | 447 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); |
417 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | 448 | |
449 | ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, | ||
418 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); | 450 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); |
419 | break; | 451 | ts->ts_longretry += ts->ts_retry[0]; |
420 | case 2: | 452 | /* fall through */ |
421 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | 453 | case 0: |
422 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); | 454 | ts->ts_rate[0] = tx_ctl->tx_control_3 & |
423 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | 455 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; |
424 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); | ||
425 | break; | ||
426 | case 3: | ||
427 | ts->ts_rate = AR5K_REG_MS(tx_ctl->tx_control_3, | ||
428 | AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); | ||
429 | ts->ts_longretry += AR5K_REG_MS(tx_ctl->tx_control_2, | ||
430 | AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3); | ||
431 | break; | 456 | break; |
432 | } | 457 | } |
433 | 458 | ||
@@ -653,7 +678,7 @@ int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) | |||
653 | } else { | 678 | } else { |
654 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; | 679 | ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; |
655 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; | 680 | ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; |
656 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; | 681 | ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; |
657 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; | 682 | ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; |
658 | } | 683 | } |
659 | 684 | ||
diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index 0e897c276858..accace5f7efb 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h | |||
@@ -854,7 +854,7 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, | |||
854 | u8 rxchainmask, | 854 | u8 rxchainmask, |
855 | bool longcal, | 855 | bool longcal, |
856 | bool *isCalDone); | 856 | bool *isCalDone); |
857 | int16_t ath9k_hw_getchan_noise(struct ath_hal *ah, | 857 | s16 ath9k_hw_getchan_noise(struct ath_hal *ah, |
858 | struct ath9k_channel *chan); | 858 | struct ath9k_channel *chan); |
859 | void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, | 859 | void ath9k_hw_write_associd(struct ath_hal *ah, const u8 *bssid, |
860 | u16 assocId); | 860 | u16 assocId); |
diff --git a/drivers/net/wireless/ath9k/beacon.c b/drivers/net/wireless/ath9k/beacon.c index eedb465d25d3..9e15c30bbc06 100644 --- a/drivers/net/wireless/ath9k/beacon.c +++ b/drivers/net/wireless/ath9k/beacon.c | |||
@@ -129,7 +129,7 @@ static void ath_beacon_setup(struct ath_softc *sc, | |||
129 | ds /* first descriptor */ | 129 | ds /* first descriptor */ |
130 | ); | 130 | ); |
131 | 131 | ||
132 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | 132 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
133 | series[0].Tries = 1; | 133 | series[0].Tries = 1; |
134 | series[0].Rate = rate; | 134 | series[0].Rate = rate; |
135 | series[0].ChSel = sc->sc_tx_chainmask; | 135 | series[0].ChSel = sc->sc_tx_chainmask; |
@@ -282,7 +282,7 @@ int ath_beaconq_setup(struct ath_hal *ah) | |||
282 | { | 282 | { |
283 | struct ath9k_tx_queue_info qi; | 283 | struct ath9k_tx_queue_info qi; |
284 | 284 | ||
285 | memzero(&qi, sizeof(qi)); | 285 | memset(&qi, 0, sizeof(qi)); |
286 | qi.tqi_aifs = 1; | 286 | qi.tqi_aifs = 1; |
287 | qi.tqi_cwmin = 0; | 287 | qi.tqi_cwmin = 0; |
288 | qi.tqi_cwmax = 0; | 288 | qi.tqi_cwmax = 0; |
@@ -662,7 +662,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
662 | else | 662 | else |
663 | av_opmode = sc->sc_ah->ah_opmode; | 663 | av_opmode = sc->sc_ah->ah_opmode; |
664 | 664 | ||
665 | memzero(&conf, sizeof(struct ath_beacon_config)); | 665 | memset(&conf, 0, sizeof(struct ath_beacon_config)); |
666 | 666 | ||
667 | conf.beacon_interval = sc->hw->conf.beacon_int ? | 667 | conf.beacon_interval = sc->hw->conf.beacon_int ? |
668 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; | 668 | sc->hw->conf.beacon_int : ATH_DEFAULT_BINTVAL; |
@@ -738,7 +738,7 @@ void ath_beacon_config(struct ath_softc *sc, int if_id) | |||
738 | } | 738 | } |
739 | } while (nexttbtt < tsftu); | 739 | } while (nexttbtt < tsftu); |
740 | #undef FUDGE | 740 | #undef FUDGE |
741 | memzero(&bs, sizeof(bs)); | 741 | memset(&bs, 0, sizeof(bs)); |
742 | bs.bs_intval = intval; | 742 | bs.bs_intval = intval; |
743 | bs.bs_nexttbtt = nexttbtt; | 743 | bs.bs_nexttbtt = nexttbtt; |
744 | bs.bs_dtimperiod = dtimperiod*intval; | 744 | bs.bs_dtimperiod = dtimperiod*intval; |
diff --git a/drivers/net/wireless/ath9k/core.c b/drivers/net/wireless/ath9k/core.c index 6c433a4d003e..c5033f6f42ac 100644 --- a/drivers/net/wireless/ath9k/core.c +++ b/drivers/net/wireless/ath9k/core.c | |||
@@ -65,7 +65,7 @@ static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) | |||
65 | for (i = 0; i < rt->rateCount; i++) | 65 | for (i = 0; i < rt->rateCount; i++) |
66 | sc->sc_rixmap[rt->info[i].rateCode] = (u8) i; | 66 | sc->sc_rixmap[rt->info[i].rateCode] = (u8) i; |
67 | 67 | ||
68 | memzero(sc->sc_hwmap, sizeof(sc->sc_hwmap)); | 68 | memset(sc->sc_hwmap, 0, sizeof(sc->sc_hwmap)); |
69 | for (i = 0; i < 256; i++) { | 69 | for (i = 0; i < 256; i++) { |
70 | u8 ix = rt->rateCodeToIndex[i]; | 70 | u8 ix = rt->rateCodeToIndex[i]; |
71 | 71 | ||
@@ -288,8 +288,6 @@ static int ath_stop(struct ath_softc *sc) | |||
288 | * hardware is gone (invalid). | 288 | * hardware is gone (invalid). |
289 | */ | 289 | */ |
290 | 290 | ||
291 | if (!(sc->sc_flags & SC_OP_INVALID)) | ||
292 | ath9k_hw_set_interrupts(ah, 0); | ||
293 | ath_draintxq(sc, false); | 291 | ath_draintxq(sc, false); |
294 | if (!(sc->sc_flags & SC_OP_INVALID)) { | 292 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
295 | ath_stoprecv(sc); | 293 | ath_stoprecv(sc); |
@@ -419,7 +417,7 @@ static void ath_chainmask_sel_init(struct ath_softc *sc, struct ath_node *an) | |||
419 | { | 417 | { |
420 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; | 418 | struct ath_chainmask_sel *cm = &an->an_chainmask_sel; |
421 | 419 | ||
422 | memzero(cm, sizeof(struct ath_chainmask_sel)); | 420 | memset(cm, 0, sizeof(struct ath_chainmask_sel)); |
423 | 421 | ||
424 | cm->cur_tx_mask = sc->sc_tx_chainmask; | 422 | cm->cur_tx_mask = sc->sc_tx_chainmask; |
425 | cm->cur_rx_mask = sc->sc_rx_chainmask; | 423 | cm->cur_rx_mask = sc->sc_rx_chainmask; |
@@ -492,6 +490,122 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht) | |||
492 | __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); | 490 | __func__, sc->sc_tx_chainmask, sc->sc_rx_chainmask); |
493 | } | 491 | } |
494 | 492 | ||
493 | /*******/ | ||
494 | /* ANI */ | ||
495 | /*******/ | ||
496 | |||
497 | /* | ||
498 | * This routine performs the periodic noise floor calibration function | ||
499 | * that is used to adjust and optimize the chip performance. This | ||
500 | * takes environmental changes (location, temperature) into account. | ||
501 | * When the task is complete, it reschedules itself depending on the | ||
502 | * appropriate interval that was calculated. | ||
503 | */ | ||
504 | |||
505 | static void ath_ani_calibrate(unsigned long data) | ||
506 | { | ||
507 | struct ath_softc *sc; | ||
508 | struct ath_hal *ah; | ||
509 | bool longcal = false; | ||
510 | bool shortcal = false; | ||
511 | bool aniflag = false; | ||
512 | unsigned int timestamp = jiffies_to_msecs(jiffies); | ||
513 | u32 cal_interval; | ||
514 | |||
515 | sc = (struct ath_softc *)data; | ||
516 | ah = sc->sc_ah; | ||
517 | |||
518 | /* | ||
519 | * don't calibrate when we're scanning. | ||
520 | * we are most likely not on our home channel. | ||
521 | */ | ||
522 | if (sc->rx_filter & FIF_BCN_PRBRESP_PROMISC) | ||
523 | return; | ||
524 | |||
525 | /* Long calibration runs independently of short calibration. */ | ||
526 | if ((timestamp - sc->sc_ani.sc_longcal_timer) >= ATH_LONG_CALINTERVAL) { | ||
527 | longcal = true; | ||
528 | DPRINTF(sc, ATH_DBG_ANI, "%s: longcal @%lu\n", | ||
529 | __func__, jiffies); | ||
530 | sc->sc_ani.sc_longcal_timer = timestamp; | ||
531 | } | ||
532 | |||
533 | /* Short calibration applies only while sc_caldone is false */ | ||
534 | if (!sc->sc_ani.sc_caldone) { | ||
535 | if ((timestamp - sc->sc_ani.sc_shortcal_timer) >= | ||
536 | ATH_SHORT_CALINTERVAL) { | ||
537 | shortcal = true; | ||
538 | DPRINTF(sc, ATH_DBG_ANI, "%s: shortcal @%lu\n", | ||
539 | __func__, jiffies); | ||
540 | sc->sc_ani.sc_shortcal_timer = timestamp; | ||
541 | sc->sc_ani.sc_resetcal_timer = timestamp; | ||
542 | } | ||
543 | } else { | ||
544 | if ((timestamp - sc->sc_ani.sc_resetcal_timer) >= | ||
545 | ATH_RESTART_CALINTERVAL) { | ||
546 | ath9k_hw_reset_calvalid(ah, ah->ah_curchan, | ||
547 | &sc->sc_ani.sc_caldone); | ||
548 | if (sc->sc_ani.sc_caldone) | ||
549 | sc->sc_ani.sc_resetcal_timer = timestamp; | ||
550 | } | ||
551 | } | ||
552 | |||
553 | /* Verify whether we must check ANI */ | ||
554 | if ((timestamp - sc->sc_ani.sc_checkani_timer) >= | ||
555 | ATH_ANI_POLLINTERVAL) { | ||
556 | aniflag = true; | ||
557 | sc->sc_ani.sc_checkani_timer = timestamp; | ||
558 | } | ||
559 | |||
560 | /* Skip all processing if there's nothing to do. */ | ||
561 | if (longcal || shortcal || aniflag) { | ||
562 | /* Call ANI routine if necessary */ | ||
563 | if (aniflag) | ||
564 | ath9k_hw_ani_monitor(ah, &sc->sc_halstats, | ||
565 | ah->ah_curchan); | ||
566 | |||
567 | /* Perform calibration if necessary */ | ||
568 | if (longcal || shortcal) { | ||
569 | bool iscaldone = false; | ||
570 | |||
571 | if (ath9k_hw_calibrate(ah, ah->ah_curchan, | ||
572 | sc->sc_rx_chainmask, longcal, | ||
573 | &iscaldone)) { | ||
574 | if (longcal) | ||
575 | sc->sc_ani.sc_noise_floor = | ||
576 | ath9k_hw_getchan_noise(ah, | ||
577 | ah->ah_curchan); | ||
578 | |||
579 | DPRINTF(sc, ATH_DBG_ANI, | ||
580 | "%s: calibrate chan %u/%x nf: %d\n", | ||
581 | __func__, | ||
582 | ah->ah_curchan->channel, | ||
583 | ah->ah_curchan->channelFlags, | ||
584 | sc->sc_ani.sc_noise_floor); | ||
585 | } else { | ||
586 | DPRINTF(sc, ATH_DBG_ANY, | ||
587 | "%s: calibrate chan %u/%x failed\n", | ||
588 | __func__, | ||
589 | ah->ah_curchan->channel, | ||
590 | ah->ah_curchan->channelFlags); | ||
591 | } | ||
592 | sc->sc_ani.sc_caldone = iscaldone; | ||
593 | } | ||
594 | } | ||
595 | |||
596 | /* | ||
597 | * Set timer interval based on previous results. | ||
598 | * The interval must be the shortest necessary to satisfy ANI, | ||
599 | * short calibration and long calibration. | ||
600 | */ | ||
601 | |||
602 | cal_interval = ATH_ANI_POLLINTERVAL; | ||
603 | if (!sc->sc_ani.sc_caldone) | ||
604 | cal_interval = min(cal_interval, (u32)ATH_SHORT_CALINTERVAL); | ||
605 | |||
606 | mod_timer(&sc->sc_ani.timer, jiffies + msecs_to_jiffies(cal_interval)); | ||
607 | } | ||
608 | |||
495 | /******************/ | 609 | /******************/ |
496 | /* VAP management */ | 610 | /* VAP management */ |
497 | /******************/ | 611 | /******************/ |
@@ -528,7 +642,7 @@ int ath_vap_attach(struct ath_softc *sc, | |||
528 | if (avp == NULL) | 642 | if (avp == NULL) |
529 | return -ENOMEM; | 643 | return -ENOMEM; |
530 | 644 | ||
531 | memzero(avp, sizeof(struct ath_vap)); | 645 | memset(avp, 0, sizeof(struct ath_vap)); |
532 | avp->av_if_data = if_data; | 646 | avp->av_if_data = if_data; |
533 | /* Set the VAP opmode */ | 647 | /* Set the VAP opmode */ |
534 | avp->av_opmode = opmode; | 648 | avp->av_opmode = opmode; |
@@ -678,12 +792,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
678 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) | 792 | if (ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) |
679 | sc->sc_imask |= ATH9K_INT_CST; | 793 | sc->sc_imask |= ATH9K_INT_CST; |
680 | 794 | ||
681 | /* Note: We disable MIB interrupts for now as we don't yet | ||
682 | * handle processing ANI, otherwise you will get an interrupt | ||
683 | * storm after about 7 hours of usage making the system unusable | ||
684 | * with huge latency. Once we do have ANI processing included | ||
685 | * we can re-enable this interrupt. */ | ||
686 | #if 0 | ||
687 | /* | 795 | /* |
688 | * Enable MIB interrupts when there are hardware phy counters. | 796 | * Enable MIB interrupts when there are hardware phy counters. |
689 | * Note we only do this (at the moment) for station mode. | 797 | * Note we only do this (at the moment) for station mode. |
@@ -692,7 +800,6 @@ int ath_open(struct ath_softc *sc, struct ath9k_channel *initial_chan) | |||
692 | ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || | 800 | ((sc->sc_ah->ah_opmode == ATH9K_M_STA) || |
693 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) | 801 | (sc->sc_ah->ah_opmode == ATH9K_M_IBSS))) |
694 | sc->sc_imask |= ATH9K_INT_MIB; | 802 | sc->sc_imask |= ATH9K_INT_MIB; |
695 | #endif | ||
696 | /* | 803 | /* |
697 | * Some hardware processes the TIM IE and fires an | 804 | * Some hardware processes the TIM IE and fires an |
698 | * interrupt when the TIM bit is set. For hardware | 805 | * interrupt when the TIM bit is set. For hardware |
@@ -993,6 +1100,10 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
993 | } | 1100 | } |
994 | sc->sc_ah = ah; | 1101 | sc->sc_ah = ah; |
995 | 1102 | ||
1103 | /* Initializes the noise floor to a reasonable default value. | ||
1104 | * Later on this will be updated during ANI processing. */ | ||
1105 | sc->sc_ani.sc_noise_floor = ATH_DEFAULT_NOISE_FLOOR; | ||
1106 | |||
996 | /* Get the hardware key cache size. */ | 1107 | /* Get the hardware key cache size. */ |
997 | sc->sc_keymax = ah->ah_caps.keycache_size; | 1108 | sc->sc_keymax = ah->ah_caps.keycache_size; |
998 | if (sc->sc_keymax > ATH_KEYMAX) { | 1109 | if (sc->sc_keymax > ATH_KEYMAX) { |
@@ -1100,6 +1211,8 @@ int ath_init(u16 devid, struct ath_softc *sc) | |||
1100 | goto bad2; | 1211 | goto bad2; |
1101 | } | 1212 | } |
1102 | 1213 | ||
1214 | setup_timer(&sc->sc_ani.timer, ath_ani_calibrate, (unsigned long)sc); | ||
1215 | |||
1103 | sc->sc_rc = ath_rate_attach(ah); | 1216 | sc->sc_rc = ath_rate_attach(ah); |
1104 | if (sc->sc_rc == NULL) { | 1217 | if (sc->sc_rc == NULL) { |
1105 | error = -EIO; | 1218 | error = -EIO; |
@@ -1221,7 +1334,7 @@ struct ath_node *ath_node_attach(struct ath_softc *sc, u8 *addr, int if_id) | |||
1221 | an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC); | 1334 | an = kmalloc(sizeof(struct ath_node), GFP_ATOMIC); |
1222 | if (an == NULL) | 1335 | if (an == NULL) |
1223 | return NULL; | 1336 | return NULL; |
1224 | memzero(an, sizeof(*an)); | 1337 | memset(an, 0, sizeof(*an)); |
1225 | 1338 | ||
1226 | an->an_sc = sc; | 1339 | an->an_sc = sc; |
1227 | memcpy(an->an_addr, addr, ETH_ALEN); | 1340 | memcpy(an->an_addr, addr, ETH_ALEN); |
@@ -1608,7 +1721,7 @@ int ath_descdma_setup(struct ath_softc *sc, | |||
1608 | error = -ENOMEM; | 1721 | error = -ENOMEM; |
1609 | goto fail2; | 1722 | goto fail2; |
1610 | } | 1723 | } |
1611 | memzero(bf, bsize); | 1724 | memset(bf, 0, bsize); |
1612 | dd->dd_bufptr = bf; | 1725 | dd->dd_bufptr = bf; |
1613 | 1726 | ||
1614 | INIT_LIST_HEAD(head); | 1727 | INIT_LIST_HEAD(head); |
@@ -1640,7 +1753,7 @@ fail2: | |||
1640 | pci_free_consistent(sc->pdev, | 1753 | pci_free_consistent(sc->pdev, |
1641 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); | 1754 | dd->dd_desc_len, dd->dd_desc, dd->dd_desc_paddr); |
1642 | fail: | 1755 | fail: |
1643 | memzero(dd, sizeof(*dd)); | 1756 | memset(dd, 0, sizeof(*dd)); |
1644 | return error; | 1757 | return error; |
1645 | #undef ATH_DESC_4KB_BOUND_CHECK | 1758 | #undef ATH_DESC_4KB_BOUND_CHECK |
1646 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED | 1759 | #undef ATH_DESC_4KB_BOUND_NUM_SKIPPED |
@@ -1665,7 +1778,7 @@ void ath_descdma_cleanup(struct ath_softc *sc, | |||
1665 | 1778 | ||
1666 | INIT_LIST_HEAD(head); | 1779 | INIT_LIST_HEAD(head); |
1667 | kfree(dd->dd_bufptr); | 1780 | kfree(dd->dd_bufptr); |
1668 | memzero(dd, sizeof(*dd)); | 1781 | memset(dd, 0, sizeof(*dd)); |
1669 | } | 1782 | } |
1670 | 1783 | ||
1671 | /*************/ | 1784 | /*************/ |
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 872f0c5a0b0e..cb3e61e57c4d 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -84,9 +84,6 @@ struct ath_node; | |||
84 | #define TSF_TO_TU(_h,_l) \ | 84 | #define TSF_TO_TU(_h,_l) \ |
85 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) | 85 | ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) |
86 | 86 | ||
87 | /* XXX: remove */ | ||
88 | #define memzero(_buf, _len) memset(_buf, 0, _len) | ||
89 | |||
90 | #define ATH9K_BH_STATUS_INTACT 0 | 87 | #define ATH9K_BH_STATUS_INTACT 0 |
91 | #define ATH9K_BH_STATUS_CHANGE 1 | 88 | #define ATH9K_BH_STATUS_CHANGE 1 |
92 | 89 | ||
@@ -184,7 +181,7 @@ void ath_update_chainmask(struct ath_softc *sc, int is_ht); | |||
184 | (_bf)->bf_lastbf = NULL; \ | 181 | (_bf)->bf_lastbf = NULL; \ |
185 | (_bf)->bf_lastfrm = NULL; \ | 182 | (_bf)->bf_lastfrm = NULL; \ |
186 | (_bf)->bf_next = NULL; \ | 183 | (_bf)->bf_next = NULL; \ |
187 | memzero(&((_bf)->bf_state), \ | 184 | memset(&((_bf)->bf_state), 0, \ |
188 | sizeof(struct ath_buf_state)); \ | 185 | sizeof(struct ath_buf_state)); \ |
189 | } while (0) | 186 | } while (0) |
190 | 187 | ||
@@ -312,7 +309,7 @@ void ath_descdma_cleanup(struct ath_softc *sc, | |||
312 | #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ | 309 | #define ATH_RX_TIMEOUT 40 /* 40 milliseconds */ |
313 | #define WME_NUM_TID 16 | 310 | #define WME_NUM_TID 16 |
314 | #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ | 311 | #define IEEE80211_BAR_CTL_TID_M 0xF000 /* tid mask */ |
315 | #define IEEE80211_BAR_CTL_TID_S 2 /* tid shift */ | 312 | #define IEEE80211_BAR_CTL_TID_S 12 /* tid shift */ |
316 | 313 | ||
317 | enum ATH_RX_TYPE { | 314 | enum ATH_RX_TYPE { |
318 | ATH_RX_NON_CONSUMED = 0, | 315 | ATH_RX_NON_CONSUMED = 0, |
@@ -803,6 +800,28 @@ void ath_slow_ant_div(struct ath_antdiv *antdiv, | |||
803 | struct ath_rx_status *rx_stats); | 800 | struct ath_rx_status *rx_stats); |
804 | void ath_setdefantenna(void *sc, u32 antenna); | 801 | void ath_setdefantenna(void *sc, u32 antenna); |
805 | 802 | ||
803 | /*******/ | ||
804 | /* ANI */ | ||
805 | /*******/ | ||
806 | |||
807 | /* ANI values for STA only. | ||
808 | FIXME: Add appropriate values for AP later */ | ||
809 | |||
810 | #define ATH_ANI_POLLINTERVAL 100 /* 100 milliseconds between ANI poll */ | ||
811 | #define ATH_SHORT_CALINTERVAL 1000 /* 1 second between calibrations */ | ||
812 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds between calibrations */ | ||
813 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes between calibrations */ | ||
814 | |||
815 | struct ath_ani { | ||
816 | bool sc_caldone; | ||
817 | int16_t sc_noise_floor; | ||
818 | unsigned int sc_longcal_timer; | ||
819 | unsigned int sc_shortcal_timer; | ||
820 | unsigned int sc_resetcal_timer; | ||
821 | unsigned int sc_checkani_timer; | ||
822 | struct timer_list timer; | ||
823 | }; | ||
824 | |||
806 | /********************/ | 825 | /********************/ |
807 | /* LED Control */ | 826 | /* LED Control */ |
808 | /********************/ | 827 | /********************/ |
@@ -1031,6 +1050,9 @@ struct ath_softc { | |||
1031 | 1050 | ||
1032 | /* Rfkill */ | 1051 | /* Rfkill */ |
1033 | struct ath_rfkill rf_kill; | 1052 | struct ath_rfkill rf_kill; |
1053 | |||
1054 | /* ANI */ | ||
1055 | struct ath_ani sc_ani; | ||
1034 | }; | 1056 | }; |
1035 | 1057 | ||
1036 | int ath_init(u16 devid, struct ath_softc *sc); | 1058 | int ath_init(u16 devid, struct ath_softc *sc); |
diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 272c75816609..62e44a0ef996 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c | |||
@@ -329,7 +329,7 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) | |||
329 | ah->ah_config.ofdm_trig_high = 500; | 329 | ah->ah_config.ofdm_trig_high = 500; |
330 | ah->ah_config.cck_trig_high = 200; | 330 | ah->ah_config.cck_trig_high = 200; |
331 | ah->ah_config.cck_trig_low = 100; | 331 | ah->ah_config.cck_trig_low = 100; |
332 | ah->ah_config.enable_ani = 0; | 332 | ah->ah_config.enable_ani = 1; |
333 | ah->ah_config.noise_immunity_level = 4; | 333 | ah->ah_config.noise_immunity_level = 4; |
334 | ah->ah_config.ofdm_weaksignal_det = 1; | 334 | ah->ah_config.ofdm_weaksignal_det = 1; |
335 | ah->ah_config.cck_weaksignal_thr = 0; | 335 | ah->ah_config.cck_weaksignal_thr = 0; |
@@ -8405,23 +8405,48 @@ u32 ath9k_hw_mhz2ieee(struct ath_hal *ah, u32 freq, u32 flags) | |||
8405 | } | 8405 | } |
8406 | } | 8406 | } |
8407 | 8407 | ||
8408 | int16_t | 8408 | /* We can tune this as we go by monitoring really low values */ |
8409 | #define ATH9K_NF_TOO_LOW -60 | ||
8410 | |||
8411 | /* AR5416 may return very high value (like -31 dBm), in those cases the nf | ||
8412 | * is incorrect and we should use the static NF value. Later we can try to | ||
8413 | * find out why they are reporting these values */ | ||
8414 | static bool ath9k_hw_nf_in_range(struct ath_hal *ah, s16 nf) | ||
8415 | { | ||
8416 | if (nf > ATH9K_NF_TOO_LOW) { | ||
8417 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | ||
8418 | "%s: noise floor value detected (%d) is " | ||
8419 | "lower than what we think is a " | ||
8420 | "reasonable value (%d)\n", | ||
8421 | __func__, nf, ATH9K_NF_TOO_LOW); | ||
8422 | return false; | ||
8423 | } | ||
8424 | return true; | ||
8425 | } | ||
8426 | |||
8427 | s16 | ||
8409 | ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) | 8428 | ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) |
8410 | { | 8429 | { |
8411 | struct ath9k_channel *ichan; | 8430 | struct ath9k_channel *ichan; |
8431 | s16 nf; | ||
8412 | 8432 | ||
8413 | ichan = ath9k_regd_check_channel(ah, chan); | 8433 | ichan = ath9k_regd_check_channel(ah, chan); |
8414 | if (ichan == NULL) { | 8434 | if (ichan == NULL) { |
8415 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, | 8435 | DPRINTF(ah->ah_sc, ATH_DBG_NF_CAL, |
8416 | "%s: invalid channel %u/0x%x; no mapping\n", | 8436 | "%s: invalid channel %u/0x%x; no mapping\n", |
8417 | __func__, chan->channel, chan->channelFlags); | 8437 | __func__, chan->channel, chan->channelFlags); |
8418 | return 0; | 8438 | return ATH_DEFAULT_NOISE_FLOOR; |
8419 | } | 8439 | } |
8420 | if (ichan->rawNoiseFloor == 0) { | 8440 | if (ichan->rawNoiseFloor == 0) { |
8421 | enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); | 8441 | enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); |
8422 | return NOISE_FLOOR[mode]; | 8442 | nf = NOISE_FLOOR[mode]; |
8423 | } else | 8443 | } else |
8424 | return ichan->rawNoiseFloor; | 8444 | nf = ichan->rawNoiseFloor; |
8445 | |||
8446 | if (!ath9k_hw_nf_in_range(ah, nf)) | ||
8447 | nf = ATH_DEFAULT_NOISE_FLOOR; | ||
8448 | |||
8449 | return nf; | ||
8425 | } | 8450 | } |
8426 | 8451 | ||
8427 | bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting) | 8452 | bool ath9k_hw_set_tsfadjust(struct ath_hal *ah, u32 setting) |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 2caba4403167..74726990d59e 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -274,10 +274,12 @@ static void ath9k_rx_prepare(struct ath_softc *sc, | |||
274 | rx_status->mactime = status->tsf; | 274 | rx_status->mactime = status->tsf; |
275 | rx_status->band = curchan->band; | 275 | rx_status->band = curchan->band; |
276 | rx_status->freq = curchan->center_freq; | 276 | rx_status->freq = curchan->center_freq; |
277 | rx_status->noise = ATH_DEFAULT_NOISE_FLOOR; | 277 | rx_status->noise = sc->sc_ani.sc_noise_floor; |
278 | rx_status->signal = rx_status->noise + status->rssi; | 278 | rx_status->signal = rx_status->noise + status->rssi; |
279 | rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100)); | 279 | rx_status->rate_idx = ath_rate2idx(sc, (status->rateKbps / 100)); |
280 | rx_status->antenna = status->antenna; | 280 | rx_status->antenna = status->antenna; |
281 | |||
282 | /* XXX Fix me, 64 cannot be the max rssi value, rigure it out */ | ||
281 | rx_status->qual = status->rssi * 100 / 64; | 283 | rx_status->qual = status->rssi * 100 / 64; |
282 | 284 | ||
283 | if (status->flags & ATH_RX_MIC_ERROR) | 285 | if (status->flags & ATH_RX_MIC_ERROR) |
@@ -427,6 +429,11 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
427 | ath_rate_newstate(sc, avp); | 429 | ath_rate_newstate(sc, avp); |
428 | /* Update ratectrl about the new state */ | 430 | /* Update ratectrl about the new state */ |
429 | ath_rc_node_update(hw, avp->rc_node); | 431 | ath_rc_node_update(hw, avp->rc_node); |
432 | |||
433 | /* Start ANI */ | ||
434 | mod_timer(&sc->sc_ani.timer, | ||
435 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | ||
436 | |||
430 | } else { | 437 | } else { |
431 | DPRINTF(sc, ATH_DBG_CONFIG, | 438 | DPRINTF(sc, ATH_DBG_CONFIG, |
432 | "%s: Bss Info DISSOC\n", __func__); | 439 | "%s: Bss Info DISSOC\n", __func__); |
@@ -1173,6 +1180,13 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1173 | return error; | 1180 | return error; |
1174 | } | 1181 | } |
1175 | 1182 | ||
1183 | if (conf->type == NL80211_IFTYPE_AP) { | ||
1184 | /* TODO: is this a suitable place to start ANI for AP mode? */ | ||
1185 | /* Start ANI */ | ||
1186 | mod_timer(&sc->sc_ani.timer, | ||
1187 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | ||
1188 | } | ||
1189 | |||
1176 | return 0; | 1190 | return 0; |
1177 | } | 1191 | } |
1178 | 1192 | ||
@@ -1195,6 +1209,8 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1195 | #ifdef CONFIG_SLOW_ANT_DIV | 1209 | #ifdef CONFIG_SLOW_ANT_DIV |
1196 | ath_slow_ant_div_stop(&sc->sc_antdiv); | 1210 | ath_slow_ant_div_stop(&sc->sc_antdiv); |
1197 | #endif | 1211 | #endif |
1212 | /* Stop ANI */ | ||
1213 | del_timer_sync(&sc->sc_ani.timer); | ||
1198 | 1214 | ||
1199 | /* Update ratectrl */ | 1215 | /* Update ratectrl */ |
1200 | ath_rate_newstate(sc, avp); | 1216 | ath_rate_newstate(sc, avp); |
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index 498256309ab7..4983402af559 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -892,7 +892,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
892 | 892 | ||
893 | hdr = (struct ieee80211_hdr *)skb->data; | 893 | hdr = (struct ieee80211_hdr *)skb->data; |
894 | fc = hdr->frame_control; | 894 | fc = hdr->frame_control; |
895 | memzero(&rx_status, sizeof(struct ath_recv_status)); | 895 | memset(&rx_status, 0, sizeof(struct ath_recv_status)); |
896 | 896 | ||
897 | if (ds->ds_rxstat.rs_more) { | 897 | if (ds->ds_rxstat.rs_more) { |
898 | /* | 898 | /* |
@@ -999,20 +999,11 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
999 | rx_status.flags |= ATH_RX_SHORT_GI; | 999 | rx_status.flags |= ATH_RX_SHORT_GI; |
1000 | } | 1000 | } |
1001 | 1001 | ||
1002 | /* sc->sc_noise_floor is only available when the station | 1002 | /* sc_noise_floor is only available when the station |
1003 | attaches to an AP, so we use a default value | 1003 | attaches to an AP, so we use a default value |
1004 | if we are not yet attached. */ | 1004 | if we are not yet attached. */ |
1005 | |||
1006 | /* XXX we should use either sc->sc_noise_floor or | ||
1007 | * ath_hal_getChanNoise(ah, &sc->sc_curchan) | ||
1008 | * to calculate the noise floor. | ||
1009 | * However, the value returned by ath_hal_getChanNoise | ||
1010 | * seems to be incorrect (-31dBm on the last test), | ||
1011 | * so we will use a hard-coded value until we | ||
1012 | * figure out what is going on. | ||
1013 | */ | ||
1014 | rx_status.abs_rssi = | 1005 | rx_status.abs_rssi = |
1015 | ds->ds_rxstat.rs_rssi + ATH_DEFAULT_NOISE_FLOOR; | 1006 | ds->ds_rxstat.rs_rssi + sc->sc_ani.sc_noise_floor; |
1016 | 1007 | ||
1017 | pci_dma_sync_single_for_cpu(sc->pdev, | 1008 | pci_dma_sync_single_for_cpu(sc->pdev, |
1018 | bf->bf_buf_addr, | 1009 | bf->bf_buf_addr, |
@@ -1166,7 +1157,7 @@ int ath_rx_aggr_start(struct ath_softc *sc, | |||
1166 | } else { | 1157 | } else { |
1167 | /* Ensure the memory is zeroed out (all internal | 1158 | /* Ensure the memory is zeroed out (all internal |
1168 | * pointers are null) */ | 1159 | * pointers are null) */ |
1169 | memzero(rxtid->rxbuf, ATH_TID_MAX_BUFS * | 1160 | memset(rxtid->rxbuf, 0, ATH_TID_MAX_BUFS * |
1170 | sizeof(struct ath_rxbuf)); | 1161 | sizeof(struct ath_rxbuf)); |
1171 | DPRINTF(sc, ATH_DBG_AGGR, | 1162 | DPRINTF(sc, ATH_DBG_AGGR, |
1172 | "%s: Allocated @%p\n", __func__, rxtid->rxbuf); | 1163 | "%s: Allocated @%p\n", __func__, rxtid->rxbuf); |
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index 25929059c7dc..3a4757942b3f 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -237,7 +237,7 @@ static int ath_tx_prepare(struct ath_softc *sc, | |||
237 | 237 | ||
238 | if (tx_info->control.hw_key) { | 238 | if (tx_info->control.hw_key) { |
239 | txctl->keyix = tx_info->control.hw_key->hw_key_idx; | 239 | txctl->keyix = tx_info->control.hw_key->hw_key_idx; |
240 | txctl->frmlen += tx_info->control.icv_len; | 240 | txctl->frmlen += tx_info->control.hw_key->icv_len; |
241 | 241 | ||
242 | if (tx_info->control.hw_key->alg == ALG_WEP) | 242 | if (tx_info->control.hw_key->alg == ALG_WEP) |
243 | txctl->keytype = ATH9K_KEY_TYPE_WEP; | 243 | txctl->keytype = ATH9K_KEY_TYPE_WEP; |
@@ -729,7 +729,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
729 | /* | 729 | /* |
730 | * Setup HAL rate series | 730 | * Setup HAL rate series |
731 | */ | 731 | */ |
732 | memzero(series, sizeof(struct ath9k_11n_rate_series) * 4); | 732 | memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); |
733 | 733 | ||
734 | for (i = 0; i < 4; i++) { | 734 | for (i = 0; i < 4; i++) { |
735 | if (!bf->bf_rcs[i].tries) | 735 | if (!bf->bf_rcs[i].tries) |
@@ -817,7 +817,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) | |||
817 | * Disable multi-rate retry when using RTS/CTS by clearing | 817 | * Disable multi-rate retry when using RTS/CTS by clearing |
818 | * series 1, 2 and 3. | 818 | * series 1, 2 and 3. |
819 | */ | 819 | */ |
820 | memzero(&series[1], sizeof(struct ath9k_11n_rate_series) * 3); | 820 | memset(&series[1], 0, sizeof(struct ath9k_11n_rate_series) * 3); |
821 | } | 821 | } |
822 | 822 | ||
823 | /* | 823 | /* |
@@ -930,7 +930,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
930 | ATH_DS_BA_BITMAP(ds), | 930 | ATH_DS_BA_BITMAP(ds), |
931 | WME_BA_BMP_SIZE >> 3); | 931 | WME_BA_BMP_SIZE >> 3); |
932 | } else { | 932 | } else { |
933 | memzero(ba, WME_BA_BMP_SIZE >> 3); | 933 | memset(ba, 0, WME_BA_BMP_SIZE >> 3); |
934 | 934 | ||
935 | /* | 935 | /* |
936 | * AR5416 can become deaf/mute when BA | 936 | * AR5416 can become deaf/mute when BA |
@@ -943,7 +943,7 @@ static void ath_tx_complete_aggr_rifs(struct ath_softc *sc, | |||
943 | needreset = 1; | 943 | needreset = 1; |
944 | } | 944 | } |
945 | } else { | 945 | } else { |
946 | memzero(ba, WME_BA_BMP_SIZE >> 3); | 946 | memset(ba, 0, WME_BA_BMP_SIZE >> 3); |
947 | } | 947 | } |
948 | } | 948 | } |
949 | 949 | ||
@@ -2098,7 +2098,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
2098 | struct ath9k_tx_queue_info qi; | 2098 | struct ath9k_tx_queue_info qi; |
2099 | int qnum; | 2099 | int qnum; |
2100 | 2100 | ||
2101 | memzero(&qi, sizeof(qi)); | 2101 | memset(&qi, 0, sizeof(qi)); |
2102 | qi.tqi_subtype = subtype; | 2102 | qi.tqi_subtype = subtype; |
2103 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; | 2103 | qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; |
2104 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; | 2104 | qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3bf74e236abc..14c44df584d0 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4588,6 +4588,7 @@ static int b43_wireless_init(struct ssb_device *dev) | |||
4588 | BIT(NL80211_IFTYPE_ADHOC); | 4588 | BIT(NL80211_IFTYPE_ADHOC); |
4589 | 4589 | ||
4590 | hw->queues = b43_modparam_qos ? 4 : 1; | 4590 | hw->queues = b43_modparam_qos ? 4 : 1; |
4591 | hw->max_altrates = 1; | ||
4591 | SET_IEEE80211_DEV(hw, dev->dev); | 4592 | SET_IEEE80211_DEV(hw, dev->dev); |
4592 | if (is_valid_ether_addr(sprom->et1mac)) | 4593 | if (is_valid_ether_addr(sprom->et1mac)) |
4593 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); | 4594 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); |
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c index 5e0b71c3ad02..2fabcf8f0474 100644 --- a/drivers/net/wireless/b43/xmit.c +++ b/drivers/net/wireless/b43/xmit.c | |||
@@ -208,7 +208,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
208 | txrate = ieee80211_get_tx_rate(dev->wl->hw, info); | 208 | txrate = ieee80211_get_tx_rate(dev->wl->hw, info); |
209 | rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; | 209 | rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; |
210 | rate_ofdm = b43_is_ofdm_rate(rate); | 210 | rate_ofdm = b43_is_ofdm_rate(rate); |
211 | fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : txrate; | 211 | fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate; |
212 | rate_fb = fbrate->hw_value; | 212 | rate_fb = fbrate->hw_value; |
213 | rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); | 213 | rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); |
214 | 214 | ||
@@ -252,7 +252,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
252 | } | 252 | } |
253 | 253 | ||
254 | /* Hardware appends ICV. */ | 254 | /* Hardware appends ICV. */ |
255 | plcp_fragment_len += info->control.icv_len; | 255 | plcp_fragment_len += info->control.hw_key->icv_len; |
256 | 256 | ||
257 | key_idx = b43_kidx_to_fw(dev, key_idx); | 257 | key_idx = b43_kidx_to_fw(dev, key_idx); |
258 | mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & | 258 | mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & |
@@ -260,7 +260,7 @@ int b43_generate_txhdr(struct b43_wldev *dev, | |||
260 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & | 260 | mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & |
261 | B43_TXH_MAC_KEYALG; | 261 | B43_TXH_MAC_KEYALG; |
262 | wlhdr_len = ieee80211_hdrlen(fctl); | 262 | wlhdr_len = ieee80211_hdrlen(fctl); |
263 | iv_len = min((size_t) info->control.iv_len, | 263 | iv_len = min((size_t) info->control.hw_key->iv_len, |
264 | ARRAY_SIZE(txhdr->iv)); | 264 | ARRAY_SIZE(txhdr->iv)); |
265 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); | 265 | memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); |
266 | } | 266 | } |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 9fb1421cbec2..c66d57560e7c 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -3710,6 +3710,7 @@ static int b43legacy_wireless_init(struct ssb_device *dev) | |||
3710 | BIT(NL80211_IFTYPE_WDS) | | 3710 | BIT(NL80211_IFTYPE_WDS) | |
3711 | BIT(NL80211_IFTYPE_ADHOC); | 3711 | BIT(NL80211_IFTYPE_ADHOC); |
3712 | hw->queues = 1; /* FIXME: hardware has more queues */ | 3712 | hw->queues = 1; /* FIXME: hardware has more queues */ |
3713 | hw->max_altrates = 1; | ||
3713 | SET_IEEE80211_DEV(hw, dev->dev); | 3714 | SET_IEEE80211_DEV(hw, dev->dev); |
3714 | if (is_valid_ether_addr(sprom->et1mac)) | 3715 | if (is_valid_ether_addr(sprom->et1mac)) |
3715 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); | 3716 | SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); |
diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c index 6835064758fb..65e833781608 100644 --- a/drivers/net/wireless/b43legacy/xmit.c +++ b/drivers/net/wireless/b43legacy/xmit.c | |||
@@ -210,7 +210,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
210 | 210 | ||
211 | rate = tx_rate->hw_value; | 211 | rate = tx_rate->hw_value; |
212 | rate_ofdm = b43legacy_is_ofdm_rate(rate); | 212 | rate_ofdm = b43legacy_is_ofdm_rate(rate); |
213 | rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info) ? : tx_rate; | 213 | rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate; |
214 | rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); | 214 | rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); |
215 | 215 | ||
216 | txhdr->mac_frame_ctl = wlhdr->frame_control; | 216 | txhdr->mac_frame_ctl = wlhdr->frame_control; |
@@ -243,7 +243,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
243 | 243 | ||
244 | if (key->enabled) { | 244 | if (key->enabled) { |
245 | /* Hardware appends ICV. */ | 245 | /* Hardware appends ICV. */ |
246 | plcp_fragment_len += info->control.icv_len; | 246 | plcp_fragment_len += info->control.hw_key->icv_len; |
247 | 247 | ||
248 | key_idx = b43legacy_kidx_to_fw(dev, key_idx); | 248 | key_idx = b43legacy_kidx_to_fw(dev, key_idx); |
249 | mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) & | 249 | mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) & |
@@ -252,7 +252,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev, | |||
252 | B43legacy_TX4_MAC_KEYALG_SHIFT) & | 252 | B43legacy_TX4_MAC_KEYALG_SHIFT) & |
253 | B43legacy_TX4_MAC_KEYALG; | 253 | B43legacy_TX4_MAC_KEYALG; |
254 | wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control); | 254 | wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control); |
255 | iv_len = min((size_t)info->control.iv_len, | 255 | iv_len = min((size_t)info->control.hw_key->iv_len, |
256 | ARRAY_SIZE(txhdr->iv)); | 256 | ARRAY_SIZE(txhdr->iv)); |
257 | memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); | 257 | memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); |
258 | } else { | 258 | } else { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 204abab76449..24a1aeb6448f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -2569,30 +2569,6 @@ static void iwl4965_post_associate(struct iwl_priv *priv) | |||
2569 | 2569 | ||
2570 | } | 2570 | } |
2571 | 2571 | ||
2572 | static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); | ||
2573 | |||
2574 | static void iwl_bg_scan_completed(struct work_struct *work) | ||
2575 | { | ||
2576 | struct iwl_priv *priv = | ||
2577 | container_of(work, struct iwl_priv, scan_completed); | ||
2578 | |||
2579 | IWL_DEBUG_SCAN("SCAN complete scan\n"); | ||
2580 | |||
2581 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
2582 | return; | ||
2583 | |||
2584 | if (test_bit(STATUS_CONF_PENDING, &priv->status)) | ||
2585 | iwl4965_mac_config(priv->hw, ieee80211_get_hw_conf(priv->hw)); | ||
2586 | |||
2587 | ieee80211_scan_completed(priv->hw); | ||
2588 | |||
2589 | /* Since setting the TXPOWER may have been deferred while | ||
2590 | * performing the scan, fire one off */ | ||
2591 | mutex_lock(&priv->mutex); | ||
2592 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
2593 | mutex_unlock(&priv->mutex); | ||
2594 | } | ||
2595 | |||
2596 | /***************************************************************************** | 2572 | /***************************************************************************** |
2597 | * | 2573 | * |
2598 | * mac80211 entry point functions | 2574 | * mac80211 entry point functions |
@@ -2812,7 +2788,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co | |||
2812 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && | 2788 | if (unlikely(!priv->cfg->mod_params->disable_hw_scan && |
2813 | test_bit(STATUS_SCANNING, &priv->status))) { | 2789 | test_bit(STATUS_SCANNING, &priv->status))) { |
2814 | IWL_DEBUG_MAC80211("leave - scanning\n"); | 2790 | IWL_DEBUG_MAC80211("leave - scanning\n"); |
2815 | set_bit(STATUS_CONF_PENDING, &priv->status); | ||
2816 | mutex_unlock(&priv->mutex); | 2791 | mutex_unlock(&priv->mutex); |
2817 | return 0; | 2792 | return 0; |
2818 | } | 2793 | } |
@@ -2898,7 +2873,6 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co | |||
2898 | IWL_DEBUG_MAC80211("leave\n"); | 2873 | IWL_DEBUG_MAC80211("leave\n"); |
2899 | 2874 | ||
2900 | out: | 2875 | out: |
2901 | clear_bit(STATUS_CONF_PENDING, &priv->status); | ||
2902 | mutex_unlock(&priv->mutex); | 2876 | mutex_unlock(&priv->mutex); |
2903 | return ret; | 2877 | return ret; |
2904 | } | 2878 | } |
@@ -4117,8 +4091,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv) | |||
4117 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); | 4091 | INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); |
4118 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); | 4092 | INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); |
4119 | 4093 | ||
4120 | /* FIXME : remove when resolved PENDING */ | ||
4121 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | ||
4122 | iwl_setup_scan_deferred_work(priv); | 4094 | iwl_setup_scan_deferred_work(priv); |
4123 | iwl_setup_power_deferred_work(priv); | 4095 | iwl_setup_power_deferred_work(priv); |
4124 | 4096 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 55a4b584ce07..288b6a800e03 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -333,8 +333,7 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv); | |||
333 | #define STATUS_SCAN_HW 15 | 333 | #define STATUS_SCAN_HW 15 |
334 | #define STATUS_POWER_PMI 16 | 334 | #define STATUS_POWER_PMI 16 |
335 | #define STATUS_FW_ERROR 17 | 335 | #define STATUS_FW_ERROR 17 |
336 | #define STATUS_CONF_PENDING 18 | 336 | #define STATUS_MODE_PENDING 18 |
337 | #define STATUS_MODE_PENDING 19 | ||
338 | 337 | ||
339 | 338 | ||
340 | static inline int iwl_is_ready(struct iwl_priv *priv) | 339 | static inline int iwl_is_ready(struct iwl_priv *priv) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index bf855c35b0c1..3b0bee331a33 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -703,7 +703,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
703 | u16 cmd_len; | 703 | u16 cmd_len; |
704 | enum ieee80211_band band; | 704 | enum ieee80211_band band; |
705 | u8 n_probes = 2; | 705 | u8 n_probes = 2; |
706 | u8 rx_chain = 0x7; /* bitmap: ABC chains */ | 706 | u8 rx_chain = priv->hw_params.valid_rx_ant; |
707 | 707 | ||
708 | conf = ieee80211_get_hw_conf(priv->hw); | 708 | conf = ieee80211_get_hw_conf(priv->hw); |
709 | 709 | ||
@@ -843,7 +843,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
843 | 843 | ||
844 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | 844 | /* Force use of chains B and C (0x6) for scan Rx for 4965 |
845 | * Avoid A (0x1) because of its off-channel reception on A-band. | 845 | * Avoid A (0x1) because of its off-channel reception on A-band. |
846 | * MIMO is not used here, but value is required */ | 846 | */ |
847 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) | 847 | if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) |
848 | rx_chain = 0x6; | 848 | rx_chain = 0x6; |
849 | } else { | 849 | } else { |
@@ -851,6 +851,7 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
851 | goto done; | 851 | goto done; |
852 | } | 852 | } |
853 | 853 | ||
854 | /* MIMO is not used here, but value is required */ | ||
854 | scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | | 855 | scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | |
855 | cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | | 856 | cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | |
856 | (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | | 857 | (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | |
@@ -915,10 +916,29 @@ static void iwl_bg_abort_scan(struct work_struct *work) | |||
915 | mutex_unlock(&priv->mutex); | 916 | mutex_unlock(&priv->mutex); |
916 | } | 917 | } |
917 | 918 | ||
919 | static void iwl_bg_scan_completed(struct work_struct *work) | ||
920 | { | ||
921 | struct iwl_priv *priv = | ||
922 | container_of(work, struct iwl_priv, scan_completed); | ||
923 | |||
924 | IWL_DEBUG_SCAN("SCAN complete scan\n"); | ||
925 | |||
926 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) | ||
927 | return; | ||
928 | |||
929 | ieee80211_scan_completed(priv->hw); | ||
930 | |||
931 | /* Since setting the TXPOWER may have been deferred while | ||
932 | * performing the scan, fire one off */ | ||
933 | mutex_lock(&priv->mutex); | ||
934 | iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); | ||
935 | mutex_unlock(&priv->mutex); | ||
936 | } | ||
937 | |||
938 | |||
918 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | 939 | void iwl_setup_scan_deferred_work(struct iwl_priv *priv) |
919 | { | 940 | { |
920 | /* FIXME: move here when resolved PENDING | 941 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); |
921 | * INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); */ | ||
922 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); | 942 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); |
923 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 943 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); |
924 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 944 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index de5e8f44b202..1994aa199d37 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -507,9 +507,10 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
507 | rx_status.noise = priv->noise; | 507 | rx_status.noise = priv->noise; |
508 | /* XX correct? */ | 508 | /* XX correct? */ |
509 | rx_status.qual = (100 * hdr->rssi) / 127; | 509 | rx_status.qual = (100 * hdr->rssi) / 127; |
510 | rx_status.rate_idx = hdr->rate & 0xf; | 510 | rx_status.rate_idx = (dev->conf.channel->band == IEEE80211_BAND_2GHZ ? |
511 | hdr->rate : (hdr->rate - 4)) & 0xf; | ||
511 | rx_status.freq = freq; | 512 | rx_status.freq = freq; |
512 | rx_status.band = IEEE80211_BAND_2GHZ; | 513 | rx_status.band = dev->conf.channel->band; |
513 | rx_status.antenna = hdr->antenna; | 514 | rx_status.antenna = hdr->antenna; |
514 | 515 | ||
515 | tsf32 = le32_to_cpu(hdr->tsf32); | 516 | tsf32 = le32_to_cpu(hdr->tsf32); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c index e1448cfa9444..5a858e5106c4 100644 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ b/drivers/net/wireless/rt2x00/rt2x00crypto.c | |||
@@ -56,10 +56,10 @@ unsigned int rt2x00crypto_tx_overhead(struct ieee80211_tx_info *tx_info) | |||
56 | * note that these lengths should only be added when | 56 | * note that these lengths should only be added when |
57 | * mac80211 does not generate it. | 57 | * mac80211 does not generate it. |
58 | */ | 58 | */ |
59 | overhead += tx_info->control.icv_len; | 59 | overhead += key->icv_len; |
60 | 60 | ||
61 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) | 61 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) |
62 | overhead += tx_info->control.iv_len; | 62 | overhead += key->iv_len; |
63 | 63 | ||
64 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { | 64 | if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { |
65 | if (key->alg == ALG_TKIP) | 65 | if (key->alg == ALG_TKIP) |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index b7f4fe8fba6e..1676ac484790 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -374,7 +374,7 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
374 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); | 374 | struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); |
375 | struct txentry_desc txdesc; | 375 | struct txentry_desc txdesc; |
376 | struct skb_frame_desc *skbdesc; | 376 | struct skb_frame_desc *skbdesc; |
377 | unsigned int iv_len = IEEE80211_SKB_CB(skb)->control.iv_len; | 377 | unsigned int iv_len; |
378 | 378 | ||
379 | if (unlikely(rt2x00queue_full(queue))) | 379 | if (unlikely(rt2x00queue_full(queue))) |
380 | return -EINVAL; | 380 | return -EINVAL; |
@@ -410,8 +410,11 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) | |||
410 | * the frame so we can provide it to the driver seperately. | 410 | * the frame so we can provide it to the driver seperately. |
411 | */ | 411 | */ |
412 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && | 412 | if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && |
413 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) | 413 | !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags) && |
414 | (IEEE80211_SKB_CB(skb)->control.hw_key != NULL)) { | ||
415 | iv_len = IEEE80211_SKB_CB(skb)->control.hw_key->iv_len; | ||
414 | rt2x00crypto_tx_remove_iv(skb, iv_len); | 416 | rt2x00crypto_tx_remove_iv(skb, iv_len); |
417 | } | ||
415 | 418 | ||
416 | /* | 419 | /* |
417 | * It could be possible that the queue was corrupted and this | 420 | * It could be possible that the queue was corrupted and this |
diff --git a/drivers/net/wireless/rt2x00/rt2x00rfkill.c b/drivers/net/wireless/rt2x00/rt2x00rfkill.c index 55eff58f1889..c3f53a92180a 100644 --- a/drivers/net/wireless/rt2x00/rt2x00rfkill.c +++ b/drivers/net/wireless/rt2x00/rt2x00rfkill.c | |||
@@ -145,10 +145,15 @@ void rt2x00rfkill_allocate(struct rt2x00_dev *rt2x00dev) | |||
145 | 145 | ||
146 | rt2x00dev->rfkill->name = rt2x00dev->ops->name; | 146 | rt2x00dev->rfkill->name = rt2x00dev->ops->name; |
147 | rt2x00dev->rfkill->data = rt2x00dev; | 147 | rt2x00dev->rfkill->data = rt2x00dev; |
148 | rt2x00dev->rfkill->state = -1; | ||
149 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; | 148 | rt2x00dev->rfkill->toggle_radio = rt2x00rfkill_toggle_radio; |
150 | if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) | 149 | if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) { |
151 | rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; | 150 | rt2x00dev->rfkill->get_state = rt2x00rfkill_get_state; |
151 | rt2x00dev->rfkill->state = | ||
152 | rt2x00dev->ops->lib->rfkill_poll(rt2x00dev) ? | ||
153 | RFKILL_STATE_SOFT_BLOCKED : RFKILL_STATE_UNBLOCKED; | ||
154 | } else { | ||
155 | rt2x00dev->rfkill->state = RFKILL_STATE_UNBLOCKED; | ||
156 | } | ||
152 | 157 | ||
153 | INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); | 158 | INIT_DELAYED_WORK(&rt2x00dev->rfkill_work, rt2x00rfkill_poll); |
154 | 159 | ||
diff --git a/drivers/net/wireless/rtl8180_dev.c b/drivers/net/wireless/rtl8180_dev.c index abcd641c54be..df7e78ee8a88 100644 --- a/drivers/net/wireless/rtl8180_dev.c +++ b/drivers/net/wireless/rtl8180_dev.c | |||
@@ -292,8 +292,8 @@ static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
292 | entry->plcp_len = cpu_to_le16(plcp_len); | 292 | entry->plcp_len = cpu_to_le16(plcp_len); |
293 | entry->tx_buf = cpu_to_le32(mapping); | 293 | entry->tx_buf = cpu_to_le32(mapping); |
294 | entry->frame_len = cpu_to_le32(skb->len); | 294 | entry->frame_len = cpu_to_le32(skb->len); |
295 | entry->flags2 = info->control.alt_retry_rate_idx >= 0 ? | 295 | entry->flags2 = info->control.retries[0].rate_idx >= 0 ? |
296 | ieee80211_get_alt_retry_rate(dev, info)->bitrate << 4 : 0; | 296 | ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; |
297 | entry->retry_limit = info->control.retry_limit; | 297 | entry->retry_limit = info->control.retry_limit; |
298 | entry->flags = cpu_to_le32(tx_flags); | 298 | entry->flags = cpu_to_le32(tx_flags); |
299 | __skb_queue_tail(&ring->queue, skb); | 299 | __skb_queue_tail(&ring->queue, skb); |
@@ -855,6 +855,7 @@ static int __devinit rtl8180_probe(struct pci_dev *pdev, | |||
855 | priv = dev->priv; | 855 | priv = dev->priv; |
856 | priv->pdev = pdev; | 856 | priv->pdev = pdev; |
857 | 857 | ||
858 | dev->max_altrates = 1; | ||
858 | SET_IEEE80211_DEV(dev, &pdev->dev); | 859 | SET_IEEE80211_DEV(dev, &pdev->dev); |
859 | pci_set_drvdata(pdev, dev); | 860 | pci_set_drvdata(pdev, dev); |
860 | 861 | ||
diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h index c6f51ad52d5b..06fcdb45106b 100644 --- a/include/linux/inetdevice.h +++ b/include/linux/inetdevice.h | |||
@@ -25,6 +25,7 @@ struct in_device | |||
25 | struct in_ifaddr *ifa_list; /* IP ifaddr chain */ | 25 | struct in_ifaddr *ifa_list; /* IP ifaddr chain */ |
26 | rwlock_t mc_list_lock; | 26 | rwlock_t mc_list_lock; |
27 | struct ip_mc_list *mc_list; /* IP multicast filter chain */ | 27 | struct ip_mc_list *mc_list; /* IP multicast filter chain */ |
28 | int mc_count; /* Number of installed mcasts */ | ||
28 | spinlock_t mc_tomb_lock; | 29 | spinlock_t mc_tomb_lock; |
29 | struct ip_mc_list *mc_tomb; | 30 | struct ip_mc_list *mc_tomb; |
30 | unsigned long mr_v1_seen; | 31 | unsigned long mr_v1_seen; |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index f5f5b1ff1584..5617a1613c91 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -292,6 +292,20 @@ enum mac80211_tx_control_flags { | |||
292 | #define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ | 292 | #define IEEE80211_TX_INFO_DRIVER_DATA_PTRS \ |
293 | (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) | 293 | (IEEE80211_TX_INFO_DRIVER_DATA_SIZE / sizeof(void *)) |
294 | 294 | ||
295 | /* maximum number of alternate rate retry stages */ | ||
296 | #define IEEE80211_TX_MAX_ALTRATE 3 | ||
297 | |||
298 | /** | ||
299 | * struct ieee80211_tx_altrate - alternate rate selection/status | ||
300 | * | ||
301 | * @rate_idx: rate index to attempt to send with | ||
302 | * @limit: number of retries before fallback | ||
303 | */ | ||
304 | struct ieee80211_tx_altrate { | ||
305 | s8 rate_idx; | ||
306 | u8 limit; | ||
307 | }; | ||
308 | |||
295 | /** | 309 | /** |
296 | * struct ieee80211_tx_info - skb transmit information | 310 | * struct ieee80211_tx_info - skb transmit information |
297 | * | 311 | * |
@@ -335,14 +349,14 @@ struct ieee80211_tx_info { | |||
335 | struct ieee80211_key_conf *hw_key; | 349 | struct ieee80211_key_conf *hw_key; |
336 | struct ieee80211_sta *sta; | 350 | struct ieee80211_sta *sta; |
337 | unsigned long jiffies; | 351 | unsigned long jiffies; |
338 | s8 rts_cts_rate_idx, alt_retry_rate_idx; | 352 | s8 rts_cts_rate_idx; |
339 | u8 retry_limit; | 353 | u8 retry_limit; |
340 | u8 icv_len; | 354 | struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE]; |
341 | u8 iv_len; | ||
342 | } control; | 355 | } control; |
343 | struct { | 356 | struct { |
344 | u64 ampdu_ack_map; | 357 | u64 ampdu_ack_map; |
345 | int ack_signal; | 358 | int ack_signal; |
359 | struct ieee80211_tx_altrate retries[IEEE80211_TX_MAX_ALTRATE + 1]; | ||
346 | u8 retry_count; | 360 | u8 retry_count; |
347 | bool excessive_retries; | 361 | bool excessive_retries; |
348 | u8 ampdu_ack_len; | 362 | u8 ampdu_ack_len; |
@@ -635,6 +649,8 @@ enum ieee80211_key_flags { | |||
635 | */ | 649 | */ |
636 | struct ieee80211_key_conf { | 650 | struct ieee80211_key_conf { |
637 | enum ieee80211_key_alg alg; | 651 | enum ieee80211_key_alg alg; |
652 | u8 icv_len; | ||
653 | u8 iv_len; | ||
638 | u8 hw_key_idx; | 654 | u8 hw_key_idx; |
639 | u8 flags; | 655 | u8 flags; |
640 | s8 keyidx; | 656 | s8 keyidx; |
@@ -828,6 +844,9 @@ enum ieee80211_hw_flags { | |||
828 | * within &struct ieee80211_vif. | 844 | * within &struct ieee80211_vif. |
829 | * @sta_data_size: size (in bytes) of the drv_priv data area | 845 | * @sta_data_size: size (in bytes) of the drv_priv data area |
830 | * within &struct ieee80211_sta. | 846 | * within &struct ieee80211_sta. |
847 | * | ||
848 | * @max_altrates: maximum number of alternate rate retry stages | ||
849 | * @max_altrate_tries: maximum number of tries for each stage | ||
831 | */ | 850 | */ |
832 | struct ieee80211_hw { | 851 | struct ieee80211_hw { |
833 | struct ieee80211_conf conf; | 852 | struct ieee80211_conf conf; |
@@ -844,6 +863,8 @@ struct ieee80211_hw { | |||
844 | u16 ampdu_queues; | 863 | u16 ampdu_queues; |
845 | u16 max_listen_interval; | 864 | u16 max_listen_interval; |
846 | s8 max_signal; | 865 | s8 max_signal; |
866 | u8 max_altrates; | ||
867 | u8 max_altrate_tries; | ||
847 | }; | 868 | }; |
848 | 869 | ||
849 | struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); | 870 | struct ieee80211_hw *wiphy_to_hw(struct wiphy *wiphy); |
@@ -900,11 +921,11 @@ ieee80211_get_rts_cts_rate(const struct ieee80211_hw *hw, | |||
900 | 921 | ||
901 | static inline struct ieee80211_rate * | 922 | static inline struct ieee80211_rate * |
902 | ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | 923 | ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, |
903 | const struct ieee80211_tx_info *c) | 924 | const struct ieee80211_tx_info *c, int idx) |
904 | { | 925 | { |
905 | if (c->control.alt_retry_rate_idx < 0) | 926 | if (c->control.retries[idx].rate_idx < 0) |
906 | return NULL; | 927 | return NULL; |
907 | return &hw->wiphy->bands[c->band]->bitrates[c->control.alt_retry_rate_idx]; | 928 | return &hw->wiphy->bands[c->band]->bitrates[c->control.retries[idx].rate_idx]; |
908 | } | 929 | } |
909 | 930 | ||
910 | /** | 931 | /** |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index f70fac612596..7f9e337e3908 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1234,6 +1234,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) | |||
1234 | write_lock_bh(&in_dev->mc_list_lock); | 1234 | write_lock_bh(&in_dev->mc_list_lock); |
1235 | im->next=in_dev->mc_list; | 1235 | im->next=in_dev->mc_list; |
1236 | in_dev->mc_list=im; | 1236 | in_dev->mc_list=im; |
1237 | in_dev->mc_count++; | ||
1237 | write_unlock_bh(&in_dev->mc_list_lock); | 1238 | write_unlock_bh(&in_dev->mc_list_lock); |
1238 | #ifdef CONFIG_IP_MULTICAST | 1239 | #ifdef CONFIG_IP_MULTICAST |
1239 | igmpv3_del_delrec(in_dev, im->multiaddr); | 1240 | igmpv3_del_delrec(in_dev, im->multiaddr); |
@@ -1282,6 +1283,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr) | |||
1282 | if (--i->users == 0) { | 1283 | if (--i->users == 0) { |
1283 | write_lock_bh(&in_dev->mc_list_lock); | 1284 | write_lock_bh(&in_dev->mc_list_lock); |
1284 | *ip = i->next; | 1285 | *ip = i->next; |
1286 | in_dev->mc_count--; | ||
1285 | write_unlock_bh(&in_dev->mc_list_lock); | 1287 | write_unlock_bh(&in_dev->mc_list_lock); |
1286 | igmp_group_dropped(i); | 1288 | igmp_group_dropped(i); |
1287 | 1289 | ||
@@ -1330,6 +1332,7 @@ void ip_mc_init_dev(struct in_device *in_dev) | |||
1330 | setup_timer(&in_dev->mr_gq_timer, igmp_gq_timer_expire, | 1332 | setup_timer(&in_dev->mr_gq_timer, igmp_gq_timer_expire, |
1331 | (unsigned long)in_dev); | 1333 | (unsigned long)in_dev); |
1332 | in_dev->mr_ifc_count = 0; | 1334 | in_dev->mr_ifc_count = 0; |
1335 | in_dev->mc_count = 0; | ||
1333 | setup_timer(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire, | 1336 | setup_timer(&in_dev->mr_ifc_timer, igmp_ifc_timer_expire, |
1334 | (unsigned long)in_dev); | 1337 | (unsigned long)in_dev); |
1335 | in_dev->mr_qrv = IGMP_Unsolicited_Report_Count; | 1338 | in_dev->mr_qrv = IGMP_Unsolicited_Report_Count; |
@@ -1369,8 +1372,8 @@ void ip_mc_destroy_dev(struct in_device *in_dev) | |||
1369 | write_lock_bh(&in_dev->mc_list_lock); | 1372 | write_lock_bh(&in_dev->mc_list_lock); |
1370 | while ((i = in_dev->mc_list) != NULL) { | 1373 | while ((i = in_dev->mc_list) != NULL) { |
1371 | in_dev->mc_list = i->next; | 1374 | in_dev->mc_list = i->next; |
1375 | in_dev->mc_count--; | ||
1372 | write_unlock_bh(&in_dev->mc_list_lock); | 1376 | write_unlock_bh(&in_dev->mc_list_lock); |
1373 | |||
1374 | igmp_group_dropped(i); | 1377 | igmp_group_dropped(i); |
1375 | ip_ma_put(i); | 1378 | ip_ma_put(i); |
1376 | 1379 | ||
@@ -2383,7 +2386,7 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v) | |||
2383 | 2386 | ||
2384 | if (state->in_dev->mc_list == im) { | 2387 | if (state->in_dev->mc_list == im) { |
2385 | seq_printf(seq, "%d\t%-10s: %5d %7s\n", | 2388 | seq_printf(seq, "%d\t%-10s: %5d %7s\n", |
2386 | state->dev->ifindex, state->dev->name, state->dev->mc_count, querier); | 2389 | state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier); |
2387 | } | 2390 | } |
2388 | 2391 | ||
2389 | seq_printf(seq, | 2392 | seq_printf(seq, |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 8427518e4f20..7f710a27e91c 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -22,6 +22,11 @@ config MAC80211_RC_PID | |||
22 | mac80211 that uses a PID controller to select the TX | 22 | mac80211 that uses a PID controller to select the TX |
23 | rate. | 23 | rate. |
24 | 24 | ||
25 | config MAC80211_RC_MINSTREL | ||
26 | bool "Minstrel" | ||
27 | ---help--- | ||
28 | This option enables the 'minstrel' TX rate control algorithm | ||
29 | |||
25 | choice | 30 | choice |
26 | prompt "Default rate control algorithm" | 31 | prompt "Default rate control algorithm" |
27 | default MAC80211_RC_DEFAULT_PID | 32 | default MAC80211_RC_DEFAULT_PID |
@@ -39,11 +44,19 @@ config MAC80211_RC_DEFAULT_PID | |||
39 | default rate control algorithm. You should choose | 44 | default rate control algorithm. You should choose |
40 | this unless you know what you are doing. | 45 | this unless you know what you are doing. |
41 | 46 | ||
47 | config MAC80211_RC_DEFAULT_MINSTREL | ||
48 | bool "Minstrel" | ||
49 | depends on MAC80211_RC_MINSTREL | ||
50 | ---help--- | ||
51 | Select Minstrel as the default rate control algorithm. | ||
52 | |||
53 | |||
42 | endchoice | 54 | endchoice |
43 | 55 | ||
44 | config MAC80211_RC_DEFAULT | 56 | config MAC80211_RC_DEFAULT |
45 | string | 57 | string |
46 | default "pid" if MAC80211_RC_DEFAULT_PID | 58 | default "pid" if MAC80211_RC_DEFAULT_PID |
59 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL | ||
47 | default "" | 60 | default "" |
48 | 61 | ||
49 | endmenu | 62 | endmenu |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 2dc8f2bff27b..31cfd1f89a72 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -41,4 +41,8 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ | |||
41 | rc80211_pid-y := rc80211_pid_algo.o | 41 | rc80211_pid-y := rc80211_pid_algo.o |
42 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | 42 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o |
43 | 43 | ||
44 | rc80211_minstrel-y := rc80211_minstrel.o | ||
45 | rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o | ||
46 | |||
44 | mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) | 47 | mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) |
48 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) | ||
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 57afcd38cd9e..a5b06fe71980 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -281,6 +281,20 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg, | |||
281 | key->conf.alg = alg; | 281 | key->conf.alg = alg; |
282 | key->conf.keyidx = idx; | 282 | key->conf.keyidx = idx; |
283 | key->conf.keylen = key_len; | 283 | key->conf.keylen = key_len; |
284 | switch (alg) { | ||
285 | case ALG_WEP: | ||
286 | key->conf.iv_len = WEP_IV_LEN; | ||
287 | key->conf.icv_len = WEP_ICV_LEN; | ||
288 | break; | ||
289 | case ALG_TKIP: | ||
290 | key->conf.iv_len = TKIP_IV_LEN; | ||
291 | key->conf.icv_len = TKIP_ICV_LEN; | ||
292 | break; | ||
293 | case ALG_CCMP: | ||
294 | key->conf.iv_len = CCMP_HDR_LEN; | ||
295 | key->conf.icv_len = CCMP_MIC_LEN; | ||
296 | break; | ||
297 | } | ||
284 | memcpy(key->conf.key, key_data, key_len); | 298 | memcpy(key->conf.key, key_data, key_len); |
285 | INIT_LIST_HEAD(&key->list); | 299 | INIT_LIST_HEAD(&key->list); |
286 | INIT_LIST_HEAD(&key->todo); | 300 | INIT_LIST_HEAD(&key->todo); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d608c44047c0..ae62ad40ad63 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -1015,6 +1015,10 @@ static int __init ieee80211_init(void) | |||
1015 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + | 1015 | BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, driver_data) + |
1016 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); | 1016 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE > sizeof(skb->cb)); |
1017 | 1017 | ||
1018 | ret = rc80211_minstrel_init(); | ||
1019 | if (ret) | ||
1020 | return ret; | ||
1021 | |||
1018 | ret = rc80211_pid_init(); | 1022 | ret = rc80211_pid_init(); |
1019 | if (ret) | 1023 | if (ret) |
1020 | return ret; | 1024 | return ret; |
@@ -1027,6 +1031,7 @@ static int __init ieee80211_init(void) | |||
1027 | static void __exit ieee80211_exit(void) | 1031 | static void __exit ieee80211_exit(void) |
1028 | { | 1032 | { |
1029 | rc80211_pid_exit(); | 1033 | rc80211_pid_exit(); |
1034 | rc80211_minstrel_exit(); | ||
1030 | 1035 | ||
1031 | /* | 1036 | /* |
1032 | * For key todo, it'll be empty by now but the work | 1037 | * For key todo, it'll be empty by now but the work |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index e859a0ab6162..49f86fa56bff 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -650,20 +650,53 @@ static void ieee80211_sta_send_apinfo(struct ieee80211_sub_if_data *sdata, | |||
650 | static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, | 650 | static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, |
651 | struct ieee80211_if_sta *ifsta) | 651 | struct ieee80211_if_sta *ifsta) |
652 | { | 652 | { |
653 | char *buf; | ||
654 | size_t len; | ||
655 | int i; | ||
653 | union iwreq_data wrqu; | 656 | union iwreq_data wrqu; |
654 | 657 | ||
658 | if (!ifsta->assocreq_ies && !ifsta->assocresp_ies) | ||
659 | return; | ||
660 | |||
661 | buf = kmalloc(50 + 2 * (ifsta->assocreq_ies_len + | ||
662 | ifsta->assocresp_ies_len), GFP_KERNEL); | ||
663 | if (!buf) | ||
664 | return; | ||
665 | |||
666 | len = sprintf(buf, "ASSOCINFO("); | ||
655 | if (ifsta->assocreq_ies) { | 667 | if (ifsta->assocreq_ies) { |
656 | memset(&wrqu, 0, sizeof(wrqu)); | 668 | len += sprintf(buf + len, "ReqIEs="); |
657 | wrqu.data.length = ifsta->assocreq_ies_len; | 669 | for (i = 0; i < ifsta->assocreq_ies_len; i++) { |
658 | wireless_send_event(sdata->dev, IWEVASSOCREQIE, &wrqu, | 670 | len += sprintf(buf + len, "%02x", |
659 | ifsta->assocreq_ies); | 671 | ifsta->assocreq_ies[i]); |
672 | } | ||
660 | } | 673 | } |
661 | if (ifsta->assocresp_ies) { | 674 | if (ifsta->assocresp_ies) { |
675 | if (ifsta->assocreq_ies) | ||
676 | len += sprintf(buf + len, " "); | ||
677 | len += sprintf(buf + len, "RespIEs="); | ||
678 | for (i = 0; i < ifsta->assocresp_ies_len; i++) { | ||
679 | len += sprintf(buf + len, "%02x", | ||
680 | ifsta->assocresp_ies[i]); | ||
681 | } | ||
682 | } | ||
683 | len += sprintf(buf + len, ")"); | ||
684 | |||
685 | if (len > IW_CUSTOM_MAX) { | ||
686 | len = sprintf(buf, "ASSOCRESPIE="); | ||
687 | for (i = 0; i < ifsta->assocresp_ies_len; i++) { | ||
688 | len += sprintf(buf + len, "%02x", | ||
689 | ifsta->assocresp_ies[i]); | ||
690 | } | ||
691 | } | ||
692 | |||
693 | if (len <= IW_CUSTOM_MAX) { | ||
662 | memset(&wrqu, 0, sizeof(wrqu)); | 694 | memset(&wrqu, 0, sizeof(wrqu)); |
663 | wrqu.data.length = ifsta->assocresp_ies_len; | 695 | wrqu.data.length = len; |
664 | wireless_send_event(sdata->dev, IWEVASSOCRESPIE, &wrqu, | 696 | wireless_send_event(sdata->dev, IWEVCUSTOM, &wrqu, buf); |
665 | ifsta->assocresp_ies); | ||
666 | } | 697 | } |
698 | |||
699 | kfree(buf); | ||
667 | } | 700 | } |
668 | 701 | ||
669 | 702 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index eb94e584d24e..d0092f847f82 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -125,4 +125,18 @@ static inline void rc80211_pid_exit(void) | |||
125 | } | 125 | } |
126 | #endif | 126 | #endif |
127 | 127 | ||
128 | #ifdef CONFIG_MAC80211_RC_MINSTREL | ||
129 | extern int rc80211_minstrel_init(void); | ||
130 | extern void rc80211_minstrel_exit(void); | ||
131 | #else | ||
132 | static inline int rc80211_minstrel_init(void) | ||
133 | { | ||
134 | return 0; | ||
135 | } | ||
136 | static inline void rc80211_minstrel_exit(void) | ||
137 | { | ||
138 | } | ||
139 | #endif | ||
140 | |||
141 | |||
128 | #endif /* IEEE80211_RATE_H */ | 142 | #endif /* IEEE80211_RATE_H */ |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c new file mode 100644 index 000000000000..f6d69dab07a3 --- /dev/null +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -0,0 +1,583 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on minstrel.c: | ||
9 | * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> | ||
10 | * Sponsored by Indranet Technologies Ltd | ||
11 | * | ||
12 | * Based on sample.c: | ||
13 | * Copyright (c) 2005 John Bicket | ||
14 | * All rights reserved. | ||
15 | * | ||
16 | * Redistribution and use in source and binary forms, with or without | ||
17 | * modification, are permitted provided that the following conditions | ||
18 | * are met: | ||
19 | * 1. Redistributions of source code must retain the above copyright | ||
20 | * notice, this list of conditions and the following disclaimer, | ||
21 | * without modification. | ||
22 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
23 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
24 | * redistribution must be conditioned upon including a substantially | ||
25 | * similar Disclaimer requirement for further binary redistribution. | ||
26 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
27 | * of any contributors may be used to endorse or promote products derived | ||
28 | * from this software without specific prior written permission. | ||
29 | * | ||
30 | * Alternatively, this software may be distributed under the terms of the | ||
31 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
32 | * Software Foundation. | ||
33 | * | ||
34 | * NO WARRANTY | ||
35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
36 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
37 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
38 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
39 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
40 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
43 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
45 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
46 | */ | ||
47 | #include <linux/netdevice.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/skbuff.h> | ||
50 | #include <linux/debugfs.h> | ||
51 | #include <linux/random.h> | ||
52 | #include <linux/ieee80211.h> | ||
53 | #include <net/mac80211.h> | ||
54 | #include "rate.h" | ||
55 | #include "rc80211_minstrel.h" | ||
56 | |||
57 | #define SAMPLE_COLUMNS 10 | ||
58 | #define SAMPLE_TBL(_mi, _idx, _col) \ | ||
59 | _mi->sample_table[(_idx * SAMPLE_COLUMNS) + _col] | ||
60 | |||
61 | /* convert mac80211 rate index to local array index */ | ||
62 | static inline int | ||
63 | rix_to_ndx(struct minstrel_sta_info *mi, int rix) | ||
64 | { | ||
65 | int i = rix; | ||
66 | for (i = rix; i >= 0; i--) | ||
67 | if (mi->r[i].rix == rix) | ||
68 | break; | ||
69 | WARN_ON(mi->r[i].rix != rix); | ||
70 | return i; | ||
71 | } | ||
72 | |||
73 | static inline bool | ||
74 | use_low_rate(struct sk_buff *skb) | ||
75 | { | ||
76 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
77 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
78 | u16 fc; | ||
79 | |||
80 | fc = le16_to_cpu(hdr->frame_control); | ||
81 | |||
82 | return ((info->flags & IEEE80211_TX_CTL_NO_ACK) || | ||
83 | (fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || | ||
84 | is_multicast_ether_addr(hdr->addr1)); | ||
85 | } | ||
86 | |||
87 | |||
88 | static void | ||
89 | minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | ||
90 | { | ||
91 | u32 max_tp = 0, index_max_tp = 0, index_max_tp2 = 0; | ||
92 | u32 max_prob = 0, index_max_prob = 0; | ||
93 | u32 usecs; | ||
94 | u32 p; | ||
95 | int i; | ||
96 | |||
97 | mi->stats_update = jiffies; | ||
98 | for (i = 0; i < mi->n_rates; i++) { | ||
99 | struct minstrel_rate *mr = &mi->r[i]; | ||
100 | |||
101 | usecs = mr->perfect_tx_time; | ||
102 | if (!usecs) | ||
103 | usecs = 1000000; | ||
104 | |||
105 | /* To avoid rounding issues, probabilities scale from 0 (0%) | ||
106 | * to 18000 (100%) */ | ||
107 | if (mr->attempts) { | ||
108 | p = (mr->success * 18000) / mr->attempts; | ||
109 | mr->succ_hist += mr->success; | ||
110 | mr->att_hist += mr->attempts; | ||
111 | mr->cur_prob = p; | ||
112 | p = ((p * (100 - mp->ewma_level)) + (mr->probability * | ||
113 | mp->ewma_level)) / 100; | ||
114 | mr->probability = p; | ||
115 | mr->cur_tp = p * (1000000 / usecs); | ||
116 | } | ||
117 | |||
118 | mr->last_success = mr->success; | ||
119 | mr->last_attempts = mr->attempts; | ||
120 | mr->success = 0; | ||
121 | mr->attempts = 0; | ||
122 | |||
123 | /* Sample less often below the 10% chance of success. | ||
124 | * Sample less often above the 95% chance of success. */ | ||
125 | if ((mr->probability > 17100) || (mr->probability < 1800)) { | ||
126 | mr->adjusted_retry_count = mr->retry_count >> 1; | ||
127 | if (mr->adjusted_retry_count > 2) | ||
128 | mr->adjusted_retry_count = 2; | ||
129 | } else { | ||
130 | mr->adjusted_retry_count = mr->retry_count; | ||
131 | } | ||
132 | if (!mr->adjusted_retry_count) | ||
133 | mr->adjusted_retry_count = 2; | ||
134 | } | ||
135 | |||
136 | for (i = 0; i < mi->n_rates; i++) { | ||
137 | struct minstrel_rate *mr = &mi->r[i]; | ||
138 | if (max_tp < mr->cur_tp) { | ||
139 | index_max_tp = i; | ||
140 | max_tp = mr->cur_tp; | ||
141 | } | ||
142 | if (max_prob < mr->probability) { | ||
143 | index_max_prob = i; | ||
144 | max_prob = mr->probability; | ||
145 | } | ||
146 | } | ||
147 | |||
148 | max_tp = 0; | ||
149 | for (i = 0; i < mi->n_rates; i++) { | ||
150 | struct minstrel_rate *mr = &mi->r[i]; | ||
151 | |||
152 | if (i == index_max_tp) | ||
153 | continue; | ||
154 | |||
155 | if (max_tp < mr->cur_tp) { | ||
156 | index_max_tp2 = i; | ||
157 | max_tp = mr->cur_tp; | ||
158 | } | ||
159 | } | ||
160 | mi->max_tp_rate = index_max_tp; | ||
161 | mi->max_tp_rate2 = index_max_tp2; | ||
162 | mi->max_prob_rate = index_max_prob; | ||
163 | } | ||
164 | |||
165 | static void | ||
166 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | ||
167 | struct ieee80211_sta *sta, void *priv_sta, | ||
168 | struct sk_buff *skb) | ||
169 | { | ||
170 | struct minstrel_sta_info *mi = priv_sta; | ||
171 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
172 | struct ieee80211_tx_altrate *ar = info->status.retries; | ||
173 | struct minstrel_priv *mp = priv; | ||
174 | int i, ndx, tries; | ||
175 | int success = 0; | ||
176 | |||
177 | if (!info->status.excessive_retries) | ||
178 | success = 1; | ||
179 | |||
180 | if (!mp->has_mrr || (ar[0].rate_idx < 0)) { | ||
181 | ndx = rix_to_ndx(mi, info->tx_rate_idx); | ||
182 | tries = info->status.retry_count + 1; | ||
183 | mi->r[ndx].success += success; | ||
184 | mi->r[ndx].attempts += tries; | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | for (i = 0; i < 4; i++) { | ||
189 | if (ar[i].rate_idx < 0) | ||
190 | break; | ||
191 | |||
192 | ndx = rix_to_ndx(mi, ar[i].rate_idx); | ||
193 | mi->r[ndx].attempts += ar[i].limit + 1; | ||
194 | |||
195 | if ((i != 3) && (ar[i + 1].rate_idx < 0)) | ||
196 | mi->r[ndx].success += success; | ||
197 | } | ||
198 | |||
199 | if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && (i >= 0)) | ||
200 | mi->sample_count++; | ||
201 | |||
202 | if (mi->sample_deferred > 0) | ||
203 | mi->sample_deferred--; | ||
204 | } | ||
205 | |||
206 | |||
207 | static inline unsigned int | ||
208 | minstrel_get_retry_count(struct minstrel_rate *mr, | ||
209 | struct ieee80211_tx_info *info) | ||
210 | { | ||
211 | unsigned int retry = mr->adjusted_retry_count; | ||
212 | |||
213 | if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) | ||
214 | retry = max(2U, min(mr->retry_count_rtscts, retry)); | ||
215 | else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) | ||
216 | retry = max(2U, min(mr->retry_count_cts, retry)); | ||
217 | return retry; | ||
218 | } | ||
219 | |||
220 | |||
221 | static int | ||
222 | minstrel_get_next_sample(struct minstrel_sta_info *mi) | ||
223 | { | ||
224 | unsigned int sample_ndx; | ||
225 | sample_ndx = SAMPLE_TBL(mi, mi->sample_idx, mi->sample_column); | ||
226 | mi->sample_idx++; | ||
227 | if (mi->sample_idx > (mi->n_rates - 2)) { | ||
228 | mi->sample_idx = 0; | ||
229 | mi->sample_column++; | ||
230 | if (mi->sample_column >= SAMPLE_COLUMNS) | ||
231 | mi->sample_column = 0; | ||
232 | } | ||
233 | return sample_ndx; | ||
234 | } | ||
235 | |||
236 | void | ||
237 | minstrel_get_rate(void *priv, struct ieee80211_supported_band *sband, | ||
238 | struct ieee80211_sta *sta, void *priv_sta, | ||
239 | struct sk_buff *skb, struct rate_selection *sel) | ||
240 | { | ||
241 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
242 | struct minstrel_sta_info *mi = priv_sta; | ||
243 | struct minstrel_priv *mp = priv; | ||
244 | struct ieee80211_tx_altrate *ar = info->control.retries; | ||
245 | unsigned int ndx, sample_ndx = 0; | ||
246 | bool mrr; | ||
247 | bool sample_slower = false; | ||
248 | bool sample = false; | ||
249 | int i, delta; | ||
250 | int mrr_ndx[3]; | ||
251 | int sample_rate; | ||
252 | |||
253 | if (!sta || !mi || use_low_rate(skb)) { | ||
254 | sel->rate_idx = rate_lowest_index(sband, sta); | ||
255 | return; | ||
256 | } | ||
257 | |||
258 | mrr = mp->has_mrr; | ||
259 | |||
260 | /* mac80211 does not allow mrr for RTS/CTS */ | ||
261 | if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) || | ||
262 | (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT)) | ||
263 | mrr = false; | ||
264 | |||
265 | if (time_after(jiffies, mi->stats_update + (mp->update_interval * | ||
266 | HZ) / 1000)) | ||
267 | minstrel_update_stats(mp, mi); | ||
268 | |||
269 | ndx = mi->max_tp_rate; | ||
270 | |||
271 | if (mrr) | ||
272 | sample_rate = mp->lookaround_rate_mrr; | ||
273 | else | ||
274 | sample_rate = mp->lookaround_rate; | ||
275 | |||
276 | mi->packet_count++; | ||
277 | delta = (mi->packet_count * sample_rate / 100) - | ||
278 | (mi->sample_count + mi->sample_deferred / 2); | ||
279 | |||
280 | /* delta > 0: sampling required */ | ||
281 | if (delta > 0) { | ||
282 | if (mi->packet_count >= 10000) { | ||
283 | mi->sample_deferred = 0; | ||
284 | mi->sample_count = 0; | ||
285 | mi->packet_count = 0; | ||
286 | } else if (delta > mi->n_rates * 2) { | ||
287 | /* With multi-rate retry, not every planned sample | ||
288 | * attempt actually gets used, due to the way the retry | ||
289 | * chain is set up - [max_tp,sample,prob,lowest] for | ||
290 | * sample_rate < max_tp. | ||
291 | * | ||
292 | * If there's too much sampling backlog and the link | ||
293 | * starts getting worse, minstrel would start bursting | ||
294 | * out lots of sampling frames, which would result | ||
295 | * in a large throughput loss. */ | ||
296 | mi->sample_count += (delta - mi->n_rates * 2); | ||
297 | } | ||
298 | |||
299 | sample_ndx = minstrel_get_next_sample(mi); | ||
300 | sample = true; | ||
301 | sample_slower = mrr && (mi->r[sample_ndx].perfect_tx_time > | ||
302 | mi->r[ndx].perfect_tx_time); | ||
303 | |||
304 | if (!sample_slower) { | ||
305 | ndx = sample_ndx; | ||
306 | mi->sample_count++; | ||
307 | } else { | ||
308 | /* Only use IEEE80211_TX_CTL_RATE_CTRL_PROBE to mark | ||
309 | * packets that have the sampling rate deferred to the | ||
310 | * second MRR stage. Increase the sample counter only | ||
311 | * if the deferred sample rate was actually used. | ||
312 | * Use the sample_deferred counter to make sure that | ||
313 | * the sampling is not done in large bursts */ | ||
314 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | ||
315 | mi->sample_deferred++; | ||
316 | } | ||
317 | } | ||
318 | sel->rate_idx = mi->r[ndx].rix; | ||
319 | info->control.retry_limit = minstrel_get_retry_count(&mi->r[ndx], info); | ||
320 | |||
321 | if (!mrr) { | ||
322 | ar[0].rate_idx = mi->lowest_rix; | ||
323 | ar[0].limit = mp->max_retry; | ||
324 | ar[1].rate_idx = -1; | ||
325 | return; | ||
326 | } | ||
327 | |||
328 | /* MRR setup */ | ||
329 | if (sample) { | ||
330 | if (sample_slower) | ||
331 | mrr_ndx[0] = sample_ndx; | ||
332 | else | ||
333 | mrr_ndx[0] = mi->max_tp_rate; | ||
334 | } else { | ||
335 | mrr_ndx[0] = mi->max_tp_rate2; | ||
336 | } | ||
337 | mrr_ndx[1] = mi->max_prob_rate; | ||
338 | mrr_ndx[2] = 0; | ||
339 | for (i = 0; i < 3; i++) { | ||
340 | ar[i].rate_idx = mi->r[mrr_ndx[i]].rix; | ||
341 | ar[i].limit = mi->r[mrr_ndx[i]].adjusted_retry_count; | ||
342 | } | ||
343 | } | ||
344 | |||
345 | |||
346 | static void | ||
347 | calc_rate_durations(struct minstrel_sta_info *mi, struct ieee80211_local *local, | ||
348 | struct minstrel_rate *d, struct ieee80211_rate *rate) | ||
349 | { | ||
350 | int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); | ||
351 | |||
352 | d->perfect_tx_time = ieee80211_frame_duration(local, 1200, | ||
353 | rate->bitrate, erp, 1); | ||
354 | d->ack_time = ieee80211_frame_duration(local, 10, | ||
355 | rate->bitrate, erp, 1); | ||
356 | } | ||
357 | |||
358 | static void | ||
359 | init_sample_table(struct minstrel_sta_info *mi) | ||
360 | { | ||
361 | unsigned int i, col, new_idx; | ||
362 | unsigned int n_srates = mi->n_rates - 1; | ||
363 | u8 rnd[8]; | ||
364 | |||
365 | mi->sample_column = 0; | ||
366 | mi->sample_idx = 0; | ||
367 | memset(mi->sample_table, 0, SAMPLE_COLUMNS * mi->n_rates); | ||
368 | |||
369 | for (col = 0; col < SAMPLE_COLUMNS; col++) { | ||
370 | for (i = 0; i < n_srates; i++) { | ||
371 | get_random_bytes(rnd, sizeof(rnd)); | ||
372 | new_idx = (i + rnd[i & 7]) % n_srates; | ||
373 | |||
374 | while (SAMPLE_TBL(mi, new_idx, col) != 0) | ||
375 | new_idx = (new_idx + 1) % n_srates; | ||
376 | |||
377 | /* Don't sample the slowest rate (i.e. slowest base | ||
378 | * rate). We must presume that the slowest rate works | ||
379 | * fine, or else other management frames will also be | ||
380 | * failing and the link will break */ | ||
381 | SAMPLE_TBL(mi, new_idx, col) = i + 1; | ||
382 | } | ||
383 | } | ||
384 | } | ||
385 | |||
386 | static void | ||
387 | minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | ||
388 | struct ieee80211_sta *sta, void *priv_sta) | ||
389 | { | ||
390 | struct minstrel_sta_info *mi = priv_sta; | ||
391 | struct minstrel_priv *mp = priv; | ||
392 | struct minstrel_rate *mr_ctl; | ||
393 | unsigned int i, n = 0; | ||
394 | unsigned int t_slot = 9; /* FIXME: get real slot time */ | ||
395 | |||
396 | mi->lowest_rix = rate_lowest_index(sband, sta); | ||
397 | mr_ctl = &mi->r[rix_to_ndx(mi, mi->lowest_rix)]; | ||
398 | mi->sp_ack_dur = mr_ctl->ack_time; | ||
399 | |||
400 | for (i = 0; i < sband->n_bitrates; i++) { | ||
401 | struct minstrel_rate *mr = &mi->r[n]; | ||
402 | unsigned int tx_time = 0, tx_time_cts = 0, tx_time_rtscts = 0; | ||
403 | unsigned int tx_time_single; | ||
404 | unsigned int cw = mp->cw_min; | ||
405 | |||
406 | if (!rate_supported(sta, sband->band, i)) | ||
407 | continue; | ||
408 | n++; | ||
409 | memset(mr, 0, sizeof(*mr)); | ||
410 | |||
411 | mr->rix = i; | ||
412 | mr->bitrate = sband->bitrates[i].bitrate / 5; | ||
413 | calc_rate_durations(mi, hw_to_local(mp->hw), mr, | ||
414 | &sband->bitrates[i]); | ||
415 | |||
416 | /* calculate maximum number of retransmissions before | ||
417 | * fallback (based on maximum segment size) */ | ||
418 | mr->retry_count = 1; | ||
419 | mr->retry_count_cts = 1; | ||
420 | mr->retry_count_rtscts = 1; | ||
421 | tx_time = mr->perfect_tx_time + mi->sp_ack_dur; | ||
422 | do { | ||
423 | /* add one retransmission */ | ||
424 | tx_time_single = mr->ack_time + mr->perfect_tx_time; | ||
425 | |||
426 | /* contention window */ | ||
427 | tx_time_single += t_slot + min(cw, mp->cw_max); | ||
428 | cw = (cw + 1) << 1; | ||
429 | |||
430 | tx_time += tx_time_single; | ||
431 | tx_time_cts += tx_time_single + mi->sp_ack_dur; | ||
432 | tx_time_rtscts += tx_time_single + 2 * mi->sp_ack_dur; | ||
433 | if ((tx_time_cts < mp->segment_size) && | ||
434 | (mr->retry_count_cts < mp->max_retry)) | ||
435 | mr->retry_count_cts++; | ||
436 | if ((tx_time_rtscts < mp->segment_size) && | ||
437 | (mr->retry_count_rtscts < mp->max_retry)) | ||
438 | mr->retry_count_rtscts++; | ||
439 | } while ((tx_time < mp->segment_size) && | ||
440 | (++mr->retry_count < mp->max_retry)); | ||
441 | mr->adjusted_retry_count = mr->retry_count; | ||
442 | } | ||
443 | |||
444 | for (i = n; i < sband->n_bitrates; i++) { | ||
445 | struct minstrel_rate *mr = &mi->r[i]; | ||
446 | mr->rix = -1; | ||
447 | } | ||
448 | |||
449 | mi->n_rates = n; | ||
450 | mi->stats_update = jiffies; | ||
451 | |||
452 | init_sample_table(mi); | ||
453 | } | ||
454 | |||
455 | static void * | ||
456 | minstrel_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) | ||
457 | { | ||
458 | struct ieee80211_supported_band *sband; | ||
459 | struct minstrel_sta_info *mi; | ||
460 | struct minstrel_priv *mp = priv; | ||
461 | struct ieee80211_hw *hw = mp->hw; | ||
462 | int max_rates = 0; | ||
463 | int i; | ||
464 | |||
465 | mi = kzalloc(sizeof(struct minstrel_sta_info), gfp); | ||
466 | if (!mi) | ||
467 | return NULL; | ||
468 | |||
469 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
470 | sband = hw->wiphy->bands[hw->conf.channel->band]; | ||
471 | if (sband->n_bitrates > max_rates) | ||
472 | max_rates = sband->n_bitrates; | ||
473 | } | ||
474 | |||
475 | mi->r = kzalloc(sizeof(struct minstrel_rate) * max_rates, gfp); | ||
476 | if (!mi->r) | ||
477 | goto error; | ||
478 | |||
479 | mi->sample_table = kmalloc(SAMPLE_COLUMNS * max_rates, gfp); | ||
480 | if (!mi->sample_table) | ||
481 | goto error1; | ||
482 | |||
483 | mi->stats_update = jiffies; | ||
484 | return mi; | ||
485 | |||
486 | error1: | ||
487 | kfree(mi->r); | ||
488 | error: | ||
489 | kfree(mi); | ||
490 | return NULL; | ||
491 | } | ||
492 | |||
493 | static void | ||
494 | minstrel_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) | ||
495 | { | ||
496 | struct minstrel_sta_info *mi = priv_sta; | ||
497 | |||
498 | kfree(mi->sample_table); | ||
499 | kfree(mi->r); | ||
500 | kfree(mi); | ||
501 | } | ||
502 | |||
503 | static void | ||
504 | minstrel_clear(void *priv) | ||
505 | { | ||
506 | } | ||
507 | |||
508 | static void * | ||
509 | minstrel_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) | ||
510 | { | ||
511 | struct minstrel_priv *mp; | ||
512 | |||
513 | mp = kzalloc(sizeof(struct minstrel_priv), GFP_ATOMIC); | ||
514 | if (!mp) | ||
515 | return NULL; | ||
516 | |||
517 | /* contention window settings | ||
518 | * Just an approximation. Using the per-queue values would complicate | ||
519 | * the calculations and is probably unnecessary */ | ||
520 | mp->cw_min = 15; | ||
521 | mp->cw_max = 1023; | ||
522 | |||
523 | /* number of packets (in %) to use for sampling other rates | ||
524 | * sample less often for non-mrr packets, because the overhead | ||
525 | * is much higher than with mrr */ | ||
526 | mp->lookaround_rate = 5; | ||
527 | mp->lookaround_rate_mrr = 10; | ||
528 | |||
529 | /* moving average weight for EWMA */ | ||
530 | mp->ewma_level = 75; | ||
531 | |||
532 | /* maximum time that the hw is allowed to stay in one MRR segment */ | ||
533 | mp->segment_size = 6000; | ||
534 | |||
535 | if (hw->max_altrate_tries > 0) | ||
536 | mp->max_retry = hw->max_altrate_tries; | ||
537 | else | ||
538 | /* safe default, does not necessarily have to match hw properties */ | ||
539 | mp->max_retry = 7; | ||
540 | |||
541 | if (hw->max_altrates >= 3) | ||
542 | mp->has_mrr = true; | ||
543 | |||
544 | mp->hw = hw; | ||
545 | mp->update_interval = 100; | ||
546 | |||
547 | return mp; | ||
548 | } | ||
549 | |||
550 | static void | ||
551 | minstrel_free(void *priv) | ||
552 | { | ||
553 | kfree(priv); | ||
554 | } | ||
555 | |||
556 | static struct rate_control_ops mac80211_minstrel = { | ||
557 | .name = "minstrel", | ||
558 | .tx_status = minstrel_tx_status, | ||
559 | .get_rate = minstrel_get_rate, | ||
560 | .rate_init = minstrel_rate_init, | ||
561 | .clear = minstrel_clear, | ||
562 | .alloc = minstrel_alloc, | ||
563 | .free = minstrel_free, | ||
564 | .alloc_sta = minstrel_alloc_sta, | ||
565 | .free_sta = minstrel_free_sta, | ||
566 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
567 | .add_sta_debugfs = minstrel_add_sta_debugfs, | ||
568 | .remove_sta_debugfs = minstrel_remove_sta_debugfs, | ||
569 | #endif | ||
570 | }; | ||
571 | |||
572 | int __init | ||
573 | rc80211_minstrel_init(void) | ||
574 | { | ||
575 | return ieee80211_rate_control_register(&mac80211_minstrel); | ||
576 | } | ||
577 | |||
578 | void | ||
579 | rc80211_minstrel_exit(void) | ||
580 | { | ||
581 | ieee80211_rate_control_unregister(&mac80211_minstrel); | ||
582 | } | ||
583 | |||
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h new file mode 100644 index 000000000000..9a90a6aee043 --- /dev/null +++ b/net/mac80211/rc80211_minstrel.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef __RC_MINSTREL_H | ||
10 | #define __RC_MINSTREL_H | ||
11 | |||
12 | struct minstrel_rate { | ||
13 | int bitrate; | ||
14 | int rix; | ||
15 | |||
16 | unsigned int perfect_tx_time; | ||
17 | unsigned int ack_time; | ||
18 | |||
19 | unsigned int retry_count; | ||
20 | unsigned int retry_count_cts; | ||
21 | unsigned int retry_count_rtscts; | ||
22 | unsigned int adjusted_retry_count; | ||
23 | |||
24 | u32 success; | ||
25 | u32 attempts; | ||
26 | u32 last_attempts; | ||
27 | u32 last_success; | ||
28 | |||
29 | /* parts per thousand */ | ||
30 | u32 cur_prob; | ||
31 | u32 probability; | ||
32 | |||
33 | /* per-rate throughput */ | ||
34 | u32 cur_tp; | ||
35 | u32 throughput; | ||
36 | |||
37 | u64 succ_hist; | ||
38 | u64 att_hist; | ||
39 | }; | ||
40 | |||
41 | struct minstrel_sta_info { | ||
42 | unsigned long stats_update; | ||
43 | unsigned int sp_ack_dur; | ||
44 | unsigned int rate_avg; | ||
45 | |||
46 | unsigned int lowest_rix; | ||
47 | |||
48 | unsigned int max_tp_rate; | ||
49 | unsigned int max_tp_rate2; | ||
50 | unsigned int max_prob_rate; | ||
51 | unsigned int packet_count; | ||
52 | unsigned int sample_count; | ||
53 | int sample_deferred; | ||
54 | |||
55 | unsigned int sample_idx; | ||
56 | unsigned int sample_column; | ||
57 | |||
58 | int n_rates; | ||
59 | struct minstrel_rate *r; | ||
60 | |||
61 | /* sampling table */ | ||
62 | u8 *sample_table; | ||
63 | |||
64 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
65 | struct dentry *dbg_stats; | ||
66 | #endif | ||
67 | }; | ||
68 | |||
69 | struct minstrel_priv { | ||
70 | struct ieee80211_hw *hw; | ||
71 | bool has_mrr; | ||
72 | unsigned int cw_min; | ||
73 | unsigned int cw_max; | ||
74 | unsigned int max_retry; | ||
75 | unsigned int ewma_level; | ||
76 | unsigned int segment_size; | ||
77 | unsigned int update_interval; | ||
78 | unsigned int lookaround_rate; | ||
79 | unsigned int lookaround_rate_mrr; | ||
80 | }; | ||
81 | |||
82 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | ||
83 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | ||
84 | |||
85 | #endif | ||
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c new file mode 100644 index 000000000000..0b024cd6b809 --- /dev/null +++ b/net/mac80211/rc80211_minstrel_debugfs.c | |||
@@ -0,0 +1,164 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on minstrel.c: | ||
9 | * Copyright (C) 2005-2007 Derek Smithies <derek@indranet.co.nz> | ||
10 | * Sponsored by Indranet Technologies Ltd | ||
11 | * | ||
12 | * Based on sample.c: | ||
13 | * Copyright (c) 2005 John Bicket | ||
14 | * All rights reserved. | ||
15 | * | ||
16 | * Redistribution and use in source and binary forms, with or without | ||
17 | * modification, are permitted provided that the following conditions | ||
18 | * are met: | ||
19 | * 1. Redistributions of source code must retain the above copyright | ||
20 | * notice, this list of conditions and the following disclaimer, | ||
21 | * without modification. | ||
22 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
23 | * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any | ||
24 | * redistribution must be conditioned upon including a substantially | ||
25 | * similar Disclaimer requirement for further binary redistribution. | ||
26 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
27 | * of any contributors may be used to endorse or promote products derived | ||
28 | * from this software without specific prior written permission. | ||
29 | * | ||
30 | * Alternatively, this software may be distributed under the terms of the | ||
31 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
32 | * Software Foundation. | ||
33 | * | ||
34 | * NO WARRANTY | ||
35 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
36 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
37 | * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY | ||
38 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | ||
39 | * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, | ||
40 | * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
41 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
42 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER | ||
43 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
44 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | ||
45 | * THE POSSIBILITY OF SUCH DAMAGES. | ||
46 | */ | ||
47 | #include <linux/netdevice.h> | ||
48 | #include <linux/types.h> | ||
49 | #include <linux/skbuff.h> | ||
50 | #include <linux/debugfs.h> | ||
51 | #include <linux/ieee80211.h> | ||
52 | #include <net/mac80211.h> | ||
53 | #include "rc80211_minstrel.h" | ||
54 | |||
55 | struct minstrel_stats_info { | ||
56 | struct minstrel_sta_info *mi; | ||
57 | char buf[4096]; | ||
58 | size_t len; | ||
59 | }; | ||
60 | |||
61 | static int | ||
62 | minstrel_stats_open(struct inode *inode, struct file *file) | ||
63 | { | ||
64 | struct minstrel_sta_info *mi = inode->i_private; | ||
65 | struct minstrel_stats_info *ms; | ||
66 | unsigned int i, tp, prob, eprob; | ||
67 | char *p; | ||
68 | |||
69 | ms = kmalloc(sizeof(*ms), GFP_KERNEL); | ||
70 | if (!ms) | ||
71 | return -ENOMEM; | ||
72 | |||
73 | file->private_data = ms; | ||
74 | p = ms->buf; | ||
75 | p += sprintf(p, "rate throughput ewma prob this prob " | ||
76 | "this succ/attempt success attempts\n"); | ||
77 | for (i = 0; i < mi->n_rates; i++) { | ||
78 | struct minstrel_rate *mr = &mi->r[i]; | ||
79 | |||
80 | *(p++) = (i == mi->max_tp_rate) ? 'T' : ' '; | ||
81 | *(p++) = (i == mi->max_tp_rate2) ? 't' : ' '; | ||
82 | *(p++) = (i == mi->max_prob_rate) ? 'P' : ' '; | ||
83 | p += sprintf(p, "%3u%s", mr->bitrate / 2, | ||
84 | (mr->bitrate & 1 ? ".5" : " ")); | ||
85 | |||
86 | tp = ((mr->cur_tp * 96) / 18000) >> 10; | ||
87 | prob = mr->cur_prob / 18; | ||
88 | eprob = mr->probability / 18; | ||
89 | |||
90 | p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u " | ||
91 | "%3u(%3u) %8llu %8llu\n", | ||
92 | tp / 10, tp % 10, | ||
93 | eprob / 10, eprob % 10, | ||
94 | prob / 10, prob % 10, | ||
95 | mr->last_success, | ||
96 | mr->last_attempts, | ||
97 | mr->succ_hist, | ||
98 | mr->att_hist); | ||
99 | } | ||
100 | p += sprintf(p, "\nTotal packet count:: ideal %d " | ||
101 | "lookaround %d\n\n", | ||
102 | mi->packet_count - mi->sample_count, | ||
103 | mi->sample_count); | ||
104 | ms->len = p - ms->buf; | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static int | ||
110 | minstrel_stats_read(struct file *file, char __user *buf, size_t len, loff_t *o) | ||
111 | { | ||
112 | struct minstrel_stats_info *ms; | ||
113 | char *src; | ||
114 | |||
115 | ms = file->private_data; | ||
116 | src = ms->buf; | ||
117 | |||
118 | len = min(len, ms->len); | ||
119 | if (len <= *o) | ||
120 | return 0; | ||
121 | |||
122 | src += *o; | ||
123 | len -= *o; | ||
124 | *o += len; | ||
125 | |||
126 | if (copy_to_user(buf, src, len)) | ||
127 | return -EFAULT; | ||
128 | |||
129 | return len; | ||
130 | } | ||
131 | |||
132 | static int | ||
133 | minstrel_stats_release(struct inode *inode, struct file *file) | ||
134 | { | ||
135 | struct minstrel_stats_info *ms = file->private_data; | ||
136 | |||
137 | kfree(ms); | ||
138 | |||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static struct file_operations minstrel_stat_fops = { | ||
143 | .owner = THIS_MODULE, | ||
144 | .open = minstrel_stats_open, | ||
145 | .read = minstrel_stats_read, | ||
146 | .release = minstrel_stats_release, | ||
147 | }; | ||
148 | |||
149 | void | ||
150 | minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir) | ||
151 | { | ||
152 | struct minstrel_sta_info *mi = priv_sta; | ||
153 | |||
154 | mi->dbg_stats = debugfs_create_file("rc_stats", S_IRUGO, dir, mi, | ||
155 | &minstrel_stat_fops); | ||
156 | } | ||
157 | |||
158 | void | ||
159 | minstrel_remove_sta_debugfs(void *priv, void *priv_sta) | ||
160 | { | ||
161 | struct minstrel_sta_info *mi = priv_sta; | ||
162 | |||
163 | debugfs_remove(mi->dbg_stats); | ||
164 | } | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 0cc2e23f082c..1460537faf33 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -454,15 +454,16 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
454 | if (unlikely(rsel.probe_idx >= 0)) { | 454 | if (unlikely(rsel.probe_idx >= 0)) { |
455 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; | 455 | info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; |
456 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; | 456 | tx->flags |= IEEE80211_TX_PROBE_LAST_FRAG; |
457 | info->control.alt_retry_rate_idx = tx->rate_idx; | 457 | info->control.retries[0].rate_idx = tx->rate_idx; |
458 | info->control.retries[0].limit = tx->local->hw.max_altrate_tries; | ||
458 | tx->rate_idx = rsel.probe_idx; | 459 | tx->rate_idx = rsel.probe_idx; |
459 | } else | 460 | } else if (info->control.retries[0].limit == 0) |
460 | info->control.alt_retry_rate_idx = -1; | 461 | info->control.retries[0].rate_idx = -1; |
461 | 462 | ||
462 | if (unlikely(tx->rate_idx < 0)) | 463 | if (unlikely(tx->rate_idx < 0)) |
463 | return TX_DROP; | 464 | return TX_DROP; |
464 | } else | 465 | } else |
465 | info->control.alt_retry_rate_idx = -1; | 466 | info->control.retries[0].rate_idx = -1; |
466 | 467 | ||
467 | if (tx->sdata->bss_conf.use_cts_prot && | 468 | if (tx->sdata->bss_conf.use_cts_prot && |
468 | (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { | 469 | (tx->flags & IEEE80211_TX_FRAGMENTED) && (rsel.nonerp_idx >= 0)) { |
@@ -521,7 +522,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
521 | * frames. | 522 | * frames. |
522 | * TODO: The last fragment could still use multiple retry | 523 | * TODO: The last fragment could still use multiple retry |
523 | * rates. */ | 524 | * rates. */ |
524 | info->control.alt_retry_rate_idx = -1; | 525 | info->control.retries[0].rate_idx = -1; |
525 | } | 526 | } |
526 | 527 | ||
527 | /* Use CTS protection for unicast frames sent using extended rates if | 528 | /* Use CTS protection for unicast frames sent using extended rates if |
@@ -551,7 +552,7 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx) | |||
551 | int idx; | 552 | int idx; |
552 | 553 | ||
553 | /* Do not use multiple retry rates when using RTS/CTS */ | 554 | /* Do not use multiple retry rates when using RTS/CTS */ |
554 | info->control.alt_retry_rate_idx = -1; | 555 | info->control.retries[0].rate_idx = -1; |
555 | 556 | ||
556 | /* Use min(data rate, max base rate) as CTS/RTS rate */ | 557 | /* Use min(data rate, max base rate) as CTS/RTS rate */ |
557 | rate = &sband->bitrates[tx->rate_idx]; | 558 | rate = &sband->bitrates[tx->rate_idx]; |
@@ -1255,8 +1256,7 @@ static int ieee80211_skb_resize(struct ieee80211_local *local, | |||
1255 | return 0; | 1256 | return 0; |
1256 | } | 1257 | } |
1257 | 1258 | ||
1258 | int ieee80211_master_start_xmit(struct sk_buff *skb, | 1259 | int ieee80211_master_start_xmit(struct sk_buff *skb, struct net_device *dev) |
1259 | struct net_device *dev) | ||
1260 | { | 1260 | { |
1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); | 1261 | struct ieee80211_master_priv *mpriv = netdev_priv(dev); |
1262 | struct ieee80211_local *local = mpriv->local; | 1262 | struct ieee80211_local *local = mpriv->local; |
@@ -1296,20 +1296,16 @@ int ieee80211_master_start_xmit(struct sk_buff *skb, | |||
1296 | 1296 | ||
1297 | if (ieee80211_vif_is_mesh(&osdata->vif) && | 1297 | if (ieee80211_vif_is_mesh(&osdata->vif) && |
1298 | ieee80211_is_data(hdr->frame_control)) { | 1298 | ieee80211_is_data(hdr->frame_control)) { |
1299 | if (ieee80211_is_data(hdr->frame_control)) { | 1299 | if (is_multicast_ether_addr(hdr->addr3)) |
1300 | if (is_multicast_ether_addr(hdr->addr3)) | 1300 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); |
1301 | memcpy(hdr->addr1, hdr->addr3, ETH_ALEN); | 1301 | else |
1302 | else | 1302 | if (mesh_nexthop_lookup(skb, osdata)) |
1303 | if (mesh_nexthop_lookup(skb, osdata)) | 1303 | return 0; |
1304 | return 0; | 1304 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) |
1305 | if (memcmp(odev->dev_addr, hdr->addr4, ETH_ALEN) != 0) | 1305 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, |
1306 | IEEE80211_IFSTA_MESH_CTR_INC(&osdata->u.mesh, | 1306 | fwded_frames); |
1307 | fwded_frames); | ||
1308 | } | ||
1309 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { | 1307 | } else if (unlikely(osdata->vif.type == NL80211_IFTYPE_MONITOR)) { |
1310 | struct ieee80211_sub_if_data *sdata; | 1308 | struct ieee80211_sub_if_data *sdata; |
1311 | struct ieee80211_local *local = osdata->local; | ||
1312 | struct ieee80211_hdr *hdr; | ||
1313 | int hdrlen; | 1309 | int hdrlen; |
1314 | u16 len_rthdr; | 1310 | u16 len_rthdr; |
1315 | 1311 | ||
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 376c84987e4f..f0e2d3ecb5c4 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -313,9 +313,6 @@ static int wep_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
313 | { | 313 | { |
314 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 314 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
315 | 315 | ||
316 | info->control.iv_len = WEP_IV_LEN; | ||
317 | info->control.icv_len = WEP_ICV_LEN; | ||
318 | |||
319 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { | 316 | if (!(tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { |
320 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) | 317 | if (ieee80211_wep_encrypt(tx->local, skb, tx->key)) |
321 | return -1; | 318 | return -1; |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 37ae9a959f63..6db649480e8f 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -152,9 +152,6 @@ static int tkip_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
152 | int len, tail; | 152 | int len, tail; |
153 | u8 *pos; | 153 | u8 *pos; |
154 | 154 | ||
155 | info->control.icv_len = TKIP_ICV_LEN; | ||
156 | info->control.iv_len = TKIP_IV_LEN; | ||
157 | |||
158 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 155 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
159 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 156 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
160 | /* hwaccel - with no need for preallocated room for IV/ICV */ | 157 | /* hwaccel - with no need for preallocated room for IV/ICV */ |
@@ -374,9 +371,6 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
374 | u8 *pos, *pn; | 371 | u8 *pos, *pn; |
375 | int i; | 372 | int i; |
376 | 373 | ||
377 | info->control.icv_len = CCMP_MIC_LEN; | ||
378 | info->control.iv_len = CCMP_HDR_LEN; | ||
379 | |||
380 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && | 374 | if ((tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) && |
381 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { | 375 | !(tx->key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) { |
382 | /* hwaccel - with no need for preallocated room for CCMP " | 376 | /* hwaccel - with no need for preallocated room for CCMP " |
diff --git a/net/rfkill/rfkill.c b/net/rfkill/rfkill.c index ea0dc04b3c77..f949a482b007 100644 --- a/net/rfkill/rfkill.c +++ b/net/rfkill/rfkill.c | |||
@@ -125,6 +125,7 @@ static void rfkill_led_trigger_activate(struct led_classdev *led) | |||
125 | 125 | ||
126 | static void notify_rfkill_state_change(struct rfkill *rfkill) | 126 | static void notify_rfkill_state_change(struct rfkill *rfkill) |
127 | { | 127 | { |
128 | rfkill_led_trigger(rfkill, rfkill->state); | ||
128 | blocking_notifier_call_chain(&rfkill_notifier_list, | 129 | blocking_notifier_call_chain(&rfkill_notifier_list, |
129 | RFKILL_STATE_CHANGED, | 130 | RFKILL_STATE_CHANGED, |
130 | rfkill); | 131 | rfkill); |
@@ -217,10 +218,8 @@ static int rfkill_toggle_radio(struct rfkill *rfkill, | |||
217 | rfkill->state = state; | 218 | rfkill->state = state; |
218 | } | 219 | } |
219 | 220 | ||
220 | if (force || rfkill->state != oldstate) { | 221 | if (force || rfkill->state != oldstate) |
221 | rfkill_led_trigger(rfkill, rfkill->state); | ||
222 | notify_rfkill_state_change(rfkill); | 222 | notify_rfkill_state_change(rfkill); |
223 | } | ||
224 | 223 | ||
225 | return retval; | 224 | return retval; |
226 | } | 225 | } |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index b97bd9fe6b79..7d82be07fa1d 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -15,7 +15,7 @@ config NL80211 | |||
15 | If unsure, say Y. | 15 | If unsure, say Y. |
16 | 16 | ||
17 | config WIRELESS_OLD_REGULATORY | 17 | config WIRELESS_OLD_REGULATORY |
18 | bool "Old wireless static regulatory defintions" | 18 | bool "Old wireless static regulatory definitions" |
19 | default n | 19 | default n |
20 | ---help--- | 20 | ---help--- |
21 | This option enables the old static regulatory information | 21 | This option enables the old static regulatory information |