diff options
-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 |
3 files changed, 123 insertions, 82 deletions
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..55030729c7d9 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); |