summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-06 13:30:49 -0800
committerJohn W. Linville <linville@tuxdriver.com>2012-03-07 13:51:52 -0500
commit0e781842cb25ed3a9d0a91bdf05c0717150c9343 (patch)
tree5a19056c6bc39ccd62521fad50219837a076646e
parent6c1011e1918be17f7f8ccca5442cd517f9c29d17 (diff)
downloadblackbird-op-linux-0e781842cb25ed3a9d0a91bdf05c0717150c9343.tar.gz
blackbird-op-linux-0e781842cb25ed3a9d0a91bdf05c0717150c9343.zip
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: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-op-mode.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-shared.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c7
5 files changed, 21 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 276570025e52..7c3165ed85bc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1403,6 +1403,16 @@ static void iwl_op_mode_dvm_stop(struct iwl_op_mode *op_mode)
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 = {
.start = iwl_op_mode_dvm_start,
.stop = iwl_op_mode_dvm_stop,
@@ -1412,6 +1422,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
.hw_rf_kill = iwl_set_hw_rfkill_state,
.free_skb = iwl_free_skb,
.nic_error = iwl_nic_error,
+ .cmd_queue_full = iwl_cmd_queue_full,
};
/*****************************************************************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index 1f62d6d1fc65..ec3a90c42efb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -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_nic_error(struct iwl_op_mode *op_mode);
+bool iwl_check_for_ct_kill(struct iwl_priv *priv);
+
/* MAC80211 */
struct ieee80211_hw *iwl_alloc_all(void);
int iwlagn_mac_setup_register(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index 55b8b27a9560..a4a4907803ca 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -122,6 +122,7 @@ struct iwl_fw;
* there are Tx packets pending in the transport layer.
* 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 *(*start)(struct iwl_trans *trans,
@@ -134,6 +135,7 @@ struct iwl_op_mode_ops {
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 (*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)
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
******************************************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-shared.h b/drivers/net/wireless/iwlwifi/iwl-shared.h
index 5e12b504aacf..8ee528479c95 100644
--- a/drivers/net/wireless/iwlwifi/iwl-shared.h
+++ b/drivers/net/wireless/iwlwifi/iwl-shared.h
@@ -461,8 +461,6 @@ enum iwl_rxon_context_id {
int iwlagn_hw_valid_rtc_data_addr(u32 addr);
void iwl_nic_config(struct iwl_priv *priv);
const char *get_cmd_string(u8 cmd);
-bool iwl_check_for_ct_kill(struct iwl_priv *priv);
-
/* notification wait support */
void iwl_abort_notification_waits(struct iwl_shared *shrd);
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
index 844606b436ed..7feeb2d52146 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c
@@ -671,7 +671,6 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
dma_addr_t phys_addr;
u32 idx;
u16 copy_size, cmd_size;
- bool is_ct_kill = false;
bool had_nocopy = false;
int i;
u8 *cmd_dest;
@@ -727,11 +726,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
spin_unlock_bh(&txq->lock);
IWL_ERR(trans, "No space in command queue\n");
- is_ct_kill = iwl_check_for_ct_kill(priv(trans));
- if (!is_ct_kill) {
- IWL_ERR(trans, "Restarting adapter queue is full\n");
- iwl_op_mode_nic_error(trans->op_mode);
- }
+ iwl_op_mode_cmd_queue_full(trans->op_mode);
return -ENOSPC;
}
OpenPOWER on IntegriCloud