diff options
Diffstat (limited to 'drivers/infiniband/core/sysfs.c')
| -rw-r--r-- | drivers/infiniband/core/sysfs.c | 128 | 
1 files changed, 81 insertions, 47 deletions
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index 9ab5df72df7..cbd0383f622 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -35,6 +35,7 @@  #include "core_priv.h"  #include <linux/slab.h> +#include <linux/stat.h>  #include <linux/string.h>  #include <rdma/ib_mad.h> @@ -178,7 +179,7 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,  {  	struct ib_port_attr attr;  	char *speed = ""; -	int rate; +	int rate;		/* in deci-Gb/sec */  	ssize_t ret;  	ret = ib_query_port(p->ibdev, p->port_num, &attr); @@ -186,11 +187,33 @@ static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused,  		return ret;  	switch (attr.active_speed) { -	case 2: speed = " DDR"; break; -	case 4: speed = " QDR"; break; +	case IB_SPEED_DDR: +		speed = " DDR"; +		rate = 50; +		break; +	case IB_SPEED_QDR: +		speed = " QDR"; +		rate = 100; +		break; +	case IB_SPEED_FDR10: +		speed = " FDR10"; +		rate = 100; +		break; +	case IB_SPEED_FDR: +		speed = " FDR"; +		rate = 140; +		break; +	case IB_SPEED_EDR: +		speed = " EDR"; +		rate = 250; +		break; +	case IB_SPEED_SDR: +	default:		/* default to SDR for invalid rates */ +		rate = 25; +		break;  	} -	rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed; +	rate *= ib_width_enum_to_int(attr.active_width);  	if (rate < 0)  		return -EINVAL; @@ -406,15 +429,19 @@ static void ib_port_release(struct kobject *kobj)  	struct attribute *a;  	int i; -	for (i = 0; (a = p->gid_group.attrs[i]); ++i) -		kfree(a); +	if (p->gid_group.attrs) { +		for (i = 0; (a = p->gid_group.attrs[i]); ++i) +			kfree(a); -	kfree(p->gid_group.attrs); +		kfree(p->gid_group.attrs); +	} -	for (i = 0; (a = p->pkey_group.attrs[i]); ++i) -		kfree(a); +	if (p->pkey_group.attrs) { +		for (i = 0; (a = p->pkey_group.attrs[i]); ++i) +			kfree(a); -	kfree(p->pkey_group.attrs); +		kfree(p->pkey_group.attrs); +	}  	kfree(p);  } @@ -511,10 +538,12 @@ static int add_port(struct ib_device *device, int port_num,  	p->port_num   = port_num;  	ret = kobject_init_and_add(&p->kobj, &port_type, -				   kobject_get(device->ports_parent), +				   device->ports_parent,  				   "%d", port_num); -	if (ret) -		goto err_put; +	if (ret) { +		kfree(p); +		return ret; +	}  	ret = sysfs_create_group(&p->kobj, &pma_group);  	if (ret) @@ -522,8 +551,10 @@ static int add_port(struct ib_device *device, int port_num,  	p->gid_group.name  = "gids";  	p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len); -	if (!p->gid_group.attrs) +	if (!p->gid_group.attrs) { +		ret = -ENOMEM;  		goto err_remove_pma; +	}  	ret = sysfs_create_group(&p->kobj, &p->gid_group);  	if (ret) @@ -532,8 +563,10 @@ static int add_port(struct ib_device *device, int port_num,  	p->pkey_group.name  = "pkeys";  	p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,  						attr.pkey_tbl_len); -	if (!p->pkey_group.attrs) +	if (!p->pkey_group.attrs) { +		ret = -ENOMEM;  		goto err_remove_gid; +	}  	ret = sysfs_create_group(&p->kobj, &p->pkey_group);  	if (ret) @@ -558,6 +591,7 @@ err_free_pkey:  		kfree(p->pkey_group.attrs[i]);  	kfree(p->pkey_group.attrs); +	p->pkey_group.attrs = NULL;  err_remove_gid:  	sysfs_remove_group(&p->kobj, &p->gid_group); @@ -567,13 +601,13 @@ err_free_gid:  		kfree(p->gid_group.attrs[i]);  	kfree(p->gid_group.attrs); +	p->gid_group.attrs = NULL;  err_remove_pma:  	sysfs_remove_group(&p->kobj, &pma_group);  err_put: -	kobject_put(device->ports_parent); -	kfree(p); +	kobject_put(&p->kobj);  	return ret;  } @@ -585,6 +619,8 @@ static ssize_t show_node_type(struct device *device,  	switch (dev->node_type) {  	case RDMA_NODE_IB_CA:	  return sprintf(buf, "%d: CA\n", dev->node_type);  	case RDMA_NODE_RNIC:	  return sprintf(buf, "%d: RNIC\n", dev->node_type); +	case RDMA_NODE_USNIC:	  return sprintf(buf, "%d: usNIC\n", dev->node_type); +	case RDMA_NODE_USNIC_UDP: return sprintf(buf, "%d: usNIC UDP\n", dev->node_type);  	case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type);  	case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type);  	default:		  return sprintf(buf, "%d: <unknown>\n", dev->node_type); @@ -780,6 +816,22 @@ static struct attribute_group iw_stats_group = {  	.attrs	= iw_proto_stats_attrs,  }; +static void free_port_list_attributes(struct ib_device *device) +{ +	struct kobject *p, *t; + +	list_for_each_entry_safe(p, t, &device->port_list, entry) { +		struct ib_port *port = container_of(p, struct ib_port, kobj); +		list_del(&p->entry); +		sysfs_remove_group(p, &pma_group); +		sysfs_remove_group(p, &port->pkey_group); +		sysfs_remove_group(p, &port->gid_group); +		kobject_put(p); +	} + +	kobject_put(device->ports_parent); +} +  int ib_device_register_sysfs(struct ib_device *device,  			     int (*port_callback)(struct ib_device *,  						  u8, struct kobject *)) @@ -790,7 +842,7 @@ int ib_device_register_sysfs(struct ib_device *device,  	class_dev->class      = &ib_class;  	class_dev->parent     = device->dma_device; -	dev_set_name(class_dev, device->name); +	dev_set_name(class_dev, "%s", device->name);  	dev_set_drvdata(class_dev, device);  	INIT_LIST_HEAD(&device->port_list); @@ -806,7 +858,7 @@ int ib_device_register_sysfs(struct ib_device *device,  	}  	device->ports_parent = kobject_create_and_add("ports", -					kobject_get(&class_dev->kobj)); +						      &class_dev->kobj);  	if (!device->ports_parent) {  		ret = -ENOMEM;  		goto err_put; @@ -833,21 +885,7 @@ int ib_device_register_sysfs(struct ib_device *device,  	return 0;  err_put: -	{ -		struct kobject *p, *t; -		struct ib_port *port; - -		list_for_each_entry_safe(p, t, &device->port_list, entry) { -			list_del(&p->entry); -			port = container_of(p, struct ib_port, kobj); -			sysfs_remove_group(p, &pma_group); -			sysfs_remove_group(p, &port->pkey_group); -			sysfs_remove_group(p, &port->gid_group); -			kobject_put(p); -		} -	} - -	kobject_put(&class_dev->kobj); +	free_port_list_attributes(device);  err_unregister:  	device_unregister(class_dev); @@ -858,22 +896,18 @@ err:  void ib_device_unregister_sysfs(struct ib_device *device)  { -	struct kobject *p, *t; -	struct ib_port *port; -  	/* Hold kobject until ib_dealloc_device() */ -	kobject_get(&device->dev.kobj); +	struct kobject *kobj_dev = kobject_get(&device->dev.kobj); +	int i; -	list_for_each_entry_safe(p, t, &device->port_list, entry) { -		list_del(&p->entry); -		port = container_of(p, struct ib_port, kobj); -		sysfs_remove_group(p, &pma_group); -		sysfs_remove_group(p, &port->pkey_group); -		sysfs_remove_group(p, &port->gid_group); -		kobject_put(p); -	} +	if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats) +		sysfs_remove_group(kobj_dev, &iw_stats_group); + +	free_port_list_attributes(device); + +	for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) +		device_remove_file(&device->dev, ib_class_attributes[i]); -	kobject_put(device->ports_parent);  	device_unregister(&device->dev);  }  | 
