Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c1381ac authored by Daniel Drake's avatar Daniel Drake Committed by John W. Linville
Browse files

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: default avatarDaniel Drake <dsd@laptop.org>
Acked-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 7a724767
Loading
Loading
Loading
Loading
+6 −14
Original line number Original line Diff line number Diff line
@@ -1666,28 +1666,20 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
	if (dev == priv->mesh_dev)
	if (dev == priv->mesh_dev)
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;


	lbs_deb_enter(LBS_DEB_CFG80211);

	switch (type) {
	switch (type) {
	case NL80211_IFTYPE_MONITOR:
	case NL80211_IFTYPE_MONITOR:
		ret = lbs_set_monitor_mode(priv, 1);
		break;
	case NL80211_IFTYPE_STATION:
	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:
	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;
		break;
	default:
	default:
		ret = -ENOTSUPP;
		return -EOPNOTSUPP;
	}
	}


	lbs_deb_enter(LBS_DEB_CFG80211);

	if (priv->iface_running)
		ret = lbs_set_iface_type(priv, type);

	if (!ret)
	if (!ret)
		priv->wdev->iftype = type;
		priv->wdev->iftype = type;


+2 −0
Original line number Original line Diff line number Diff line
@@ -9,6 +9,7 @@


#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include <linux/firmware.h>
#include <linux/firmware.h>
#include <linux/nl80211.h>


/* Should be terminated by a NULL entry */
/* Should be terminated by a NULL entry */
struct lbs_fw_table {
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_start_iface(struct lbs_private *priv);
int lbs_stop_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);
int lbs_rtap_supported(struct lbs_private *priv);


+32 −0
Original line number Original line Diff line number Diff line
@@ -99,6 +99,32 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
	return 0;
	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)
int lbs_start_iface(struct lbs_private *priv)
{
{
	struct cmd_ds_802_11_mac_address cmd;
	struct cmd_ds_802_11_mac_address cmd;
@@ -120,6 +146,12 @@ int lbs_start_iface(struct lbs_private *priv)
		goto err;
		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);
	lbs_update_channel(priv);


	priv->iface_running = true;
	priv->iface_running = true;