iwlwifi: wipe out the status of the SCD when we disable a queue
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Sun, 30 Sep 2012 14:25:43 +0000 (16:25 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 16 Oct 2012 14:31:53 +0000 (16:31 +0200)
When we disable a queue, we don't want the SCD to remember anything
about this queue (what packet was transmitted but not acked, what
packed was acked etc...).
Wipe out all this data in its SRAM.

Constify the arguments to iwl_write_targ_mem_dwords on the way.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/iwl-io.c
drivers/net/wireless/iwlwifi/iwl-io.h
drivers/net/wireless/iwlwifi/iwl-prph.h
drivers/net/wireless/iwlwifi/pcie/tx.c

index 3dfebfb8434ff63e9b2ce7a2b2a86a7b01fad281..54c41b44bffea05581221166b93d3d57d33b1c5e 100644 (file)
@@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
 EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
 
 int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
-                              void *buf, int dwords)
+                              const void *buf, int dwords)
 {
        unsigned long flags;
        int offs, result = 0;
-       u32 *vals = buf;
+       const u32 *vals = buf;
 
        spin_lock_irqsave(&trans->reg_lock, flags);
        if (likely(iwl_grab_nic_access(trans))) {
index 50d3819739d12bd8296b3be9dec03425a488f45a..e1aa69f66de633befb027f28d820d738ad43a7e6 100644 (file)
@@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
        } while (0)
 
 int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
-                              void *buf, int dwords);
+                              const void *buf, int dwords);
 
 u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
 int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
index 9253ef1dba72d005f407b34c1bfb2665fb9b4be6..c3a4bb41e53370931832e8a7427d3361337e469d 100644 (file)
 #define SCD_CONTEXT_QUEUE_OFFSET(x)\
        (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
 
+#define SCD_TX_STTS_QUEUE_OFFSET(x)\
+       (SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))
+
 #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
        ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
 
index b50d1b4a4fcf98d4ef600ed93836494e42ed1536..f3c23afbbe63f34c07212cc1346872090274522d 100644 (file)
@@ -481,6 +481,9 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        u16 rd_ptr, wr_ptr;
+       u32 stts_addr = trans_pcie->scd_base_addr +
+                       SCD_TX_STTS_QUEUE_OFFSET(txq_id);
+       static const u32 zero_val[4] = {};
        int n_bd = trans_pcie->txq[txq_id].q.n_bd;
 
        if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
@@ -494,6 +497,9 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
        WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
                  txq_id, rd_ptr, wr_ptr);
 
+       _iwl_write_targ_mem_dwords(trans, stts_addr,
+                                  zero_val, ARRAY_SIZE(zero_val));
+
        iwl_txq_set_inactive(trans, txq_id);
        IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
 }