aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-04-30 14:30:43 -0400
committerReinette Chatre <reinette.chatre@intel.com>2010-05-10 18:09:04 -0400
commitfd1af15d0a82ae681ecf34192150e27455c9c494 (patch)
tree828b4532c5aa2df1859f461e828fd8b4606ec43c /drivers/net/wireless
parent4ff739747de20506e478269221f22f3d8d24c706 (diff)
iwlwifi: track station IDs
mac80211 allows us to store private data per station, so put the station ID there. This allows us to avoid the station ID lookup when removing regular stations. To also be able to avoid the lookup to remove the special IBSS BSSID station, track its ID in the per-vif private data. Signed-off-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-3945.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.c61
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-sta.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c12
8 files changed, 82 insertions, 52 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 7fb159565f68..306e23aee1ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -2461,28 +2461,26 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
2461static int iwl3945_manage_ibss_station(struct iwl_priv *priv, 2461static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
2462 struct ieee80211_vif *vif, bool add) 2462 struct ieee80211_vif *vif, bool add)
2463{ 2463{
2464 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
2464 int ret; 2465 int ret;
2465 2466
2466 /*
2467 * NB: this assumes that the station it gets will be
2468 * IWL_STA_ID, which will happen but isn't obvious.
2469 */
2470
2471 if (add) { 2467 if (add) {
2472 ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false); 2468 ret = iwl_add_local_station(priv, vif->bss_conf.bssid, false,
2469 &vif_priv->ibss_bssid_sta_id);
2473 if (ret) 2470 if (ret)
2474 return ret; 2471 return ret;
2475 2472
2476 iwl3945_sync_sta(priv, IWL_STA_ID, 2473 iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
2477 (priv->band == IEEE80211_BAND_5GHZ) ? 2474 (priv->band == IEEE80211_BAND_5GHZ) ?
2478 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, 2475 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP,
2479 CMD_ASYNC); 2476 CMD_ASYNC);
2480 iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); 2477 iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
2481 2478
2482 return 0; 2479 return 0;
2483 } 2480 }
2484 2481
2485 return iwl_remove_station(priv, vif->bss_conf.bssid); 2482 return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
2483 vif->bss_conf.bssid);
2486} 2484}
2487 2485
2488/** 2486/**
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h
index 8fe24eee1c56..bb2aeebf3652 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.h
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.h
@@ -106,7 +106,12 @@ struct iwl3945_rs_sta {
106}; 106};
107 107
108 108
109/*
110 * The common struct MUST be first because it is shared between
111 * 3945 and agn!
112 */
109struct iwl3945_sta_priv { 113struct iwl3945_sta_priv {
114 struct iwl_station_priv_common common;
110 struct iwl3945_rs_sta rs_sta; 115 struct iwl3945_rs_sta rs_sta;
111}; 116};
112 117
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index f05e6002a04e..81de88ef745e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1520,7 +1520,11 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1520int iwlagn_manage_ibss_station(struct iwl_priv *priv, 1520int iwlagn_manage_ibss_station(struct iwl_priv *priv,
1521 struct ieee80211_vif *vif, bool add) 1521 struct ieee80211_vif *vif, bool add)
1522{ 1522{
1523 struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
1524
1523 if (add) 1525 if (add)
1524 return iwl_add_local_station(priv, vif->bss_conf.bssid, true); 1526 return iwl_add_local_station(priv, vif->bss_conf.bssid, true,
1525 return iwl_remove_station(priv, vif->bss_conf.bssid); 1527 &vif_priv->ibss_bssid_sta_id);
1528 return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
1529 vif->bss_conf.bssid);
1526} 1530}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 0c913ea71f1e..b2c5665c516e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2854,6 +2854,8 @@ static int iwl_mac_setup_register(struct iwl_priv *priv,
2854 IEEE80211_HW_SUPPORTS_STATIC_SMPS; 2854 IEEE80211_HW_SUPPORTS_STATIC_SMPS;
2855 2855
2856 hw->sta_data_size = sizeof(struct iwl_station_priv); 2856 hw->sta_data_size = sizeof(struct iwl_station_priv);
2857 hw->vif_data_size = sizeof(struct iwl_vif_priv);
2858
2857 hw->wiphy->interface_modes = 2859 hw->wiphy->interface_modes =
2858 BIT(NL80211_IFTYPE_STATION) | 2860 BIT(NL80211_IFTYPE_STATION) |
2859 BIT(NL80211_IFTYPE_ADHOC); 2861 BIT(NL80211_IFTYPE_ADHOC);
@@ -3229,6 +3231,8 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
3229 int ret; 3231 int ret;
3230 u8 sta_id; 3232 u8 sta_id;
3231 3233
3234 sta_priv->common.sta_id = IWL_INVALID_STATION;
3235
3232 IWL_DEBUG_INFO(priv, "received request to add station %pM\n", 3236 IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
3233 sta->addr); 3237 sta->addr);
3234 3238
@@ -3245,12 +3249,14 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
3245 return ret; 3249 return ret;
3246 } 3250 }
3247 3251
3252 sta_priv->common.sta_id = sta_id;
3253
3248 /* Initialize rate scaling */ 3254 /* Initialize rate scaling */
3249 IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", 3255 IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
3250 sta->addr); 3256 sta->addr);
3251 iwl_rs_rate_init(priv, sta, sta_id); 3257 iwl_rs_rate_init(priv, sta, sta_id);
3252 3258
3253 return ret; 3259 return 0;
3254} 3260}
3255 3261
3256/***************************************************************************** 3262/*****************************************************************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 46571f7f7abf..f3f3473c5c7e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -497,20 +497,38 @@ struct iwl_station_entry {
497 struct iwl_link_quality_cmd *lq; 497 struct iwl_link_quality_cmd *lq;
498}; 498};
499 499
500struct iwl_station_priv_common {
501 u8 sta_id;
502};
503
500/* 504/*
501 * iwl_station_priv: Driver's private station information 505 * iwl_station_priv: Driver's private station information
502 * 506 *
503 * When mac80211 creates a station it reserves some space (hw->sta_data_size) 507 * When mac80211 creates a station it reserves some space (hw->sta_data_size)
504 * in the structure for use by driver. This structure is places in that 508 * in the structure for use by driver. This structure is places in that
505 * space. 509 * space.
510 *
511 * The common struct MUST be first because it is shared between
512 * 3945 and agn!
506 */ 513 */
507struct iwl_station_priv { 514struct iwl_station_priv {
515 struct iwl_station_priv_common common;
508 struct iwl_lq_sta lq_sta; 516 struct iwl_lq_sta lq_sta;
509 atomic_t pending_frames; 517 atomic_t pending_frames;
510 bool client; 518 bool client;
511 bool asleep; 519 bool asleep;
512}; 520};
513 521
522/**
523 * struct iwl_vif_priv - driver's private per-interface information
524 *
525 * When mac80211 allocates a virtual interface, it can allocate
526 * space for us to put data into.
527 */
528struct iwl_vif_priv {
529 u8 ibss_bssid_sta_id;
530};
531
514/* one for each uCode image (inst/data, boot/init/runtime) */ 532/* one for each uCode image (inst/data, boot/init/runtime) */
515struct fw_desc { 533struct fw_desc {
516 void *v_addr; /* access by driver */ 534 void *v_addr; /* access by driver */
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 */
472int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) 472int 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 */
585int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) 592int 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; 645out_err:
652out:
653 spin_unlock_irqrestore(&priv->sta_lock, flags); 646 spin_unlock_irqrestore(&priv->sta_lock, flags);
654 return ret; 647 return -EINVAL;
655} 648}
656EXPORT_SYMBOL_GPL(iwl_remove_station); 649EXPORT_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)
1467EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); 1460EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count);
1468 1461
1469int iwl_mac_sta_remove(struct ieee80211_hw *hw, 1462int 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);
diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h
index 50c9d5138a4b..8efb83d6cf5c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-sta.h
+++ b/drivers/net/wireless/iwlwifi/iwl-sta.h
@@ -68,12 +68,14 @@ int iwl_get_free_ucode_key_index(struct iwl_priv *priv);
68int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); 68int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr);
69int iwl_send_add_sta(struct iwl_priv *priv, 69int iwl_send_add_sta(struct iwl_priv *priv,
70 struct iwl_addsta_cmd *sta, u8 flags); 70 struct iwl_addsta_cmd *sta, u8 flags);
71int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs); 71int iwl_add_local_station(struct iwl_priv *priv, const u8 *addr, bool init_rs,
72 u8 *sta_id_r);
72int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, 73int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr,
73 bool is_ap, 74 bool is_ap,
74 struct ieee80211_sta_ht_cap *ht_info, 75 struct ieee80211_sta_ht_cap *ht_info,
75 u8 *sta_id_r); 76 u8 *sta_id_r);
76int iwl_remove_station(struct iwl_priv *priv, const u8 *addr); 77int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id,
78 const u8 *addr);
77int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, 79int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
78 struct ieee80211_sta *sta); 80 struct ieee80211_sta *sta);
79void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); 81void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 1a445711e34a..48fb59bbfbd9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3378,10 +3378,13 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
3378 struct ieee80211_sta *sta) 3378 struct ieee80211_sta *sta)
3379{ 3379{
3380 struct iwl_priv *priv = hw->priv; 3380 struct iwl_priv *priv = hw->priv;
3381 struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
3381 int ret; 3382 int ret;
3382 bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; 3383 bool is_ap = vif->type == NL80211_IFTYPE_STATION;
3383 u8 sta_id; 3384 u8 sta_id;
3384 3385
3386 sta_priv->common.sta_id = IWL_INVALID_STATION;
3387
3385 IWL_DEBUG_INFO(priv, "received request to add station %pM\n", 3388 IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
3386 sta->addr); 3389 sta->addr);
3387 3390
@@ -3394,16 +3397,14 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
3394 return ret; 3397 return ret;
3395 } 3398 }
3396 3399
3400 sta_priv->common.sta_id = sta_id;
3401
3397 /* Initialize rate scaling */ 3402 /* Initialize rate scaling */
3398 IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", 3403 IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
3399 sta->addr); 3404 sta->addr);
3400 iwl3945_rs_rate_init(priv, sta, sta_id); 3405 iwl3945_rs_rate_init(priv, sta, sta_id);
3401 3406
3402 return 0; 3407 return 0;
3403
3404
3405
3406 return ret;
3407} 3408}
3408/***************************************************************************** 3409/*****************************************************************************
3409 * 3410 *
@@ -3887,6 +3888,7 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
3887 3888
3888 hw->rate_control_algorithm = "iwl-3945-rs"; 3889 hw->rate_control_algorithm = "iwl-3945-rs";
3889 hw->sta_data_size = sizeof(struct iwl3945_sta_priv); 3890 hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
3891 hw->vif_data_size = sizeof(struct iwl_vif_priv);
3890 3892
3891 /* Tell mac80211 our characteristics */ 3893 /* Tell mac80211 our characteristics */
3892 hw->flags = IEEE80211_HW_SIGNAL_DBM | 3894 hw->flags = IEEE80211_HW_SIGNAL_DBM |