diff options
author | Mohamed Abbas <mabbas@linux.intel.com> | 2007-11-28 22:10:14 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:05:36 -0500 |
commit | 5c0eef960bdb87a53ba390aab7b069b2bc8d7f6d (patch) | |
tree | 7c219792536fc1bfcbdf35ae2741a0621f3ccdea /drivers/net/wireless/iwlwifi/iwl3945-base.c | |
parent | 7878a5a4fcc5002e805c054730c4c5639c9d071d (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>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl3945-base.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 82c1e0d45cf2..3272608ced83 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 | */ |
4126 | void iwl3945_rx_replenish(void *data) | 4126 | static 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 | */ | ||
4165 | void __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 | |||
4174 | void 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 */ |