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:
Emmanuel Grumbach 2015-07-20 12:14:39 +03:00
Родитель be88a1ada9
Коммит c9fdec9f39
1 изменённых файлов: 19 добавлений и 3 удалений

Просмотреть файл

@ -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;
} }