1 #include <linux/hardirq.h>
2 #include <linux/netdevice.h>
3 #include <linux/ethtool.h>
4 #include <linux/delay.h>
11 static void lbs_ethtool_get_drvinfo(struct net_device
*dev
,
12 struct ethtool_drvinfo
*info
)
14 struct lbs_private
*priv
= dev
->ml_priv
;
16 snprintf(info
->fw_version
, sizeof(info
->fw_version
),
18 priv
->fwrelease
>> 24 & 0xff,
19 priv
->fwrelease
>> 16 & 0xff,
20 priv
->fwrelease
>> 8 & 0xff,
21 priv
->fwrelease
& 0xff);
22 strlcpy(info
->driver
, "libertas", sizeof(info
->driver
));
23 strlcpy(info
->version
, lbs_driver_version
, sizeof(info
->version
));
27 * All 8388 parts have 16KiB EEPROM size at the time of writing.
28 * In case that changes this needs fixing.
30 #define LBS_EEPROM_LEN 16384
32 static int lbs_ethtool_get_eeprom_len(struct net_device
*dev
)
34 return LBS_EEPROM_LEN
;
37 static int lbs_ethtool_get_eeprom(struct net_device
*dev
,
38 struct ethtool_eeprom
*eeprom
, u8
* bytes
)
40 struct lbs_private
*priv
= dev
->ml_priv
;
41 struct cmd_ds_802_11_eeprom_access cmd
;
44 lbs_deb_enter(LBS_DEB_ETHTOOL
);
46 if (eeprom
->offset
+ eeprom
->len
> LBS_EEPROM_LEN
||
47 eeprom
->len
> LBS_EEPROM_READ_LEN
) {
52 cmd
.hdr
.size
= cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access
) -
53 LBS_EEPROM_READ_LEN
+ eeprom
->len
);
54 cmd
.action
= cpu_to_le16(CMD_ACT_GET
);
55 cmd
.offset
= cpu_to_le16(eeprom
->offset
);
56 cmd
.len
= cpu_to_le16(eeprom
->len
);
57 ret
= lbs_cmd_with_response(priv
, CMD_802_11_EEPROM_ACCESS
, &cmd
);
59 memcpy(bytes
, cmd
.value
, eeprom
->len
);
62 lbs_deb_leave_args(LBS_DEB_ETHTOOL
, "ret %d", ret
);
66 static void lbs_ethtool_get_wol(struct net_device
*dev
,
67 struct ethtool_wolinfo
*wol
)
69 struct lbs_private
*priv
= dev
->ml_priv
;
71 wol
->supported
= WAKE_UCAST
|WAKE_MCAST
|WAKE_BCAST
|WAKE_PHY
;
73 if (priv
->wol_criteria
== EHS_REMOVE_WAKEUP
)
76 if (priv
->wol_criteria
& EHS_WAKE_ON_UNICAST_DATA
)
77 wol
->wolopts
|= WAKE_UCAST
;
78 if (priv
->wol_criteria
& EHS_WAKE_ON_MULTICAST_DATA
)
79 wol
->wolopts
|= WAKE_MCAST
;
80 if (priv
->wol_criteria
& EHS_WAKE_ON_BROADCAST_DATA
)
81 wol
->wolopts
|= WAKE_BCAST
;
82 if (priv
->wol_criteria
& EHS_WAKE_ON_MAC_EVENT
)
83 wol
->wolopts
|= WAKE_PHY
;
86 static int lbs_ethtool_set_wol(struct net_device
*dev
,
87 struct ethtool_wolinfo
*wol
)
89 struct lbs_private
*priv
= dev
->ml_priv
;
91 if (wol
->wolopts
& ~(WAKE_UCAST
|WAKE_MCAST
|WAKE_BCAST
|WAKE_PHY
))
94 priv
->wol_criteria
= 0;
95 if (wol
->wolopts
& WAKE_UCAST
)
96 priv
->wol_criteria
|= EHS_WAKE_ON_UNICAST_DATA
;
97 if (wol
->wolopts
& WAKE_MCAST
)
98 priv
->wol_criteria
|= EHS_WAKE_ON_MULTICAST_DATA
;
99 if (wol
->wolopts
& WAKE_BCAST
)
100 priv
->wol_criteria
|= EHS_WAKE_ON_BROADCAST_DATA
;
101 if (wol
->wolopts
& WAKE_PHY
)
102 priv
->wol_criteria
|= EHS_WAKE_ON_MAC_EVENT
;
103 if (wol
->wolopts
== 0)
104 priv
->wol_criteria
|= EHS_REMOVE_WAKEUP
;
108 const struct ethtool_ops lbs_ethtool_ops
= {
109 .get_drvinfo
= lbs_ethtool_get_drvinfo
,
110 .get_eeprom
= lbs_ethtool_get_eeprom
,
111 .get_eeprom_len
= lbs_ethtool_get_eeprom_len
,
112 #ifdef CONFIG_LIBERTAS_MESH
113 .get_sset_count
= lbs_mesh_ethtool_get_sset_count
,
114 .get_ethtool_stats
= lbs_mesh_ethtool_get_stats
,
115 .get_strings
= lbs_mesh_ethtool_get_strings
,
117 .get_wol
= lbs_ethtool_get_wol
,
118 .set_wol
= lbs_ethtool_set_wol
,