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>
This commit is contained in:
committed by
David S. Miller
parent
d1f7a5b8cf
commit
506e9025e0
@@ -111,21 +111,23 @@ out:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
|
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria)
|
||||||
uint8_t gpio, uint8_t gap)
|
|
||||||
{
|
{
|
||||||
struct cmd_ds_host_sleep cmd_config;
|
struct cmd_ds_host_sleep cmd_config;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
cmd_config.criteria = cpu_to_le32(criteria);
|
cmd_config.criteria = cpu_to_le32(criteria);
|
||||||
cmd_config.gpio = gpio;
|
cmd_config.gpio = priv->wol_gpio;
|
||||||
cmd_config.gap = gap;
|
cmd_config.gap = priv->wol_gap;
|
||||||
|
|
||||||
ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
|
ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config);
|
||||||
if (ret) {
|
if (!ret) {
|
||||||
|
lbs_deb_cmd("Set WOL criteria to %x\n", criteria);
|
||||||
|
priv->wol_criteria = criteria;
|
||||||
|
} else {
|
||||||
lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
|
lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
|
EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg);
|
||||||
|
@@ -33,8 +33,7 @@ int lbs_set_channel(struct lbs_private *priv, u8 channel);
|
|||||||
|
|
||||||
int lbs_mesh_config(struct lbs_private *priv, int enable);
|
int lbs_mesh_config(struct lbs_private *priv, int enable);
|
||||||
|
|
||||||
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria,
|
int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria);
|
||||||
uint8_t gpio, uint8_t gap);
|
|
||||||
int lbs_suspend(struct lbs_private *priv);
|
int lbs_suspend(struct lbs_private *priv);
|
||||||
int lbs_resume(struct lbs_private *priv);
|
int lbs_resume(struct lbs_private *priv);
|
||||||
|
|
||||||
|
@@ -153,6 +153,11 @@ struct lbs_private {
|
|||||||
int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
|
int (*hw_get_int_status) (struct lbs_private *priv, u8 *);
|
||||||
int (*hw_read_event_cause) (struct lbs_private *);
|
int (*hw_read_event_cause) (struct lbs_private *);
|
||||||
|
|
||||||
|
/* Wake On LAN */
|
||||||
|
uint32_t wol_criteria;
|
||||||
|
uint8_t wol_gpio;
|
||||||
|
uint8_t wol_gap;
|
||||||
|
|
||||||
/* was struct lbs_adapter from here... */
|
/* was struct lbs_adapter from here... */
|
||||||
|
|
||||||
/** Wlan adapter data structure*/
|
/** Wlan adapter data structure*/
|
||||||
|
@@ -8,6 +8,8 @@
|
|||||||
#include "dev.h"
|
#include "dev.h"
|
||||||
#include "join.h"
|
#include "join.h"
|
||||||
#include "wext.h"
|
#include "wext.h"
|
||||||
|
#include "cmd.h"
|
||||||
|
|
||||||
static const char * mesh_stat_strings[]= {
|
static const char * mesh_stat_strings[]= {
|
||||||
"drop_duplicate_bcast",
|
"drop_duplicate_bcast",
|
||||||
"drop_ttl_zero",
|
"drop_ttl_zero",
|
||||||
@@ -172,6 +174,49 @@ static void lbs_ethtool_get_strings(struct net_device *dev,
|
|||||||
lbs_deb_enter(LBS_DEB_ETHTOOL);
|
lbs_deb_enter(LBS_DEB_ETHTOOL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lbs_ethtool_get_wol(struct net_device *dev,
|
||||||
|
struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct lbs_private *priv = dev->priv;
|
||||||
|
|
||||||
|
if (priv->wol_criteria == 0xffffffff) {
|
||||||
|
/* Interface driver didn't configure wake */
|
||||||
|
wol->supported = wol->wolopts = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY;
|
||||||
|
|
||||||
|
if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA)
|
||||||
|
wol->wolopts |= WAKE_UCAST;
|
||||||
|
if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA)
|
||||||
|
wol->wolopts |= WAKE_MCAST;
|
||||||
|
if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA)
|
||||||
|
wol->wolopts |= WAKE_BCAST;
|
||||||
|
if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT)
|
||||||
|
wol->wolopts |= WAKE_PHY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lbs_ethtool_set_wol(struct net_device *dev,
|
||||||
|
struct ethtool_wolinfo *wol)
|
||||||
|
{
|
||||||
|
struct lbs_private *priv = dev->priv;
|
||||||
|
uint32_t criteria = 0;
|
||||||
|
|
||||||
|
if (priv->wol_criteria == 0xffffffff && wol->wolopts)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (wol->wolopts & WAKE_UCAST) criteria |= EHS_WAKE_ON_UNICAST_DATA;
|
||||||
|
if (wol->wolopts & WAKE_MCAST) criteria |= EHS_WAKE_ON_MULTICAST_DATA;
|
||||||
|
if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA;
|
||||||
|
if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT;
|
||||||
|
|
||||||
|
return lbs_host_sleep_cfg(priv, criteria);
|
||||||
|
}
|
||||||
|
|
||||||
struct ethtool_ops lbs_ethtool_ops = {
|
struct ethtool_ops lbs_ethtool_ops = {
|
||||||
.get_drvinfo = lbs_ethtool_get_drvinfo,
|
.get_drvinfo = lbs_ethtool_get_drvinfo,
|
||||||
.get_eeprom = lbs_ethtool_get_eeprom,
|
.get_eeprom = lbs_ethtool_get_eeprom,
|
||||||
@@ -179,5 +224,7 @@ struct ethtool_ops lbs_ethtool_ops = {
|
|||||||
.get_sset_count = lbs_ethtool_get_sset_count,
|
.get_sset_count = lbs_ethtool_get_sset_count,
|
||||||
.get_ethtool_stats = lbs_ethtool_get_stats,
|
.get_ethtool_stats = lbs_ethtool_get_stats,
|
||||||
.get_strings = lbs_ethtool_get_strings,
|
.get_strings = lbs_ethtool_get_strings,
|
||||||
|
.get_wol = lbs_ethtool_get_wol,
|
||||||
|
.set_wol = lbs_ethtool_set_wol,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -242,9 +242,9 @@ static int if_usb_probe(struct usb_interface *intf,
|
|||||||
|
|
||||||
if_usb_set_boot2_ver(priv);
|
if_usb_set_boot2_ver(priv);
|
||||||
|
|
||||||
/* Set suspend/resume configuration:
|
priv->wol_gpio = 2; /* Wake via GPIO2... */
|
||||||
wake via GPIO2 after a 20ms delay */
|
priv->wol_gap = 20; /* ... after 20ms */
|
||||||
lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA, 2, 20);
|
lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA);
|
||||||
|
|
||||||
usb_get_dev(udev);
|
usb_get_dev(udev);
|
||||||
usb_set_intfdata(intf, cardp);
|
usb_set_intfdata(intf, cardp);
|
||||||
|
@@ -839,6 +839,11 @@ int lbs_suspend(struct lbs_private *priv)
|
|||||||
struct cmd_header cmd;
|
struct cmd_header cmd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (priv->wol_criteria == 0xffffffff) {
|
||||||
|
lbs_pr_info("Suspend attempt without configuring wake params!\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
|
|
||||||
ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd,
|
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)
|
|||||||
sprintf(priv->mesh_ssid, "mesh");
|
sprintf(priv->mesh_ssid, "mesh");
|
||||||
priv->mesh_ssid_len = 4;
|
priv->mesh_ssid_len = 4;
|
||||||
|
|
||||||
|
priv->wol_criteria = 0xffffffff;
|
||||||
|
priv->wol_gpio = 0xff;
|
||||||
|
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
err_init_adapter:
|
err_init_adapter:
|
||||||
|
Reference in New Issue
Block a user