aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c137
1 files changed, 67 insertions, 70 deletions
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