diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6aa49ad172aabc20cdf4e17712b0d07a4c25a68c..ea0301025c15d5605a7c22f0f8789d97c0f967f3 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -84,22 +84,22 @@ static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, struct net_device *dev; enum ieee80211_if_types itype; struct ieee80211_sub_if_data *sdata; + int ret; /* we're under RTNL */ dev = __dev_get_by_index(&init_net, ifindex); if (!dev) return -ENODEV; - if (netif_running(dev)) - return -EBUSY; - itype = nl80211_type_to_mac80211_type(type); if (itype == IEEE80211_IF_TYPE_INVALID) return -EINVAL; sdata = IEEE80211_DEV_TO_SUB_IF(dev); - ieee80211_if_change_type(sdata, itype); + ret = ieee80211_if_change_type(sdata, itype); + if (ret) + return ret; if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len) ieee80211_if_sta_set_mesh_id(&sdata->u.sta, diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 35bcdfef9045ff15d1bad2397f46608cb1732f02..2146c0c436d2eaecc44678e2f1bd6845bfbd42f4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -930,8 +930,8 @@ void ieee80211_if_setup(struct net_device *dev); int ieee80211_if_add(struct ieee80211_local *local, const char *name, struct net_device **new_dev, enum ieee80211_if_types type, struct vif_params *params); -void ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, - enum ieee80211_if_types type); +int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, + enum ieee80211_if_types type); void ieee80211_if_remove(struct net_device *dev); void ieee80211_remove_interfaces(struct ieee80211_local *local); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6cf121bebd7a03dee0afeb3f042f62845b9752ea..2e3adcb3ce235bb20a7b625193e01c8d557016e0 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -138,9 +138,23 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, ieee80211_debugfs_add_netdev(sdata); } -void ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, - enum ieee80211_if_types type) +int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, + enum ieee80211_if_types type) { + ASSERT_RTNL(); + + if (type == sdata->vif.type) + return 0; + + /* + * We could, here, on changes between IBSS/STA/MESH modes, + * invoke an MLME function instead that disassociates etc. + * and goes into the requested mode. + */ + + if (netif_running(sdata->dev)) + return -EBUSY; + /* Purge and reset type-dependent state. */ ieee80211_teardown_sdata(sdata->dev); ieee80211_setup_sdata(sdata, type); @@ -149,6 +163,8 @@ void ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, sdata->basic_rates = 0; sdata->drop_unencrypted = 0; sdata->sequence = 0; + + return 0; } int ieee80211_if_add(struct ieee80211_local *local, const char *name, diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index f2fdd334219525582b2d83c636824ef172c078fc..c041db9556c731acc2a54ed9fe695cf1a5b25c5f 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c @@ -296,14 +296,7 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev, return -EINVAL; } - if (type == sdata->vif.type) - return 0; - if (netif_running(dev)) - return -EBUSY; - - ieee80211_if_change_type(sdata, type); - - return 0; + return ieee80211_if_change_type(sdata, type); }