]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iwlwifi: pcie: avoid unnecessarily taking spinlock
authorJohannes Berg <johannes.berg@intel.com>
Tue, 30 Mar 2021 13:24:50 +0000 (16:24 +0300)
committerLuca Coelho <luciano.coelho@intel.com>
Wed, 14 Apr 2021 09:05:26 +0000 (12:05 +0300)
Most devices don't set the apmg_wake_up_wa flag, so we don't do
anything for them. Avoid taking the spinlock for every command
unless the device needs this workaround.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20210330162204.1ab60af3f318.I51cc202f68a2a953223e70c3e8610343412961b6@changeid
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index 7ae32491b5dae275df23ada603167c1ee3b4b68a..5ce61fb469cd02a32b1a22a5119695902b9ea681 100644 (file)
@@ -181,16 +181,20 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
-       lockdep_assert_held(&trans_pcie->reg_lock);
-
        if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
                return;
-       if (WARN_ON(!trans_pcie->cmd_hold_nic_awake))
+
+       spin_lock(&trans_pcie->reg_lock);
+
+       if (WARN_ON(!trans_pcie->cmd_hold_nic_awake)) {
+               spin_unlock(&trans_pcie->reg_lock);
                return;
+       }
 
        trans_pcie->cmd_hold_nic_awake = false;
        __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
                                   CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+       spin_unlock(&trans_pcie->reg_lock);
 }
 
 /*
@@ -198,7 +202,6 @@ static void iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
  */
 static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_txq *txq = trans->txqs.txq[txq_id];
 
        if (!txq) {
@@ -222,12 +225,9 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
                iwl_txq_free_tfd(trans, txq);
                txq->read_ptr = iwl_txq_inc_wrap(trans, txq->read_ptr);
 
-               if (txq->read_ptr == txq->write_ptr) {
-                       spin_lock(&trans_pcie->reg_lock);
-                       if (txq_id == trans->txqs.cmd.q_id)
-                               iwl_pcie_clear_cmd_in_flight(trans);
-                       spin_unlock(&trans_pcie->reg_lock);
-               }
+               if (txq->read_ptr == txq->write_ptr &&
+                   txq_id == trans->txqs.cmd.q_id)
+                       iwl_pcie_clear_cmd_in_flight(trans);
        }
 
        while (!skb_queue_empty(&txq->overflow_q)) {
@@ -629,22 +629,23 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
                                      const struct iwl_host_cmd *cmd)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       int ret;
-
-       lockdep_assert_held(&trans_pcie->reg_lock);
+       int ret = 0;
 
        /* Make sure the NIC is still alive in the bus */
        if (test_bit(STATUS_TRANS_DEAD, &trans->status))
                return -ENODEV;
 
+       if (!trans->trans_cfg->base_params->apmg_wake_up_wa)
+               return 0;
+
+       spin_lock(&trans_pcie->reg_lock);
        /*
         * wake up the NIC to make sure that the firmware will see the host
         * command - we will let the NIC sleep once all the host commands
         * returned. This needs to be done only on NICs that have
-        * apmg_wake_up_wa set.
+        * apmg_wake_up_wa set (see above.)
         */
-       if (trans->trans_cfg->base_params->apmg_wake_up_wa &&
-           !trans_pcie->cmd_hold_nic_awake) {
+       if (!trans_pcie->cmd_hold_nic_awake) {
                __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
                                         CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
 
@@ -657,12 +658,14 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
                        __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
                                        CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
                        IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
-                       return -EIO;
+                       ret = -EIO;
+               } else {
+                       trans_pcie->cmd_hold_nic_awake = true;
                }
-               trans_pcie->cmd_hold_nic_awake = true;
        }
+       spin_unlock(&trans_pcie->reg_lock);
 
-       return 0;
+       return ret;
 }
 
 /*
@@ -674,7 +677,6 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
  */
 static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_txq *txq = trans->txqs.txq[txq_id];
        int nfreed = 0;
        u16 r;
@@ -705,12 +707,8 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
                }
        }
 
-       if (txq->read_ptr == txq->write_ptr) {
-               /* BHs are also disabled due to txq->lock */
-               spin_lock(&trans_pcie->reg_lock);
+       if (txq->read_ptr == txq->write_ptr)
                iwl_pcie_clear_cmd_in_flight(trans);
-               spin_unlock(&trans_pcie->reg_lock);
-       }
 
        iwl_txq_progress(txq);
 }
@@ -914,7 +912,6 @@ void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id,
 int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                          struct iwl_host_cmd *cmd)
 {
-       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_txq *txq = trans->txqs.txq[trans->txqs.cmd.q_id];
        struct iwl_device_cmd *out_cmd;
        struct iwl_cmd_meta *out_meta;
@@ -1161,19 +1158,16 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        if (txq->read_ptr == txq->write_ptr && txq->wd_timeout)
                mod_timer(&txq->stuck_timer, jiffies + txq->wd_timeout);
 
-       spin_lock(&trans_pcie->reg_lock);
        ret = iwl_pcie_set_cmd_in_flight(trans, cmd);
        if (ret < 0) {
                idx = ret;
-               goto unlock_reg;
+               goto out;
        }
 
        /* Increment and update queue's write index */
        txq->write_ptr = iwl_txq_inc_wrap(trans, txq->write_ptr);
        iwl_pcie_txq_inc_wr_ptr(trans, txq);
 
- unlock_reg:
-       spin_unlock(&trans_pcie->reg_lock);
  out:
        spin_unlock_irqrestore(&txq->lock, flags);
  free_dup_buf: