diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 456 |
1 files changed, 210 insertions, 246 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index db934476b5e9..85ed235ac901 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -35,62 +35,6 @@ | |||
35 | #include "iwl-core.h" | 35 | #include "iwl-core.h" |
36 | #include "iwl-sta.h" | 36 | #include "iwl-sta.h" |
37 | 37 | ||
38 | u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) | ||
39 | { | ||
40 | int i; | ||
41 | int start = 0; | ||
42 | int ret = IWL_INVALID_STATION; | ||
43 | unsigned long flags; | ||
44 | |||
45 | if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || | ||
46 | (priv->iw_mode == NL80211_IFTYPE_AP)) | ||
47 | start = IWL_STA_ID; | ||
48 | |||
49 | if (is_broadcast_ether_addr(addr)) | ||
50 | return priv->hw_params.bcast_sta_id; | ||
51 | |||
52 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
53 | for (i = start; i < priv->hw_params.max_stations; i++) | ||
54 | if (priv->stations[i].used && | ||
55 | (!compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
56 | addr))) { | ||
57 | ret = i; | ||
58 | goto out; | ||
59 | } | ||
60 | |||
61 | IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", | ||
62 | addr, priv->num_stations); | ||
63 | |||
64 | out: | ||
65 | /* | ||
66 | * It may be possible that more commands interacting with stations | ||
67 | * arrive before we completed processing the adding of | ||
68 | * station | ||
69 | */ | ||
70 | if (ret != IWL_INVALID_STATION && | ||
71 | (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || | ||
72 | ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && | ||
73 | (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { | ||
74 | IWL_ERR(priv, "Requested station info for sta %d before ready.\n", | ||
75 | ret); | ||
76 | ret = IWL_INVALID_STATION; | ||
77 | } | ||
78 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
79 | return ret; | ||
80 | } | ||
81 | EXPORT_SYMBOL(iwl_find_station); | ||
82 | |||
83 | int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | ||
84 | { | ||
85 | if (priv->iw_mode == NL80211_IFTYPE_STATION) { | ||
86 | return IWL_AP_ID; | ||
87 | } else { | ||
88 | u8 *da = ieee80211_get_DA(hdr); | ||
89 | return iwl_find_station(priv, da); | ||
90 | } | ||
91 | } | ||
92 | EXPORT_SYMBOL(iwl_get_ra_sta_id); | ||
93 | |||
94 | /* priv->sta_lock must be held */ | 38 | /* priv->sta_lock must be held */ |
95 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) | 39 | static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) |
96 | { | 40 | { |
@@ -340,10 +284,12 @@ static u8 iwl_prep_station(struct iwl_priv *priv, const u8 *addr, | |||
340 | station->sta.sta.sta_id = sta_id; | 284 | station->sta.sta.sta_id = sta_id; |
341 | station->sta.station_flags = 0; | 285 | station->sta.station_flags = 0; |
342 | 286 | ||
343 | /* BCAST station and IBSS stations do not work in HT mode */ | 287 | /* |
344 | if (sta_id != priv->hw_params.bcast_sta_id && | 288 | * OK to call unconditionally, since local stations (IBSS BSSID |
345 | priv->iw_mode != NL80211_IFTYPE_ADHOC) | 289 | * STA and broadcast STA) pass in a NULL ht_info, and mac80211 |
346 | iwl_set_ht_add_station(priv, sta_id, ht_info); | 290 | * doesn't allow HT IBSS. |
291 | */ | ||
292 | iwl_set_ht_add_station(priv, sta_id, ht_info); | ||
347 | 293 | ||
348 | /* 3945 only */ | 294 | /* 3945 only */ |
349 | rate = (priv->band == IEEE80211_BAND_5GHZ) ? | 295 | rate = (priv->band == IEEE80211_BAND_5GHZ) ? |
@@ -418,20 +364,21 @@ int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, | |||
418 | } | 364 | } |
419 | EXPORT_SYMBOL(iwl_add_station_common); | 365 | EXPORT_SYMBOL(iwl_add_station_common); |
420 | 366 | ||
421 | static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) | 367 | static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, |
368 | u8 sta_id) | ||
422 | { | 369 | { |
423 | int i, r; | 370 | int i, r; |
424 | struct iwl_link_quality_cmd link_cmd = { | 371 | struct iwl_link_quality_cmd *link_cmd; |
425 | .reserved1 = 0, | ||
426 | }; | ||
427 | u32 rate_flags; | 372 | u32 rate_flags; |
428 | int ret = 0; | ||
429 | 373 | ||
374 | link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL); | ||
375 | if (!link_cmd) { | ||
376 | IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n"); | ||
377 | return NULL; | ||
378 | } | ||
430 | /* Set up the rate scaling to start at selected rate, fall back | 379 | /* 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 */ | 380 | * all the way down to 1M in IEEE order, and then spin on 1M */ |
432 | if (is_ap) | 381 | if (priv->band == IEEE80211_BAND_5GHZ) |
433 | r = IWL_RATE_54M_INDEX; | ||
434 | else if (priv->band == IEEE80211_BAND_5GHZ) | ||
435 | r = IWL_RATE_6M_INDEX; | 382 | r = IWL_RATE_6M_INDEX; |
436 | else | 383 | else |
437 | r = IWL_RATE_1M_INDEX; | 384 | r = IWL_RATE_1M_INDEX; |
@@ -444,49 +391,48 @@ 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) << | 391 | rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << |
445 | RATE_MCS_ANT_POS; | 392 | RATE_MCS_ANT_POS; |
446 | 393 | ||
447 | link_cmd.rs_table[i].rate_n_flags = | 394 | link_cmd->rs_table[i].rate_n_flags = |
448 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); | 395 | iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); |
449 | r = iwl_get_prev_ieee_rate(r); | 396 | r = iwl_get_prev_ieee_rate(r); |
450 | } | 397 | } |
451 | 398 | ||
452 | link_cmd.general_params.single_stream_ant_msk = | 399 | link_cmd->general_params.single_stream_ant_msk = |
453 | first_antenna(priv->hw_params.valid_tx_ant); | 400 | first_antenna(priv->hw_params.valid_tx_ant); |
454 | 401 | ||
455 | link_cmd.general_params.dual_stream_ant_msk = | 402 | link_cmd->general_params.dual_stream_ant_msk = |
456 | priv->hw_params.valid_tx_ant & | 403 | priv->hw_params.valid_tx_ant & |
457 | ~first_antenna(priv->hw_params.valid_tx_ant); | 404 | ~first_antenna(priv->hw_params.valid_tx_ant); |
458 | if (!link_cmd.general_params.dual_stream_ant_msk) { | 405 | if (!link_cmd->general_params.dual_stream_ant_msk) { |
459 | link_cmd.general_params.dual_stream_ant_msk = ANT_AB; | 406 | link_cmd->general_params.dual_stream_ant_msk = ANT_AB; |
460 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { | 407 | } else if (num_of_ant(priv->hw_params.valid_tx_ant) == 2) { |
461 | link_cmd.general_params.dual_stream_ant_msk = | 408 | link_cmd->general_params.dual_stream_ant_msk = |
462 | priv->hw_params.valid_tx_ant; | 409 | priv->hw_params.valid_tx_ant; |
463 | } | 410 | } |
464 | 411 | ||
465 | link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; | 412 | link_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; |
466 | link_cmd.agg_params.agg_time_limit = | 413 | link_cmd->agg_params.agg_time_limit = |
467 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); | 414 | cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); |
468 | 415 | ||
469 | /* Update the rate scaling for control frame Tx to AP */ | 416 | link_cmd->sta_id = sta_id; |
470 | link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; | ||
471 | 417 | ||
472 | ret = iwl_send_cmd_pdu(priv, REPLY_TX_LINK_QUALITY_CMD, | 418 | return link_cmd; |
473 | sizeof(link_cmd), &link_cmd); | ||
474 | if (ret) | ||
475 | IWL_ERR(priv, "REPLY_TX_LINK_QUALITY_CMD failed (%d)\n", ret); | ||
476 | } | 419 | } |
477 | 420 | ||
478 | /* | 421 | /* |
479 | * iwl_add_local_stations - Add stations not requested by mac80211 | 422 | * iwl_add_bssid_station - Add the special IBSS BSSID station |
480 | * | ||
481 | * This will be either the broadcast station or the bssid station needed by | ||
482 | * ad-hoc. | ||
483 | * | 423 | * |
484 | * Function sleeps. | 424 | * Function sleeps. |
485 | */ | 425 | */ |
486 | int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) | 426 | int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, |
427 | u8 *sta_id_r) | ||
487 | { | 428 | { |
488 | int ret; | 429 | int ret; |
489 | u8 sta_id; | 430 | u8 sta_id; |
431 | struct iwl_link_quality_cmd *link_cmd; | ||
432 | unsigned long flags; | ||
433 | |||
434 | if (*sta_id_r) | ||
435 | *sta_id_r = IWL_INVALID_STATION; | ||
490 | 436 | ||
491 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); | 437 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); |
492 | if (ret) { | 438 | if (ret) { |
@@ -494,12 +440,34 @@ int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) | |||
494 | return ret; | 440 | return ret; |
495 | } | 441 | } |
496 | 442 | ||
497 | if (init_rs) | 443 | if (sta_id_r) |
444 | *sta_id_r = sta_id; | ||
445 | |||
446 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
447 | priv->stations[sta_id].used |= IWL_STA_LOCAL; | ||
448 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
449 | |||
450 | if (init_rs) { | ||
498 | /* Set up default rate scaling table in device's station table */ | 451 | /* Set up default rate scaling table in device's station table */ |
499 | iwl_sta_init_lq(priv, addr, false); | 452 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); |
453 | if (!link_cmd) { | ||
454 | IWL_ERR(priv, "Unable to initialize rate scaling for station %pM.\n", | ||
455 | addr); | ||
456 | return -ENOMEM; | ||
457 | } | ||
458 | |||
459 | ret = iwl_send_lq_cmd(priv, link_cmd, CMD_SYNC, true); | ||
460 | if (ret) | ||
461 | IWL_ERR(priv, "Link quality command failed (%d)\n", ret); | ||
462 | |||
463 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
464 | priv->stations[sta_id].lq = link_cmd; | ||
465 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
466 | } | ||
467 | |||
500 | return 0; | 468 | return 0; |
501 | } | 469 | } |
502 | EXPORT_SYMBOL(iwl_add_local_station); | 470 | EXPORT_SYMBOL(iwl_add_bssid_station); |
503 | 471 | ||
504 | /** | 472 | /** |
505 | * iwl_sta_ucode_deactivate - deactivate ucode status for a station | 473 | * iwl_sta_ucode_deactivate - deactivate ucode status for a station |
@@ -509,7 +477,8 @@ EXPORT_SYMBOL(iwl_add_local_station); | |||
509 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) | 477 | static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id) |
510 | { | 478 | { |
511 | /* Ucode must be active and driver must be non active */ | 479 | /* Ucode must be active and driver must be non active */ |
512 | if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) | 480 | if ((priv->stations[sta_id].used & |
481 | (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) != IWL_STA_UCODE_ACTIVE) | ||
513 | IWL_ERR(priv, "removed non active STA %u\n", sta_id); | 482 | IWL_ERR(priv, "removed non active STA %u\n", sta_id); |
514 | 483 | ||
515 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; | 484 | priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; |
@@ -574,18 +543,16 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
574 | /** | 543 | /** |
575 | * iwl_remove_station - Remove driver's knowledge of station. | 544 | * iwl_remove_station - Remove driver's knowledge of station. |
576 | */ | 545 | */ |
577 | static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) | 546 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, |
547 | const u8 *addr) | ||
578 | { | 548 | { |
579 | int sta_id = IWL_INVALID_STATION; | ||
580 | int i, ret = -EINVAL; | ||
581 | unsigned long flags; | ||
582 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | ||
583 | struct iwl_station_entry *station; | 549 | struct iwl_station_entry *station; |
550 | unsigned long flags; | ||
584 | 551 | ||
585 | if (!iwl_is_ready(priv)) { | 552 | if (!iwl_is_ready(priv)) { |
586 | IWL_DEBUG_INFO(priv, | 553 | IWL_DEBUG_INFO(priv, |
587 | "Unable to remove station %pM, device not ready.\n", | 554 | "Unable to remove station %pM, device not ready.\n", |
588 | sta->addr); | 555 | addr); |
589 | /* | 556 | /* |
590 | * It is typical for stations to be removed when we are | 557 | * It is typical for stations to be removed when we are |
591 | * going down. Return success since device will be down | 558 | * going down. Return success since device will be down |
@@ -594,37 +561,30 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) | |||
594 | return 0; | 561 | return 0; |
595 | } | 562 | } |
596 | 563 | ||
597 | spin_lock_irqsave(&priv->sta_lock, flags); | 564 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", |
598 | 565 | sta_id, addr); | |
599 | if (is_ap) | ||
600 | sta_id = IWL_AP_ID; | ||
601 | else | ||
602 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) | ||
603 | if (priv->stations[i].used && | ||
604 | !compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
605 | sta->addr)) { | ||
606 | sta_id = i; | ||
607 | break; | ||
608 | } | ||
609 | 566 | ||
610 | if (unlikely(sta_id == IWL_INVALID_STATION)) | 567 | if (WARN_ON(sta_id == IWL_INVALID_STATION)) |
611 | goto out; | 568 | return -EINVAL; |
612 | 569 | ||
613 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", | 570 | spin_lock_irqsave(&priv->sta_lock, flags); |
614 | sta_id, sta->addr); | ||
615 | 571 | ||
616 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { | 572 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { |
617 | IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", | 573 | IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", |
618 | sta->addr); | 574 | addr); |
619 | goto out; | 575 | goto out_err; |
620 | } | 576 | } |
621 | 577 | ||
622 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | 578 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { |
623 | IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", | 579 | IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", |
624 | sta->addr); | 580 | addr); |
625 | goto out; | 581 | goto out_err; |
626 | } | 582 | } |
627 | 583 | ||
584 | if (priv->stations[sta_id].used & IWL_STA_LOCAL) { | ||
585 | kfree(priv->stations[sta_id].lq); | ||
586 | priv->stations[sta_id].lq = NULL; | ||
587 | } | ||
628 | 588 | ||
629 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; | 589 | priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; |
630 | 590 | ||
@@ -635,56 +595,35 @@ static int iwl_remove_station(struct iwl_priv *priv, struct ieee80211_sta *sta) | |||
635 | station = &priv->stations[sta_id]; | 595 | station = &priv->stations[sta_id]; |
636 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 596 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
637 | 597 | ||
638 | ret = iwl_send_remove_station(priv, station); | 598 | return iwl_send_remove_station(priv, station); |
639 | return ret; | 599 | out_err: |
640 | out: | ||
641 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 600 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
642 | return ret; | 601 | return -EINVAL; |
643 | } | 602 | } |
603 | EXPORT_SYMBOL_GPL(iwl_remove_station); | ||
644 | 604 | ||
645 | /** | 605 | /** |
646 | * iwl_clear_ucode_stations() - clear entire station table driver and/or ucode | 606 | * iwl_clear_ucode_stations - clear ucode station table bits |
647 | * @priv: | 607 | * |
648 | * @force: If set then the uCode station table needs to be cleared here. If | 608 | * This function clears all the bits in the driver indicating |
649 | * not set then the uCode station table has already been cleared, | 609 | * which stations are active in the ucode. Call when something |
650 | * for example after sending it a RXON command without ASSOC bit | 610 | * other than explicit station management would cause this in |
651 | * set, and we just need to change driver state here. | 611 | * the ucode, e.g. unassociated RXON. |
652 | */ | 612 | */ |
653 | void iwl_clear_ucode_stations(struct iwl_priv *priv, bool force) | 613 | void iwl_clear_ucode_stations(struct iwl_priv *priv) |
654 | { | 614 | { |
655 | int i; | 615 | int i; |
656 | unsigned long flags_spin; | 616 | unsigned long flags_spin; |
657 | bool cleared = false; | 617 | bool cleared = false; |
658 | 618 | ||
659 | IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver%s\n", | 619 | IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n"); |
660 | force ? " and ucode" : ""); | ||
661 | |||
662 | if (force) { | ||
663 | if (!iwl_is_ready(priv)) { | ||
664 | /* | ||
665 | * If device is not ready at this point the station | ||
666 | * table is likely already empty (uCode not ready | ||
667 | * to receive station requests) or will soon be | ||
668 | * due to interface going down. | ||
669 | */ | ||
670 | IWL_DEBUG_INFO(priv, "Unable to remove stations from device - device not ready\n"); | ||
671 | } else { | ||
672 | iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL); | ||
673 | } | ||
674 | } | ||
675 | 620 | ||
676 | spin_lock_irqsave(&priv->sta_lock, flags_spin); | 621 | spin_lock_irqsave(&priv->sta_lock, flags_spin); |
677 | if (force) { | 622 | for (i = 0; i < priv->hw_params.max_stations; i++) { |
678 | IWL_DEBUG_INFO(priv, "Clearing all station information in driver\n"); | 623 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { |
679 | priv->num_stations = 0; | 624 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); |
680 | memset(priv->stations, 0, sizeof(priv->stations)); | 625 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; |
681 | } else { | 626 | cleared = true; |
682 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
683 | if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) { | ||
684 | IWL_DEBUG_INFO(priv, "Clearing ucode active for station %d\n", i); | ||
685 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
686 | cleared = true; | ||
687 | } | ||
688 | } | 627 | } |
689 | } | 628 | } |
690 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 629 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
@@ -1027,18 +966,23 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, | |||
1027 | 966 | ||
1028 | void iwl_update_tkip_key(struct iwl_priv *priv, | 967 | void iwl_update_tkip_key(struct iwl_priv *priv, |
1029 | struct ieee80211_key_conf *keyconf, | 968 | struct ieee80211_key_conf *keyconf, |
1030 | const u8 *addr, u32 iv32, u16 *phase1key) | 969 | struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) |
1031 | { | 970 | { |
1032 | u8 sta_id = IWL_INVALID_STATION; | 971 | u8 sta_id; |
1033 | unsigned long flags; | 972 | unsigned long flags; |
1034 | int i; | 973 | int i; |
1035 | 974 | ||
1036 | sta_id = iwl_find_station(priv, addr); | 975 | if (sta) { |
1037 | if (sta_id == IWL_INVALID_STATION) { | 976 | sta_id = iwl_sta_id(sta); |
1038 | IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", | 977 | |
1039 | addr); | 978 | if (sta_id == IWL_INVALID_STATION) { |
1040 | return; | 979 | IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", |
1041 | } | 980 | sta->addr); |
981 | return; | ||
982 | } | ||
983 | } else | ||
984 | sta_id = priv->hw_params.bcast_sta_id; | ||
985 | |||
1042 | 986 | ||
1043 | if (iwl_scan_cancel(priv)) { | 987 | if (iwl_scan_cancel(priv)) { |
1044 | /* cancel scan failed, just live w/ bad key and rely | 988 | /* cancel scan failed, just live w/ bad key and rely |
@@ -1178,6 +1122,39 @@ static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, | |||
1178 | #endif | 1122 | #endif |
1179 | 1123 | ||
1180 | /** | 1124 | /** |
1125 | * is_lq_table_valid() - Test one aspect of LQ cmd for validity | ||
1126 | * | ||
1127 | * It sometimes happens when a HT rate has been in use and we | ||
1128 | * loose connectivity with AP then mac80211 will first tell us that the | ||
1129 | * current channel is not HT anymore before removing the station. In such a | ||
1130 | * scenario the RXON flags will be updated to indicate we are not | ||
1131 | * communicating HT anymore, but the LQ command may still contain HT rates. | ||
1132 | * Test for this to prevent driver from sending LQ command between the time | ||
1133 | * RXON flags are updated and when LQ command is updated. | ||
1134 | */ | ||
1135 | static bool is_lq_table_valid(struct iwl_priv *priv, | ||
1136 | struct iwl_link_quality_cmd *lq) | ||
1137 | { | ||
1138 | int i; | ||
1139 | struct iwl_ht_config *ht_conf = &priv->current_ht_config; | ||
1140 | |||
1141 | if (ht_conf->is_ht) | ||
1142 | return true; | ||
1143 | |||
1144 | IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n", | ||
1145 | priv->active_rxon.channel); | ||
1146 | for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { | ||
1147 | if (le32_to_cpu(lq->rs_table[i].rate_n_flags) & RATE_MCS_HT_MSK) { | ||
1148 | IWL_DEBUG_INFO(priv, | ||
1149 | "index %d of LQ expects HT channel\n", | ||
1150 | i); | ||
1151 | return false; | ||
1152 | } | ||
1153 | } | ||
1154 | return true; | ||
1155 | } | ||
1156 | |||
1157 | /** | ||
1181 | * iwl_send_lq_cmd() - Send link quality command | 1158 | * iwl_send_lq_cmd() - Send link quality command |
1182 | * @init: This command is sent as part of station initialization right | 1159 | * @init: This command is sent as part of station initialization right |
1183 | * after station has been added. | 1160 | * after station has been added. |
@@ -1206,8 +1183,12 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
1206 | iwl_dump_lq_cmd(priv, lq); | 1183 | iwl_dump_lq_cmd(priv, lq); |
1207 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); | 1184 | BUG_ON(init && (cmd.flags & CMD_ASYNC)); |
1208 | 1185 | ||
1209 | ret = iwl_send_cmd(priv, &cmd); | 1186 | if (is_lq_table_valid(priv, lq)) |
1210 | if (ret || (cmd.flags & CMD_ASYNC)) | 1187 | ret = iwl_send_cmd(priv, &cmd); |
1188 | else | ||
1189 | ret = -EINVAL; | ||
1190 | |||
1191 | if (cmd.flags & CMD_ASYNC) | ||
1211 | return ret; | 1192 | return ret; |
1212 | 1193 | ||
1213 | if (init) { | 1194 | if (init) { |
@@ -1217,92 +1198,72 @@ int iwl_send_lq_cmd(struct iwl_priv *priv, | |||
1217 | priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | 1198 | priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; |
1218 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); | 1199 | spin_unlock_irqrestore(&priv->sta_lock, flags_spin); |
1219 | } | 1200 | } |
1220 | return 0; | 1201 | return ret; |
1221 | } | 1202 | } |
1222 | EXPORT_SYMBOL(iwl_send_lq_cmd); | 1203 | EXPORT_SYMBOL(iwl_send_lq_cmd); |
1223 | 1204 | ||
1224 | /** | 1205 | /** |
1225 | * iwl_add_bcast_station - add broadcast station into station table. | 1206 | * iwl_alloc_bcast_station - add broadcast station into driver's station table. |
1207 | * | ||
1208 | * This adds the broadcast station into the driver's station table | ||
1209 | * and marks it driver active, so that it will be restored to the | ||
1210 | * device at the next best time. | ||
1226 | */ | 1211 | */ |
1227 | void iwl_add_bcast_station(struct iwl_priv *priv) | 1212 | int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq) |
1228 | { | 1213 | { |
1229 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | 1214 | struct iwl_link_quality_cmd *link_cmd; |
1230 | iwl_add_local_station(priv, iwl_bcast_addr, true); | 1215 | unsigned long flags; |
1231 | } | 1216 | u8 sta_id; |
1232 | EXPORT_SYMBOL(iwl_add_bcast_station); | ||
1233 | 1217 | ||
1234 | /** | 1218 | spin_lock_irqsave(&priv->sta_lock, flags); |
1235 | * iwl3945_add_bcast_station - add broadcast station into station table. | 1219 | sta_id = iwl_prep_station(priv, iwl_bcast_addr, false, NULL); |
1236 | */ | 1220 | if (sta_id == IWL_INVALID_STATION) { |
1237 | void iwl3945_add_bcast_station(struct iwl_priv *priv) | 1221 | IWL_ERR(priv, "Unable to prepare broadcast station\n"); |
1238 | { | 1222 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1239 | IWL_DEBUG_INFO(priv, "Adding broadcast station to station table\n"); | ||
1240 | iwl_add_local_station(priv, iwl_bcast_addr, false); | ||
1241 | /* | ||
1242 | * 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 | ||
1244 | * just release station table access right here. | ||
1245 | */ | ||
1246 | priv->stations[priv->hw_params.bcast_sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; | ||
1247 | 1223 | ||
1248 | } | 1224 | return -EINVAL; |
1249 | EXPORT_SYMBOL(iwl3945_add_bcast_station); | 1225 | } |
1250 | 1226 | ||
1251 | /** | 1227 | priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE; |
1252 | * iwl_get_sta_id - Find station's index within station table | 1228 | priv->stations[sta_id].used |= IWL_STA_BCAST; |
1253 | * | 1229 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1254 | * If new IBSS station, create new entry in station table | ||
1255 | */ | ||
1256 | int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) | ||
1257 | { | ||
1258 | int sta_id; | ||
1259 | __le16 fc = hdr->frame_control; | ||
1260 | 1230 | ||
1261 | /* If this frame is broadcast or management, use broadcast station id */ | 1231 | if (init_lq) { |
1262 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) | 1232 | link_cmd = iwl_sta_alloc_lq(priv, sta_id); |
1263 | return priv->hw_params.bcast_sta_id; | 1233 | if (!link_cmd) { |
1234 | IWL_ERR(priv, | ||
1235 | "Unable to initialize rate scaling for bcast station.\n"); | ||
1236 | return -ENOMEM; | ||
1237 | } | ||
1264 | 1238 | ||
1265 | switch (priv->iw_mode) { | 1239 | spin_lock_irqsave(&priv->sta_lock, flags); |
1240 | priv->stations[sta_id].lq = link_cmd; | ||
1241 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1242 | } | ||
1266 | 1243 | ||
1267 | /* If we are a client station in a BSS network, use the special | 1244 | return 0; |
1268 | * AP station entry (that's the only station we communicate with) */ | 1245 | } |
1269 | case NL80211_IFTYPE_STATION: | 1246 | EXPORT_SYMBOL_GPL(iwl_alloc_bcast_station); |
1270 | /* | ||
1271 | * If addition of station not complete yet, which means | ||
1272 | * that rate scaling has not been initialized, then return | ||
1273 | * the broadcast station. | ||
1274 | */ | ||
1275 | if (!(priv->stations[IWL_AP_ID].used & IWL_STA_UCODE_ACTIVE)) | ||
1276 | return priv->hw_params.bcast_sta_id; | ||
1277 | return IWL_AP_ID; | ||
1278 | |||
1279 | /* If we are an AP, then find the station, or use BCAST */ | ||
1280 | case NL80211_IFTYPE_AP: | ||
1281 | sta_id = iwl_find_station(priv, hdr->addr1); | ||
1282 | if (sta_id != IWL_INVALID_STATION) | ||
1283 | return sta_id; | ||
1284 | return priv->hw_params.bcast_sta_id; | ||
1285 | |||
1286 | /* If this frame is going out to an IBSS network, find the station, | ||
1287 | * or create a new station table entry */ | ||
1288 | case NL80211_IFTYPE_ADHOC: | ||
1289 | sta_id = iwl_find_station(priv, hdr->addr1); | ||
1290 | if (sta_id != IWL_INVALID_STATION) | ||
1291 | return sta_id; | ||
1292 | |||
1293 | IWL_DEBUG_DROP(priv, "Station %pM not in station map. " | ||
1294 | "Defaulting to broadcast...\n", | ||
1295 | hdr->addr1); | ||
1296 | iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); | ||
1297 | return priv->hw_params.bcast_sta_id; | ||
1298 | 1247 | ||
1299 | default: | 1248 | void iwl_dealloc_bcast_station(struct iwl_priv *priv) |
1300 | IWL_WARN(priv, "Unknown mode of operation: %d\n", | 1249 | { |
1301 | priv->iw_mode); | 1250 | unsigned long flags; |
1302 | return priv->hw_params.bcast_sta_id; | 1251 | int i; |
1252 | |||
1253 | spin_lock_irqsave(&priv->sta_lock, flags); | ||
1254 | for (i = 0; i < priv->hw_params.max_stations; i++) { | ||
1255 | if (!(priv->stations[i].used & IWL_STA_BCAST)) | ||
1256 | continue; | ||
1257 | |||
1258 | priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE; | ||
1259 | priv->num_stations--; | ||
1260 | BUG_ON(priv->num_stations < 0); | ||
1261 | kfree(priv->stations[i].lq); | ||
1262 | priv->stations[i].lq = NULL; | ||
1303 | } | 1263 | } |
1264 | spin_unlock_irqrestore(&priv->sta_lock, flags); | ||
1304 | } | 1265 | } |
1305 | EXPORT_SYMBOL(iwl_get_sta_id); | 1266 | EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); |
1306 | 1267 | ||
1307 | /** | 1268 | /** |
1308 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table | 1269 | * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table |
@@ -1322,13 +1283,13 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) | |||
1322 | } | 1283 | } |
1323 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); | 1284 | EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); |
1324 | 1285 | ||
1325 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, | 1286 | int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, |
1326 | const u8 *addr, int tid, u16 ssn) | 1287 | int tid, u16 ssn) |
1327 | { | 1288 | { |
1328 | unsigned long flags; | 1289 | unsigned long flags; |
1329 | int sta_id; | 1290 | int sta_id; |
1330 | 1291 | ||
1331 | sta_id = iwl_find_station(priv, addr); | 1292 | sta_id = iwl_sta_id(sta); |
1332 | if (sta_id == IWL_INVALID_STATION) | 1293 | if (sta_id == IWL_INVALID_STATION) |
1333 | return -ENXIO; | 1294 | return -ENXIO; |
1334 | 1295 | ||
@@ -1341,16 +1302,17 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, | |||
1341 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 1302 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
1342 | 1303 | ||
1343 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, | 1304 | return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, |
1344 | CMD_ASYNC); | 1305 | CMD_ASYNC); |
1345 | } | 1306 | } |
1346 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); | 1307 | EXPORT_SYMBOL(iwl_sta_rx_agg_start); |
1347 | 1308 | ||
1348 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) | 1309 | int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, |
1310 | int tid) | ||
1349 | { | 1311 | { |
1350 | unsigned long flags; | 1312 | unsigned long flags; |
1351 | int sta_id; | 1313 | int sta_id; |
1352 | 1314 | ||
1353 | sta_id = iwl_find_station(priv, addr); | 1315 | sta_id = iwl_sta_id(sta); |
1354 | if (sta_id == IWL_INVALID_STATION) { | 1316 | if (sta_id == IWL_INVALID_STATION) { |
1355 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); | 1317 | IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); |
1356 | return -ENXIO; | 1318 | return -ENXIO; |
@@ -1402,14 +1364,16 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1402 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | 1364 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); |
1403 | 1365 | ||
1404 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, | 1366 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, |
1405 | struct ieee80211_vif *vif, | 1367 | struct ieee80211_vif *vif, |
1406 | struct ieee80211_sta *sta) | 1368 | struct ieee80211_sta *sta) |
1407 | { | 1369 | { |
1408 | int ret; | ||
1409 | struct iwl_priv *priv = hw->priv; | 1370 | struct iwl_priv *priv = hw->priv; |
1371 | struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; | ||
1372 | int ret; | ||
1373 | |||
1410 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", | 1374 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", |
1411 | sta->addr); | 1375 | sta->addr); |
1412 | ret = iwl_remove_station(priv, sta); | 1376 | ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); |
1413 | if (ret) | 1377 | if (ret) |
1414 | IWL_ERR(priv, "Error removing station %pM\n", | 1378 | IWL_ERR(priv, "Error removing station %pM\n", |
1415 | sta->addr); | 1379 | sta->addr); |