Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

libertas: Fine grained configuration of wake-on-lan.

Based on a patch from Shailendra Govardhan <shailen@marvell.com>.
This patch allows implementation of more specific wake-on-lan rules than those
of ethtool.

Please note that only firmware 5.110.22.p20 and above supports this feature.

This patch only implements the driver/firmware interface, not the
userspace/driver interface.

Signed-off-by: Anna Neal <anna@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Anna Neal and committed by
John W. Linville
582c1b53 50da3ead

+65 -7
+15 -3
drivers/net/wireless/libertas/cmd.c
··· 159 159 return ret; 160 160 } 161 161 162 - int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria) 162 + int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, 163 + struct wol_config *p_wol_config) 163 164 { 164 165 struct cmd_ds_host_sleep cmd_config; 165 166 int ret; ··· 170 169 cmd_config.gpio = priv->wol_gpio; 171 170 cmd_config.gap = priv->wol_gap; 172 171 172 + if (p_wol_config != NULL) 173 + memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config, 174 + sizeof(struct wol_config)); 175 + else 176 + cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; 177 + 173 178 ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); 174 179 if (!ret) { 175 - lbs_deb_cmd("Set WOL criteria to %x\n", criteria); 176 - priv->wol_criteria = criteria; 180 + if (criteria) { 181 + lbs_deb_cmd("Set WOL criteria to %x\n", criteria); 182 + priv->wol_criteria = criteria; 183 + } else 184 + memcpy((uint8_t *) p_wol_config, 185 + (uint8_t *)&cmd_config.wol_conf, 186 + sizeof(struct wol_config)); 177 187 } else { 178 188 lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); 179 189 }
+2 -1
drivers/net/wireless/libertas/cmd.h
··· 56 56 uint16_t action, uint16_t type); 57 57 int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); 58 58 59 - int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria); 59 + int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, 60 + struct wol_config *p_wol_config); 60 61 int lbs_suspend(struct lbs_private *priv); 61 62 void lbs_resume(struct lbs_private *priv); 62 63
+12
drivers/net/wireless/libertas/defs.h
··· 149 149 #define EHS_WAKE_ON_MAC_EVENT 0x0004 150 150 #define EHS_WAKE_ON_MULTICAST_DATA 0x0008 151 151 #define EHS_REMOVE_WAKEUP 0xFFFFFFFF 152 + /* Wake rules for Host_Sleep_CFG command */ 153 + #define WOL_RULE_NET_TYPE_INFRA_OR_IBSS 0x00 154 + #define WOL_RULE_NET_TYPE_MESH 0x10 155 + #define WOL_RULE_ADDR_TYPE_BCAST 0x01 156 + #define WOL_RULE_ADDR_TYPE_MCAST 0x08 157 + #define WOL_RULE_ADDR_TYPE_UCAST 0x02 158 + #define WOL_RULE_OP_AND 0x01 159 + #define WOL_RULE_OP_OR 0x02 160 + #define WOL_RULE_OP_INVALID 0xFF 161 + #define WOL_RESULT_VALID_CMD 0 162 + #define WOL_RESULT_NOSPC_ERR 1 163 + #define WOL_RESULT_EEXIST_ERR 2 152 164 153 165 /** Misc constants */ 154 166 /* This section defines 802.11 specific contants */
+1 -1
drivers/net/wireless/libertas/ethtool.c
··· 180 180 if (wol->wolopts & WAKE_BCAST) criteria |= EHS_WAKE_ON_BROADCAST_DATA; 181 181 if (wol->wolopts & WAKE_PHY) criteria |= EHS_WAKE_ON_MAC_EVENT; 182 182 183 - return lbs_host_sleep_cfg(priv, criteria); 183 + return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); 184 184 } 185 185 186 186 struct ethtool_ops lbs_ethtool_ops = {
+8
drivers/net/wireless/libertas/host.h
··· 220 220 CMD_ACT_FWT_ACCESS_TIME, 221 221 }; 222 222 223 + /* Define action or option for CMD_802_11_HOST_SLEEP_CFG */ 224 + enum cmd_wol_cfg_opts { 225 + CMD_ACT_ACTION_NONE = 0, 226 + CMD_ACT_SET_WOL_RULE, 227 + CMD_ACT_GET_WOL_RULE, 228 + CMD_ACT_RESET_WOL_RULE, 229 + }; 230 + 223 231 /* Define action or option for CMD_MESH_ACCESS */ 224 232 enum cmd_mesh_access_opts { 225 233 CMD_ACT_MESH_GET_TTL = 1,
+25 -1
drivers/net/wireless/libertas/hostcmd.h
··· 580 580 u8 key[32]; 581 581 }; 582 582 583 + #define MAX_WOL_RULES 16 584 + 585 + struct host_wol_rule { 586 + uint8_t rule_no; 587 + uint8_t rule_ops; 588 + __le16 sig_offset; 589 + __le16 sig_length; 590 + __le16 reserve; 591 + __be32 sig_mask; 592 + __be32 signature; 593 + }; 594 + 595 + struct wol_config { 596 + uint8_t action; 597 + uint8_t pattern; 598 + uint8_t no_rules_in_cmd; 599 + uint8_t result; 600 + struct host_wol_rule rule[MAX_WOL_RULES]; 601 + }; 602 + 603 + 583 604 struct cmd_ds_host_sleep { 584 605 struct cmd_header hdr; 585 606 __le32 criteria; 586 607 uint8_t gpio; 587 - uint8_t gap; 608 + uint16_t gap; 609 + struct wol_config wol_conf; 588 610 } __attribute__ ((packed)); 611 + 612 + 589 613 590 614 struct cmd_ds_802_11_key_material { 591 615 struct cmd_header hdr;
+2 -1
drivers/net/wireless/libertas/if_usb.c
··· 178 178 179 179 priv->wol_gpio = 2; /* Wake via GPIO2... */ 180 180 priv->wol_gap = 20; /* ... after 20ms */ 181 - lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA); 181 + lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA, 182 + (struct wol_config *) NULL); 182 183 183 184 wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); 184 185 wake_method.action = cpu_to_le16(CMD_ACT_GET);