aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorReinette Chatre <reinette.chatre@intel.com>2010-04-23 13:33:33 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-05-10 18:08:51 -0400
commitd2e210aef3a8e7472f91d10a50ecbc91c0a53d62 (patch)
tree072dceeed6ab669ed0619d4c195d11a01df6b93d /drivers/net/wireless
parent459bc732abad5e461da9a06d82dfc0cb1119ef5a (diff)
iwlwifi: make bcast LQ command available for later restore actions
When adding the broadcast station the link quality command is generated on demand, sent to device, and disappears. It is thus not available for later cases when we need to restore stations and need to send the link quality command afterwards. Now, when first adding the broadcast station, also generate its link quality command to always be available for later restoring. Also fix an issue when adding local stations where the "in progress" state is never cleared. Reported-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c91
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h7
4 files changed, 75 insertions, 29 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index d609414844db..e8c9bcafe564 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -2042,7 +2042,9 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
2042 goto out_err; 2042 goto out_err;
2043 2043
2044 /* Add the broadcast address so we can send broadcast frames */ 2044 /* Add the broadcast address so we can send broadcast frames */
2045 priv->cfg->ops->lib->add_bcast_station(priv); 2045 err = priv->cfg->ops->lib->add_bcast_station(priv);
2046 if (err)
2047 goto out_err;
2046 2048
2047 goto out; 2049 goto out;
2048 2050
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index f66c1c1848c8..8d53fc973a43 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -201,7 +201,7 @@ struct iwl_lib_ops {
201 /* temperature */ 201 /* temperature */
202 struct iwl_temp_ops temp_ops; 202 struct iwl_temp_ops temp_ops;
203 /* station management */ 203 /* station management */
204 void (*add_bcast_station)(struct iwl_priv *priv); 204 int (*add_bcast_station)(struct iwl_priv *priv);
205 /* recover from tx queue stall */ 205 /* recover from tx queue stall */
206 void (*recover_from_tx_stall)(unsigned long data); 206 void (*recover_from_tx_stall)(unsigned long data);
207 /* check for plcp health */ 207 /* check for plcp health */
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
index db934476b5e9..5c6b3262baf9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.c
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
@@ -418,15 +418,19 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
418} 418}
419EXPORT_SYMBOL(iwl_add_station_common); 419EXPORT_SYMBOL(iwl_add_station_common);
420 420
421static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) 421static struct iwl_link_quality_cmd *iwl_sta_init_lq(struct iwl_priv *priv,
422 const u8 *addr, bool is_ap)
422{ 423{
423 int i, r; 424 int i, r;
424 struct iwl_link_quality_cmd link_cmd = { 425 struct iwl_link_quality_cmd *link_cmd;
425 .reserved1 = 0,
426 };
427 u32 rate_flags; 426 u32 rate_flags;
428 int ret = 0; 427 int ret = 0;
429 428
429 link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
430 if (!link_cmd) {
431 IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
432 return NULL;
433 }
430 /* Set up the rate scaling to start at selected rate, fall back 434 /* Set up the rate scaling to start at selected rate, fall back
431 * all the way down to 1M in IEEE order, and then spin on 1M */ 435 * all the way down to 1M in IEEE order, and then spin on 1M */
432 if (is_ap) 436 if (is_ap)
@@ -444,35 +448,36 @@ static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap)
444 rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << 448 rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) <<
445 RATE_MCS_ANT_POS; 449 RATE_MCS_ANT_POS;
446 450
447 link_cmd.rs_table[i].rate_n_flags = 451 link_cmd->rs_table[i].rate_n_flags =
448 iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); 452 iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags);
449 r = iwl_get_prev_ieee_rate(r); 453 r = iwl_get_prev_ieee_rate(r);
450 } 454 }
451 455
452 link_cmd.general_params.single_stream_ant_msk = 456 link_cmd->general_params.single_stream_ant_msk =
453 first_antenna(priv->hw_params.valid_tx_ant); 457 first_antenna(priv->hw_params.valid_tx_ant);
454 458
455 link_cmd.general_params.dual_stream_ant_msk = 459 link_cmd->general_params.dual_stream_ant_msk =
456 priv->hw_params.valid_tx_ant & 460 priv->hw_params.valid_tx_ant &
457 ~first_antenna(priv->hw_params.valid_tx_ant); 461 ~first_antenna(priv->hw_params.valid_tx_ant);
458 if (!link_cmd.general_params.dual_stream_ant_msk) { 462 if (!link_cmd->general_params.dual_stream_ant_msk) {
459 link_cmd.general_params.dual_stream_ant_msk = ANT_AB; 463 link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
460 } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { 464 } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
461 link_cmd.general_params.dual_stream_ant_msk = 465 link_cmd->general_params.dual_stream_ant_msk =
462 priv->hw_params.valid_tx_ant; 466 priv->hw_params.valid_tx_ant;
463 } 467 }
464 468
465 link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; 469 link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
466 link_cmd.agg_params.agg_time_limit = 470 link_cmd->agg_params.agg_time_limit =
467 cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); 471 cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF);
468 472
469 /* Update the rate scaling for control frame Tx to AP */ 473 /* Update the rate scaling for control frame Tx to AP */
470 link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; 474 link_cmd->sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id;
471 475
472 ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, 476 ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true);
473 sizeof(link_cmd), &link_cmd);
474 if (ret) 477 if (ret)
475 IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret); 478 IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
479
480 return link_cmd;
476} 481}
477 482
478/* 483/*
@@ -487,6 +492,8 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs)
487{ 492{
488 int ret; 493 int ret;
489 u8 sta_id; 494 u8 sta_id;
495 struct iwl_link_quality_cmd *link_cmd;
496 unsigned long flags;
490 497
491 ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); 498 ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id);
492 if (ret) { 499 if (ret) {
@@ -494,9 +501,23 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs)
494 return ret; 501 return ret;
495 } 502 }
496 503
497 if (init_rs) 504 spin_lock_irqsave(&priv->sta_lock, flags);
505 priv->stations[sta_id].used |= IWL_STA_LOCAL;
506 spin_unlock_irqrestore(&priv->sta_lock, flags);
507
508 if (init_rs) {
498 /* Set up default rate scaling table in device's station table */ 509 /* Set up default rate scaling table in device's station table */
499 iwl_sta_init_lq(priv, addr, false); 510 link_cmd = iwl_sta_init_lq(priv, addr, false);
511 if (!link_cmd) {
512 IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n",
513 addr);
514 return -ENOMEM;
515 }
516 spin_lock_irqsave(&priv->sta_lock, flags);
517 priv->stations[sta_id].lq = link_cmd;
518 spin_unlock_irqrestore(&priv->sta_lock, flags);
519 }
520
500 return 0; 521 return 0;
501} 522}
502EXPORT_SYMBOL(iwl_add_local_station); 523EXPORT_SYMBOL(iwl_add_local_station);
@@ -509,7 +530,8 @@ EXPORT_SYMBOL(iwl_add_local_station);
509static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) 530static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
510{ 531{
511 /* Ucode must be active and driver must be non active */ 532 /* Ucode must be active and driver must be non active */
512 if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) 533 if ((priv->stations[sta_id].used &
534 (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE)
513 IWL_ERR(priv, "removed non active STA %u\n", sta_id); 535 IWL_ERR(priv, "removed non active STA %u\n", sta_id);
514 536
515 priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; 537 priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
@@ -676,8 +698,23 @@ void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force)
676 spin_lock_irqsave(&priv->sta_lock, flags_spin); 698 spin_lock_irqsave(&priv->sta_lock, flags_spin);
677 if (force) { 699 if (force) {
678 IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); 700 IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n");
701 /*
702 * The station entry contains a link to the LQ command. For
703 * all stations managed by mac80211 this memory will be
704 * managed by it also. For local stations (broadcast and
705 * bssid station when in adhoc mode) we need to maintain
706 * this lq command separately. This memory is created when
707 * these stations are added.
708 */
709 for (i = 0; i < priv->hw_params.max_stations; i++) {
710 if (priv->stations[i].used & IWL_STA_LOCAL) {
711 kfree(priv->stations[i].lq);
712 priv->stations[i].lq = NULL;
713 }
714 }
679 priv->num_stations = 0; 715 priv->num_stations = 0;
680 memset(priv->stations, 0, sizeof(priv->stations)); 716 memset(priv->stations, 0, sizeof(priv->stations));
717 cleared = true;
681 } else { 718 } else {
682 for (i = 0; i < priv->hw_params.max_stations; i++) { 719 for (i = 0; i < priv->hw_params.max_stations; i++) {
683 if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { 720 if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
@@ -1207,7 +1244,8 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
1207 BUG_ON(init && (cmd.flags & CMD_ASYNC)); 1244 BUG_ON(init && (cmd.flags & CMD_ASYNC));
1208 1245
1209 ret = iwl_send_cmd(priv, &cmd); 1246 ret = iwl_send_cmd(priv, &cmd);
1210 if (ret || (cmd.flags & CMD_ASYNC)) 1247
1248 if (cmd.flags & CMD_ASYNC)
1211 return ret; 1249 return ret;
1212 1250
1213 if (init) { 1251 if (init) {
@@ -1217,33 +1255,36 @@ int iwl_send_lq_cmd(struct iwl_priv *priv,
1217 priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; 1255 priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
1218 spin_unlock_irqrestore(&priv->sta_lock, flags_spin); 1256 spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
1219 } 1257 }
1220 return 0; 1258 return ret;
1221} 1259}
1222EXPORT_SYMBOL(iwl_send_lq_cmd); 1260EXPORT_SYMBOL(iwl_send_lq_cmd);
1223 1261
1224/** 1262/**
1225 * iwl_add_bcast_station - add broadcast station into station table. 1263 * iwl_add_bcast_station - add broadcast station into station table.
1226 */ 1264 */
1227void iwl_add_bcast_station(struct iwl_priv *priv) 1265int iwl_add_bcast_station(struct iwl_priv *priv)
1228{ 1266{
1229 IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); 1267 IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
1230 iwl_add_local_station(priv, iwl_bcast_addr, true); 1268 return iwl_add_local_station(priv, iwl_bcast_addr, true);
1231} 1269}
1232EXPORT_SYMBOL(iwl_add_bcast_station); 1270EXPORT_SYMBOL(iwl_add_bcast_station);
1233 1271
1234/** 1272/**
1235 * iwl3945_add_bcast_station - add broadcast station into station table. 1273 * iwl3945_add_bcast_station - add broadcast station into station table.
1236 */ 1274 */
1237void iwl3945_add_bcast_station(struct iwl_priv *priv) 1275int iwl3945_add_bcast_station(struct iwl_priv *priv)
1238{ 1276{
1277 int ret;
1278
1239 IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); 1279 IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n");
1240 iwl_add_local_station(priv, iwl_bcast_addr, false); 1280 ret = iwl_add_local_station(priv, iwl_bcast_addr, false);
1241 /* 1281 /*
1242 * It is assumed that when station is added more initialization 1282 * It is assumed that when station is added more initialization
1243 * needs to be done, but for 3945 it is not the case and we can 1283 * needs to be done, but for 3945 it is not the case and we can
1244 * just release station table access right here. 1284 * just release station table access right here.
1245 */ 1285 */
1246 priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; 1286 priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
1287 return ret;
1247 1288
1248} 1289}
1249EXPORT_SYMBOL(iwl3945_add_bcast_station); 1290EXPORT_SYMBOL(iwl3945_add_bcast_station);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 42cd2f4a01cd..b0ed2eb931fd 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -36,6 +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
40 this is for bcast and bssid (when adhoc)
41 stations */
39 42
40 43
41/** 44/**
@@ -57,8 +60,8 @@ void iwl_update_tkip_key(struct iwl_priv *priv,
57 struct ieee80211_key_conf *keyconf, 60 struct ieee80211_key_conf *keyconf,
58 const u8 *addr, u32 iv32, u16 *phase1key); 61 const u8 *addr, u32 iv32, u16 *phase1key);
59 62
60void iwl_add_bcast_station(struct iwl_priv *priv); 63int iwl_add_bcast_station(struct iwl_priv *priv);
61void iwl3945_add_bcast_station(struct iwl_priv *priv); 64int iwl3945_add_bcast_station(struct iwl_priv *priv);
62void iwl_restore_stations(struct iwl_priv *priv); 65void iwl_restore_stations(struct iwl_priv *priv);
63void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); 66void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force);
64int iwl_get_free_ucode_key_index(struct iwl_priv *priv); 67int iwl_get_free_ucode_key_index(struct iwl_priv *priv);