iwlwifi: pcie: fix prepare card flow
When the card is not owned by the PCIe bus, we need to acquire ownership first. This flow is implemented in iwl_pcie_prepare_card_hw. Because of a hardware bug, we need to disable link power management before we can request ownership otherwise the other user of the device won't get notified that we are requesting the device which will prevent us from acquire ownership. Same holds for the down flow where we need to make sure that any other potential user is notified that the driver is going down. CC: <stable@vger.kernel.org> [4.1] Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
Родитель
be88a1ada9
Коммит
c9fdec9f39
|
@ -478,10 +478,16 @@ static void iwl_pcie_apm_stop(struct iwl_trans *trans, bool op_mode_leave)
|
||||||
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
if (trans->cfg->device_family == IWL_DEVICE_FAMILY_7000)
|
||||||
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
|
iwl_set_bits_prph(trans, APMG_PCIDEV_STT_REG,
|
||||||
APMG_PCIDEV_STT_VAL_WAKE_ME);
|
APMG_PCIDEV_STT_VAL_WAKE_ME);
|
||||||
else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
else if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
|
||||||
|
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||||
|
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||||
CSR_HW_IF_CONFIG_REG_PREPARE |
|
CSR_HW_IF_CONFIG_REG_PREPARE |
|
||||||
CSR_HW_IF_CONFIG_REG_ENABLE_PME);
|
CSR_HW_IF_CONFIG_REG_ENABLE_PME);
|
||||||
|
mdelay(1);
|
||||||
|
iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||||
|
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||||
|
}
|
||||||
mdelay(5);
|
mdelay(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,6 +581,10 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||||
if (ret >= 0)
|
if (ret >= 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
iwl_set_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||||
|
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||||
|
msleep(1);
|
||||||
|
|
||||||
for (iter = 0; iter < 10; iter++) {
|
for (iter = 0; iter < 10; iter++) {
|
||||||
/* If HW is not ready, prepare the conditions to check again */
|
/* If HW is not ready, prepare the conditions to check again */
|
||||||
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
|
||||||
|
@ -582,8 +592,10 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = iwl_pcie_set_hw_ready(trans);
|
ret = iwl_pcie_set_hw_ready(trans);
|
||||||
if (ret >= 0)
|
if (ret >= 0) {
|
||||||
return 0;
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
usleep_range(200, 1000);
|
usleep_range(200, 1000);
|
||||||
t += 200;
|
t += 200;
|
||||||
|
@ -593,6 +605,10 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
|
||||||
|
|
||||||
IWL_ERR(trans, "Couldn't prepare the card\n");
|
IWL_ERR(trans, "Couldn't prepare the card\n");
|
||||||
|
|
||||||
|
out:
|
||||||
|
iwl_clear_bit(trans, CSR_DBG_LINK_PWR_MGMT_REG,
|
||||||
|
CSR_RESET_LINK_PWR_MGMT_DISABLED);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче