diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-11-24 21:37:57 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-28 15:04:52 -0500 |
commit | f4709fdf683e1ed37b321c258b614ebe39752bf3 (patch) | |
tree | 5e6c234d7fae2b3807dd0b2e61bbc5f015ea5db5 /drivers/net/wireless/ath/ath9k/mac.c | |
parent | 1bc1488067ee2c295b933ef6decd6035230f1a1c (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/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/mac.c | 29 |
1 files changed, 27 insertions, 2 deletions
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 | } |
71 | EXPORT_SYMBOL(ath9k_hw_numtxpending); | 71 | EXPORT_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 | */ | ||
73 | bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) | 98 | bool 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--; |