forked from Minki/linux
libertas: fix changing interface type when interface is down
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@laptop.org> Acked-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
7a72476766
commit
5c1381ac3f
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user