aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2012-06-04 10:54:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-06-06 15:20:32 -0400
commit07c15a3ffd68ff1a3276daa26885b277f19e4abd (patch)
tree54e487efbff040565f647b99b3e49111533140ad /drivers/net/wireless/ath
parentb74713d04effbacd3d126ce94cec18742187b6ce (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.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c3
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
533chip_reset: 537chip_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]) {