diff options
author | Johannes Berg <johannes.berg@intel.com> | 2011-05-04 10:50:44 -0400 |
---|---|---|
committer | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2011-05-13 13:32:04 -0400 |
commit | 214d14d4d323aab5d455b409e279f9e1e6631123 (patch) | |
tree | 7bbdbedb41d551ed803262e3aad1ab36e0e607ba | |
parent | 3fa507386dc4cdf731344cb9361e9cca373cedb9 (diff) |
iwlagn: clean up TXQ indirection
All of these functions no longer need to be
accessed indirectly since they're shared in
all AGN devices.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-1000.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-2000.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 149 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 160 |
10 files changed, 164 insertions, 203 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index b4c81931e136..61d4a11f566b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -171,10 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
171 | 171 | ||
172 | static struct iwl_lib_ops iwl1000_lib = { | 172 | static struct iwl_lib_ops iwl1000_lib = { |
173 | .set_hw_params = iwl1000_hw_set_hw_params, | 173 | .set_hw_params = iwl1000_hw_set_hw_params, |
174 | .txq_set_sched = iwlagn_txq_set_sched, | ||
175 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
176 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
177 | .txq_init = iwl_hw_tx_queue_init, | ||
178 | .rx_handler_setup = iwlagn_rx_handler_setup, | 174 | .rx_handler_setup = iwlagn_rx_handler_setup, |
179 | .setup_deferred_work = iwlagn_setup_deferred_work, | 175 | .setup_deferred_work = iwlagn_setup_deferred_work, |
180 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, | 176 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index 9f34cd7b6399..86feec86d130 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -252,10 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, | |||
252 | 252 | ||
253 | static struct iwl_lib_ops iwl2000_lib = { | 253 | static struct iwl_lib_ops iwl2000_lib = { |
254 | .set_hw_params = iwl2000_hw_set_hw_params, | 254 | .set_hw_params = iwl2000_hw_set_hw_params, |
255 | .txq_set_sched = iwlagn_txq_set_sched, | ||
256 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
257 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
258 | .txq_init = iwl_hw_tx_queue_init, | ||
259 | .rx_handler_setup = iwlagn_rx_handler_setup, | 255 | .rx_handler_setup = iwlagn_rx_handler_setup, |
260 | .setup_deferred_work = iwlagn_bt_setup_deferred_work, | 256 | .setup_deferred_work = iwlagn_bt_setup_deferred_work, |
261 | .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, | 257 | .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 09751f2386cb..a70b8cfafda1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -339,10 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
339 | 339 | ||
340 | static struct iwl_lib_ops iwl5000_lib = { | 340 | static struct iwl_lib_ops iwl5000_lib = { |
341 | .set_hw_params = iwl5000_hw_set_hw_params, | 341 | .set_hw_params = iwl5000_hw_set_hw_params, |
342 | .txq_set_sched = iwlagn_txq_set_sched, | ||
343 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
344 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
345 | .txq_init = iwl_hw_tx_queue_init, | ||
346 | .rx_handler_setup = iwlagn_rx_handler_setup, | 342 | .rx_handler_setup = iwlagn_rx_handler_setup, |
347 | .setup_deferred_work = iwlagn_setup_deferred_work, | 343 | .setup_deferred_work = iwlagn_setup_deferred_work, |
348 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, | 344 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
@@ -374,10 +370,6 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
374 | 370 | ||
375 | static struct iwl_lib_ops iwl5150_lib = { | 371 | static struct iwl_lib_ops iwl5150_lib = { |
376 | .set_hw_params = iwl5150_hw_set_hw_params, | 372 | .set_hw_params = iwl5150_hw_set_hw_params, |
377 | .txq_set_sched = iwlagn_txq_set_sched, | ||
378 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
379 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
380 | .txq_init = iwl_hw_tx_queue_init, | ||
381 | .rx_handler_setup = iwlagn_rx_handler_setup, | 373 | .rx_handler_setup = iwlagn_rx_handler_setup, |
382 | .setup_deferred_work = iwlagn_setup_deferred_work, | 374 | .setup_deferred_work = iwlagn_setup_deferred_work, |
383 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, | 375 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 860c26e4836d..f8c710db6e6f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -278,10 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
278 | 278 | ||
279 | static struct iwl_lib_ops iwl6000_lib = { | 279 | static struct iwl_lib_ops iwl6000_lib = { |
280 | .set_hw_params = iwl6000_hw_set_hw_params, | 280 | .set_hw_params = iwl6000_hw_set_hw_params, |
281 | .txq_set_sched = iwlagn_txq_set_sched, | ||
282 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
283 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
284 | .txq_init = iwl_hw_tx_queue_init, | ||
285 | .rx_handler_setup = iwlagn_rx_handler_setup, | 281 | .rx_handler_setup = iwlagn_rx_handler_setup, |
286 | .setup_deferred_work = iwlagn_setup_deferred_work, | 282 | .setup_deferred_work = iwlagn_setup_deferred_work, |
287 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, | 283 | .is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr, |
@@ -314,10 +310,6 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
314 | 310 | ||
315 | static struct iwl_lib_ops iwl6030_lib = { | 311 | static struct iwl_lib_ops iwl6030_lib = { |
316 | .set_hw_params = iwl6000_hw_set_hw_params, | 312 | .set_hw_params = iwl6000_hw_set_hw_params, |
317 | .txq_set_sched = iwlagn_txq_set_sched, | ||
318 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | ||
319 | .txq_free_tfd = iwl_hw_txq_free_tfd, | ||
320 | .txq_init = iwl_hw_tx_queue_init, | ||
321 | .rx_handler_setup = iwlagn_bt_rx_handler_setup, | 313 | .rx_handler_setup = iwlagn_bt_rx_handler_setup, |
322 | .setup_deferred_work = iwlagn_bt_setup_deferred_work, | 314 | .setup_deferred_work = iwlagn_bt_setup_deferred_work, |
323 | .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, | 315 | .cancel_deferred_work = iwlagn_bt_cancel_deferred_work, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 7c1becf9e2c1..d34e103c71cf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -750,12 +750,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
750 | spin_unlock(&priv->sta_lock); | 750 | spin_unlock(&priv->sta_lock); |
751 | 751 | ||
752 | /* Attach buffers to TFD */ | 752 | /* Attach buffers to TFD */ |
753 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 753 | iwlagn_txq_attach_buf_to_tfd(priv, txq, txcmd_phys, firstlen, 1, 0); |
754 | txcmd_phys, firstlen, 1, 0); | ||
755 | if (secondlen > 0) | 754 | if (secondlen > 0) |
756 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 755 | iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, |
757 | phys_addr, secondlen, | 756 | secondlen, 0, 0); |
758 | 0, 0); | ||
759 | 757 | ||
760 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | 758 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + |
761 | offsetof(struct iwl_tx_cmd, scratch); | 759 | offsetof(struct iwl_tx_cmd, scratch); |
@@ -911,7 +909,7 @@ int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) | |||
911 | spin_lock_irqsave(&priv->lock, flags); | 909 | spin_lock_irqsave(&priv->lock, flags); |
912 | 910 | ||
913 | /* Turn off all Tx DMA fifos */ | 911 | /* Turn off all Tx DMA fifos */ |
914 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | 912 | iwlagn_txq_set_sched(priv, 0); |
915 | 913 | ||
916 | /* Tell NIC where to find the "keep warm" buffer */ | 914 | /* Tell NIC where to find the "keep warm" buffer */ |
917 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | 915 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); |
@@ -949,7 +947,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | |||
949 | spin_lock_irqsave(&priv->lock, flags); | 947 | spin_lock_irqsave(&priv->lock, flags); |
950 | 948 | ||
951 | /* Turn off all Tx DMA fifos */ | 949 | /* Turn off all Tx DMA fifos */ |
952 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | 950 | iwlagn_txq_set_sched(priv, 0); |
953 | 951 | ||
954 | /* Tell NIC where to find the "keep warm" buffer */ | 952 | /* Tell NIC where to find the "keep warm" buffer */ |
955 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | 953 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); |
@@ -975,7 +973,7 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | |||
975 | /* Turn off all Tx DMA fifos */ | 973 | /* Turn off all Tx DMA fifos */ |
976 | spin_lock_irqsave(&priv->lock, flags); | 974 | spin_lock_irqsave(&priv->lock, flags); |
977 | 975 | ||
978 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | 976 | iwlagn_txq_set_sched(priv, 0); |
979 | 977 | ||
980 | /* Stop each Tx DMA channel, and wait for it to be idle */ | 978 | /* Stop each Tx DMA channel, and wait for it to be idle */ |
981 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { | 979 | for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { |
@@ -1258,7 +1256,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1258 | 1256 | ||
1259 | iwlagn_txq_inval_byte_cnt_tbl(priv, txq); | 1257 | iwlagn_txq_inval_byte_cnt_tbl(priv, txq); |
1260 | 1258 | ||
1261 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 1259 | iwlagn_txq_free_tfd(priv, txq); |
1262 | } | 1260 | } |
1263 | return nfreed; | 1261 | return nfreed; |
1264 | } | 1262 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index e35755c577db..97de5d9de67b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -440,7 +440,7 @@ static int iwlagn_alive_notify(struct iwl_priv *priv) | |||
440 | IWL_MASK(0, priv->hw_params.max_txq_num)); | 440 | IWL_MASK(0, priv->hw_params.max_txq_num)); |
441 | 441 | ||
442 | /* Activate all Tx DMA/FIFO channels */ | 442 | /* Activate all Tx DMA/FIFO channels */ |
443 | priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); | 443 | iwlagn_txq_set_sched(priv, IWL_MASK(0, 7)); |
444 | 444 | ||
445 | /* map queues to FIFOs */ | 445 | /* map queues to FIFOs */ |
446 | if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) | 446 | if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2713081ed996..2bb08d7e0674 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -200,155 +200,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | |||
200 | return err; | 200 | return err; |
201 | } | 201 | } |
202 | 202 | ||
203 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | ||
204 | { | ||
205 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
206 | |||
207 | dma_addr_t addr = get_unaligned_le32(&tb->lo); | ||
208 | if (sizeof(dma_addr_t) > sizeof(u32)) | ||
209 | addr |= | ||
210 | ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; | ||
211 | |||
212 | return addr; | ||
213 | } | ||
214 | |||
215 | static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) | ||
216 | { | ||
217 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
218 | |||
219 | return le16_to_cpu(tb->hi_n_len) >> 4; | ||
220 | } | ||
221 | |||
222 | static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, | ||
223 | dma_addr_t addr, u16 len) | ||
224 | { | ||
225 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
226 | u16 hi_n_len = len << 4; | ||
227 | |||
228 | put_unaligned_le32(addr, &tb->lo); | ||
229 | if (sizeof(dma_addr_t) > sizeof(u32)) | ||
230 | hi_n_len |= ((addr >> 16) >> 16) & 0xF; | ||
231 | |||
232 | tb->hi_n_len = cpu_to_le16(hi_n_len); | ||
233 | |||
234 | tfd->num_tbs = idx + 1; | ||
235 | } | ||
236 | |||
237 | static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) | ||
238 | { | ||
239 | return tfd->num_tbs & 0x1f; | ||
240 | } | ||
241 | |||
242 | /** | ||
243 | * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] | ||
244 | * @priv - driver private data | ||
245 | * @txq - tx queue | ||
246 | * | ||
247 | * Does NOT advance any TFD circular buffer read/write indexes | ||
248 | * Does NOT free the TFD itself (which is within circular buffer) | ||
249 | */ | ||
250 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
251 | { | ||
252 | struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; | ||
253 | struct iwl_tfd *tfd; | ||
254 | struct pci_dev *dev = priv->pci_dev; | ||
255 | int index = txq->q.read_ptr; | ||
256 | int i; | ||
257 | int num_tbs; | ||
258 | |||
259 | tfd = &tfd_tmp[index]; | ||
260 | |||
261 | /* Sanity check on number of chunks */ | ||
262 | num_tbs = iwl_tfd_get_num_tbs(tfd); | ||
263 | |||
264 | if (num_tbs >= IWL_NUM_OF_TBS) { | ||
265 | IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); | ||
266 | /* @todo issue fatal error, it is quite serious situation */ | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | /* Unmap tx_cmd */ | ||
271 | if (num_tbs) | ||
272 | pci_unmap_single(dev, | ||
273 | dma_unmap_addr(&txq->meta[index], mapping), | ||
274 | dma_unmap_len(&txq->meta[index], len), | ||
275 | PCI_DMA_BIDIRECTIONAL); | ||
276 | |||
277 | /* Unmap chunks, if any. */ | ||
278 | for (i = 1; i < num_tbs; i++) | ||
279 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), | ||
280 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); | ||
281 | |||
282 | /* free SKB */ | ||
283 | if (txq->txb) { | ||
284 | struct sk_buff *skb; | ||
285 | |||
286 | skb = txq->txb[txq->q.read_ptr].skb; | ||
287 | |||
288 | /* can be called from irqs-disabled context */ | ||
289 | if (skb) { | ||
290 | dev_kfree_skb_any(skb); | ||
291 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | |||
296 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | ||
297 | struct iwl_tx_queue *txq, | ||
298 | dma_addr_t addr, u16 len, | ||
299 | u8 reset, u8 pad) | ||
300 | { | ||
301 | struct iwl_queue *q; | ||
302 | struct iwl_tfd *tfd, *tfd_tmp; | ||
303 | u32 num_tbs; | ||
304 | |||
305 | q = &txq->q; | ||
306 | tfd_tmp = (struct iwl_tfd *)txq->tfds; | ||
307 | tfd = &tfd_tmp[q->write_ptr]; | ||
308 | |||
309 | if (reset) | ||
310 | memset(tfd, 0, sizeof(*tfd)); | ||
311 | |||
312 | num_tbs = iwl_tfd_get_num_tbs(tfd); | ||
313 | |||
314 | /* Each TFD can point to a maximum 20 Tx buffers */ | ||
315 | if (num_tbs >= IWL_NUM_OF_TBS) { | ||
316 | IWL_ERR(priv, "Error can not send more than %d chunks\n", | ||
317 | IWL_NUM_OF_TBS); | ||
318 | return -EINVAL; | ||
319 | } | ||
320 | |||
321 | if (WARN_ON(addr & ~DMA_BIT_MASK(36))) | ||
322 | return -EINVAL; | ||
323 | |||
324 | if (unlikely(addr & ~IWL_TX_DMA_MASK)) | ||
325 | IWL_ERR(priv, "Unaligned address = %llx\n", | ||
326 | (unsigned long long)addr); | ||
327 | |||
328 | iwl_tfd_set_tb(tfd, num_tbs, addr, len); | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
335 | * given Tx queue, and enable the DMA channel used for that queue. | ||
336 | * | ||
337 | * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA | ||
338 | * channels supported in hardware. | ||
339 | */ | ||
340 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | ||
341 | struct iwl_tx_queue *txq) | ||
342 | { | ||
343 | int txq_id = txq->q.id; | ||
344 | |||
345 | /* Circular buffer (TFD queue in DRAM) physical base address */ | ||
346 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
347 | txq->q.dma_addr >> 8); | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | static void iwl_bg_beacon_update(struct work_struct *work) | 203 | static void iwl_bg_beacon_update(struct work_struct *work) |
353 | { | 204 | { |
354 | struct iwl_priv *priv = | 205 | struct iwl_priv *priv = |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index fe33fe8aa418..269e0c47927b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -191,12 +191,10 @@ int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); | |||
191 | void iwl_setup_rx_handlers(struct iwl_priv *priv); | 191 | void iwl_setup_rx_handlers(struct iwl_priv *priv); |
192 | 192 | ||
193 | /* tx */ | 193 | /* tx */ |
194 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 194 | void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
195 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 195 | int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, |
196 | struct iwl_tx_queue *txq, | 196 | struct iwl_tx_queue *txq, |
197 | dma_addr_t addr, u16 len, u8 reset, u8 pad); | 197 | dma_addr_t addr, u16 len, u8 reset, u8 pad); |
198 | int iwl_hw_tx_queue_init(struct iwl_priv *priv, | ||
199 | struct iwl_tx_queue *txq); | ||
200 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, | 198 | void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, |
201 | struct ieee80211_tx_info *info); | 199 | struct ieee80211_tx_info *info); |
202 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); | 200 | int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 5b5b0cce4a54..3bb76f6ea410 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -127,16 +127,6 @@ struct iwl_temp_ops { | |||
127 | struct iwl_lib_ops { | 127 | struct iwl_lib_ops { |
128 | /* set hw dependent parameters */ | 128 | /* set hw dependent parameters */ |
129 | int (*set_hw_params)(struct iwl_priv *priv); | 129 | int (*set_hw_params)(struct iwl_priv *priv); |
130 | /* Handling TX */ | ||
131 | void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); | ||
132 | int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, | ||
133 | struct iwl_tx_queue *txq, | ||
134 | dma_addr_t addr, | ||
135 | u16 len, u8 reset, u8 pad); | ||
136 | void (*txq_free_tfd)(struct iwl_priv *priv, | ||
137 | struct iwl_tx_queue *txq); | ||
138 | int (*txq_init)(struct iwl_priv *priv, | ||
139 | struct iwl_tx_queue *txq); | ||
140 | /* setup Rx handler */ | 130 | /* setup Rx handler */ |
141 | void (*rx_handler_setup)(struct iwl_priv *priv); | 131 | void (*rx_handler_setup)(struct iwl_priv *priv); |
142 | /* setup deferred work */ | 132 | /* setup deferred work */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7843195efb05..302284bef961 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
33 | #include <net/mac80211.h> | 33 | #include <net/mac80211.h> |
34 | #include "iwl-eeprom.h" | 34 | #include "iwl-eeprom.h" |
35 | #include "iwl-agn.h" | ||
35 | #include "iwl-dev.h" | 36 | #include "iwl-dev.h" |
36 | #include "iwl-core.h" | 37 | #include "iwl-core.h" |
37 | #include "iwl-sta.h" | 38 | #include "iwl-sta.h" |
@@ -85,6 +86,154 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
85 | txq->need_update = 0; | 86 | txq->need_update = 0; |
86 | } | 87 | } |
87 | 88 | ||
89 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | ||
90 | { | ||
91 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
92 | |||
93 | dma_addr_t addr = get_unaligned_le32(&tb->lo); | ||
94 | if (sizeof(dma_addr_t) > sizeof(u32)) | ||
95 | addr |= | ||
96 | ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; | ||
97 | |||
98 | return addr; | ||
99 | } | ||
100 | |||
101 | static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) | ||
102 | { | ||
103 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
104 | |||
105 | return le16_to_cpu(tb->hi_n_len) >> 4; | ||
106 | } | ||
107 | |||
108 | static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, | ||
109 | dma_addr_t addr, u16 len) | ||
110 | { | ||
111 | struct iwl_tfd_tb *tb = &tfd->tbs[idx]; | ||
112 | u16 hi_n_len = len << 4; | ||
113 | |||
114 | put_unaligned_le32(addr, &tb->lo); | ||
115 | if (sizeof(dma_addr_t) > sizeof(u32)) | ||
116 | hi_n_len |= ((addr >> 16) >> 16) & 0xF; | ||
117 | |||
118 | tb->hi_n_len = cpu_to_le16(hi_n_len); | ||
119 | |||
120 | tfd->num_tbs = idx + 1; | ||
121 | } | ||
122 | |||
123 | static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) | ||
124 | { | ||
125 | return tfd->num_tbs & 0x1f; | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] | ||
130 | * @priv - driver private data | ||
131 | * @txq - tx queue | ||
132 | * | ||
133 | * Does NOT advance any TFD circular buffer read/write indexes | ||
134 | * Does NOT free the TFD itself (which is within circular buffer) | ||
135 | */ | ||
136 | void iwlagn_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
137 | { | ||
138 | struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; | ||
139 | struct iwl_tfd *tfd; | ||
140 | struct pci_dev *dev = priv->pci_dev; | ||
141 | int index = txq->q.read_ptr; | ||
142 | int i; | ||
143 | int num_tbs; | ||
144 | |||
145 | tfd = &tfd_tmp[index]; | ||
146 | |||
147 | /* Sanity check on number of chunks */ | ||
148 | num_tbs = iwl_tfd_get_num_tbs(tfd); | ||
149 | |||
150 | if (num_tbs >= IWL_NUM_OF_TBS) { | ||
151 | IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); | ||
152 | /* @todo issue fatal error, it is quite serious situation */ | ||
153 | return; | ||
154 | } | ||
155 | |||
156 | /* Unmap tx_cmd */ | ||
157 | if (num_tbs) | ||
158 | pci_unmap_single(dev, | ||
159 | dma_unmap_addr(&txq->meta[index], mapping), | ||
160 | dma_unmap_len(&txq->meta[index], len), | ||
161 | PCI_DMA_BIDIRECTIONAL); | ||
162 | |||
163 | /* Unmap chunks, if any. */ | ||
164 | for (i = 1; i < num_tbs; i++) | ||
165 | pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), | ||
166 | iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); | ||
167 | |||
168 | /* free SKB */ | ||
169 | if (txq->txb) { | ||
170 | struct sk_buff *skb; | ||
171 | |||
172 | skb = txq->txb[txq->q.read_ptr].skb; | ||
173 | |||
174 | /* can be called from irqs-disabled context */ | ||
175 | if (skb) { | ||
176 | dev_kfree_skb_any(skb); | ||
177 | txq->txb[txq->q.read_ptr].skb = NULL; | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | int iwlagn_txq_attach_buf_to_tfd(struct iwl_priv *priv, | ||
183 | struct iwl_tx_queue *txq, | ||
184 | dma_addr_t addr, u16 len, | ||
185 | u8 reset, u8 pad) | ||
186 | { | ||
187 | struct iwl_queue *q; | ||
188 | struct iwl_tfd *tfd, *tfd_tmp; | ||
189 | u32 num_tbs; | ||
190 | |||
191 | q = &txq->q; | ||
192 | tfd_tmp = (struct iwl_tfd *)txq->tfds; | ||
193 | tfd = &tfd_tmp[q->write_ptr]; | ||
194 | |||
195 | if (reset) | ||
196 | memset(tfd, 0, sizeof(*tfd)); | ||
197 | |||
198 | num_tbs = iwl_tfd_get_num_tbs(tfd); | ||
199 | |||
200 | /* Each TFD can point to a maximum 20 Tx buffers */ | ||
201 | if (num_tbs >= IWL_NUM_OF_TBS) { | ||
202 | IWL_ERR(priv, "Error can not send more than %d chunks\n", | ||
203 | IWL_NUM_OF_TBS); | ||
204 | return -EINVAL; | ||
205 | } | ||
206 | |||
207 | if (WARN_ON(addr & ~DMA_BIT_MASK(36))) | ||
208 | return -EINVAL; | ||
209 | |||
210 | if (unlikely(addr & ~IWL_TX_DMA_MASK)) | ||
211 | IWL_ERR(priv, "Unaligned address = %llx\n", | ||
212 | (unsigned long long)addr); | ||
213 | |||
214 | iwl_tfd_set_tb(tfd, num_tbs, addr, len); | ||
215 | |||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | /* | ||
220 | * Tell nic where to find circular buffer of Tx Frame Descriptors for | ||
221 | * given Tx queue, and enable the DMA channel used for that queue. | ||
222 | * | ||
223 | * supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA | ||
224 | * channels supported in hardware. | ||
225 | */ | ||
226 | static int iwlagn_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) | ||
227 | { | ||
228 | int txq_id = txq->q.id; | ||
229 | |||
230 | /* Circular buffer (TFD queue in DRAM) physical base address */ | ||
231 | iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), | ||
232 | txq->q.dma_addr >> 8); | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
88 | /** | 237 | /** |
89 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | 238 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's |
90 | */ | 239 | */ |
@@ -97,7 +246,7 @@ void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) | |||
97 | return; | 246 | return; |
98 | 247 | ||
99 | while (q->write_ptr != q->read_ptr) { | 248 | while (q->write_ptr != q->read_ptr) { |
100 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 249 | iwlagn_txq_free_tfd(priv, txq); |
101 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | 250 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); |
102 | } | 251 | } |
103 | } | 252 | } |
@@ -391,7 +540,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
391 | return ret; | 540 | return ret; |
392 | 541 | ||
393 | /* Tell device where to find queue */ | 542 | /* Tell device where to find queue */ |
394 | priv->cfg->ops->lib->txq_init(priv, txq); | 543 | iwlagn_tx_queue_init(priv, txq); |
395 | 544 | ||
396 | return 0; | 545 | return 0; |
397 | err: | 546 | err: |
@@ -420,7 +569,7 @@ void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
420 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | 569 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); |
421 | 570 | ||
422 | /* Tell device where to find queue */ | 571 | /* Tell device where to find queue */ |
423 | priv->cfg->ops->lib->txq_init(priv, txq); | 572 | iwlagn_tx_queue_init(priv, txq); |
424 | } | 573 | } |
425 | 574 | ||
426 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 575 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
@@ -553,9 +702,8 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
553 | 702 | ||
554 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | 703 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); |
555 | 704 | ||
556 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 705 | iwlagn_txq_attach_buf_to_tfd(priv, txq, phys_addr, fix_size, 1, |
557 | phys_addr, fix_size, 1, | 706 | U32_PAD(cmd->len[0])); |
558 | U32_PAD(cmd->len[0])); | ||
559 | 707 | ||
560 | /* Increment and update queue's write index */ | 708 | /* Increment and update queue's write index */ |
561 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 709 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |