aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-11-07 08:59:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:25:54 -0500
commit066dae93bdfcc7af5e38a33617773fd5c6457607 (patch)
tree27aeba1ca5cfb85f4c418fa11e01c34cbd139ec0 /drivers/net/wireless/ath/ath9k/main.c
parent21e731a1b15bf03927e292af1b4a2c84fc8af817 (diff)
ath9k: rework tx queue selection and fix queue stopping/waking
The current ath9k tx queue handling code showed a few issues that could lead to locking issues, tx stalls due to stopped queues, and maybe even DMA issues. The main source of these issues is that in some places the queue is selected via skb queue mapping in places where this mapping may no longer be valid. One such place is when data frames are transmitted via the CAB queue (for powersave buffered frames). This is made even worse by a lookup WMM AC values from the assigned tx queue (which is undefined for the CAB queue). This messed up the pending frame counting, which in turn caused issues with queues getting stopped, but not woken again. To fix these issues, this patch removes an unnecessary abstraction separating a driver internal queue number from the skb queue number (not to be confused with the hardware queue number). It seems that this abstraction may have been necessary because of tx queue preinitialization from the initvals. This patch avoids breakage here by pushing the software <-> hardware queue mapping to the function that assigns the tx queues and redefining the WMM AC definitions to match the numbers used by mac80211 (also affects ath9k_htc). To ensure consistency wrt. pending frame count tracking, these counters are moved to the ath_txq struct, updated with the txq lock held, but only where the tx queue selected by the skb queue map actually matches the tx queue used by the driver for the frame. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Reported-by: Björn Smedman <bjorn.smedman@venatech.se> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c71
1 files changed, 10 insertions, 61 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index d522112cf736..df7c62d9bec4 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -330,7 +330,7 @@ void ath_paprd_calibrate(struct work_struct *work)
330 struct ath_tx_control txctl; 330 struct ath_tx_control txctl;
331 struct ath9k_hw_cal_data *caldata = ah->caldata; 331 struct ath9k_hw_cal_data *caldata = ah->caldata;
332 struct ath_common *common = ath9k_hw_common(ah); 332 struct ath_common *common = ath9k_hw_common(ah);
333 int qnum, ftype; 333 int ftype;
334 int chain_ok = 0; 334 int chain_ok = 0;
335 int chain; 335 int chain;
336 int len = 1800; 336 int len = 1800;
@@ -357,8 +357,7 @@ void ath_paprd_calibrate(struct work_struct *work)
357 memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); 357 memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
358 358
359 memset(&txctl, 0, sizeof(txctl)); 359 memset(&txctl, 0, sizeof(txctl));
360 qnum = sc->tx.hwq_map[WME_AC_BE]; 360 txctl.txq = sc->tx.txq_map[WME_AC_BE];
361 txctl.txq = &sc->tx.txq[qnum];
362 361
363 ath9k_ps_wakeup(sc); 362 ath9k_ps_wakeup(sc);
364 ar9003_paprd_init_table(ah); 363 ar9003_paprd_init_table(ah);
@@ -1024,56 +1023,6 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
1024 return r; 1023 return r;
1025} 1024}
1026 1025
1027static int ath_get_hal_qnum(u16 queue, struct ath_softc *sc)
1028{
1029 int qnum;
1030
1031 switch (queue) {
1032 case 0:
1033 qnum = sc->tx.hwq_map[WME_AC_VO];
1034 break;
1035 case 1:
1036 qnum = sc->tx.hwq_map[WME_AC_VI];
1037 break;
1038 case 2:
1039 qnum = sc->tx.hwq_map[WME_AC_BE];
1040 break;
1041 case 3:
1042 qnum = sc->tx.hwq_map[WME_AC_BK];
1043 break;
1044 default:
1045 qnum = sc->tx.hwq_map[WME_AC_BE];
1046 break;
1047 }
1048
1049 return qnum;
1050}
1051
1052int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc)
1053{
1054 int qnum;
1055
1056 switch (queue) {
1057 case WME_AC_VO:
1058 qnum = 0;
1059 break;
1060 case WME_AC_VI:
1061 qnum = 1;
1062 break;
1063 case WME_AC_BE:
1064 qnum = 2;
1065 break;
1066 case WME_AC_BK:
1067 qnum = 3;
1068 break;
1069 default:
1070 qnum = -1;
1071 break;
1072 }
1073
1074 return qnum;
1075}
1076
1077/* XXX: Remove me once we don't depend on ath9k_channel for all 1026/* XXX: Remove me once we don't depend on ath9k_channel for all
1078 * this redundant data */ 1027 * this redundant data */
1079void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, 1028void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
@@ -1243,7 +1192,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
1243 struct ath_tx_control txctl; 1192 struct ath_tx_control txctl;
1244 int padpos, padsize; 1193 int padpos, padsize;
1245 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 1194 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
1246 int qnum;
1247 1195
1248 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { 1196 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
1249 ath_print(common, ATH_DBG_XMIT, 1197 ath_print(common, ATH_DBG_XMIT,
@@ -1316,8 +1264,7 @@ static int ath9k_tx(struct ieee80211_hw *hw,
1316 memmove(skb->data, skb->data + padsize, padpos); 1264 memmove(skb->data, skb->data + padsize, padpos);
1317 } 1265 }
1318 1266
1319 qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); 1267 txctl.txq = sc->tx.txq_map[skb_get_queue_mapping(skb)];
1320 txctl.txq = &sc->tx.txq[qnum];
1321 1268
1322 ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); 1269 ath_print(common, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb);
1323 1270
@@ -1801,12 +1748,15 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
1801 struct ath_wiphy *aphy = hw->priv; 1748 struct ath_wiphy *aphy = hw->priv;
1802 struct ath_softc *sc = aphy->sc; 1749 struct ath_softc *sc = aphy->sc;
1803 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1750 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1751 struct ath_txq *txq;
1804 struct ath9k_tx_queue_info qi; 1752 struct ath9k_tx_queue_info qi;
1805 int ret = 0, qnum; 1753 int ret = 0;
1806 1754
1807 if (queue >= WME_NUM_AC) 1755 if (queue >= WME_NUM_AC)
1808 return 0; 1756 return 0;
1809 1757
1758 txq = sc->tx.txq_map[queue];
1759
1810 mutex_lock(&sc->mutex); 1760 mutex_lock(&sc->mutex);
1811 1761
1812 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); 1762 memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1815,20 +1765,19 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
1815 qi.tqi_cwmin = params->cw_min; 1765 qi.tqi_cwmin = params->cw_min;
1816 qi.tqi_cwmax = params->cw_max; 1766 qi.tqi_cwmax = params->cw_max;
1817 qi.tqi_burstTime = params->txop; 1767 qi.tqi_burstTime = params->txop;
1818 qnum = ath_get_hal_qnum(queue, sc);
1819 1768
1820 ath_print(common, ATH_DBG_CONFIG, 1769 ath_print(common, ATH_DBG_CONFIG,
1821 "Configure tx [queue/halq] [%d/%d], " 1770 "Configure tx [queue/halq] [%d/%d], "
1822 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", 1771 "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n",
1823 queue, qnum, params->aifs, params->cw_min, 1772 queue, txq->axq_qnum, params->aifs, params->cw_min,
1824 params->cw_max, params->txop); 1773 params->cw_max, params->txop);
1825 1774
1826 ret = ath_txq_update(sc, qnum, &qi); 1775 ret = ath_txq_update(sc, txq->axq_qnum, &qi);
1827 if (ret) 1776 if (ret)
1828 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); 1777 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
1829 1778
1830 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) 1779 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
1831 if ((qnum == sc->tx.hwq_map[WME_AC_BE]) && !ret) 1780 if (queue == WME_AC_BE && !ret)
1832 ath_beaconq_config(sc); 1781 ath_beaconq_config(sc);
1833 1782
1834 mutex_unlock(&sc->mutex); 1783 mutex_unlock(&sc->mutex);