aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-04-29 03:53:29 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-05-10 18:09:02 -0400
commit2c810ccdbac434ae38f4ec5331d3f047dc90f98a (patch)
treee1bd92e76baf88d5ac3f4af37e709f8c746fd623 /drivers
parenta6a0345c837346d1b74f4907d4747e6c1053a99f (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.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c137
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c8
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:
656EXPORT_SYMBOL_GPL(iwl_remove_station); 656EXPORT_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 */
666void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) 666void 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,
1251EXPORT_SYMBOL(iwl_send_lq_cmd); 1215EXPORT_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 */
1256int iwl_add_bcast_station(struct iwl_priv *priv) 1224int 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}
1261EXPORT_SYMBOL(iwl_add_bcast_station); 1258EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station);
1262 1259
1263/** 1260void iwl_dealloc_bcast_station(struct iwl_priv *priv)
1264 * iwl3945_add_bcast_station - add broadcast station into station table.
1265 */
1266int 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}
1281EXPORT_SYMBOL(iwl3945_add_bcast_station); 1278EXPORT_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
63int iwl_add_bcast_station(struct iwl_priv *priv);
64int iwl3945_add_bcast_station(struct iwl_priv *priv);
65void iwl_restore_stations(struct iwl_priv *priv); 63void iwl_restore_stations(struct iwl_priv *priv);
66void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); 64void iwl_clear_ucode_stations(struct iwl_priv *priv);
65int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq);
66void iwl_dealloc_bcast_station(struct iwl_priv *priv);
67int iwl_get_free_ucode_key_index(struct iwl_priv *priv); 67int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
68int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); 68int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
69int iwl_send_add_sta(struct iwl_priv *priv, 69int 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