From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BDF5A3F167F; Wed, 25 Mar 2026 14:50:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774450246; cv=none; b=D52C7RMXVYYgfBd08Am9ZjkXupWQHB8/da5VnGUItV6UJ6eTQRtpN3ZjCBYMLrQvSY3KeNZ7cjtVlsqQ/XrdyAgHSRCxC6weXpgcsiDWpL3rQrrKhwR+JP3bb3PShK5W7jyl3ABQ4L2KMY9WlbNqPMrcpLyQ2PTcvqfizxXH/aw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774450246; c=relaxed/simple; bh=B2jjbUhgJ4MXfE+thEyq82EMdUbPh8/iHqQ9R3WcBr4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=EVC58hjVd3h+bVLLriMtKmdc23hKRJhWv2YkV20bxuT0MEo2wwyoPfwURXPXY0S4gmqxLcooTiuU9/ZNFy1ebcbmeoVJ3c6U1T3tx8yJUJZJ0+0/rfIS05USf0Vb/xIdTJcyCS7nG1BEPD4rZ+74tbDfPsRfUak5FQtssXuKjMk= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=M1gm8g3q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="M1gm8g3q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 25395C2BCB0; Wed, 25 Mar 2026 14:50:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774450246; bh=B2jjbUhgJ4MXfE+thEyq82EMdUbPh8/iHqQ9R3WcBr4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=M1gm8g3qQFotMXbcMKjVuBkbwizglIo98Qyf/BYiw6Xvku3PSVcDf2GFilrh/36FE 01SQaNyaud2axP3yebSvkmhsm/ChT81hPRg6+QKWIpvMOSvTk9+IAi4BejsQppjnDT P9XbNwPgpoA56QWc0NdBMVFHE4Pma4pvpBvZBLVEDcOlhzwlGY31iR8NPeik9pIzIO rj6uWyFlu/9vdNJDsWE+xaSkjuG/cYsTyjzzc5WsDIHRYCr1cv3qi2EdW1HFWDPLel V/Dc7CnBmMXTYPiNOumVyn9WHQNb74V51WA2hulXfnIpVpX7YLjOUN5CiGsrauEXuL 1vd+ZKSna/zeg== From: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= To: netdev@vger.kernel.org, "David S. Miller" , Andrew Lunn , Donald Hunter , Eric Dumazet , Jakub Kicinski , Maxime Chevallier , Naveen Mamindlapalli , Paolo Abeni , Simon Horman Cc: =?UTF-8?q?Bj=C3=B6rn=20T=C3=B6pel?= , Danielle Ratson , Hariprasad Kelam , Ido Schimmel , Kory Maincent , Leon Romanovsky , Michael Chan , Oleksij Rempel , Pavan Chebbi , Piergiorgio Beruto , Russell King , Saeed Mahameed , Shuah Khan , Tariq Toukan , Willem de Bruijn , Kees Cook , linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-rdma@vger.kernel.org Subject: [PATCH net-next v2 02/12] ethtool: Convert per-PHY commands to dump_one_dev Date: Wed, 25 Mar 2026 15:50:09 +0100 Message-ID: <20260325145022.2607545-3-bjorn@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260325145022.2607545-1-bjorn@kernel.org> References: <20260325145022.2607545-1-bjorn@kernel.org> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Convert PSE, PLCA, PHY, and MSE commands from the separate ethnl_perphy_{start,dumpit,done} handlers to use the generic dump_one_dev callback. This removes the per-PHY specific dump infrastructure (ethnl_perphy_dump_ctx, ethnl_perphy_dump_context, ethnl_perphy_start, ethnl_perphy_dumpit, ethnl_perphy_done, and the internal helpers) in favor of a shared ethnl_perphy_dump_one_dev() function. Signed-off-by: Björn Töpel --- net/ethtool/mse.c | 1 + net/ethtool/netlink.c | 194 ++++++------------------------------------ net/ethtool/netlink.h | 4 + net/ethtool/phy.c | 1 + net/ethtool/plca.c | 2 + net/ethtool/pse-pd.c | 1 + 6 files changed, 35 insertions(+), 168 deletions(-) diff --git a/net/ethtool/mse.c b/net/ethtool/mse.c index e91b74430f76..3f33182283ce 100644 --- a/net/ethtool/mse.c +++ b/net/ethtool/mse.c @@ -325,4 +325,5 @@ const struct ethnl_request_ops ethnl_mse_request_ops = { .cleanup_data = mse_cleanup_data, .reply_size = mse_reply_size, .fill_reply = mse_fill_reply, + .dump_one_dev = ethnl_perphy_dump_one_dev, }; diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c index 8d161f0882d0..edeeca67918a 100644 --- a/net/ethtool/netlink.c +++ b/net/ethtool/netlink.c @@ -399,12 +399,6 @@ static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb) return (struct ethnl_dump_ctx *)cb->ctx; } -static struct ethnl_perphy_dump_ctx * -ethnl_perphy_dump_context(struct netlink_callback *cb) -{ - return (struct ethnl_perphy_dump_ctx *)cb->ctx; -} - /** * ethnl_default_parse() - Parse request message * @req_info: pointer to structure to put data into @@ -686,169 +680,33 @@ static int ethnl_default_start(struct netlink_callback *cb) return ret; } -/* per-PHY ->start() handler for GET requests */ -static int ethnl_perphy_start(struct netlink_callback *cb) +/* Shared dump_one_dev for per-PHY commands (PSE, PLCA, PHY, MSE) */ +int ethnl_perphy_dump_one_dev(struct sk_buff *skb, + struct ethnl_dump_ctx *ctx, + unsigned long *pos_sub, + const struct genl_info *info) { - struct ethnl_perphy_dump_ctx *phy_ctx = ethnl_perphy_dump_context(cb); - const struct genl_dumpit_info *info = genl_dumpit_info(cb); - struct ethnl_dump_ctx *ctx = &phy_ctx->ethnl_ctx; - struct ethnl_reply_data *reply_data; - const struct ethnl_request_ops *ops; - struct ethnl_req_info *req_info; - struct genlmsghdr *ghdr; - int ret; - - BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx)); - - ghdr = nlmsg_data(cb->nlh); - ops = ethnl_default_requests[ghdr->cmd]; - if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", ghdr->cmd)) - return -EOPNOTSUPP; - req_info = kzalloc(ops->req_info_size, GFP_KERNEL); - if (!req_info) - return -ENOMEM; - reply_data = kmalloc(ops->reply_data_size, GFP_KERNEL); - if (!reply_data) { - ret = -ENOMEM; - goto free_req_info; - } - - /* Unlike per-dev dump, don't ignore dev. The dump handler - * will notice it and dump PHYs from given dev. We only keep track of - * the dev's ifindex, .dumpit() will grab and release the netdev itself. - */ - ret = ethnl_default_parse(req_info, &info->info, ops, false); - if (ret < 0) - goto free_reply_data; - if (req_info->dev) { - phy_ctx->ifindex = req_info->dev->ifindex; - netdev_put(req_info->dev, &req_info->dev_tracker); - req_info->dev = NULL; - } - - ctx->ops = ops; - ctx->req_info = req_info; - ctx->reply_data = reply_data; - ctx->pos_ifindex = 0; - - return 0; - -free_reply_data: - kfree(reply_data); -free_req_info: - kfree(req_info); - - return ret; -} - -static int ethnl_perphy_dump_one_dev(struct sk_buff *skb, - struct ethnl_perphy_dump_ctx *ctx, - const struct genl_info *info) -{ - struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; - struct net_device *dev = ethnl_ctx->req_info->dev; + struct net_device *dev = ctx->req_info->dev; struct phy_device_node *pdn; int ret; if (!dev->link_topo) return 0; - xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn, - ctx->pos_phyindex) { - ethnl_ctx->req_info->phy_index = ctx->pos_phyindex; + xa_for_each_start(&dev->link_topo->phys, *pos_sub, pdn, + *pos_sub) { + ctx->req_info->phy_index = *pos_sub; /* We can re-use the original dump_one as ->prepare_data in * commands use ethnl_req_get_phydev(), which gets the PHY from * the req_info->phy_index */ - ret = ethnl_default_dump_one(skb, dev, ethnl_ctx, info); + ret = ethnl_default_dump_one(skb, dev, ctx, info); if (ret) return ret; } - ctx->pos_phyindex = 0; - - return 0; -} - -static int ethnl_perphy_dump_all_dev(struct sk_buff *skb, - struct ethnl_perphy_dump_ctx *ctx, - const struct genl_info *info) -{ - struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; - struct net *net = sock_net(skb->sk); - netdevice_tracker dev_tracker; - struct net_device *dev; - int ret = 0; - - rcu_read_lock(); - for_each_netdev_dump(net, dev, ethnl_ctx->pos_ifindex) { - netdev_hold(dev, &dev_tracker, GFP_ATOMIC); - rcu_read_unlock(); - - /* per-PHY commands use ethnl_req_get_phydev(), which needs the - * net_device in the req_info - */ - ethnl_ctx->req_info->dev = dev; - ret = ethnl_perphy_dump_one_dev(skb, ctx, info); - - rcu_read_lock(); - netdev_put(dev, &dev_tracker); - ethnl_ctx->req_info->dev = NULL; - - if (ret < 0 && ret != -EOPNOTSUPP) { - if (likely(skb->len)) - ret = skb->len; - break; - } - ret = 0; - } - rcu_read_unlock(); - - return ret; -} - -/* per-PHY ->dumpit() handler for GET requests. */ -static int ethnl_perphy_dumpit(struct sk_buff *skb, - struct netlink_callback *cb) -{ - struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); - const struct genl_dumpit_info *info = genl_dumpit_info(cb); - struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; - int ret = 0; - - if (ctx->ifindex) { - netdevice_tracker dev_tracker; - struct net_device *dev; - - dev = netdev_get_by_index(genl_info_net(&info->info), - ctx->ifindex, &dev_tracker, - GFP_KERNEL); - if (!dev) - return -ENODEV; - - ethnl_ctx->req_info->dev = dev; - ret = ethnl_perphy_dump_one_dev(skb, ctx, genl_info_dump(cb)); - - if (ret < 0 && ret != -EOPNOTSUPP && likely(skb->len)) - ret = skb->len; - - netdev_put(dev, &dev_tracker); - } else { - ret = ethnl_perphy_dump_all_dev(skb, ctx, genl_info_dump(cb)); - } - - return ret; -} - -/* per-PHY ->done() handler for GET requests */ -static int ethnl_perphy_done(struct netlink_callback *cb) -{ - struct ethnl_perphy_dump_ctx *ctx = ethnl_perphy_dump_context(cb); - struct ethnl_dump_ctx *ethnl_ctx = &ctx->ethnl_ctx; - - kfree(ethnl_ctx->reply_data); - kfree(ethnl_ctx->req_info); + *pos_sub = 0; return 0; } @@ -1410,9 +1268,9 @@ static const struct genl_ops ethtool_genl_ops[] = { { .cmd = ETHTOOL_MSG_PSE_GET, .doit = ethnl_default_doit, - .start = ethnl_perphy_start, - .dumpit = ethnl_perphy_dumpit, - .done = ethnl_perphy_done, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, .policy = ethnl_pse_get_policy, .maxattr = ARRAY_SIZE(ethnl_pse_get_policy) - 1, }, @@ -1434,9 +1292,9 @@ static const struct genl_ops ethtool_genl_ops[] = { { .cmd = ETHTOOL_MSG_PLCA_GET_CFG, .doit = ethnl_default_doit, - .start = ethnl_perphy_start, - .dumpit = ethnl_perphy_dumpit, - .done = ethnl_perphy_done, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, .policy = ethnl_plca_get_cfg_policy, .maxattr = ARRAY_SIZE(ethnl_plca_get_cfg_policy) - 1, }, @@ -1450,9 +1308,9 @@ static const struct genl_ops ethtool_genl_ops[] = { { .cmd = ETHTOOL_MSG_PLCA_GET_STATUS, .doit = ethnl_default_doit, - .start = ethnl_perphy_start, - .dumpit = ethnl_perphy_dumpit, - .done = ethnl_perphy_done, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, .policy = ethnl_plca_get_status_policy, .maxattr = ARRAY_SIZE(ethnl_plca_get_status_policy) - 1, }, @@ -1482,9 +1340,9 @@ static const struct genl_ops ethtool_genl_ops[] = { { .cmd = ETHTOOL_MSG_PHY_GET, .doit = ethnl_default_doit, - .start = ethnl_perphy_start, - .dumpit = ethnl_perphy_dumpit, - .done = ethnl_perphy_done, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, .policy = ethnl_phy_get_policy, .maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1, }, @@ -1528,9 +1386,9 @@ static const struct genl_ops ethtool_genl_ops[] = { { .cmd = ETHTOOL_MSG_MSE_GET, .doit = ethnl_default_doit, - .start = ethnl_perphy_start, - .dumpit = ethnl_perphy_dumpit, - .done = ethnl_perphy_done, + .start = ethnl_default_start, + .dumpit = ethnl_default_dumpit, + .done = ethnl_default_done, .policy = ethnl_mse_get_policy, .maxattr = ARRAY_SIZE(ethnl_mse_get_policy) - 1, }, diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index e01adc5db02f..dda2f5593ed9 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -546,6 +546,10 @@ int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb); int ethnl_tsinfo_done(struct netlink_callback *cb); int ethnl_rss_create_doit(struct sk_buff *skb, struct genl_info *info); int ethnl_rss_delete_doit(struct sk_buff *skb, struct genl_info *info); +int ethnl_perphy_dump_one_dev(struct sk_buff *skb, + struct ethnl_dump_ctx *ctx, + unsigned long *pos_sub, + const struct genl_info *info); extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN]; extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN]; diff --git a/net/ethtool/phy.c b/net/ethtool/phy.c index d4e6887055ab..4bb23a5d6ad5 100644 --- a/net/ethtool/phy.c +++ b/net/ethtool/phy.c @@ -162,4 +162,5 @@ const struct ethnl_request_ops ethnl_phy_request_ops = { .reply_size = phy_reply_size, .fill_reply = phy_fill_reply, .cleanup_data = phy_cleanup_data, + .dump_one_dev = ethnl_perphy_dump_one_dev, }; diff --git a/net/ethtool/plca.c b/net/ethtool/plca.c index 91f0c4233298..84e902532617 100644 --- a/net/ethtool/plca.c +++ b/net/ethtool/plca.c @@ -188,6 +188,7 @@ const struct ethnl_request_ops ethnl_plca_cfg_request_ops = { .prepare_data = plca_get_cfg_prepare_data, .reply_size = plca_get_cfg_reply_size, .fill_reply = plca_get_cfg_fill_reply, + .dump_one_dev = ethnl_perphy_dump_one_dev, .set = ethnl_set_plca, .set_ntf_cmd = ETHTOOL_MSG_PLCA_NTF, @@ -268,4 +269,5 @@ const struct ethnl_request_ops ethnl_plca_status_request_ops = { .prepare_data = plca_get_status_prepare_data, .reply_size = plca_get_status_reply_size, .fill_reply = plca_get_status_fill_reply, + .dump_one_dev = ethnl_perphy_dump_one_dev, }; diff --git a/net/ethtool/pse-pd.c b/net/ethtool/pse-pd.c index 2eb9bdc2dcb9..83f0205053a3 100644 --- a/net/ethtool/pse-pd.c +++ b/net/ethtool/pse-pd.c @@ -338,6 +338,7 @@ const struct ethnl_request_ops ethnl_pse_request_ops = { .reply_size = pse_reply_size, .fill_reply = pse_fill_reply, .cleanup_data = pse_cleanup_data, + .dump_one_dev = ethnl_perphy_dump_one_dev, .set = ethnl_set_pse, /* PSE has no notification */ -- 2.53.0