diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/pcie/rx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/pcie/rx.c | 91 |
1 files changed, 57 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index d1a61ba6247..17c8e5d8268 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -35,10 +35,6 @@ | |||
35 | #include "internal.h" | 35 | #include "internal.h" |
36 | #include "iwl-op-mode.h" | 36 | #include "iwl-op-mode.h" |
37 | 37 | ||
38 | #ifdef CONFIG_IWLWIFI_IDI | ||
39 | #include "iwl-amfh.h" | ||
40 | #endif | ||
41 | |||
42 | /****************************************************************************** | 38 | /****************************************************************************** |
43 | * | 39 | * |
44 | * RX path functions | 40 | * RX path functions |
@@ -181,15 +177,15 @@ void iwl_rx_queue_update_write_ptr(struct iwl_trans *trans, | |||
181 | } | 177 | } |
182 | 178 | ||
183 | /** | 179 | /** |
184 | * iwlagn_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr | 180 | * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr |
185 | */ | 181 | */ |
186 | static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | 182 | static inline __le32 iwl_dma_addr2rbd_ptr(dma_addr_t dma_addr) |
187 | { | 183 | { |
188 | return cpu_to_le32((u32)(dma_addr >> 8)); | 184 | return cpu_to_le32((u32)(dma_addr >> 8)); |
189 | } | 185 | } |
190 | 186 | ||
191 | /** | 187 | /** |
192 | * iwlagn_rx_queue_restock - refill RX queue from pre-allocated pool | 188 | * iwl_rx_queue_restock - refill RX queue from pre-allocated pool |
193 | * | 189 | * |
194 | * If there are slots in the RX queue that need to be restocked, | 190 | * If there are slots in the RX queue that need to be restocked, |
195 | * and we have free pre-allocated buffers, fill the ranks as much | 191 | * and we have free pre-allocated buffers, fill the ranks as much |
@@ -199,7 +195,7 @@ static inline __le32 iwlagn_dma_addr2rbd_ptr(dma_addr_t dma_addr) | |||
199 | * also updates the memory address in the firmware to reference the new | 195 | * also updates the memory address in the firmware to reference the new |
200 | * target buffer. | 196 | * target buffer. |
201 | */ | 197 | */ |
202 | static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | 198 | static void iwl_rx_queue_restock(struct iwl_trans *trans) |
203 | { | 199 | { |
204 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 200 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
205 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 201 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
@@ -207,6 +203,17 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
207 | struct iwl_rx_mem_buffer *rxb; | 203 | struct iwl_rx_mem_buffer *rxb; |
208 | unsigned long flags; | 204 | unsigned long flags; |
209 | 205 | ||
206 | /* | ||
207 | * If the device isn't enabled - not need to try to add buffers... | ||
208 | * This can happen when we stop the device and still have an interrupt | ||
209 | * pending. We stop the APM before we sync the interrupts / tasklets | ||
210 | * because we have to (see comment there). On the other hand, since | ||
211 | * the APM is stopped, we cannot access the HW (in particular not prph). | ||
212 | * So don't try to restock if the APM has been already stopped. | ||
213 | */ | ||
214 | if (!test_bit(STATUS_DEVICE_ENABLED, &trans_pcie->status)) | ||
215 | return; | ||
216 | |||
210 | spin_lock_irqsave(&rxq->lock, flags); | 217 | spin_lock_irqsave(&rxq->lock, flags); |
211 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { | 218 | while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { |
212 | /* The overwritten rxb must be a used one */ | 219 | /* The overwritten rxb must be a used one */ |
@@ -219,7 +226,7 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
219 | list_del(element); | 226 | list_del(element); |
220 | 227 | ||
221 | /* Point to Rx buffer via next RBD in circular buffer */ | 228 | /* Point to Rx buffer via next RBD in circular buffer */ |
222 | rxq->bd[rxq->write] = iwlagn_dma_addr2rbd_ptr(rxb->page_dma); | 229 | rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(rxb->page_dma); |
223 | rxq->queue[rxq->write] = rxb; | 230 | rxq->queue[rxq->write] = rxb; |
224 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; | 231 | rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; |
225 | rxq->free_count--; | 232 | rxq->free_count--; |
@@ -230,7 +237,6 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
230 | if (rxq->free_count <= RX_LOW_WATERMARK) | 237 | if (rxq->free_count <= RX_LOW_WATERMARK) |
231 | schedule_work(&trans_pcie->rx_replenish); | 238 | schedule_work(&trans_pcie->rx_replenish); |
232 | 239 | ||
233 | |||
234 | /* If we've added more space for the firmware to place data, tell it. | 240 | /* If we've added more space for the firmware to place data, tell it. |
235 | * Increment device's write pointer in multiples of 8. */ | 241 | * Increment device's write pointer in multiples of 8. */ |
236 | if (rxq->write_actual != (rxq->write & ~0x7)) { | 242 | if (rxq->write_actual != (rxq->write & ~0x7)) { |
@@ -241,15 +247,16 @@ static void iwlagn_rx_queue_restock(struct iwl_trans *trans) | |||
241 | } | 247 | } |
242 | } | 248 | } |
243 | 249 | ||
244 | /** | 250 | /* |
245 | * iwlagn_rx_replenish - Move all used packet from rx_used to rx_free | 251 | * iwl_rx_allocate - allocate a page for each used RBD |
246 | * | ||
247 | * When moving to rx_free an SKB is allocated for the slot. | ||
248 | * | 252 | * |
249 | * Also restock the Rx queue via iwl_rx_queue_restock. | 253 | * A used RBD is an Rx buffer that has been given to the stack. To use it again |
250 | * This is called as a scheduled work item (except for during initialization) | 254 | * a page must be allocated and the RBD must point to the page. This function |
255 | * doesn't change the HW pointer but handles the list of pages that is used by | ||
256 | * iwl_rx_queue_restock. The latter function will update the HW to use the newly | ||
257 | * allocated buffers. | ||
251 | */ | 258 | */ |
252 | static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | 259 | static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority) |
253 | { | 260 | { |
254 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 261 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
255 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; | 262 | struct iwl_rx_queue *rxq = &trans_pcie->rxq; |
@@ -328,23 +335,31 @@ static void iwlagn_rx_allocate(struct iwl_trans *trans, gfp_t priority) | |||
328 | } | 335 | } |
329 | } | 336 | } |
330 | 337 | ||
331 | void iwlagn_rx_replenish(struct iwl_trans *trans) | 338 | /* |
339 | * iwl_rx_replenish - Move all used buffers from rx_used to rx_free | ||
340 | * | ||
341 | * When moving to rx_free an page is allocated for the slot. | ||
342 | * | ||
343 | * Also restock the Rx queue via iwl_rx_queue_restock. | ||
344 | * This is called as a scheduled work item (except for during initialization) | ||
345 | */ | ||
346 | void iwl_rx_replenish(struct iwl_trans *trans) | ||
332 | { | 347 | { |
333 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 348 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
334 | unsigned long flags; | 349 | unsigned long flags; |
335 | 350 | ||
336 | iwlagn_rx_allocate(trans, GFP_KERNEL); | 351 | iwl_rx_allocate(trans, GFP_KERNEL); |
337 | 352 | ||
338 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); | 353 | spin_lock_irqsave(&trans_pcie->irq_lock, flags); |
339 | iwlagn_rx_queue_restock(trans); | 354 | iwl_rx_queue_restock(trans); |
340 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); | 355 | spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); |
341 | } | 356 | } |
342 | 357 | ||
343 | static void iwlagn_rx_replenish_now(struct iwl_trans *trans) | 358 | static void iwl_rx_replenish_now(struct iwl_trans *trans) |
344 | { | 359 | { |
345 | iwlagn_rx_allocate(trans, GFP_ATOMIC); | 360 | iwl_rx_allocate(trans, GFP_ATOMIC); |
346 | 361 | ||
347 | iwlagn_rx_queue_restock(trans); | 362 | iwl_rx_queue_restock(trans); |
348 | } | 363 | } |
349 | 364 | ||
350 | void iwl_bg_rx_replenish(struct work_struct *data) | 365 | void iwl_bg_rx_replenish(struct work_struct *data) |
@@ -352,7 +367,7 @@ void iwl_bg_rx_replenish(struct work_struct *data) | |||
352 | struct iwl_trans_pcie *trans_pcie = | 367 | struct iwl_trans_pcie *trans_pcie = |
353 | container_of(data, struct iwl_trans_pcie, rx_replenish); | 368 | container_of(data, struct iwl_trans_pcie, rx_replenish); |
354 | 369 | ||
355 | iwlagn_rx_replenish(trans_pcie->trans); | 370 | iwl_rx_replenish(trans_pcie->trans); |
356 | } | 371 | } |
357 | 372 | ||
358 | static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | 373 | static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, |
@@ -421,13 +436,23 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
421 | index = SEQ_TO_INDEX(sequence); | 436 | index = SEQ_TO_INDEX(sequence); |
422 | cmd_index = get_cmd_index(&txq->q, index); | 437 | cmd_index = get_cmd_index(&txq->q, index); |
423 | 438 | ||
424 | if (reclaim) | 439 | if (reclaim) { |
425 | cmd = txq->entries[cmd_index].cmd; | 440 | struct iwl_pcie_tx_queue_entry *ent; |
426 | else | 441 | ent = &txq->entries[cmd_index]; |
442 | cmd = ent->copy_cmd; | ||
443 | WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD); | ||
444 | } else { | ||
427 | cmd = NULL; | 445 | cmd = NULL; |
446 | } | ||
428 | 447 | ||
429 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); | 448 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); |
430 | 449 | ||
450 | if (reclaim) { | ||
451 | /* The original command isn't needed any more */ | ||
452 | kfree(txq->entries[cmd_index].copy_cmd); | ||
453 | txq->entries[cmd_index].copy_cmd = NULL; | ||
454 | } | ||
455 | |||
431 | /* | 456 | /* |
432 | * After here, we should always check rxcb._page_stolen, | 457 | * After here, we should always check rxcb._page_stolen, |
433 | * if it is true then one of the handlers took the page. | 458 | * if it is true then one of the handlers took the page. |
@@ -520,7 +545,7 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
520 | count++; | 545 | count++; |
521 | if (count >= 8) { | 546 | if (count >= 8) { |
522 | rxq->read = i; | 547 | rxq->read = i; |
523 | iwlagn_rx_replenish_now(trans); | 548 | iwl_rx_replenish_now(trans); |
524 | count = 0; | 549 | count = 0; |
525 | } | 550 | } |
526 | } | 551 | } |
@@ -529,9 +554,9 @@ static void iwl_rx_handle(struct iwl_trans *trans) | |||
529 | /* Backtrack one entry */ | 554 | /* Backtrack one entry */ |
530 | rxq->read = i; | 555 | rxq->read = i; |
531 | if (fill_rx) | 556 | if (fill_rx) |
532 | iwlagn_rx_replenish_now(trans); | 557 | iwl_rx_replenish_now(trans); |
533 | else | 558 | else |
534 | iwlagn_rx_queue_restock(trans); | 559 | iwl_rx_queue_restock(trans); |
535 | } | 560 | } |
536 | 561 | ||
537 | /** | 562 | /** |
@@ -713,11 +738,9 @@ void iwl_irq_tasklet(struct iwl_trans *trans) | |||
713 | /* Disable periodic interrupt; we use it as just a one-shot. */ | 738 | /* Disable periodic interrupt; we use it as just a one-shot. */ |
714 | iwl_write8(trans, CSR_INT_PERIODIC_REG, | 739 | iwl_write8(trans, CSR_INT_PERIODIC_REG, |
715 | CSR_INT_PERIODIC_DIS); | 740 | CSR_INT_PERIODIC_DIS); |
716 | #ifdef CONFIG_IWLWIFI_IDI | 741 | |
717 | iwl_amfh_rx_handler(); | ||
718 | #else | ||
719 | iwl_rx_handle(trans); | 742 | iwl_rx_handle(trans); |
720 | #endif | 743 | |
721 | /* | 744 | /* |
722 | * Enable periodic interrupt in 8 msec only if we received | 745 | * Enable periodic interrupt in 8 msec only if we received |
723 | * real RX interrupt (instead of just periodic int), to catch | 746 | * real RX interrupt (instead of just periodic int), to catch |