diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-rx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-rx.c | 80 |
1 files changed, 61 insertions, 19 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 0f718f6df5fd..0d09f571e185 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -123,12 +123,11 @@ EXPORT_SYMBOL(iwl_rx_queue_space); | |||
123 | /** | 123 | /** |
124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue | 124 | * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue |
125 | */ | 125 | */ |
126 | int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | 126 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) |
127 | { | 127 | { |
128 | unsigned long flags; | 128 | unsigned long flags; |
129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; | 129 | u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; |
130 | u32 reg; | 130 | u32 reg; |
131 | int ret = 0; | ||
132 | 131 | ||
133 | spin_lock_irqsave(&q->lock, flags); | 132 | spin_lock_irqsave(&q->lock, flags); |
134 | 133 | ||
@@ -161,7 +160,6 @@ int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) | |||
161 | 160 | ||
162 | exit_unlock: | 161 | exit_unlock: |
163 | spin_unlock_irqrestore(&q->lock, flags); | 162 | spin_unlock_irqrestore(&q->lock, flags); |
164 | return ret; | ||
165 | } | 163 | } |
166 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); | 164 | EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); |
167 | /** | 165 | /** |
@@ -184,14 +182,13 @@ static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, | |||
184 | * also updates the memory address in the firmware to reference the new | 182 | * also updates the memory address in the firmware to reference the new |
185 | * target buffer. | 183 | * target buffer. |
186 | */ | 184 | */ |
187 | int iwl_rx_queue_restock(struct iwl_priv *priv) | 185 | void iwl_rx_queue_restock(struct iwl_priv *priv) |
188 | { | 186 | { |
189 | struct iwl_rx_queue *rxq = &priv->rxq; | 187 | struct iwl_rx_queue *rxq = &priv->rxq; |
190 | struct list_head *element; | 188 | struct list_head *element; |
191 | struct iwl_rx_mem_buffer *rxb; | 189 | struct iwl_rx_mem_buffer *rxb; |
192 | unsigned long flags; | 190 | unsigned long flags; |
193 | int write; | 191 | int write; |
194 | int ret = 0; | ||
195 | 192 | ||
196 | spin_lock_irqsave(&rxq->lock, flags); | 193 | spin_lock_irqsave(&rxq->lock, flags); |
197 | write = rxq->write & ~0x7; | 194 | write = rxq->write & ~0x7; |
@@ -220,10 +217,8 @@ int iwl_rx_queue_restock(struct iwl_priv *priv) | |||
220 | spin_lock_irqsave(&rxq->lock, flags); | 217 | spin_lock_irqsave(&rxq->lock, flags); |
221 | rxq->need_update = 1; | 218 | rxq->need_update = 1; |
222 | spin_unlock_irqrestore(&rxq->lock, flags); | 219 | spin_unlock_irqrestore(&rxq->lock, flags); |
223 | ret = iwl_rx_queue_update_write_ptr(priv, rxq); | 220 | iwl_rx_queue_update_write_ptr(priv, rxq); |
224 | } | 221 | } |
225 | |||
226 | return ret; | ||
227 | } | 222 | } |
228 | EXPORT_SYMBOL(iwl_rx_queue_restock); | 223 | EXPORT_SYMBOL(iwl_rx_queue_restock); |
229 | 224 | ||
@@ -350,10 +345,10 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) | |||
350 | } | 345 | } |
351 | } | 346 | } |
352 | 347 | ||
353 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 348 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
354 | rxq->dma_addr); | 349 | rxq->dma_addr); |
355 | pci_free_consistent(priv->pci_dev, sizeof(struct iwl_rb_status), | 350 | dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), |
356 | rxq->rb_stts, rxq->rb_stts_dma); | 351 | rxq->rb_stts, rxq->rb_stts_dma); |
357 | rxq->bd = NULL; | 352 | rxq->bd = NULL; |
358 | rxq->rb_stts = NULL; | 353 | rxq->rb_stts = NULL; |
359 | } | 354 | } |
@@ -362,7 +357,7 @@ EXPORT_SYMBOL(iwl_rx_queue_free); | |||
362 | int iwl_rx_queue_alloc(struct iwl_priv *priv) | 357 | int iwl_rx_queue_alloc(struct iwl_priv *priv) |
363 | { | 358 | { |
364 | struct iwl_rx_queue *rxq = &priv->rxq; | 359 | struct iwl_rx_queue *rxq = &priv->rxq; |
365 | struct pci_dev *dev = priv->pci_dev; | 360 | struct device *dev = &priv->pci_dev->dev; |
366 | int i; | 361 | int i; |
367 | 362 | ||
368 | spin_lock_init(&rxq->lock); | 363 | spin_lock_init(&rxq->lock); |
@@ -370,12 +365,13 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
370 | INIT_LIST_HEAD(&rxq->rx_used); | 365 | INIT_LIST_HEAD(&rxq->rx_used); |
371 | 366 | ||
372 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ | 367 | /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ |
373 | rxq->bd = pci_alloc_consistent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr); | 368 | rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, |
369 | GFP_KERNEL); | ||
374 | if (!rxq->bd) | 370 | if (!rxq->bd) |
375 | goto err_bd; | 371 | goto err_bd; |
376 | 372 | ||
377 | rxq->rb_stts = pci_alloc_consistent(dev, sizeof(struct iwl_rb_status), | 373 | rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), |
378 | &rxq->rb_stts_dma); | 374 | &rxq->rb_stts_dma, GFP_KERNEL); |
379 | if (!rxq->rb_stts) | 375 | if (!rxq->rb_stts) |
380 | goto err_rb; | 376 | goto err_rb; |
381 | 377 | ||
@@ -392,8 +388,8 @@ int iwl_rx_queue_alloc(struct iwl_priv *priv) | |||
392 | return 0; | 388 | return 0; |
393 | 389 | ||
394 | err_rb: | 390 | err_rb: |
395 | pci_free_consistent(priv->pci_dev, 4 * RX_QUEUE_SIZE, rxq->bd, | 391 | dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, |
396 | rxq->dma_addr); | 392 | rxq->dma_addr); |
397 | err_bd: | 393 | err_bd: |
398 | return -ENOMEM; | 394 | return -ENOMEM; |
399 | } | 395 | } |
@@ -620,6 +616,11 @@ static void iwl_accumulative_statistics(struct iwl_priv *priv, | |||
620 | 616 | ||
621 | #define REG_RECALIB_PERIOD (60) | 617 | #define REG_RECALIB_PERIOD (60) |
622 | 618 | ||
619 | /* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */ | ||
620 | #define ACK_CNT_RATIO (50) | ||
621 | #define BA_TIMEOUT_CNT (5) | ||
622 | #define BA_TIMEOUT_MAX (16) | ||
623 | |||
623 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" | 624 | #define PLCP_MSG "plcp_err exceeded %u, %u, %u, %u, %u, %d, %u mSecs\n" |
624 | void iwl_rx_statistics(struct iwl_priv *priv, | 625 | void iwl_rx_statistics(struct iwl_priv *priv, |
625 | struct iwl_rx_mem_buffer *rxb) | 626 | struct iwl_rx_mem_buffer *rxb) |
@@ -629,6 +630,9 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
629 | int combined_plcp_delta; | 630 | int combined_plcp_delta; |
630 | unsigned int plcp_msec; | 631 | unsigned int plcp_msec; |
631 | unsigned long plcp_received_jiffies; | 632 | unsigned long plcp_received_jiffies; |
633 | int actual_ack_cnt_delta; | ||
634 | int expected_ack_cnt_delta; | ||
635 | int ba_timeout_delta; | ||
632 | 636 | ||
633 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", | 637 | IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", |
634 | (int)sizeof(priv->statistics), | 638 | (int)sizeof(priv->statistics), |
@@ -643,6 +647,44 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
643 | #ifdef CONFIG_IWLWIFI_DEBUG | 647 | #ifdef CONFIG_IWLWIFI_DEBUG |
644 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); | 648 | iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats); |
645 | #endif | 649 | #endif |
650 | actual_ack_cnt_delta = le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) - | ||
651 | le32_to_cpu(priv->statistics.tx.actual_ack_cnt); | ||
652 | expected_ack_cnt_delta = le32_to_cpu( | ||
653 | pkt->u.stats.tx.expected_ack_cnt) - | ||
654 | le32_to_cpu(priv->statistics.tx.expected_ack_cnt); | ||
655 | ba_timeout_delta = le32_to_cpu( | ||
656 | pkt->u.stats.tx.agg.ba_timeout) - | ||
657 | le32_to_cpu(priv->statistics.tx.agg.ba_timeout); | ||
658 | if ((priv->agg_tids_count > 0) && | ||
659 | (expected_ack_cnt_delta > 0) && | ||
660 | (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta) < | ||
661 | ACK_CNT_RATIO) && | ||
662 | (ba_timeout_delta > BA_TIMEOUT_CNT)) { | ||
663 | IWL_DEBUG_RADIO(priv, | ||
664 | "actual_ack_cnt delta = %d, expected_ack_cnt = %d\n", | ||
665 | actual_ack_cnt_delta, expected_ack_cnt_delta); | ||
666 | |||
667 | #ifdef CONFIG_IWLWIFI_DEBUG | ||
668 | IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n", | ||
669 | priv->delta_statistics.tx.rx_detected_cnt); | ||
670 | IWL_DEBUG_RADIO(priv, | ||
671 | "ack_or_ba_timeout_collision delta = %d\n", | ||
672 | priv->delta_statistics.tx.ack_or_ba_timeout_collision); | ||
673 | #endif | ||
674 | IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n", | ||
675 | ba_timeout_delta); | ||
676 | if ((actual_ack_cnt_delta == 0) && | ||
677 | (ba_timeout_delta >= | ||
678 | BA_TIMEOUT_MAX)) { | ||
679 | IWL_DEBUG_RADIO(priv, | ||
680 | "call iwl_force_reset(IWL_FW_RESET)\n"); | ||
681 | iwl_force_reset(priv, IWL_FW_RESET); | ||
682 | } else { | ||
683 | IWL_DEBUG_RADIO(priv, | ||
684 | "call iwl_force_reset(IWL_RF_RESET)\n"); | ||
685 | iwl_force_reset(priv, IWL_RF_RESET); | ||
686 | } | ||
687 | } | ||
646 | /* | 688 | /* |
647 | * check for plcp_err and trigger radio reset if it exceeds | 689 | * check for plcp_err and trigger radio reset if it exceeds |
648 | * the plcp error threshold plcp_delta. | 690 | * the plcp error threshold plcp_delta. |
@@ -689,7 +731,7 @@ void iwl_rx_statistics(struct iwl_priv *priv, | |||
689 | * Reset the RF radio due to the high plcp | 731 | * Reset the RF radio due to the high plcp |
690 | * error rate | 732 | * error rate |
691 | */ | 733 | */ |
692 | iwl_force_rf_reset(priv); | 734 | iwl_force_reset(priv, IWL_RF_RESET); |
693 | } | 735 | } |
694 | } | 736 | } |
695 | 737 | ||