Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
This commit is contained in:
commit
fae172136c
|
@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
|
||||||
static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
int ret = 0;
|
int ret;
|
||||||
|
|
||||||
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
ASSERT_RTNL();
|
||||||
|
|
||||||
if (local->monitor_sdata)
|
if (local->monitor_sdata)
|
||||||
goto out_unlock;
|
return 0;
|
||||||
|
|
||||||
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
|
sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
|
||||||
if (!sdata) {
|
if (!sdata)
|
||||||
ret = -ENOMEM;
|
return -ENOMEM;
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* set up data */
|
/* set up data */
|
||||||
sdata->local = local;
|
sdata->local = local;
|
||||||
|
@ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
||||||
if (WARN_ON(ret)) {
|
if (WARN_ON(ret)) {
|
||||||
/* ok .. stupid driver, it asked for this! */
|
/* ok .. stupid driver, it asked for this! */
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
goto out_unlock;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ieee80211_check_queues(sdata);
|
ret = ieee80211_check_queues(sdata);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
goto out_unlock;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
|
ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
|
||||||
|
@ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
drv_remove_interface(local, sdata);
|
drv_remove_interface(local, sdata);
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
goto out_unlock;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&local->iflist_mtx);
|
||||||
rcu_assign_pointer(local->monitor_sdata, sdata);
|
rcu_assign_pointer(local->monitor_sdata, sdata);
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&local->iflist_mtx);
|
mutex_unlock(&local->iflist_mtx);
|
||||||
return ret;
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
||||||
|
@ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
||||||
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ASSERT_RTNL();
|
||||||
|
|
||||||
mutex_lock(&local->iflist_mtx);
|
mutex_lock(&local->iflist_mtx);
|
||||||
|
|
||||||
sdata = rcu_dereference_protected(local->monitor_sdata,
|
sdata = rcu_dereference_protected(local->monitor_sdata,
|
||||||
lockdep_is_held(&local->iflist_mtx));
|
lockdep_is_held(&local->iflist_mtx));
|
||||||
if (!sdata)
|
if (!sdata) {
|
||||||
goto out_unlock;
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
rcu_assign_pointer(local->monitor_sdata, NULL);
|
rcu_assign_pointer(local->monitor_sdata, NULL);
|
||||||
|
mutex_unlock(&local->iflist_mtx);
|
||||||
|
|
||||||
synchronize_net();
|
synchronize_net();
|
||||||
|
|
||||||
ieee80211_vif_release_channel(sdata);
|
ieee80211_vif_release_channel(sdata);
|
||||||
|
@ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
|
||||||
drv_remove_interface(local, sdata);
|
drv_remove_interface(local, sdata);
|
||||||
|
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
out_unlock:
|
|
||||||
mutex_unlock(&local->iflist_mtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1060,7 +1060,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
||||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
if (ieee80211_vif_is_mesh(&sdata->vif) &&
|
||||||
|
ieee80211_sdata_running(sdata))
|
||||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3608,8 +3608,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
|
||||||
|
|
||||||
/* Restart STA timers */
|
/* Restart STA timers */
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
ieee80211_restart_sta_timer(sdata);
|
if (ieee80211_sdata_running(sdata))
|
||||||
|
ieee80211_restart_sta_timer(sdata);
|
||||||
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2675,7 +2675,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
|
||||||
|
|
||||||
memset(nskb->cb, 0, sizeof(nskb->cb));
|
memset(nskb->cb, 0, sizeof(nskb->cb));
|
||||||
|
|
||||||
ieee80211_tx_skb(rx->sdata, nskb);
|
if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
|
||||||
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
|
||||||
|
|
||||||
|
info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
|
||||||
|
IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
|
||||||
|
IEEE80211_TX_CTL_NO_CCK_RATE;
|
||||||
|
if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
|
||||||
|
info->hw_queue =
|
||||||
|
local->hw.offchannel_tx_hw_queue;
|
||||||
|
}
|
||||||
|
|
||||||
|
__ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
|
||||||
|
status->band);
|
||||||
}
|
}
|
||||||
dev_kfree_skb(rx->skb);
|
dev_kfree_skb(rx->skb);
|
||||||
return RX_QUEUED;
|
return RX_QUEUED;
|
||||||
|
|
|
@ -766,6 +766,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||||
struct ieee80211_local *local;
|
struct ieee80211_local *local;
|
||||||
struct ieee80211_sub_if_data *sdata;
|
struct ieee80211_sub_if_data *sdata;
|
||||||
int ret, i;
|
int ret, i;
|
||||||
|
bool have_key = false;
|
||||||
|
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
|
@ -793,12 +794,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
|
||||||
list_del_rcu(&sta->list);
|
list_del_rcu(&sta->list);
|
||||||
|
|
||||||
mutex_lock(&local->key_mtx);
|
mutex_lock(&local->key_mtx);
|
||||||
for (i = 0; i < NUM_DEFAULT_KEYS; i++)
|
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
|
||||||
__ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
|
__ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
|
||||||
if (sta->ptk)
|
have_key = true;
|
||||||
|
}
|
||||||
|
if (sta->ptk) {
|
||||||
__ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
|
__ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
|
||||||
|
have_key = true;
|
||||||
|
}
|
||||||
mutex_unlock(&local->key_mtx);
|
mutex_unlock(&local->key_mtx);
|
||||||
|
|
||||||
|
if (!have_key)
|
||||||
|
synchronize_net();
|
||||||
|
|
||||||
sta->dead = true;
|
sta->dead = true;
|
||||||
|
|
||||||
local->num_sta--;
|
local->num_sta--;
|
||||||
|
|
|
@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
|
||||||
rdev_rfkill_poll(rdev);
|
rdev_rfkill_poll(rdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
||||||
|
struct wireless_dev *wdev)
|
||||||
|
{
|
||||||
|
lockdep_assert_held(&rdev->devlist_mtx);
|
||||||
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
|
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!wdev->p2p_started)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rdev_stop_p2p_device(rdev, wdev);
|
||||||
|
wdev->p2p_started = false;
|
||||||
|
|
||||||
|
rdev->opencount--;
|
||||||
|
|
||||||
|
if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
|
||||||
|
bool busy = work_busy(&rdev->scan_done_wk);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the work isn't pending or running (in which case it would
|
||||||
|
* be waiting for the lock we hold) the driver didn't properly
|
||||||
|
* cancel the scan when the interface was removed. In this case
|
||||||
|
* warn and leak the scan request object to not crash later.
|
||||||
|
*/
|
||||||
|
WARN_ON(!busy);
|
||||||
|
|
||||||
|
rdev->scan_req->aborted = true;
|
||||||
|
___cfg80211_scan_done(rdev, !busy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
||||||
{
|
{
|
||||||
struct cfg80211_registered_device *rdev = data;
|
struct cfg80211_registered_device *rdev = data;
|
||||||
|
@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
|
||||||
|
/* read-only iteration need not hold the devlist_mtx */
|
||||||
|
|
||||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||||
if (wdev->netdev) {
|
if (wdev->netdev) {
|
||||||
|
@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
|
||||||
/* otherwise, check iftype */
|
/* otherwise, check iftype */
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
if (!wdev->p2p_started)
|
/* but this requires it */
|
||||||
break;
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
rdev_stop_p2p_device(rdev, wdev);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev->p2p_started = false;
|
cfg80211_stop_p2p_device(rdev, wdev);
|
||||||
rdev->opencount--;
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
|
||||||
rtnl_unlock();
|
rtnl_unlock();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -745,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work)
|
||||||
wdev = container_of(work, struct wireless_dev, cleanup_work);
|
wdev = container_of(work, struct wireless_dev, cleanup_work);
|
||||||
rdev = wiphy_to_dev(wdev->wiphy);
|
rdev = wiphy_to_dev(wdev->wiphy);
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
||||||
rdev->scan_req->aborted = true;
|
rdev->scan_req->aborted = true;
|
||||||
___cfg80211_scan_done(rdev, true);
|
___cfg80211_scan_done(rdev, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg80211_unlock_rdev(rdev);
|
|
||||||
|
|
||||||
mutex_lock(&rdev->sched_scan_mtx);
|
|
||||||
|
|
||||||
if (WARN_ON(rdev->sched_scan_req &&
|
if (WARN_ON(rdev->sched_scan_req &&
|
||||||
rdev->sched_scan_req->dev == wdev->netdev)) {
|
rdev->sched_scan_req->dev == wdev->netdev)) {
|
||||||
__cfg80211_stop_sched_scan(rdev, false);
|
__cfg80211_stop_sched_scan(rdev, false);
|
||||||
|
@ -781,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
list_del_rcu(&wdev->list);
|
list_del_rcu(&wdev->list);
|
||||||
rdev->devlist_generation++;
|
rdev->devlist_generation++;
|
||||||
|
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
case NL80211_IFTYPE_P2P_DEVICE:
|
case NL80211_IFTYPE_P2P_DEVICE:
|
||||||
if (!wdev->p2p_started)
|
cfg80211_stop_p2p_device(rdev, wdev);
|
||||||
break;
|
|
||||||
rdev_stop_p2p_device(rdev, wdev);
|
|
||||||
wdev->p2p_started = false;
|
|
||||||
rdev->opencount--;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARN_ON_ONCE(1);
|
WARN_ON_ONCE(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
EXPORT_SYMBOL(cfg80211_unregister_wdev);
|
||||||
|
@ -936,6 +964,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||||
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
|
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
switch (wdev->iftype) {
|
switch (wdev->iftype) {
|
||||||
#ifdef CONFIG_CFG80211_WEXT
|
#ifdef CONFIG_CFG80211_WEXT
|
||||||
|
@ -967,6 +996,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
rdev->opencount++;
|
rdev->opencount++;
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
|
|
|
@ -503,6 +503,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
||||||
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
||||||
enum nl80211_iftype iftype, int num);
|
enum nl80211_iftype iftype, int num);
|
||||||
|
|
||||||
|
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
|
||||||
|
struct wireless_dev *wdev);
|
||||||
|
|
||||||
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
|
#define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
|
||||||
|
|
||||||
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
#ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
|
||||||
|
|
|
@ -4702,14 +4702,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!rdev->ops->scan)
|
if (!rdev->ops->scan)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (rdev->scan_req)
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
return -EBUSY;
|
if (rdev->scan_req) {
|
||||||
|
err = -EBUSY;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
|
||||||
n_channels = validate_scan_freqs(
|
n_channels = validate_scan_freqs(
|
||||||
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
|
||||||
if (!n_channels)
|
if (!n_channels) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
enum ieee80211_band band;
|
enum ieee80211_band band;
|
||||||
n_channels = 0;
|
n_channels = 0;
|
||||||
|
@ -4723,23 +4728,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
|
nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
|
||||||
n_ssids++;
|
n_ssids++;
|
||||||
|
|
||||||
if (n_ssids > wiphy->max_scan_ssids)
|
if (n_ssids > wiphy->max_scan_ssids) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (info->attrs[NL80211_ATTR_IE])
|
if (info->attrs[NL80211_ATTR_IE])
|
||||||
ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
|
||||||
else
|
else
|
||||||
ie_len = 0;
|
ie_len = 0;
|
||||||
|
|
||||||
if (ie_len > wiphy->max_scan_ie_len)
|
if (ie_len > wiphy->max_scan_ie_len) {
|
||||||
return -EINVAL;
|
err = -EINVAL;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
request = kzalloc(sizeof(*request)
|
request = kzalloc(sizeof(*request)
|
||||||
+ sizeof(*request->ssids) * n_ssids
|
+ sizeof(*request->ssids) * n_ssids
|
||||||
+ sizeof(*request->channels) * n_channels
|
+ sizeof(*request->channels) * n_channels
|
||||||
+ ie_len, GFP_KERNEL);
|
+ ie_len, GFP_KERNEL);
|
||||||
if (!request)
|
if (!request) {
|
||||||
return -ENOMEM;
|
err = -ENOMEM;
|
||||||
|
goto unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (n_ssids)
|
if (n_ssids)
|
||||||
request->ssids = (void *)&request->channels[n_channels];
|
request->ssids = (void *)&request->channels[n_channels];
|
||||||
|
@ -4876,6 +4887,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
|
||||||
kfree(request);
|
kfree(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unlock:
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7749,20 +7762,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
|
||||||
if (!rdev->ops->stop_p2p_device)
|
if (!rdev->ops->stop_p2p_device)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (!wdev->p2p_started)
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
return 0;
|
cfg80211_stop_p2p_device(rdev, wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
rdev_stop_p2p_device(rdev, wdev);
|
|
||||||
wdev->p2p_started = false;
|
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
|
||||||
rdev->opencount--;
|
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
|
||||||
|
|
||||||
if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
|
|
||||||
rdev->scan_req->aborted = true;
|
|
||||||
___cfg80211_scan_done(rdev, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -8486,7 +8488,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
|
||||||
struct nlattr *nest;
|
struct nlattr *nest;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
ASSERT_RDEV_LOCK(rdev);
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
if (WARN_ON(!req))
|
if (WARN_ON(!req))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
|
||||||
union iwreq_data wrqu;
|
union iwreq_data wrqu;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ASSERT_RDEV_LOCK(rdev);
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
request = rdev->scan_req;
|
request = rdev->scan_req;
|
||||||
|
|
||||||
|
@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
|
||||||
rdev = container_of(wk, struct cfg80211_registered_device,
|
rdev = container_of(wk, struct cfg80211_registered_device,
|
||||||
scan_done_wk);
|
scan_done_wk);
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
___cfg80211_scan_done(rdev, false);
|
___cfg80211_scan_done(rdev, false);
|
||||||
cfg80211_unlock_rdev(rdev);
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
|
||||||
|
@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
||||||
found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
|
found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
found->pub.beacon_interval = tmp->pub.beacon_interval;
|
|
||||||
found->pub.signal = tmp->pub.signal;
|
|
||||||
found->pub.capability = tmp->pub.capability;
|
|
||||||
found->ts = tmp->ts;
|
|
||||||
|
|
||||||
/* Update IEs */
|
/* Update IEs */
|
||||||
if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
|
if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
|
||||||
const struct cfg80211_bss_ies *old;
|
const struct cfg80211_bss_ies *old;
|
||||||
|
@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
||||||
|
|
||||||
if (found->pub.hidden_beacon_bss &&
|
if (found->pub.hidden_beacon_bss &&
|
||||||
!list_empty(&found->hidden_list)) {
|
!list_empty(&found->hidden_list)) {
|
||||||
|
const struct cfg80211_bss_ies *f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The found BSS struct is one of the probe
|
* The found BSS struct is one of the probe
|
||||||
* response members of a group, but we're
|
* response members of a group, but we're
|
||||||
|
@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
||||||
* SSID to showing it, which is confusing so
|
* SSID to showing it, which is confusing so
|
||||||
* drop this information.
|
* drop this information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
f = rcu_access_pointer(tmp->pub.beacon_ies);
|
||||||
|
kfree_rcu((struct cfg80211_bss_ies *)f,
|
||||||
|
rcu_head);
|
||||||
goto drop;
|
goto drop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
|
||||||
kfree_rcu((struct cfg80211_bss_ies *)old,
|
kfree_rcu((struct cfg80211_bss_ies *)old,
|
||||||
rcu_head);
|
rcu_head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
found->pub.beacon_interval = tmp->pub.beacon_interval;
|
||||||
|
found->pub.signal = tmp->pub.signal;
|
||||||
|
found->pub.capability = tmp->pub.capability;
|
||||||
|
found->ts = tmp->ts;
|
||||||
} else {
|
} else {
|
||||||
struct cfg80211_internal_bss *new;
|
struct cfg80211_internal_bss *new;
|
||||||
struct cfg80211_internal_bss *hidden;
|
struct cfg80211_internal_bss *hidden;
|
||||||
|
@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||||
if (IS_ERR(rdev))
|
if (IS_ERR(rdev))
|
||||||
return PTR_ERR(rdev);
|
return PTR_ERR(rdev);
|
||||||
|
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
if (rdev->scan_req) {
|
if (rdev->scan_req) {
|
||||||
err = -EBUSY;
|
err = -EBUSY;
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
|
||||||
dev_hold(dev);
|
dev_hold(dev);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
kfree(creq);
|
kfree(creq);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
ASSERT_RDEV_LOCK(rdev);
|
ASSERT_RDEV_LOCK(rdev);
|
||||||
ASSERT_WDEV_LOCK(wdev);
|
ASSERT_WDEV_LOCK(wdev);
|
||||||
|
lockdep_assert_held(&rdev->sched_scan_mtx);
|
||||||
|
|
||||||
if (rdev->scan_req)
|
if (rdev->scan_req)
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -320,11 +321,9 @@ void cfg80211_sme_scan_done(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||||
|
|
||||||
mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
|
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
__cfg80211_sme_scan_done(dev);
|
__cfg80211_sme_scan_done(dev);
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cfg80211_sme_rx_auth(struct net_device *dev,
|
void cfg80211_sme_rx_auth(struct net_device *dev,
|
||||||
|
@ -924,9 +923,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
/* might request scan - scan_mtx -> wdev_mtx dependency */
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(dev->ieee80211_ptr);
|
wdev_lock(dev->ieee80211_ptr);
|
||||||
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
|
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
|
||||||
wdev_unlock(dev->ieee80211_ptr);
|
wdev_unlock(dev->ieee80211_ptr);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
|
|
|
@ -27,7 +27,8 @@
|
||||||
#define WIPHY_PR_ARG __entry->wiphy_name
|
#define WIPHY_PR_ARG __entry->wiphy_name
|
||||||
|
|
||||||
#define WDEV_ENTRY __field(u32, id)
|
#define WDEV_ENTRY __field(u32, id)
|
||||||
#define WDEV_ASSIGN (__entry->id) = (wdev ? wdev->identifier : 0)
|
#define WDEV_ASSIGN (__entry->id) = (!IS_ERR_OR_NULL(wdev) \
|
||||||
|
? wdev->identifier : 0)
|
||||||
#define WDEV_PR_FMT "wdev(%u)"
|
#define WDEV_PR_FMT "wdev(%u)"
|
||||||
#define WDEV_PR_ARG (__entry->id)
|
#define WDEV_PR_ARG (__entry->id)
|
||||||
|
|
||||||
|
@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl,
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
WIPHY_ASSIGN;
|
WIPHY_ASSIGN;
|
||||||
WIPHY_ASSIGN;
|
NETDEV_ASSIGN;
|
||||||
__entry->acl_policy = params->acl_policy;
|
__entry->acl_policy = params->acl_policy;
|
||||||
),
|
),
|
||||||
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
|
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
|
||||||
|
|
|
@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||||
|
@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
|
||||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
err = 0;
|
err = 0;
|
||||||
|
@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
|
||||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
||||||
|
|
||||||
cfg80211_lock_rdev(rdev);
|
cfg80211_lock_rdev(rdev);
|
||||||
mutex_lock(&rdev->devlist_mtx);
|
mutex_lock(&rdev->devlist_mtx);
|
||||||
|
mutex_lock(&rdev->sched_scan_mtx);
|
||||||
wdev_lock(wdev);
|
wdev_lock(wdev);
|
||||||
|
|
||||||
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
if (wdev->sme_state != CFG80211_SME_IDLE) {
|
||||||
|
@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
|
||||||
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
err = cfg80211_mgd_wext_connect(rdev, wdev);
|
||||||
out:
|
out:
|
||||||
wdev_unlock(wdev);
|
wdev_unlock(wdev);
|
||||||
|
mutex_unlock(&rdev->sched_scan_mtx);
|
||||||
mutex_unlock(&rdev->devlist_mtx);
|
mutex_unlock(&rdev->devlist_mtx);
|
||||||
cfg80211_unlock_rdev(rdev);
|
cfg80211_unlock_rdev(rdev);
|
||||||
return err;
|
return err;
|
||||||
|
|
Loading…
Reference in a new issue