1 // SPDX-License-Identifier: GPL-2.0-only 2 3 #include <linux/phy.h> 4 #include "netlink.h" 5 #include "common.h" 6 7 /* CABLE_TEST_ACT */ 8 9 static const struct nla_policy 10 cable_test_act_policy[ETHTOOL_A_CABLE_TEST_MAX + 1] = { 11 [ETHTOOL_A_CABLE_TEST_UNSPEC] = { .type = NLA_REJECT }, 12 [ETHTOOL_A_CABLE_TEST_HEADER] = { .type = NLA_NESTED }, 13 }; 14 15 int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info) 16 { 17 struct nlattr *tb[ETHTOOL_A_CABLE_TEST_MAX + 1]; 18 struct ethnl_req_info req_info = {}; 19 struct net_device *dev; 20 int ret; 21 22 ret = nlmsg_parse(info->nlhdr, GENL_HDRLEN, tb, 23 ETHTOOL_A_CABLE_TEST_MAX, 24 cable_test_act_policy, info->extack); 25 if (ret < 0) 26 return ret; 27 28 ret = ethnl_parse_header_dev_get(&req_info, 29 tb[ETHTOOL_A_CABLE_TEST_HEADER], 30 genl_info_net(info), info->extack, 31 true); 32 if (ret < 0) 33 return ret; 34 35 dev = req_info.dev; 36 if (!dev->phydev) { 37 ret = -EOPNOTSUPP; 38 goto out_dev_put; 39 } 40 41 rtnl_lock(); 42 ret = ethnl_ops_begin(dev); 43 if (ret < 0) 44 goto out_rtnl; 45 46 ret = phy_start_cable_test(dev->phydev, info->extack); 47 48 ethnl_ops_complete(dev); 49 out_rtnl: 50 rtnl_unlock(); 51 out_dev_put: 52 dev_put(dev); 53 return ret; 54 } 55