diff options
author | Daniel Drake <dsd@laptop.org> | 2011-10-14 07:05:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-10-14 14:48:24 -0400 |
commit | 5c1381ac3f3f49ab1e0886ea8f1432c9a5def519 (patch) | |
tree | 8a7defc05a6eac854432449e0f452df26c70d935 /drivers/net/wireless/libertas | |
parent | 7a72476766735c57bc00d655770f8f21f232f482 (diff) |
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>
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r-- | drivers/net/wireless/libertas/cfg.c | 20 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/decl.h | 2 | ||||
-rw-r--r-- | 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 610bfcee3cf6..ff6378276ff0 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, | |||
1666 | if (dev == priv->mesh_dev) | 1666 | if (dev == priv->mesh_dev) |
1667 | return -EOPNOTSUPP; | 1667 | return -EOPNOTSUPP; |
1668 | 1668 | ||
1669 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1670 | |||
1671 | switch (type) { | 1669 | switch (type) { |
1672 | case NL80211_IFTYPE_MONITOR: | 1670 | case NL80211_IFTYPE_MONITOR: |
1673 | ret = lbs_set_monitor_mode(priv, 1); | ||
1674 | break; | ||
1675 | case NL80211_IFTYPE_STATION: | 1671 | case NL80211_IFTYPE_STATION: |
1676 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
1677 | ret = lbs_set_monitor_mode(priv, 0); | ||
1678 | if (!ret) | ||
1679 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); | ||
1680 | break; | ||
1681 | case NL80211_IFTYPE_ADHOC: | 1672 | case NL80211_IFTYPE_ADHOC: |
1682 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
1683 | ret = lbs_set_monitor_mode(priv, 0); | ||
1684 | if (!ret) | ||
1685 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); | ||
1686 | break; | 1673 | break; |
1687 | default: | 1674 | default: |
1688 | ret = -ENOTSUPP; | 1675 | return -EOPNOTSUPP; |
1689 | } | 1676 | } |
1690 | 1677 | ||
1678 | lbs_deb_enter(LBS_DEB_CFG80211); | ||
1679 | |||
1680 | if (priv->iface_running) | ||
1681 | ret = lbs_set_iface_type(priv, type); | ||
1682 | |||
1691 | if (!ret) | 1683 | if (!ret) |
1692 | priv->wdev->iftype = type; | 1684 | priv->wdev->iftype = type; |
1693 | 1685 | ||
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h index 9304e6fc421f..bc951ab4b681 100644 --- a/drivers/net/wireless/libertas/decl.h +++ b/drivers/net/wireless/libertas/decl.h | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/netdevice.h> | 10 | #include <linux/netdevice.h> |
11 | #include <linux/firmware.h> | 11 | #include <linux/firmware.h> |
12 | #include <linux/nl80211.h> | ||
12 | 13 | ||
13 | /* Should be terminated by a NULL entry */ | 14 | /* Should be terminated by a NULL entry */ |
14 | struct lbs_fw_table { | 15 | struct lbs_fw_table { |
@@ -45,6 +46,7 @@ void lbs_host_to_card_done(struct lbs_private *priv); | |||
45 | 46 | ||
46 | int lbs_start_iface(struct lbs_private *priv); | 47 | int lbs_start_iface(struct lbs_private *priv); |
47 | int lbs_stop_iface(struct lbs_private *priv); | 48 | int lbs_stop_iface(struct lbs_private *priv); |
49 | int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type); | ||
48 | 50 | ||
49 | int lbs_rtap_supported(struct lbs_private *priv); | 51 | int lbs_rtap_supported(struct lbs_private *priv); |
50 | 52 | ||
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 6a326233391f..f78afd7bb768 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) | |||
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | 101 | ||
102 | int lbs_set_iface_type(struct lbs_private *priv, enum nl80211_iftype type) | ||
103 | { | ||
104 | int ret = 0; | ||
105 | |||
106 | switch (type) { | ||
107 | case NL80211_IFTYPE_MONITOR: | ||
108 | ret = lbs_set_monitor_mode(priv, 1); | ||
109 | break; | ||
110 | case NL80211_IFTYPE_STATION: | ||
111 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
112 | ret = lbs_set_monitor_mode(priv, 0); | ||
113 | if (!ret) | ||
114 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 1); | ||
115 | break; | ||
116 | case NL80211_IFTYPE_ADHOC: | ||
117 | if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) | ||
118 | ret = lbs_set_monitor_mode(priv, 0); | ||
119 | if (!ret) | ||
120 | ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, 2); | ||
121 | break; | ||
122 | default: | ||
123 | ret = -ENOTSUPP; | ||
124 | } | ||
125 | return ret; | ||
126 | } | ||
127 | |||
102 | int lbs_start_iface(struct lbs_private *priv) | 128 | int lbs_start_iface(struct lbs_private *priv) |
103 | { | 129 | { |
104 | struct cmd_ds_802_11_mac_address cmd; | 130 | struct cmd_ds_802_11_mac_address cmd; |
@@ -120,6 +146,12 @@ int lbs_start_iface(struct lbs_private *priv) | |||
120 | goto err; | 146 | goto err; |
121 | } | 147 | } |
122 | 148 | ||
149 | ret = lbs_set_iface_type(priv, priv->wdev->iftype); | ||
150 | if (ret) { | ||
151 | lbs_deb_net("set iface type failed\n"); | ||
152 | goto err; | ||
153 | } | ||
154 | |||
123 | lbs_update_channel(priv); | 155 | lbs_update_channel(priv); |
124 | 156 | ||
125 | priv->iface_running = true; | 157 | priv->iface_running = true; |