mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
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: 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>
This commit is contained in:
parent
6c5379077f
commit
1ff50bda6e
3 changed files with 24 additions and 33 deletions
|
@ -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 {
|
||||||
* 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 {
|
||||||
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 {
|
||||||
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 {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 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 {
|
||||||
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,
|
||||||
/*
|
/*
|
||||||
* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@ out:
|
||||||
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)
|
||||||
/* 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,
|
||||||
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;
|
||||||
|
|
Loading…
Add table
Reference in a new issue