|
@@ -1021,82 +1021,6 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
|
|
|
&first_ucode_section);
|
|
|
}
|
|
|
|
|
|
-static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
|
|
- const struct fw_img *fw, bool run_in_rfkill)
|
|
|
-{
|
|
|
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
|
- bool hw_rfkill;
|
|
|
- int ret;
|
|
|
-
|
|
|
- mutex_lock(&trans_pcie->mutex);
|
|
|
-
|
|
|
- /* Someone called stop_device, don't try to start_fw */
|
|
|
- if (trans_pcie->is_down) {
|
|
|
- IWL_WARN(trans,
|
|
|
- "Can't start_fw since the HW hasn't been started\n");
|
|
|
- ret = EIO;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- /* This may fail if AMT took ownership of the device */
|
|
|
- if (iwl_pcie_prepare_card_hw(trans)) {
|
|
|
- IWL_WARN(trans, "Exit HW not ready\n");
|
|
|
- ret = -EIO;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- iwl_enable_rfkill_int(trans);
|
|
|
-
|
|
|
- /* If platform's RF_KILL switch is NOT set to KILL */
|
|
|
- hw_rfkill = iwl_is_rfkill_set(trans);
|
|
|
- if (hw_rfkill)
|
|
|
- set_bit(STATUS_RFKILL, &trans->status);
|
|
|
- else
|
|
|
- clear_bit(STATUS_RFKILL, &trans->status);
|
|
|
- iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
|
|
- if (hw_rfkill && !run_in_rfkill) {
|
|
|
- ret = -ERFKILL;
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
|
|
-
|
|
|
- ret = iwl_pcie_nic_init(trans);
|
|
|
- if (ret) {
|
|
|
- IWL_ERR(trans, "Unable to init nic\n");
|
|
|
- goto out;
|
|
|
- }
|
|
|
-
|
|
|
- /* make sure rfkill handshake bits are cleared */
|
|
|
- iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
|
|
- iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
|
|
|
- CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
|
|
-
|
|
|
- /* clear (again), then enable host interrupts */
|
|
|
- iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
|
|
- iwl_enable_interrupts(trans);
|
|
|
-
|
|
|
- /* really make sure rfkill handshake bits are cleared */
|
|
|
- iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
|
|
- iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
|
|
-
|
|
|
- /* Load the given image to the HW */
|
|
|
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
|
|
- ret = iwl_pcie_load_given_ucode_8000(trans, fw);
|
|
|
- else
|
|
|
- ret = iwl_pcie_load_given_ucode(trans, fw);
|
|
|
-
|
|
|
-out:
|
|
|
- mutex_unlock(&trans_pcie->mutex);
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
|
|
-{
|
|
|
- iwl_pcie_reset_ict(trans);
|
|
|
- iwl_pcie_tx_start(trans, scd_addr);
|
|
|
-}
|
|
|
-
|
|
|
static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
|
|
{
|
|
|
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)
|
|
|
* already dead.
|
|
|
*/
|
|
|
if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
|
|
|
- IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
|
|
|
+ IWL_DEBUG_INFO(trans,
|
|
|
+ "DEVICE_ENABLED bit was set and is now cleared\n");
|
|
|
iwl_pcie_tx_stop(trans);
|
|
|
iwl_pcie_rx_stop(trans);
|
|
|
|
|
@@ -1161,7 +1086,6 @@ static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
|
|
iwl_disable_interrupts(trans);
|
|
|
spin_unlock(&trans_pcie->irq_lock);
|
|
|
|
|
|
-
|
|
|
/* clear all status bits */
|
|
|
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
|
|
|
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)
|
|
|
if (hw_rfkill != was_hw_rfkill)
|
|
|
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
|
|
|
|
|
- /* re-take ownership to prevent other users from stealing the deivce */
|
|
|
+ /* re-take ownership to prevent other users from stealing the device */
|
|
|
iwl_pcie_prepare_card_hw(trans);
|
|
|
}
|
|
|
|
|
|
+static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
|
|
|
+ const struct fw_img *fw, bool run_in_rfkill)
|
|
|
+{
|
|
|
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
|
|
+ bool hw_rfkill;
|
|
|
+ int ret;
|
|
|
+
|
|
|
+ /* This may fail if AMT took ownership of the device */
|
|
|
+ if (iwl_pcie_prepare_card_hw(trans)) {
|
|
|
+ IWL_WARN(trans, "Exit HW not ready\n");
|
|
|
+ ret = -EIO;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ iwl_enable_rfkill_int(trans);
|
|
|
+
|
|
|
+ iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * We enabled the RF-Kill interrupt and the handler may very
|
|
|
+ * well be running. Disable the interrupts to make sure no other
|
|
|
+ * interrupt can be fired.
|
|
|
+ */
|
|
|
+ iwl_disable_interrupts(trans);
|
|
|
+
|
|
|
+ /* Make sure it finished running */
|
|
|
+ synchronize_irq(trans_pcie->pci_dev->irq);
|
|
|
+
|
|
|
+ mutex_lock(&trans_pcie->mutex);
|
|
|
+
|
|
|
+ /* If platform's RF_KILL switch is NOT set to KILL */
|
|
|
+ hw_rfkill = iwl_is_rfkill_set(trans);
|
|
|
+ if (hw_rfkill)
|
|
|
+ set_bit(STATUS_RFKILL, &trans->status);
|
|
|
+ else
|
|
|
+ clear_bit(STATUS_RFKILL, &trans->status);
|
|
|
+ iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
|
|
+ if (hw_rfkill && !run_in_rfkill) {
|
|
|
+ ret = -ERFKILL;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Someone called stop_device, don't try to start_fw */
|
|
|
+ if (trans_pcie->is_down) {
|
|
|
+ IWL_WARN(trans,
|
|
|
+ "Can't start_fw since the HW hasn't been started\n");
|
|
|
+ ret = -EIO;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* make sure rfkill handshake bits are cleared */
|
|
|
+ iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
|
|
+ iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR,
|
|
|
+ CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
|
|
|
+
|
|
|
+ /* clear (again), then enable host interrupts */
|
|
|
+ iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
|
|
|
+
|
|
|
+ ret = iwl_pcie_nic_init(trans);
|
|
|
+ if (ret) {
|
|
|
+ IWL_ERR(trans, "Unable to init nic\n");
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Now, we load the firmware and don't want to be interrupted, even
|
|
|
+ * by the RF-Kill interrupt (hence mask all the interrupt besides the
|
|
|
+ * FH_TX interrupt which is needed to load the firmware). If the
|
|
|
+ * RF-Kill switch is toggled, we will find out after having loaded
|
|
|
+ * the firmware and return the proper value to the caller.
|
|
|
+ */
|
|
|
+ iwl_enable_fw_load_int(trans);
|
|
|
+
|
|
|
+ /* really make sure rfkill handshake bits are cleared */
|
|
|
+ iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
|
|
+ iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
|
|
|
+
|
|
|
+ /* Load the given image to the HW */
|
|
|
+ if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
|
|
|
+ ret = iwl_pcie_load_given_ucode_8000(trans, fw);
|
|
|
+ else
|
|
|
+ ret = iwl_pcie_load_given_ucode(trans, fw);
|
|
|
+ iwl_enable_interrupts(trans);
|
|
|
+
|
|
|
+ /* re-check RF-Kill state since we may have missed the interrupt */
|
|
|
+ hw_rfkill = iwl_is_rfkill_set(trans);
|
|
|
+ if (hw_rfkill)
|
|
|
+ set_bit(STATUS_RFKILL, &trans->status);
|
|
|
+ else
|
|
|
+ clear_bit(STATUS_RFKILL, &trans->status);
|
|
|
+
|
|
|
+ iwl_trans_pcie_rf_kill(trans, hw_rfkill);
|
|
|
+ if (hw_rfkill && !run_in_rfkill)
|
|
|
+ ret = -ERFKILL;
|
|
|
+
|
|
|
+out:
|
|
|
+ mutex_unlock(&trans_pcie->mutex);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
|
|
|
+{
|
|
|
+ iwl_pcie_reset_ict(trans);
|
|
|
+ iwl_pcie_tx_start(trans, scd_addr);
|
|
|
+}
|
|
|
+
|
|
|
static void iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
|
|
|
{
|
|
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|