iwlwifi: make iwl4965_mac_conf_tx in atomic context
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Fri, 11 Jul 2008 03:53:34 +0000 (11:53 +0800)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 14 Jul 2008 18:52:58 +0000 (14:52 -0400)
This patch fixes iwl4965_mac_conf_tx. A mutex was taken in atomic context
leading to Oops. This patch removes the mutex and extends the hold
priv->lock. None of the field of QOS is accessed without priv->lock held.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Zhu Yi <yi.zhu@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl4965-base.c

index d877039e2d45ec14bb1a012d68c782562abe3243..92754ee49e450d264d89406f9c9fcee9f9a59fd7 100644 (file)
@@ -725,7 +725,7 @@ struct iwl4965_csa_notification {
  * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
  * value, to cap the CW value.
  */
-struct iwl4965_ac_qos {
+struct iwl_ac_qos {
        __le16 cw_min;
        __le16 cw_max;
        u8 aifsn;
@@ -747,9 +747,9 @@ struct iwl4965_ac_qos {
  * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
  * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
  */
-struct iwl4965_qosparam_cmd {
+struct iwl_qosparam_cmd {
        __le32 qos_flags;
-       struct iwl4965_ac_qos ac[AC_NUM];
+       struct iwl_ac_qos ac[AC_NUM];
 } __attribute__ ((packed));
 
 /******************************************************************************
index 81a57cb2266bf33f5223abab895093ee84f251aa..92a37664d45322aa789118d9523a9ecf5aa41a19 100644 (file)
@@ -290,7 +290,7 @@ struct iwl_cmd {
                struct iwl4965_bt_cmd bt;
                struct iwl4965_rxon_time_cmd rxon_time;
                struct iwl4965_powertable_cmd powertable;
-               struct iwl4965_qosparam_cmd qosparam;
+               struct iwl_qosparam_cmd qosparam;
                struct iwl_tx_cmd tx;
                struct iwl4965_tx_beacon_cmd tx_beacon;
                struct iwl4965_rxon_assoc_cmd rxon_assoc;
@@ -435,7 +435,7 @@ struct iwl_ht_info {
        u8 non_GF_STA_present;
 };
 
-union iwl4965_qos_capabity {
+union iwl_qos_capabity {
        struct {
                u8 edca_count:4;        /* bit 0-3 */
                u8 q_ack:1;             /* bit 4 */
@@ -456,11 +456,11 @@ union iwl4965_qos_capabity {
 };
 
 /* QoS structures */
-struct iwl4965_qos_info {
+struct iwl_qos_info {
        int qos_enable;
        int qos_active;
-       union iwl4965_qos_capabity qos_cap;
-       struct iwl4965_qosparam_cmd def_qos_parm;
+       union iwl_qos_capabity qos_cap;
+       struct iwl_qosparam_cmd def_qos_parm;
 };
 
 #define STA_PS_STATUS_WAKE             0
@@ -1042,7 +1042,7 @@ struct iwl_priv {
        u16 assoc_capability;
        u8 ps_mode;
 
-       struct iwl4965_qos_info qos_data;
+       struct iwl_qos_info qos_data;
 
        struct workqueue_struct *workqueue;
 
index fbb854e31bdb139c0742bb8d2a8b6017920f8015..55648a8c88a2214baa90a400cb4a0f5cf8eadc40 100644 (file)
@@ -575,25 +575,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
 /*
  * QoS  support
 */
-static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
-                                      struct iwl4965_qosparam_cmd *qos)
+static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
 {
-
-       return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
-                               sizeof(struct iwl4965_qosparam_cmd), qos);
-}
-
-static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
-{
-       unsigned long flags;
-
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
        if (!priv->qos_data.qos_enable)
                return;
 
-       spin_lock_irqsave(&priv->lock, flags);
        priv->qos_data.def_qos_parm.qos_flags = 0;
 
        if (priv->qos_data.qos_cap.q_AP.queue_request &&
@@ -607,15 +596,14 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
        if (priv->current_ht_config.is_ht)
                priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        if (force || iwl_is_associated(priv)) {
                IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
                                priv->qos_data.qos_active,
                                priv->qos_data.def_qos_parm.qos_flags);
 
-               iwl4965_send_qos_params_command(priv,
-                               &(priv->qos_data.def_qos_parm));
+               iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+                                      sizeof(struct iwl_qosparam_cmd),
+                                      &priv->qos_data.def_qos_parm, NULL);
        }
 }
 
@@ -2424,6 +2412,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
        struct ieee80211_conf *conf = NULL;
        int ret = 0;
        DECLARE_MAC_BUF(mac);
+       unsigned long flags;
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
                IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
@@ -2513,7 +2502,9 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
        if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
                priv->assoc_station_added = 1;
 
-       iwl4965_activate_qos(priv, 0);
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_activate_qos(priv, 0);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        iwl_power_update_mode(priv, 0);
        /* we have just associated, don't start scan too early */
@@ -2845,6 +2836,7 @@ out:
 static void iwl4965_config_ap(struct iwl_priv *priv)
 {
        int ret = 0;
+       unsigned long flags;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -2892,7 +2884,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwl4965_commit_rxon(priv);
-               iwl4965_activate_qos(priv, 1);
+               spin_lock_irqsave(&priv->lock, flags);
+               iwl_activate_qos(priv, 1);
+               spin_unlock_irqrestore(&priv->lock, flags);
                iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
        }
        iwl4965_send_beacon_cmd(priv);
@@ -3340,15 +3334,12 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
        priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
        priv->qos_data.qos_active = 1;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
-               iwl4965_activate_qos(priv, 1);
+               iwl_activate_qos(priv, 1);
        else if (priv->assoc_id && iwl_is_associated(priv))
-               iwl4965_activate_qos(priv, 0);
+               iwl_activate_qos(priv, 0);
 
-       mutex_unlock(&priv->mutex);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        IWL_DEBUG_MAC80211("leave\n");
        return 0;