diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 137 |
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: | |||
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 |