Commit 218733cf authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Wey-Yi Guy

iwlwifi: provide proper API to disable all interrupts

Since the op_mode may go away, the transport needs to be able to
be told not to update the op_mode at all (even for RF kill).
Provide this API and use it in the proper places.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
parent d23f78e6
...@@ -1633,7 +1633,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, ...@@ -1633,7 +1633,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
goto out_free_traffic_mem; goto out_free_traffic_mem;
} }
/* Reset chip to save power until we load uCode during "up". */ /* 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)) if (iwl_eeprom_check_version(priv))
goto out_free_eeprom; goto out_free_eeprom;
...@@ -1786,6 +1786,7 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) ...@@ -1786,6 +1786,7 @@ void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
dev_kfree_skb(priv->beacon_skb); dev_kfree_skb(priv->beacon_skb);
iwl_trans_stop_hw(priv->trans, true);
ieee80211_free_hw(priv->hw); ieee80211_free_hw(priv->hw);
} }
......
...@@ -355,7 +355,7 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw) ...@@ -355,7 +355,7 @@ void iwlagn_mac_stop(struct ieee80211_hw *hw)
* even if interface is down, trans->down will leave the RF * even if interface is down, trans->down will leave the RF
* kill interrupt enabled * kill interrupt enabled
*/ */
iwl_trans_stop_hw(priv->trans); iwl_trans_stop_hw(priv->trans, false);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
......
...@@ -1210,6 +1210,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) ...@@ -1210,6 +1210,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans)
iwl_disable_interrupts(trans); iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags); spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
iwl_enable_rfkill_int(trans);
/* wait to make sure we flush pending tasklet*/ /* wait to make sure we flush pending tasklet*/
synchronize_irq(trans_pcie->irq); synchronize_irq(trans_pcie->irq);
tasklet_kill(&trans_pcie->irq_tasklet); tasklet_kill(&trans_pcie->irq_tasklet);
...@@ -1436,24 +1438,37 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans) ...@@ -1436,24 +1438,37 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
return err; 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; bool hw_rfkill;
unsigned long flags;
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
iwl_apm_stop(trans); iwl_apm_stop(trans);
spin_lock_irqsave(&trans_pcie->irq_lock, flags);
iwl_disable_interrupts(trans);
spin_unlock_irqrestore(&trans_pcie->irq_lock, flags);
iwl_write32(trans, CSR_INT, 0xFFFFFFFF); iwl_write32(trans, CSR_INT, 0xFFFFFFFF);
/* Even if we stop the HW, we still want the RF kill interrupt */ if (!op_mode_leaving) {
/*
* Even if we stop the HW, we still want the RF kill
* interrupt
*/
iwl_enable_rfkill_int(trans); iwl_enable_rfkill_int(trans);
/* /*
* Check again since the RF kill state may have changed while all the * Check again since the RF kill state may have changed while
* interrupts were disabled, in this case we couldn't receive the * all the interrupts were disabled, in this case we couldn't
* RF kill interrupt and update the state in the op_mode. * receive the RF kill interrupt and update the state in the
* op_mode.
*/ */
hw_rfkill = iwl_is_rfkill_set(trans); hw_rfkill = iwl_is_rfkill_set(trans);
iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill); 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, static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
......
...@@ -335,7 +335,8 @@ struct iwl_trans; ...@@ -335,7 +335,8 @@ struct iwl_trans;
* @start_hw: starts the HW- from that point on, the HW can send interrupts * @start_hw: starts the HW- from that point on, the HW can send interrupts
* May sleep * May sleep
* @stop_hw: stops the HW- from that point on, the HW will be in low power but * @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 * May sleep
* @start_fw: allocates and inits all the resources for the transport * @start_fw: allocates and inits all the resources for the transport
* layer. Also kick a fw image. * layer. Also kick a fw image.
...@@ -379,7 +380,7 @@ struct iwl_trans; ...@@ -379,7 +380,7 @@ struct iwl_trans;
struct iwl_trans_ops { struct iwl_trans_ops {
int (*start_hw)(struct iwl_trans *iwl_trans); 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); int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw);
void (*fw_alive)(struct iwl_trans *trans); void (*fw_alive)(struct iwl_trans *trans);
void (*stop_device)(struct iwl_trans *trans); void (*stop_device)(struct iwl_trans *trans);
...@@ -478,11 +479,12 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans) ...@@ -478,11 +479,12 @@ static inline int iwl_trans_start_hw(struct iwl_trans *trans)
return trans->ops->start_hw(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(); might_sleep();
trans->ops->stop_hw(trans); trans->ops->stop_hw(trans, op_mode_leaving);
trans->state = IWL_TRANS_NO_FW; trans->state = IWL_TRANS_NO_FW;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment