aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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 |