From: Maxime Chevallier <maxime.chevallier@bootlin.com> To: davem@davemloft.net Cc: "Maxime Chevallier" <maxime.chevallier@bootlin.com>, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, "Andrew Lunn" <andrew@lunn.ch>, "Jakub Kicinski" <kuba@kernel.org>, "Eric Dumazet" <edumazet@google.com>, "Paolo Abeni" <pabeni@redhat.com>, "Russell King" <linux@armlinux.org.uk>, linux-arm-kernel@lists.infradead.org, "Christophe Leroy" <christophe.leroy@csgroup.eu>, "Herve Codina" <herve.codina@bootlin.com>, "Florian Fainelli" <f.fainelli@gmail.com>, "Heiner Kallweit" <hkallweit1@gmail.com>, "Vladimir Oltean" <vladimir.oltean@nxp.com>, "Köry Maincent" <kory.maincent@bootlin.com>, "Jesse Brandeburg" <jesse.brandeburg@intel.com>, "Jonathan Corbet" <corbet@lwn.net>, "Marek Behún" <kabel@kernel.org>, "Piergiorgio Beruto" <piergiorgio.beruto@gmail.com>, "Oleksij Rempel" <o.rempel@pengutronix.de>, "Nicolò Veronese" <nicveronese@gmail.com> Subject: [RFC PATCH net-next v3 08/13] netlink: specs: add ethnl PHY_GET command set Date: Fri, 1 Dec 2023 17:36:58 +0100 [thread overview] Message-ID: <20231201163704.1306431-9-maxime.chevallier@bootlin.com> (raw) In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> The PHY_GET command, supporting both DUMP and GET operations, is used to retrieve the list of PHYs connected to a netdevice, and get topology information to know where exactly it sits on the physical link. Add the netlink specs corresponding to that command, and bump the ethtool-user.c|h autogenerated files. Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> --- V3: New patch Documentation/netlink/specs/ethtool.yaml | 65 ++++++ tools/net/ynl/generated/ethtool-user.c | 257 +++++++++++++++++++++++ tools/net/ynl/generated/ethtool-user.h | 153 ++++++++++++++ 3 files changed, 475 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 4e0790648913..280b090b5f7c 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -16,6 +16,11 @@ definitions: name: stringset type: enum entries: [] + - + name: phy-upstream-type + enum-name: + type: enum + entries: [ mac, phy ] attribute-sets: - @@ -942,6 +947,45 @@ attribute-sets: - name: burst-tmr type: u32 + - + name: phy-upstream + attributes: + - + name: index + type: u32 + - + name: sfp-name + type: string + - + name: phy + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: index + type: u32 + - + name: drvname + type: string + - + name: name + type: string + - + name: upstream-type + type: u8 + enum: phy-upstream-type + - + name: upstream + type: nest + nested-attributes: phy-upstream + - + name: downstream-sfp-name + type: string + - + name: id + type: u32 operations: enum-model: directional @@ -1692,3 +1736,24 @@ operations: name: mm-ntf doc: Notification for change in MAC Merge configuration. notify: mm-get + - + name: phy-get + doc: Get PHY devices attached to an interface + + attribute-set: phy + + do: &phy-get-op + request: + attributes: + - header + reply: + attributes: + - header + - index + - drvname + - name + - upstream-type + - upstream + - downstream-sfp-name + - id + dump: *phy-get-op diff --git a/tools/net/ynl/generated/ethtool-user.c b/tools/net/ynl/generated/ethtool-user.c index 295661eb3a3e..b63ba2d2e25e 100644 --- a/tools/net/ynl/generated/ethtool-user.c +++ b/tools/net/ynl/generated/ethtool-user.c @@ -59,6 +59,7 @@ static const char * const ethtool_op_strmap[] = { [41] = "plca-ntf", [ETHTOOL_MSG_MM_GET] = "mm-get", [43] = "mm-ntf", + [ETHTOOL_MSG_PHY_GET] = "phy-get", }; const char *ethtool_op_str(int op) @@ -91,6 +92,18 @@ const char *ethtool_stringset_str(enum ethtool_stringset value) return ethtool_stringset_strmap[value]; } +static const char * const ethtool_phy_upstream_type_strmap[] = { + [0] = "mac", + [1] = "phy", +}; + +const char *ethtool_phy_upstream_type_str(int value) +{ + if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_phy_upstream_type_strmap)) + return NULL; + return ethtool_phy_upstream_type_strmap[value]; +} + /* Policies */ struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = { [ETHTOOL_A_HEADER_DEV_INDEX] = { .name = "dev-index", .type = YNL_PT_U32, }, @@ -154,6 +167,16 @@ struct ynl_policy_nest ethtool_mm_stat_nest = { .table = ethtool_mm_stat_policy, }; +struct ynl_policy_attr ethtool_phy_upstream_policy[ETHTOOL_A_PHY_UPSTREAM_MAX + 1] = { + [ETHTOOL_A_PHY_UPSTREAM_INDEX] = { .name = "index", .type = YNL_PT_U32, }, + [ETHTOOL_A_PHY_UPSTREAM_SFP_NAME] = { .name = "sfp-name", .type = YNL_PT_NUL_STR, }, +}; + +struct ynl_policy_nest ethtool_phy_upstream_nest = { + .max_attr = ETHTOOL_A_PHY_UPSTREAM_MAX, + .table = ethtool_phy_upstream_policy, +}; + struct ynl_policy_attr ethtool_cable_result_policy[ETHTOOL_A_CABLE_RESULT_MAX + 1] = { [ETHTOOL_A_CABLE_RESULT_PAIR] = { .name = "pair", .type = YNL_PT_U8, }, [ETHTOOL_A_CABLE_RESULT_CODE] = { .name = "code", .type = YNL_PT_U8, }, @@ -667,6 +690,22 @@ struct ynl_policy_nest ethtool_mm_nest = { .table = ethtool_mm_policy, }; +struct ynl_policy_attr ethtool_phy_policy[ETHTOOL_A_PHY_MAX + 1] = { + [ETHTOOL_A_PHY_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = ðtool_header_nest, }, + [ETHTOOL_A_PHY_INDEX] = { .name = "index", .type = YNL_PT_U32, }, + [ETHTOOL_A_PHY_DRVNAME] = { .name = "drvname", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_NAME] = { .name = "name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_UPSTREAM_TYPE] = { .name = "upstream-type", .type = YNL_PT_U8, }, + [ETHTOOL_A_PHY_UPSTREAM] = { .name = "upstream", .type = YNL_PT_NEST, .nest = ðtool_phy_upstream_nest, }, + [ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME] = { .name = "downstream-sfp-name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_ID] = { .name = "id", .type = YNL_PT_U32, }, +}; + +struct ynl_policy_nest ethtool_phy_nest = { + .max_attr = ETHTOOL_A_PHY_MAX, + .table = ethtool_phy_policy, +}; + /* Common nested types */ void ethtool_header_free(struct ethtool_header *obj) { @@ -899,6 +938,42 @@ int ethtool_mm_stat_parse(struct ynl_parse_arg *yarg, return 0; } +void ethtool_phy_upstream_free(struct ethtool_phy_upstream *obj) +{ + free(obj->sfp_name); +} + +int ethtool_phy_upstream_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested) +{ + struct ethtool_phy_upstream *dst = yarg->data; + const struct nlattr *attr; + + mnl_attr_for_each_nested(attr, nested) { + unsigned int type = mnl_attr_get_type(attr); + + if (type == ETHTOOL_A_PHY_UPSTREAM_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.index = 1; + dst->index = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_PHY_UPSTREAM_SFP_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.sfp_name_len = len; + dst->sfp_name = malloc(len + 1); + memcpy(dst->sfp_name, mnl_attr_get_str(attr), len); + dst->sfp_name[len] = 0; + } + } + + return 0; +} + void ethtool_cable_result_free(struct ethtool_cable_result *obj) { } @@ -6158,6 +6233,188 @@ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req) return 0; } +/* ============== ETHTOOL_MSG_PHY_GET ============== */ +/* ETHTOOL_MSG_PHY_GET - do */ +void ethtool_phy_get_req_free(struct ethtool_phy_get_req *req) +{ + ethtool_header_free(&req->header); + free(req); +} + +void ethtool_phy_get_rsp_free(struct ethtool_phy_get_rsp *rsp) +{ + ethtool_header_free(&rsp->header); + free(rsp->drvname); + free(rsp->name); + ethtool_phy_upstream_free(&rsp->upstream); + free(rsp->downstream_sfp_name); + free(rsp); +} + +int ethtool_phy_get_rsp_parse(const struct nlmsghdr *nlh, void *data) +{ + struct ynl_parse_arg *yarg = data; + struct ethtool_phy_get_rsp *dst; + const struct nlattr *attr; + struct ynl_parse_arg parg; + + dst = yarg->data; + parg.ys = yarg->ys; + + mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { + unsigned int type = mnl_attr_get_type(attr); + + if (type == ETHTOOL_A_PHY_HEADER) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.header = 1; + + parg.rsp_policy = ðtool_header_nest; + parg.data = &dst->header; + if (ethtool_header_parse(&parg, attr)) + return MNL_CB_ERROR; + } else if (type == ETHTOOL_A_PHY_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.index = 1; + dst->index = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_PHY_DRVNAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.drvname_len = len; + dst->drvname = malloc(len + 1); + memcpy(dst->drvname, mnl_attr_get_str(attr), len); + dst->drvname[len] = 0; + } else if (type == ETHTOOL_A_PHY_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.name_len = len; + dst->name = malloc(len + 1); + memcpy(dst->name, mnl_attr_get_str(attr), len); + dst->name[len] = 0; + } else if (type == ETHTOOL_A_PHY_UPSTREAM_TYPE) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.upstream_type = 1; + dst->upstream_type = mnl_attr_get_u8(attr); + } else if (type == ETHTOOL_A_PHY_UPSTREAM) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.upstream = 1; + + parg.rsp_policy = ðtool_phy_upstream_nest; + parg.data = &dst->upstream; + if (ethtool_phy_upstream_parse(&parg, attr)) + return MNL_CB_ERROR; + } else if (type == ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.downstream_sfp_name_len = len; + dst->downstream_sfp_name = malloc(len + 1); + memcpy(dst->downstream_sfp_name, mnl_attr_get_str(attr), len); + dst->downstream_sfp_name[len] = 0; + } else if (type == ETHTOOL_A_PHY_ID) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.id = 1; + dst->id = mnl_attr_get_u32(attr); + } + } + + return MNL_CB_OK; +} + +struct ethtool_phy_get_rsp * +ethtool_phy_get(struct ynl_sock *ys, struct ethtool_phy_get_req *req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct ethtool_phy_get_rsp *rsp; + struct nlmsghdr *nlh; + int err; + + nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PHY_GET, 1); + ys->req_policy = ðtool_phy_nest; + yrs.yarg.rsp_policy = ðtool_phy_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_PHY_HEADER, &req->header); + + rsp = calloc(1, sizeof(*rsp)); + yrs.yarg.data = rsp; + yrs.cb = ethtool_phy_get_rsp_parse; + yrs.rsp_cmd = ETHTOOL_MSG_PHY_GET; + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) + goto err_free; + + return rsp; + +err_free: + ethtool_phy_get_rsp_free(rsp); + return NULL; +} + +/* ETHTOOL_MSG_PHY_GET - dump */ +void ethtool_phy_get_list_free(struct ethtool_phy_get_list *rsp) +{ + struct ethtool_phy_get_list *next = rsp; + + while ((void *)next != YNL_LIST_END) { + rsp = next; + next = rsp->next; + + ethtool_header_free(&rsp->obj.header); + free(rsp->obj.drvname); + free(rsp->obj.name); + ethtool_phy_upstream_free(&rsp->obj.upstream); + free(rsp->obj.downstream_sfp_name); + free(rsp); + } +} + +struct ethtool_phy_get_list * +ethtool_phy_get_dump(struct ynl_sock *ys, struct ethtool_phy_get_req_dump *req) +{ + struct ynl_dump_state yds = {}; + struct nlmsghdr *nlh; + int err; + + yds.ys = ys; + yds.alloc_sz = sizeof(struct ethtool_phy_get_list); + yds.cb = ethtool_phy_get_rsp_parse; + yds.rsp_cmd = ETHTOOL_MSG_PHY_GET; + yds.rsp_policy = ðtool_phy_nest; + + nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PHY_GET, 1); + ys->req_policy = ðtool_phy_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_PHY_HEADER, &req->header); + + err = ynl_exec_dump(ys, nlh, &yds); + if (err < 0) + goto free_list; + + return yds.first; + +free_list: + ethtool_phy_get_list_free(yds.first); + return NULL; +} + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ int ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr *nlh, void *data) { diff --git a/tools/net/ynl/generated/ethtool-user.h b/tools/net/ynl/generated/ethtool-user.h index 97c079c0f332..59ebb0a1a09f 100644 --- a/tools/net/ynl/generated/ethtool-user.h +++ b/tools/net/ynl/generated/ethtool-user.h @@ -20,6 +20,7 @@ extern const struct ynl_family ynl_ethtool_family; const char *ethtool_op_str(int op); const char *ethtool_udp_tunnel_type_str(int value); const char *ethtool_stringset_str(enum ethtool_stringset value); +const char *ethtool_phy_upstream_type_str(int value); /* Common nested types */ struct ethtool_header { @@ -90,6 +91,16 @@ struct ethtool_mm_stat { __u64 hold_count; }; +struct ethtool_phy_upstream { + struct { + __u32 index:1; + __u32 sfp_name_len; + } _present; + + __u32 index; + char *sfp_name; +}; + struct ethtool_cable_result { struct { __u32 pair:1; @@ -6018,6 +6029,148 @@ ethtool_mm_set_req_set_tx_min_frag_size(struct ethtool_mm_set_req *req, */ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req); +/* ============== ETHTOOL_MSG_PHY_GET ============== */ +/* ETHTOOL_MSG_PHY_GET - do */ +struct ethtool_phy_get_req { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_phy_get_req *ethtool_phy_get_req_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_phy_get_req)); +} +void ethtool_phy_get_req_free(struct ethtool_phy_get_req *req); + +static inline void +ethtool_phy_get_req_set_header_dev_index(struct ethtool_phy_get_req *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_phy_get_req_set_header_dev_name(struct ethtool_phy_get_req *req, + const char *dev_name) +{ + free(req->header.dev_name); + req->header._present.dev_name_len = strlen(dev_name); + req->header.dev_name = malloc(req->header._present.dev_name_len + 1); + memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len); + req->header.dev_name[req->header._present.dev_name_len] = 0; +} +static inline void +ethtool_phy_get_req_set_header_flags(struct ethtool_phy_get_req *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_phy_get_req_set_header_phy_index(struct ethtool_phy_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_phy_get_rsp { + struct { + __u32 header:1; + __u32 index:1; + __u32 drvname_len; + __u32 name_len; + __u32 upstream_type:1; + __u32 upstream:1; + __u32 downstream_sfp_name_len; + __u32 id:1; + } _present; + + struct ethtool_header header; + __u32 index; + char *drvname; + char *name; + __u8 upstream_type; + struct ethtool_phy_upstream upstream; + char *downstream_sfp_name; + __u32 id; +}; + +void ethtool_phy_get_rsp_free(struct ethtool_phy_get_rsp *rsp); + +/* + * Get PHY devices attached to an interface + */ +struct ethtool_phy_get_rsp * +ethtool_phy_get(struct ynl_sock *ys, struct ethtool_phy_get_req *req); + +/* ETHTOOL_MSG_PHY_GET - dump */ +struct ethtool_phy_get_req_dump { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_phy_get_req_dump * +ethtool_phy_get_req_dump_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_phy_get_req_dump)); +} +void ethtool_phy_get_req_dump_free(struct ethtool_phy_get_req_dump *req); + +static inline void +ethtool_phy_get_req_dump_set_header_dev_index(struct ethtool_phy_get_req_dump *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_phy_get_req_dump_set_header_dev_name(struct ethtool_phy_get_req_dump *req, + const char *dev_name) +{ + free(req->header.dev_name); + req->header._present.dev_name_len = strlen(dev_name); + req->header.dev_name = malloc(req->header._present.dev_name_len + 1); + memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len); + req->header.dev_name[req->header._present.dev_name_len] = 0; +} +static inline void +ethtool_phy_get_req_dump_set_header_flags(struct ethtool_phy_get_req_dump *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_phy_get_req_dump_set_header_phy_index(struct ethtool_phy_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_phy_get_list { + struct ethtool_phy_get_list *next; + struct ethtool_phy_get_rsp obj __attribute__((aligned(8))); +}; + +void ethtool_phy_get_list_free(struct ethtool_phy_get_list *rsp); + +struct ethtool_phy_get_list * +ethtool_phy_get_dump(struct ynl_sock *ys, struct ethtool_phy_get_req_dump *req); + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ struct ethtool_cable_test_ntf_rsp { struct { -- 2.42.0
WARNING: multiple messages have this Message-ID (diff)
From: Maxime Chevallier <maxime.chevallier@bootlin.com> To: davem@davemloft.net Cc: "Maxime Chevallier" <maxime.chevallier@bootlin.com>, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, thomas.petazzoni@bootlin.com, "Andrew Lunn" <andrew@lunn.ch>, "Jakub Kicinski" <kuba@kernel.org>, "Eric Dumazet" <edumazet@google.com>, "Paolo Abeni" <pabeni@redhat.com>, "Russell King" <linux@armlinux.org.uk>, linux-arm-kernel@lists.infradead.org, "Christophe Leroy" <christophe.leroy@csgroup.eu>, "Herve Codina" <herve.codina@bootlin.com>, "Florian Fainelli" <f.fainelli@gmail.com>, "Heiner Kallweit" <hkallweit1@gmail.com>, "Vladimir Oltean" <vladimir.oltean@nxp.com>, "Köry Maincent" <kory.maincent@bootlin.com>, "Jesse Brandeburg" <jesse.brandeburg@intel.com>, "Jonathan Corbet" <corbet@lwn.net>, "Marek Behún" <kabel@kernel.org>, "Piergiorgio Beruto" <piergiorgio.beruto@gmail.com>, "Oleksij Rempel" <o.rempel@pengutronix.de>, "Nicolò Veronese" <nicveronese@gmail.com> Subject: [RFC PATCH net-next v3 08/13] netlink: specs: add ethnl PHY_GET command set Date: Fri, 1 Dec 2023 17:36:58 +0100 [thread overview] Message-ID: <20231201163704.1306431-9-maxime.chevallier@bootlin.com> (raw) In-Reply-To: <20231201163704.1306431-1-maxime.chevallier@bootlin.com> The PHY_GET command, supporting both DUMP and GET operations, is used to retrieve the list of PHYs connected to a netdevice, and get topology information to know where exactly it sits on the physical link. Add the netlink specs corresponding to that command, and bump the ethtool-user.c|h autogenerated files. Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com> --- V3: New patch Documentation/netlink/specs/ethtool.yaml | 65 ++++++ tools/net/ynl/generated/ethtool-user.c | 257 +++++++++++++++++++++++ tools/net/ynl/generated/ethtool-user.h | 153 ++++++++++++++ 3 files changed, 475 insertions(+) diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 4e0790648913..280b090b5f7c 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -16,6 +16,11 @@ definitions: name: stringset type: enum entries: [] + - + name: phy-upstream-type + enum-name: + type: enum + entries: [ mac, phy ] attribute-sets: - @@ -942,6 +947,45 @@ attribute-sets: - name: burst-tmr type: u32 + - + name: phy-upstream + attributes: + - + name: index + type: u32 + - + name: sfp-name + type: string + - + name: phy + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: index + type: u32 + - + name: drvname + type: string + - + name: name + type: string + - + name: upstream-type + type: u8 + enum: phy-upstream-type + - + name: upstream + type: nest + nested-attributes: phy-upstream + - + name: downstream-sfp-name + type: string + - + name: id + type: u32 operations: enum-model: directional @@ -1692,3 +1736,24 @@ operations: name: mm-ntf doc: Notification for change in MAC Merge configuration. notify: mm-get + - + name: phy-get + doc: Get PHY devices attached to an interface + + attribute-set: phy + + do: &phy-get-op + request: + attributes: + - header + reply: + attributes: + - header + - index + - drvname + - name + - upstream-type + - upstream + - downstream-sfp-name + - id + dump: *phy-get-op diff --git a/tools/net/ynl/generated/ethtool-user.c b/tools/net/ynl/generated/ethtool-user.c index 295661eb3a3e..b63ba2d2e25e 100644 --- a/tools/net/ynl/generated/ethtool-user.c +++ b/tools/net/ynl/generated/ethtool-user.c @@ -59,6 +59,7 @@ static const char * const ethtool_op_strmap[] = { [41] = "plca-ntf", [ETHTOOL_MSG_MM_GET] = "mm-get", [43] = "mm-ntf", + [ETHTOOL_MSG_PHY_GET] = "phy-get", }; const char *ethtool_op_str(int op) @@ -91,6 +92,18 @@ const char *ethtool_stringset_str(enum ethtool_stringset value) return ethtool_stringset_strmap[value]; } +static const char * const ethtool_phy_upstream_type_strmap[] = { + [0] = "mac", + [1] = "phy", +}; + +const char *ethtool_phy_upstream_type_str(int value) +{ + if (value < 0 || value >= (int)MNL_ARRAY_SIZE(ethtool_phy_upstream_type_strmap)) + return NULL; + return ethtool_phy_upstream_type_strmap[value]; +} + /* Policies */ struct ynl_policy_attr ethtool_header_policy[ETHTOOL_A_HEADER_MAX + 1] = { [ETHTOOL_A_HEADER_DEV_INDEX] = { .name = "dev-index", .type = YNL_PT_U32, }, @@ -154,6 +167,16 @@ struct ynl_policy_nest ethtool_mm_stat_nest = { .table = ethtool_mm_stat_policy, }; +struct ynl_policy_attr ethtool_phy_upstream_policy[ETHTOOL_A_PHY_UPSTREAM_MAX + 1] = { + [ETHTOOL_A_PHY_UPSTREAM_INDEX] = { .name = "index", .type = YNL_PT_U32, }, + [ETHTOOL_A_PHY_UPSTREAM_SFP_NAME] = { .name = "sfp-name", .type = YNL_PT_NUL_STR, }, +}; + +struct ynl_policy_nest ethtool_phy_upstream_nest = { + .max_attr = ETHTOOL_A_PHY_UPSTREAM_MAX, + .table = ethtool_phy_upstream_policy, +}; + struct ynl_policy_attr ethtool_cable_result_policy[ETHTOOL_A_CABLE_RESULT_MAX + 1] = { [ETHTOOL_A_CABLE_RESULT_PAIR] = { .name = "pair", .type = YNL_PT_U8, }, [ETHTOOL_A_CABLE_RESULT_CODE] = { .name = "code", .type = YNL_PT_U8, }, @@ -667,6 +690,22 @@ struct ynl_policy_nest ethtool_mm_nest = { .table = ethtool_mm_policy, }; +struct ynl_policy_attr ethtool_phy_policy[ETHTOOL_A_PHY_MAX + 1] = { + [ETHTOOL_A_PHY_HEADER] = { .name = "header", .type = YNL_PT_NEST, .nest = ðtool_header_nest, }, + [ETHTOOL_A_PHY_INDEX] = { .name = "index", .type = YNL_PT_U32, }, + [ETHTOOL_A_PHY_DRVNAME] = { .name = "drvname", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_NAME] = { .name = "name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_UPSTREAM_TYPE] = { .name = "upstream-type", .type = YNL_PT_U8, }, + [ETHTOOL_A_PHY_UPSTREAM] = { .name = "upstream", .type = YNL_PT_NEST, .nest = ðtool_phy_upstream_nest, }, + [ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME] = { .name = "downstream-sfp-name", .type = YNL_PT_NUL_STR, }, + [ETHTOOL_A_PHY_ID] = { .name = "id", .type = YNL_PT_U32, }, +}; + +struct ynl_policy_nest ethtool_phy_nest = { + .max_attr = ETHTOOL_A_PHY_MAX, + .table = ethtool_phy_policy, +}; + /* Common nested types */ void ethtool_header_free(struct ethtool_header *obj) { @@ -899,6 +938,42 @@ int ethtool_mm_stat_parse(struct ynl_parse_arg *yarg, return 0; } +void ethtool_phy_upstream_free(struct ethtool_phy_upstream *obj) +{ + free(obj->sfp_name); +} + +int ethtool_phy_upstream_parse(struct ynl_parse_arg *yarg, + const struct nlattr *nested) +{ + struct ethtool_phy_upstream *dst = yarg->data; + const struct nlattr *attr; + + mnl_attr_for_each_nested(attr, nested) { + unsigned int type = mnl_attr_get_type(attr); + + if (type == ETHTOOL_A_PHY_UPSTREAM_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.index = 1; + dst->index = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_PHY_UPSTREAM_SFP_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.sfp_name_len = len; + dst->sfp_name = malloc(len + 1); + memcpy(dst->sfp_name, mnl_attr_get_str(attr), len); + dst->sfp_name[len] = 0; + } + } + + return 0; +} + void ethtool_cable_result_free(struct ethtool_cable_result *obj) { } @@ -6158,6 +6233,188 @@ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req) return 0; } +/* ============== ETHTOOL_MSG_PHY_GET ============== */ +/* ETHTOOL_MSG_PHY_GET - do */ +void ethtool_phy_get_req_free(struct ethtool_phy_get_req *req) +{ + ethtool_header_free(&req->header); + free(req); +} + +void ethtool_phy_get_rsp_free(struct ethtool_phy_get_rsp *rsp) +{ + ethtool_header_free(&rsp->header); + free(rsp->drvname); + free(rsp->name); + ethtool_phy_upstream_free(&rsp->upstream); + free(rsp->downstream_sfp_name); + free(rsp); +} + +int ethtool_phy_get_rsp_parse(const struct nlmsghdr *nlh, void *data) +{ + struct ynl_parse_arg *yarg = data; + struct ethtool_phy_get_rsp *dst; + const struct nlattr *attr; + struct ynl_parse_arg parg; + + dst = yarg->data; + parg.ys = yarg->ys; + + mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { + unsigned int type = mnl_attr_get_type(attr); + + if (type == ETHTOOL_A_PHY_HEADER) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.header = 1; + + parg.rsp_policy = ðtool_header_nest; + parg.data = &dst->header; + if (ethtool_header_parse(&parg, attr)) + return MNL_CB_ERROR; + } else if (type == ETHTOOL_A_PHY_INDEX) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.index = 1; + dst->index = mnl_attr_get_u32(attr); + } else if (type == ETHTOOL_A_PHY_DRVNAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.drvname_len = len; + dst->drvname = malloc(len + 1); + memcpy(dst->drvname, mnl_attr_get_str(attr), len); + dst->drvname[len] = 0; + } else if (type == ETHTOOL_A_PHY_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.name_len = len; + dst->name = malloc(len + 1); + memcpy(dst->name, mnl_attr_get_str(attr), len); + dst->name[len] = 0; + } else if (type == ETHTOOL_A_PHY_UPSTREAM_TYPE) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.upstream_type = 1; + dst->upstream_type = mnl_attr_get_u8(attr); + } else if (type == ETHTOOL_A_PHY_UPSTREAM) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.upstream = 1; + + parg.rsp_policy = ðtool_phy_upstream_nest; + parg.data = &dst->upstream; + if (ethtool_phy_upstream_parse(&parg, attr)) + return MNL_CB_ERROR; + } else if (type == ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME) { + unsigned int len; + + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + + len = strnlen(mnl_attr_get_str(attr), mnl_attr_get_payload_len(attr)); + dst->_present.downstream_sfp_name_len = len; + dst->downstream_sfp_name = malloc(len + 1); + memcpy(dst->downstream_sfp_name, mnl_attr_get_str(attr), len); + dst->downstream_sfp_name[len] = 0; + } else if (type == ETHTOOL_A_PHY_ID) { + if (ynl_attr_validate(yarg, attr)) + return MNL_CB_ERROR; + dst->_present.id = 1; + dst->id = mnl_attr_get_u32(attr); + } + } + + return MNL_CB_OK; +} + +struct ethtool_phy_get_rsp * +ethtool_phy_get(struct ynl_sock *ys, struct ethtool_phy_get_req *req) +{ + struct ynl_req_state yrs = { .yarg = { .ys = ys, }, }; + struct ethtool_phy_get_rsp *rsp; + struct nlmsghdr *nlh; + int err; + + nlh = ynl_gemsg_start_req(ys, ys->family_id, ETHTOOL_MSG_PHY_GET, 1); + ys->req_policy = ðtool_phy_nest; + yrs.yarg.rsp_policy = ðtool_phy_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_PHY_HEADER, &req->header); + + rsp = calloc(1, sizeof(*rsp)); + yrs.yarg.data = rsp; + yrs.cb = ethtool_phy_get_rsp_parse; + yrs.rsp_cmd = ETHTOOL_MSG_PHY_GET; + + err = ynl_exec(ys, nlh, &yrs); + if (err < 0) + goto err_free; + + return rsp; + +err_free: + ethtool_phy_get_rsp_free(rsp); + return NULL; +} + +/* ETHTOOL_MSG_PHY_GET - dump */ +void ethtool_phy_get_list_free(struct ethtool_phy_get_list *rsp) +{ + struct ethtool_phy_get_list *next = rsp; + + while ((void *)next != YNL_LIST_END) { + rsp = next; + next = rsp->next; + + ethtool_header_free(&rsp->obj.header); + free(rsp->obj.drvname); + free(rsp->obj.name); + ethtool_phy_upstream_free(&rsp->obj.upstream); + free(rsp->obj.downstream_sfp_name); + free(rsp); + } +} + +struct ethtool_phy_get_list * +ethtool_phy_get_dump(struct ynl_sock *ys, struct ethtool_phy_get_req_dump *req) +{ + struct ynl_dump_state yds = {}; + struct nlmsghdr *nlh; + int err; + + yds.ys = ys; + yds.alloc_sz = sizeof(struct ethtool_phy_get_list); + yds.cb = ethtool_phy_get_rsp_parse; + yds.rsp_cmd = ETHTOOL_MSG_PHY_GET; + yds.rsp_policy = ðtool_phy_nest; + + nlh = ynl_gemsg_start_dump(ys, ys->family_id, ETHTOOL_MSG_PHY_GET, 1); + ys->req_policy = ðtool_phy_nest; + + if (req->_present.header) + ethtool_header_put(nlh, ETHTOOL_A_PHY_HEADER, &req->header); + + err = ynl_exec_dump(ys, nlh, &yds); + if (err < 0) + goto free_list; + + return yds.first; + +free_list: + ethtool_phy_get_list_free(yds.first); + return NULL; +} + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ int ethtool_cable_test_ntf_rsp_parse(const struct nlmsghdr *nlh, void *data) { diff --git a/tools/net/ynl/generated/ethtool-user.h b/tools/net/ynl/generated/ethtool-user.h index 97c079c0f332..59ebb0a1a09f 100644 --- a/tools/net/ynl/generated/ethtool-user.h +++ b/tools/net/ynl/generated/ethtool-user.h @@ -20,6 +20,7 @@ extern const struct ynl_family ynl_ethtool_family; const char *ethtool_op_str(int op); const char *ethtool_udp_tunnel_type_str(int value); const char *ethtool_stringset_str(enum ethtool_stringset value); +const char *ethtool_phy_upstream_type_str(int value); /* Common nested types */ struct ethtool_header { @@ -90,6 +91,16 @@ struct ethtool_mm_stat { __u64 hold_count; }; +struct ethtool_phy_upstream { + struct { + __u32 index:1; + __u32 sfp_name_len; + } _present; + + __u32 index; + char *sfp_name; +}; + struct ethtool_cable_result { struct { __u32 pair:1; @@ -6018,6 +6029,148 @@ ethtool_mm_set_req_set_tx_min_frag_size(struct ethtool_mm_set_req *req, */ int ethtool_mm_set(struct ynl_sock *ys, struct ethtool_mm_set_req *req); +/* ============== ETHTOOL_MSG_PHY_GET ============== */ +/* ETHTOOL_MSG_PHY_GET - do */ +struct ethtool_phy_get_req { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_phy_get_req *ethtool_phy_get_req_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_phy_get_req)); +} +void ethtool_phy_get_req_free(struct ethtool_phy_get_req *req); + +static inline void +ethtool_phy_get_req_set_header_dev_index(struct ethtool_phy_get_req *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_phy_get_req_set_header_dev_name(struct ethtool_phy_get_req *req, + const char *dev_name) +{ + free(req->header.dev_name); + req->header._present.dev_name_len = strlen(dev_name); + req->header.dev_name = malloc(req->header._present.dev_name_len + 1); + memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len); + req->header.dev_name[req->header._present.dev_name_len] = 0; +} +static inline void +ethtool_phy_get_req_set_header_flags(struct ethtool_phy_get_req *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_phy_get_req_set_header_phy_index(struct ethtool_phy_get_req *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_phy_get_rsp { + struct { + __u32 header:1; + __u32 index:1; + __u32 drvname_len; + __u32 name_len; + __u32 upstream_type:1; + __u32 upstream:1; + __u32 downstream_sfp_name_len; + __u32 id:1; + } _present; + + struct ethtool_header header; + __u32 index; + char *drvname; + char *name; + __u8 upstream_type; + struct ethtool_phy_upstream upstream; + char *downstream_sfp_name; + __u32 id; +}; + +void ethtool_phy_get_rsp_free(struct ethtool_phy_get_rsp *rsp); + +/* + * Get PHY devices attached to an interface + */ +struct ethtool_phy_get_rsp * +ethtool_phy_get(struct ynl_sock *ys, struct ethtool_phy_get_req *req); + +/* ETHTOOL_MSG_PHY_GET - dump */ +struct ethtool_phy_get_req_dump { + struct { + __u32 header:1; + } _present; + + struct ethtool_header header; +}; + +static inline struct ethtool_phy_get_req_dump * +ethtool_phy_get_req_dump_alloc(void) +{ + return calloc(1, sizeof(struct ethtool_phy_get_req_dump)); +} +void ethtool_phy_get_req_dump_free(struct ethtool_phy_get_req_dump *req); + +static inline void +ethtool_phy_get_req_dump_set_header_dev_index(struct ethtool_phy_get_req_dump *req, + __u32 dev_index) +{ + req->_present.header = 1; + req->header._present.dev_index = 1; + req->header.dev_index = dev_index; +} +static inline void +ethtool_phy_get_req_dump_set_header_dev_name(struct ethtool_phy_get_req_dump *req, + const char *dev_name) +{ + free(req->header.dev_name); + req->header._present.dev_name_len = strlen(dev_name); + req->header.dev_name = malloc(req->header._present.dev_name_len + 1); + memcpy(req->header.dev_name, dev_name, req->header._present.dev_name_len); + req->header.dev_name[req->header._present.dev_name_len] = 0; +} +static inline void +ethtool_phy_get_req_dump_set_header_flags(struct ethtool_phy_get_req_dump *req, + __u32 flags) +{ + req->_present.header = 1; + req->header._present.flags = 1; + req->header.flags = flags; +} +static inline void +ethtool_phy_get_req_dump_set_header_phy_index(struct ethtool_phy_get_req_dump *req, + __u32 phy_index) +{ + req->_present.header = 1; + req->header._present.phy_index = 1; + req->header.phy_index = phy_index; +} + +struct ethtool_phy_get_list { + struct ethtool_phy_get_list *next; + struct ethtool_phy_get_rsp obj __attribute__((aligned(8))); +}; + +void ethtool_phy_get_list_free(struct ethtool_phy_get_list *rsp); + +struct ethtool_phy_get_list * +ethtool_phy_get_dump(struct ynl_sock *ys, struct ethtool_phy_get_req_dump *req); + /* ETHTOOL_MSG_CABLE_TEST_NTF - event */ struct ethtool_cable_test_ntf_rsp { struct { -- 2.42.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2023-12-01 16:37 UTC|newest] Thread overview: 47+ messages / expand[flat|nested] mbox.gz Atom feed top 2023-12-01 16:36 [RFC PATCH net-next v3 00/13] Introduce PHY listing and link_topology tracking Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 01/13] net: phy: Introduce ethernet link topology representation Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-05 14:49 ` kernel test robot 2023-12-05 15:31 ` kernel test robot 2023-12-09 17:02 ` Simon Horman 2023-12-09 17:02 ` Simon Horman 2023-12-11 11:06 ` Maxime Chevallier 2023-12-11 11:06 ` Maxime Chevallier 2023-12-11 14:09 ` Andrew Lunn 2023-12-11 14:09 ` Andrew Lunn 2023-12-12 13:10 ` Maxime Chevallier 2023-12-12 13:10 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 02/13] net: sfp: pass the phy_device when disconnecting an sfp module's PHY Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 03/13] net: phy: add helpers to handle sfp phy connect/disconnect Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 04/13] net: sfp: Add helper to return the SFP bus name Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 05/13] net: ethtool: Allow passing a phy index for some commands Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-05 16:35 ` kernel test robot 2023-12-01 16:36 ` [RFC PATCH net-next v3 06/13] netlink: specs: add phy-index as a header parameter Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-04 10:36 ` Maxime Chevallier 2023-12-04 10:36 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 07/13] net: ethtool: Introduce a command to list PHYs on an interface Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-09 17:04 ` Simon Horman 2023-12-09 17:04 ` Simon Horman 2023-12-11 11:07 ` Maxime Chevallier 2023-12-11 11:07 ` Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier [this message] 2023-12-01 16:36 ` [RFC PATCH net-next v3 08/13] netlink: specs: add ethnl PHY_GET command set Maxime Chevallier 2023-12-04 10:37 ` Maxime Chevallier 2023-12-04 10:37 ` Maxime Chevallier 2023-12-01 16:36 ` [RFC PATCH net-next v3 09/13] net: ethtool: plca: Target the command to the requested PHY Maxime Chevallier 2023-12-01 16:36 ` Maxime Chevallier 2023-12-01 16:37 ` [RFC PATCH net-next v3 10/13] net: ethtool: pse-pd: " Maxime Chevallier 2023-12-01 16:37 ` Maxime Chevallier 2023-12-01 16:37 ` [RFC PATCH net-next v3 11/13] net: ethtool: cable-test: " Maxime Chevallier 2023-12-01 16:37 ` Maxime Chevallier 2023-12-01 16:37 ` [RFC PATCH net-next v3 12/13] net: ethtool: strset: Allow querying phy stats by index Maxime Chevallier 2023-12-01 16:37 ` Maxime Chevallier 2023-12-01 16:37 ` [RFC PATCH net-next v3 13/13] Documentation: networking: document phy_link_topology Maxime Chevallier 2023-12-01 16:37 ` Maxime Chevallier
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20231201163704.1306431-9-maxime.chevallier@bootlin.com \ --to=maxime.chevallier@bootlin.com \ --cc=andrew@lunn.ch \ --cc=christophe.leroy@csgroup.eu \ --cc=corbet@lwn.net \ --cc=davem@davemloft.net \ --cc=edumazet@google.com \ --cc=f.fainelli@gmail.com \ --cc=herve.codina@bootlin.com \ --cc=hkallweit1@gmail.com \ --cc=jesse.brandeburg@intel.com \ --cc=kabel@kernel.org \ --cc=kory.maincent@bootlin.com \ --cc=kuba@kernel.org \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-kernel@vger.kernel.org \ --cc=linux@armlinux.org.uk \ --cc=netdev@vger.kernel.org \ --cc=nicveronese@gmail.com \ --cc=o.rempel@pengutronix.de \ --cc=pabeni@redhat.com \ --cc=piergiorgio.beruto@gmail.com \ --cc=thomas.petazzoni@bootlin.com \ --cc=vladimir.oltean@nxp.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.