aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-sta.c
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/net/wireless/iwlwifi/iwl-sta.c
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/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