1428 lines · 38.7 KB · C
RawDownload
/* * 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.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t