1 --- a/drivers/net/wireless/ath/ath5k/ath5k.h
2 +++ b/drivers/net/wireless/ath/ath5k/ath5k.h
3 @@ -872,6 +872,19 @@ enum ath5k_int {
4 AR5K_INT_QTRIG = 0x40000000, /* Non common */
5 AR5K_INT_GLOBAL = 0x80000000,
7 + AR5K_INT_TX_ALL = AR5K_INT_TXOK
13 + AR5K_INT_RX_ALL = AR5K_INT_RXOK
20 AR5K_INT_COMMON = AR5K_INT_RXOK
23 --- a/drivers/net/wireless/ath/ath5k/base.c
24 +++ b/drivers/net/wireless/ath/ath5k/base.c
25 @@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_soft
29 +ath5k_set_current_imask(struct ath5k_softc *sc)
31 + enum ath5k_int imask = sc->imask;
32 + unsigned long flags;
34 + spin_lock_irqsave(&sc->irqlock, flags);
36 + imask &= ~AR5K_INT_RX_ALL;
38 + imask &= ~AR5K_INT_TX_ALL;
39 + ath5k_hw_set_imr(sc->ah, imask);
40 + spin_unlock_irqrestore(&sc->irqlock, flags);
44 ath5k_tasklet_rx(unsigned long data)
46 struct ath5k_rx_status rs = {};
47 @@ -1506,6 +1521,8 @@ next:
48 } while (ath5k_rxbuf_setup(sc, bf) == 0);
50 spin_unlock(&sc->rxbuflock);
51 + sc->rx_pending = false;
52 + ath5k_set_current_imask(sc);
56 @@ -1693,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)
57 for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
58 if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
59 ath5k_tx_processq(sc, &sc->txqs[i]);
61 + sc->tx_pending = false;
62 + ath5k_set_current_imask(sc);
66 @@ -2122,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k
67 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
71 +ath5k_schedule_rx(struct ath5k_softc *sc)
73 + sc->rx_pending = true;
74 + tasklet_schedule(&sc->rxtq);
78 +ath5k_schedule_tx(struct ath5k_softc *sc)
80 + sc->tx_pending = true;
81 + tasklet_schedule(&sc->txtq);
85 ath5k_intr(int irq, void *dev_id)
87 @@ -2164,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)
88 ieee80211_queue_work(sc->hw, &sc->reset_work);
91 - tasklet_schedule(&sc->rxtq);
92 + ath5k_schedule_rx(sc);
94 if (status & AR5K_INT_SWBA) {
95 tasklet_hi_schedule(&sc->beacontq);
96 @@ -2182,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)
97 ath5k_hw_update_tx_triglevel(ah, true);
99 if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
100 - tasklet_schedule(&sc->rxtq);
101 + ath5k_schedule_rx(sc);
102 if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
103 | AR5K_INT_TXERR | AR5K_INT_TXEOL))
104 - tasklet_schedule(&sc->txtq);
105 + ath5k_schedule_tx(sc);
106 if (status & AR5K_INT_BMISS) {
109 @@ -2204,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)
111 } while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
113 + if (sc->rx_pending || sc->tx_pending)
114 + ath5k_set_current_imask(sc);
116 if (unlikely(!counter))
117 ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
119 @@ -2575,6 +2612,8 @@ done:
121 static void stop_tasklets(struct ath5k_softc *sc)
123 + sc->rx_pending = false;
124 + sc->tx_pending = false;
125 tasklet_kill(&sc->rxtq);
126 tasklet_kill(&sc->txtq);
127 tasklet_kill(&sc->calib);
128 --- a/drivers/net/wireless/ath/ath5k/base.h
129 +++ b/drivers/net/wireless/ath/ath5k/base.h
130 @@ -207,6 +207,10 @@ struct ath5k_softc {
132 enum ath5k_int imask; /* interrupt mask copy */
134 + spinlock_t irqlock;
135 + bool rx_pending; /* rx tasklet pending */
136 + bool tx_pending; /* tx tasklet pending */
139 u8 bssidmask[ETH_ALEN];