mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
mac80211: use cfg80211s BSS infrastructure
Remove all the code from mac80211 to keep track of BSSes and use the cfg80211-provided code completely. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
79420f09e7
commit
00d3f14cf9
8 changed files with 119 additions and 423 deletions
|
@ -33,9 +33,9 @@ typedef u16 __nocast zd_addr_t;
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# define dev_dbg_f(dev, fmt, args...) \
|
# define dev_dbg_f(dev, fmt, args...) \
|
||||||
dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
|
dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
|
||||||
# define dev_dbg_f_limit(dev, fmt, args...) do {\
|
# define dev_dbg_f_limit(dev, fmt, args...) do { \
|
||||||
if (net_ratelimit())
|
if (net_ratelimit()) \
|
||||||
dev_printk_f(KERN_DEBUG, dev, fmt, ## args)
|
dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \
|
||||||
} while (0)
|
} while (0)
|
||||||
#else
|
#else
|
||||||
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
|
# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0)
|
||||||
|
|
|
@ -72,43 +72,36 @@ struct ieee80211_fragment_entry {
|
||||||
|
|
||||||
|
|
||||||
struct ieee80211_bss {
|
struct ieee80211_bss {
|
||||||
struct list_head list;
|
/* Yes, this is a hack */
|
||||||
struct ieee80211_bss *hnext;
|
struct cfg80211_bss cbss;
|
||||||
|
|
||||||
|
/* don't want to look up all the time */
|
||||||
size_t ssid_len;
|
size_t ssid_len;
|
||||||
|
|
||||||
atomic_t users;
|
|
||||||
|
|
||||||
u8 bssid[ETH_ALEN];
|
|
||||||
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
u8 ssid[IEEE80211_MAX_SSID_LEN];
|
||||||
|
|
||||||
u8 dtim_period;
|
u8 dtim_period;
|
||||||
u16 capability; /* host byte order */
|
|
||||||
enum ieee80211_band band;
|
|
||||||
int freq;
|
|
||||||
int signal, noise, qual;
|
|
||||||
u8 *ies; /* all information elements from the last Beacon or Probe
|
|
||||||
* Response frames; note Beacon frame is not allowed to
|
|
||||||
* override values from Probe Response */
|
|
||||||
size_t ies_len;
|
|
||||||
bool wmm_used;
|
bool wmm_used;
|
||||||
|
|
||||||
|
unsigned long last_probe_resp;
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_MESH
|
#ifdef CONFIG_MAC80211_MESH
|
||||||
u8 *mesh_id;
|
u8 *mesh_id;
|
||||||
size_t mesh_id_len;
|
size_t mesh_id_len;
|
||||||
u8 *mesh_cfg;
|
u8 *mesh_cfg;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define IEEE80211_MAX_SUPP_RATES 32
|
#define IEEE80211_MAX_SUPP_RATES 32
|
||||||
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
|
u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
|
||||||
size_t supp_rates_len;
|
size_t supp_rates_len;
|
||||||
u64 timestamp;
|
|
||||||
int beacon_int;
|
|
||||||
|
|
||||||
unsigned long last_probe_resp;
|
/*
|
||||||
unsigned long last_update;
|
* During assocation, we save an ERP value from a probe response so
|
||||||
|
|
||||||
/* during assocation, we save an ERP value from a probe response so
|
|
||||||
* that we can feed ERP info to the driver when handling the
|
* that we can feed ERP info to the driver when handling the
|
||||||
* association completes. these fields probably won't be up-to-date
|
* association completes. these fields probably won't be up-to-date
|
||||||
* otherwise, you probably don't want to use them. */
|
* otherwise, you probably don't want to use them.
|
||||||
int has_erp_value;
|
*/
|
||||||
|
bool has_erp_value;
|
||||||
u8 erp_value;
|
u8 erp_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -668,9 +661,6 @@ struct ieee80211_local {
|
||||||
struct ieee80211_sub_if_data *scan_sdata;
|
struct ieee80211_sub_if_data *scan_sdata;
|
||||||
enum nl80211_channel_type oper_channel_type;
|
enum nl80211_channel_type oper_channel_type;
|
||||||
struct ieee80211_channel *oper_channel, *csa_channel;
|
struct ieee80211_channel *oper_channel, *csa_channel;
|
||||||
struct list_head bss_list;
|
|
||||||
struct ieee80211_bss *bss_hash[STA_HASH_SIZE];
|
|
||||||
spinlock_t bss_lock;
|
|
||||||
|
|
||||||
/* SNMP counters */
|
/* SNMP counters */
|
||||||
/* dot11CountersTable */
|
/* dot11CountersTable */
|
||||||
|
@ -936,8 +926,6 @@ ieee80211_rx_result
|
||||||
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
|
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct ieee80211_rx_status *rx_status);
|
struct ieee80211_rx_status *rx_status);
|
||||||
void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
|
|
||||||
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
|
|
||||||
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
|
int ieee80211_sta_set_extra_ie(struct ieee80211_sub_if_data *sdata,
|
||||||
char *ie, size_t len);
|
char *ie, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -734,6 +734,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
|
||||||
|
|
||||||
wiphy->privid = mac80211_wiphy_privid;
|
wiphy->privid = mac80211_wiphy_privid;
|
||||||
wiphy->max_scan_ssids = 4;
|
wiphy->max_scan_ssids = 4;
|
||||||
|
/* Yes, putting cfg80211_bss into ieee80211_bss is a hack */
|
||||||
|
wiphy->bss_priv_size = sizeof(struct ieee80211_bss) -
|
||||||
|
sizeof(struct cfg80211_bss);
|
||||||
|
|
||||||
local = wiphy_priv(wiphy);
|
local = wiphy_priv(wiphy);
|
||||||
local->hw.wiphy = wiphy;
|
local->hw.wiphy = wiphy;
|
||||||
|
@ -877,8 +880,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
|
||||||
mpriv->local = local;
|
mpriv->local = local;
|
||||||
local->mdev = mdev;
|
local->mdev = mdev;
|
||||||
|
|
||||||
ieee80211_rx_bss_list_init(local);
|
|
||||||
|
|
||||||
local->hw.workqueue =
|
local->hw.workqueue =
|
||||||
create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
|
create_singlethread_workqueue(wiphy_name(local->hw.wiphy));
|
||||||
if (!local->hw.workqueue) {
|
if (!local->hw.workqueue) {
|
||||||
|
@ -1018,7 +1019,6 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
|
||||||
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
ieee80211_rx_bss_list_deinit(local);
|
|
||||||
ieee80211_clear_tx_pending(local);
|
ieee80211_clear_tx_pending(local);
|
||||||
sta_info_stop(local);
|
sta_info_stop(local);
|
||||||
rate_control_deinitialize(local);
|
rate_control_deinitialize(local);
|
||||||
|
|
|
@ -275,16 +275,6 @@ u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_t
|
||||||
& tbl->hash_mask;
|
& tbl->hash_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len)
|
|
||||||
{
|
|
||||||
if (!mesh_id_len)
|
|
||||||
return 1;
|
|
||||||
else if (mesh_id_len == 1)
|
|
||||||
return (u8) mesh_id[0];
|
|
||||||
else
|
|
||||||
return (u8) (mesh_id[0] + 2 * mesh_id[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mesh_table *mesh_table_alloc(int size_order)
|
struct mesh_table *mesh_table_alloc(int size_order)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
|
@ -196,7 +196,6 @@ struct mesh_rmc {
|
||||||
|
|
||||||
/* Public interfaces */
|
/* Public interfaces */
|
||||||
/* Various */
|
/* Various */
|
||||||
u8 mesh_id_hash(u8 *mesh_id, int mesh_id_len);
|
|
||||||
int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
|
int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
|
||||||
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
|
int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr,
|
||||||
struct ieee80211_sub_if_data *sdata);
|
struct ieee80211_sub_if_data *sdata);
|
||||||
|
|
|
@ -55,10 +55,10 @@ static u8 *ieee80211_bss_get_ie(struct ieee80211_bss *bss, u8 ie)
|
||||||
{
|
{
|
||||||
u8 *end, *pos;
|
u8 *end, *pos;
|
||||||
|
|
||||||
pos = bss->ies;
|
pos = bss->cbss.information_elements;
|
||||||
if (pos == NULL)
|
if (pos == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
end = pos + bss->ies_len;
|
end = pos + bss->cbss.len_information_elements;
|
||||||
|
|
||||||
while (pos + 1 < end) {
|
while (pos + 1 < end) {
|
||||||
if (pos + 2 + pos[1] > end)
|
if (pos + 2 + pos[1] > end)
|
||||||
|
@ -289,7 +289,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
||||||
local->hw.conf.channel->center_freq,
|
local->hw.conf.channel->center_freq,
|
||||||
ifsta->ssid, ifsta->ssid_len);
|
ifsta->ssid, ifsta->ssid_len);
|
||||||
if (bss) {
|
if (bss) {
|
||||||
if (bss->capability & WLAN_CAPABILITY_PRIVACY)
|
if (bss->cbss.capability & WLAN_CAPABILITY_PRIVACY)
|
||||||
capab |= WLAN_CAPABILITY_PRIVACY;
|
capab |= WLAN_CAPABILITY_PRIVACY;
|
||||||
if (bss->wmm_used)
|
if (bss->wmm_used)
|
||||||
wmm = 1;
|
wmm = 1;
|
||||||
|
@ -300,7 +300,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
|
||||||
* b-only mode) */
|
* b-only mode) */
|
||||||
rates_len = ieee80211_compatible_rates(bss, sband, &rates);
|
rates_len = ieee80211_compatible_rates(bss, sband, &rates);
|
||||||
|
|
||||||
if ((bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
|
if ((bss->cbss.capability & WLAN_CAPABILITY_SPECTRUM_MGMT) &&
|
||||||
(local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
|
(local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
|
||||||
capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
|
capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
|
||||||
|
|
||||||
|
@ -816,12 +816,12 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
|
||||||
ifsta->ssid, ifsta->ssid_len);
|
ifsta->ssid, ifsta->ssid_len);
|
||||||
if (bss) {
|
if (bss) {
|
||||||
/* set timing information */
|
/* set timing information */
|
||||||
sdata->vif.bss_conf.beacon_int = bss->beacon_int;
|
sdata->vif.bss_conf.beacon_int = bss->cbss.beacon_interval;
|
||||||
sdata->vif.bss_conf.timestamp = bss->timestamp;
|
sdata->vif.bss_conf.timestamp = bss->cbss.tsf;
|
||||||
sdata->vif.bss_conf.dtim_period = bss->dtim_period;
|
sdata->vif.bss_conf.dtim_period = bss->dtim_period;
|
||||||
|
|
||||||
bss_info_changed |= ieee80211_handle_bss_capability(sdata,
|
bss_info_changed |= ieee80211_handle_bss_capability(sdata,
|
||||||
bss->capability, bss->has_erp_value, bss->erp_value);
|
bss->cbss.capability, bss->has_erp_value, bss->erp_value);
|
||||||
|
|
||||||
ieee80211_rx_bss_put(local, bss);
|
ieee80211_rx_bss_put(local, bss);
|
||||||
}
|
}
|
||||||
|
@ -1041,7 +1041,7 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata,
|
||||||
if (!bss)
|
if (!bss)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
|
bss_privacy = !!(bss->cbss.capability & WLAN_CAPABILITY_PRIVACY);
|
||||||
wep_privacy = !!ieee80211_sta_wep_configured(sdata);
|
wep_privacy = !!ieee80211_sta_wep_configured(sdata);
|
||||||
privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
|
privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
|
||||||
|
|
||||||
|
@ -1416,8 +1416,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||||
/* Add STA entry for the AP */
|
/* Add STA entry for the AP */
|
||||||
sta = sta_info_get(local, ifsta->bssid);
|
sta = sta_info_get(local, ifsta->bssid);
|
||||||
if (!sta) {
|
if (!sta) {
|
||||||
struct ieee80211_bss *bss;
|
|
||||||
|
|
||||||
newsta = true;
|
newsta = true;
|
||||||
|
|
||||||
sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
|
sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC);
|
||||||
|
@ -1427,15 +1425,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bss = ieee80211_rx_bss_get(local, ifsta->bssid,
|
|
||||||
local->hw.conf.channel->center_freq,
|
|
||||||
ifsta->ssid, ifsta->ssid_len);
|
|
||||||
if (bss) {
|
|
||||||
sta->last_signal = bss->signal;
|
|
||||||
sta->last_qual = bss->qual;
|
|
||||||
sta->last_noise = bss->noise;
|
|
||||||
ieee80211_rx_bss_put(local, bss);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update new sta with its last rx activity */
|
/* update new sta with its last rx activity */
|
||||||
sta->last_rx = jiffies;
|
sta->last_rx = jiffies;
|
||||||
|
@ -1691,10 +1680,11 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_bss *bss)
|
struct ieee80211_bss *bss)
|
||||||
{
|
{
|
||||||
return __ieee80211_sta_join_ibss(sdata, ifsta,
|
return __ieee80211_sta_join_ibss(sdata, ifsta,
|
||||||
bss->bssid, bss->beacon_int,
|
bss->cbss.bssid,
|
||||||
bss->freq,
|
bss->cbss.beacon_interval,
|
||||||
|
bss->cbss.channel->center_freq,
|
||||||
bss->supp_rates_len, bss->supp_rates,
|
bss->supp_rates_len, bss->supp_rates,
|
||||||
bss->capability);
|
bss->cbss.capability);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||||
|
@ -1769,7 +1759,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* was just updated in ieee80211_bss_info_update */
|
/* was just updated in ieee80211_bss_info_update */
|
||||||
beacon_timestamp = bss->timestamp;
|
beacon_timestamp = bss->cbss.tsf;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In STA mode, the remaining parameters should not be overridden
|
* In STA mode, the remaining parameters should not be overridden
|
||||||
|
@ -1784,8 +1774,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
||||||
/* check if we need to merge IBSS */
|
/* check if we need to merge IBSS */
|
||||||
if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
|
if (sdata->vif.type == NL80211_IFTYPE_ADHOC && beacon &&
|
||||||
(!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
|
(!(sdata->u.sta.flags & IEEE80211_STA_BSSID_SET)) &&
|
||||||
bss->capability & WLAN_CAPABILITY_IBSS &&
|
bss->cbss.capability & WLAN_CAPABILITY_IBSS &&
|
||||||
bss->freq == local->oper_channel->center_freq &&
|
bss->cbss.channel == local->oper_channel &&
|
||||||
elems->ssid_len == sdata->u.sta.ssid_len &&
|
elems->ssid_len == sdata->u.sta.ssid_len &&
|
||||||
memcmp(elems->ssid, sdata->u.sta.ssid,
|
memcmp(elems->ssid, sdata->u.sta.ssid,
|
||||||
sdata->u.sta.ssid_len) == 0) {
|
sdata->u.sta.ssid_len) == 0) {
|
||||||
|
@ -2230,37 +2220,6 @@ static void ieee80211_sta_reset_auth(struct ieee80211_sub_if_data *sdata,
|
||||||
netif_carrier_off(sdata->dev);
|
netif_carrier_off(sdata->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta,
|
|
||||||
const char *ssid, int ssid_len)
|
|
||||||
{
|
|
||||||
int tmp, hidden_ssid;
|
|
||||||
|
|
||||||
if (ssid_len == ifsta->ssid_len &&
|
|
||||||
!memcmp(ifsta->ssid, ssid, ssid_len))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
hidden_ssid = 1;
|
|
||||||
tmp = ssid_len;
|
|
||||||
while (tmp--) {
|
|
||||||
if (ssid[tmp] != '\0') {
|
|
||||||
hidden_ssid = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (ssid_len == 1 && ssid[0] == ' ')
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
|
static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_if_sta *ifsta)
|
struct ieee80211_if_sta *ifsta)
|
||||||
{
|
{
|
||||||
|
@ -2319,8 +2278,6 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_bss *bss;
|
struct ieee80211_bss *bss;
|
||||||
int found = 0;
|
|
||||||
u8 bssid[ETH_ALEN];
|
|
||||||
int active_ibss;
|
int active_ibss;
|
||||||
|
|
||||||
if (ifsta->ssid_len == 0)
|
if (ifsta->ssid_len == 0)
|
||||||
|
@ -2331,56 +2288,39 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata,
|
||||||
printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
|
printk(KERN_DEBUG "%s: sta_find_ibss (active_ibss=%d)\n",
|
||||||
sdata->dev->name, active_ibss);
|
sdata->dev->name, active_ibss);
|
||||||
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
||||||
spin_lock_bh(&local->bss_lock);
|
|
||||||
list_for_each_entry(bss, &local->bss_list, list) {
|
|
||||||
if (ifsta->ssid_len != bss->ssid_len ||
|
|
||||||
memcmp(ifsta->ssid, bss->ssid, bss->ssid_len) != 0
|
|
||||||
|| !(bss->capability & WLAN_CAPABILITY_IBSS))
|
|
||||||
continue;
|
|
||||||
if ((ifsta->flags & IEEE80211_STA_BSSID_SET) &&
|
|
||||||
memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) != 0)
|
|
||||||
continue;
|
|
||||||
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
|
||||||
printk(KERN_DEBUG " bssid=%pM found\n", bss->bssid);
|
|
||||||
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
|
||||||
memcpy(bssid, bss->bssid, ETH_ALEN);
|
|
||||||
found = 1;
|
|
||||||
if (active_ibss || memcmp(bssid, ifsta->bssid, ETH_ALEN) != 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
if (active_ibss)
|
||||||
if (found)
|
return 0;
|
||||||
printk(KERN_DEBUG " sta_find_ibss: selected %pM current "
|
|
||||||
"%pM\n", bssid, ifsta->bssid);
|
|
||||||
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
|
||||||
|
|
||||||
if (found &&
|
if (ifsta->flags & IEEE80211_STA_BSSID_SET)
|
||||||
((!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) ||
|
bss = ieee80211_rx_bss_get(local, ifsta->bssid, 0,
|
||||||
memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0)) {
|
|
||||||
int ret;
|
|
||||||
int search_freq;
|
|
||||||
|
|
||||||
if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
|
|
||||||
search_freq = bss->freq;
|
|
||||||
else
|
|
||||||
search_freq = local->hw.conf.channel->center_freq;
|
|
||||||
|
|
||||||
bss = ieee80211_rx_bss_get(local, bssid, search_freq,
|
|
||||||
ifsta->ssid, ifsta->ssid_len);
|
ifsta->ssid, ifsta->ssid_len);
|
||||||
if (!bss)
|
else
|
||||||
goto dont_join;
|
bss = (void *)cfg80211_get_ibss(local->hw.wiphy,
|
||||||
|
NULL,
|
||||||
|
ifsta->ssid, ifsta->ssid_len);
|
||||||
|
|
||||||
|
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
||||||
|
if (bss)
|
||||||
|
printk(KERN_DEBUG " sta_find_ibss: selected %pM current "
|
||||||
|
"%pM\n", bss->cbss.bssid, ifsta->bssid);
|
||||||
|
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
||||||
|
|
||||||
|
if (bss &&
|
||||||
|
(!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) ||
|
||||||
|
memcmp(ifsta->bssid, bss->cbss.bssid, ETH_ALEN))) {
|
||||||
|
int ret;
|
||||||
|
|
||||||
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
|
printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM"
|
||||||
" based on configured SSID\n",
|
" based on configured SSID\n",
|
||||||
sdata->dev->name, bssid);
|
sdata->dev->name, bss->cbss.bssid);
|
||||||
|
|
||||||
ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
|
ret = ieee80211_sta_join_ibss(sdata, ifsta, bss);
|
||||||
ieee80211_rx_bss_put(local, bss);
|
ieee80211_rx_bss_put(local, bss);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
} else if (bss)
|
||||||
|
ieee80211_rx_bss_put(local, bss);
|
||||||
|
|
||||||
dont_join:
|
|
||||||
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
#ifdef CONFIG_MAC80211_IBSS_DEBUG
|
||||||
printk(KERN_DEBUG " did not try to join ibss\n");
|
printk(KERN_DEBUG " did not try to join ibss\n");
|
||||||
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
#endif /* CONFIG_MAC80211_IBSS_DEBUG */
|
||||||
|
@ -2436,51 +2376,44 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
|
||||||
struct ieee80211_if_sta *ifsta)
|
struct ieee80211_if_sta *ifsta)
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_bss *bss, *selected = NULL;
|
struct ieee80211_bss *bss;
|
||||||
int top_rssi = 0, freq;
|
u8 *bssid = ifsta->bssid, *ssid = ifsta->ssid;
|
||||||
|
u8 ssid_len = ifsta->ssid_len;
|
||||||
|
u16 capa_mask = WLAN_CAPABILITY_ESS;
|
||||||
|
u16 capa_val = WLAN_CAPABILITY_ESS;
|
||||||
|
struct ieee80211_channel *chan = local->oper_channel;
|
||||||
|
|
||||||
spin_lock_bh(&local->bss_lock);
|
if (ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
|
||||||
freq = local->oper_channel->center_freq;
|
IEEE80211_STA_AUTO_BSSID_SEL |
|
||||||
list_for_each_entry(bss, &local->bss_list, list) {
|
IEEE80211_STA_AUTO_CHANNEL_SEL)) {
|
||||||
if (!(bss->capability & WLAN_CAPABILITY_ESS))
|
capa_mask |= WLAN_CAPABILITY_PRIVACY;
|
||||||
continue;
|
if (sdata->default_key)
|
||||||
|
capa_val |= WLAN_CAPABILITY_PRIVACY;
|
||||||
if ((ifsta->flags & (IEEE80211_STA_AUTO_SSID_SEL |
|
|
||||||
IEEE80211_STA_AUTO_BSSID_SEL |
|
|
||||||
IEEE80211_STA_AUTO_CHANNEL_SEL)) &&
|
|
||||||
(!!(bss->capability & WLAN_CAPABILITY_PRIVACY) ^
|
|
||||||
!!sdata->default_key))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL) &&
|
|
||||||
bss->freq != freq)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL) &&
|
|
||||||
memcmp(bss->bssid, ifsta->bssid, ETH_ALEN))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) &&
|
|
||||||
!ieee80211_sta_match_ssid(ifsta, bss->ssid, bss->ssid_len))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!selected || top_rssi < bss->signal) {
|
|
||||||
selected = bss;
|
|
||||||
top_rssi = bss->signal;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (selected)
|
|
||||||
atomic_inc(&selected->users);
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
|
|
||||||
if (selected) {
|
if (ifsta->flags & IEEE80211_STA_AUTO_CHANNEL_SEL)
|
||||||
ieee80211_set_freq(sdata, selected->freq);
|
chan = NULL;
|
||||||
|
|
||||||
|
if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
|
||||||
|
bssid = NULL;
|
||||||
|
|
||||||
|
if (ifsta->flags & IEEE80211_STA_AUTO_SSID_SEL) {
|
||||||
|
ssid = NULL;
|
||||||
|
ssid_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bss = (void *)cfg80211_get_bss(local->hw.wiphy, chan,
|
||||||
|
bssid, ssid, ssid_len,
|
||||||
|
capa_mask, capa_val);
|
||||||
|
|
||||||
|
if (bss) {
|
||||||
|
ieee80211_set_freq(sdata, bss->cbss.channel->center_freq);
|
||||||
if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
|
if (!(ifsta->flags & IEEE80211_STA_SSID_SET))
|
||||||
ieee80211_sta_set_ssid(sdata, selected->ssid,
|
ieee80211_sta_set_ssid(sdata, bss->ssid,
|
||||||
selected->ssid_len);
|
bss->ssid_len);
|
||||||
ieee80211_sta_set_bssid(sdata, selected->bssid);
|
ieee80211_sta_set_bssid(sdata, bss->cbss.bssid);
|
||||||
ieee80211_sta_def_wmm_params(sdata, selected->supp_rates_len,
|
ieee80211_sta_def_wmm_params(sdata, bss->supp_rates_len,
|
||||||
selected->supp_rates);
|
bss->supp_rates);
|
||||||
if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED)
|
if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED)
|
||||||
sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED;
|
sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED;
|
||||||
else
|
else
|
||||||
|
@ -2489,14 +2422,14 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata,
|
||||||
/* Send out direct probe if no probe resp was received or
|
/* Send out direct probe if no probe resp was received or
|
||||||
* the one we have is outdated
|
* the one we have is outdated
|
||||||
*/
|
*/
|
||||||
if (!selected->last_probe_resp ||
|
if (!bss->last_probe_resp ||
|
||||||
time_after(jiffies, selected->last_probe_resp
|
time_after(jiffies, bss->last_probe_resp
|
||||||
+ IEEE80211_SCAN_RESULT_EXPIRE))
|
+ IEEE80211_SCAN_RESULT_EXPIRE))
|
||||||
ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
|
ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE;
|
||||||
else
|
else
|
||||||
ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
|
ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE;
|
||||||
|
|
||||||
ieee80211_rx_bss_put(local, selected);
|
ieee80211_rx_bss_put(local, bss);
|
||||||
ieee80211_sta_reset_auth(sdata, ifsta);
|
ieee80211_sta_reset_auth(sdata, ifsta);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,10 +12,7 @@
|
||||||
* published by the Free Software Foundation.
|
* published by the Free Software Foundation.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO:
|
/* TODO: figure out how to avoid that the "current BSS" expires */
|
||||||
* figure out how to avoid that the "current BSS" expires
|
|
||||||
* use cfg80211's BSS handling
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/wireless.h>
|
#include <linux/wireless.h>
|
||||||
#include <linux/if_arp.h>
|
#include <linux/if_arp.h>
|
||||||
|
@ -30,192 +27,29 @@
|
||||||
#define IEEE80211_CHANNEL_TIME (HZ / 33)
|
#define IEEE80211_CHANNEL_TIME (HZ / 33)
|
||||||
#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
|
#define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5)
|
||||||
|
|
||||||
void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
|
|
||||||
{
|
|
||||||
spin_lock_init(&local->bss_lock);
|
|
||||||
INIT_LIST_HEAD(&local->bss_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
|
|
||||||
{
|
|
||||||
struct ieee80211_bss *bss, *tmp;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(bss, tmp, &local->bss_list, list)
|
|
||||||
ieee80211_rx_bss_put(local, bss);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ieee80211_bss *
|
struct ieee80211_bss *
|
||||||
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
|
ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq,
|
||||||
u8 *ssid, u8 ssid_len)
|
u8 *ssid, u8 ssid_len)
|
||||||
{
|
{
|
||||||
struct ieee80211_bss *bss;
|
return (void *)cfg80211_get_bss(local->hw.wiphy,
|
||||||
|
ieee80211_get_channel(local->hw.wiphy,
|
||||||
spin_lock_bh(&local->bss_lock);
|
freq),
|
||||||
bss = local->bss_hash[STA_HASH(bssid)];
|
bssid, ssid, ssid_len,
|
||||||
while (bss) {
|
0, 0);
|
||||||
if (!bss_mesh_cfg(bss) &&
|
|
||||||
!memcmp(bss->bssid, bssid, ETH_ALEN) &&
|
|
||||||
bss->freq == freq &&
|
|
||||||
bss->ssid_len == ssid_len &&
|
|
||||||
(ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
|
|
||||||
atomic_inc(&bss->users);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bss = bss->hnext;
|
|
||||||
}
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
return bss;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Caller must hold local->bss_lock */
|
static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss)
|
||||||
static void __ieee80211_rx_bss_hash_add(struct ieee80211_local *local,
|
|
||||||
struct ieee80211_bss *bss)
|
|
||||||
{
|
{
|
||||||
u8 hash_idx;
|
struct ieee80211_bss *bss = (void *)cbss;
|
||||||
|
|
||||||
if (bss_mesh_cfg(bss))
|
|
||||||
hash_idx = mesh_id_hash(bss_mesh_id(bss),
|
|
||||||
bss_mesh_id_len(bss));
|
|
||||||
else
|
|
||||||
hash_idx = STA_HASH(bss->bssid);
|
|
||||||
|
|
||||||
bss->hnext = local->bss_hash[hash_idx];
|
|
||||||
local->bss_hash[hash_idx] = bss;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Caller must hold local->bss_lock */
|
|
||||||
static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
|
|
||||||
struct ieee80211_bss *bss)
|
|
||||||
{
|
|
||||||
struct ieee80211_bss *b, *prev = NULL;
|
|
||||||
b = local->bss_hash[STA_HASH(bss->bssid)];
|
|
||||||
while (b) {
|
|
||||||
if (b == bss) {
|
|
||||||
if (!prev)
|
|
||||||
local->bss_hash[STA_HASH(bss->bssid)] =
|
|
||||||
bss->hnext;
|
|
||||||
else
|
|
||||||
prev->hnext = bss->hnext;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
prev = b;
|
|
||||||
b = b->hnext;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ieee80211_bss *
|
|
||||||
ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq,
|
|
||||||
u8 *ssid, u8 ssid_len)
|
|
||||||
{
|
|
||||||
struct ieee80211_bss *bss;
|
|
||||||
|
|
||||||
bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
|
|
||||||
if (!bss)
|
|
||||||
return NULL;
|
|
||||||
atomic_set(&bss->users, 2);
|
|
||||||
memcpy(bss->bssid, bssid, ETH_ALEN);
|
|
||||||
bss->freq = freq;
|
|
||||||
if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
|
|
||||||
memcpy(bss->ssid, ssid, ssid_len);
|
|
||||||
bss->ssid_len = ssid_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_lock_bh(&local->bss_lock);
|
|
||||||
/* TODO: order by RSSI? */
|
|
||||||
list_add_tail(&bss->list, &local->bss_list);
|
|
||||||
__ieee80211_rx_bss_hash_add(local, bss);
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
return bss;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_MESH
|
|
||||||
static struct ieee80211_bss *
|
|
||||||
ieee80211_rx_mesh_bss_get(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
|
|
||||||
u8 *mesh_cfg, int freq)
|
|
||||||
{
|
|
||||||
struct ieee80211_bss *bss;
|
|
||||||
|
|
||||||
spin_lock_bh(&local->bss_lock);
|
|
||||||
bss = local->bss_hash[mesh_id_hash(mesh_id, mesh_id_len)];
|
|
||||||
while (bss) {
|
|
||||||
if (bss_mesh_cfg(bss) &&
|
|
||||||
!memcmp(bss_mesh_cfg(bss), mesh_cfg, MESH_CFG_CMP_LEN) &&
|
|
||||||
bss->freq == freq &&
|
|
||||||
mesh_id_len == bss->mesh_id_len &&
|
|
||||||
(mesh_id_len == 0 || !memcmp(bss->mesh_id, mesh_id,
|
|
||||||
mesh_id_len))) {
|
|
||||||
atomic_inc(&bss->users);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bss = bss->hnext;
|
|
||||||
}
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
return bss;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ieee80211_bss *
|
|
||||||
ieee80211_rx_mesh_bss_add(struct ieee80211_local *local, u8 *mesh_id, int mesh_id_len,
|
|
||||||
u8 *mesh_cfg, int mesh_config_len, int freq)
|
|
||||||
{
|
|
||||||
struct ieee80211_bss *bss;
|
|
||||||
|
|
||||||
if (mesh_config_len != IEEE80211_MESH_CONFIG_LEN)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
bss = kzalloc(sizeof(*bss), GFP_ATOMIC);
|
|
||||||
if (!bss)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
bss->mesh_cfg = kmalloc(MESH_CFG_CMP_LEN, GFP_ATOMIC);
|
|
||||||
if (!bss->mesh_cfg) {
|
|
||||||
kfree(bss);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mesh_id_len && mesh_id_len <= IEEE80211_MAX_MESH_ID_LEN) {
|
|
||||||
bss->mesh_id = kmalloc(mesh_id_len, GFP_ATOMIC);
|
|
||||||
if (!bss->mesh_id) {
|
|
||||||
kfree(bss->mesh_cfg);
|
|
||||||
kfree(bss);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
memcpy(bss->mesh_id, mesh_id, mesh_id_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic_set(&bss->users, 2);
|
|
||||||
memcpy(bss->mesh_cfg, mesh_cfg, MESH_CFG_CMP_LEN);
|
|
||||||
bss->mesh_id_len = mesh_id_len;
|
|
||||||
bss->freq = freq;
|
|
||||||
spin_lock_bh(&local->bss_lock);
|
|
||||||
/* TODO: order by RSSI? */
|
|
||||||
list_add_tail(&bss->list, &local->bss_list);
|
|
||||||
__ieee80211_rx_bss_hash_add(local, bss);
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
return bss;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void ieee80211_rx_bss_free(struct ieee80211_bss *bss)
|
|
||||||
{
|
|
||||||
kfree(bss->ies);
|
|
||||||
kfree(bss_mesh_id(bss));
|
kfree(bss_mesh_id(bss));
|
||||||
kfree(bss_mesh_cfg(bss));
|
kfree(bss_mesh_cfg(bss));
|
||||||
kfree(bss);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_rx_bss_put(struct ieee80211_local *local,
|
void ieee80211_rx_bss_put(struct ieee80211_local *local,
|
||||||
struct ieee80211_bss *bss)
|
struct ieee80211_bss *bss)
|
||||||
{
|
{
|
||||||
local_bh_disable();
|
cfg80211_put_bss((struct cfg80211_bss *)bss);
|
||||||
if (!atomic_dec_and_lock(&bss->users, &local->bss_lock)) {
|
|
||||||
local_bh_enable();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
__ieee80211_rx_bss_hash_del(local, bss);
|
|
||||||
list_del(&bss->list);
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
ieee80211_rx_bss_free(bss);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ieee80211_bss *
|
struct ieee80211_bss *
|
||||||
|
@ -228,7 +62,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||||
bool beacon)
|
bool beacon)
|
||||||
{
|
{
|
||||||
struct ieee80211_bss *bss;
|
struct ieee80211_bss *bss;
|
||||||
int clen, freq = channel->center_freq;
|
int clen;
|
||||||
enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE;
|
enum cfg80211_signal_type sigtype = CFG80211_SIGNAL_TYPE_NONE;
|
||||||
s32 signal = 0;
|
s32 signal = 0;
|
||||||
|
|
||||||
|
@ -240,39 +74,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||||
signal = (rx_status->signal * 100) / local->hw.max_signal;
|
signal = (rx_status->signal * 100) / local->hw.max_signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg80211_put_bss(
|
bss = (void *)cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
||||||
cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
mgmt, len, signal, sigtype,
|
||||||
mgmt, len, signal, sigtype,
|
GFP_ATOMIC);
|
||||||
GFP_ATOMIC));
|
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_MESH
|
if (!bss)
|
||||||
if (elems->mesh_config)
|
return NULL;
|
||||||
bss = ieee80211_rx_mesh_bss_get(local, elems->mesh_id,
|
|
||||||
elems->mesh_id_len, elems->mesh_config, freq);
|
bss->cbss.free_priv = ieee80211_rx_bss_free;
|
||||||
else
|
|
||||||
#endif
|
|
||||||
bss = ieee80211_rx_bss_get(local, mgmt->bssid, freq,
|
|
||||||
elems->ssid, elems->ssid_len);
|
|
||||||
if (!bss) {
|
|
||||||
#ifdef CONFIG_MAC80211_MESH
|
|
||||||
if (elems->mesh_config)
|
|
||||||
bss = ieee80211_rx_mesh_bss_add(local, elems->mesh_id,
|
|
||||||
elems->mesh_id_len, elems->mesh_config,
|
|
||||||
elems->mesh_config_len, freq);
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
bss = ieee80211_rx_bss_add(local, mgmt->bssid, freq,
|
|
||||||
elems->ssid, elems->ssid_len);
|
|
||||||
if (!bss)
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
#if 0
|
|
||||||
/* TODO: order by RSSI? */
|
|
||||||
spin_lock_bh(&local->bss_lock);
|
|
||||||
list_move_tail(&bss->list, &local->bss_list);
|
|
||||||
spin_unlock_bh(&local->bss_lock);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/* save the ERP value so that it is available at association time */
|
/* save the ERP value so that it is available at association time */
|
||||||
if (elems->erp_info && elems->erp_info_len >= 1) {
|
if (elems->erp_info && elems->erp_info_len >= 1) {
|
||||||
|
@ -280,9 +89,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||||
bss->has_erp_value = 1;
|
bss->has_erp_value = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
|
|
||||||
bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
|
|
||||||
|
|
||||||
if (elems->tim) {
|
if (elems->tim) {
|
||||||
struct ieee80211_tim_ie *tim_ie =
|
struct ieee80211_tim_ie *tim_ie =
|
||||||
(struct ieee80211_tim_ie *)elems->tim;
|
(struct ieee80211_tim_ie *)elems->tim;
|
||||||
|
@ -311,34 +117,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||||
bss->supp_rates_len += clen;
|
bss->supp_rates_len += clen;
|
||||||
}
|
}
|
||||||
|
|
||||||
bss->band = rx_status->band;
|
|
||||||
|
|
||||||
bss->timestamp = le64_to_cpu(mgmt->u.beacon.timestamp);
|
|
||||||
bss->last_update = jiffies;
|
|
||||||
bss->signal = rx_status->signal;
|
|
||||||
bss->noise = rx_status->noise;
|
|
||||||
bss->qual = rx_status->qual;
|
|
||||||
bss->wmm_used = elems->wmm_param || elems->wmm_info;
|
bss->wmm_used = elems->wmm_param || elems->wmm_info;
|
||||||
|
|
||||||
if (!beacon)
|
if (!beacon)
|
||||||
bss->last_probe_resp = jiffies;
|
bss->last_probe_resp = jiffies;
|
||||||
|
|
||||||
/*
|
|
||||||
* For probe responses, or if we don't have any information yet,
|
|
||||||
* use the IEs from the beacon.
|
|
||||||
*/
|
|
||||||
if (!bss->ies || !beacon) {
|
|
||||||
if (bss->ies == NULL || bss->ies_len < elems->total_len) {
|
|
||||||
kfree(bss->ies);
|
|
||||||
bss->ies = kmalloc(elems->total_len, GFP_ATOMIC);
|
|
||||||
}
|
|
||||||
if (bss->ies) {
|
|
||||||
memcpy(bss->ies, elems->ie_start, elems->total_len);
|
|
||||||
bss->ies_len = elems->total_len;
|
|
||||||
} else
|
|
||||||
bss->ies_len = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return bss;
|
return bss;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,7 +133,7 @@ void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid,
|
||||||
|
|
||||||
bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
|
bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len);
|
||||||
if (bss) {
|
if (bss) {
|
||||||
atomic_dec(&bss->users);
|
cfg80211_unlink_bss(local->hw.wiphy, (void *)bss);
|
||||||
ieee80211_rx_bss_put(local, bss);
|
ieee80211_rx_bss_put(local, bss);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,8 +102,9 @@ void ieee80211_chswitch_work(struct work_struct *work)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
sdata->local->oper_channel = sdata->local->csa_channel;
|
sdata->local->oper_channel = sdata->local->csa_channel;
|
||||||
|
/* XXX: shouldn't really modify cfg80211-owned data! */
|
||||||
if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
|
if (!ieee80211_hw_config(sdata->local, IEEE80211_CONF_CHANGE_CHANNEL))
|
||||||
bss->freq = sdata->local->oper_channel->center_freq;
|
bss->cbss.channel = sdata->local->oper_channel;
|
||||||
|
|
||||||
ieee80211_rx_bss_put(sdata->local, bss);
|
ieee80211_rx_bss_put(sdata->local, bss);
|
||||||
exit:
|
exit:
|
||||||
|
@ -158,7 +159,9 @@ void ieee80211_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
||||||
IEEE80211_QUEUE_STOP_REASON_CSA);
|
IEEE80211_QUEUE_STOP_REASON_CSA);
|
||||||
ifsta->flags |= IEEE80211_STA_CSA_RECEIVED;
|
ifsta->flags |= IEEE80211_STA_CSA_RECEIVED;
|
||||||
mod_timer(&ifsta->chswitch_timer,
|
mod_timer(&ifsta->chswitch_timer,
|
||||||
jiffies + msecs_to_jiffies(sw_elem->count * bss->beacon_int));
|
jiffies +
|
||||||
|
msecs_to_jiffies(sw_elem->count *
|
||||||
|
bss->cbss.beacon_interval));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue