iwlwifi: queue: don't crash if txq->entries is NULL

The code was really awkward, we would first dereference
txq->entries when calling iwl_txq_genX_tfd_unmap and then
we would check that txq->entries is non-NULL.
Fix that by exiting if txq->entries is NULL.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20210115130252.173359fc236d.I75c7c2397d20df8d7fbc24cb16a5232d5c551889@changeid
This commit is contained in:
Emmanuel Grumbach 2021-01-15 13:05:53 +02:00 committed by Kalle Valo
parent a800f95858
commit 0f8d5656b3

View File

@ -142,26 +142,25 @@ void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
* idx is bounded by n_window * idx is bounded by n_window
*/ */
int idx = iwl_txq_get_cmd_index(txq, txq->read_ptr); int idx = iwl_txq_get_cmd_index(txq, txq->read_ptr);
struct sk_buff *skb;
lockdep_assert_held(&txq->lock); lockdep_assert_held(&txq->lock);
if (!txq->entries)
return;
iwl_txq_gen2_tfd_unmap(trans, &txq->entries[idx].meta, iwl_txq_gen2_tfd_unmap(trans, &txq->entries[idx].meta,
iwl_txq_get_tfd(trans, txq, idx)); iwl_txq_get_tfd(trans, txq, idx));
/* free SKB */ skb = txq->entries[idx].skb;
if (txq->entries) {
struct sk_buff *skb;
skb = txq->entries[idx].skb; /* Can be called from irqs-disabled context
* If skb is not NULL, it means that the whole queue is being
/* Can be called from irqs-disabled context * freed and that the queue is not empty - free the skb
* If skb is not NULL, it means that the whole queue is being */
* freed and that the queue is not empty - free the skb if (skb) {
*/ iwl_op_mode_free_skb(trans->op_mode, skb);
if (skb) { txq->entries[idx].skb = NULL;
iwl_op_mode_free_skb(trans->op_mode, skb);
txq->entries[idx].skb = NULL;
}
} }
} }
@ -1494,28 +1493,28 @@ void iwl_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
*/ */
int rd_ptr = txq->read_ptr; int rd_ptr = txq->read_ptr;
int idx = iwl_txq_get_cmd_index(txq, rd_ptr); int idx = iwl_txq_get_cmd_index(txq, rd_ptr);
struct sk_buff *skb;
lockdep_assert_held(&txq->lock); lockdep_assert_held(&txq->lock);
if (!txq->entries)
return;
/* We have only q->n_window txq->entries, but we use /* We have only q->n_window txq->entries, but we use
* TFD_QUEUE_SIZE_MAX tfds * TFD_QUEUE_SIZE_MAX tfds
*/ */
iwl_txq_gen1_tfd_unmap(trans, &txq->entries[idx].meta, txq, rd_ptr); iwl_txq_gen1_tfd_unmap(trans, &txq->entries[idx].meta, txq, rd_ptr);
/* free SKB */ /* free SKB */
if (txq->entries) { skb = txq->entries[idx].skb;
struct sk_buff *skb;
skb = txq->entries[idx].skb; /* Can be called from irqs-disabled context
* If skb is not NULL, it means that the whole queue is being
/* Can be called from irqs-disabled context * freed and that the queue is not empty - free the skb
* If skb is not NULL, it means that the whole queue is being */
* freed and that the queue is not empty - free the skb if (skb) {
*/ iwl_op_mode_free_skb(trans->op_mode, skb);
if (skb) { txq->entries[idx].skb = NULL;
iwl_op_mode_free_skb(trans->op_mode, skb);
txq->entries[idx].skb = NULL;
}
} }
} }