Commit cda4ee3f authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by John W. Linville

iwlagn: fix the race in the unmapping of the HCMD

As Stanislaw pointed out, my patch

	iwlagn: fix a race in the unmapping of the TFDs

solved only part of the problem. The race still exists for TFDs of
the host commands. Fix that too.
Reported-by: default avatarStanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent c125d5e8
...@@ -407,6 +407,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) ...@@ -407,6 +407,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
struct iwl_queue *q = &txq->q; struct iwl_queue *q = &txq->q;
enum dma_data_direction dma_dir; enum dma_data_direction dma_dir;
unsigned long flags; unsigned long flags;
spinlock_t *lock;
if (!q->n_bd) if (!q->n_bd)
return; return;
...@@ -414,19 +415,22 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) ...@@ -414,19 +415,22 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id)
/* In the command queue, all the TBs are mapped as BIDI /* In the command queue, all the TBs are mapped as BIDI
* so unmap them as such. * so unmap them as such.
*/ */
if (txq_id == trans->shrd->cmd_queue) if (txq_id == trans->shrd->cmd_queue) {
dma_dir = DMA_BIDIRECTIONAL; dma_dir = DMA_BIDIRECTIONAL;
else lock = &trans->hcmd_lock;
} else {
dma_dir = DMA_TO_DEVICE; dma_dir = DMA_TO_DEVICE;
lock = &trans->shrd->sta_lock;
}
spin_lock_irqsave(&trans->shrd->sta_lock, flags); spin_lock_irqsave(lock, flags);
while (q->write_ptr != q->read_ptr) { while (q->write_ptr != q->read_ptr) {
/* The read_ptr needs to bound by q->n_window */ /* The read_ptr needs to bound by q->n_window */
iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr), iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr),
dma_dir); dma_dir);
q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
} }
spin_unlock_irqrestore(&trans->shrd->sta_lock, flags); spin_unlock_irqrestore(lock, flags);
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment