iwlwifi: get the correct HCMD in the response handler
[deliverable/linux.git] / drivers / net / wireless / iwlwifi / pcie / rx.c
index d6860c070c16c06a0255d02ea380c56210b64909..d80604a2bb1a16c5951cb31aa5a790bc2349a814 100644 (file)
@@ -421,13 +421,23 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
                index = SEQ_TO_INDEX(sequence);
                cmd_index = get_cmd_index(&txq->q, index);
 
-               if (reclaim)
-                       cmd = txq->entries[cmd_index].cmd;
-               else
+               if (reclaim) {
+                       struct iwl_pcie_tx_queue_entry *ent;
+                       ent = &txq->entries[cmd_index];
+                       cmd = ent->copy_cmd;
+                       WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
+               } else {
                        cmd = NULL;
+               }
 
                err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
 
+               if (reclaim) {
+                       /* The original command isn't needed any more */
+                       kfree(txq->entries[cmd_index].copy_cmd);
+                       txq->entries[cmd_index].copy_cmd = NULL;
+               }
+
                /*
                 * After here, we should always check rxcb._page_stolen,
                 * if it is true then one of the handlers took the page.
@@ -867,23 +877,19 @@ void iwl_disable_ict(struct iwl_trans *trans)
        spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
 }
 
+/* legacy (non-ICT) ISR. Assumes that trans_pcie->irq_lock is held */
 static irqreturn_t iwl_isr(int irq, void *data)
 {
        struct iwl_trans *trans = data;
-       struct iwl_trans_pcie *trans_pcie;
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        u32 inta, inta_mask;
-       unsigned long flags;
 #ifdef CONFIG_IWLWIFI_DEBUG
        u32 inta_fh;
 #endif
-       if (!trans)
-               return IRQ_NONE;
 
-       trace_iwlwifi_dev_irq(trans->dev);
+       lockdep_assert_held(&trans_pcie->irq_lock);
 
-       trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+       trace_iwlwifi_dev_irq(trans->dev);
 
        /* Disable (but don't clear!) interrupts here to avoid
         *    back-to-back ISRs and sporadic interrupts from our NIC.
@@ -907,7 +913,7 @@ static irqreturn_t iwl_isr(int irq, void *data)
                /* Hardware disappeared. It might have already raised
                 * an interrupt */
                IWL_WARN(trans, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
-               goto unplugged;
+               return IRQ_HANDLED;
        }
 
 #ifdef CONFIG_IWLWIFI_DEBUG
@@ -926,18 +932,13 @@ static irqreturn_t iwl_isr(int irq, void *data)
                 !trans_pcie->inta)
                iwl_enable_interrupts(trans);
 
- unplugged:
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
-       return IRQ_HANDLED;
-
- none:
+none:
        /* re-enable interrupts here since we don't have anything to service. */
        /* only Re-enable if disabled by irq  and no schedules tasklet. */
        if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
            !trans_pcie->inta)
                iwl_enable_interrupts(trans);
 
-       spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
        return IRQ_NONE;
 }
 
@@ -963,15 +964,19 @@ irqreturn_t iwl_isr_ict(int irq, void *data)
 
        trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
+       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+
        /* dram interrupt table not set yet,
         * use legacy interrupt.
         */
-       if (!trans_pcie->use_ict)
-               return iwl_isr(irq, data);
+       if (unlikely(!trans_pcie->use_ict)) {
+               irqreturn_t ret = iwl_isr(irq, data);
+               spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+               return ret;
+       }
 
        trace_iwlwifi_dev_irq(trans->dev);
 
-       spin_lock_irqsave(&trans_pcie->irq_lock, flags);
 
        /* Disable (but don't clear!) interrupts here to avoid
         * back-to-back ISRs and sporadic interrupts from our NIC.
This page took 0.041098 seconds and 5 git commands to generate.