diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-sta.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-sta.c | 61 |
1 files changed, 28 insertions, 33 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index e95282b93c3a..d1986dedc863 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c | |||
@@ -462,26 +462,33 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, | |||
462 | } | 462 | } |
463 | 463 | ||
464 | /* | 464 | /* |
465 | * iwl_add_local_stations - Add stations not requested by mac80211 | 465 | * iwl_add_local_station - Add stations not requested by mac80211 |
466 | * | 466 | * |
467 | * This will be either the broadcast station or the bssid station needed by | 467 | * This will be either the broadcast station or the bssid station needed by |
468 | * ad-hoc. | 468 | * ad-hoc. |
469 | * | 469 | * |
470 | * Function sleeps. | 470 | * Function sleeps. |
471 | */ | 471 | */ |
472 | int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) | 472 | int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, |
473 | u8 *sta_id_r) | ||
473 | { | 474 | { |
474 | int ret; | 475 | int ret; |
475 | u8 sta_id; | 476 | u8 sta_id; |
476 | struct iwl_link_quality_cmd *link_cmd; | 477 | struct iwl_link_quality_cmd *link_cmd; |
477 | unsigned long flags; | 478 | unsigned long flags; |
478 | 479 | ||
480 | if (*sta_id_r) | ||
481 | *sta_id_r = IWL_INVALID_STATION; | ||
482 | |||
479 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); | 483 | ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); |
480 | if (ret) { | 484 | if (ret) { |
481 | IWL_ERR(priv, "Unable to add station %pM\n", addr); | 485 | IWL_ERR(priv, "Unable to add station %pM\n", addr); |
482 | return ret; | 486 | return ret; |
483 | } | 487 | } |
484 | 488 | ||
489 | if (sta_id_r) | ||
490 | *sta_id_r = sta_id; | ||
491 | |||
485 | spin_lock_irqsave(&priv->sta_lock, flags); | 492 | spin_lock_irqsave(&priv->sta_lock, flags); |
486 | priv->stations[sta_id].used |= IWL_STA_LOCAL; | 493 | priv->stations[sta_id].used |= IWL_STA_LOCAL; |
487 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 494 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
@@ -582,13 +589,11 @@ static int iwl_send_remove_station(struct iwl_priv *priv, | |||
582 | /** | 589 | /** |
583 | * iwl_remove_station - Remove driver's knowledge of station. | 590 | * iwl_remove_station - Remove driver's knowledge of station. |
584 | */ | 591 | */ |
585 | int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) | 592 | int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, |
593 | const u8 *addr) | ||
586 | { | 594 | { |
587 | int sta_id = IWL_INVALID_STATION; | ||
588 | int i, ret = -EINVAL; | ||
589 | unsigned long flags; | ||
590 | bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; | ||
591 | struct iwl_station_entry *station; | 595 | struct iwl_station_entry *station; |
596 | unsigned long flags; | ||
592 | 597 | ||
593 | if (!iwl_is_ready(priv)) { | 598 | if (!iwl_is_ready(priv)) { |
594 | IWL_DEBUG_INFO(priv, | 599 | IWL_DEBUG_INFO(priv, |
@@ -602,35 +607,24 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) | |||
602 | return 0; | 607 | return 0; |
603 | } | 608 | } |
604 | 609 | ||
605 | spin_lock_irqsave(&priv->sta_lock, flags); | 610 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", |
606 | 611 | sta_id, addr); | |
607 | if (is_ap) | ||
608 | sta_id = IWL_AP_ID; | ||
609 | else | ||
610 | for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) | ||
611 | if (priv->stations[i].used && | ||
612 | !compare_ether_addr(priv->stations[i].sta.sta.addr, | ||
613 | addr)) { | ||
614 | sta_id = i; | ||
615 | break; | ||
616 | } | ||
617 | 612 | ||
618 | if (unlikely(sta_id == IWL_INVALID_STATION)) | 613 | if (WARN_ON(sta_id == IWL_INVALID_STATION)) |
619 | goto out; | 614 | return -EINVAL; |
620 | 615 | ||
621 | IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", | 616 | spin_lock_irqsave(&priv->sta_lock, flags); |
622 | sta_id, addr); | ||
623 | 617 | ||
624 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { | 618 | if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { |
625 | IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", | 619 | IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", |
626 | addr); | 620 | addr); |
627 | goto out; | 621 | goto out_err; |
628 | } | 622 | } |
629 | 623 | ||
630 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { | 624 | if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { |
631 | IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", | 625 | IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", |
632 | addr); | 626 | addr); |
633 | goto out; | 627 | goto out_err; |
634 | } | 628 | } |
635 | 629 | ||
636 | if (priv->stations[sta_id].used & IWL_STA_LOCAL) { | 630 | if (priv->stations[sta_id].used & IWL_STA_LOCAL) { |
@@ -647,11 +641,10 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) | |||
647 | station = &priv->stations[sta_id]; | 641 | station = &priv->stations[sta_id]; |
648 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 642 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
649 | 643 | ||
650 | ret = iwl_send_remove_station(priv, station); | 644 | return iwl_send_remove_station(priv, station); |
651 | return ret; | 645 | out_err: |
652 | out: | ||
653 | spin_unlock_irqrestore(&priv->sta_lock, flags); | 646 | spin_unlock_irqrestore(&priv->sta_lock, flags); |
654 | return ret; | 647 | return -EINVAL; |
655 | } | 648 | } |
656 | EXPORT_SYMBOL_GPL(iwl_remove_station); | 649 | EXPORT_SYMBOL_GPL(iwl_remove_station); |
657 | 650 | ||
@@ -1467,14 +1460,16 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) | |||
1467 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); | 1460 | EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); |
1468 | 1461 | ||
1469 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, | 1462 | int iwl_mac_sta_remove(struct ieee80211_hw *hw, |
1470 | struct ieee80211_vif *vif, | 1463 | struct ieee80211_vif *vif, |
1471 | struct ieee80211_sta *sta) | 1464 | struct ieee80211_sta *sta) |
1472 | { | 1465 | { |
1473 | int ret; | ||
1474 | struct iwl_priv *priv = hw->priv; | 1466 | struct iwl_priv *priv = hw->priv; |
1467 | struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; | ||
1468 | int ret; | ||
1469 | |||
1475 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", | 1470 | IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", |
1476 | sta->addr); | 1471 | sta->addr); |
1477 | ret = iwl_remove_station(priv, sta->addr); | 1472 | ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); |
1478 | if (ret) | 1473 | if (ret) |
1479 | IWL_ERR(priv, "Error removing station %pM\n", | 1474 | IWL_ERR(priv, "Error removing station %pM\n", |
1480 | sta->addr); | 1475 | sta->addr); |