diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 91 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.h | 7 |
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 | } |
419 | EXPORT_SYMBOL(iwl_add_station_common); | 419 | EXPORT_SYMBOL(iwl_add_station_common); |
420 | 420 | ||
421 | static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) | 421 | static 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 | } |
502 | EXPORT_SYMBOL(iwl_add_local_station); | 523 | EXPORT_SYMBOL(iwl_add_local_station); |
@@ -509,7 +530,8 @@ EXPORT_SYMBOL(iwl_add_local_station); | |||
509 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) | 530 | static 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 | } |
1222 | EXPORT_SYMBOL(iwl_send_lq_cmd); | 1260 | EXPORT_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 | */ |
1227 | void iwl_add_bcast_station(struct iwl_priv *priv) | 1265 | int 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 | } |
1232 | EXPORT_SYMBOL(iwl_add_bcast_station); | 1270 | EXPORT_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 | */ |
1237 | void iwl3945_add_bcast_station(struct iwl_priv *priv) | 1275 | int 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 | } |
1249 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | 1290 | EXPORT_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 | ||
60 | void iwl_add_bcast_station(struct iwl_priv *priv); | 63 | int iwl_add_bcast_station(struct iwl_priv *priv); |
61 | void iwl3945_add_bcast_station(struct iwl_priv *priv); | 64 | int iwl3945_add_bcast_station(struct iwl_priv *priv); |
62 | void iwl_restore_stations(struct iwl_priv *priv); | 65 | void iwl_restore_stations(struct iwl_priv *priv); |
63 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); | 66 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force); |
64 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); | 67 | int iwl_get_free_ucode_key_index(struct iwl_priv *priv); |