diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 068f7f8..c6ee847 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -43,7 +43,6 @@ #include "iwl-fh.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" -#include "iwl-sta.h" #include "iwl-3945.h" #include "iwl-eeprom.h" #include "iwl-core.h" @@ -51,6 +50,7 @@ #include "iwl-led.h" #include "iwl-3945-led.h" #include "iwl-3945-debugfs.h" +#include "iwl-sta.h" #define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ @@ -2462,26 +2462,23 @@ static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) static int iwl3945_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; int ret; if (add) { - ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false, - &vif_priv->ibss_bssid_sta_id); + ret = iwl_add_bssid_station(priv, vif->bss_conf.bssid, false); if (ret) return ret; - iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id, + iwl3945_sync_sta(priv, IWL_STA_ID, (priv->band == IEEE80211_BAND_5GHZ) ? IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, CMD_ASYNC); - iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id); + iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); return 0; } - return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, - vif->bss_conf.bssid); + return iwl_remove_station(priv, vif->bss_conf.bssid); } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index bb2aeeb..8fe24ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -106,12 +106,7 @@ struct iwl3945_rs_sta { }; -/* - * The common struct MUST be first because it is shared between - * 3945 and agn! - */ struct iwl3945_sta_priv { - struct iwl_station_priv_common common; struct iwl3945_rs_sta rs_sta; }; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index d3afdda..93893ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -1953,50 +1953,6 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, return 0; } -static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) -{ - int i; - int start = 0; - int ret = IWL_INVALID_STATION; - unsigned long flags; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || - (priv->iw_mode == NL80211_IFTYPE_AP)) - start = IWL_STA_ID; - - if (is_broadcast_ether_addr(addr)) - return priv->hw_params.bcast_sta_id; - - spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_params.max_stations; i++) - if (priv->stations[i].used && - (!compare_ether_addr(priv->stations[i].sta.sta.addr, - addr))) { - ret = i; - goto out; - } - - IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", - addr, priv->num_stations); - - out: - /* - * It may be possible that more commands interacting with stations - * arrive before we completed processing the adding of - * station - */ - if (ret != IWL_INVALID_STATION && - (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || - ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && - (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { - IWL_ERR(priv, "Requested station info for sta %d before ready.\n", - ret); - ret = IWL_INVALID_STATION; - } - spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; -} - static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) { if (priv->iw_mode == NL80211_IFTYPE_STATION) { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 1004cfc..1811805 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c @@ -1520,11 +1520,7 @@ void iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) int iwlagn_manage_ibss_station(struct iwl_priv *priv, struct ieee80211_vif *vif, bool add) { - struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv; - if (add) - return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true, - &vif_priv->ibss_bssid_sta_id); - return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id, - vif->bss_conf.bssid); + return iwl_add_bssid_station(priv, vif->bss_conf.bssid, true); + return iwl_remove_station(priv, vif->bss_conf.bssid); } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 19d41ec..5555360 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -566,11 +566,11 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); - /* Find index into station table for destination station */ - if (!info->control.sta) + /* Find (or create) index into station table for destination station */ + if (info->flags & IEEE80211_TX_CTL_INJECTED) sta_id = priv->hw_params.bcast_sta_id; else - sta_id = iwl_sta_id(info->control.sta); + sta_id = iwl_get_sta_id(priv, hdr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -962,7 +962,7 @@ static int iwlagn_txq_ctx_activate_free(struct iwl_priv *priv) } int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) + const u8 *ra, u16 tid, u16 *ssn) { int sta_id; int tx_fifo; @@ -976,9 +976,9 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, return tx_fifo; IWL_WARN(priv, "%s on ra = %pM tid = %d\n", - __func__, sta->addr, tid); + __func__, ra, tid); - sta_id = iwl_sta_id(sta); + sta_id = iwl_find_station(priv, ra); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Start AGG on invalid station\n"); return -ENXIO; @@ -1012,7 +1012,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, if (tid_data->tfds_in_queue == 0) { IWL_DEBUG_HT(priv, "HW queue is empty\n"); tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ieee80211_start_tx_ba_cb_irqsafe(vif, ra, tid); } else { IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", tid_data->tfds_in_queue); @@ -1022,18 +1022,23 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, } int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid) + const u8 *ra, u16 tid) { int tx_fifo_id, txq_id, sta_id, ssn = -1; struct iwl_tid_data *tid_data; int write_ptr, read_ptr; unsigned long flags; + if (!ra) { + IWL_ERR(priv, "ra = NULL\n"); + return -EINVAL; + } + tx_fifo_id = get_fifo_from_tid(tid); if (unlikely(tx_fifo_id < 0)) return tx_fifo_id; - sta_id = iwl_sta_id(sta); + sta_id = iwl_find_station(priv, ra); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); @@ -1043,7 +1048,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, if (priv->stations[sta_id].tid[tid].agg.state == IWL_EMPTYING_HW_QUEUE_ADDBA) { IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, ra, tid); priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; return 0; } @@ -1080,7 +1085,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, tx_fifo_id); spin_unlock_irqrestore(&priv->lock, flags); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + ieee80211_stop_tx_ba_cb_irqsafe(vif, ra, tid); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index aef4f71..e47c3d5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -2855,8 +2855,6 @@ static int iwl_mac_setup_register(struct iwl_priv *priv, IEEE80211_HW_SUPPORTS_STATIC_SMPS; hw->sta_data_size = sizeof(struct iwl_station_priv); - hw->vif_data_size = sizeof(struct iwl_vif_priv); - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); @@ -3058,7 +3056,8 @@ static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, struct iwl_priv *priv = hw->priv; IWL_DEBUG_MAC80211(priv, "enter\n"); - iwl_update_tkip_key(priv, keyconf, sta, + iwl_update_tkip_key(priv, keyconf, + sta ? sta->addr : iwl_bcast_addr, iv32, phase1key); IWL_DEBUG_MAC80211(priv, "leave\n"); @@ -3070,6 +3069,7 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; + const u8 *addr; int ret; u8 sta_id; bool is_default_wep_key = false; @@ -3080,17 +3080,13 @@ static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); return -EOPNOTSUPP; } + addr = sta ? sta->addr : iwl_bcast_addr; + sta_id = iwl_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", + addr); + return -EINVAL; - if (sta) { - sta_id = iwl_sta_id(sta); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - sta->addr); - return -EINVAL; - } - } else { - sta_id = priv->hw_params.bcast_sta_id; } mutex_lock(&priv->mutex); @@ -3154,17 +3150,17 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, switch (action) { case IEEE80211_AMPDU_RX_START: IWL_DEBUG_HT(priv, "start Rx\n"); - return iwl_sta_rx_agg_start(priv, sta, tid, *ssn); + return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); case IEEE80211_AMPDU_RX_STOP: IWL_DEBUG_HT(priv, "stop Rx\n"); - ret = iwl_sta_rx_agg_stop(priv, sta, tid); + ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return 0; else return ret; case IEEE80211_AMPDU_TX_START: IWL_DEBUG_HT(priv, "start Tx\n"); - ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); + ret = iwlagn_tx_agg_start(priv, vif, sta->addr, tid, ssn); if (ret == 0) { priv->_agn.agg_tids_count++; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", @@ -3173,7 +3169,7 @@ static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, return ret; case IEEE80211_AMPDU_TX_STOP: IWL_DEBUG_HT(priv, "stop Tx\n"); - ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); + ret = iwlagn_tx_agg_stop(priv, vif, sta->addr, tid); if ((ret == 0) && (priv->_agn.agg_tids_count > 0)) { priv->_agn.agg_tids_count--; IWL_DEBUG_HT(priv, "priv->_agn.agg_tids_count = %u\n", @@ -3215,7 +3211,7 @@ static void iwl_mac_sta_notify(struct ieee80211_hw *hw, if (!sta_priv->asleep) break; sta_priv->asleep = false; - sta_id = iwl_sta_id(sta); + sta_id = iwl_find_station(priv, sta->addr); if (sta_id != IWL_INVALID_STATION) iwl_sta_modify_ps_wake(priv, sta_id); break; @@ -3234,8 +3230,6 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, int ret; u8 sta_id; - sta_priv->common.sta_id = IWL_INVALID_STATION; - IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); @@ -3252,14 +3246,12 @@ static int iwlagn_mac_sta_add(struct ieee80211_hw *hw, return ret; } - sta_priv->common.sta_id = sta_id; - /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl_rs_rate_init(priv, sta, sta_id); - return 0; + return ret; } /***************************************************************************** diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 2d74805..c441773 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h @@ -136,9 +136,9 @@ void iwlagn_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, struct ieee80211_tx_info *info); int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid, u16 *ssn); + const u8 *ra, u16 tid, u16 *ssn); int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, u16 tid); + const u8 *ra, u16 tid); int iwlagn_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f3f3473..46571f7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -497,38 +497,20 @@ struct iwl_station_entry { struct iwl_link_quality_cmd *lq; }; -struct iwl_station_priv_common { - u8 sta_id; -}; - /* * iwl_station_priv: Driver's private station information * * When mac80211 creates a station it reserves some space (hw->sta_data_size) * in the structure for use by driver. This structure is places in that * space. - * - * The common struct MUST be first because it is shared between - * 3945 and agn! */ struct iwl_station_priv { - struct iwl_station_priv_common common; struct iwl_lq_sta lq_sta; atomic_t pending_frames; bool client; bool asleep; }; -/** - * struct iwl_vif_priv - driver's private per-interface information - * - * When mac80211 allocates a virtual interface, it can allocate - * space for us to put data into. - */ -struct iwl_vif_priv { - u8 ibss_bssid_sta_id; -}; - /* one for each uCode image (inst/data, boot/init/runtime) */ struct fw_desc { 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 83a2636..27437c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -35,6 +35,51 @@ #include "iwl-core.h" #include "iwl-sta.h" +u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) +{ + int i; + int start = 0; + int ret = IWL_INVALID_STATION; + unsigned long flags; + + if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || + (priv->iw_mode == NL80211_IFTYPE_AP)) + start = IWL_STA_ID; + + if (is_broadcast_ether_addr(addr)) + return priv->hw_params.bcast_sta_id; + + spin_lock_irqsave(&priv->sta_lock, flags); + for (i = start; i < priv->hw_params.max_stations; i++) + if (priv->stations[i].used && + (!compare_ether_addr(priv->stations[i].sta.sta.addr, + addr))) { + ret = i; + goto out; + } + + IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", + addr, priv->num_stations); + + out: + /* + * It may be possible that more commands interacting with stations + * arrive before we completed processing the adding of + * station + */ + if (ret != IWL_INVALID_STATION && + (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) || + ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) && + (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) { + IWL_ERR(priv, "Requested station info for sta %d before ready.\n", + ret); + ret = IWL_INVALID_STATION; + } + spin_unlock_irqrestore(&priv->sta_lock, flags); + return ret; +} +EXPORT_SYMBOL(iwl_find_station); + /* priv->sta_lock must be held */ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) { @@ -423,26 +468,19 @@ static struct iwl_link_quality_cmd *iwl_sta_alloc_lq(struct iwl_priv *priv, * * Function sleeps. */ -int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, - u8 *sta_id_r) +int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs) { int ret; u8 sta_id; struct iwl_link_quality_cmd *link_cmd; unsigned long flags; - if (sta_id_r) - *sta_id_r = IWL_INVALID_STATION; - ret = iwl_add_station_common(priv, addr, 0, NULL, &sta_id); if (ret) { IWL_ERR(priv, "Unable to add station %pM\n", addr); return ret; } - if (sta_id_r) - *sta_id_r = sta_id; - spin_lock_irqsave(&priv->sta_lock, flags); priv->stations[sta_id].used |= IWL_STA_LOCAL; spin_unlock_irqrestore(&priv->sta_lock, flags); @@ -543,11 +581,13 @@ static int iwl_send_remove_station(struct iwl_priv *priv, /** * iwl_remove_station - Remove driver's knowledge of station. */ -int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, - const u8 *addr) +int iwl_remove_station(struct iwl_priv *priv, const u8 *addr) { - struct iwl_station_entry *station; + int sta_id = IWL_INVALID_STATION; + int i, ret = -EINVAL; unsigned long flags; + bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; + struct iwl_station_entry *station; if (!iwl_is_ready(priv)) { IWL_DEBUG_INFO(priv, @@ -561,24 +601,35 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, return 0; } - IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", - sta_id, addr); + spin_lock_irqsave(&priv->sta_lock, flags); - if (WARN_ON(sta_id == IWL_INVALID_STATION)) - return -EINVAL; + if (is_ap) + sta_id = IWL_AP_ID; + else + for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) + if (priv->stations[i].used && + !compare_ether_addr(priv->stations[i].sta.sta.addr, + addr)) { + sta_id = i; + break; + } - spin_lock_irqsave(&priv->sta_lock, flags); + if (unlikely(sta_id == IWL_INVALID_STATION)) + goto out; + + IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", + sta_id, addr); if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n", addr); - goto out_err; + goto out; } if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n", addr); - goto out_err; + goto out; } if (priv->stations[sta_id].used & IWL_STA_LOCAL) { @@ -595,10 +646,11 @@ int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, station = &priv->stations[sta_id]; spin_unlock_irqrestore(&priv->sta_lock, flags); - return iwl_send_remove_station(priv, station); -out_err: + ret = iwl_send_remove_station(priv, station); + return ret; +out: spin_unlock_irqrestore(&priv->sta_lock, flags); - return -EINVAL; + return ret; } EXPORT_SYMBOL_GPL(iwl_remove_station); @@ -966,23 +1018,18 @@ static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 *phase1key) + const u8 *addr, u32 iv32, u16 *phase1key) { - u8 sta_id; + u8 sta_id = IWL_INVALID_STATION; unsigned long flags; int i; - if (sta) { - sta_id = iwl_sta_id(sta); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not initialised.\n", - sta->addr); - return; - } - } else - sta_id = priv->hw_params.bcast_sta_id; - + sta_id = iwl_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", + addr); + return; + } if (iwl_scan_cancel(priv)) { /* cancel scan failed, just live w/ bad key and rely @@ -1266,6 +1313,62 @@ void iwl_dealloc_bcast_station(struct iwl_priv *priv) EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_station); /** + * iwl_get_sta_id - Find station's index within station table + * + * If new IBSS station, create new entry in station table + */ +int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) +{ + int sta_id; + __le16 fc = hdr->frame_control; + + /* If this frame is broadcast or management, use broadcast station id */ + if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) + return priv->hw_params.bcast_sta_id; + + switch (priv->iw_mode) { + + /* If we are a client station in a BSS network, use the special + * AP station entry (that's the only station we communicate with) */ + case NL80211_IFTYPE_STATION: + /* + * If addition of station not complete yet, which means + * that rate scaling has not been initialized, then return + * the broadcast station. + */ + if (!(priv->stations[IWL_AP_ID].used & IWL_STA_UCODE_ACTIVE)) + return priv->hw_params.bcast_sta_id; + return IWL_AP_ID; + + /* If we are an AP, then find the station, or use BCAST */ + case NL80211_IFTYPE_AP: + sta_id = iwl_find_station(priv, hdr->addr1); + if (sta_id != IWL_INVALID_STATION) + return sta_id; + return priv->hw_params.bcast_sta_id; + + /* If this frame is going out to an IBSS network, find the station, + * or create a new station table entry */ + case NL80211_IFTYPE_ADHOC: + sta_id = iwl_find_station(priv, hdr->addr1); + if (sta_id != IWL_INVALID_STATION) + return sta_id; + + IWL_DEBUG_DROP(priv, "Station %pM not in station map. " + "Defaulting to broadcast...\n", + hdr->addr1); + iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); + return priv->hw_params.bcast_sta_id; + + default: + IWL_WARN(priv, "Unknown mode of operation: %d\n", + priv->iw_mode); + return priv->hw_params.bcast_sta_id; + } +} +EXPORT_SYMBOL(iwl_get_sta_id); + +/** * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table */ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) @@ -1283,13 +1386,13 @@ void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) } EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); -int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid, u16 ssn) +int iwl_sta_rx_agg_start(struct iwl_priv *priv, + const u8 *addr, int tid, u16 ssn) { unsigned long flags; int sta_id; - sta_id = iwl_sta_id(sta); + sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) return -ENXIO; @@ -1302,17 +1405,16 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, spin_unlock_irqrestore(&priv->sta_lock, flags); return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, - CMD_ASYNC); + CMD_ASYNC); } EXPORT_SYMBOL(iwl_sta_rx_agg_start); -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid) +int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) { unsigned long flags; int sta_id; - sta_id = iwl_sta_id(sta); + sta_id = iwl_find_station(priv, addr); if (sta_id == IWL_INVALID_STATION) { IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); return -ENXIO; @@ -1364,16 +1466,14 @@ void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt) EXPORT_SYMBOL(iwl_sta_modify_sleep_tx_count); int iwl_mac_sta_remove(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta) + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) { - struct iwl_priv *priv = hw->priv; - struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv; int ret; - + struct iwl_priv *priv = hw->priv; IWL_DEBUG_INFO(priv, "received request to remove station %pM\n", sta->addr); - ret = iwl_remove_station(priv, sta_common->sta_id, sta->addr); + ret = iwl_remove_station(priv, sta->addr); if (ret) IWL_ERR(priv, "Error removing station %pM\n", sta->addr); diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h index c2a453a..b662203 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ b/drivers/net/wireless/iwlwifi/iwl-sta.h @@ -29,8 +29,6 @@ #ifndef __iwl_sta_h__ #define __iwl_sta_h__ -#include "iwl-dev.h" - #define HW_KEY_DYNAMIC 0 #define HW_KEY_DEFAULT 1 @@ -43,6 +41,12 @@ #define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */ +/** + * iwl_find_station - Find station id for a given BSSID + * @bssid: MAC address of station ID to find + */ +u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); + int iwl_remove_default_wep_key(struct iwl_priv *priv, struct ieee80211_key_conf *key); int iwl_set_default_wep_key(struct iwl_priv *priv, @@ -54,30 +58,28 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, struct ieee80211_key_conf *key, u8 sta_id); void iwl_update_tkip_key(struct iwl_priv *priv, struct ieee80211_key_conf *keyconf, - struct ieee80211_sta *sta, u32 iv32, u16 *phase1key); + const u8 *addr, u32 iv32, u16 *phase1key); void iwl_restore_stations(struct iwl_priv *priv); void iwl_clear_ucode_stations(struct iwl_priv *priv); int iwl_alloc_bcast_station(struct iwl_priv *priv, bool init_lq); void iwl_dealloc_bcast_station(struct iwl_priv *priv); int iwl_get_free_ucode_key_index(struct iwl_priv *priv); +int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); int iwl_send_add_sta(struct iwl_priv *priv, struct iwl_addsta_cmd *sta, u8 flags); -int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs, - u8 *sta_id_r); +int iwl_add_bssid_station(struct iwl_priv *priv, const u8 *addr, bool init_rs); int iwl_add_station_common(struct iwl_priv *priv, const u8 *addr, bool is_ap, struct ieee80211_sta_ht_cap *ht_info, u8 *sta_id_r); -int iwl_remove_station(struct iwl_priv *priv, const u8 sta_id, - const u8 *addr); +int iwl_remove_station(struct iwl_priv *priv, const u8 *addr); int iwl_mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta); void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); -int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid, u16 ssn); -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta, - int tid); +int iwl_sta_rx_agg_start(struct iwl_priv *priv, + const u8 *addr, int tid, u16 ssn); +int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id); void iwl_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt); @@ -100,11 +102,4 @@ static inline void iwl_clear_driver_stations(struct iwl_priv *priv) spin_unlock_irqrestore(&priv->sta_lock, flags); } -static inline int iwl_sta_id(struct ieee80211_sta *sta) -{ - if (WARN_ON(!sta)) - return IWL_INVALID_STATION; - - return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id; -} #endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 3e5bffb..53ff45a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -52,12 +52,12 @@ #include "iwl-fh.h" #include "iwl-3945-fh.h" #include "iwl-commands.h" -#include "iwl-sta.h" #include "iwl-3945.h" #include "iwl-core.h" #include "iwl-helpers.h" #include "iwl-dev.h" #include "iwl-spectrum.h" +#include "iwl-sta.h" /* * module name, copyright, version, etc. @@ -509,11 +509,11 @@ static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) hdr_len = ieee80211_hdrlen(fc); - /* Find index into station table for destination station */ - if (!info->control.sta) + /* Find (or create) index into station table for destination station */ + if (info->flags & IEEE80211_TX_CTL_INJECTED) sta_id = priv->hw_params.bcast_sta_id; else - sta_id = iwl_sta_id(info->control.sta); + sta_id = iwl_get_sta_id(priv, hdr); if (sta_id == IWL_INVALID_STATION) { IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", hdr->addr1); @@ -3322,6 +3322,7 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct iwl_priv *priv = hw->priv; + const u8 *addr; int ret = 0; u8 sta_id = IWL_INVALID_STATION; u8 static_key; @@ -3333,19 +3334,15 @@ static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return -EOPNOTSUPP; } + addr = sta ? sta->addr : iwl_bcast_addr; static_key = !iwl_is_associated(priv); if (!static_key) { - if (!sta) { - sta_id = priv->hw_params.bcast_sta_id; - } else { - sta_id = iwl_sta_id(sta); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, - "leave - %pM not in station map.\n", - sta->addr); - return -EINVAL; - } + sta_id = iwl_find_station(priv, addr); + if (sta_id == IWL_INVALID_STATION) { + IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", + addr); + return -EINVAL; } } @@ -3382,13 +3379,10 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_sta *sta) { struct iwl_priv *priv = hw->priv; - struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv; int ret; - bool is_ap = vif->type == NL80211_IFTYPE_STATION; + bool is_ap = priv->iw_mode == NL80211_IFTYPE_STATION; u8 sta_id; - sta_priv->common.sta_id = IWL_INVALID_STATION; - IWL_DEBUG_INFO(priv, "received request to add station %pM\n", sta->addr); @@ -3401,14 +3395,16 @@ static int iwl3945_mac_sta_add(struct ieee80211_hw *hw, return ret; } - sta_priv->common.sta_id = sta_id; - /* Initialize rate scaling */ IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n", sta->addr); iwl3945_rs_rate_init(priv, sta, sta_id); return 0; + + + + return ret; } /***************************************************************************** * @@ -3892,7 +3888,6 @@ static int iwl3945_setup_mac(struct iwl_priv *priv) hw->rate_control_algorithm = "iwl-3945-rs"; hw->sta_data_size = sizeof(struct iwl3945_sta_priv); - hw->vif_data_size = sizeof(struct iwl_vif_priv); /* Tell mac80211 our characteristics */ hw->flags = IEEE80211_HW_SIGNAL_DBM |