iwlwifi: virtualize command queue full behaviour
authorJohannes Berg <johannes.berg@intel.com>
Tue, 6 Mar 2012 21:30:49 +0000 (13:30 -0800)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 7 Mar 2012 18:51:52 +0000 (13:51 -0500)
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>
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-agn.h
drivers/net/wireless/iwlwifi/iwl-op-mode.h
drivers/net/wireless/iwlwifi/iwl-shared.h
drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c

index 276570025e52fa5fa02b854cff49e9394f1b45f8..7c3165ed85bc229f5ea67fb624659dc9755569df 100644 (file)
@@ -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,
 };
 
 /*****************************************************************************
index 1f62d6d1fc652e28b4a20a6f8f8af8fbf0a8fb9d..ec3a90c42efb0a0c2116967f9243dad06b896f9c 100644 (file)
@@ -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,
index 55b8b27a9560f2f235f64d7d56d9780d8fe1fb15..a4a4907803caf05bb0a3d50282f71f60dc1bfb3a 100644 (file)
@@ -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
 ******************************************************/
index 5e12b504aacfb825fe70282f3b05f33239bec673..8ee528479c9561d63dc9f6a01993aaf47b3477e7 100644 (file)
@@ -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);
index 844606b436ed653052ebc7003453efadcc2871b5..7feeb2d521463f56b97dcd1d109d626b115c8c5b 100644 (file)
@@ -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;
        }