aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-03-06 16:30:49 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-07 13:51:52 -0500
commit0e781842cb25ed3a9d0a91bdf05c0717150c9343 (patch)
tree5a19056c6bc39ccd62521fad50219837a076646e /drivers/net/wireless
parent6c1011e1918be17f7f8ccca5442cd517f9c29d17 (diff)
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>
Diffstat (limited to 'drivers/net/wireless')
-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)
1403 ieee80211_free_hw(priv->hw); 1403 ieee80211_free_hw(priv->hw);
1404} 1404}
1405 1405
1406static void iwl_cmd_queue_full(struct iwl_op_mode *op_mode)
1407{
1408 struct iwl_priv *priv = IWL_OP_MODE_GET_DVM(op_mode);
1409
1410 if (!iwl_check_for_ct_kill(priv)) {
1411 IWL_ERR(priv, "Restarting adapter queue is full\n");
1412 iwl_nic_error(op_mode);
1413 }
1414}
1415
1406const struct iwl_op_mode_ops iwl_dvm_ops = { 1416const struct iwl_op_mode_ops iwl_dvm_ops = {
1407 .start = iwl_op_mode_dvm_start, 1417 .start = iwl_op_mode_dvm_start,
1408 .stop = iwl_op_mode_dvm_stop, 1418 .stop = iwl_op_mode_dvm_stop,
@@ -1412,6 +1422,7 @@ const struct iwl_op_mode_ops iwl_dvm_ops = {
1412 .hw_rf_kill = iwl_set_hw_rfkill_state, 1422 .hw_rf_kill = iwl_set_hw_rfkill_state,
1413 .free_skb = iwl_free_skb, 1423 .free_skb = iwl_free_skb,
1414 .nic_error = iwl_nic_error, 1424 .nic_error = iwl_nic_error,
1425 .cmd_queue_full = iwl_cmd_queue_full,
1415}; 1426};
1416 1427
1417/***************************************************************************** 1428/*****************************************************************************
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);
90void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac); 90void iwl_stop_sw_queue(struct iwl_op_mode *op_mode, u8 ac);
91void iwl_nic_error(struct iwl_op_mode *op_mode); 91void iwl_nic_error(struct iwl_op_mode *op_mode);
92 92
93bool iwl_check_for_ct_kill(struct iwl_priv *priv);
94
93/* MAC80211 */ 95/* MAC80211 */
94struct ieee80211_hw *iwl_alloc_all(void); 96struct ieee80211_hw *iwl_alloc_all(void);
95int iwlagn_mac_setup_register(struct iwl_priv *priv, 97int 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;
122 * there are Tx packets pending in the transport layer. 122 * there are Tx packets pending in the transport layer.
123 * Must be atomic 123 * Must be atomic
124 * @nic_error: error notification. Must be atomic 124 * @nic_error: error notification. Must be atomic
125 * @cmd_queue_full: Called when the command queue gets full. Must be atomic.
125 */ 126 */
126struct iwl_op_mode_ops { 127struct iwl_op_mode_ops {
127 struct iwl_op_mode *(*start)(struct iwl_trans *trans, 128 struct iwl_op_mode *(*start)(struct iwl_trans *trans,
@@ -134,6 +135,7 @@ struct iwl_op_mode_ops {
134 void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state); 135 void (*hw_rf_kill)(struct iwl_op_mode *op_mode, bool state);
135 void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb); 136 void (*free_skb)(struct iwl_op_mode *op_mode, struct sk_buff *skb);
136 void (*nic_error)(struct iwl_op_mode *op_mode); 137 void (*nic_error)(struct iwl_op_mode *op_mode);
138 void (*cmd_queue_full)(struct iwl_op_mode *op_mode);
137}; 139};
138 140
139/** 141/**
@@ -192,6 +194,11 @@ static inline void iwl_op_mode_nic_error(struct iwl_op_mode *op_mode)
192 op_mode->ops->nic_error(op_mode); 194 op_mode->ops->nic_error(op_mode);
193} 195}
194 196
197static inline void iwl_op_mode_cmd_queue_full(struct iwl_op_mode *op_mode)
198{
199 op_mode->ops->cmd_queue_full(op_mode);
200}
201
195/***************************************************** 202/*****************************************************
196* Op mode layers implementations 203* Op mode layers implementations
197******************************************************/ 204******************************************************/
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 {
461int iwlagn_hw_valid_rtc_data_addr(u32 addr); 461int iwlagn_hw_valid_rtc_data_addr(u32 addr);
462void iwl_nic_config(struct iwl_priv *priv); 462void iwl_nic_config(struct iwl_priv *priv);
463const char *get_cmd_string(u8 cmd); 463const char *get_cmd_string(u8 cmd);
464bool iwl_check_for_ct_kill(struct iwl_priv *priv);
465
466 464
467/* notification wait support */ 465/* notification wait support */
468void iwl_abort_notification_waits(struct iwl_shared *shrd); 466void 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)
671 dma_addr_t phys_addr; 671 dma_addr_t phys_addr;
672 u32 idx; 672 u32 idx;
673 u16 copy_size, cmd_size; 673 u16 copy_size, cmd_size;
674 bool is_ct_kill = false;
675 bool had_nocopy = false; 674 bool had_nocopy = false;
676 int i; 675 int i;
677 u8 *cmd_dest; 676 u8 *cmd_dest;
@@ -727,11 +726,7 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
727 spin_unlock_bh(&txq->lock); 726 spin_unlock_bh(&txq->lock);
728 727
729 IWL_ERR(trans, "No space in command queue\n"); 728 IWL_ERR(trans, "No space in command queue\n");
730 is_ct_kill = iwl_check_for_ct_kill(priv(trans)); 729 iwl_op_mode_cmd_queue_full(trans->op_mode);
731 if (!is_ct_kill) {
732 IWL_ERR(trans, "Restarting adapter queue is full\n");
733 iwl_op_mode_nic_error(trans->op_mode);
734 }
735 return -ENOSPC; 730 return -ENOSPC;
736 } 731 }
737 732