Skip to content

Commit

Permalink
iwlwifi: pcie: fix tracking of cmd_in_flight
Browse files Browse the repository at this point in the history
The cmd_in_flight tracking was introduced to workaround faulty
power management hardware, by having the driver keep the NIC
awake as long as there are commands in flight. However, some of
the code handling this workaround was unconditionally executed,
which resulted with an inconsistent state where the driver assumed
that the NIC was awake although it wasn't.

Fix this by renaming 'cmd_in_flight' to 'cmd_hold_nic_awake' and
handling the NIC requested awake state only for hardwares for
which the workaround is needed.

Signed-off-by: Ilan Peer <[email protected]>
Signed-off-by: Emmanuel Grumbach <[email protected]>
  • Loading branch information
ilanpeer2 authored and egrumbach committed May 28, 2015
1 parent 2922089 commit fc8a350
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 19 deletions.
6 changes: 3 additions & 3 deletions drivers/net/wireless/iwlwifi/pcie/internal.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
* Copyright(c) 2003 - 2015 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
*
* Portions of this file are derived from the ipw3945 project, as well
* as portions of the ieee80211 subsystem header files.
Expand Down Expand Up @@ -320,7 +320,7 @@ struct iwl_trans_pcie {

/*protect hw register */
spinlock_t reg_lock;
bool cmd_in_flight;
bool cmd_hold_nic_awake;
bool ref_cmd_in_flight;

/* protect ref counter */
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/iwlwifi/pcie/trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans, bool silent,

spin_lock_irqsave(&trans_pcie->reg_lock, *flags);

if (trans_pcie->cmd_in_flight)
if (trans_pcie->cmd_hold_nic_awake)
goto out;

/* this bit wakes up the NIC */
Expand Down Expand Up @@ -1438,7 +1438,7 @@ static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans,
*/
__acquire(&trans_pcie->reg_lock);

if (trans_pcie->cmd_in_flight)
if (trans_pcie->cmd_hold_nic_awake)
goto out;

__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
Expand Down
23 changes: 9 additions & 14 deletions drivers/net/wireless/iwlwifi/pcie/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1039,18 +1039,14 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
iwl_trans_pcie_ref(trans);
}

if (trans_pcie->cmd_in_flight)
return 0;

trans_pcie->cmd_in_flight = true;

/*
* 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.
*/
if (trans->cfg->base_params->apmg_wake_up_wa) {
if (trans->cfg->base_params->apmg_wake_up_wa &&
!trans_pcie->cmd_hold_nic_awake) {
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
Expand All @@ -1064,10 +1060,10 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
if (ret < 0) {
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
trans_pcie->cmd_in_flight = false;
IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
return -EIO;
}
trans_pcie->cmd_hold_nic_awake = true;
}

return 0;
Expand All @@ -1085,15 +1081,14 @@ static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
iwl_trans_pcie_unref(trans);
}

if (WARN_ON(!trans_pcie->cmd_in_flight))
return 0;

trans_pcie->cmd_in_flight = false;
if (trans->cfg->base_params->apmg_wake_up_wa) {
if (WARN_ON(!trans_pcie->cmd_hold_nic_awake))
return 0;

if (trans->cfg->base_params->apmg_wake_up_wa)
trans_pcie->cmd_hold_nic_awake = false;
__iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);

CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
}
return 0;
}

Expand Down

0 comments on commit fc8a350

Please sign in to comment.