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

ethtool: set EEE settings with EEE_SET request

Implement EEE_SET netlink request to set EEE settings of a network device.
These are traditionally set with ETHTOOL_SEEE ioctl request.

The netlink interface allows setting the EEE status for all link modes
supported by kernel but only first 32 link modes can be set at the moment
as only those are supported by the ethtool_ops callback.

Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Michal Kubecek and committed by
David S. Miller
fd77be7b b7eeefe7

+104 -1
+24 -1
Documentation/networking/ethtool-netlink.rst
··· 202 202 ``ETHTOOL_MSG_PAUSE_GET`` get pause parameters 203 203 ``ETHTOOL_MSG_PAUSE_SET`` set pause parameters 204 204 ``ETHTOOL_MSG_EEE_GET`` get EEE settings 205 + ``ETHTOOL_MSG_EEE_SET`` set EEE settings 205 206 ===================================== ================================ 206 207 207 208 Kernel to userspace: ··· 905 904 first 32 are provided by the ``ethtool_ops`` callback. 906 905 907 906 907 + EEE_SET 908 + ======= 909 + 910 + Sets pause parameters like ``ETHTOOL_GEEEPARAM`` ioctl request. 911 + 912 + Request contents: 913 + 914 + ===================================== ====== ========================== 915 + ``ETHTOOL_A_EEE_HEADER`` nested request header 916 + ``ETHTOOL_A_EEE_MODES_OURS`` bool advertised modes 917 + ``ETHTOOL_A_EEE_ENABLED`` bool EEE is enabled 918 + ``ETHTOOL_A_EEE_TX_LPI_ENABLED`` bool Tx lpi enabled 919 + ``ETHTOOL_A_EEE_TX_LPI_TIMER`` u32 Tx lpi timeout (in us) 920 + ===================================== ====== ========================== 921 + 922 + ``ETHTOOL_A_EEE_MODES_OURS`` is used to either list link modes to advertise 923 + EEE for (if there is no mask) or specify changes to the list (if there is 924 + a mask). The netlink interface allows reporting EEE status for all link modes 925 + but only first 32 can be set at the moment as that is what the ``ethtool_ops`` 926 + callback supports. 927 + 928 + 908 929 Request translation 909 930 =================== 910 931 ··· 1006 983 ``ETHTOOL_GMODULEINFO`` n/a 1007 984 ``ETHTOOL_GMODULEEEPROM`` n/a 1008 985 ``ETHTOOL_GEEE`` ``ETHTOOL_MSG_EEE_GET`` 1009 - ``ETHTOOL_SEEE`` n/a 986 + ``ETHTOOL_SEEE`` ``ETHTOOL_MSG_EEE_SET`` 1010 987 ``ETHTOOL_GRSSH`` n/a 1011 988 ``ETHTOOL_SRSSH`` n/a 1012 989 ``ETHTOOL_GTUNABLE`` n/a
+1
include/uapi/linux/ethtool_netlink.h
··· 37 37 ETHTOOL_MSG_PAUSE_GET, 38 38 ETHTOOL_MSG_PAUSE_SET, 39 39 ETHTOOL_MSG_EEE_GET, 40 + ETHTOOL_MSG_EEE_SET, 40 41 41 42 /* add new constants above here */ 42 43 __ETHTOOL_MSG_USER_CNT,
+73
net/ethtool/eee.c
··· 128 128 .reply_size = eee_reply_size, 129 129 .fill_reply = eee_fill_reply, 130 130 }; 131 + 132 + /* EEE_SET */ 133 + 134 + static const struct nla_policy 135 + eee_set_policy[ETHTOOL_A_EEE_MAX + 1] = { 136 + [ETHTOOL_A_EEE_UNSPEC] = { .type = NLA_REJECT }, 137 + [ETHTOOL_A_EEE_HEADER] = { .type = NLA_NESTED }, 138 + [ETHTOOL_A_EEE_MODES_OURS] = { .type = NLA_NESTED }, 139 + [ETHTOOL_A_EEE_MODES_PEER] = { .type = NLA_REJECT }, 140 + [ETHTOOL_A_EEE_ACTIVE] = { .type = NLA_REJECT }, 141 + [ETHTOOL_A_EEE_ENABLED] = { .type = NLA_U8 }, 142 + [ETHTOOL_A_EEE_TX_LPI_ENABLED] = { .type = NLA_U8 }, 143 + [ETHTOOL_A_EEE_TX_LPI_TIMER] = { .type = NLA_U32 }, 144 + }; 145 + 146 + int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info) 147 + { 148 + struct nlattr *tb[ETHTOOL_A_EEE_MAX + 1]; 149 + struct ethtool_eee eee = {}; 150 + struct ethnl_req_info req_info = {}; 151 + const struct ethtool_ops *ops; 152 + struct net_device *dev; 153 + bool mod = false; 154 + int ret; 155 + 156 + ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_EEE_MAX, 157 + eee_set_policy, info->extack); 158 + if (ret < 0) 159 + return ret; 160 + ret = ethnl_parse_header_dev_get(&req_info, 161 + tb[ETHTOOL_A_EEE_HEADER], 162 + genl_info_net(info), info->extack, 163 + true); 164 + if (ret < 0) 165 + return ret; 166 + dev = req_info.dev; 167 + ops = dev->ethtool_ops; 168 + ret = -EOPNOTSUPP; 169 + if (!ops->get_eee || !ops->set_eee) 170 + goto out_dev; 171 + 172 + rtnl_lock(); 173 + ret = ethnl_ops_begin(dev); 174 + if (ret < 0) 175 + goto out_rtnl; 176 + ret = ops->get_eee(dev, &eee); 177 + if (ret < 0) 178 + goto out_ops; 179 + 180 + ret = ethnl_update_bitset32(&eee.advertised, EEE_MODES_COUNT, 181 + tb[ETHTOOL_A_EEE_MODES_OURS], 182 + link_mode_names, info->extack, &mod); 183 + if (ret < 0) 184 + goto out_ops; 185 + ethnl_update_bool32(&eee.eee_enabled, tb[ETHTOOL_A_EEE_ENABLED], &mod); 186 + ethnl_update_bool32(&eee.tx_lpi_enabled, 187 + tb[ETHTOOL_A_EEE_TX_LPI_ENABLED], &mod); 188 + ethnl_update_bool32(&eee.tx_lpi_timer, tb[ETHTOOL_A_EEE_TX_LPI_TIMER], 189 + &mod); 190 + ret = 0; 191 + if (!mod) 192 + goto out_ops; 193 + 194 + ret = dev->ethtool_ops->set_eee(dev, &eee); 195 + 196 + out_ops: 197 + ethnl_ops_complete(dev); 198 + out_rtnl: 199 + rtnl_unlock(); 200 + out_dev: 201 + dev_put(dev); 202 + return ret; 203 + }
+5
net/ethtool/netlink.c
··· 824 824 .dumpit = ethnl_default_dumpit, 825 825 .done = ethnl_default_done, 826 826 }, 827 + { 828 + .cmd = ETHTOOL_MSG_EEE_SET, 829 + .flags = GENL_UNS_ADMIN_PERM, 830 + .doit = ethnl_set_eee, 831 + }, 827 832 }; 828 833 829 834 static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
+1
net/ethtool/netlink.h
··· 355 355 int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info); 356 356 int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info); 357 357 int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info); 358 + int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info); 358 359 359 360 #endif /* _NET_ETHTOOL_NETLINK_H */