diff options
Diffstat (limited to 'net/wireless/pmsr.c')
| -rw-r--r-- | net/wireless/pmsr.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c index de9286703280..0216ab555249 100644 --- a/net/wireless/pmsr.c +++ b/net/wireless/pmsr.c | |||
| @@ -256,8 +256,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) | |||
| 256 | if (err) | 256 | if (err) |
| 257 | goto out_err; | 257 | goto out_err; |
| 258 | } else { | 258 | } else { |
| 259 | memcpy(req->mac_addr, nla_data(info->attrs[NL80211_ATTR_MAC]), | 259 | memcpy(req->mac_addr, wdev_address(wdev), ETH_ALEN); |
| 260 | ETH_ALEN); | ||
| 261 | memset(req->mac_addr_mask, 0xff, ETH_ALEN); | 260 | memset(req->mac_addr_mask, 0xff, ETH_ALEN); |
| 262 | } | 261 | } |
| 263 | 262 | ||
| @@ -272,6 +271,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info) | |||
| 272 | 271 | ||
| 273 | req->n_peers = count; | 272 | req->n_peers = count; |
| 274 | req->cookie = cfg80211_assign_cookie(rdev); | 273 | req->cookie = cfg80211_assign_cookie(rdev); |
| 274 | req->nl_portid = info->snd_portid; | ||
| 275 | 275 | ||
| 276 | err = rdev_start_pmsr(rdev, wdev, req); | 276 | err = rdev_start_pmsr(rdev, wdev, req); |
| 277 | if (err) | 277 | if (err) |
| @@ -530,14 +530,14 @@ free: | |||
| 530 | } | 530 | } |
| 531 | EXPORT_SYMBOL_GPL(cfg80211_pmsr_report); | 531 | EXPORT_SYMBOL_GPL(cfg80211_pmsr_report); |
| 532 | 532 | ||
| 533 | void cfg80211_pmsr_free_wk(struct work_struct *work) | 533 | static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev) |
| 534 | { | 534 | { |
| 535 | struct wireless_dev *wdev = container_of(work, struct wireless_dev, | ||
| 536 | pmsr_free_wk); | ||
| 537 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | 535 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); |
| 538 | struct cfg80211_pmsr_request *req, *tmp; | 536 | struct cfg80211_pmsr_request *req, *tmp; |
| 539 | LIST_HEAD(free_list); | 537 | LIST_HEAD(free_list); |
| 540 | 538 | ||
| 539 | lockdep_assert_held(&wdev->mtx); | ||
| 540 | |||
| 541 | spin_lock_bh(&wdev->pmsr_lock); | 541 | spin_lock_bh(&wdev->pmsr_lock); |
| 542 | list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) { | 542 | list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) { |
| 543 | if (req->nl_portid) | 543 | if (req->nl_portid) |
| @@ -547,14 +547,22 @@ void cfg80211_pmsr_free_wk(struct work_struct *work) | |||
| 547 | spin_unlock_bh(&wdev->pmsr_lock); | 547 | spin_unlock_bh(&wdev->pmsr_lock); |
| 548 | 548 | ||
| 549 | list_for_each_entry_safe(req, tmp, &free_list, list) { | 549 | list_for_each_entry_safe(req, tmp, &free_list, list) { |
| 550 | wdev_lock(wdev); | ||
| 551 | rdev_abort_pmsr(rdev, wdev, req); | 550 | rdev_abort_pmsr(rdev, wdev, req); |
| 552 | wdev_unlock(wdev); | ||
| 553 | 551 | ||
| 554 | kfree(req); | 552 | kfree(req); |
| 555 | } | 553 | } |
| 556 | } | 554 | } |
| 557 | 555 | ||
| 556 | void cfg80211_pmsr_free_wk(struct work_struct *work) | ||
| 557 | { | ||
| 558 | struct wireless_dev *wdev = container_of(work, struct wireless_dev, | ||
| 559 | pmsr_free_wk); | ||
| 560 | |||
| 561 | wdev_lock(wdev); | ||
| 562 | cfg80211_pmsr_process_abort(wdev); | ||
| 563 | wdev_unlock(wdev); | ||
| 564 | } | ||
| 565 | |||
| 558 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) | 566 | void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) |
| 559 | { | 567 | { |
| 560 | struct cfg80211_pmsr_request *req; | 568 | struct cfg80211_pmsr_request *req; |
| @@ -568,8 +576,8 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev) | |||
| 568 | spin_unlock_bh(&wdev->pmsr_lock); | 576 | spin_unlock_bh(&wdev->pmsr_lock); |
| 569 | 577 | ||
| 570 | if (found) | 578 | if (found) |
| 571 | schedule_work(&wdev->pmsr_free_wk); | 579 | cfg80211_pmsr_process_abort(wdev); |
| 572 | flush_work(&wdev->pmsr_free_wk); | 580 | |
| 573 | WARN_ON(!list_empty(&wdev->pmsr_list)); | 581 | WARN_ON(!list_empty(&wdev->pmsr_list)); |
| 574 | } | 582 | } |
| 575 | 583 | ||
