aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-07-10 23:53:34 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-07-14 14:52:58 -0400
commit1ff50bda6eef4466366e197541508fc69af0f0c0 (patch)
tree79499aa72caab98d52cb95602eb64d08b24c4ed4
parent6c5379077f47f6eff9c23caf8513751d2f582e72 (diff)
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>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c39
3 files changed, 24 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index d877039e2d45..92754ee49e45 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -725,7 +725,7 @@ struct iwl4965_csa_notification {
725 * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW 725 * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW
726 * value, to cap the CW value. 726 * value, to cap the CW value.
727 */ 727 */
728struct iwl4965_ac_qos { 728struct iwl_ac_qos {
729 __le16 cw_min; 729 __le16 cw_min;
730 __le16 cw_max; 730 __le16 cw_max;
731 u8 aifsn; 731 u8 aifsn;
@@ -747,9 +747,9 @@ struct iwl4965_ac_qos {
747 * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs 747 * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
748 * 0: Background, 1: Best Effort, 2: Video, 3: Voice. 748 * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
749 */ 749 */
750struct iwl4965_qosparam_cmd { 750struct iwl_qosparam_cmd {
751 __le32 qos_flags; 751 __le32 qos_flags;
752 struct iwl4965_ac_qos ac[AC_NUM]; 752 struct iwl_ac_qos ac[AC_NUM];
753} __attribute__ ((packed)); 753} __attribute__ ((packed));
754 754
755/****************************************************************************** 755/******************************************************************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 81a57cb2266b..92a37664d453 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -290,7 +290,7 @@ struct iwl_cmd {
290 struct iwl4965_bt_cmd bt; 290 struct iwl4965_bt_cmd bt;
291 struct iwl4965_rxon_time_cmd rxon_time; 291 struct iwl4965_rxon_time_cmd rxon_time;
292 struct iwl4965_powertable_cmd powertable; 292 struct iwl4965_powertable_cmd powertable;
293 struct iwl4965_qosparam_cmd qosparam; 293 struct iwl_qosparam_cmd qosparam;
294 struct iwl_tx_cmd tx; 294 struct iwl_tx_cmd tx;
295 struct iwl4965_tx_beacon_cmd tx_beacon; 295 struct iwl4965_tx_beacon_cmd tx_beacon;
296 struct iwl4965_rxon_assoc_cmd rxon_assoc; 296 struct iwl4965_rxon_assoc_cmd rxon_assoc;
@@ -435,7 +435,7 @@ struct iwl_ht_info {
435 u8 non_GF_STA_present; 435 u8 non_GF_STA_present;
436}; 436};
437 437
438union iwl4965_qos_capabity { 438union iwl_qos_capabity {
439 struct { 439 struct {
440 u8 edca_count:4; /* bit 0-3 */ 440 u8 edca_count:4; /* bit 0-3 */
441 u8 q_ack:1; /* bit 4 */ 441 u8 q_ack:1; /* bit 4 */
@@ -456,11 +456,11 @@ union iwl4965_qos_capabity {
456}; 456};
457 457
458/* QoS structures */ 458/* QoS structures */
459struct iwl4965_qos_info { 459struct iwl_qos_info {
460 int qos_enable; 460 int qos_enable;
461 int qos_active; 461 int qos_active;
462 union iwl4965_qos_capabity qos_cap; 462 union iwl_qos_capabity qos_cap;
463 struct iwl4965_qosparam_cmd def_qos_parm; 463 struct iwl_qosparam_cmd def_qos_parm;
464}; 464};
465 465
466#define STA_PS_STATUS_WAKE 0 466#define STA_PS_STATUS_WAKE 0
@@ -1042,7 +1042,7 @@ struct iwl_priv {
1042 u16 assoc_capability; 1042 u16 assoc_capability;
1043 u8 ps_mode; 1043 u8 ps_mode;
1044 1044
1045 struct iwl4965_qos_info qos_data; 1045 struct iwl_qos_info qos_data;
1046 1046
1047 struct workqueue_struct *workqueue; 1047 struct workqueue_struct *workqueue;
1048 1048
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index fbb854e31bdb..55648a8c88a2 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -575,25 +575,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
575/* 575/*
576 * QoS support 576 * QoS support
577*/ 577*/
578static int iwl4965_send_qos_params_command(struct iwl_priv *priv, 578static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
579 struct iwl4965_qosparam_cmd *qos)
580{ 579{
581
582 return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
583 sizeof(struct iwl4965_qosparam_cmd), qos);
584}
585
586static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
587{
588 unsigned long flags;
589
590 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 580 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
591 return; 581 return;
592 582
593 if (!priv->qos_data.qos_enable) 583 if (!priv->qos_data.qos_enable)
594 return; 584 return;
595 585
596 spin_lock_irqsave(&priv->lock, flags);
597 priv->qos_data.def_qos_parm.qos_flags = 0; 586 priv->qos_data.def_qos_parm.qos_flags = 0;
598 587
599 if (priv->qos_data.qos_cap.q_AP.queue_request && 588 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 if (priv->current_ht_config.is_ht) 596 if (priv->current_ht_config.is_ht)
608 priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; 597 priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
609 598
610 spin_unlock_irqrestore(&priv->lock, flags);
611
612 if (force || iwl_is_associated(priv)) { 599 if (force || iwl_is_associated(priv)) {
613 IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n", 600 IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
614 priv->qos_data.qos_active, 601 priv->qos_data.qos_active,
615 priv->qos_data.def_qos_parm.qos_flags); 602 priv->qos_data.def_qos_parm.qos_flags);
616 603
617 iwl4965_send_qos_params_command(priv, 604 iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
618 &(priv->qos_data.def_qos_parm)); 605 sizeof(struct iwl_qosparam_cmd),
606 &priv->qos_data.def_qos_parm, NULL);
619 } 607 }
620} 608}
621 609
@@ -2424,6 +2412,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
2424 struct ieee80211_conf *conf = NULL; 2412 struct ieee80211_conf *conf = NULL;
2425 int ret = 0; 2413 int ret = 0;
2426 DECLARE_MAC_BUF(mac); 2414 DECLARE_MAC_BUF(mac);
2415 unsigned long flags;
2427 2416
2428 if (priv->iw_mode == IEEE80211_IF_TYPE_AP) { 2417 if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
2429 IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__); 2418 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 if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS) 2502 if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
2514 priv->assoc_station_added = 1; 2503 priv->assoc_station_added = 1;
2515 2504
2516 iwl4965_activate_qos(priv, 0); 2505 spin_lock_irqsave(&priv->lock, flags);
2506 iwl_activate_qos(priv, 0);
2507 spin_unlock_irqrestore(&priv->lock, flags);
2517 2508
2518 iwl_power_update_mode(priv, 0); 2509 iwl_power_update_mode(priv, 0);
2519 /* we have just associated, don't start scan too early */ 2510 /* we have just associated, don't start scan too early */
@@ -2845,6 +2836,7 @@ out:
2845static void iwl4965_config_ap(struct iwl_priv *priv) 2836static void iwl4965_config_ap(struct iwl_priv *priv)
2846{ 2837{
2847 int ret = 0; 2838 int ret = 0;
2839 unsigned long flags;
2848 2840
2849 if (test_bit(STATUS_EXIT_PENDING, &priv->status)) 2841 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
2850 return; 2842 return;
@@ -2892,7 +2884,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
2892 /* restore RXON assoc */ 2884 /* restore RXON assoc */
2893 priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; 2885 priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
2894 iwl4965_commit_rxon(priv); 2886 iwl4965_commit_rxon(priv);
2895 iwl4965_activate_qos(priv, 1); 2887 spin_lock_irqsave(&priv->lock, flags);
2888 iwl_activate_qos(priv, 1);
2889 spin_unlock_irqrestore(&priv->lock, flags);
2896 iwl_rxon_add_station(priv, iwl_bcast_addr, 0); 2890 iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
2897 } 2891 }
2898 iwl4965_send_beacon_cmd(priv); 2892 iwl4965_send_beacon_cmd(priv);
@@ -3340,15 +3334,12 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
3340 priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; 3334 priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
3341 priv->qos_data.qos_active = 1; 3335 priv->qos_data.qos_active = 1;
3342 3336
3343 spin_unlock_irqrestore(&priv->lock, flags);
3344
3345 mutex_lock(&priv->mutex);
3346 if (priv->iw_mode == IEEE80211_IF_TYPE_AP) 3337 if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
3347 iwl4965_activate_qos(priv, 1); 3338 iwl_activate_qos(priv, 1);
3348 else if (priv->assoc_id && iwl_is_associated(priv)) 3339 else if (priv->assoc_id && iwl_is_associated(priv))
3349 iwl4965_activate_qos(priv, 0); 3340 iwl_activate_qos(priv, 0);
3350 3341
3351 mutex_unlock(&priv->mutex); 3342 spin_unlock_irqrestore(&priv->lock, flags);
3352 3343
3353 IWL_DEBUG_MAC80211("leave\n"); 3344 IWL_DEBUG_MAC80211("leave\n");
3354 return 0; 3345 return 0;