diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2012-06-04 10:54:07 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-06-06 15:20:32 -0400 |
commit | 07c15a3ffd68ff1a3276daa26885b277f19e4abd (patch) | |
tree | 54e487efbff040565f647b99b3e49111533140ad /drivers/net/wireless/ath | |
parent | b74713d04effbacd3d126ce94cec18742187b6ce (diff) |
ath9k: Fix powersave locking
The 'ps_flags' is used/accessed in a variety of contexts
and requires proper locking. Use 'sc_pm_lock' appropriately.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 3 |
3 files changed, 21 insertions, 9 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 34d6f26c6bc7..88f7ad106e05 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -345,7 +345,7 @@ void ath9k_tasklet(unsigned long data) | |||
345 | struct ath_softc *sc = (struct ath_softc *)data; | 345 | struct ath_softc *sc = (struct ath_softc *)data; |
346 | struct ath_hw *ah = sc->sc_ah; | 346 | struct ath_hw *ah = sc->sc_ah; |
347 | struct ath_common *common = ath9k_hw_common(ah); | 347 | struct ath_common *common = ath9k_hw_common(ah); |
348 | 348 | unsigned long flags; | |
349 | u32 status = sc->intrstatus; | 349 | u32 status = sc->intrstatus; |
350 | u32 rxmask; | 350 | u32 rxmask; |
351 | 351 | ||
@@ -369,6 +369,7 @@ void ath9k_tasklet(unsigned long data) | |||
369 | goto out; | 369 | goto out; |
370 | } | 370 | } |
371 | 371 | ||
372 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
372 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | 373 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { |
373 | /* | 374 | /* |
374 | * TSF sync does not look correct; remain awake to sync with | 375 | * TSF sync does not look correct; remain awake to sync with |
@@ -377,6 +378,7 @@ void ath9k_tasklet(unsigned long data) | |||
377 | ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n"); | 378 | ath_dbg(common, PS, "TSFOOR - Sync with next Beacon\n"); |
378 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; | 379 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; |
379 | } | 380 | } |
381 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
380 | 382 | ||
381 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 383 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
382 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | | 384 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | |
@@ -526,8 +528,10 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
526 | /* Clear RxAbort bit so that we can | 528 | /* Clear RxAbort bit so that we can |
527 | * receive frames */ | 529 | * receive frames */ |
528 | ath9k_setpower(sc, ATH9K_PM_AWAKE); | 530 | ath9k_setpower(sc, ATH9K_PM_AWAKE); |
531 | spin_lock(&sc->sc_pm_lock); | ||
529 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 532 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
530 | sc->ps_flags |= PS_WAIT_FOR_BEACON; | 533 | sc->ps_flags |= PS_WAIT_FOR_BEACON; |
534 | spin_unlock(&sc->sc_pm_lock); | ||
531 | } | 535 | } |
532 | 536 | ||
533 | chip_reset: | 537 | chip_reset: |
@@ -682,6 +686,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
682 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 686 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
683 | struct ath_tx_control txctl; | 687 | struct ath_tx_control txctl; |
684 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 688 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
689 | unsigned long flags; | ||
685 | 690 | ||
686 | if (sc->ps_enabled) { | 691 | if (sc->ps_enabled) { |
687 | /* | 692 | /* |
@@ -704,6 +709,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
704 | * completed and if needed, also for RX of buffered frames. | 709 | * completed and if needed, also for RX of buffered frames. |
705 | */ | 710 | */ |
706 | ath9k_ps_wakeup(sc); | 711 | ath9k_ps_wakeup(sc); |
712 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
707 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) | 713 | if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) |
708 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 714 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
709 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 715 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
@@ -719,6 +725,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
719 | * the ps_flags bit is cleared. We are just dropping | 725 | * the ps_flags bit is cleared. We are just dropping |
720 | * the ps_usecount here. | 726 | * the ps_usecount here. |
721 | */ | 727 | */ |
728 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
722 | ath9k_ps_restore(sc); | 729 | ath9k_ps_restore(sc); |
723 | } | 730 | } |
724 | 731 | ||
@@ -1479,7 +1486,7 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1479 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1486 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1480 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; | 1487 | struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; |
1481 | struct ath_vif *avp = (void *)vif->drv_priv; | 1488 | struct ath_vif *avp = (void *)vif->drv_priv; |
1482 | 1489 | unsigned long flags; | |
1483 | /* | 1490 | /* |
1484 | * Skip iteration if primary station vif's bss info | 1491 | * Skip iteration if primary station vif's bss info |
1485 | * was not changed | 1492 | * was not changed |
@@ -1501,7 +1508,10 @@ static void ath9k_bss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) | |||
1501 | * on the receipt of the first Beacon frame (i.e., | 1508 | * on the receipt of the first Beacon frame (i.e., |
1502 | * after time sync with the AP). | 1509 | * after time sync with the AP). |
1503 | */ | 1510 | */ |
1511 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
1504 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | 1512 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
1513 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
1514 | |||
1505 | /* Reset rssi stats */ | 1515 | /* Reset rssi stats */ |
1506 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; | 1516 | sc->last_rssi = ATH_RSSI_DUMMY_MARKER; |
1507 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | 1517 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index b54e15941ba4..fbdcc80437fe 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -587,13 +587,13 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb, bool mybeacon) | |||
587 | 587 | ||
588 | /* Process Beacon and CAB receive in PS state */ | 588 | /* Process Beacon and CAB receive in PS state */ |
589 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) | 589 | if (((sc->ps_flags & PS_WAIT_FOR_BEACON) || ath9k_check_auto_sleep(sc)) |
590 | && mybeacon) | 590 | && mybeacon) { |
591 | ath_rx_ps_beacon(sc, skb); | 591 | ath_rx_ps_beacon(sc, skb); |
592 | else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && | 592 | } else if ((sc->ps_flags & PS_WAIT_FOR_CAB) && |
593 | (ieee80211_is_data(hdr->frame_control) || | 593 | (ieee80211_is_data(hdr->frame_control) || |
594 | ieee80211_is_action(hdr->frame_control)) && | 594 | ieee80211_is_action(hdr->frame_control)) && |
595 | is_multicast_ether_addr(hdr->addr1) && | 595 | is_multicast_ether_addr(hdr->addr1) && |
596 | !ieee80211_has_moredata(hdr->frame_control)) { | 596 | !ieee80211_has_moredata(hdr->frame_control)) { |
597 | /* | 597 | /* |
598 | * No more broadcast/multicast frames to be received at this | 598 | * No more broadcast/multicast frames to be received at this |
599 | * point. | 599 | * point. |
@@ -1229,7 +1229,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1229 | skb_trim(skb, skb->len - 8); | 1229 | skb_trim(skb, skb->len - 8); |
1230 | 1230 | ||
1231 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 1231 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
1232 | |||
1233 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | | 1232 | if ((sc->ps_flags & (PS_WAIT_FOR_BEACON | |
1234 | PS_WAIT_FOR_CAB | | 1233 | PS_WAIT_FOR_CAB | |
1235 | PS_WAIT_FOR_PSPOLL_DATA)) || | 1234 | PS_WAIT_FOR_PSPOLL_DATA)) || |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index bb74780903d5..f777ddcd1172 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1994,6 +1994,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1994 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1994 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1995 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; | 1995 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; |
1996 | int q, padpos, padsize; | 1996 | int q, padpos, padsize; |
1997 | unsigned long flags; | ||
1997 | 1998 | ||
1998 | ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); | 1999 | ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); |
1999 | 2000 | ||
@@ -2012,6 +2013,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
2012 | skb_pull(skb, padsize); | 2013 | skb_pull(skb, padsize); |
2013 | } | 2014 | } |
2014 | 2015 | ||
2016 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
2015 | if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { | 2017 | if ((sc->ps_flags & PS_WAIT_FOR_TX_ACK) && !txq->axq_depth) { |
2016 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; | 2018 | sc->ps_flags &= ~PS_WAIT_FOR_TX_ACK; |
2017 | ath_dbg(common, PS, | 2019 | ath_dbg(common, PS, |
@@ -2021,6 +2023,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
2021 | PS_WAIT_FOR_PSPOLL_DATA | | 2023 | PS_WAIT_FOR_PSPOLL_DATA | |
2022 | PS_WAIT_FOR_TX_ACK)); | 2024 | PS_WAIT_FOR_TX_ACK)); |
2023 | } | 2025 | } |
2026 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
2024 | 2027 | ||
2025 | q = skb_get_queue_mapping(skb); | 2028 | q = skb_get_queue_mapping(skb); |
2026 | if (txq == sc->tx.txq_map[q]) { | 2029 | if (txq == sc->tx.txq_map[q]) { |