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

ethtool: set pause parameters with PAUSE_SET request

Implement PAUSE_SET netlink request to set pause parameters of a network
device. Thease are traditionally set with ETHTOOL_SPAUSEPARAM ioctl
request.

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
3ab87993 7f59fb32

+70 -1
+2 -1
Documentation/networking/ethtool-netlink.rst
··· 200 200 ``ETHTOOL_MSG_COALESCE_GET`` get coalescing parameters 201 201 ``ETHTOOL_MSG_COALESCE_SET`` set coalescing parameters 202 202 ``ETHTOOL_MSG_PAUSE_GET`` get pause parameters 203 + ``ETHTOOL_MSG_PAUSE_SET`` set pause parameters 203 204 ===================================== ================================ 204 205 205 206 Kernel to userspace: ··· 900 899 ``ETHTOOL_GRINGPARAM`` ``ETHTOOL_MSG_RINGS_GET`` 901 900 ``ETHTOOL_SRINGPARAM`` ``ETHTOOL_MSG_RINGS_SET`` 902 901 ``ETHTOOL_GPAUSEPARAM`` ``ETHTOOL_MSG_PAUSE_GET`` 903 - ``ETHTOOL_SPAUSEPARAM`` n/a 902 + ``ETHTOOL_SPAUSEPARAM`` ``ETHTOOL_MSG_PAUSE_SET`` 904 903 ``ETHTOOL_GRXCSUM`` ``ETHTOOL_MSG_FEATURES_GET`` 905 904 ``ETHTOOL_SRXCSUM`` ``ETHTOOL_MSG_FEATURES_SET`` 906 905 ``ETHTOOL_GTXCSUM`` ``ETHTOOL_MSG_FEATURES_GET``
+1
include/uapi/linux/ethtool_netlink.h
··· 35 35 ETHTOOL_MSG_COALESCE_GET, 36 36 ETHTOOL_MSG_COALESCE_SET, 37 37 ETHTOOL_MSG_PAUSE_GET, 38 + ETHTOOL_MSG_PAUSE_SET, 38 39 39 40 /* add new constants above here */ 40 41 __ETHTOOL_MSG_USER_CNT,
+5
net/ethtool/netlink.c
··· 809 809 .dumpit = ethnl_default_dumpit, 810 810 .done = ethnl_default_done, 811 811 }, 812 + { 813 + .cmd = ETHTOOL_MSG_PAUSE_SET, 814 + .flags = GENL_UNS_ADMIN_PERM, 815 + .doit = ethnl_set_pause, 816 + }, 812 817 }; 813 818 814 819 static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
+1
net/ethtool/netlink.h
··· 353 353 int ethnl_set_rings(struct sk_buff *skb, struct genl_info *info); 354 354 int ethnl_set_channels(struct sk_buff *skb, struct genl_info *info); 355 355 int ethnl_set_coalesce(struct sk_buff *skb, struct genl_info *info); 356 + int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info); 356 357 357 358 #endif /* _NET_ETHTOOL_NETLINK_H */
+61
net/ethtool/pause.c
··· 79 79 .reply_size = pause_reply_size, 80 80 .fill_reply = pause_fill_reply, 81 81 }; 82 + 83 + /* PAUSE_SET */ 84 + 85 + static const struct nla_policy 86 + pause_set_policy[ETHTOOL_A_PAUSE_MAX + 1] = { 87 + [ETHTOOL_A_PAUSE_UNSPEC] = { .type = NLA_REJECT }, 88 + [ETHTOOL_A_PAUSE_HEADER] = { .type = NLA_NESTED }, 89 + [ETHTOOL_A_PAUSE_AUTONEG] = { .type = NLA_U8 }, 90 + [ETHTOOL_A_PAUSE_RX] = { .type = NLA_U8 }, 91 + [ETHTOOL_A_PAUSE_TX] = { .type = NLA_U8 }, 92 + }; 93 + 94 + int ethnl_set_pause(struct sk_buff *skb, struct genl_info *info) 95 + { 96 + struct nlattr *tb[ETHTOOL_A_PAUSE_MAX + 1]; 97 + struct ethtool_pauseparam params = {}; 98 + struct ethnl_req_info req_info = {}; 99 + const struct ethtool_ops *ops; 100 + struct net_device *dev; 101 + bool mod = false; 102 + int ret; 103 + 104 + ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, ETHTOOL_A_PAUSE_MAX, 105 + pause_set_policy, info->extack); 106 + if (ret < 0) 107 + return ret; 108 + ret = ethnl_parse_header_dev_get(&req_info, 109 + tb[ETHTOOL_A_PAUSE_HEADER], 110 + genl_info_net(info), info->extack, 111 + true); 112 + if (ret < 0) 113 + return ret; 114 + dev = req_info.dev; 115 + ops = dev->ethtool_ops; 116 + ret = -EOPNOTSUPP; 117 + if (!ops->get_pauseparam || !ops->set_pauseparam) 118 + goto out_dev; 119 + 120 + rtnl_lock(); 121 + ret = ethnl_ops_begin(dev); 122 + if (ret < 0) 123 + goto out_rtnl; 124 + ops->get_pauseparam(dev, &params); 125 + 126 + ethnl_update_bool32(&params.autoneg, tb[ETHTOOL_A_PAUSE_AUTONEG], &mod); 127 + ethnl_update_bool32(&params.rx_pause, tb[ETHTOOL_A_PAUSE_RX], &mod); 128 + ethnl_update_bool32(&params.tx_pause, tb[ETHTOOL_A_PAUSE_TX], &mod); 129 + ret = 0; 130 + if (!mod) 131 + goto out_ops; 132 + 133 + ret = dev->ethtool_ops->set_pauseparam(dev, &params); 134 + 135 + out_ops: 136 + ethnl_ops_complete(dev); 137 + out_rtnl: 138 + rtnl_unlock(); 139 + out_dev: 140 + dev_put(dev); 141 + return ret; 142 + }