diff options
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/iwl-8000.c | 42 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/internal.h | 9 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 188 |
7 files changed, 164 insertions, 94 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/Kconfig b/drivers/net/wireless/intel/iwlwifi/Kconfig index 866067789330..7438fbeef744 100644 --- a/drivers/net/wireless/intel/iwlwifi/Kconfig +++ b/drivers/net/wireless/intel/iwlwifi/Kconfig | |||
| @@ -53,7 +53,6 @@ config IWLWIFI_LEDS | |||
| 53 | 53 | ||
| 54 | config IWLDVM | 54 | config IWLDVM |
| 55 | tristate "Intel Wireless WiFi DVM Firmware support" | 55 | tristate "Intel Wireless WiFi DVM Firmware support" |
| 56 | depends on m | ||
| 57 | help | 56 | help |
| 58 | This is the driver that supports the DVM firmware. The list | 57 | This is the driver that supports the DVM firmware. The list |
| 59 | of the devices that use this firmware is available here: | 58 | of the devices that use this firmware is available here: |
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c index c84a0299d43e..bce9b3420a13 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-8000.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | * | 7 | * |
| 8 | * Copyright(c) 2014 Intel Corporation. All rights reserved. | 8 | * Copyright(c) 2014 Intel Corporation. All rights reserved. |
| 9 | * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH | 9 | * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH |
| 10 | * Copyright(c) 2016 Intel Deutschland GmbH | ||
| 10 | * | 11 | * |
| 11 | * This program is free software; you can redistribute it and/or modify | 12 | * This program is free software; you can redistribute it and/or modify |
| 12 | * it under the terms of version 2 of the GNU General Public License as | 13 | * it under the terms of version 2 of the GNU General Public License as |
| @@ -70,12 +71,15 @@ | |||
| 70 | 71 | ||
| 71 | /* Highest firmware API version supported */ | 72 | /* Highest firmware API version supported */ |
| 72 | #define IWL8000_UCODE_API_MAX 20 | 73 | #define IWL8000_UCODE_API_MAX 20 |
| 74 | #define IWL8265_UCODE_API_MAX 20 | ||
| 73 | 75 | ||
| 74 | /* Oldest version we won't warn about */ | 76 | /* Oldest version we won't warn about */ |
| 75 | #define IWL8000_UCODE_API_OK 13 | 77 | #define IWL8000_UCODE_API_OK 13 |
| 78 | #define IWL8265_UCODE_API_OK 20 | ||
| 76 | 79 | ||
| 77 | /* Lowest firmware API version supported */ | 80 | /* Lowest firmware API version supported */ |
| 78 | #define IWL8000_UCODE_API_MIN 13 | 81 | #define IWL8000_UCODE_API_MIN 13 |
| 82 | #define IWL8265_UCODE_API_MIN 20 | ||
| 79 | 83 | ||
| 80 | /* NVM versions */ | 84 | /* NVM versions */ |
| 81 | #define IWL8000_NVM_VERSION 0x0a1d | 85 | #define IWL8000_NVM_VERSION 0x0a1d |
| @@ -93,6 +97,10 @@ | |||
| 93 | #define IWL8000_MODULE_FIRMWARE(api) \ | 97 | #define IWL8000_MODULE_FIRMWARE(api) \ |
| 94 | IWL8000_FW_PRE "-" __stringify(api) ".ucode" | 98 | IWL8000_FW_PRE "-" __stringify(api) ".ucode" |
| 95 | 99 | ||
| 100 | #define IWL8265_FW_PRE "iwlwifi-8265-" | ||
| 101 | #define IWL8265_MODULE_FIRMWARE(api) \ | ||
| 102 | IWL8265_FW_PRE __stringify(api) ".ucode" | ||
| 103 | |||
| 96 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 | 104 | #define NVM_HW_SECTION_NUM_FAMILY_8000 10 |
| 97 | #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" | 105 | #define DEFAULT_NVM_FILE_FAMILY_8000B "nvmData-8000B" |
| 98 | #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" | 106 | #define DEFAULT_NVM_FILE_FAMILY_8000C "nvmData-8000C" |
| @@ -144,10 +152,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { | |||
| 144 | .support_tx_backoff = true, | 152 | .support_tx_backoff = true, |
| 145 | }; | 153 | }; |
| 146 | 154 | ||
| 147 | #define IWL_DEVICE_8000 \ | 155 | #define IWL_DEVICE_8000_COMMON \ |
| 148 | .ucode_api_max = IWL8000_UCODE_API_MAX, \ | ||
| 149 | .ucode_api_ok = IWL8000_UCODE_API_OK, \ | ||
| 150 | .ucode_api_min = IWL8000_UCODE_API_MIN, \ | ||
| 151 | .device_family = IWL_DEVICE_FAMILY_8000, \ | 156 | .device_family = IWL_DEVICE_FAMILY_8000, \ |
| 152 | .max_inst_size = IWL60_RTC_INST_SIZE, \ | 157 | .max_inst_size = IWL60_RTC_INST_SIZE, \ |
| 153 | .max_data_size = IWL60_RTC_DATA_SIZE, \ | 158 | .max_data_size = IWL60_RTC_DATA_SIZE, \ |
| @@ -167,10 +172,28 @@ static const struct iwl_tt_params iwl8000_tt_params = { | |||
| 167 | .thermal_params = &iwl8000_tt_params, \ | 172 | .thermal_params = &iwl8000_tt_params, \ |
| 168 | .apmg_not_supported = true | 173 | .apmg_not_supported = true |
| 169 | 174 | ||
| 175 | #define IWL_DEVICE_8000 \ | ||
| 176 | IWL_DEVICE_8000_COMMON, \ | ||
| 177 | .ucode_api_max = IWL8000_UCODE_API_MAX, \ | ||
| 178 | .ucode_api_ok = IWL8000_UCODE_API_OK, \ | ||
| 179 | .ucode_api_min = IWL8000_UCODE_API_MIN \ | ||
| 180 | |||
| 181 | #define IWL_DEVICE_8260 \ | ||
| 182 | IWL_DEVICE_8000_COMMON, \ | ||
| 183 | .ucode_api_max = IWL8000_UCODE_API_MAX, \ | ||
| 184 | .ucode_api_ok = IWL8000_UCODE_API_OK, \ | ||
| 185 | .ucode_api_min = IWL8000_UCODE_API_MIN \ | ||
| 186 | |||
| 187 | #define IWL_DEVICE_8265 \ | ||
| 188 | IWL_DEVICE_8000_COMMON, \ | ||
| 189 | .ucode_api_max = IWL8265_UCODE_API_MAX, \ | ||
| 190 | .ucode_api_ok = IWL8265_UCODE_API_OK, \ | ||
| 191 | .ucode_api_min = IWL8265_UCODE_API_MIN \ | ||
| 192 | |||
| 170 | const struct iwl_cfg iwl8260_2n_cfg = { | 193 | const struct iwl_cfg iwl8260_2n_cfg = { |
| 171 | .name = "Intel(R) Dual Band Wireless N 8260", | 194 | .name = "Intel(R) Dual Band Wireless N 8260", |
| 172 | .fw_name_pre = IWL8000_FW_PRE, | 195 | .fw_name_pre = IWL8000_FW_PRE, |
| 173 | IWL_DEVICE_8000, | 196 | IWL_DEVICE_8260, |
| 174 | .ht_params = &iwl8000_ht_params, | 197 | .ht_params = &iwl8000_ht_params, |
| 175 | .nvm_ver = IWL8000_NVM_VERSION, | 198 | .nvm_ver = IWL8000_NVM_VERSION, |
| 176 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 199 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
| @@ -179,7 +202,7 @@ const struct iwl_cfg iwl8260_2n_cfg = { | |||
| 179 | const struct iwl_cfg iwl8260_2ac_cfg = { | 202 | const struct iwl_cfg iwl8260_2ac_cfg = { |
| 180 | .name = "Intel(R) Dual Band Wireless AC 8260", | 203 | .name = "Intel(R) Dual Band Wireless AC 8260", |
| 181 | .fw_name_pre = IWL8000_FW_PRE, | 204 | .fw_name_pre = IWL8000_FW_PRE, |
| 182 | IWL_DEVICE_8000, | 205 | IWL_DEVICE_8260, |
| 183 | .ht_params = &iwl8000_ht_params, | 206 | .ht_params = &iwl8000_ht_params, |
| 184 | .nvm_ver = IWL8000_NVM_VERSION, | 207 | .nvm_ver = IWL8000_NVM_VERSION, |
| 185 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 208 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
| @@ -188,8 +211,8 @@ const struct iwl_cfg iwl8260_2ac_cfg = { | |||
| 188 | 211 | ||
| 189 | const struct iwl_cfg iwl8265_2ac_cfg = { | 212 | const struct iwl_cfg iwl8265_2ac_cfg = { |
| 190 | .name = "Intel(R) Dual Band Wireless AC 8265", | 213 | .name = "Intel(R) Dual Band Wireless AC 8265", |
| 191 | .fw_name_pre = IWL8000_FW_PRE, | 214 | .fw_name_pre = IWL8265_FW_PRE, |
| 192 | IWL_DEVICE_8000, | 215 | IWL_DEVICE_8265, |
| 193 | .ht_params = &iwl8000_ht_params, | 216 | .ht_params = &iwl8000_ht_params, |
| 194 | .nvm_ver = IWL8000_NVM_VERSION, | 217 | .nvm_ver = IWL8000_NVM_VERSION, |
| 195 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 218 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
| @@ -209,7 +232,7 @@ const struct iwl_cfg iwl4165_2ac_cfg = { | |||
| 209 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { | 232 | const struct iwl_cfg iwl8260_2ac_sdio_cfg = { |
| 210 | .name = "Intel(R) Dual Band Wireless-AC 8260", | 233 | .name = "Intel(R) Dual Band Wireless-AC 8260", |
| 211 | .fw_name_pre = IWL8000_FW_PRE, | 234 | .fw_name_pre = IWL8000_FW_PRE, |
| 212 | IWL_DEVICE_8000, | 235 | IWL_DEVICE_8260, |
| 213 | .ht_params = &iwl8000_ht_params, | 236 | .ht_params = &iwl8000_ht_params, |
| 214 | .nvm_ver = IWL8000_NVM_VERSION, | 237 | .nvm_ver = IWL8000_NVM_VERSION, |
| 215 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, | 238 | .nvm_calib_ver = IWL8000_TX_POWER_VERSION, |
| @@ -236,3 +259,4 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = { | |||
| 236 | }; | 259 | }; |
| 237 | 260 | ||
| 238 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); | 261 | MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK)); |
| 262 | MODULE_FIRMWARE(IWL8265_MODULE_FIRMWARE(IWL8265_UCODE_API_OK)); | ||
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index 7acb49075683..ab4c2a0470b2 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c | |||
| @@ -243,8 +243,10 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first) | |||
| 243 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { | 243 | if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) { |
| 244 | char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); | 244 | char rev_step = 'A' + CSR_HW_REV_STEP(drv->trans->hw_rev); |
| 245 | 245 | ||
| 246 | snprintf(drv->firmware_name, sizeof(drv->firmware_name), | 246 | if (rev_step != 'A') |
| 247 | "%s%c-%s.ucode", name_pre, rev_step, tag); | 247 | snprintf(drv->firmware_name, |
| 248 | sizeof(drv->firmware_name), "%s%c-%s.ucode", | ||
| 249 | name_pre, rev_step, tag); | ||
| 248 | } | 250 | } |
| 249 | 251 | ||
| 250 | IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", | 252 | IWL_DEBUG_INFO(drv, "attempting to load firmware %s'%s'\n", |
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 9a15642f80dd..ea1e177c2ea1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c | |||
| @@ -1298,6 +1298,10 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
| 1298 | return -EBUSY; | 1298 | return -EBUSY; |
| 1299 | } | 1299 | } |
| 1300 | 1300 | ||
| 1301 | /* we don't support "match all" in the firmware */ | ||
| 1302 | if (!req->n_match_sets) | ||
| 1303 | return -EOPNOTSUPP; | ||
| 1304 | |||
| 1301 | ret = iwl_mvm_check_running_scans(mvm, type); | 1305 | ret = iwl_mvm_check_running_scans(mvm, type); |
| 1302 | if (ret) | 1306 | if (ret) |
| 1303 | return ret; | 1307 | return ret; |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index cc3888e2700d..73c95594eabe 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h | |||
| @@ -490,6 +490,15 @@ static inline void iwl_enable_interrupts(struct iwl_trans *trans) | |||
| 490 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | 490 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | static inline void iwl_enable_fw_load_int(struct iwl_trans *trans) | ||
| 494 | { | ||
| 495 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 496 | |||
| 497 | IWL_DEBUG_ISR(trans, "Enabling FW load interrupt\n"); | ||
| 498 | trans_pcie->inta_mask = CSR_INT_BIT_FH_TX; | ||
| 499 | iwl_write32(trans, CSR_INT_MASK, trans_pcie->inta_mask); | ||
| 500 | } | ||
| 501 | |||
| 493 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) | 502 | static inline void iwl_enable_rfkill_int(struct iwl_trans *trans) |
| 494 | { | 503 | { |
| 495 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 504 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index ccafbd8cf4b3..152cf9ad9566 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c | |||
| @@ -1438,9 +1438,11 @@ irqreturn_t iwl_pcie_irq_handler(int irq, void *dev_id) | |||
| 1438 | inta & ~trans_pcie->inta_mask); | 1438 | inta & ~trans_pcie->inta_mask); |
| 1439 | } | 1439 | } |
| 1440 | 1440 | ||
| 1441 | /* Re-enable all interrupts */ | 1441 | /* we are loading the firmware, enable FH_TX interrupt only */ |
| 1442 | /* only Re-enable if disabled by irq */ | 1442 | if (handled & CSR_INT_BIT_FH_TX) |
| 1443 | if (test_bit(STATUS_INT_ENABLED, &trans->status)) | 1443 | iwl_enable_fw_load_int(trans); |
| 1444 | /* only Re-enable all interrupt if disabled by irq */ | ||
| 1445 | else if (test_bit(STATUS_INT_ENABLED, &trans->status)) | ||
| 1444 | iwl_enable_interrupts(trans); | 1446 | iwl_enable_interrupts(trans); |
| 1445 | /* Re-enable RF_KILL if it occurred */ | 1447 | /* Re-enable RF_KILL if it occurred */ |
| 1446 | else if (handled & CSR_INT_BIT_RF_KILL) | 1448 | else if (handled & CSR_INT_BIT_RF_KILL) |
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index d60a467a983c..5a854c609477 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c | |||
| @@ -1021,82 +1021,6 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans, | |||
| 1021 | &first_ucode_section); | 1021 | &first_ucode_section); |
| 1022 | } | 1022 | } |
| 1023 | 1023 | ||
| 1024 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | ||
| 1025 | const struct fw_img *fw, bool run_in_rfkill) | ||
| 1026 | { | ||
| 1027 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 1028 | bool hw_rfkill; | ||
| 1029 | int ret; | ||
| 1030 | |||
| 1031 | mutex_lock(&trans_pcie->mutex); | ||
| 1032 | |||
| 1033 | /* Someone called stop_device, don't try to start_fw */ | ||
| 1034 | if (trans_pcie->is_down) { | ||
| 1035 | IWL_WARN(trans, | ||
| 1036 | "Can't start_fw since the HW hasn't been started\n"); | ||
| 1037 | ret = EIO; | ||
| 1038 | goto out; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | /* This may fail if AMT took ownership of the device */ | ||
| 1042 | if (iwl_pcie_prepare_card_hw(trans)) { | ||
| 1043 | IWL_WARN(trans, "Exit HW not ready\n"); | ||
| 1044 | ret = -EIO; | ||
| 1045 | goto out; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | iwl_enable_rfkill_int(trans); | ||
| 1049 | |||
| 1050 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
| 1051 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
| 1052 | if (hw_rfkill) | ||
| 1053 | set_bit(STATUS_RFKILL, &trans->status); | ||
| 1054 | else | ||
| 1055 | clear_bit(STATUS_RFKILL, &trans->status); | ||
| 1056 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
| 1057 | if (hw_rfkill && !run_in_rfkill) { | ||
| 1058 | ret = -ERFKILL; | ||
| 1059 | goto out; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
| 1063 | |||
| 1064 | ret = iwl_pcie_nic_init(trans); | ||
| 1065 | if (ret) { | ||
| 1066 | IWL_ERR(trans, "Unable to init nic\n"); | ||
| 1067 | goto out; | ||
| 1068 | } | ||
| 1069 | |||
| 1070 | /* make sure rfkill handshake bits are cleared */ | ||
| 1071 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 1072 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, | ||
| 1073 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
| 1074 | |||
| 1075 | /* clear (again), then enable host interrupts */ | ||
| 1076 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
| 1077 | iwl_enable_interrupts(trans); | ||
| 1078 | |||
| 1079 | /* really make sure rfkill handshake bits are cleared */ | ||
| 1080 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 1081 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 1082 | |||
| 1083 | /* Load the given image to the HW */ | ||
| 1084 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
| 1085 | ret = iwl_pcie_load_given_ucode_8000(trans, fw); | ||
| 1086 | else | ||
| 1087 | ret = iwl_pcie_load_given_ucode(trans, fw); | ||
| 1088 | |||
| 1089 | out: | ||
| 1090 | mutex_unlock(&trans_pcie->mutex); | ||
| 1091 | return ret; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) | ||
| 1095 | { | ||
| 1096 | iwl_pcie_reset_ict(trans); | ||
| 1097 | iwl_pcie_tx_start(trans, scd_addr); | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | 1024 | static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) |
| 1101 | { | 1025 | { |
| 1102 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1026 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| @@ -1127,7 +1051,8 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
| 1127 | * already dead. | 1051 | * already dead. |
| 1128 | */ | 1052 | */ |
| 1129 | if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { | 1053 | if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { |
| 1130 | IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); | 1054 | IWL_DEBUG_INFO(trans, |
| 1055 | "DEVICE_ENABLED bit was set and is now cleared\n"); | ||
| 1131 | iwl_pcie_tx_stop(trans); | 1056 | iwl_pcie_tx_stop(trans); |
| 1132 | iwl_pcie_rx_stop(trans); | 1057 | iwl_pcie_rx_stop(trans); |
| 1133 | 1058 | ||
| @@ -1161,7 +1086,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
| 1161 | iwl_disable_interrupts(trans); | 1086 | iwl_disable_interrupts(trans); |
| 1162 | spin_unlock(&trans_pcie->irq_lock); | 1087 | spin_unlock(&trans_pcie->irq_lock); |
| 1163 | 1088 | ||
| 1164 | |||
| 1165 | /* clear all status bits */ | 1089 | /* clear all status bits */ |
| 1166 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | 1090 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
| 1167 | clear_bit(STATUS_INT_ENABLED, &trans->status); | 1091 | clear_bit(STATUS_INT_ENABLED, &trans->status); |
| @@ -1194,10 +1118,116 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | |||
| 1194 | if (hw_rfkill != was_hw_rfkill) | 1118 | if (hw_rfkill != was_hw_rfkill) |
| 1195 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | 1119 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); |
| 1196 | 1120 | ||
| 1197 | /* re-take ownership to prevent other users from stealing the deivce */ | 1121 | /* re-take ownership to prevent other users from stealing the device */ |
| 1198 | iwl_pcie_prepare_card_hw(trans); | 1122 | iwl_pcie_prepare_card_hw(trans); |
| 1199 | } | 1123 | } |
| 1200 | 1124 | ||
| 1125 | static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, | ||
| 1126 | const struct fw_img *fw, bool run_in_rfkill) | ||
| 1127 | { | ||
| 1128 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | ||
| 1129 | bool hw_rfkill; | ||
| 1130 | int ret; | ||
| 1131 | |||
| 1132 | /* This may fail if AMT took ownership of the device */ | ||
| 1133 | if (iwl_pcie_prepare_card_hw(trans)) { | ||
| 1134 | IWL_WARN(trans, "Exit HW not ready\n"); | ||
| 1135 | ret = -EIO; | ||
| 1136 | goto out; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | iwl_enable_rfkill_int(trans); | ||
| 1140 | |||
| 1141 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
| 1142 | |||
| 1143 | /* | ||
| 1144 | * We enabled the RF-Kill interrupt and the handler may very | ||
| 1145 | * well be running. Disable the interrupts to make sure no other | ||
| 1146 | * interrupt can be fired. | ||
| 1147 | */ | ||
| 1148 | iwl_disable_interrupts(trans); | ||
| 1149 | |||
| 1150 | /* Make sure it finished running */ | ||
| 1151 | synchronize_irq(trans_pcie->pci_dev->irq); | ||
| 1152 | |||
| 1153 | mutex_lock(&trans_pcie->mutex); | ||
| 1154 | |||
| 1155 | /* If platform's RF_KILL switch is NOT set to KILL */ | ||
| 1156 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
| 1157 | if (hw_rfkill) | ||
| 1158 | set_bit(STATUS_RFKILL, &trans->status); | ||
| 1159 | else | ||
| 1160 | clear_bit(STATUS_RFKILL, &trans->status); | ||
| 1161 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
| 1162 | if (hw_rfkill && !run_in_rfkill) { | ||
| 1163 | ret = -ERFKILL; | ||
| 1164 | goto out; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | /* Someone called stop_device, don't try to start_fw */ | ||
| 1168 | if (trans_pcie->is_down) { | ||
| 1169 | IWL_WARN(trans, | ||
| 1170 | "Can't start_fw since the HW hasn't been started\n"); | ||
| 1171 | ret = -EIO; | ||
| 1172 | goto out; | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | /* make sure rfkill handshake bits are cleared */ | ||
| 1176 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 1177 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, | ||
| 1178 | CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); | ||
| 1179 | |||
| 1180 | /* clear (again), then enable host interrupts */ | ||
| 1181 | iwl_write32(trans, CSR_INT, 0xFFFFFFFF); | ||
| 1182 | |||
| 1183 | ret = iwl_pcie_nic_init(trans); | ||
| 1184 | if (ret) { | ||
| 1185 | IWL_ERR(trans, "Unable to init nic\n"); | ||
| 1186 | goto out; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | /* | ||
| 1190 | * Now, we load the firmware and don't want to be interrupted, even | ||
| 1191 | * by the RF-Kill interrupt (hence mask all the interrupt besides the | ||
| 1192 | * FH_TX interrupt which is needed to load the firmware). If the | ||
| 1193 | * RF-Kill switch is toggled, we will find out after having loaded | ||
| 1194 | * the firmware and return the proper value to the caller. | ||
| 1195 | */ | ||
| 1196 | iwl_enable_fw_load_int(trans); | ||
| 1197 | |||
| 1198 | /* really make sure rfkill handshake bits are cleared */ | ||
| 1199 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 1200 | iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); | ||
| 1201 | |||
| 1202 | /* Load the given image to the HW */ | ||
| 1203 | if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) | ||
| 1204 | ret = iwl_pcie_load_given_ucode_8000(trans, fw); | ||
| 1205 | else | ||
| 1206 | ret = iwl_pcie_load_given_ucode(trans, fw); | ||
| 1207 | iwl_enable_interrupts(trans); | ||
| 1208 | |||
| 1209 | /* re-check RF-Kill state since we may have missed the interrupt */ | ||
| 1210 | hw_rfkill = iwl_is_rfkill_set(trans); | ||
| 1211 | if (hw_rfkill) | ||
| 1212 | set_bit(STATUS_RFKILL, &trans->status); | ||
| 1213 | else | ||
| 1214 | clear_bit(STATUS_RFKILL, &trans->status); | ||
| 1215 | |||
| 1216 | iwl_trans_pcie_rf_kill(trans, hw_rfkill); | ||
| 1217 | if (hw_rfkill && !run_in_rfkill) | ||
| 1218 | ret = -ERFKILL; | ||
| 1219 | |||
| 1220 | out: | ||
| 1221 | mutex_unlock(&trans_pcie->mutex); | ||
| 1222 | return ret; | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr) | ||
| 1226 | { | ||
| 1227 | iwl_pcie_reset_ict(trans); | ||
| 1228 | iwl_pcie_tx_start(trans, scd_addr); | ||
| 1229 | } | ||
| 1230 | |||
| 1201 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) | 1231 | static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power) |
| 1202 | { | 1232 | { |
| 1203 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 1233 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
