aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-08-26 03:30:32 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-08-26 03:52:58 -0400
commita98655387762394371b88cdfb8215884757978ab (patch)
tree612c1221bc1d7f8e84260953a40a507c229dda13 /net/mac80211
parentbcdd822007e44b1da1ad5a62f20b75ee7d8da608 (diff)
mac80211: fix change_interface queue assignments
Jouni reported that with mac80211_hwsim, multicast TX was causing crashes due to invalid vif->cab_queue assignment. It turns out that this is caused by change_interface() getting invoked and not having the vif->type/vif->p2p assigned correctly before calling the queue check (ieee80211_check_queues). Fix this by passing the 'external' interface type to the function and adjusting it accordingly. While at it, also fix the error path in change_interface, it wasn't correctly resetting to the external type but using the internal one instead. Fortunately this affects on hwsim because all other drivers set the vif->type/vif->p2p variables when changing iftype. This shouldn't be needed, but almost all implementations actually do it for their own internal handling. Reported-by: Jouni Malinen <j@w1.fi> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/iface.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7ca534bf4cea..fcecd633514e 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -308,12 +308,13 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
308 return 0; 308 return 0;
309} 309}
310 310
311static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) 311static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
312 enum nl80211_iftype iftype)
312{ 313{
313 int n_queues = sdata->local->hw.queues; 314 int n_queues = sdata->local->hw.queues;
314 int i; 315 int i;
315 316
316 if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) { 317 if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
317 for (i = 0; i < IEEE80211_NUM_ACS; i++) { 318 for (i = 0; i < IEEE80211_NUM_ACS; i++) {
318 if (WARN_ON_ONCE(sdata->vif.hw_queue[i] == 319 if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
319 IEEE80211_INVAL_HW_QUEUE)) 320 IEEE80211_INVAL_HW_QUEUE))
@@ -324,8 +325,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata)
324 } 325 }
325 } 326 }
326 327
327 if ((sdata->vif.type != NL80211_IFTYPE_AP && 328 if ((iftype != NL80211_IFTYPE_AP &&
328 sdata->vif.type != NL80211_IFTYPE_MESH_POINT) || 329 iftype != NL80211_IFTYPE_P2P_GO &&
330 iftype != NL80211_IFTYPE_MESH_POINT) ||
329 !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) { 331 !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) {
330 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; 332 sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
331 return 0; 333 return 0;
@@ -408,7 +410,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
408 return ret; 410 return ret;
409 } 411 }
410 412
411 ret = ieee80211_check_queues(sdata); 413 ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);
412 if (ret) { 414 if (ret) {
413 kfree(sdata); 415 kfree(sdata);
414 return ret; 416 return ret;
@@ -592,7 +594,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
592 res = drv_add_interface(local, sdata); 594 res = drv_add_interface(local, sdata);
593 if (res) 595 if (res)
594 goto err_stop; 596 goto err_stop;
595 res = ieee80211_check_queues(sdata); 597 res = ieee80211_check_queues(sdata,
598 ieee80211_vif_type_p2p(&sdata->vif));
596 if (res) 599 if (res)
597 goto err_del_interface; 600 goto err_del_interface;
598 } 601 }
@@ -1389,14 +1392,14 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
1389 1392
1390 ret = drv_change_interface(local, sdata, internal_type, p2p); 1393 ret = drv_change_interface(local, sdata, internal_type, p2p);
1391 if (ret) 1394 if (ret)
1392 type = sdata->vif.type; 1395 type = ieee80211_vif_type_p2p(&sdata->vif);
1393 1396
1394 /* 1397 /*
1395 * Ignore return value here, there's not much we can do since 1398 * Ignore return value here, there's not much we can do since
1396 * the driver changed the interface type internally already. 1399 * the driver changed the interface type internally already.
1397 * The warnings will hopefully make driver authors fix it :-) 1400 * The warnings will hopefully make driver authors fix it :-)
1398 */ 1401 */
1399 ieee80211_check_queues(sdata); 1402 ieee80211_check_queues(sdata, type);
1400 1403
1401 ieee80211_setup_sdata(sdata, type); 1404 ieee80211_setup_sdata(sdata, type);
1402 1405