RDMA/core: Expose the ib port sysfs attribute machinery
authorJason Gunthorpe <jgg@nvidia.com>
Fri, 11 Jun 2021 16:00:28 +0000 (19:00 +0300)
committerJason Gunthorpe <jgg@nvidia.com>
Wed, 16 Jun 2021 23:58:30 +0000 (20:58 -0300)
Other things outside the core code are creating attributes against the
port. This patch exposes the basic machinery to do this.

The ib_port_attribute type allows creating groups of attributes attatched
to the port and comes with the usual machinery to do this.

Link: https://lore.kernel.org/r/5c4aeae57f6fa7c59a1d6d1c5506069516ae9bbf.1623427137.git.leonro@nvidia.com
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/core/sysfs.c
include/rdma/ib_sysfs.h [new file with mode: 0644]

index 14b8388..3c5541c 100644 (file)
 #include <rdma/ib_pma.h>
 #include <rdma/ib_cache.h>
 #include <rdma/rdma_counter.h>
-
-struct ib_port;
-
-struct port_attribute {
-       struct attribute attr;
-       ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf);
-       ssize_t (*store)(struct ib_port *, struct port_attribute *,
-                        const char *buf, size_t count);
-};
-
-#define PORT_ATTR(_name, _mode, _show, _store) \
-struct port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store)
-
-#define PORT_ATTR_RO(_name) \
-struct port_attribute port_attr_##_name = __ATTR_RO(_name)
+#include <rdma/ib_sysfs.h>
 
 struct port_table_attribute {
-       struct port_attribute   attr;
+       struct ib_port_attribute attr;
        char                    name[8];
        int                     index;
        __be16                  attr_id;
@@ -97,7 +83,7 @@ struct hw_stats_device_attribute {
 };
 
 struct hw_stats_port_attribute {
-       struct port_attribute attr;
+       struct ib_port_attribute attr;
        ssize_t (*show)(struct ib_device *ibdev, struct rdma_hw_stats *stats,
                        unsigned int index, unsigned int port_num, char *buf);
        ssize_t (*store)(struct ib_device *ibdev, struct rdma_hw_stats *stats,
@@ -119,29 +105,55 @@ struct hw_stats_port_data {
 static ssize_t port_attr_show(struct kobject *kobj,
                              struct attribute *attr, char *buf)
 {
-       struct port_attribute *port_attr =
-               container_of(attr, struct port_attribute, attr);
+       struct ib_port_attribute *port_attr =
+               container_of(attr, struct ib_port_attribute, attr);
        struct ib_port *p = container_of(kobj, struct ib_port, kobj);
 
        if (!port_attr->show)
                return -EIO;
 
-       return port_attr->show(p, port_attr, buf);
+       return port_attr->show(p->ibdev, p->port_num, port_attr, buf);
 }
 
 static ssize_t port_attr_store(struct kobject *kobj,
                               struct attribute *attr,
                               const char *buf, size_t count)
 {
-       struct port_attribute *port_attr =
-               container_of(attr, struct port_attribute, attr);
+       struct ib_port_attribute *port_attr =
+               container_of(attr, struct ib_port_attribute, attr);
        struct ib_port *p = container_of(kobj, struct ib_port, kobj);
 
        if (!port_attr->store)
                return -EIO;
-       return port_attr->store(p, port_attr, buf, count);
+       return port_attr->store(p->ibdev, p->port_num, port_attr, buf, count);
 }
 
+int ib_port_sysfs_create_groups(struct ib_device *ibdev, u32 port_num,
+                               const struct attribute_group **groups)
+{
+       return sysfs_create_groups(&ibdev->port_data[port_num].sysfs->kobj,
+                                  groups);
+}
+EXPORT_SYMBOL_GPL(ib_port_sysfs_create_groups);
+
+void ib_port_sysfs_remove_groups(struct ib_device *ibdev, u32 port_num,
+                                const struct attribute_group **groups)
+{
+       return sysfs_remove_groups(&ibdev->port_data[port_num].sysfs->kobj,
+                                  groups);
+}
+EXPORT_SYMBOL_GPL(ib_port_sysfs_remove_groups);
+
+struct ib_device *ib_port_sysfs_get_ibdev_kobj(struct kobject *kobj,
+                                              u32 *port_num)
+{
+       struct ib_port *port = container_of(kobj, struct ib_port, kobj);
+
+       *port_num = port->port_num;
+       return port->ibdev;
+}
+EXPORT_SYMBOL(ib_port_sysfs_get_ibdev_kobj);
+
 static const struct sysfs_ops port_sysfs_ops = {
        .show   = port_attr_show,
        .store  = port_attr_store
@@ -171,25 +183,27 @@ static ssize_t hw_stat_device_store(struct device *dev,
                                count);
 }
 
-static ssize_t hw_stat_port_show(struct ib_port *port,
-                                struct port_attribute *attr, char *buf)
+static ssize_t hw_stat_port_show(struct ib_device *ibdev, u32 port_num,
+                                struct ib_port_attribute *attr, char *buf)
 {
        struct hw_stats_port_attribute *stat_attr =
                container_of(attr, struct hw_stats_port_attribute, attr);
+       struct ib_port *port = ibdev->port_data[port_num].sysfs;
 
-       return stat_attr->show(port->ibdev, port->hw_stats_data->stats,
+       return stat_attr->show(ibdev, port->hw_stats_data->stats,
                               stat_attr - port->hw_stats_data->attrs,
                               port->port_num, buf);
 }
 
-static ssize_t hw_stat_port_store(struct ib_port *port,
-                                 struct port_attribute *attr, const char *buf,
-                                 size_t count)
+static ssize_t hw_stat_port_store(struct ib_device *ibdev, u32 port_num,
+                                 struct ib_port_attribute *attr,
+                                 const char *buf, size_t count)
 {
        struct hw_stats_port_attribute *stat_attr =
                container_of(attr, struct hw_stats_port_attribute, attr);
+       struct ib_port *port = ibdev->port_data[port_num].sysfs;
 
-       return stat_attr->store(port->ibdev, port->hw_stats_data->stats,
+       return stat_attr->store(ibdev, port->hw_stats_data->stats,
                                stat_attr - port->hw_stats_data->attrs,
                                port->port_num, buf, count);
 }
@@ -197,23 +211,23 @@ static ssize_t hw_stat_port_store(struct ib_port *port,
 static ssize_t gid_attr_show(struct kobject *kobj,
                             struct attribute *attr, char *buf)
 {
-       struct port_attribute *port_attr =
-               container_of(attr, struct port_attribute, attr);
+       struct ib_port_attribute *port_attr =
+               container_of(attr, struct ib_port_attribute, attr);
        struct ib_port *p = container_of(kobj, struct gid_attr_group,
                                         kobj)->port;
 
        if (!port_attr->show)
                return -EIO;
 
-       return port_attr->show(p, port_attr, buf);
+       return port_attr->show(p->ibdev, p->port_num, port_attr, buf);
 }
 
 static const struct sysfs_ops gid_attr_sysfs_ops = {
        .show = gid_attr_show
 };
 
-static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
-                         char *buf)
+static ssize_t state_show(struct ib_device *ibdev, u32 port_num,
+                         struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        ssize_t ret;
@@ -227,7 +241,7 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
                [IB_PORT_ACTIVE_DEFER]  = "ACTIVE_DEFER"
        };
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
@@ -238,81 +252,80 @@ static ssize_t state_show(struct ib_port *p, struct port_attribute *unused,
                                  "UNKNOWN");
 }
 
-static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused,
-                       char *buf)
+static ssize_t lid_show(struct ib_device *ibdev, u32 port_num,
+                       struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
        return sysfs_emit(buf, "0x%x\n", attr.lid);
 }
 
-static ssize_t lid_mask_count_show(struct ib_port *p,
-                                  struct port_attribute *unused,
-                                  char *buf)
+static ssize_t lid_mask_count_show(struct ib_device *ibdev, u32 port_num,
+                                  struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
        return sysfs_emit(buf, "%d\n", attr.lmc);
 }
 
-static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused,
-                          char *buf)
+static ssize_t sm_lid_show(struct ib_device *ibdev, u32 port_num,
+                          struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
        return sysfs_emit(buf, "0x%x\n", attr.sm_lid);
 }
 
-static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused,
-                         char *buf)
+static ssize_t sm_sl_show(struct ib_device *ibdev, u32 port_num,
+                         struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
        return sysfs_emit(buf, "%d\n", attr.sm_sl);
 }
 
-static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused,
-                            char *buf)
+static ssize_t cap_mask_show(struct ib_device *ibdev, u32 port_num,
+                            struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
        return sysfs_emit(buf, "0x%08x\n", attr.port_cap_flags);
 }
 
-static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,
-                        char *buf)
+static ssize_t rate_show(struct ib_device *ibdev, u32 port_num,
+                        struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
        char *speed = "";
        int rate;               /* in deci-Gb/sec */
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
@@ -379,14 +392,14 @@ static const char *phys_state_to_str(enum ib_port_phys_state phys_state)
        return "<unknown>";
 }
 
-static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,
-                              char *buf)
+static ssize_t phys_state_show(struct ib_device *ibdev, u32 port_num,
+                              struct ib_port_attribute *unused, char *buf)
 {
        struct ib_port_attr attr;
 
        ssize_t ret;
 
-       ret = ib_query_port(p->ibdev, p->port_num, &attr);
+       ret = ib_query_port(ibdev, port_num, &attr);
        if (ret)
                return ret;
 
@@ -394,12 +407,12 @@ static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused,
                          phys_state_to_str(attr.phys_state));
 }
 
-static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
-                              char *buf)
+static ssize_t link_layer_show(struct ib_device *ibdev, u32 port_num,
+                              struct ib_port_attribute *unused, char *buf)
 {
        const char *output;
 
-       switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) {
+       switch (rdma_port_get_link_layer(ibdev, port_num)) {
        case IB_LINK_LAYER_INFINIBAND:
                output = "InfiniBand";
                break;
@@ -414,26 +427,26 @@ static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused,
        return sysfs_emit(buf, "%s\n", output);
 }
 
-static PORT_ATTR_RO(state);
-static PORT_ATTR_RO(lid);
-static PORT_ATTR_RO(lid_mask_count);
-static PORT_ATTR_RO(sm_lid);
-static PORT_ATTR_RO(sm_sl);
-static PORT_ATTR_RO(cap_mask);
-static PORT_ATTR_RO(rate);
-static PORT_ATTR_RO(phys_state);
-static PORT_ATTR_RO(link_layer);
+static IB_PORT_ATTR_RO(state);
+static IB_PORT_ATTR_RO(lid);
+static IB_PORT_ATTR_RO(lid_mask_count);
+static IB_PORT_ATTR_RO(sm_lid);
+static IB_PORT_ATTR_RO(sm_sl);
+static IB_PORT_ATTR_RO(cap_mask);
+static IB_PORT_ATTR_RO(rate);
+static IB_PORT_ATTR_RO(phys_state);
+static IB_PORT_ATTR_RO(link_layer);
 
 static struct attribute *port_default_attrs[] = {
-       &port_attr_state.attr,
-       &port_attr_lid.attr,
-       &port_attr_lid_mask_count.attr,
-       &port_attr_sm_lid.attr,
-       &port_attr_sm_sl.attr,
-       &port_attr_cap_mask.attr,
-       &port_attr_rate.attr,
-       &port_attr_phys_state.attr,
-       &port_attr_link_layer.attr,
+       &ib_port_attr_state.attr,
+       &ib_port_attr_lid.attr,
+       &ib_port_attr_lid_mask_count.attr,
+       &ib_port_attr_sm_lid.attr,
+       &ib_port_attr_sm_sl.attr,
+       &ib_port_attr_cap_mask.attr,
+       &ib_port_attr_rate.attr,
+       &ib_port_attr_phys_state.attr,
+       &ib_port_attr_link_layer.attr,
        NULL
 };
 
@@ -457,7 +470,8 @@ static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf)
 }
 
 static ssize_t _show_port_gid_attr(
-       struct ib_port *p, struct port_attribute *attr, char *buf,
+       struct ib_device *ibdev, u32 port_num, struct ib_port_attribute *attr,
+       char *buf,
        ssize_t (*print)(const struct ib_gid_attr *gid_attr, char *buf))
 {
        struct port_table_attribute *tab_attr =
@@ -465,7 +479,7 @@ static ssize_t _show_port_gid_attr(
        const struct ib_gid_attr *gid_attr;
        ssize_t ret;
 
-       gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index);
+       gid_attr = rdma_get_gid_attr(ibdev, port_num, tab_attr->index);
        if (IS_ERR(gid_attr))
                /* -EINVAL is returned for user space compatibility reasons. */
                return -EINVAL;
@@ -475,15 +489,15 @@ static ssize_t _show_port_gid_attr(
        return ret;
 }
 
-static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
-                            char *buf)
+static ssize_t show_port_gid(struct ib_device *ibdev, u32 port_num,
+                            struct ib_port_attribute *attr, char *buf)
 {
        struct port_table_attribute *tab_attr =
                container_of(attr, struct port_table_attribute, attr);
        const struct ib_gid_attr *gid_attr;
        int len;
 
-       gid_attr = rdma_get_gid_attr(p->ibdev, p->port_num, tab_attr->index);
+       gid_attr = rdma_get_gid_attr(ibdev, port_num, tab_attr->index);
        if (IS_ERR(gid_attr)) {
                const union ib_gid zgid = {};
 
@@ -504,28 +518,30 @@ static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr,
        return len;
 }
 
-static ssize_t show_port_gid_attr_ndev(struct ib_port *p,
-                                      struct port_attribute *attr, char *buf)
+static ssize_t show_port_gid_attr_ndev(struct ib_device *ibdev, u32 port_num,
+                                      struct ib_port_attribute *attr,
+                                      char *buf)
 {
-       return _show_port_gid_attr(p, attr, buf, print_ndev);
+       return _show_port_gid_attr(ibdev, port_num, attr, buf, print_ndev);
 }
 
-static ssize_t show_port_gid_attr_gid_type(struct ib_port *p,
-                                          struct port_attribute *attr,
+static ssize_t show_port_gid_attr_gid_type(struct ib_device *ibdev,
+                                          u32 port_num,
+                                          struct ib_port_attribute *attr,
                                           char *buf)
 {
-       return _show_port_gid_attr(p, attr, buf, print_gid_type);
+       return _show_port_gid_attr(ibdev, port_num, attr, buf, print_gid_type);
 }
 
-static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr,
-                             char *buf)
+static ssize_t show_port_pkey(struct ib_device *ibdev, u32 port_num,
+                             struct ib_port_attribute *attr, char *buf)
 {
        struct port_table_attribute *tab_attr =
                container_of(attr, struct port_table_attribute, attr);
        u16 pkey;
        int ret;
 
-       ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey);
+       ret = ib_query_pkey(ibdev, port_num, tab_attr->index, &pkey);
        if (ret)
                return ret;
 
@@ -594,8 +610,8 @@ out:
        return ret;
 }
 
-static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
-                               char *buf)
+static ssize_t show_pma_counter(struct ib_device *ibdev, u32 port_num,
+                               struct ib_port_attribute *attr, char *buf)
 {
        struct port_table_attribute *tab_attr =
                container_of(attr, struct port_table_attribute, attr);
@@ -605,7 +621,7 @@ static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr,
        u8 data[8];
        int len;
 
-       ret = get_perf_mad(p->ibdev, p->port_num, tab_attr->attr_id, &data,
+       ret = get_perf_mad(ibdev, port_num, tab_attr->attr_id, &data,
                        40 + offset / 8, sizeof(data));
        if (ret < 0)
                return ret;
@@ -1077,10 +1093,11 @@ struct rdma_hw_stats *ib_get_hw_stats_port(struct ib_device *ibdev,
        return ibdev->port_data[port_num].sysfs->hw_stats_data->stats;
 }
 
-static int alloc_port_table_group(
-       const char *name, struct attribute_group *group,
-       struct port_table_attribute *attrs, size_t num,
-       ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf))
+static int
+alloc_port_table_group(const char *name, struct attribute_group *group,
+                      struct port_table_attribute *attrs, size_t num,
+                      ssize_t (*show)(struct ib_device *ibdev, u32 port_num,
+                                      struct ib_port_attribute *, char *buf))
 {
        struct attribute **attr_list;
        int i;
diff --git a/include/rdma/ib_sysfs.h b/include/rdma/ib_sysfs.h
new file mode 100644 (file)
index 0000000..f869d0e
--- /dev/null
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
+/*
+ * Copyright (c) 2021 Mellanox Technologies Ltd.  All rights reserved.
+ */
+#ifndef DEF_RDMA_IB_SYSFS_H
+#define DEF_RDMA_IB_SYSFS_H
+
+#include <linux/sysfs.h>
+
+struct ib_device;
+
+struct ib_port_attribute {
+       struct attribute attr;
+       ssize_t (*show)(struct ib_device *ibdev, u32 port_num,
+                       struct ib_port_attribute *attr, char *buf);
+       ssize_t (*store)(struct ib_device *ibdev, u32 port_num,
+                        struct ib_port_attribute *attr, const char *buf,
+                        size_t count);
+};
+
+#define IB_PORT_ATTR_RW(_name)                                                 \
+       struct ib_port_attribute ib_port_attr_##_name = __ATTR_RW(_name)
+
+#define IB_PORT_ATTR_ADMIN_RW(_name)                                           \
+       struct ib_port_attribute ib_port_attr_##_name =                        \
+               __ATTR_RW_MODE(_name, 0600)
+
+#define IB_PORT_ATTR_RO(_name)                                                 \
+       struct ib_port_attribute ib_port_attr_##_name = __ATTR_RO(_name)
+
+#define IB_PORT_ATTR_WO(_name)                                                 \
+       struct ib_port_attribute ib_port_attr_##_name = __ATTR_WO(_name)
+
+int ib_port_sysfs_create_groups(struct ib_device *ibdev, u32 port_num,
+                               const struct attribute_group **groups);
+void ib_port_sysfs_remove_groups(struct ib_device *ibdev, u32 port_num,
+                                const struct attribute_group **groups);
+struct ib_device *ib_port_sysfs_get_ibdev_kobj(struct kobject *kobj,
+                                              u32 *port_num);
+
+#endif