On Fri, 2011-10-14 at 12:05 +0100, Daniel Drake wrote: > The recent changes to only power the device when the interface up > introduced a bug: changing interface type, legal when the interface > is down, performs device I/O. > > Fix this functionality by validating and recording the interface > type when the change is requested, but only applying the change > if/when the interface is brought up. > > Signed-off-by: Daniel Drake <dsd@xxxxxxxxxx> Acked-by: Dan Williams <dcbw@xxxxxxxxxx> > --- > drivers/net/wireless/libertas/cfg.c | 20 ++++++-------------- > drivers/net/wireless/libertas/decl.h | 2 ++ > drivers/net/wireless/libertas/main.c | 32 ++++++++++++++++++++++++++++++++ > 3 files changed, 40 insertions(+), 14 deletions(-) > > diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c > index 610bfce..ff63782 100644 > --- a/drivers/net/wireless/libertas/cfg.c > +++ b/drivers/net/wireless/libertas/cfg.c > @@ -1666,28 +1666,20 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev, > if (dev == priv->mesh_dev) > return -EOPNOTSUPP; > > - lbs_deb_enter(LBS_DEB_CFG80211); > - > switch (type) { > case NL80211_IFTYPE_MONITOR: > - ret = lbs_set_monitor_mode(priv, 1); > - break; > case NL80211_IFTYPE_STATION: > - if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) > - ret = lbs_set_monitor_mode(priv, 0); > - if (!ret) > - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); > - break; > case NL80211_IFTYPE_ADHOC: > - if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) > - ret = lbs_set_monitor_mode(priv, 0); > - if (!ret) > - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); > break; > default: > - ret = -ENOTSUPP; > + return -EOPNOTSUPP; > } > > + lbs_deb_enter(LBS_DEB_CFG80211); > + > + if (priv->iface_running) > + ret = lbs_set_iface_type(priv, type); > + > if (!ret) > priv->wdev->iftype = type; > > diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h > index 9304e6f..bc951ab 100644 > --- a/drivers/net/wireless/libertas/decl.h > +++ b/drivers/net/wireless/libertas/decl.h > @@ -9,6 +9,7 @@ > > #include <linux/netdevice.h> > #include <linux/firmware.h> > +#include <linux/nl80211.h> > > /* Should be terminated by a NULL entry */ > struct lbs_fw_table { > @@ -45,6 +46,7 @@ void lbs_host_to_card_done(struct lbs_private *priv); > > int lbs_start_iface(struct lbs_private *priv); > int lbs_stop_iface(struct lbs_private *priv); > +int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type); > > int lbs_rtap_supported(struct lbs_private *priv); > > diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c > index 6a32623..f78afd7 100644 > --- a/drivers/net/wireless/libertas/main.c > +++ b/drivers/net/wireless/libertas/main.c > @@ -99,6 +99,32 @@ u8 lbs_data_rate_to_fw_index(u32 rate) > return 0; > } > > +int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type) > +{ > + int ret = 0; > + > + switch (type) { > + case NL80211_IFTYPE_MONITOR: > + ret = lbs_set_monitor_mode(priv, 1); > + break; > + case NL80211_IFTYPE_STATION: > + if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) > + ret = lbs_set_monitor_mode(priv, 0); > + if (!ret) > + ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); > + break; > + case NL80211_IFTYPE_ADHOC: > + if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) > + ret = lbs_set_monitor_mode(priv, 0); > + if (!ret) > + ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); > + break; > + default: > + ret = -ENOTSUPP; > + } > + return ret; > +} > + > int lbs_start_iface(struct lbs_private *priv) > { > struct cmd_ds_802_11_mac_address cmd; > @@ -120,6 +146,12 @@ int lbs_start_iface(struct lbs_private *priv) > goto err; > } > > + ret = lbs_set_iface_type(priv, priv->wdev->iftype); > + if (ret) { > + lbs_deb_net("set iface type failed\n"); > + goto err; > + } > + > lbs_update_channel(priv); > > priv->iface_running = true; -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html