Skip to content

Commit

Permalink
libertas: fix changing interface type when interface is down
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Daniel Drake authored and John W. Linville committed Oct 14, 2011
1 parent 7a72476 commit 5c1381a
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
20 changes: 6 additions & 14 deletions drivers/net/wireless/libertas/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/wireless/libertas/decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);

Expand Down
32 changes: 32 additions & 0 deletions drivers/net/wireless/libertas/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 5c1381a

Please sign in to comment.