Skip to content

Commit 841942b

Browse files
minimaxwelldavem330
authored andcommitted
net: ethtool: Allow passing a phy index for some commands
Some netlink commands are target towards ethernet PHYs, to control some of their features. As there's several such commands, add the ability to pass a PHY index in the ethnl request, which will populate the generic ethnl_req_info with the relevant phydev when the command targets a PHY. Signed-off-by: Maxime Chevallier <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fdd3539 commit 841942b

File tree

4 files changed

+59
-2
lines changed

4 files changed

+59
-2
lines changed

Documentation/networking/ethtool-netlink.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Structure of this header is
5757
``ETHTOOL_A_HEADER_DEV_INDEX`` u32 device ifindex
5858
``ETHTOOL_A_HEADER_DEV_NAME`` string device name
5959
``ETHTOOL_A_HEADER_FLAGS`` u32 flags common for all requests
60+
``ETHTOOL_A_HEADER_PHY_INDEX`` u32 phy device index
6061
============================== ====== =============================
6162

6263
``ETHTOOL_A_HEADER_DEV_INDEX`` and ``ETHTOOL_A_HEADER_DEV_NAME`` identify the
@@ -81,6 +82,12 @@ the behaviour is backward compatible, i.e. requests from old clients not aware
8182
of the flag should be interpreted the way the client expects. A client must
8283
not set flags it does not understand.
8384

85+
``ETHTOOL_A_HEADER_PHY_INDEX`` identifies the Ethernet PHY the message relates to.
86+
As there are numerous commands that are related to PHY configuration, and because
87+
there may be more than one PHY on the link, the PHY index can be passed in the
88+
request for the commands that needs it. It is, however, not mandatory, and if it
89+
is not passed for commands that target a PHY, the net_device.phydev pointer
90+
is used.
8491

8592
Bit sets
8693
========

include/uapi/linux/ethtool_netlink.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ enum {
132132
ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */
133133
ETHTOOL_A_HEADER_DEV_NAME, /* string */
134134
ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */
135+
ETHTOOL_A_HEADER_PHY_INDEX, /* u32 */
135136

136137
/* add new constants above here */
137138
__ETHTOOL_A_HEADER_CNT,

net/ethtool/netlink.c

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/ethtool_netlink.h>
55
#include <linux/pm_runtime.h>
66
#include "netlink.h"
7+
#include <linux/phy_link_topology.h>
78

89
static struct genl_family ethtool_genl_family;
910

@@ -30,6 +31,24 @@ const struct nla_policy ethnl_header_policy_stats[] = {
3031
ETHTOOL_FLAGS_STATS),
3132
};
3233

34+
const struct nla_policy ethnl_header_policy_phy[] = {
35+
[ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
36+
[ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
37+
.len = ALTIFNAMSIZ - 1 },
38+
[ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
39+
ETHTOOL_FLAGS_BASIC),
40+
[ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
41+
};
42+
43+
const struct nla_policy ethnl_header_policy_phy_stats[] = {
44+
[ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
45+
[ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
46+
.len = ALTIFNAMSIZ - 1 },
47+
[ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
48+
ETHTOOL_FLAGS_STATS),
49+
[ETHTOOL_A_HEADER_PHY_INDEX] = NLA_POLICY_MIN(NLA_U32, 1),
50+
};
51+
3352
int ethnl_ops_begin(struct net_device *dev)
3453
{
3554
int ret;
@@ -89,8 +108,9 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
89108
const struct nlattr *header, struct net *net,
90109
struct netlink_ext_ack *extack, bool require_dev)
91110
{
92-
struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy)];
111+
struct nlattr *tb[ARRAY_SIZE(ethnl_header_policy_phy)];
93112
const struct nlattr *devname_attr;
113+
struct phy_device *phydev = NULL;
94114
struct net_device *dev = NULL;
95115
u32 flags = 0;
96116
int ret;
@@ -104,7 +124,7 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
104124
/* No validation here, command policy should have a nested policy set
105125
* for the header, therefore validation should have already been done.
106126
*/
107-
ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy) - 1, header,
127+
ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy_phy) - 1, header,
108128
NULL, extack);
109129
if (ret < 0)
110130
return ret;
@@ -145,6 +165,30 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
145165
return -EINVAL;
146166
}
147167

168+
if (dev) {
169+
if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) {
170+
struct nlattr *phy_id;
171+
172+
phy_id = tb[ETHTOOL_A_HEADER_PHY_INDEX];
173+
phydev = phy_link_topo_get_phy(dev->link_topo,
174+
nla_get_u32(phy_id));
175+
if (!phydev) {
176+
NL_SET_BAD_ATTR(extack, phy_id);
177+
return -ENODEV;
178+
}
179+
} else {
180+
/* If we need a PHY but no phy index is specified, fallback
181+
* to dev->phydev
182+
*/
183+
phydev = dev->phydev;
184+
}
185+
} else if (tb[ETHTOOL_A_HEADER_PHY_INDEX]) {
186+
NL_SET_ERR_MSG_ATTR(extack, header,
187+
"can't target a PHY without a netdev");
188+
return -EINVAL;
189+
}
190+
191+
req_info->phydev = phydev;
148192
req_info->dev = dev;
149193
req_info->flags = flags;
150194
return 0;

net/ethtool/netlink.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ static inline unsigned int ethnl_reply_header_size(void)
250250
* @dev: network device the request is for (may be null)
251251
* @dev_tracker: refcount tracker for @dev reference
252252
* @flags: request flags common for all request types
253+
* @phydev: phy_device connected to @dev this request is for (may be null)
253254
*
254255
* This is a common base for request specific structures holding data from
255256
* parsed userspace request. These always embed struct ethnl_req_info at
@@ -259,6 +260,7 @@ struct ethnl_req_info {
259260
struct net_device *dev;
260261
netdevice_tracker dev_tracker;
261262
u32 flags;
263+
struct phy_device *phydev;
262264
};
263265

264266
static inline void ethnl_parse_header_dev_put(struct ethnl_req_info *req_info)
@@ -395,9 +397,12 @@ extern const struct ethnl_request_ops ethnl_rss_request_ops;
395397
extern const struct ethnl_request_ops ethnl_plca_cfg_request_ops;
396398
extern const struct ethnl_request_ops ethnl_plca_status_request_ops;
397399
extern const struct ethnl_request_ops ethnl_mm_request_ops;
400+
extern const struct ethnl_request_ops ethnl_phy_request_ops;
398401

399402
extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
400403
extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
404+
extern const struct nla_policy ethnl_header_policy_phy[ETHTOOL_A_HEADER_PHY_INDEX + 1];
405+
extern const struct nla_policy ethnl_header_policy_phy_stats[ETHTOOL_A_HEADER_PHY_INDEX + 1];
401406
extern const struct nla_policy ethnl_strset_get_policy[ETHTOOL_A_STRSET_COUNTS_ONLY + 1];
402407
extern const struct nla_policy ethnl_linkinfo_get_policy[ETHTOOL_A_LINKINFO_HEADER + 1];
403408
extern const struct nla_policy ethnl_linkinfo_set_policy[ETHTOOL_A_LINKINFO_TP_MDIX_CTRL + 1];

0 commit comments

Comments
 (0)