diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/recv.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 92 |
1 files changed, 64 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index cece1c4c6bda..61edfab20ffc 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -145,6 +145,10 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
145 | u8 ratecode; | 145 | u8 ratecode; |
146 | __le16 fc; | 146 | __le16 fc; |
147 | struct ieee80211_hw *hw; | 147 | struct ieee80211_hw *hw; |
148 | struct ieee80211_sta *sta; | ||
149 | struct ath_node *an; | ||
150 | int last_rssi = ATH_RSSI_DUMMY_MARKER; | ||
151 | |||
148 | 152 | ||
149 | hdr = (struct ieee80211_hdr *)skb->data; | 153 | hdr = (struct ieee80211_hdr *)skb->data; |
150 | fc = hdr->frame_control; | 154 | fc = hdr->frame_control; |
@@ -229,17 +233,57 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
229 | } | 233 | } |
230 | } | 234 | } |
231 | 235 | ||
236 | rcu_read_lock(); | ||
237 | sta = ieee80211_find_sta(sc->hw, hdr->addr2); | ||
238 | if (sta) { | ||
239 | an = (struct ath_node *) sta->drv_priv; | ||
240 | if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD && | ||
241 | !ds->ds_rxstat.rs_moreaggr) | ||
242 | ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi); | ||
243 | last_rssi = an->last_rssi; | ||
244 | } | ||
245 | rcu_read_unlock(); | ||
246 | |||
247 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | ||
248 | ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi, | ||
249 | ATH_RSSI_EP_MULTIPLIER); | ||
250 | if (ds->ds_rxstat.rs_rssi < 0) | ||
251 | ds->ds_rxstat.rs_rssi = 0; | ||
252 | else if (ds->ds_rxstat.rs_rssi > 127) | ||
253 | ds->ds_rxstat.rs_rssi = 127; | ||
254 | |||
232 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | 255 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); |
233 | rx_status->band = hw->conf.channel->band; | 256 | rx_status->band = hw->conf.channel->band; |
234 | rx_status->freq = hw->conf.channel->center_freq; | 257 | rx_status->freq = hw->conf.channel->center_freq; |
235 | rx_status->noise = sc->ani.noise_floor; | 258 | rx_status->noise = sc->ani.noise_floor; |
236 | rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; | 259 | rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi; |
237 | rx_status->antenna = ds->ds_rxstat.rs_antenna; | 260 | rx_status->antenna = ds->ds_rxstat.rs_antenna; |
238 | 261 | ||
239 | /* at 45 you will be able to use MCS 15 reliably. A more elaborate | 262 | /* |
240 | * scheme can be used here but it requires tables of SNR/throughput for | 263 | * Theory for reporting quality: |
241 | * each possible mode used. */ | 264 | * |
242 | rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45; | 265 | * At a hardware RSSI of 45 you will be able to use MCS 7 reliably. |
266 | * At a hardware RSSI of 45 you will be able to use MCS 15 reliably. | ||
267 | * At a hardware RSSI of 35 you should be able use 54 Mbps reliably. | ||
268 | * | ||
269 | * MCS 7 is the highets MCS index usable by a 1-stream device. | ||
270 | * MCS 15 is the highest MCS index usable by a 2-stream device. | ||
271 | * | ||
272 | * All ath9k devices are either 1-stream or 2-stream. | ||
273 | * | ||
274 | * How many bars you see is derived from the qual reporting. | ||
275 | * | ||
276 | * A more elaborate scheme can be used here but it requires tables | ||
277 | * of SNR/throughput for each possible mode used. For the MCS table | ||
278 | * you can refer to the wireless wiki: | ||
279 | * | ||
280 | * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n | ||
281 | * | ||
282 | */ | ||
283 | if (conf_is_ht(&hw->conf)) | ||
284 | rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45; | ||
285 | else | ||
286 | rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 35; | ||
243 | 287 | ||
244 | /* rssi can be more than 45 though, anything above that | 288 | /* rssi can be more than 45 though, anything above that |
245 | * should be considered at 100% */ | 289 | * should be considered at 100% */ |
@@ -505,11 +549,6 @@ static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | |||
505 | return false; | 549 | return false; |
506 | } | 550 | } |
507 | 551 | ||
508 | static void ath_rx_ps_back_to_sleep(struct ath_softc *sc) | ||
509 | { | ||
510 | sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB); | ||
511 | } | ||
512 | |||
513 | static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | 552 | static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) |
514 | { | 553 | { |
515 | struct ieee80211_mgmt *mgmt; | 554 | struct ieee80211_mgmt *mgmt; |
@@ -521,6 +560,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
521 | if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0) | 560 | if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0) |
522 | return; /* not from our current AP */ | 561 | return; /* not from our current AP */ |
523 | 562 | ||
563 | sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; | ||
564 | |||
524 | if (sc->sc_flags & SC_OP_BEACON_SYNC) { | 565 | if (sc->sc_flags & SC_OP_BEACON_SYNC) { |
525 | sc->sc_flags &= ~SC_OP_BEACON_SYNC; | 566 | sc->sc_flags &= ~SC_OP_BEACON_SYNC; |
526 | DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on " | 567 | DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on " |
@@ -528,14 +569,6 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
528 | ath_beacon_config(sc, NULL); | 569 | ath_beacon_config(sc, NULL); |
529 | } | 570 | } |
530 | 571 | ||
531 | if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) { | ||
532 | /* We are not in PS mode anymore; remain awake */ | ||
533 | DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain " | ||
534 | "awake\n"); | ||
535 | sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | SC_OP_WAIT_FOR_CAB); | ||
536 | return; | ||
537 | } | ||
538 | |||
539 | if (ath_beacon_dtim_pending_cab(skb)) { | 572 | if (ath_beacon_dtim_pending_cab(skb)) { |
540 | /* | 573 | /* |
541 | * Remain awake waiting for buffered broadcast/multicast | 574 | * Remain awake waiting for buffered broadcast/multicast |
@@ -556,11 +589,9 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
556 | * fails to send a frame indicating that all CAB frames have | 589 | * fails to send a frame indicating that all CAB frames have |
557 | * been delivered. | 590 | * been delivered. |
558 | */ | 591 | */ |
592 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; | ||
559 | DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n"); | 593 | DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n"); |
560 | } | 594 | } |
561 | |||
562 | /* No more broadcast/multicast frames to be received at this point. */ | ||
563 | ath_rx_ps_back_to_sleep(sc); | ||
564 | } | 595 | } |
565 | 596 | ||
566 | static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | 597 | static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) |
@@ -578,13 +609,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
578 | ieee80211_is_action(hdr->frame_control)) && | 609 | ieee80211_is_action(hdr->frame_control)) && |
579 | is_multicast_ether_addr(hdr->addr1) && | 610 | is_multicast_ether_addr(hdr->addr1) && |
580 | !ieee80211_has_moredata(hdr->frame_control)) { | 611 | !ieee80211_has_moredata(hdr->frame_control)) { |
581 | DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to " | ||
582 | "sleep\n"); | ||
583 | /* | 612 | /* |
584 | * No more broadcast/multicast frames to be received at this | 613 | * No more broadcast/multicast frames to be received at this |
585 | * point. | 614 | * point. |
586 | */ | 615 | */ |
587 | ath_rx_ps_back_to_sleep(sc); | 616 | sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; |
617 | DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to " | ||
618 | "sleep\n"); | ||
588 | } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && | 619 | } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && |
589 | !is_multicast_ether_addr(hdr->addr1) && | 620 | !is_multicast_ether_addr(hdr->addr1) && |
590 | !ieee80211_has_morefrags(hdr->frame_control)) { | 621 | !ieee80211_has_morefrags(hdr->frame_control)) { |
@@ -619,13 +650,18 @@ static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb, | |||
619 | if (aphy == NULL) | 650 | if (aphy == NULL) |
620 | continue; | 651 | continue; |
621 | nskb = skb_copy(skb, GFP_ATOMIC); | 652 | nskb = skb_copy(skb, GFP_ATOMIC); |
622 | if (nskb) | 653 | if (nskb) { |
623 | __ieee80211_rx(aphy->hw, nskb, rx_status); | 654 | memcpy(IEEE80211_SKB_RXCB(nskb), rx_status, |
655 | sizeof(*rx_status)); | ||
656 | ieee80211_rx(aphy->hw, nskb); | ||
657 | } | ||
624 | } | 658 | } |
625 | __ieee80211_rx(sc->hw, skb, rx_status); | 659 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); |
660 | ieee80211_rx(sc->hw, skb); | ||
626 | } else { | 661 | } else { |
627 | /* Deliver unicast frames based on receiver address */ | 662 | /* Deliver unicast frames based on receiver address */ |
628 | __ieee80211_rx(ath_get_virt_hw(sc, hdr), skb, rx_status); | 663 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); |
664 | ieee80211_rx(ath_get_virt_hw(sc, hdr), skb); | ||
629 | } | 665 | } |
630 | } | 666 | } |
631 | 667 | ||