diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2008-07-10 23:53:34 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-07-14 14:52:58 -0400 |
commit | 1ff50bda6eef4466366e197541508fc69af0f0c0 (patch) | |
tree | 79499aa72caab98d52cb95602eb64d08b24c4ed4 | |
parent | 6c5379077f47f6eff9c23caf8513751d2f582e72 (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.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl4965-base.c | 39 |
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 | */ |
728 | struct iwl4965_ac_qos { | 728 | struct 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 | */ |
750 | struct iwl4965_qosparam_cmd { | 750 | struct 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 | ||
438 | union iwl4965_qos_capabity { | 438 | union 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 */ |
459 | struct iwl4965_qos_info { | 459 | struct 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 | */ |
578 | static int iwl4965_send_qos_params_command(struct iwl_priv *priv, | 578 | static 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 | |||
586 | static 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: | |||
2845 | static void iwl4965_config_ap(struct iwl_priv *priv) | 2836 | static 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; |