From: Yajun Deng <yajun.deng@linux.dev>
To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org,
pabeni@redhat.com, horms@kernel.org, andrew+netdev@lunn.ch
Cc: netdev@vger.kernel.org, Yajun Deng <yajun.deng@linux.dev>
Subject: [PATCH net-next] net: sysfs: Implement is_visible for phys_(port_id, port_name, switch_id)
Date: Thu, 15 May 2025 21:02:05 +0800 [thread overview]
Message-ID: <20250515130205.3274-1-yajun.deng@linux.dev> (raw)
phys_port_id_show, phys_port_name_show and phys_switch_id_show would
return -EOPNOTSUPP if the netdev didn't implement the corresponding
method.
There is no point in creating these files if they are unsupported.
Put these attributes in netdev_phys_group and implement the is_visible
method. make phys_(port_id, port_name, switch_id) invisible if the netdev
dosen't implement the corresponding method.
Signed-off-by: Yajun Deng <yajun.deng@linux.dev>
---
include/linux/netdevice.h | 2 +-
net/core/net-sysfs.c | 78 +++++++++++++++++++++++++--------------
2 files changed, 52 insertions(+), 28 deletions(-)
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 32a1e41636a9..efbcc4836498 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -2384,7 +2384,7 @@ struct net_device {
struct dm_hw_stat_delta __rcu *dm_private;
#endif
struct device dev;
- const struct attribute_group *sysfs_groups[4];
+ const struct attribute_group *sysfs_groups[5];
const struct attribute_group *sysfs_rx_queue_group;
const struct rtnl_link_ops *rtnl_link_ops;
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index 1ace0cd01adc..f176b7808abe 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -641,12 +641,6 @@ static ssize_t phys_port_id_show(struct device *dev,
struct netdev_phys_item_id ppid;
ssize_t ret;
- /* The check is also done in dev_get_phys_port_id; this helps returning
- * early without hitting the locking section below.
- */
- if (!netdev->netdev_ops->ndo_get_phys_port_id)
- return -EOPNOTSUPP;
-
ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev);
if (ret)
return ret;
@@ -659,7 +653,8 @@ static ssize_t phys_port_id_show(struct device *dev,
return ret;
}
-static DEVICE_ATTR_RO(phys_port_id);
+static struct device_attribute dev_attr_phys_port_id =
+ __ATTR(phys_port_id, 0444, phys_port_id_show, NULL);
static ssize_t phys_port_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -668,13 +663,6 @@ static ssize_t phys_port_name_show(struct device *dev,
char name[IFNAMSIZ];
ssize_t ret;
- /* The checks are also done in dev_get_phys_port_name; this helps
- * returning early without hitting the locking section below.
- */
- if (!netdev->netdev_ops->ndo_get_phys_port_name &&
- !netdev->devlink_port)
- return -EOPNOTSUPP;
-
ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev);
if (ret)
return ret;
@@ -687,7 +675,8 @@ static ssize_t phys_port_name_show(struct device *dev,
return ret;
}
-static DEVICE_ATTR_RO(phys_port_name);
+static struct device_attribute dev_attr_phys_port_name =
+ __ATTR(phys_port_name, 0444, phys_port_name_show, NULL);
static ssize_t phys_switch_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -696,14 +685,6 @@ static ssize_t phys_switch_id_show(struct device *dev,
struct netdev_phys_item_id ppid = { };
ssize_t ret;
- /* The checks are also done in dev_get_phys_port_name; this helps
- * returning early without hitting the locking section below. This works
- * because recurse is false when calling dev_get_port_parent_id.
- */
- if (!netdev->netdev_ops->ndo_get_port_parent_id &&
- !netdev->devlink_port)
- return -EOPNOTSUPP;
-
ret = sysfs_rtnl_lock(&dev->kobj, &attr->attr, netdev);
if (ret)
return ret;
@@ -716,7 +697,52 @@ static ssize_t phys_switch_id_show(struct device *dev,
return ret;
}
-static DEVICE_ATTR_RO(phys_switch_id);
+static struct device_attribute dev_attr_phys_switch_id =
+ __ATTR(phys_switch_id, 0444, phys_switch_id_show, NULL);
+
+static struct attribute *netdev_phys_attrs[] __ro_after_init = {
+ &dev_attr_phys_port_id.attr,
+ &dev_attr_phys_port_name.attr,
+ &dev_attr_phys_switch_id.attr,
+ NULL,
+};
+
+static umode_t netdev_phys_is_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct net_device *netdev = to_net_dev(dev);
+
+ if (attr == &dev_attr_phys_port_id.attr) {
+ /* The check is also done in dev_get_phys_port_id; this helps returning
+ * early without hitting the locking section below.
+ */
+ if (!netdev->netdev_ops->ndo_get_phys_port_id)
+ return 0;
+ } else if (attr == &dev_attr_phys_port_name.attr) {
+ /* The checks are also done in dev_get_phys_port_name; this helps
+ * returning early without hitting the locking section below.
+ */
+ if (!netdev->netdev_ops->ndo_get_phys_port_name &&
+ !netdev->devlink_port)
+ return 0;
+ } else if (attr == &dev_attr_phys_switch_id.attr) {
+ /* The checks are also done in dev_get_phys_port_name; this helps
+ * returning early without hitting the locking section below. This works
+ * because recurse is false when calling dev_get_port_parent_id.
+ */
+ if (!netdev->netdev_ops->ndo_get_port_parent_id &&
+ !netdev->devlink_port)
+ return 0;
+ }
+
+ return attr->mode;
+}
+
+static struct attribute_group netdev_phys_group = {
+ .attrs = netdev_phys_attrs,
+ .is_visible = netdev_phys_is_visible,
+};
static ssize_t threaded_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -783,9 +809,6 @@ static struct attribute *net_class_attrs[] __ro_after_init = {
&dev_attr_tx_queue_len.attr,
&dev_attr_gro_flush_timeout.attr,
&dev_attr_napi_defer_hard_irqs.attr,
- &dev_attr_phys_port_id.attr,
- &dev_attr_phys_port_name.attr,
- &dev_attr_phys_switch_id.attr,
&dev_attr_proto_down.attr,
&dev_attr_carrier_up_count.attr,
&dev_attr_carrier_down_count.attr,
@@ -2328,6 +2351,7 @@ int netdev_register_kobject(struct net_device *ndev)
groups++;
*groups++ = &netstat_group;
+ *groups++ = &netdev_phys_group;
if (wireless_group_needed(ndev))
*groups++ = &wireless_group;
--
2.25.1
next reply other threads:[~2025-05-15 13:02 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-05-15 13:02 Yajun Deng [this message]
2025-05-16 22:26 ` [PATCH net-next] net: sysfs: Implement is_visible for phys_(port_id, port_name, switch_id) Jakub Kicinski
2025-05-17 2:24 ` Yajun Deng
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=20250515130205.3274-1-yajun.deng@linux.dev \
--to=yajun.deng@linux.dev \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.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: link
Be 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.