Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
This commit is contained in:
@@ -83,13 +83,14 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
|
||||
cbss = cfg80211_inform_bss_frame(local->hw.wiphy, channel,
|
||||
mgmt, len, signal, GFP_ATOMIC);
|
||||
|
||||
if (!cbss)
|
||||
return NULL;
|
||||
|
||||
cbss->free_priv = ieee80211_rx_bss_free;
|
||||
bss = (void *)cbss->priv;
|
||||
|
||||
bss->device_ts = rx_status->device_timestamp;
|
||||
|
||||
if (elems->parse_error) {
|
||||
if (beacon)
|
||||
bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
|
||||
@@ -164,52 +165,47 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
|
||||
return bss;
|
||||
}
|
||||
|
||||
ieee80211_rx_result
|
||||
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||
void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct ieee80211_sub_if_data *sdata1, *sdata2;
|
||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
struct ieee80211_bss *bss;
|
||||
u8 *elements;
|
||||
struct ieee80211_channel *channel;
|
||||
size_t baselen;
|
||||
int freq;
|
||||
__le16 fc;
|
||||
bool presp, beacon = false;
|
||||
bool beacon;
|
||||
struct ieee802_11_elems elems;
|
||||
|
||||
if (skb->len < 2)
|
||||
return RX_DROP_UNUSABLE;
|
||||
if (skb->len < 24 ||
|
||||
(!ieee80211_is_probe_resp(mgmt->frame_control) &&
|
||||
!ieee80211_is_beacon(mgmt->frame_control)))
|
||||
return;
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *) skb->data;
|
||||
fc = mgmt->frame_control;
|
||||
sdata1 = rcu_dereference(local->scan_sdata);
|
||||
sdata2 = rcu_dereference(local->sched_scan_sdata);
|
||||
|
||||
if (ieee80211_is_ctl(fc))
|
||||
return RX_CONTINUE;
|
||||
if (likely(!sdata1 && !sdata2))
|
||||
return;
|
||||
|
||||
if (skb->len < 24)
|
||||
return RX_CONTINUE;
|
||||
|
||||
presp = ieee80211_is_probe_resp(fc);
|
||||
if (presp) {
|
||||
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
|
||||
/* ignore ProbeResp to foreign address */
|
||||
if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
|
||||
return RX_DROP_MONITOR;
|
||||
if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&
|
||||
(!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
|
||||
return;
|
||||
|
||||
presp = true;
|
||||
elements = mgmt->u.probe_resp.variable;
|
||||
baselen = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
||||
beacon = false;
|
||||
} else {
|
||||
beacon = ieee80211_is_beacon(fc);
|
||||
baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||
elements = mgmt->u.beacon.variable;
|
||||
beacon = true;
|
||||
}
|
||||
|
||||
if (!presp && !beacon)
|
||||
return RX_CONTINUE;
|
||||
|
||||
if (baselen > skb->len)
|
||||
return RX_DROP_MONITOR;
|
||||
return;
|
||||
|
||||
ieee802_11_parse_elems(elements, skb->len - baselen, &elems);
|
||||
|
||||
@@ -219,22 +215,16 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
|
||||
else
|
||||
freq = rx_status->freq;
|
||||
|
||||
channel = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
|
||||
channel = ieee80211_get_channel(local->hw.wiphy, freq);
|
||||
|
||||
if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
|
||||
return RX_DROP_MONITOR;
|
||||
return;
|
||||
|
||||
bss = ieee80211_bss_info_update(sdata->local, rx_status,
|
||||
bss = ieee80211_bss_info_update(local, rx_status,
|
||||
mgmt, skb->len, &elems,
|
||||
channel, beacon);
|
||||
if (bss)
|
||||
ieee80211_rx_bss_put(sdata->local, bss);
|
||||
|
||||
if (channel == sdata->local->oper_channel)
|
||||
return RX_CONTINUE;
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
return RX_QUEUED;
|
||||
ieee80211_rx_bss_put(local, bss);
|
||||
}
|
||||
|
||||
/* return false if no more work */
|
||||
@@ -292,7 +282,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
|
||||
return;
|
||||
|
||||
if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
|
||||
int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
|
||||
int rc;
|
||||
|
||||
rc = drv_hw_scan(local,
|
||||
rcu_dereference_protected(local->scan_sdata,
|
||||
lockdep_is_held(&local->mtx)),
|
||||
local->hw_scan_req);
|
||||
|
||||
if (rc == 0)
|
||||
return;
|
||||
}
|
||||
@@ -393,7 +389,10 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local)
|
||||
if (!local->scan_req || local->scanning)
|
||||
return;
|
||||
|
||||
if (!ieee80211_can_scan(local, local->scan_sdata))
|
||||
if (!ieee80211_can_scan(local,
|
||||
rcu_dereference_protected(
|
||||
local->scan_sdata,
|
||||
lockdep_is_held(&local->mtx))))
|
||||
return;
|
||||
|
||||
ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
|
||||
@@ -404,9 +403,12 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
|
||||
unsigned long *next_delay)
|
||||
{
|
||||
int i;
|
||||
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
|
||||
struct ieee80211_sub_if_data *sdata;
|
||||
enum ieee80211_band band = local->hw.conf.channel->band;
|
||||
|
||||
sdata = rcu_dereference_protected(local->scan_sdata,
|
||||
lockdep_is_held(&local->mtx));;
|
||||
|
||||
for (i = 0; i < local->scan_req->n_ssids; i++)
|
||||
ieee80211_send_probe_req(
|
||||
sdata, NULL,
|
||||
@@ -438,7 +440,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
if (!ieee80211_can_scan(local, sdata)) {
|
||||
/* wait for the work to finish/time out */
|
||||
local->scan_req = req;
|
||||
local->scan_sdata = sdata;
|
||||
rcu_assign_pointer(local->scan_sdata, sdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -472,7 +474,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
local->scan_req = req;
|
||||
local->scan_sdata = sdata;
|
||||
rcu_assign_pointer(local->scan_sdata, sdata);
|
||||
|
||||
if (local->ops->hw_scan) {
|
||||
__set_bit(SCAN_HW_SCANNING, &local->scanning);
|
||||
@@ -532,7 +534,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
ieee80211_recalc_idle(local);
|
||||
|
||||
local->scan_req = NULL;
|
||||
local->scan_sdata = NULL;
|
||||
rcu_assign_pointer(local->scan_sdata, NULL);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -719,7 +721,8 @@ void ieee80211_scan_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
sdata = local->scan_sdata;
|
||||
sdata = rcu_dereference_protected(local->scan_sdata,
|
||||
lockdep_is_held(&local->mtx));
|
||||
|
||||
/* When scanning on-channel, the first-callback means completed. */
|
||||
if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
|
||||
@@ -740,7 +743,7 @@ void ieee80211_scan_work(struct work_struct *work)
|
||||
int rc;
|
||||
|
||||
local->scan_req = NULL;
|
||||
local->scan_sdata = NULL;
|
||||
rcu_assign_pointer(local->scan_sdata, NULL);
|
||||
|
||||
rc = __ieee80211_start_scan(sdata, req);
|
||||
if (rc) {
|
||||
@@ -892,7 +895,9 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
|
||||
|
||||
if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
|
||||
if (local->ops->cancel_hw_scan)
|
||||
drv_cancel_hw_scan(local, local->scan_sdata);
|
||||
drv_cancel_hw_scan(local,
|
||||
rcu_dereference_protected(local->scan_sdata,
|
||||
lockdep_is_held(&local->mtx)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -914,9 +919,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int ret, i;
|
||||
|
||||
mutex_lock(&sdata->local->mtx);
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
if (local->sched_scanning) {
|
||||
if (rcu_access_pointer(local->sched_scan_sdata)) {
|
||||
ret = -EBUSY;
|
||||
goto out;
|
||||
}
|
||||
@@ -927,6 +932,9 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
|
||||
if (!local->hw.wiphy->bands[i])
|
||||
continue;
|
||||
|
||||
local->sched_scan_ies.ie[i] = kzalloc(2 +
|
||||
IEEE80211_MAX_SSID_LEN +
|
||||
local->scan_ies_len +
|
||||
@@ -947,7 +955,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
|
||||
ret = drv_sched_scan_start(local, sdata, req,
|
||||
&local->sched_scan_ies);
|
||||
if (ret == 0) {
|
||||
local->sched_scanning = true;
|
||||
rcu_assign_pointer(local->sched_scan_sdata, sdata);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -955,7 +963,7 @@ out_free:
|
||||
while (i > 0)
|
||||
kfree(local->sched_scan_ies.ie[--i]);
|
||||
out:
|
||||
mutex_unlock(&sdata->local->mtx);
|
||||
mutex_unlock(&local->mtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -964,22 +972,22 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata)
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
int ret = 0, i;
|
||||
|
||||
mutex_lock(&sdata->local->mtx);
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
if (!local->ops->sched_scan_stop) {
|
||||
ret = -ENOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (local->sched_scanning) {
|
||||
if (rcu_access_pointer(local->sched_scan_sdata)) {
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
|
||||
kfree(local->sched_scan_ies.ie[i]);
|
||||
|
||||
drv_sched_scan_stop(local, sdata);
|
||||
local->sched_scanning = false;
|
||||
rcu_assign_pointer(local->sched_scan_sdata, NULL);
|
||||
}
|
||||
out:
|
||||
mutex_unlock(&sdata->local->mtx);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1003,7 +1011,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
if (!local->sched_scanning) {
|
||||
if (!rcu_access_pointer(local->sched_scan_sdata)) {
|
||||
mutex_unlock(&local->mtx);
|
||||
return;
|
||||
}
|
||||
@@ -1011,7 +1019,7 @@ void ieee80211_sched_scan_stopped_work(struct work_struct *work)
|
||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
|
||||
kfree(local->sched_scan_ies.ie[i]);
|
||||
|
||||
local->sched_scanning = false;
|
||||
rcu_assign_pointer(local->sched_scan_sdata, NULL);
|
||||
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
|
Fai riferimento in un nuovo problema
Block a user