Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem

This commit is contained in:
John W. Linville
2012-07-20 12:30:48 -04:00
163 ha cambiato i file con 5139 aggiunte e 2915 eliminazioni

Vedi File

@@ -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);