Commit 0e781842 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

iwlwifi: virtualize command queue full behaviour

When the command queue is full, the transport
will return -ENOSPC, but the reaction to that
depends on the op_mode. Virtualize that, the
DVM op_mode checks for CT-kill and restarts
the hardware otherwise.

We may be able to get rid of this callback by
putting the behaviour check into the wrapper
but that needs more careful evaluation.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 6c1011e1
...@@ -1403,6 +1403,16 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode) ...@@ -1403,6 +1403,16 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
ieee80211_free_hw(priv->hw); ieee80211_free_hw(priv->hw);
} }
static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
{
struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
if (!iwl_check_for_ct_kill(priv)) {
IWL_ERR(priv, "Restarting adapter queue is full\n");
iwl_nic_error(op_mode);
}
}
const struct iwl_op_mode_ops iwl_dvm_ops = { const struct iwl_op_mode_ops iwl_dvm_ops = {
.start = iwl_op_mode_dvm_start, .start = iwl_op_mode_dvm_start,
.stop = iwl_op_mode_dvm_stop, .stop = iwl_op_mode_dvm_stop,
...@@ -1412,6 +1422,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = { ...@@ -1412,6 +1422,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
.hw_rf_kill = iwl_set_hw_rfkill_state, .hw_rf_kill = iwl_set_hw_rfkill_state,
.free_skb = iwl_free_skb, .free_skb = iwl_free_skb,
.nic_error = iwl_nic_error, .nic_error = iwl_nic_error,
.cmd_queue_full = iwl_cmd_queue_full,
}; };
/***************************************************************************** /*****************************************************************************
......
...@@ -90,6 +90,8 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state); ...@@ -90,6 +90,8 @@ void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state);
void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac); void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
void iwl_nic_error(struct iwl_op_mode *op_mode); void iwl_nic_error(struct iwl_op_mode *op_mode);
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
/* MAC80211 */ /* MAC80211 */
struct ieee80211_hw *iwl_alloc_all(void); struct ieee80211_hw *iwl_alloc_all(void);
int iwlagn_mac_setup_register(struct iwl_priv *priv, int iwlagn_mac_setup_register(struct iwl_priv *priv,
......
...@@ -122,6 +122,7 @@ struct iwl_fw; ...@@ -122,6 +122,7 @@ struct iwl_fw;
* there are Tx packets pending in the transport layer. * there are Tx packets pending in the transport layer.
* Must be atomic * Must be atomic
* @nic_error: error notification. Must be atomic * @nic_error: error notification. Must be atomic
* @cmd_queue_full: Called when the command queue gets full. Must be atomic.
*/ */
struct iwl_op_mode_ops { struct iwl_op_mode_ops {
struct iwl_op_mode *(*start)(struct iwl_trans *trans, struct iwl_op_mode *(*start)(struct iwl_trans *trans,
...@@ -134,6 +135,7 @@ struct iwl_op_mode_ops { ...@@ -134,6 +135,7 @@ struct iwl_op_mode_ops {
void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
void (*nic_error)(struct iwl_op_mode *op_mode); void (*nic_error)(struct iwl_op_mode *op_mode);
void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
}; };
/** /**
...@@ -192,6 +194,11 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode) ...@@ -192,6 +194,11 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode)
op_mode->ops->nic_error(op_mode); op_mode->ops->nic_error(op_mode);
} }
static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
{
op_mode->ops->cmd_queue_full(op_mode);
}
/***************************************************** /*****************************************************
* Op mode layers implementations * Op mode layers implementations
******************************************************/ ******************************************************/
......
...@@ -461,8 +461,6 @@ enum iwl_rxon_context_id { ...@@ -461,8 +461,6 @@ enum iwl_rxon_context_id {
int iwlagn_hw_valid_rtc_data_addr(u32 addr); int iwlagn_hw_valid_rtc_data_addr(u32 addr);
void iwl_nic_config(struct iwl_priv *priv); void iwl_nic_config(struct iwl_priv *priv);
const char *get_cmd_string(u8 cmd); const char *get_cmd_string(u8 cmd);
bool iwl_check_for_ct_kill(struct iwl_priv *priv);
/* notification wait support */ /* notification wait support */
void iwl_abort_notification_waits(struct iwl_shared *shrd); void iwl_abort_notification_waits(struct iwl_shared *shrd);
......
...@@ -671,7 +671,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) ...@@ -671,7 +671,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
dma_addr_t phys_addr; dma_addr_t phys_addr;
u32 idx; u32 idx;
u16 copy_size, cmd_size; u16 copy_size, cmd_size;
bool is_ct_kill = false;
bool had_nocopy = false; bool had_nocopy = false;
int i; int i;
u8 *cmd_dest; u8 *cmd_dest;
...@@ -727,11 +726,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) ...@@ -727,11 +726,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
spin_unlock_bh(&txq->lock); spin_unlock_bh(&txq->lock);
IWL_ERR(trans, "No space in command queue\n"); IWL_ERR(trans, "No space in command queue\n");
is_ct_kill = iwl_check_for_ct_kill(priv(trans)); iwl_op_mode_cmd_queue_full(trans->op_mode);
if (!is_ct_kill) {
IWL_ERR(trans, "Restarting adapter queue is full\n");
iwl_op_mode_nic_error(trans->op_mode);
}
return -ENOSPC; return -ENOSPC;
} }
......
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