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: |
