aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/iface.c
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2014-03-05 07:14:08 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-04-09 04:55:49 -0400
commit4e141dad266908735967b0961c8d90187825e0bc (patch)
tree2fe457b25b558543257bb3c73d888e4f4bab8b5b /net/mac80211/iface.c
parentb6a550156bc08a472c9d2515631649e229fcfcef (diff)
mac80211: protect AP VLAN list with local->mtx
It was impossible to change chanctx of master AP for AP VLANs because the copy function requires RTNL which can't be simply taken in mac80211 code due to possible deadlocks. This is required for future chanctx reservation that re-bind vifs to new chanctx. This requires safe AP VLAN iteration without RTNL. Now VLANs can be iterated while holding either RTNL or local->mtx because the list is modified while holding both of these locks. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Luciano Coelho <luciano.coelho@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r--net/mac80211/iface.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index ad5badd783d8..90b60633a27a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -496,7 +496,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
496 if (!sdata->bss) 496 if (!sdata->bss)
497 return -ENOLINK; 497 return -ENOLINK;
498 498
499 mutex_lock(&local->mtx);
499 list_add(&sdata->u.vlan.list, &sdata->bss->vlans); 500 list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
501 mutex_unlock(&local->mtx);
500 502
501 master = container_of(sdata->bss, 503 master = container_of(sdata->bss,
502 struct ieee80211_sub_if_data, u.ap); 504 struct ieee80211_sub_if_data, u.ap);
@@ -726,8 +728,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
726 drv_stop(local); 728 drv_stop(local);
727 err_del_bss: 729 err_del_bss:
728 sdata->bss = NULL; 730 sdata->bss = NULL;
729 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 731 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
732 mutex_lock(&local->mtx);
730 list_del(&sdata->u.vlan.list); 733 list_del(&sdata->u.vlan.list);
734 mutex_unlock(&local->mtx);
735 }
731 /* might already be clear but that doesn't matter */ 736 /* might already be clear but that doesn't matter */
732 clear_bit(SDATA_STATE_RUNNING, &sdata->state); 737 clear_bit(SDATA_STATE_RUNNING, &sdata->state);
733 return res; 738 return res;
@@ -879,7 +884,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
879 884
880 switch (sdata->vif.type) { 885 switch (sdata->vif.type) {
881 case NL80211_IFTYPE_AP_VLAN: 886 case NL80211_IFTYPE_AP_VLAN:
887 mutex_lock(&local->mtx);
882 list_del(&sdata->u.vlan.list); 888 list_del(&sdata->u.vlan.list);
889 mutex_unlock(&local->mtx);
883 RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL); 890 RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
884 /* no need to tell driver */ 891 /* no need to tell driver */
885 break; 892 break;