aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-11-24 21:37:57 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-28 15:04:52 -0500
commitf4709fdf683e1ed37b321c258b614ebe39752bf3 (patch)
tree5e6c234d7fae2b3807dd0b2e61bbc5f015ea5db5 /drivers/net/wireless/ath/ath9k
parent1bc1488067ee2c295b933ef6decd6035230f1a1c (diff)
ath9k: Fix maximum tx fifo settings for single stream devices
Atheros single stream AR9285 and AR9271 have half the PCU TX FIFO buffer size of that of dual stream devices. Dual stream devices have a max PCU TX FIFO size of 8 KB while single stream devices have 4 KB. Single stream devices have an issue though and require hardware only to use half of the amount of its capable PCU TX FIFO size, 2 KB and this requires a change in software. Technically a change would not have been required (except for frame burst considerations of 128 bytes) if these devices would have been able to use the full 4 KB of the PCU TX FIFO size but our systems engineers recommend 2 KB to be used only. We enforce this through software by reducing the max frame triggger level to 2 KB. Fixing the max frame trigger level should then have a few benefits: * The PER will now be adjusted as designed for underruns when the max trigger level is reached. This should help alleviate the bus as the rate control algorithm chooses a slower rate which should ensure frames are transmitted properly under high system bus load. * The poll we use on our TX queues should now trigger and work as designed for single stream devices. The hardware passes data from each TX queue on the PCU TX FIFO queue respecting each queue's priority. The new trigger level ensures this seeding of the PCU TX FIFO queue occurs as designed which could mean avoiding false resets and actually reseting hw correctly when a TX queue is indeed stuck. * Some undocumented / unsupported behaviour could have been triggered when the max trigger level level was being set to 4 KB on single stream devices. Its not clear what this issue was to me yet. Cc: Kyungwan Nam <kyungwan.nam@atheros.com> Cc: Bennyam Malavazi <bennyam.malavazi@atheros.com> Cc: Stephen Chen <stephen.chen@atheros.com> Cc: Shan Palanisamy <shan.palanisamy@atheros.com> Cc: Paul Shaw <paul.shaw@atheros.com> Signed-off-by: Vasanthakumar Thiagarajan <vasanth@atheros.com> Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c11
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c29
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h8
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c12
5 files changed, 53 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 63d84613dc96..493160c8c754 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -918,6 +918,11 @@ int ath9k_hw_init(struct ath_hw *ah)
918 ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n", 918 ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
919 ah->config.serialize_regmode); 919 ah->config.serialize_regmode);
920 920
921 if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
922 ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
923 else
924 ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
925
921 if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { 926 if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
922 ath_print(common, ATH_DBG_FATAL, 927 ath_print(common, ATH_DBG_FATAL,
923 "Mac Chip Rev 0x%02x.%x is not supported by " 928 "Mac Chip Rev 0x%02x.%x is not supported by "
@@ -3224,7 +3229,11 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
3224 pCap->keycache_size = AR_KEYTABLE_SIZE; 3229 pCap->keycache_size = AR_KEYTABLE_SIZE;
3225 3230
3226 pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; 3231 pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
3227 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; 3232
3233 if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
3234 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
3235 else
3236 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
3228 3237
3229 if (AR_SREV_9285_10_OR_LATER(ah)) 3238 if (AR_SREV_9285_10_OR_LATER(ah))
3230 pCap->num_gpio_pins = AR9285_NUM_GPIO; 3239 pCap->num_gpio_pins = AR9285_NUM_GPIO;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index b12634262d97..46e1572dc945 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -226,6 +226,7 @@ struct ath9k_ops_config {
226#define AR_SPUR_FEEQ_BOUND_HT20 10 226#define AR_SPUR_FEEQ_BOUND_HT20 10
227 int spurmode; 227 int spurmode;
228 u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; 228 u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
229 u8 max_txtrig_level;
229}; 230};
230 231
231enum ath9k_int { 232enum ath9k_int {
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 09ed441eb6ba..71b84d91dcff 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -70,12 +70,37 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
70} 70}
71EXPORT_SYMBOL(ath9k_hw_numtxpending); 71EXPORT_SYMBOL(ath9k_hw_numtxpending);
72 72
73/**
74 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
75 *
76 * @ah: atheros hardware struct
77 * @bIncTrigLevel: whether or not the frame trigger level should be updated
78 *
79 * The frame trigger level specifies the minimum number of bytes,
80 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
81 * before the PCU will initiate sending the frame on the air. This can
82 * mean we initiate transmit before a full frame is on the PCU TX FIFO.
83 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
84 * first)
85 *
86 * Caution must be taken to ensure to set the frame trigger level based
87 * on the DMA request size. For example if the DMA request size is set to
88 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
89 * there need to be enough space in the tx FIFO for the requested transfer
90 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
91 * the threshold to a value beyond 6, then the transmit will hang.
92 *
93 * Current dual stream devices have a PCU TX FIFO size of 8 KB.
94 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
95 * there is a hardware issue which forces us to use 2 KB instead so the
96 * frame trigger level must not exceed 2 KB for these chipsets.
97 */
73bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) 98bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
74{ 99{
75 u32 txcfg, curLevel, newLevel; 100 u32 txcfg, curLevel, newLevel;
76 enum ath9k_int omask; 101 enum ath9k_int omask;
77 102
78 if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) 103 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
79 return false; 104 return false;
80 105
81 omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); 106 omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
@@ -84,7 +109,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
84 curLevel = MS(txcfg, AR_FTRIG); 109 curLevel = MS(txcfg, AR_FTRIG);
85 newLevel = curLevel; 110 newLevel = curLevel;
86 if (bIncTrigLevel) { 111 if (bIncTrigLevel) {
87 if (curLevel < MAX_TX_FIFO_THRESHOLD) 112 if (curLevel < ah->config.max_txtrig_level)
88 newLevel++; 113 newLevel++;
89 } else if (curLevel > MIN_TX_FIFO_THRESHOLD) 114 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
90 newLevel--; 115 newLevel--;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 6cc04951a051..0c87771383f0 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -86,9 +86,15 @@
86#define ATH9K_TX_SW_ABORTED 0x40 86#define ATH9K_TX_SW_ABORTED 0x40
87#define ATH9K_TX_SW_FILTERED 0x80 87#define ATH9K_TX_SW_FILTERED 0x80
88 88
89/* 64 bytes */
89#define MIN_TX_FIFO_THRESHOLD 0x1 90#define MIN_TX_FIFO_THRESHOLD 0x1
91
92/*
93 * Single stream device AR9285 and AR9271 require 2 KB
94 * to work around a hardware issue, all other devices
95 * have can use the max 4 KB limit.
96 */
90#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) 97#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
91#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
92 98
93struct ath_tx_status { 99struct ath_tx_status {
94 u32 ts_tstamp; 100 u32 ts_tstamp;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index e697bd934904..c915954d4d5b 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1235,10 +1235,14 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1235 return; 1235 return;
1236 1236
1237 /* 1237 /*
1238 * If underrun error is seen assume it as an excessive retry only 1238 * If an underrun error is seen assume it as an excessive retry only
1239 * if prefetch trigger level have reached the max (0x3f for 5416) 1239 * if max frame trigger level has been reached (2 KB for singel stream,
1240 * Adjust the long retry as if the frame was tried hw->max_rate_tries 1240 * and 4 KB for dual stream). Adjust the long retry as if the frame was
1241 * times. This affects how ratectrl updates PER for the failed rate. 1241 * tried hw->max_rate_tries times to affect how ratectrl updates PER for
1242 * the failed rate. In case of congestion on the bus penalizing these
1243 * type of underruns should help hardware actually transmit new frames
1244 * successfully by eventually preferring slower rates. This itself
1245 * should also alleviate congestion on the bus.
1242 */ 1246 */
1243 if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) && 1247 if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) &&
1244 (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) { 1248 (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {