diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-04-29 03:53:29 -0400 |
---|---|---|
committer | Reinette Chatre <reinette.chatre@intel.com> | 2010-05-10 18:09:02 -0400 |
commit | 2c810ccdbac434ae38f4ec5331d3f047dc90f98a (patch) | |
tree | e1bd92e76baf88d5ac3f4af37e709f8c746fd623 /drivers | |
parent | a6a0345c837346d1b74f4907d4747e6c1053a99f (diff) |
iwlwifi: rework broadcast station management
Currently, the broadcast station is managed along
with the interface type, rather than always being
present. That leads to a bug with injection -- it
is currently not possible to inject frames when
the only virtual interface is a monitor, because
in that the required broadcast station is missing.
Additionally, allocating and deallocating the
broadcast station's LQ all the time is wasteful,
and the code to support this is fairly complex.
So this changes completely the way we manage the
broadcast station. Rather than manage it along
with any interface, we now allocate it when we
bring the device up, and remove it again when we
bring the device down. When we bring the device
up, we don't immediately program the broadcast
station into it, instead we just mark it active
and rely on the next restore cycle to upload it
to the device. This works because an unassociated
RXON is always required at least once to set up
device parameters, which implies a reprogramming
of stations into the device.
As we now manage all stations properly, there no
longer is a need for forcing a clearing of them
via iwl_clear_ucode_stations(), which can become
a lot simpler.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-1000.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-4965.c | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-5000.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 137 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.h | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 8 |
11 files changed, 89 insertions, 99 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index a2f7cbcc2f7c..6be2992f8f21 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -212,7 +212,6 @@ static struct iwl_lib_ops iwl1000_lib = { | |||
212 | .temperature = iwlagn_temperature, | 212 | .temperature = iwlagn_temperature, |
213 | .set_ct_kill = iwl1000_set_ct_threshold, | 213 | .set_ct_kill = iwl1000_set_ct_threshold, |
214 | }, | 214 | }, |
215 | .add_bcast_station = iwl_add_bcast_station, | ||
216 | .manage_ibss_station = iwlagn_manage_ibss_station, | 215 | .manage_ibss_station = iwlagn_manage_ibss_station, |
217 | .debugfs_ops = { | 216 | .debugfs_ops = { |
218 | .rx_stats_read = iwl_ucode_rx_stats_read, | 217 | .rx_stats_read = iwl_ucode_rx_stats_read, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 05d808b28777..7fb159565f68 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -1992,7 +1992,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
1992 | "configuration (%d).\n", rc); | 1992 | "configuration (%d).\n", rc); |
1993 | return rc; | 1993 | return rc; |
1994 | } | 1994 | } |
1995 | iwl_clear_ucode_stations(priv, false); | 1995 | iwl_clear_ucode_stations(priv); |
1996 | iwl_restore_stations(priv); | 1996 | iwl_restore_stations(priv); |
1997 | } | 1997 | } |
1998 | 1998 | ||
@@ -2025,7 +2025,7 @@ static int iwl3945_commit_rxon(struct iwl_priv *priv) | |||
2025 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); | 2025 | memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); |
2026 | 2026 | ||
2027 | if (!new_assoc) { | 2027 | if (!new_assoc) { |
2028 | iwl_clear_ucode_stations(priv, false); | 2028 | iwl_clear_ucode_stations(priv); |
2029 | iwl_restore_stations(priv); | 2029 | iwl_restore_stations(priv); |
2030 | } | 2030 | } |
2031 | 2031 | ||
@@ -2853,7 +2853,6 @@ static struct iwl_lib_ops iwl3945_lib = { | |||
2853 | .isr = iwl_isr_legacy, | 2853 | .isr = iwl_isr_legacy, |
2854 | .config_ap = iwl3945_config_ap, | 2854 | .config_ap = iwl3945_config_ap, |
2855 | .manage_ibss_station = iwl3945_manage_ibss_station, | 2855 | .manage_ibss_station = iwl3945_manage_ibss_station, |
2856 | .add_bcast_station = iwl3945_add_bcast_station, | ||
2857 | .check_plcp_health = iwl3945_good_plcp_health, | 2856 | .check_plcp_health = iwl3945_good_plcp_health, |
2858 | 2857 | ||
2859 | .debugfs_ops = { | 2858 | .debugfs_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index b8bf837af464..93893aec6cc4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -2190,7 +2190,6 @@ static struct iwl_lib_ops iwl4965_lib = { | |||
2190 | .temperature = iwl4965_temperature_calib, | 2190 | .temperature = iwl4965_temperature_calib, |
2191 | .set_ct_kill = iwl4965_set_ct_threshold, | 2191 | .set_ct_kill = iwl4965_set_ct_threshold, |
2192 | }, | 2192 | }, |
2193 | .add_bcast_station = iwl_add_bcast_station, | ||
2194 | .manage_ibss_station = iwlagn_manage_ibss_station, | 2193 | .manage_ibss_station = iwlagn_manage_ibss_station, |
2195 | .debugfs_ops = { | 2194 | .debugfs_ops = { |
2196 | .rx_stats_read = iwl_ucode_rx_stats_read, | 2195 | .rx_stats_read = iwl_ucode_rx_stats_read, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index efda0e8ccacb..a28af7eb67eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -351,7 +351,6 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
351 | .temperature = iwlagn_temperature, | 351 | .temperature = iwlagn_temperature, |
352 | .set_ct_kill = iwl5000_set_ct_threshold, | 352 | .set_ct_kill = iwl5000_set_ct_threshold, |
353 | }, | 353 | }, |
354 | .add_bcast_station = iwl_add_bcast_station, | ||
355 | .manage_ibss_station = iwlagn_manage_ibss_station, | 354 | .manage_ibss_station = iwlagn_manage_ibss_station, |
356 | .debugfs_ops = { | 355 | .debugfs_ops = { |
357 | .rx_stats_read = iwl_ucode_rx_stats_read, | 356 | .rx_stats_read = iwl_ucode_rx_stats_read, |
@@ -414,7 +413,6 @@ static struct iwl_lib_ops iwl5150_lib = { | |||
414 | .temperature = iwl5150_temperature, | 413 | .temperature = iwl5150_temperature, |
415 | .set_ct_kill = iwl5150_set_ct_threshold, | 414 | .set_ct_kill = iwl5150_set_ct_threshold, |
416 | }, | 415 | }, |
417 | .add_bcast_station = iwl_add_bcast_station, | ||
418 | .manage_ibss_station = iwlagn_manage_ibss_station, | 416 | .manage_ibss_station = iwlagn_manage_ibss_station, |
419 | .debugfs_ops = { | 417 | .debugfs_ops = { |
420 | .rx_stats_read = iwl_ucode_rx_stats_read, | 418 | .rx_stats_read = iwl_ucode_rx_stats_read, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 03c73244703c..9fbf54cd3e1a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -317,7 +317,6 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
317 | .temperature = iwlagn_temperature, | 317 | .temperature = iwlagn_temperature, |
318 | .set_ct_kill = iwl6000_set_ct_threshold, | 318 | .set_ct_kill = iwl6000_set_ct_threshold, |
319 | }, | 319 | }, |
320 | .add_bcast_station = iwl_add_bcast_station, | ||
321 | .manage_ibss_station = iwlagn_manage_ibss_station, | 320 | .manage_ibss_station = iwlagn_manage_ibss_station, |
322 | .debugfs_ops = { | 321 | .debugfs_ops = { |
323 | .rx_stats_read = iwl_ucode_rx_stats_read, | 322 | .rx_stats_read = iwl_ucode_rx_stats_read, |
@@ -390,7 +389,6 @@ static struct iwl_lib_ops iwl6050_lib = { | |||
390 | .set_ct_kill = iwl6000_set_ct_threshold, | 389 | .set_ct_kill = iwl6000_set_ct_threshold, |
391 | .set_calib_version = iwl6050_set_calib_version, | 390 | .set_calib_version = iwl6050_set_calib_version, |
392 | }, | 391 | }, |
393 | .add_bcast_station = iwl_add_bcast_station, | ||
394 | .manage_ibss_station = iwlagn_manage_ibss_station, | 392 | .manage_ibss_station = iwlagn_manage_ibss_station, |
395 | .debugfs_ops = { | 393 | .debugfs_ops = { |
396 | .rx_stats_read = iwl_ucode_rx_stats_read, | 394 | .rx_stats_read = iwl_ucode_rx_stats_read, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 85e045baf5ae..0c913ea71f1e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -156,7 +156,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
156 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); | 156 | IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); |
157 | return ret; | 157 | return ret; |
158 | } | 158 | } |
159 | iwl_clear_ucode_stations(priv, false); | 159 | iwl_clear_ucode_stations(priv); |
160 | iwl_restore_stations(priv); | 160 | iwl_restore_stations(priv); |
161 | ret = iwl_restore_default_wep_keys(priv); | 161 | ret = iwl_restore_default_wep_keys(priv); |
162 | if (ret) { | 162 | if (ret) { |
@@ -188,7 +188,7 @@ int iwl_commit_rxon(struct iwl_priv *priv) | |||
188 | } | 188 | } |
189 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); | 189 | IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n"); |
190 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); | 190 | memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); |
191 | iwl_clear_ucode_stations(priv, false); | 191 | iwl_clear_ucode_stations(priv); |
192 | iwl_restore_stations(priv); | 192 | iwl_restore_stations(priv); |
193 | ret = iwl_restore_default_wep_keys(priv); | 193 | ret = iwl_restore_default_wep_keys(priv); |
194 | if (ret) { | 194 | if (ret) { |
@@ -2403,7 +2403,8 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2403 | if (!exit_pending) | 2403 | if (!exit_pending) |
2404 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2404 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2405 | 2405 | ||
2406 | iwl_clear_ucode_stations(priv, true); | 2406 | iwl_clear_ucode_stations(priv); |
2407 | iwl_dealloc_bcast_station(priv); | ||
2407 | 2408 | ||
2408 | /* Unblock any waiting calls */ | 2409 | /* Unblock any waiting calls */ |
2409 | wake_up_interruptible_all(&priv->wait_command_queue); | 2410 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2550,6 +2551,10 @@ static int __iwl_up(struct iwl_priv *priv) | |||
2550 | return -EIO; | 2551 | return -EIO; |
2551 | } | 2552 | } |
2552 | 2553 | ||
2554 | ret = iwl_alloc_bcast_station(priv, true); | ||
2555 | if (ret) | ||
2556 | return ret; | ||
2557 | |||
2553 | iwl_prepare_card_hw(priv); | 2558 | iwl_prepare_card_hw(priv); |
2554 | 2559 | ||
2555 | if (!priv->hw_ready) { | 2560 | if (!priv->hw_ready) { |
@@ -3032,7 +3037,6 @@ void iwl_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3032 | /* restore RXON assoc */ | 3037 | /* restore RXON assoc */ |
3033 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3038 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3034 | iwlcore_commit_rxon(priv); | 3039 | iwlcore_commit_rxon(priv); |
3035 | iwl_add_bcast_station(priv); | ||
3036 | } | 3040 | } |
3037 | iwl_send_beacon_cmd(priv); | 3041 | iwl_send_beacon_cmd(priv); |
3038 | 3042 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index d7a36205f0e1..f007b36ec54e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c | |||
@@ -2042,11 +2042,6 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
2042 | if (err) | 2042 | if (err) |
2043 | goto out_err; | 2043 | goto out_err; |
2044 | 2044 | ||
2045 | /* Add the broadcast address so we can send broadcast frames */ | ||
2046 | err = priv->cfg->ops->lib->add_bcast_station(priv); | ||
2047 | if (err) | ||
2048 | goto out_err; | ||
2049 | |||
2050 | goto out; | 2045 | goto out; |
2051 | 2046 | ||
2052 | out_err: | 2047 | out_err: |
@@ -2069,8 +2064,6 @@ void iwl_mac_remove_interface(struct ieee80211_hw *hw, | |||
2069 | 2064 | ||
2070 | mutex_lock(&priv->mutex); | 2065 | mutex_lock(&priv->mutex); |
2071 | 2066 | ||
2072 | iwl_clear_ucode_stations(priv, true); | ||
2073 | |||
2074 | if (iwl_is_ready_rf(priv)) { | 2067 | if (iwl_is_ready_rf(priv)) { |
2075 | iwl_scan_cancel_timeout(priv, 100); | 2068 | iwl_scan_cancel_timeout(priv, 100); |
2076 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; | 2069 | priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 1774ce9186eb..d80aa6c8d785 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -191,7 +191,6 @@ struct iwl_lib_ops { | |||
191 | /* temperature */ | 191 | /* temperature */ |
192 | struct iwl_temp_ops temp_ops; | 192 | struct iwl_temp_ops temp_ops; |
193 | /* station management */ | 193 | /* station management */ |
194 | int (*add_bcast_station)(struct iwl_priv *priv); | ||
195 | int (*manage_ibss_station)(struct iwl_priv *priv, | 194 | int (*manage_ibss_station)(struct iwl_priv *priv, |
196 | struct ieee80211_vif *vif, bool add); | 195 | struct ieee80211_vif *vif, bool add); |
197 | /* recover from tx queue stall */ | 196 | /* recover from tx queue stall */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 5bf82b9b523b..7e51647cf02d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -656,63 +656,27 @@ out: | |||
656 | EXPORT_SYMBOL_GPL(iwl_remove_station); | 656 | EXPORT_SYMBOL_GPL(iwl_remove_station); |
657 | 657 | ||
658 | /** | 658 | /** |
659 | * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode | 659 | * iwl_clear_ucode_stations - clear ucode station table bits |
660 | * @priv: | 660 | * |
661 | * @force: If set then the uCode station table needs to be cleared here. If | 661 | * This function clears all the bits in the driver indicating |
662 | * not set then the uCode station table has already been cleared, | 662 | * which stations are active in the ucode. Call when something |
663 | * for example after sending it a RXON command without ASSOC bit | 663 | * other than explicit station management would cause this in |
664 | * set, and we just need to change driver state here. | 664 | * the ucode, e.g. unassociated RXON. |
665 | */ | 665 | */ |
666 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) | 666 | void iwl_clear_ucode_stations(struct iwl_priv *priv) |
667 | { | 667 | { |
668 | int i; | 668 | int i; |
669 | unsigned long flags_spin; | 669 | unsigned long flags_spin; |
670 | bool cleared = false; | 670 | bool cleared = false; |
671 | 671 | ||
672 | IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n", | 672 | IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); |
673 | force ? " and ucode" : ""); | ||
674 | |||
675 | if (force) { | ||
676 | if (!iwl_is_ready(priv)) { | ||
677 | /* | ||
678 | * If device is not ready at this point the station | ||
679 | * table is likely already empty (uCode not ready | ||
680 | * to receive station requests) or will soon be | ||
681 | * due to interface going down. | ||
682 | */ | ||
683 | IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n"); | ||
684 | } else { | ||
685 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL); | ||
686 | } | ||
687 | } | ||
688 | 673 | ||
689 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 674 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
690 | if (force) { | 675 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
691 | IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); | 676 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { |
692 | /* | 677 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); |
693 | * The station entry contains a link to the LQ command. For | 678 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; |
694 | * all stations managed by mac80211 this memory will be | 679 | cleared = true; |
695 | * managed by it also. For local stations (broadcast and | ||
696 | * bssid station when in adhoc mode) we need to maintain | ||
697 | * this lq command separately. This memory is created when | ||
698 | * these stations are added. | ||
699 | */ | ||
700 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
701 | if (priv->stations[i].used & IWL_STA_LOCAL) { | ||
702 | kfree(priv->stations[i].lq); | ||
703 | priv->stations[i].lq = NULL; | ||
704 | } | ||
705 | } | ||
706 | priv->num_stations = 0; | ||
707 | memset(priv->stations, 0, sizeof(priv->stations)); | ||
708 | cleared = true; | ||
709 | } else { | ||
710 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
711 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { | ||
712 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); | ||
713 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
714 | cleared = true; | ||
715 | } | ||
716 | } | 680 | } |
717 | } | 681 | } |
718 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 682 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
@@ -1251,34 +1215,67 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
1251 | EXPORT_SYMBOL(iwl_send_lq_cmd); | 1215 | EXPORT_SYMBOL(iwl_send_lq_cmd); |
1252 | 1216 | ||
1253 | /** | 1217 | /** |
1254 | * iwl_add_bcast_station - add broadcast station into station table. | 1218 | * iwl_alloc_bcast_station - add broadcast station into driver's station table. |
1219 | * | ||
1220 | * This adds the broadcast station into the driver's station table | ||
1221 | * and marks it driver active, so that it will be restored to the | ||
1222 | * device at the next best time. | ||
1255 | */ | 1223 | */ |
1256 | int iwl_add_bcast_station(struct iwl_priv *priv) | 1224 | int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) |
1257 | { | 1225 | { |
1258 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | 1226 | struct iwl_link_quality_cmd *link_cmd; |
1259 | return iwl_add_local_station(priv, iwl_bcast_addr, true); | 1227 | unsigned long flags; |
1228 | u8 sta_id; | ||
1229 | |||
1230 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1231 | sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL); | ||
1232 | if (sta_id == IWL_INVALID_STATION) { | ||
1233 | IWL_ERR(priv, "Unable to prepare broadcast station\n"); | ||
1234 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1235 | |||
1236 | return -EINVAL; | ||
1237 | } | ||
1238 | |||
1239 | priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; | ||
1240 | priv->stations[sta_id].used |= IWL_STA_BCAST; | ||
1241 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1242 | |||
1243 | if (init_lq) { | ||
1244 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); | ||
1245 | if (!link_cmd) { | ||
1246 | IWL_ERR(priv, | ||
1247 | "Unable to initialize rate scaling for bcast station.\n"); | ||
1248 | return -ENOMEM; | ||
1249 | } | ||
1250 | |||
1251 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1252 | priv->stations[sta_id].lq = link_cmd; | ||
1253 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1254 | } | ||
1255 | |||
1256 | return 0; | ||
1260 | } | 1257 | } |
1261 | EXPORT_SYMBOL(iwl_add_bcast_station); | 1258 | EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); |
1262 | 1259 | ||
1263 | /** | 1260 | void iwl_dealloc_bcast_station(struct iwl_priv *priv) |
1264 | * iwl3945_add_bcast_station - add broadcast station into station table. | ||
1265 | */ | ||
1266 | int iwl3945_add_bcast_station(struct iwl_priv *priv) | ||
1267 | { | 1261 | { |
1268 | int ret; | 1262 | unsigned long flags; |
1269 | 1263 | int i; | |
1270 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | ||
1271 | ret = iwl_add_local_station(priv, iwl_bcast_addr, false); | ||
1272 | /* | ||
1273 | * It is assumed that when station is added more initialization | ||
1274 | * needs to be done, but for 3945 it is not the case and we can | ||
1275 | * just release station table access right here. | ||
1276 | */ | ||
1277 | priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
1278 | return ret; | ||
1279 | 1264 | ||
1265 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1266 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
1267 | if (!(priv->stations[i].used & IWL_STA_BCAST)) | ||
1268 | continue; | ||
1269 | |||
1270 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
1271 | priv->num_stations--; | ||
1272 | BUG_ON(priv->num_stations < 0); | ||
1273 | kfree(priv->stations[i].lq); | ||
1274 | priv->stations[i].lq = NULL; | ||
1275 | } | ||
1276 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1280 | } | 1277 | } |
1281 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | 1278 | EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); |
1282 | 1279 | ||
1283 | /** | 1280 | /** |
1284 | * iwl_get_sta_id - Find station's index within station table | 1281 | * iwl_get_sta_id - Find station's index within station table |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index 1a0e590a824d..50c9d5138a4b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h | |||
@@ -36,9 +36,9 @@ | |||
36 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ | 36 | #define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ |
37 | #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of | 37 | #define IWL_STA_UCODE_INPROGRESS BIT(2) /* ucode entry is in process of |
38 | being activated */ | 38 | being activated */ |
39 | #define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211 | 39 | #define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211; |
40 | this is for bcast and bssid (when adhoc) | 40 | (this is for the IBSS BSSID stations) */ |
41 | stations */ | 41 | #define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */ |
42 | 42 | ||
43 | 43 | ||
44 | /** | 44 | /** |
@@ -60,10 +60,10 @@ void iwl_update_tkip_key(struct iwl_priv *priv, | |||
60 | struct ieee80211_key_conf *keyconf, | 60 | struct ieee80211_key_conf *keyconf, |
61 | const u8 *addr, u32 iv32, u16 *phase1key); | 61 | const u8 *addr, u32 iv32, u16 *phase1key); |
62 | 62 | ||
63 | int iwl_add_bcast_station(struct iwl_priv *priv); | ||
64 | int iwl3945_add_bcast_station(struct iwl_priv *priv); | ||
65 | void iwl_restore_stations(struct iwl_priv *priv); | 63 | void iwl_restore_stations(struct iwl_priv *priv); |
66 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); | 64 | void iwl_clear_ucode_stations(struct iwl_priv *priv); |
65 | int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); | ||
66 | void iwl_dealloc_bcast_station(struct iwl_priv *priv); | ||
67 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | 67 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); |
68 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); | 68 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); |
69 | int iwl_send_add_sta(struct iwl_priv *priv, | 69 | int iwl_send_add_sta(struct iwl_priv *priv, |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 85a46ad667de..1a445711e34a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -2583,7 +2583,8 @@ static void __iwl3945_down(struct iwl_priv *priv) | |||
2583 | set_bit(STATUS_EXIT_PENDING, &priv->status); | 2583 | set_bit(STATUS_EXIT_PENDING, &priv->status); |
2584 | 2584 | ||
2585 | /* Station information will now be cleared in device */ | 2585 | /* Station information will now be cleared in device */ |
2586 | iwl_clear_ucode_stations(priv, true); | 2586 | iwl_clear_ucode_stations(priv); |
2587 | iwl_dealloc_bcast_station(priv); | ||
2587 | 2588 | ||
2588 | /* Unblock any waiting calls */ | 2589 | /* Unblock any waiting calls */ |
2589 | wake_up_interruptible_all(&priv->wait_command_queue); | 2590 | wake_up_interruptible_all(&priv->wait_command_queue); |
@@ -2664,6 +2665,10 @@ static int __iwl3945_up(struct iwl_priv *priv) | |||
2664 | { | 2665 | { |
2665 | int rc, i; | 2666 | int rc, i; |
2666 | 2667 | ||
2668 | rc = iwl_alloc_bcast_station(priv, false); | ||
2669 | if (rc) | ||
2670 | return rc; | ||
2671 | |||
2667 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { | 2672 | if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { |
2668 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); | 2673 | IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); |
2669 | return -EIO; | 2674 | return -EIO; |
@@ -3302,7 +3307,6 @@ void iwl3945_config_ap(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
3302 | /* restore RXON assoc */ | 3307 | /* restore RXON assoc */ |
3303 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; | 3308 | priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; |
3304 | iwlcore_commit_rxon(priv); | 3309 | iwlcore_commit_rxon(priv); |
3305 | iwl3945_add_bcast_station(priv); | ||
3306 | } | 3310 | } |
3307 | iwl3945_send_beacon_cmd(priv); | 3311 | iwl3945_send_beacon_cmd(priv); |
3308 | 3312 | ||