/* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "core_priv.h" #include <linux/slab.h>#include <linux/stat.h>#include <linux/string.h>#include <linux/netdevice.h>#include <linux/ethtool.h> #include <rdma/ib_mad.h>#include <rdma/ib_pma.h>#include <rdma/ib_cache.h>#include <rdma/rdma_counter.h>#include <rdma/ib_sysfs.h> struct port_table_attribute { struct ib_port_attribute attr; char name[8]; int index; __be16 attr_id;}; struct gid_attr_group { struct ib_port *port; struct kobject kobj; struct attribute_group groups[2]; const struct attribute_group *groups_list[3]; struct port_table_attribute attrs_list[];}; struct ib_port { struct kobject kobj; struct ib_device *ibdev; struct gid_attr_group *gid_attr_group; struct hw_stats_port_data *hw_stats_data; struct attribute_group groups[3]; const struct attribute_group *groups_list[5]; u32 port_num; struct port_table_attribute attrs_list[];}; struct hw_stats_device_attribute { struct device_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, unsigned int index, unsigned int port_num, const char *buf, size_t count);}; struct hw_stats_port_attribute { 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, unsigned int index, unsigned int port_num, const char *buf, size_t count);}; struct hw_stats_device_data { struct attribute_group group; struct rdma_hw_stats *stats; struct hw_stats_device_attribute attrs[];}; struct hw_stats_port_data { struct rdma_hw_stats *stats; struct hw_stats_port_attribute attrs[];}; static ssize_t port_attr_show(struct kobject *kobj, struct attribute *attr, char *buf){ 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->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 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->ibdev, p->port_num, port_attr, buf, count);} 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}; static ssize_t hw_stat_device_show(struct device *dev, struct device_attribute *attr, char *buf){ struct hw_stats_device_attribute *stat_attr = container_of(attr, struct hw_stats_device_attribute, attr); struct ib_device *ibdev = container_of(dev, struct ib_device, dev); return stat_attr->show(ibdev, ibdev->hw_stats_data->stats, stat_attr - ibdev->hw_stats_data->attrs, 0, buf);} static ssize_t hw_stat_device_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count){ struct hw_stats_device_attribute *stat_attr = container_of(attr, struct hw_stats_device_attribute, attr); struct ib_device *ibdev = container_of(dev, struct ib_device, dev); return stat_attr->store(ibdev, ibdev->hw_stats_data->stats, stat_attr - ibdev->hw_stats_data->attrs, 0, buf, count);} 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(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_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(ibdev, port->hw_stats_data->stats, stat_attr - port->hw_stats_data->attrs, port->port_num, buf, count);} static ssize_t gid_attr_show(struct kobject *kobj, struct attribute *attr, char *buf){ 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->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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf){ struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%d: %s\n", attr.state, ib_port_state_to_str(attr.state));} 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(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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf){ struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%u\n", attr.lmc);} 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(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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf){ struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%u\n", attr.sm_sl);} 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(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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf){ struct ib_port_speed_info speed_info; struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; ret = ib_port_attr_to_speed_info(&attr, &speed_info); if (ret) return ret; return sysfs_emit(buf, "%d%s Gb/sec (%dX%s)\n", speed_info.rate / 10, speed_info.rate % 10 ? ".5" : "", ib_width_enum_to_int(attr.active_width), speed_info.str);} static const char *phys_state_to_str(enum ib_port_phys_state phys_state){ static const char *phys_state_str[] = { "<unknown>", "Sleep", "Polling", "Disabled", "PortConfigurationTraining", "LinkUp", "LinkErrorRecovery", "Phy Test", }; if (phys_state < ARRAY_SIZE(phys_state_str)) return phys_state_str[phys_state]; return "<unknown>";} 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(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%u: %s\n", attr.phys_state, phys_state_to_str(attr.phys_state));} 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(ibdev, port_num)) { case IB_LINK_LAYER_INFINIBAND: output = "InfiniBand"; break; case IB_LINK_LAYER_ETHERNET: output = "Ethernet"; break; default: output = "Unknown"; break; } return sysfs_emit(buf, "%s\n", output);} 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[] = { &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};ATTRIBUTE_GROUPS(port_default); static ssize_t print_ndev(const struct ib_gid_attr *gid_attr, char *buf){ struct net_device *ndev; int ret = -EINVAL; rcu_read_lock(); ndev = rcu_dereference(gid_attr->ndev); if (ndev) ret = sysfs_emit(buf, "%s\n", ndev->name); rcu_read_unlock(); return ret;} static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf){ return sysfs_emit(buf, "%s\n", ib_cache_gid_type_str(gid_attr->gid_type));} static ssize_t _show_port_gid_attr( 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 = container_of(attr, struct port_table_attribute, attr); const struct ib_gid_attr *gid_attr; ssize_t ret; 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; ret = print(gid_attr, buf); rdma_put_gid_attr(gid_attr); return ret;} 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(ibdev, port_num, tab_attr->index); if (IS_ERR(gid_attr)) { const union ib_gid zgid = {}; /* If reading GID fails, it is likely due to GID entry being * empty (invalid) or reserved GID in the table. User space * expects to read GID table entries as long as it given index * is within GID table size. Administrative/debugging tool * fails to query rest of the GID entries if it hits error * while querying a GID of the given index. To avoid user * space throwing such error on fail to read gid, return zero * GID as before. This maintains backward compatibility. */ return sysfs_emit(buf, "%pI6\n", zgid.raw); } len = sysfs_emit(buf, "%pI6\n", gid_attr->gid.raw); rdma_put_gid_attr(gid_attr); return len;} 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(ibdev, port_num, attr, buf, print_ndev);} 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(ibdev, port_num, attr, buf, print_gid_type);} 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(ibdev, port_num, tab_attr->index, &pkey); if (ret) return ret; return sysfs_emit(buf, "0x%04x\n", pkey);} #define PORT_PMA_ATTR(_name, _counter, _width, _offset) \struct port_table_attribute port_pma_attr_##_name = { \ .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ .index = (_offset) | ((_width) << 16) | ((_counter) << 24), \ .attr_id = IB_PMA_PORT_COUNTERS, \} #define PORT_PMA_ATTR_EXT(_name, _width, _offset) \struct port_table_attribute port_pma_attr_ext_##_name = { \ .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ .index = (_offset) | ((_width) << 16), \ .attr_id = IB_PMA_PORT_COUNTERS_EXT, \}Lines 1–500 of 1428. Load more
/* * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU * General Public License (GPL) Version 2, available from the file * COPYING in the main directory of this source tree, or the * OpenIB.org BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "core_priv.h" #include <linux/slab.h> #include <linux/stat.h> #include <linux/string.h> #include <linux/netdevice.h> #include <linux/ethtool.h> #include <rdma/ib_mad.h> #include <rdma/ib_pma.h> #include <rdma/ib_cache.h> #include <rdma/rdma_counter.h> #include <rdma/ib_sysfs.h> struct port_table_attribute { struct ib_port_attribute attr; char name[8]; int index; __be16 attr_id; }; struct gid_attr_group { struct ib_port *port; struct kobject kobj; struct attribute_group groups[2]; const struct attribute_group *groups_list[3]; struct port_table_attribute attrs_list[]; }; struct ib_port { struct kobject kobj; struct ib_device *ibdev; struct gid_attr_group *gid_attr_group; struct hw_stats_port_data *hw_stats_data; struct attribute_group groups[3]; const struct attribute_group *groups_list[5]; u32 port_num; struct port_table_attribute attrs_list[]; }; struct hw_stats_device_attribute { struct device_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, unsigned int index, unsigned int port_num, const char *buf, size_t count); }; struct hw_stats_port_attribute { 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, unsigned int index, unsigned int port_num, const char *buf, size_t count); }; struct hw_stats_device_data { struct attribute_group group; struct rdma_hw_stats *stats; struct hw_stats_device_attribute attrs[]; }; struct hw_stats_port_data { struct rdma_hw_stats *stats; struct hw_stats_port_attribute attrs[]; }; static ssize_t port_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { 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->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 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->ibdev, p->port_num, port_attr, buf, count); } 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 }; static ssize_t hw_stat_device_show(struct device *dev, struct device_attribute *attr, char *buf) { struct hw_stats_device_attribute *stat_attr = container_of(attr, struct hw_stats_device_attribute, attr); struct ib_device *ibdev = container_of(dev, struct ib_device, dev); return stat_attr->show(ibdev, ibdev->hw_stats_data->stats, stat_attr - ibdev->hw_stats_data->attrs, 0, buf); } static ssize_t hw_stat_device_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hw_stats_device_attribute *stat_attr = container_of(attr, struct hw_stats_device_attribute, attr); struct ib_device *ibdev = container_of(dev, struct ib_device, dev); return stat_attr->store(ibdev, ibdev->hw_stats_data->stats, stat_attr - ibdev->hw_stats_data->attrs, 0, buf, count); } 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(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_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(ibdev, port->hw_stats_data->stats, stat_attr - port->hw_stats_data->attrs, port->port_num, buf, count); } static ssize_t gid_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) { 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->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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf) { struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%d: %s\n", attr.state, ib_port_state_to_str(attr.state)); } 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(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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf) { struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%u\n", attr.lmc); } 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(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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf) { struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%u\n", attr.sm_sl); } 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(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_device *ibdev, u32 port_num, struct ib_port_attribute *unused, char *buf) { struct ib_port_speed_info speed_info; struct ib_port_attr attr; ssize_t ret; ret = ib_query_port(ibdev, port_num, &attr); if (ret) return ret; ret = ib_port_attr_to_speed_info(&attr, &speed_info); if (ret) return ret; return sysfs_emit(buf, "%d%s Gb/sec (%dX%s)\n", speed_info.rate / 10, speed_info.rate % 10 ? ".5" : "", ib_width_enum_to_int(attr.active_width), speed_info.str); } static const char *phys_state_to_str(enum ib_port_phys_state phys_state) { static const char *phys_state_str[] = { "<unknown>", "Sleep", "Polling", "Disabled", "PortConfigurationTraining", "LinkUp", "LinkErrorRecovery", "Phy Test", }; if (phys_state < ARRAY_SIZE(phys_state_str)) return phys_state_str[phys_state]; return "<unknown>"; } 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(ibdev, port_num, &attr); if (ret) return ret; return sysfs_emit(buf, "%u: %s\n", attr.phys_state, phys_state_to_str(attr.phys_state)); } 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(ibdev, port_num)) { case IB_LINK_LAYER_INFINIBAND: output = "InfiniBand"; break; case IB_LINK_LAYER_ETHERNET: output = "Ethernet"; break; default: output = "Unknown"; break; } return sysfs_emit(buf, "%s\n", output); } 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[] = { &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 }; ATTRIBUTE_GROUPS(port_default); static ssize_t print_ndev(const struct ib_gid_attr *gid_attr, char *buf) { struct net_device *ndev; int ret = -EINVAL; rcu_read_lock(); ndev = rcu_dereference(gid_attr->ndev); if (ndev) ret = sysfs_emit(buf, "%s\n", ndev->name); rcu_read_unlock(); return ret; } static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf) { return sysfs_emit(buf, "%s\n", ib_cache_gid_type_str(gid_attr->gid_type)); } static ssize_t _show_port_gid_attr( 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 = container_of(attr, struct port_table_attribute, attr); const struct ib_gid_attr *gid_attr; ssize_t ret; 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; ret = print(gid_attr, buf); rdma_put_gid_attr(gid_attr); return ret; } 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(ibdev, port_num, tab_attr->index); if (IS_ERR(gid_attr)) { const union ib_gid zgid = {}; /* If reading GID fails, it is likely due to GID entry being * empty (invalid) or reserved GID in the table. User space * expects to read GID table entries as long as it given index * is within GID table size. Administrative/debugging tool * fails to query rest of the GID entries if it hits error * while querying a GID of the given index. To avoid user * space throwing such error on fail to read gid, return zero * GID as before. This maintains backward compatibility. */ return sysfs_emit(buf, "%pI6\n", zgid.raw); } len = sysfs_emit(buf, "%pI6\n", gid_attr->gid.raw); rdma_put_gid_attr(gid_attr); return len; } 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(ibdev, port_num, attr, buf, print_ndev); } 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(ibdev, port_num, attr, buf, print_gid_type); } 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(ibdev, port_num, tab_attr->index, &pkey); if (ret) return ret; return sysfs_emit(buf, "0x%04x\n", pkey); } #define PORT_PMA_ATTR(_name, _counter, _width, _offset) \ struct port_table_attribute port_pma_attr_##_name = { \ .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ .index = (_offset) | ((_width) << 16) | ((_counter) << 24), \ .attr_id = IB_PMA_PORT_COUNTERS, \ } #define PORT_PMA_ATTR_EXT(_name, _width, _offset) \ struct port_table_attribute port_pma_attr_ext_##_name = { \ .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ .index = (_offset) | ((_width) << 16), \ .attr_id = IB_PMA_PORT_COUNTERS_EXT, \ }