aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2015-12-08 09:04:39 -0500
committerJohannes Berg <johannes.berg@intel.com>2015-12-15 07:13:59 -0500
commit1ea2c864808e525247d2b6cfdb61b93fe669145e (patch)
tree74ef74dda5947e96e9b52de08838684e0b63c683 /net
parent74430f9489a3b6116a5c144eea2bc62cd52012f6 (diff)
mac80211: reprogram in interface order
During reprogramming, mac80211 currently first adds all the channel contexts, then binds them to the vifs and then goes to reconfigure all the interfaces. Drivers might, perhaps implicitly, rely on the operation order for certain things that typically happen within a single function elsewhere in mac80211. To avoid problems with that, reorder the code in mac80211's restart/reprogramming to work fully within the interface loop so that the order of operations is like in normal operation. For iwlwifi, this fixes a firmware crash when reprogramming with an AP/GO interface active. Reported-by: David Spinadel <david.spinadel@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/util.c76
1 files changed, 37 insertions, 39 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index f9a8d1401ba4..33344f5a66a8 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1723,6 +1723,27 @@ static void ieee80211_assign_chanctx(struct ieee80211_local *local,
1723 mutex_unlock(&local->chanctx_mtx); 1723 mutex_unlock(&local->chanctx_mtx);
1724} 1724}
1725 1725
1726static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
1727{
1728 struct ieee80211_local *local = sdata->local;
1729 struct sta_info *sta;
1730
1731 /* add STAs back */
1732 mutex_lock(&local->sta_mtx);
1733 list_for_each_entry(sta, &local->sta_list, list) {
1734 enum ieee80211_sta_state state;
1735
1736 if (!sta->uploaded || sta->sdata != sdata)
1737 continue;
1738
1739 for (state = IEEE80211_STA_NOTEXIST;
1740 state < sta->sta_state; state++)
1741 WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
1742 state + 1));
1743 }
1744 mutex_unlock(&local->sta_mtx);
1745}
1746
1726int ieee80211_reconfig(struct ieee80211_local *local) 1747int ieee80211_reconfig(struct ieee80211_local *local)
1727{ 1748{
1728 struct ieee80211_hw *hw = &local->hw; 1749 struct ieee80211_hw *hw = &local->hw;
@@ -1858,50 +1879,11 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1858 WARN_ON(drv_add_chanctx(local, ctx)); 1879 WARN_ON(drv_add_chanctx(local, ctx));
1859 mutex_unlock(&local->chanctx_mtx); 1880 mutex_unlock(&local->chanctx_mtx);
1860 1881
1861 list_for_each_entry(sdata, &local->interfaces, list) {
1862 if (!ieee80211_sdata_running(sdata))
1863 continue;
1864 ieee80211_assign_chanctx(local, sdata);
1865 }
1866
1867 sdata = rtnl_dereference(local->monitor_sdata); 1882 sdata = rtnl_dereference(local->monitor_sdata);
1868 if (sdata && ieee80211_sdata_running(sdata)) 1883 if (sdata && ieee80211_sdata_running(sdata))
1869 ieee80211_assign_chanctx(local, sdata); 1884 ieee80211_assign_chanctx(local, sdata);
1870 } 1885 }
1871 1886
1872 /* add STAs back */
1873 mutex_lock(&local->sta_mtx);
1874 list_for_each_entry(sta, &local->sta_list, list) {
1875 enum ieee80211_sta_state state;
1876
1877 if (!sta->uploaded)
1878 continue;
1879
1880 /* AP-mode stations will be added later */
1881 if (sta->sdata->vif.type == NL80211_IFTYPE_AP)
1882 continue;
1883
1884 for (state = IEEE80211_STA_NOTEXIST;
1885 state < sta->sta_state; state++)
1886 WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
1887 state + 1));
1888 }
1889 mutex_unlock(&local->sta_mtx);
1890
1891 /* reconfigure tx conf */
1892 if (hw->queues >= IEEE80211_NUM_ACS) {
1893 list_for_each_entry(sdata, &local->interfaces, list) {
1894 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
1895 sdata->vif.type == NL80211_IFTYPE_MONITOR ||
1896 !ieee80211_sdata_running(sdata))
1897 continue;
1898
1899 for (i = 0; i < IEEE80211_NUM_ACS; i++)
1900 drv_conf_tx(local, sdata, i,
1901 &sdata->tx_conf[i]);
1902 }
1903 }
1904
1905 /* reconfigure hardware */ 1887 /* reconfigure hardware */
1906 ieee80211_hw_config(local, ~0); 1888 ieee80211_hw_config(local, ~0);
1907 1889
@@ -1914,6 +1896,22 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1914 if (!ieee80211_sdata_running(sdata)) 1896 if (!ieee80211_sdata_running(sdata))
1915 continue; 1897 continue;
1916 1898
1899 ieee80211_assign_chanctx(local, sdata);
1900
1901 switch (sdata->vif.type) {
1902 case NL80211_IFTYPE_AP_VLAN:
1903 case NL80211_IFTYPE_MONITOR:
1904 break;
1905 default:
1906 ieee80211_reconfig_stations(sdata);
1907 /* fall through */
1908 case NL80211_IFTYPE_AP: /* AP stations are handled later */
1909 for (i = 0; i < IEEE80211_NUM_ACS; i++)
1910 drv_conf_tx(local, sdata, i,
1911 &sdata->tx_conf[i]);
1912 break;
1913 }
1914
1917 /* common change flags for all interface types */ 1915 /* common change flags for all interface types */
1918 changed = BSS_CHANGED_ERP_CTS_PROT | 1916 changed = BSS_CHANGED_ERP_CTS_PROT |
1919 BSS_CHANGED_ERP_PREAMBLE | 1917 BSS_CHANGED_ERP_PREAMBLE |