Commit 1ff50bda authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by John W. Linville

iwlwifi: make iwl4965_mac_conf_tx in atomic context

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