aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath5k/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath5k/base.c')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c71
1 files changed, 56 insertions, 15 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 349a5963931..203243bacc8 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -1444,6 +1444,21 @@ ath5k_receive_frame_ok(struct ath5k_softc *sc, struct ath5k_rx_status *rs)
1444} 1444}
1445 1445
1446static void 1446static void
1447ath5k_set_current_imask(struct ath5k_softc *sc)
1448{
1449 enum ath5k_int imask = sc->imask;
1450 unsigned long flags;
1451
1452 spin_lock_irqsave(&sc->irqlock, flags);
1453 if (sc->rx_pending)
1454 imask &= ~AR5K_INT_RX_ALL;
1455 if (sc->tx_pending)
1456 imask &= ~AR5K_INT_TX_ALL;
1457 ath5k_hw_set_imr(sc->ah, imask);
1458 spin_unlock_irqrestore(&sc->irqlock, flags);
1459}
1460
1461static void
1447ath5k_tasklet_rx(unsigned long data) 1462ath5k_tasklet_rx(unsigned long data)
1448{ 1463{
1449 struct ath5k_rx_status rs = {}; 1464 struct ath5k_rx_status rs = {};
@@ -1506,6 +1521,8 @@ next:
1506 } while (ath5k_rxbuf_setup(sc, bf) == 0); 1521 } while (ath5k_rxbuf_setup(sc, bf) == 0);
1507unlock: 1522unlock:
1508 spin_unlock(&sc->rxbuflock); 1523 spin_unlock(&sc->rxbuflock);
1524 sc->rx_pending = false;
1525 ath5k_set_current_imask(sc);
1509} 1526}
1510 1527
1511 1528
@@ -1573,28 +1590,28 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
1573 struct ath5k_txq *txq, struct ath5k_tx_status *ts) 1590 struct ath5k_txq *txq, struct ath5k_tx_status *ts)
1574{ 1591{
1575 struct ieee80211_tx_info *info; 1592 struct ieee80211_tx_info *info;
1593 u8 tries[3];
1576 int i; 1594 int i;
1577 1595
1578 sc->stats.tx_all_count++; 1596 sc->stats.tx_all_count++;
1579 sc->stats.tx_bytes_count += skb->len; 1597 sc->stats.tx_bytes_count += skb->len;
1580 info = IEEE80211_SKB_CB(skb); 1598 info = IEEE80211_SKB_CB(skb);
1581 1599
1600 tries[0] = info->status.rates[0].count;
1601 tries[1] = info->status.rates[1].count;
1602 tries[2] = info->status.rates[2].count;
1603
1582 ieee80211_tx_info_clear_status(info); 1604 ieee80211_tx_info_clear_status(info);
1583 for (i = 0; i < 4; i++) { 1605
1606 for (i = 0; i < ts->ts_final_idx; i++) {
1584 struct ieee80211_tx_rate *r = 1607 struct ieee80211_tx_rate *r =
1585 &info->status.rates[i]; 1608 &info->status.rates[i];
1586 1609
1587 if (ts->ts_rate[i]) { 1610 r->count = tries[i];
1588 r->idx = ath5k_hw_to_driver_rix(sc, ts->ts_rate[i]);
1589 r->count = ts->ts_retry[i];
1590 } else {
1591 r->idx = -1;
1592 r->count = 0;
1593 }
1594 } 1611 }
1595 1612
1596 /* count the successful attempt as well */ 1613 info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
1597 info->status.rates[ts->ts_final_idx].count++; 1614 info->status.rates[ts->ts_final_idx + 1].idx = -1;
1598 1615
1599 if (unlikely(ts->ts_status)) { 1616 if (unlikely(ts->ts_status)) {
1600 sc->stats.ack_fail++; 1617 sc->stats.ack_fail++;
@@ -1609,6 +1626,9 @@ ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
1609 } else { 1626 } else {
1610 info->flags |= IEEE80211_TX_STAT_ACK; 1627 info->flags |= IEEE80211_TX_STAT_ACK;
1611 info->status.ack_signal = ts->ts_rssi; 1628 info->status.ack_signal = ts->ts_rssi;
1629
1630 /* count the successful attempt as well */
1631 info->status.rates[ts->ts_final_idx].count++;
1612 } 1632 }
1613 1633
1614 /* 1634 /*
@@ -1690,6 +1710,9 @@ ath5k_tasklet_tx(unsigned long data)
1690 for (i=0; i < AR5K_NUM_TX_QUEUES; i++) 1710 for (i=0; i < AR5K_NUM_TX_QUEUES; i++)
1691 if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) 1711 if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i)))
1692 ath5k_tx_processq(sc, &sc->txqs[i]); 1712 ath5k_tx_processq(sc, &sc->txqs[i]);
1713
1714 sc->tx_pending = false;
1715 ath5k_set_current_imask(sc);
1693} 1716}
1694 1717
1695 1718
@@ -2119,6 +2142,20 @@ ath5k_intr_calibration_poll(struct ath5k_hw *ah)
2119 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */ 2142 * AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); */
2120} 2143}
2121 2144
2145static void
2146ath5k_schedule_rx(struct ath5k_softc *sc)
2147{
2148 sc->rx_pending = true;
2149 tasklet_schedule(&sc->rxtq);
2150}
2151
2152static void
2153ath5k_schedule_tx(struct ath5k_softc *sc)
2154{
2155 sc->tx_pending = true;
2156 tasklet_schedule(&sc->txtq);
2157}
2158
2122irqreturn_t 2159irqreturn_t
2123ath5k_intr(int irq, void *dev_id) 2160ath5k_intr(int irq, void *dev_id)
2124{ 2161{
@@ -2161,7 +2198,7 @@ ath5k_intr(int irq, void *dev_id)
2161 ieee80211_queue_work(sc->hw, &sc->reset_work); 2198 ieee80211_queue_work(sc->hw, &sc->reset_work);
2162 } 2199 }
2163 else 2200 else
2164 tasklet_schedule(&sc->rxtq); 2201 ath5k_schedule_rx(sc);
2165 } else { 2202 } else {
2166 if (status & AR5K_INT_SWBA) { 2203 if (status & AR5K_INT_SWBA) {
2167 tasklet_hi_schedule(&sc->beacontq); 2204 tasklet_hi_schedule(&sc->beacontq);
@@ -2179,10 +2216,10 @@ ath5k_intr(int irq, void *dev_id)
2179 ath5k_hw_update_tx_triglevel(ah, true); 2216 ath5k_hw_update_tx_triglevel(ah, true);
2180 } 2217 }
2181 if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) 2218 if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR))
2182 tasklet_schedule(&sc->rxtq); 2219 ath5k_schedule_rx(sc);
2183 if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC 2220 if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC
2184 | AR5K_INT_TXERR | AR5K_INT_TXEOL)) 2221 | AR5K_INT_TXERR | AR5K_INT_TXEOL))
2185 tasklet_schedule(&sc->txtq); 2222 ath5k_schedule_tx(sc);
2186 if (status & AR5K_INT_BMISS) { 2223 if (status & AR5K_INT_BMISS) {
2187 /* TODO */ 2224 /* TODO */
2188 } 2225 }
@@ -2201,6 +2238,9 @@ ath5k_intr(int irq, void *dev_id)
2201 2238
2202 } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); 2239 } while (ath5k_hw_is_intr_pending(ah) && --counter > 0);
2203 2240
2241 if (sc->rx_pending || sc->tx_pending)
2242 ath5k_set_current_imask(sc);
2243
2204 if (unlikely(!counter)) 2244 if (unlikely(!counter))
2205 ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); 2245 ATH5K_WARN(sc, "too many interrupts, giving up for now\n");
2206 2246
@@ -2572,6 +2612,8 @@ done:
2572 2612
2573static void stop_tasklets(struct ath5k_softc *sc) 2613static void stop_tasklets(struct ath5k_softc *sc)
2574{ 2614{
2615 sc->rx_pending = false;
2616 sc->tx_pending = false;
2575 tasklet_kill(&sc->rxtq); 2617 tasklet_kill(&sc->rxtq);
2576 tasklet_kill(&sc->txtq); 2618 tasklet_kill(&sc->txtq);
2577 tasklet_kill(&sc->calib); 2619 tasklet_kill(&sc->calib);
@@ -2838,7 +2880,7 @@ ath5k_init(struct ieee80211_hw *hw)
2838 INIT_WORK(&sc->reset_work, ath5k_reset_work); 2880 INIT_WORK(&sc->reset_work, ath5k_reset_work);
2839 INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work); 2881 INIT_DELAYED_WORK(&sc->tx_complete_work, ath5k_tx_complete_poll_work);
2840 2882
2841 ret = ath5k_eeprom_read_mac(ah, mac); 2883 ret = ath5k_hw_common(ah)->bus_ops->eeprom_read_mac(ah, mac);
2842 if (ret) { 2884 if (ret) {
2843 ATH5K_ERR(sc, "unable to read address from EEPROM\n"); 2885 ATH5K_ERR(sc, "unable to read address from EEPROM\n");
2844 goto err_queues; 2886 goto err_queues;
@@ -2898,7 +2940,6 @@ ath5k_deinit_softc(struct ath5k_softc *sc)
2898 * XXX: ??? detach ath5k_hw ??? 2940 * XXX: ??? detach ath5k_hw ???
2899 * Other than that, it's straightforward... 2941 * Other than that, it's straightforward...
2900 */ 2942 */
2901 ath5k_debug_finish_device(sc);
2902 ieee80211_unregister_hw(hw); 2943 ieee80211_unregister_hw(hw);
2903 ath5k_desc_free(sc); 2944 ath5k_desc_free(sc);
2904 ath5k_txq_release(sc); 2945 ath5k_txq_release(sc);