aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2013-04-10 09:31:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-04-10 09:31:39 -0400
commit6fe5468f452c0c40348ebd4e737758a842286ca8 (patch)
treebefe5ab33c457a9e695b65be72600f383266e611 /net
parentdeb09280cd72ceb8b0679490f076d0e9f30dd456 (diff)
parent69a2bac8984c4e6dba78b330ed183fd580c65e99 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts: drivers/net/wireless/rt2x00/rt2x00pci.c
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c6
-rw-r--r--net/mac80211/chan.c17
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/iface.c2
-rw-r--r--net/mac80211/offchannel.c23
-rw-r--r--net/nfc/llcp/llcp.c8
-rw-r--r--net/nfc/llcp/sock.c6
-rw-r--r--net/wireless/sme.c2
8 files changed, 44 insertions, 24 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e5c1441ac2b8..c50c19402588 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2641,7 +2641,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
2641 list_del(&dep->list); 2641 list_del(&dep->list);
2642 mutex_unlock(&local->mtx); 2642 mutex_unlock(&local->mtx);
2643 2643
2644 ieee80211_roc_notify_destroy(dep); 2644 ieee80211_roc_notify_destroy(dep, true);
2645 return 0; 2645 return 0;
2646 } 2646 }
2647 2647
@@ -2681,7 +2681,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
2681 ieee80211_start_next_roc(local); 2681 ieee80211_start_next_roc(local);
2682 mutex_unlock(&local->mtx); 2682 mutex_unlock(&local->mtx);
2683 2683
2684 ieee80211_roc_notify_destroy(found); 2684 ieee80211_roc_notify_destroy(found, true);
2685 } else { 2685 } else {
2686 /* work may be pending so use it all the time */ 2686 /* work may be pending so use it all the time */
2687 found->abort = true; 2687 found->abort = true;
@@ -2691,6 +2691,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
2691 2691
2692 /* work will clean up etc */ 2692 /* work will clean up etc */
2693 flush_delayed_work(&found->work); 2693 flush_delayed_work(&found->work);
2694 WARN_ON(!found->to_be_freed);
2695 kfree(found);
2694 } 2696 }
2695 2697
2696 return 0; 2698 return 0;
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 78c0d90dd641..931be419ab5a 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
63 enum ieee80211_chanctx_mode mode) 63 enum ieee80211_chanctx_mode mode)
64{ 64{
65 struct ieee80211_chanctx *ctx; 65 struct ieee80211_chanctx *ctx;
66 u32 changed;
66 int err; 67 int err;
67 68
68 lockdep_assert_held(&local->chanctx_mtx); 69 lockdep_assert_held(&local->chanctx_mtx);
@@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
76 ctx->conf.rx_chains_dynamic = 1; 77 ctx->conf.rx_chains_dynamic = 1;
77 ctx->mode = mode; 78 ctx->mode = mode;
78 79
80 /* acquire mutex to prevent idle from changing */
81 mutex_lock(&local->mtx);
82 /* turn idle off *before* setting channel -- some drivers need that */
83 changed = ieee80211_idle_off(local);
84 if (changed)
85 ieee80211_hw_config(local, changed);
86
79 if (!local->use_chanctx) { 87 if (!local->use_chanctx) {
80 local->_oper_channel_type = 88 local->_oper_channel_type =
81 cfg80211_get_chandef_type(chandef); 89 cfg80211_get_chandef_type(chandef);
@@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
85 err = drv_add_chanctx(local, ctx); 93 err = drv_add_chanctx(local, ctx);
86 if (err) { 94 if (err) {
87 kfree(ctx); 95 kfree(ctx);
88 return ERR_PTR(err); 96 ctx = ERR_PTR(err);
97
98 ieee80211_recalc_idle(local);
99 goto out;
89 } 100 }
90 } 101 }
91 102
103 /* and keep the mutex held until the new chanctx is on the list */
92 list_add_rcu(&ctx->list, &local->chanctx_list); 104 list_add_rcu(&ctx->list, &local->chanctx_list);
93 105
94 mutex_lock(&local->mtx); 106 out:
95 ieee80211_recalc_idle(local);
96 mutex_unlock(&local->mtx); 107 mutex_unlock(&local->mtx);
97 108
98 return ctx; 109 return ctx;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ae2d1754b792..0b09716d22ad 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -309,6 +309,7 @@ struct ieee80211_roc_work {
309 struct ieee80211_channel *chan; 309 struct ieee80211_channel *chan;
310 310
311 bool started, abort, hw_begun, notified; 311 bool started, abort, hw_begun, notified;
312 bool to_be_freed;
312 313
313 unsigned long hw_start_time; 314 unsigned long hw_start_time;
314 315
@@ -1330,7 +1331,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local);
1330void ieee80211_roc_setup(struct ieee80211_local *local); 1331void ieee80211_roc_setup(struct ieee80211_local *local);
1331void ieee80211_start_next_roc(struct ieee80211_local *local); 1332void ieee80211_start_next_roc(struct ieee80211_local *local);
1332void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata); 1333void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
1333void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc); 1334void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
1334void ieee80211_sw_roc_work(struct work_struct *work); 1335void ieee80211_sw_roc_work(struct work_struct *work);
1335void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); 1336void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
1336 1337
@@ -1344,6 +1345,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
1344 enum nl80211_iftype type); 1345 enum nl80211_iftype type);
1345void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata); 1346void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
1346void ieee80211_remove_interfaces(struct ieee80211_local *local); 1347void ieee80211_remove_interfaces(struct ieee80211_local *local);
1348u32 ieee80211_idle_off(struct ieee80211_local *local);
1347void ieee80211_recalc_idle(struct ieee80211_local *local); 1349void ieee80211_recalc_idle(struct ieee80211_local *local);
1348void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, 1350void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
1349 const int offset); 1351 const int offset);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2a3c1e9bdf25..69aaba79a9f7 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
78 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); 78 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
79} 79}
80 80
81static u32 ieee80211_idle_off(struct ieee80211_local *local) 81u32 ieee80211_idle_off(struct ieee80211_local *local)
82{ 82{
83 if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) 83 if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
84 return 0; 84 return 0;
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index b01eb7314ec6..cce795871ab1 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
297 } 297 }
298} 298}
299 299
300void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) 300void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free)
301{ 301{
302 struct ieee80211_roc_work *dep, *tmp; 302 struct ieee80211_roc_work *dep, *tmp;
303 303
304 if (WARN_ON(roc->to_be_freed))
305 return;
306
304 /* was never transmitted */ 307 /* was never transmitted */
305 if (roc->frame) { 308 if (roc->frame) {
306 cfg80211_mgmt_tx_status(&roc->sdata->wdev, 309 cfg80211_mgmt_tx_status(&roc->sdata->wdev,
@@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
316 GFP_KERNEL); 319 GFP_KERNEL);
317 320
318 list_for_each_entry_safe(dep, tmp, &roc->dependents, list) 321 list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
319 ieee80211_roc_notify_destroy(dep); 322 ieee80211_roc_notify_destroy(dep, true);
320 323
321 kfree(roc); 324 if (free)
325 kfree(roc);
326 else
327 roc->to_be_freed = true;
322} 328}
323 329
324void ieee80211_sw_roc_work(struct work_struct *work) 330void ieee80211_sw_roc_work(struct work_struct *work)
@@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work)
331 337
332 mutex_lock(&local->mtx); 338 mutex_lock(&local->mtx);
333 339
340 if (roc->to_be_freed)
341 goto out_unlock;
342
334 if (roc->abort) 343 if (roc->abort)
335 goto finish; 344 goto finish;
336 345
@@ -370,7 +379,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
370 finish: 379 finish:
371 list_del(&roc->list); 380 list_del(&roc->list);
372 started = roc->started; 381 started = roc->started;
373 ieee80211_roc_notify_destroy(roc); 382 ieee80211_roc_notify_destroy(roc, !roc->abort);
374 383
375 if (started) { 384 if (started) {
376 ieee80211_flush_queues(local, NULL); 385 ieee80211_flush_queues(local, NULL);
@@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
410 419
411 list_del(&roc->list); 420 list_del(&roc->list);
412 421
413 ieee80211_roc_notify_destroy(roc); 422 ieee80211_roc_notify_destroy(roc, true);
414 423
415 /* if there's another roc, start it now */ 424 /* if there's another roc, start it now */
416 ieee80211_start_next_roc(local); 425 ieee80211_start_next_roc(local);
@@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
460 list_for_each_entry_safe(roc, tmp, &tmp_list, list) { 469 list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
461 if (local->ops->remain_on_channel) { 470 if (local->ops->remain_on_channel) {
462 list_del(&roc->list); 471 list_del(&roc->list);
463 ieee80211_roc_notify_destroy(roc); 472 ieee80211_roc_notify_destroy(roc, true);
464 } else { 473 } else {
465 ieee80211_queue_delayed_work(&local->hw, &roc->work, 0); 474 ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
466 475
467 /* work will clean up etc */ 476 /* work will clean up etc */
468 flush_delayed_work(&roc->work); 477 flush_delayed_work(&roc->work);
478 WARN_ON(!roc->to_be_freed);
479 kfree(roc);
469 } 480 }
470 } 481 }
471 482
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c
index bb67b98b9797..7de0368aff0c 100644
--- a/net/nfc/llcp/llcp.c
+++ b/net/nfc/llcp/llcp.c
@@ -107,8 +107,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
107 accept_sk->sk_state_change(sk); 107 accept_sk->sk_state_change(sk);
108 108
109 bh_unlock_sock(accept_sk); 109 bh_unlock_sock(accept_sk);
110
111 sock_orphan(accept_sk);
112 } 110 }
113 111
114 if (listen == true) { 112 if (listen == true) {
@@ -134,8 +132,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
134 132
135 bh_unlock_sock(sk); 133 bh_unlock_sock(sk);
136 134
137 sock_orphan(sk);
138
139 sk_del_node_init(sk); 135 sk_del_node_init(sk);
140 } 136 }
141 137
@@ -164,8 +160,6 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
164 160
165 bh_unlock_sock(sk); 161 bh_unlock_sock(sk);
166 162
167 sock_orphan(sk);
168
169 sk_del_node_init(sk); 163 sk_del_node_init(sk);
170 } 164 }
171 165
@@ -869,7 +863,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
869 skb_get(skb); 863 skb_get(skb);
870 } else { 864 } else {
871 pr_err("Receive queue is full\n"); 865 pr_err("Receive queue is full\n");
872 kfree_skb(skb);
873 } 866 }
874 867
875 nfc_llcp_sock_put(llcp_sock); 868 nfc_llcp_sock_put(llcp_sock);
@@ -1072,7 +1065,6 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
1072 skb_get(skb); 1065 skb_get(skb);
1073 } else { 1066 } else {
1074 pr_err("Receive queue is full\n"); 1067 pr_err("Receive queue is full\n");
1075 kfree_skb(skb);
1076 } 1068 }
1077 } 1069 }
1078 1070
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c
index f1b377e247fe..6fa76704cb13 100644
--- a/net/nfc/llcp/sock.c
+++ b/net/nfc/llcp/sock.c
@@ -388,7 +388,9 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
388 } 388 }
389 389
390 if (sk->sk_state == LLCP_CONNECTED || !newsock) { 390 if (sk->sk_state == LLCP_CONNECTED || !newsock) {
391 nfc_llcp_accept_unlink(sk); 391 list_del_init(&lsk->accept_queue);
392 sock_put(sk);
393
392 if (newsock) 394 if (newsock)
393 sock_graft(sk, newsock); 395 sock_graft(sk, newsock);
394 396
@@ -582,8 +584,6 @@ static int llcp_sock_release(struct socket *sock)
582 nfc_llcp_accept_unlink(accept_sk); 584 nfc_llcp_accept_unlink(accept_sk);
583 585
584 release_sock(accept_sk); 586 release_sock(accept_sk);
585
586 sock_orphan(accept_sk);
587 } 587 }
588 } 588 }
589 589
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 818ad637819a..a9dc5c736df0 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -228,6 +228,7 @@ void cfg80211_conn_work(struct work_struct *work)
228 rtnl_lock(); 228 rtnl_lock();
229 cfg80211_lock_rdev(rdev); 229 cfg80211_lock_rdev(rdev);
230 mutex_lock(&rdev->devlist_mtx); 230 mutex_lock(&rdev->devlist_mtx);
231 mutex_lock(&rdev->sched_scan_mtx);
231 232
232 list_for_each_entry(wdev, &rdev->wdev_list, list) { 233 list_for_each_entry(wdev, &rdev->wdev_list, list) {
233 wdev_lock(wdev); 234 wdev_lock(wdev);
@@ -252,6 +253,7 @@ void cfg80211_conn_work(struct work_struct *work)
252 wdev_unlock(wdev); 253 wdev_unlock(wdev);
253 } 254 }
254 255
256 mutex_unlock(&rdev->sched_scan_mtx);
255 mutex_unlock(&rdev->devlist_mtx); 257 mutex_unlock(&rdev->devlist_mtx);
256 cfg80211_unlock_rdev(rdev); 258 cfg80211_unlock_rdev(rdev);
257 rtnl_unlock(); 259 rtnl_unlock();