goto out_free_traffic_mem;
}
/* Reset chip to save power until we load uCode during "up". */
- iwl_trans_stop_hw(priv->trans);
+ iwl_trans_stop_hw(priv->trans, false);
if (iwl_eeprom_check_version(priv))
goto out_free_eeprom;
dev_kfree_skb(priv->beacon_skb);
+ iwl_trans_stop_hw(priv->trans, true);
ieee80211_free_hw(priv->hw);
}
iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
+ iwl_enable_rfkill_int(trans);
+
/* wait to make sure we flush pending tasklet*/
synchronize_irq(trans_pcie->irq);
tasklet_kill(&trans_pcie->irq_tasklet);
return err;
}
-static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans)
+static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
+ bool op_mode_leaving)
{
bool hw_rfkill;
+ unsigned long flags;
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
iwl_apm_stop(trans);
- iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
+ spin_lock_irqsave(&trans_pcie->irq_lock, flags);
+ iwl_disable_interrupts(trans);
+ spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
- /* Even if we stop the HW, we still want the RF kill interrupt */
- iwl_enable_rfkill_int(trans);
+ iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
- /*
- * Check again since the RF kill state may have changed while all the
- * interrupts were disabled, in this case we couldn't receive the
- * RF kill interrupt and update the state in the op_mode.
- */
- hw_rfkill = iwl_is_rfkill_set(trans);
- iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+ if (!op_mode_leaving) {
+ /*
+ * Even if we stop the HW, we still want the RF kill
+ * interrupt
+ */
+ iwl_enable_rfkill_int(trans);
+
+ /*
+ * Check again since the RF kill state may have changed while
+ * all the interrupts were disabled, in this case we couldn't
+ * receive the RF kill interrupt and update the state in the
+ * op_mode.
+ */
+ hw_rfkill = iwl_is_rfkill_set(trans);
+ iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
+ }
}
static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
* @start_hw: starts the HW- from that point on, the HW can send interrupts
* May sleep
* @stop_hw: stops the HW- from that point on, the HW will be in low power but
- * will still issue interrupt if the HW RF kill is triggered.
+ * will still issue interrupt if the HW RF kill is triggered unless
+ * op_mode_leaving is true.
* May sleep
* @start_fw: allocates and inits all the resources for the transport
* layer. Also kick a fw image.
struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans);
- void (*stop_hw)(struct iwl_trans *iwl_trans);
+ void (*stop_hw)(struct iwl_trans *iwl_trans, bool op_mode_leaving);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
void (*fw_alive)(struct iwl_trans *trans);
void (*stop_device)(struct iwl_trans *trans);
return trans->ops->start_hw(trans);
}
-static inline void iwl_trans_stop_hw(struct iwl_trans *trans)
+static inline void iwl_trans_stop_hw(struct iwl_trans *trans,
+ bool op_mode_leaving)
{
might_sleep();
- trans->ops->stop_hw(trans);
+ trans->ops->stop_hw(trans, op_mode_leaving);
trans->state = IWL_TRANS_NO_FW;
}