mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
bcdd822007
commit
a986553877
|
@ -308,12 +308,13 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata)
|
static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
|
||||||
|
enum nl80211_iftype iftype)
|
||||||
{
|
{
|
||||||
int n_queues = sdata->local->hw.queues;
|
int n_queues = sdata->local->hw.queues;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) {
|
if (iftype != NL80211_IFTYPE_P2P_DEVICE) {
|
||||||
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
|
||||||
if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
|
if (WARN_ON_ONCE(sdata->vif.hw_queue[i] ==
|
||||||
IEEE80211_INVAL_HW_QUEUE))
|
IEEE80211_INVAL_HW_QUEUE))
|
||||||
|
@ -324,8 +325,9 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sdata->vif.type != NL80211_IFTYPE_AP &&
|
if ((iftype != NL80211_IFTYPE_AP &&
|
||||||
sdata->vif.type != NL80211_IFTYPE_MESH_POINT) ||
|
iftype != NL80211_IFTYPE_P2P_GO &&
|
||||||
|
iftype != NL80211_IFTYPE_MESH_POINT) ||
|
||||||
!(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) {
|
!(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) {
|
||||||
sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
|
sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -408,7 +410,7 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = ieee80211_check_queues(sdata);
|
ret = ieee80211_check_queues(sdata, NL80211_IFTYPE_MONITOR);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
kfree(sdata);
|
kfree(sdata);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -592,7 +594,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||||
res = drv_add_interface(local, sdata);
|
res = drv_add_interface(local, sdata);
|
||||||
if (res)
|
if (res)
|
||||||
goto err_stop;
|
goto err_stop;
|
||||||
res = ieee80211_check_queues(sdata);
|
res = ieee80211_check_queues(sdata,
|
||||||
|
ieee80211_vif_type_p2p(&sdata->vif));
|
||||||
if (res)
|
if (res)
|
||||||
goto err_del_interface;
|
goto err_del_interface;
|
||||||
}
|
}
|
||||||
|
@ -1389,14 +1392,14 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
|
||||||
|
|
||||||
ret = drv_change_interface(local, sdata, internal_type, p2p);
|
ret = drv_change_interface(local, sdata, internal_type, p2p);
|
||||||
if (ret)
|
if (ret)
|
||||||
type = sdata->vif.type;
|
type = ieee80211_vif_type_p2p(&sdata->vif);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ignore return value here, there's not much we can do since
|
* Ignore return value here, there's not much we can do since
|
||||||
* the driver changed the interface type internally already.
|
* the driver changed the interface type internally already.
|
||||||
* The warnings will hopefully make driver authors fix it :-)
|
* The warnings will hopefully make driver authors fix it :-)
|
||||||
*/
|
*/
|
||||||
ieee80211_check_queues(sdata);
|
ieee80211_check_queues(sdata, type);
|
||||||
|
|
||||||
ieee80211_setup_sdata(sdata, type);
|
ieee80211_setup_sdata(sdata, type);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue