diff options
author | David Woodhouse <dwmw2@infradead.org> | 2007-12-12 20:06:06 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 18:07:05 -0500 |
commit | 506e9025e030c441679fb1ae77fb0d6266c34443 (patch) | |
tree | 9869587068fae691b9bdee93c6b9df85ef786023 /drivers/net | |
parent | d1f7a5b8cfefdb443a05a9e3d636fe7fef57459a (diff) |
libertas: add ethtool support for wake-on-lan configuration
Also, check that suspend is refused if HOST_SLEEP_CFG hasn't been done.
Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/libertas/cmd.c | 14 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/cmd.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/dev.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/ethtool.c | 47 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/if_usb.c | 6 | ||||
-rw-r--r-- | drivers/net/wireless/libertas/main.c | 8 |
6 files changed, 72 insertions, 11 deletions
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index f87cecb4c579..ddf15271244f 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -111,21 +111,23 @@ out: | |||
111 | return ret; | 111 | return ret; |
112 | } | 112 | } |
113 | 113 | ||
114 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | 114 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria) |
115 | uint8_t gpio, uint8_t gap) | ||
116 | { | 115 | { |
117 | struct cmd_ds_host_sleep cmd_config; | 116 | struct cmd_ds_host_sleep cmd_config; |
118 | int ret; | 117 | int ret; |
119 | 118 | ||
120 | cmd_config.criteria = cpu_to_le32(criteria); | 119 | cmd_config.criteria = cpu_to_le32(criteria); |
121 | cmd_config.gpio = gpio; | 120 | cmd_config.gpio = priv->wol_gpio; |
122 | cmd_config.gap = gap; | 121 | cmd_config.gap = priv->wol_gap; |
123 | 122 | ||
124 | ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); | 123 | ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); |
125 | if (ret) { | 124 | if (!ret) { |
125 | lbs_deb_cmd("Set WOL criteria to %x\n", criteria); | ||
126 | priv->wol_criteria = criteria; | ||
127 | } else { | ||
126 | lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); | 128 | lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); |
127 | return ret; | ||
128 | } | 129 | } |
130 | |||
129 | return ret; | 131 | return ret; |
130 | } | 132 | } |
131 | EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); | 133 | EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); |
diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h index e44a0db50487..55f2436574df 100644 --- a/drivers/net/wireless/libertas/cmd.h +++ b/drivers/net/wireless/libertas/cmd.h | |||
@@ -33,8 +33,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel); | |||
33 | 33 | ||
34 | int lbs_mesh_config(struct lbs_private *priv, int enable); | 34 | int lbs_mesh_config(struct lbs_private *priv, int enable); |
35 | 35 | ||
36 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | 36 | int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); |
37 | uint8_t gpio, uint8_t gap); | ||
38 | int lbs_suspend(struct lbs_private *priv); | 37 | int lbs_suspend(struct lbs_private *priv); |
39 | int lbs_resume(struct lbs_private *priv); | 38 | int lbs_resume(struct lbs_private *priv); |
40 | 39 | ||
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h index 86b45a471fc6..60a6a51d0dcb 100644 --- a/drivers/net/wireless/libertas/dev.h +++ b/drivers/net/wireless/libertas/dev.h | |||
@@ -153,6 +153,11 @@ struct lbs_private { | |||
153 | int (*hw_get_int_status) (struct lbs_private *priv, u8 *); | 153 | int (*hw_get_int_status) (struct lbs_private *priv, u8 *); |
154 | int (*hw_read_event_cause) (struct lbs_private *); | 154 | int (*hw_read_event_cause) (struct lbs_private *); |
155 | 155 | ||
156 | /* Wake On LAN */ | ||
157 | uint32_t wol_criteria; | ||
158 | uint8_t wol_gpio; | ||
159 | uint8_t wol_gap; | ||
160 | |||
156 | /* was struct lbs_adapter from here... */ | 161 | /* was struct lbs_adapter from here... */ |
157 | 162 | ||
158 | /** Wlan adapter data structure*/ | 163 | /** Wlan adapter data structure*/ |
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c index a54b4f406af2..21e6f988ea81 100644 --- a/drivers/net/wireless/libertas/ethtool.c +++ b/drivers/net/wireless/libertas/ethtool.c | |||
@@ -8,6 +8,8 @@ | |||
8 | #include "dev.h" | 8 | #include "dev.h" |
9 | #include "join.h" | 9 | #include "join.h" |
10 | #include "wext.h" | 10 | #include "wext.h" |
11 | #include "cmd.h" | ||
12 | |||
11 | static const char * mesh_stat_strings[]= { | 13 | static const char * mesh_stat_strings[]= { |
12 | "drop_duplicate_bcast", | 14 | "drop_duplicate_bcast", |
13 | "drop_ttl_zero", | 15 | "drop_ttl_zero", |
@@ -172,6 +174,49 @@ static void lbs_ethtool_get_strings(struct net_device *dev, | |||
172 | lbs_deb_enter(LBS_DEB_ETHTOOL); | 174 | lbs_deb_enter(LBS_DEB_ETHTOOL); |
173 | } | 175 | } |
174 | 176 | ||
177 | static void lbs_ethtool_get_wol(struct net_device *dev, | ||
178 | struct ethtool_wolinfo *wol) | ||
179 | { | ||
180 | struct lbs_private *priv = dev->priv; | ||
181 | |||
182 | if (priv->wol_criteria == 0xffffffff) { | ||
183 | /* Interface driver didn't configure wake */ | ||
184 | wol->supported = wol->wolopts = 0; | ||
185 | return; | ||
186 | } | ||
187 | |||
188 | wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; | ||
189 | |||
190 | if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) | ||
191 | wol->wolopts |= WAKE_UCAST; | ||
192 | if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) | ||
193 | wol->wolopts |= WAKE_MCAST; | ||
194 | if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA) | ||
195 | wol->wolopts |= WAKE_BCAST; | ||
196 | if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT) | ||
197 | wol->wolopts |= WAKE_PHY; | ||
198 | } | ||
199 | |||
200 | static int lbs_ethtool_set_wol(struct net_device *dev, | ||
201 | struct ethtool_wolinfo *wol) | ||
202 | { | ||
203 | struct lbs_private *priv = dev->priv; | ||
204 | uint32_t criteria = 0; | ||
205 | |||
206 | if (priv->wol_criteria == 0xffffffff && wol->wolopts) | ||
207 | return -EOPNOTSUPP; | ||
208 | |||
209 | if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) | ||
210 | return -EOPNOTSUPP; | ||
211 | |||
212 | if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA; | ||
213 | if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA; | ||
214 | if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA; | ||
215 | if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT; | ||
216 | |||
217 | return lbs_host_sleep_cfg(priv, criteria); | ||
218 | } | ||
219 | |||
175 | struct ethtool_ops lbs_ethtool_ops = { | 220 | struct ethtool_ops lbs_ethtool_ops = { |
176 | .get_drvinfo = lbs_ethtool_get_drvinfo, | 221 | .get_drvinfo = lbs_ethtool_get_drvinfo, |
177 | .get_eeprom = lbs_ethtool_get_eeprom, | 222 | .get_eeprom = lbs_ethtool_get_eeprom, |
@@ -179,5 +224,7 @@ struct ethtool_ops lbs_ethtool_ops = { | |||
179 | .get_sset_count = lbs_ethtool_get_sset_count, | 224 | .get_sset_count = lbs_ethtool_get_sset_count, |
180 | .get_ethtool_stats = lbs_ethtool_get_stats, | 225 | .get_ethtool_stats = lbs_ethtool_get_stats, |
181 | .get_strings = lbs_ethtool_get_strings, | 226 | .get_strings = lbs_ethtool_get_strings, |
227 | .get_wol = lbs_ethtool_get_wol, | ||
228 | .set_wol = lbs_ethtool_set_wol, | ||
182 | }; | 229 | }; |
183 | 230 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index 15715a6b59e0..819141652599 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -242,9 +242,9 @@ static int if_usb_probe(struct usb_interface *intf, | |||
242 | 242 | ||
243 | if_usb_set_boot2_ver(priv); | 243 | if_usb_set_boot2_ver(priv); |
244 | 244 | ||
245 | /* Set suspend/resume configuration: | 245 | priv->wol_gpio = 2; /* Wake via GPIO2... */ |
246 | wake via GPIO2 after a 20ms delay */ | 246 | priv->wol_gap = 20; /* ... after 20ms */ |
247 | lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA, 2, 20); | 247 | lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA); |
248 | 248 | ||
249 | usb_get_dev(udev); | 249 | usb_get_dev(udev); |
250 | usb_set_intfdata(intf, cardp); | 250 | usb_set_intfdata(intf, cardp); |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index 1ea119ed3d22..5e2f3296be34 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -839,6 +839,11 @@ int lbs_suspend(struct lbs_private *priv) | |||
839 | struct cmd_header cmd; | 839 | struct cmd_header cmd; |
840 | int ret; | 840 | int ret; |
841 | 841 | ||
842 | if (priv->wol_criteria == 0xffffffff) { | ||
843 | lbs_pr_info("Suspend attempt without configuring wake params!\n"); | ||
844 | return -EINVAL; | ||
845 | } | ||
846 | |||
842 | memset(&cmd, 0, sizeof(cmd)); | 847 | memset(&cmd, 0, sizeof(cmd)); |
843 | 848 | ||
844 | ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, | 849 | ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, |
@@ -1088,6 +1093,9 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
1088 | sprintf(priv->mesh_ssid, "mesh"); | 1093 | sprintf(priv->mesh_ssid, "mesh"); |
1089 | priv->mesh_ssid_len = 4; | 1094 | priv->mesh_ssid_len = 4; |
1090 | 1095 | ||
1096 | priv->wol_criteria = 0xffffffff; | ||
1097 | priv->wol_gpio = 0xff; | ||
1098 | |||
1091 | goto done; | 1099 | goto done; |
1092 | 1100 | ||
1093 | err_init_adapter: | 1101 | err_init_adapter: |