]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iwlwifi: queue: avoid memory leak in reset flow
authorMordechay Goodstein <mordechay.goodstein@intel.com>
Sun, 11 Apr 2021 09:46:22 +0000 (12:46 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Wed, 14 Apr 2021 09:07:19 +0000 (12:07 +0300)
In case the device is stopped any usage of hw queues needs to be
reallocated in fw due to fw reset after device stop, so all driver
internal queue should also be freed, and if we don't free the next usage
would leak the old memory and get in recover flows
"iwlwifi 0000:00:03.0: dma_pool_destroy iwlwifi:bc" warning.

Also warn about trying to reuse an internal allocated queue.

Signed-off-by: Mordechay Goodstein <mordechay.goodstein@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210411124417.c72d2f0355c4.Ia3baff633b9b9109f88ab379ef0303aa152c16bf@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
drivers/net/wireless/intel/iwlwifi/queue/tx.c
drivers/net/wireless/intel/iwlwifi/queue/tx.h

index 9d94c47952d1fb92f35e80e86ff03c91a4aed7db..1bcd36e9e00869e490e7083e65192df48e349537 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
  * Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
  */
 #include "iwl-trans.h"
 #include "iwl-prph.h"
@@ -143,7 +143,7 @@ void _iwl_trans_pcie_gen2_stop_device(struct iwl_trans *trans)
        if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
                IWL_DEBUG_INFO(trans,
                               "DEVICE_ENABLED bit was set and is now cleared\n");
-               iwl_txq_gen2_tx_stop(trans);
+               iwl_txq_gen2_tx_free(trans);
                iwl_pcie_rx_stop(trans);
        }
 
index 494f9dbf92d687eb8aaa21df8cac02775b88ec0a..451b06069350196e99518c5c8decf309d5cc804f 100644 (file)
 #include "iwl-scd.h"
 #include <linux/dmapool.h>
 
-/*
- * iwl_txq_gen2_tx_stop - Stop all Tx DMA channels
- */
-void iwl_txq_gen2_tx_stop(struct iwl_trans *trans)
-{
-       int txq_id;
-
-       /*
-        * This function can be called before the op_mode disabled the
-        * queues. This happens when we have an rfkill interrupt.
-        * Since we stop Tx altogether - mark the queues as stopped.
-        */
-       memset(trans->txqs.queue_stopped, 0,
-              sizeof(trans->txqs.queue_stopped));
-       memset(trans->txqs.queue_used, 0, sizeof(trans->txqs.queue_used));
-
-       /* Unmap DMA from host system and free skb's */
-       for (txq_id = 0; txq_id < ARRAY_SIZE(trans->txqs.txq); txq_id++) {
-               if (!trans->txqs.txq[txq_id])
-                       continue;
-               iwl_txq_gen2_unmap(trans, txq_id);
-       }
-}
-
 /*
  * iwl_txq_update_byte_tbl - Set up entry in Tx byte-count array
  */
@@ -1184,6 +1160,12 @@ static int iwl_txq_alloc_response(struct iwl_trans *trans, struct iwl_txq *txq,
                goto error_free_resp;
        }
 
+       if (WARN_ONCE(trans->txqs.txq[qid],
+                     "queue %d already allocated\n", qid)) {
+               ret = -EIO;
+               goto error_free_resp;
+       }
+
        txq->id = qid;
        trans->txqs.txq[qid] = txq;
        wr_ptr &= (trans->trans_cfg->base_params->max_tfd_queue_size - 1);
index af1dbdf5617a012833db892369d486c6952fbbd0..20efc62acf133a1c43c40d504a09640947fef580 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2020 Intel Corporation
+ * Copyright (C) 2020-2021 Intel Corporation
  */
 #ifndef __iwl_trans_queue_tx_h__
 #define __iwl_trans_queue_tx_h__
@@ -123,7 +123,6 @@ int iwl_txq_gen2_tx(struct iwl_trans *trans, struct sk_buff *skb,
 void iwl_txq_dyn_free(struct iwl_trans *trans, int queue);
 void iwl_txq_gen2_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq);
 void iwl_txq_inc_wr_ptr(struct iwl_trans *trans, struct iwl_txq *txq);
-void iwl_txq_gen2_tx_stop(struct iwl_trans *trans);
 void iwl_txq_gen2_tx_free(struct iwl_trans *trans);
 int iwl_txq_init(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
                 bool cmd_queue);