aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamed Abbas <mabbas@linux.intel.com>2007-11-28 22:10:14 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 18:05:36 -0500
commit5c0eef960bdb87a53ba390aab7b069b2bc8d7f6d (patch)
tree7c219792536fc1bfcbdf35ae2741a0621f3ccdea
parent7878a5a4fcc5002e805c054730c4c5639c9d071d (diff)
iwlwifi: fix ucode assertion for RX queue overrun
This patch allows the driver to restock the RX queue early if the RX queue is almost empty. This will help on avoiding any ucode assert for the RX overrun problem. Signed-off-by: Mohamed Abbas <mabbas@linux.intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c37
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c38
2 files changed, 71 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 82c1e0d45cf..3272608ced8 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -4123,9 +4123,8 @@ static int iwl3945_rx_queue_restock(struct iwl3945_priv *priv)
4123 * Also restock the Rx queue via iwl3945_rx_queue_restock. 4123 * Also restock the Rx queue via iwl3945_rx_queue_restock.
4124 * This is called as a scheduled work item (except for during initialization) 4124 * This is called as a scheduled work item (except for during initialization)
4125 */ 4125 */
4126void iwl3945_rx_replenish(void *data) 4126static void iwl3945_rx_allocate(struct iwl3945_priv *priv)
4127{ 4127{
4128 struct iwl3945_priv *priv = data;
4129 struct iwl3945_rx_queue *rxq = &priv->rxq; 4128 struct iwl3945_rx_queue *rxq = &priv->rxq;
4130 struct list_head *element; 4129 struct list_head *element;
4131 struct iwl3945_rx_mem_buffer *rxb; 4130 struct iwl3945_rx_mem_buffer *rxb;
@@ -4158,6 +4157,26 @@ void iwl3945_rx_replenish(void *data)
4158 rxq->free_count++; 4157 rxq->free_count++;
4159 } 4158 }
4160 spin_unlock_irqrestore(&rxq->lock, flags); 4159 spin_unlock_irqrestore(&rxq->lock, flags);
4160}
4161
4162/*
4163 * this should be called while priv->lock is locked
4164 */
4165void __iwl3945_rx_replenish(void *data)
4166{
4167 struct iwl3945_priv *priv = data;
4168
4169 iwl3945_rx_allocate(priv);
4170 iwl3945_rx_queue_restock(priv);
4171}
4172
4173
4174void iwl3945_rx_replenish(void *data)
4175{
4176 struct iwl3945_priv *priv = data;
4177 unsigned long flags;
4178
4179 iwl3945_rx_allocate(priv);
4161 4180
4162 spin_lock_irqsave(&priv->lock, flags); 4181 spin_lock_irqsave(&priv->lock, flags);
4163 iwl3945_rx_queue_restock(priv); 4182 iwl3945_rx_queue_restock(priv);
@@ -4335,12 +4354,16 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
4335 u32 r, i; 4354 u32 r, i;
4336 int reclaim; 4355 int reclaim;
4337 unsigned long flags; 4356 unsigned long flags;
4357 u8 fill_rx = 0;
4358 u32 count = 0;
4338 4359
4339 /* uCode's read index (stored in shared DRAM) indicates the last Rx 4360 /* uCode's read index (stored in shared DRAM) indicates the last Rx
4340 * buffer that the driver may process (last buffer filled by ucode). */ 4361 * buffer that the driver may process (last buffer filled by ucode). */
4341 r = iwl3945_hw_get_rx_read(priv); 4362 r = iwl3945_hw_get_rx_read(priv);
4342 i = rxq->read; 4363 i = rxq->read;
4343 4364
4365 if (iwl3945_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
4366 fill_rx = 1;
4344 /* Rx interrupt, but nothing sent from uCode */ 4367 /* Rx interrupt, but nothing sent from uCode */
4345 if (i == r) 4368 if (i == r)
4346 IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i); 4369 IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
@@ -4411,6 +4434,16 @@ static void iwl3945_rx_handle(struct iwl3945_priv *priv)
4411 list_add_tail(&rxb->list, &priv->rxq.rx_used); 4434 list_add_tail(&rxb->list, &priv->rxq.rx_used);
4412 spin_unlock_irqrestore(&rxq->lock, flags); 4435 spin_unlock_irqrestore(&rxq->lock, flags);
4413 i = (i + 1) & RX_QUEUE_MASK; 4436 i = (i + 1) & RX_QUEUE_MASK;
4437 /* If there are a lot of unused frames,
4438 * restock the Rx queue so ucode won't assert. */
4439 if (fill_rx) {
4440 count++;
4441 if (count >= 8) {
4442 priv->rxq.read = i;
4443 __iwl3945_rx_replenish(priv);
4444 count = 0;
4445 }
4446 }
4414 } 4447 }
4415 4448
4416 /* Backtrack one entry */ 4449 /* Backtrack one entry */
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 670f611adf9..6be38ce701f 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -4477,9 +4477,8 @@ static int iwl4965_rx_queue_restock(struct iwl4965_priv *priv)
4477 * Also restock the Rx queue via iwl4965_rx_queue_restock. 4477 * Also restock the Rx queue via iwl4965_rx_queue_restock.
4478 * This is called as a scheduled work item (except for during initialization) 4478 * This is called as a scheduled work item (except for during initialization)
4479 */ 4479 */
4480void iwl4965_rx_replenish(void *data) 4480static void iwl4965_rx_allocate(struct iwl4965_priv *priv)
4481{ 4481{
4482 struct iwl4965_priv *priv = data;
4483 struct iwl4965_rx_queue *rxq = &priv->rxq; 4482 struct iwl4965_rx_queue *rxq = &priv->rxq;
4484 struct list_head *element; 4483 struct list_head *element;
4485 struct iwl4965_rx_mem_buffer *rxb; 4484 struct iwl4965_rx_mem_buffer *rxb;
@@ -4512,6 +4511,26 @@ void iwl4965_rx_replenish(void *data)
4512 rxq->free_count++; 4511 rxq->free_count++;
4513 } 4512 }
4514 spin_unlock_irqrestore(&rxq->lock, flags); 4513 spin_unlock_irqrestore(&rxq->lock, flags);
4514}
4515
4516/*
4517 * this should be called while priv->lock is locked
4518*/
4519void __iwl4965_rx_replenish(void *data)
4520{
4521 struct iwl4965_priv *priv = data;
4522
4523 iwl4965_rx_allocate(priv);
4524 iwl4965_rx_queue_restock(priv);
4525}
4526
4527
4528void iwl4965_rx_replenish(void *data)
4529{
4530 struct iwl4965_priv *priv = data;
4531 unsigned long flags;
4532
4533 iwl4965_rx_allocate(priv);
4515 4534
4516 spin_lock_irqsave(&priv->lock, flags); 4535 spin_lock_irqsave(&priv->lock, flags);
4517 iwl4965_rx_queue_restock(priv); 4536 iwl4965_rx_queue_restock(priv);
@@ -4689,6 +4708,8 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
4689 u32 r, i; 4708 u32 r, i;
4690 int reclaim; 4709 int reclaim;
4691 unsigned long flags; 4710 unsigned long flags;
4711 u8 fill_rx = 0;
4712 u32 count = 0;
4692 4713
4693 /* uCode's read index (stored in shared DRAM) indicates the last Rx 4714 /* uCode's read index (stored in shared DRAM) indicates the last Rx
4694 * buffer that the driver may process (last buffer filled by ucode). */ 4715 * buffer that the driver may process (last buffer filled by ucode). */
@@ -4699,6 +4720,9 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
4699 if (i == r) 4720 if (i == r)
4700 IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i); 4721 IWL_DEBUG(IWL_DL_RX | IWL_DL_ISR, "r = %d, i = %d\n", r, i);
4701 4722
4723 if (iwl4965_rx_queue_space(rxq) > (RX_QUEUE_SIZE / 2))
4724 fill_rx = 1;
4725
4702 while (i != r) { 4726 while (i != r) {
4703 rxb = rxq->queue[i]; 4727 rxb = rxq->queue[i];
4704 4728
@@ -4768,6 +4792,16 @@ static void iwl4965_rx_handle(struct iwl4965_priv *priv)
4768 list_add_tail(&rxb->list, &priv->rxq.rx_used); 4792 list_add_tail(&rxb->list, &priv->rxq.rx_used);
4769 spin_unlock_irqrestore(&rxq->lock, flags); 4793 spin_unlock_irqrestore(&rxq->lock, flags);
4770 i = (i + 1) & RX_QUEUE_MASK; 4794 i = (i + 1) & RX_QUEUE_MASK;
4795 /* If there are a lot of unused frames,
4796 * restock the Rx queue so ucode wont assert. */
4797 if (fill_rx) {
4798 count++;
4799 if (count >= 8) {
4800 priv->rxq.read = i;
4801 __iwl4965_rx_replenish(priv);
4802 count = 0;
4803 }
4804 }
4771 } 4805 }
4772 4806
4773 /* Backtrack one entry */ 4807 /* Backtrack one entry */