brintos

brintos / linux-shallow public Read only

0
0
Text · 39.8 KiB · 9f97bef Raw
1485 lines · c
1/*2 * Copyright (c) 2004, 2005 Topspin Communications.  All rights reserved.3 * Copyright (c) 2005 Mellanox Technologies Ltd.  All rights reserved.4 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.5 *6 * This software is available to you under a choice of one of two7 * licenses.  You may choose to be licensed under the terms of the GNU8 * General Public License (GPL) Version 2, available from the file9 * COPYING in the main directory of this source tree, or the10 * OpenIB.org BSD license below:11 *12 *     Redistribution and use in source and binary forms, with or13 *     without modification, are permitted provided that the following14 *     conditions are met:15 *16 *      - Redistributions of source code must retain the above17 *        copyright notice, this list of conditions and the following18 *        disclaimer.19 *20 *      - Redistributions in binary form must reproduce the above21 *        copyright notice, this list of conditions and the following22 *        disclaimer in the documentation and/or other materials23 *        provided with the distribution.24 *25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE32 * SOFTWARE.33 */34 35#include "core_priv.h"36 37#include <linux/slab.h>38#include <linux/stat.h>39#include <linux/string.h>40#include <linux/netdevice.h>41#include <linux/ethtool.h>42 43#include <rdma/ib_mad.h>44#include <rdma/ib_pma.h>45#include <rdma/ib_cache.h>46#include <rdma/rdma_counter.h>47#include <rdma/ib_sysfs.h>48 49struct port_table_attribute {50	struct ib_port_attribute attr;51	char			name[8];52	int			index;53	__be16			attr_id;54};55 56struct gid_attr_group {57	struct ib_port *port;58	struct kobject kobj;59	struct attribute_group groups[2];60	const struct attribute_group *groups_list[3];61	struct port_table_attribute attrs_list[];62};63 64struct ib_port {65	struct kobject kobj;66	struct ib_device *ibdev;67	struct gid_attr_group *gid_attr_group;68	struct hw_stats_port_data *hw_stats_data;69 70	struct attribute_group groups[3];71	const struct attribute_group *groups_list[5];72	u32 port_num;73	struct port_table_attribute attrs_list[];74};75 76struct hw_stats_device_attribute {77	struct device_attribute attr;78	ssize_t (*show)(struct ib_device *ibdev, struct rdma_hw_stats *stats,79			unsigned int index, unsigned int port_num, char *buf);80	ssize_t (*store)(struct ib_device *ibdev, struct rdma_hw_stats *stats,81			 unsigned int index, unsigned int port_num,82			 const char *buf, size_t count);83};84 85struct hw_stats_port_attribute {86	struct ib_port_attribute attr;87	ssize_t (*show)(struct ib_device *ibdev, struct rdma_hw_stats *stats,88			unsigned int index, unsigned int port_num, char *buf);89	ssize_t (*store)(struct ib_device *ibdev, struct rdma_hw_stats *stats,90			 unsigned int index, unsigned int port_num,91			 const char *buf, size_t count);92};93 94struct hw_stats_device_data {95	struct attribute_group group;96	struct rdma_hw_stats *stats;97	struct hw_stats_device_attribute attrs[];98};99 100struct hw_stats_port_data {101	struct rdma_hw_stats *stats;102	struct hw_stats_port_attribute attrs[];103};104 105static ssize_t port_attr_show(struct kobject *kobj,106			      struct attribute *attr, char *buf)107{108	struct ib_port_attribute *port_attr =109		container_of(attr, struct ib_port_attribute, attr);110	struct ib_port *p = container_of(kobj, struct ib_port, kobj);111 112	if (!port_attr->show)113		return -EIO;114 115	return port_attr->show(p->ibdev, p->port_num, port_attr, buf);116}117 118static ssize_t port_attr_store(struct kobject *kobj,119			       struct attribute *attr,120			       const char *buf, size_t count)121{122	struct ib_port_attribute *port_attr =123		container_of(attr, struct ib_port_attribute, attr);124	struct ib_port *p = container_of(kobj, struct ib_port, kobj);125 126	if (!port_attr->store)127		return -EIO;128	return port_attr->store(p->ibdev, p->port_num, port_attr, buf, count);129}130 131struct ib_device *ib_port_sysfs_get_ibdev_kobj(struct kobject *kobj,132					       u32 *port_num)133{134	struct ib_port *port = container_of(kobj, struct ib_port, kobj);135 136	*port_num = port->port_num;137	return port->ibdev;138}139EXPORT_SYMBOL(ib_port_sysfs_get_ibdev_kobj);140 141static const struct sysfs_ops port_sysfs_ops = {142	.show	= port_attr_show,143	.store	= port_attr_store144};145 146static ssize_t hw_stat_device_show(struct device *dev,147				   struct device_attribute *attr, char *buf)148{149	struct hw_stats_device_attribute *stat_attr =150		container_of(attr, struct hw_stats_device_attribute, attr);151	struct ib_device *ibdev = container_of(dev, struct ib_device, dev);152 153	return stat_attr->show(ibdev, ibdev->hw_stats_data->stats,154			       stat_attr - ibdev->hw_stats_data->attrs, 0, buf);155}156 157static ssize_t hw_stat_device_store(struct device *dev,158				    struct device_attribute *attr,159				    const char *buf, size_t count)160{161	struct hw_stats_device_attribute *stat_attr =162		container_of(attr, struct hw_stats_device_attribute, attr);163	struct ib_device *ibdev = container_of(dev, struct ib_device, dev);164 165	return stat_attr->store(ibdev, ibdev->hw_stats_data->stats,166				stat_attr - ibdev->hw_stats_data->attrs, 0, buf,167				count);168}169 170static ssize_t hw_stat_port_show(struct ib_device *ibdev, u32 port_num,171				 struct ib_port_attribute *attr, char *buf)172{173	struct hw_stats_port_attribute *stat_attr =174		container_of(attr, struct hw_stats_port_attribute, attr);175	struct ib_port *port = ibdev->port_data[port_num].sysfs;176 177	return stat_attr->show(ibdev, port->hw_stats_data->stats,178			       stat_attr - port->hw_stats_data->attrs,179			       port->port_num, buf);180}181 182static ssize_t hw_stat_port_store(struct ib_device *ibdev, u32 port_num,183				  struct ib_port_attribute *attr,184				  const char *buf, size_t count)185{186	struct hw_stats_port_attribute *stat_attr =187		container_of(attr, struct hw_stats_port_attribute, attr);188	struct ib_port *port = ibdev->port_data[port_num].sysfs;189 190	return stat_attr->store(ibdev, port->hw_stats_data->stats,191				stat_attr - port->hw_stats_data->attrs,192				port->port_num, buf, count);193}194 195static ssize_t gid_attr_show(struct kobject *kobj,196			     struct attribute *attr, char *buf)197{198	struct ib_port_attribute *port_attr =199		container_of(attr, struct ib_port_attribute, attr);200	struct ib_port *p = container_of(kobj, struct gid_attr_group,201					 kobj)->port;202 203	if (!port_attr->show)204		return -EIO;205 206	return port_attr->show(p->ibdev, p->port_num, port_attr, buf);207}208 209static const struct sysfs_ops gid_attr_sysfs_ops = {210	.show = gid_attr_show211};212 213static ssize_t state_show(struct ib_device *ibdev, u32 port_num,214			  struct ib_port_attribute *unused, char *buf)215{216	struct ib_port_attr attr;217	ssize_t ret;218 219	static const char *state_name[] = {220		[IB_PORT_NOP]		= "NOP",221		[IB_PORT_DOWN]		= "DOWN",222		[IB_PORT_INIT]		= "INIT",223		[IB_PORT_ARMED]		= "ARMED",224		[IB_PORT_ACTIVE]	= "ACTIVE",225		[IB_PORT_ACTIVE_DEFER]	= "ACTIVE_DEFER"226	};227 228	ret = ib_query_port(ibdev, port_num, &attr);229	if (ret)230		return ret;231 232	return sysfs_emit(buf, "%d: %s\n", attr.state,233			  attr.state >= 0 &&234					  attr.state < ARRAY_SIZE(state_name) ?235				  state_name[attr.state] :236				  "UNKNOWN");237}238 239static ssize_t lid_show(struct ib_device *ibdev, u32 port_num,240			struct ib_port_attribute *unused, char *buf)241{242	struct ib_port_attr attr;243	ssize_t ret;244 245	ret = ib_query_port(ibdev, port_num, &attr);246	if (ret)247		return ret;248 249	return sysfs_emit(buf, "0x%x\n", attr.lid);250}251 252static ssize_t lid_mask_count_show(struct ib_device *ibdev, u32 port_num,253				   struct ib_port_attribute *unused, char *buf)254{255	struct ib_port_attr attr;256	ssize_t ret;257 258	ret = ib_query_port(ibdev, port_num, &attr);259	if (ret)260		return ret;261 262	return sysfs_emit(buf, "%u\n", attr.lmc);263}264 265static ssize_t sm_lid_show(struct ib_device *ibdev, u32 port_num,266			   struct ib_port_attribute *unused, char *buf)267{268	struct ib_port_attr attr;269	ssize_t ret;270 271	ret = ib_query_port(ibdev, port_num, &attr);272	if (ret)273		return ret;274 275	return sysfs_emit(buf, "0x%x\n", attr.sm_lid);276}277 278static ssize_t sm_sl_show(struct ib_device *ibdev, u32 port_num,279			  struct ib_port_attribute *unused, char *buf)280{281	struct ib_port_attr attr;282	ssize_t ret;283 284	ret = ib_query_port(ibdev, port_num, &attr);285	if (ret)286		return ret;287 288	return sysfs_emit(buf, "%u\n", attr.sm_sl);289}290 291static ssize_t cap_mask_show(struct ib_device *ibdev, u32 port_num,292			     struct ib_port_attribute *unused, char *buf)293{294	struct ib_port_attr attr;295	ssize_t ret;296 297	ret = ib_query_port(ibdev, port_num, &attr);298	if (ret)299		return ret;300 301	return sysfs_emit(buf, "0x%08x\n", attr.port_cap_flags);302}303 304static ssize_t rate_show(struct ib_device *ibdev, u32 port_num,305			 struct ib_port_attribute *unused, char *buf)306{307	struct ib_port_attr attr;308	char *speed = "";309	int rate;		/* in deci-Gb/sec */310	ssize_t ret;311 312	ret = ib_query_port(ibdev, port_num, &attr);313	if (ret)314		return ret;315 316	switch (attr.active_speed) {317	case IB_SPEED_DDR:318		speed = " DDR";319		rate = 50;320		break;321	case IB_SPEED_QDR:322		speed = " QDR";323		rate = 100;324		break;325	case IB_SPEED_FDR10:326		speed = " FDR10";327		rate = 100;328		break;329	case IB_SPEED_FDR:330		speed = " FDR";331		rate = 140;332		break;333	case IB_SPEED_EDR:334		speed = " EDR";335		rate = 250;336		break;337	case IB_SPEED_HDR:338		speed = " HDR";339		rate = 500;340		break;341	case IB_SPEED_NDR:342		speed = " NDR";343		rate = 1000;344		break;345	case IB_SPEED_XDR:346		speed = " XDR";347		rate = 2000;348		break;349	case IB_SPEED_SDR:350	default:		/* default to SDR for invalid rates */351		speed = " SDR";352		rate = 25;353		break;354	}355 356	rate *= ib_width_enum_to_int(attr.active_width);357	if (rate < 0)358		return -EINVAL;359 360	return sysfs_emit(buf, "%d%s Gb/sec (%dX%s)\n", rate / 10,361			  rate % 10 ? ".5" : "",362			  ib_width_enum_to_int(attr.active_width), speed);363}364 365static const char *phys_state_to_str(enum ib_port_phys_state phys_state)366{367	static const char *phys_state_str[] = {368		"<unknown>",369		"Sleep",370		"Polling",371		"Disabled",372		"PortConfigurationTraining",373		"LinkUp",374		"LinkErrorRecovery",375		"Phy Test",376	};377 378	if (phys_state < ARRAY_SIZE(phys_state_str))379		return phys_state_str[phys_state];380	return "<unknown>";381}382 383static ssize_t phys_state_show(struct ib_device *ibdev, u32 port_num,384			       struct ib_port_attribute *unused, char *buf)385{386	struct ib_port_attr attr;387 388	ssize_t ret;389 390	ret = ib_query_port(ibdev, port_num, &attr);391	if (ret)392		return ret;393 394	return sysfs_emit(buf, "%u: %s\n", attr.phys_state,395			  phys_state_to_str(attr.phys_state));396}397 398static ssize_t link_layer_show(struct ib_device *ibdev, u32 port_num,399			       struct ib_port_attribute *unused, char *buf)400{401	const char *output;402 403	switch (rdma_port_get_link_layer(ibdev, port_num)) {404	case IB_LINK_LAYER_INFINIBAND:405		output = "InfiniBand";406		break;407	case IB_LINK_LAYER_ETHERNET:408		output = "Ethernet";409		break;410	default:411		output = "Unknown";412		break;413	}414 415	return sysfs_emit(buf, "%s\n", output);416}417 418static IB_PORT_ATTR_RO(state);419static IB_PORT_ATTR_RO(lid);420static IB_PORT_ATTR_RO(lid_mask_count);421static IB_PORT_ATTR_RO(sm_lid);422static IB_PORT_ATTR_RO(sm_sl);423static IB_PORT_ATTR_RO(cap_mask);424static IB_PORT_ATTR_RO(rate);425static IB_PORT_ATTR_RO(phys_state);426static IB_PORT_ATTR_RO(link_layer);427 428static struct attribute *port_default_attrs[] = {429	&ib_port_attr_state.attr,430	&ib_port_attr_lid.attr,431	&ib_port_attr_lid_mask_count.attr,432	&ib_port_attr_sm_lid.attr,433	&ib_port_attr_sm_sl.attr,434	&ib_port_attr_cap_mask.attr,435	&ib_port_attr_rate.attr,436	&ib_port_attr_phys_state.attr,437	&ib_port_attr_link_layer.attr,438	NULL439};440ATTRIBUTE_GROUPS(port_default);441 442static ssize_t print_ndev(const struct ib_gid_attr *gid_attr, char *buf)443{444	struct net_device *ndev;445	int ret = -EINVAL;446 447	rcu_read_lock();448	ndev = rcu_dereference(gid_attr->ndev);449	if (ndev)450		ret = sysfs_emit(buf, "%s\n", ndev->name);451	rcu_read_unlock();452	return ret;453}454 455static ssize_t print_gid_type(const struct ib_gid_attr *gid_attr, char *buf)456{457	return sysfs_emit(buf, "%s\n",458			  ib_cache_gid_type_str(gid_attr->gid_type));459}460 461static ssize_t _show_port_gid_attr(462	struct ib_device *ibdev, u32 port_num, struct ib_port_attribute *attr,463	char *buf,464	ssize_t (*print)(const struct ib_gid_attr *gid_attr, char *buf))465{466	struct port_table_attribute *tab_attr =467		container_of(attr, struct port_table_attribute, attr);468	const struct ib_gid_attr *gid_attr;469	ssize_t ret;470 471	gid_attr = rdma_get_gid_attr(ibdev, port_num, tab_attr->index);472	if (IS_ERR(gid_attr))473		/* -EINVAL is returned for user space compatibility reasons. */474		return -EINVAL;475 476	ret = print(gid_attr, buf);477	rdma_put_gid_attr(gid_attr);478	return ret;479}480 481static ssize_t show_port_gid(struct ib_device *ibdev, u32 port_num,482			     struct ib_port_attribute *attr, char *buf)483{484	struct port_table_attribute *tab_attr =485		container_of(attr, struct port_table_attribute, attr);486	const struct ib_gid_attr *gid_attr;487	int len;488 489	gid_attr = rdma_get_gid_attr(ibdev, port_num, tab_attr->index);490	if (IS_ERR(gid_attr)) {491		const union ib_gid zgid = {};492 493		/* If reading GID fails, it is likely due to GID entry being494		 * empty (invalid) or reserved GID in the table.  User space495		 * expects to read GID table entries as long as it given index496		 * is within GID table size.  Administrative/debugging tool497		 * fails to query rest of the GID entries if it hits error498		 * while querying a GID of the given index.  To avoid user499		 * space throwing such error on fail to read gid, return zero500		 * GID as before. This maintains backward compatibility.501		 */502		return sysfs_emit(buf, "%pI6\n", zgid.raw);503	}504 505	len = sysfs_emit(buf, "%pI6\n", gid_attr->gid.raw);506	rdma_put_gid_attr(gid_attr);507	return len;508}509 510static ssize_t show_port_gid_attr_ndev(struct ib_device *ibdev, u32 port_num,511				       struct ib_port_attribute *attr,512				       char *buf)513{514	return _show_port_gid_attr(ibdev, port_num, attr, buf, print_ndev);515}516 517static ssize_t show_port_gid_attr_gid_type(struct ib_device *ibdev,518					   u32 port_num,519					   struct ib_port_attribute *attr,520					   char *buf)521{522	return _show_port_gid_attr(ibdev, port_num, attr, buf, print_gid_type);523}524 525static ssize_t show_port_pkey(struct ib_device *ibdev, u32 port_num,526			      struct ib_port_attribute *attr, char *buf)527{528	struct port_table_attribute *tab_attr =529		container_of(attr, struct port_table_attribute, attr);530	u16 pkey;531	int ret;532 533	ret = ib_query_pkey(ibdev, port_num, tab_attr->index, &pkey);534	if (ret)535		return ret;536 537	return sysfs_emit(buf, "0x%04x\n", pkey);538}539 540#define PORT_PMA_ATTR(_name, _counter, _width, _offset)			\541struct port_table_attribute port_pma_attr_##_name = {			\542	.attr  = __ATTR(_name, S_IRUGO, show_pma_counter, NULL),	\543	.index = (_offset) | ((_width) << 16) | ((_counter) << 24),	\544	.attr_id = IB_PMA_PORT_COUNTERS,				\545}546 547#define PORT_PMA_ATTR_EXT(_name, _width, _offset)			\548struct port_table_attribute port_pma_attr_ext_##_name = {		\549	.attr  = __ATTR(_name, S_IRUGO, show_pma_counter, NULL),	\550	.index = (_offset) | ((_width) << 16),				\551	.attr_id = IB_PMA_PORT_COUNTERS_EXT,				\552}553 554/*555 * Get a Perfmgmt MAD block of data.556 * Returns error code or the number of bytes retrieved.557 */558static int get_perf_mad(struct ib_device *dev, int port_num, __be16 attr,559		void *data, int offset, size_t size)560{561	struct ib_mad *in_mad;562	struct ib_mad *out_mad;563	size_t mad_size = sizeof(*out_mad);564	u16 out_mad_pkey_index = 0;565	ssize_t ret;566 567	if (!dev->ops.process_mad)568		return -ENOSYS;569 570	in_mad = kzalloc(sizeof(*in_mad), GFP_KERNEL);571	out_mad = kzalloc(sizeof(*out_mad), GFP_KERNEL);572	if (!in_mad || !out_mad) {573		ret = -ENOMEM;574		goto out;575	}576 577	in_mad->mad_hdr.base_version  = 1;578	in_mad->mad_hdr.mgmt_class    = IB_MGMT_CLASS_PERF_MGMT;579	in_mad->mad_hdr.class_version = 1;580	in_mad->mad_hdr.method        = IB_MGMT_METHOD_GET;581	in_mad->mad_hdr.attr_id       = attr;582 583	if (attr != IB_PMA_CLASS_PORT_INFO)584		in_mad->data[41] = port_num;	/* PortSelect field */585 586	if ((dev->ops.process_mad(dev, IB_MAD_IGNORE_MKEY, port_num, NULL, NULL,587				  in_mad, out_mad, &mad_size,588				  &out_mad_pkey_index) &589	     (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) !=590	    (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) {591		ret = -EINVAL;592		goto out;593	}594	memcpy(data, out_mad->data + offset, size);595	ret = size;596out:597	kfree(in_mad);598	kfree(out_mad);599	return ret;600}601 602static ssize_t show_pma_counter(struct ib_device *ibdev, u32 port_num,603				struct ib_port_attribute *attr, char *buf)604{605	struct port_table_attribute *tab_attr =606		container_of(attr, struct port_table_attribute, attr);607	int offset = tab_attr->index & 0xffff;608	int width  = (tab_attr->index >> 16) & 0xff;609	int ret;610	u8 data[8];611	int len;612 613	ret = get_perf_mad(ibdev, port_num, tab_attr->attr_id, &data,614			40 + offset / 8, sizeof(data));615	if (ret < 0)616		return ret;617 618	switch (width) {619	case 4:620		len = sysfs_emit(buf, "%d\n",621				 (*data >> (4 - (offset % 8))) & 0xf);622		break;623	case 8:624		len = sysfs_emit(buf, "%u\n", *data);625		break;626	case 16:627		len = sysfs_emit(buf, "%u\n", be16_to_cpup((__be16 *)data));628		break;629	case 32:630		len = sysfs_emit(buf, "%u\n", be32_to_cpup((__be32 *)data));631		break;632	case 64:633		len = sysfs_emit(buf, "%llu\n", be64_to_cpup((__be64 *)data));634		break;635	default:636		len = 0;637		break;638	}639 640	return len;641}642 643static PORT_PMA_ATTR(symbol_error		    ,  0, 16,  32);644static PORT_PMA_ATTR(link_error_recovery	    ,  1,  8,  48);645static PORT_PMA_ATTR(link_downed		    ,  2,  8,  56);646static PORT_PMA_ATTR(port_rcv_errors		    ,  3, 16,  64);647static PORT_PMA_ATTR(port_rcv_remote_physical_errors,  4, 16,  80);648static PORT_PMA_ATTR(port_rcv_switch_relay_errors   ,  5, 16,  96);649static PORT_PMA_ATTR(port_xmit_discards		    ,  6, 16, 112);650static PORT_PMA_ATTR(port_xmit_constraint_errors    ,  7,  8, 128);651static PORT_PMA_ATTR(port_rcv_constraint_errors	    ,  8,  8, 136);652static PORT_PMA_ATTR(local_link_integrity_errors    ,  9,  4, 152);653static PORT_PMA_ATTR(excessive_buffer_overrun_errors, 10,  4, 156);654static PORT_PMA_ATTR(VL15_dropped		    , 11, 16, 176);655static PORT_PMA_ATTR(port_xmit_data		    , 12, 32, 192);656static PORT_PMA_ATTR(port_rcv_data		    , 13, 32, 224);657static PORT_PMA_ATTR(port_xmit_packets		    , 14, 32, 256);658static PORT_PMA_ATTR(port_rcv_packets		    , 15, 32, 288);659static PORT_PMA_ATTR(port_xmit_wait		    ,  0, 32, 320);660 661/*662 * Counters added by extended set663 */664static PORT_PMA_ATTR_EXT(port_xmit_data		    , 64,  64);665static PORT_PMA_ATTR_EXT(port_rcv_data		    , 64, 128);666static PORT_PMA_ATTR_EXT(port_xmit_packets	    , 64, 192);667static PORT_PMA_ATTR_EXT(port_rcv_packets	    , 64, 256);668static PORT_PMA_ATTR_EXT(unicast_xmit_packets	    , 64, 320);669static PORT_PMA_ATTR_EXT(unicast_rcv_packets	    , 64, 384);670static PORT_PMA_ATTR_EXT(multicast_xmit_packets	    , 64, 448);671static PORT_PMA_ATTR_EXT(multicast_rcv_packets	    , 64, 512);672 673static struct attribute *pma_attrs[] = {674	&port_pma_attr_symbol_error.attr.attr,675	&port_pma_attr_link_error_recovery.attr.attr,676	&port_pma_attr_link_downed.attr.attr,677	&port_pma_attr_port_rcv_errors.attr.attr,678	&port_pma_attr_port_rcv_remote_physical_errors.attr.attr,679	&port_pma_attr_port_rcv_switch_relay_errors.attr.attr,680	&port_pma_attr_port_xmit_discards.attr.attr,681	&port_pma_attr_port_xmit_constraint_errors.attr.attr,682	&port_pma_attr_port_rcv_constraint_errors.attr.attr,683	&port_pma_attr_local_link_integrity_errors.attr.attr,684	&port_pma_attr_excessive_buffer_overrun_errors.attr.attr,685	&port_pma_attr_VL15_dropped.attr.attr,686	&port_pma_attr_port_xmit_data.attr.attr,687	&port_pma_attr_port_rcv_data.attr.attr,688	&port_pma_attr_port_xmit_packets.attr.attr,689	&port_pma_attr_port_rcv_packets.attr.attr,690	&port_pma_attr_port_xmit_wait.attr.attr,691	NULL692};693 694static struct attribute *pma_attrs_ext[] = {695	&port_pma_attr_symbol_error.attr.attr,696	&port_pma_attr_link_error_recovery.attr.attr,697	&port_pma_attr_link_downed.attr.attr,698	&port_pma_attr_port_rcv_errors.attr.attr,699	&port_pma_attr_port_rcv_remote_physical_errors.attr.attr,700	&port_pma_attr_port_rcv_switch_relay_errors.attr.attr,701	&port_pma_attr_port_xmit_discards.attr.attr,702	&port_pma_attr_port_xmit_constraint_errors.attr.attr,703	&port_pma_attr_port_rcv_constraint_errors.attr.attr,704	&port_pma_attr_local_link_integrity_errors.attr.attr,705	&port_pma_attr_excessive_buffer_overrun_errors.attr.attr,706	&port_pma_attr_VL15_dropped.attr.attr,707	&port_pma_attr_ext_port_xmit_data.attr.attr,708	&port_pma_attr_ext_port_rcv_data.attr.attr,709	&port_pma_attr_ext_port_xmit_packets.attr.attr,710	&port_pma_attr_port_xmit_wait.attr.attr,711	&port_pma_attr_ext_port_rcv_packets.attr.attr,712	&port_pma_attr_ext_unicast_rcv_packets.attr.attr,713	&port_pma_attr_ext_unicast_xmit_packets.attr.attr,714	&port_pma_attr_ext_multicast_rcv_packets.attr.attr,715	&port_pma_attr_ext_multicast_xmit_packets.attr.attr,716	NULL717};718 719static struct attribute *pma_attrs_noietf[] = {720	&port_pma_attr_symbol_error.attr.attr,721	&port_pma_attr_link_error_recovery.attr.attr,722	&port_pma_attr_link_downed.attr.attr,723	&port_pma_attr_port_rcv_errors.attr.attr,724	&port_pma_attr_port_rcv_remote_physical_errors.attr.attr,725	&port_pma_attr_port_rcv_switch_relay_errors.attr.attr,726	&port_pma_attr_port_xmit_discards.attr.attr,727	&port_pma_attr_port_xmit_constraint_errors.attr.attr,728	&port_pma_attr_port_rcv_constraint_errors.attr.attr,729	&port_pma_attr_local_link_integrity_errors.attr.attr,730	&port_pma_attr_excessive_buffer_overrun_errors.attr.attr,731	&port_pma_attr_VL15_dropped.attr.attr,732	&port_pma_attr_ext_port_xmit_data.attr.attr,733	&port_pma_attr_ext_port_rcv_data.attr.attr,734	&port_pma_attr_ext_port_xmit_packets.attr.attr,735	&port_pma_attr_ext_port_rcv_packets.attr.attr,736	&port_pma_attr_port_xmit_wait.attr.attr,737	NULL738};739 740static const struct attribute_group pma_group = {741	.name  = "counters",742	.attrs  = pma_attrs743};744 745static const struct attribute_group pma_group_ext = {746	.name  = "counters",747	.attrs  = pma_attrs_ext748};749 750static const struct attribute_group pma_group_noietf = {751	.name  = "counters",752	.attrs  = pma_attrs_noietf753};754 755static void ib_port_release(struct kobject *kobj)756{757	struct ib_port *port = container_of(kobj, struct ib_port, kobj);758	int i;759 760	for (i = 0; i != ARRAY_SIZE(port->groups); i++)761		kfree(port->groups[i].attrs);762	if (port->hw_stats_data)763		rdma_free_hw_stats_struct(port->hw_stats_data->stats);764	kfree(port->hw_stats_data);765	kvfree(port);766}767 768static void ib_port_gid_attr_release(struct kobject *kobj)769{770	struct gid_attr_group *gid_attr_group =771		container_of(kobj, struct gid_attr_group, kobj);772	int i;773 774	for (i = 0; i != ARRAY_SIZE(gid_attr_group->groups); i++)775		kfree(gid_attr_group->groups[i].attrs);776	kfree(gid_attr_group);777}778 779static struct kobj_type port_type = {780	.release       = ib_port_release,781	.sysfs_ops     = &port_sysfs_ops,782	.default_groups = port_default_groups,783};784 785static struct kobj_type gid_attr_type = {786	.sysfs_ops      = &gid_attr_sysfs_ops,787	.release        = ib_port_gid_attr_release788};789 790/*791 * Figure out which counter table to use depending on792 * the device capabilities.793 */794static const struct attribute_group *get_counter_table(struct ib_device *dev,795						       int port_num)796{797	struct ib_class_port_info cpi;798 799	if (get_perf_mad(dev, port_num, IB_PMA_CLASS_PORT_INFO,800				&cpi, 40, sizeof(cpi)) >= 0) {801		if (cpi.capability_mask & IB_PMA_CLASS_CAP_EXT_WIDTH)802			/* We have extended counters */803			return &pma_group_ext;804 805		if (cpi.capability_mask & IB_PMA_CLASS_CAP_EXT_WIDTH_NOIETF)806			/* But not the IETF ones */807			return &pma_group_noietf;808	}809 810	/* Fall back to normal counters */811	return &pma_group;812}813 814static int update_hw_stats(struct ib_device *dev, struct rdma_hw_stats *stats,815			   u32 port_num, int index)816{817	int ret;818 819	if (time_is_after_eq_jiffies(stats->timestamp + stats->lifespan))820		return 0;821	ret = dev->ops.get_hw_stats(dev, stats, port_num, index);822	if (ret < 0)823		return ret;824	if (ret == stats->num_counters)825		stats->timestamp = jiffies;826 827	return 0;828}829 830static int print_hw_stat(struct ib_device *dev, int port_num,831			 struct rdma_hw_stats *stats, int index, char *buf)832{833	u64 v = rdma_counter_get_hwstat_value(dev, port_num, index);834 835	return sysfs_emit(buf, "%llu\n", stats->value[index] + v);836}837 838static ssize_t show_hw_stats(struct ib_device *ibdev,839			     struct rdma_hw_stats *stats, unsigned int index,840			     unsigned int port_num, char *buf)841{842	int ret;843 844	mutex_lock(&stats->lock);845	ret = update_hw_stats(ibdev, stats, port_num, index);846	if (ret)847		goto unlock;848	ret = print_hw_stat(ibdev, port_num, stats, index, buf);849unlock:850	mutex_unlock(&stats->lock);851 852	return ret;853}854 855static ssize_t show_stats_lifespan(struct ib_device *ibdev,856				   struct rdma_hw_stats *stats,857				   unsigned int index, unsigned int port_num,858				   char *buf)859{860	int msecs;861 862	mutex_lock(&stats->lock);863	msecs = jiffies_to_msecs(stats->lifespan);864	mutex_unlock(&stats->lock);865 866	return sysfs_emit(buf, "%d\n", msecs);867}868 869static ssize_t set_stats_lifespan(struct ib_device *ibdev,870				   struct rdma_hw_stats *stats,871				   unsigned int index, unsigned int port_num,872				   const char *buf, size_t count)873{874	int msecs;875	int jiffies;876	int ret;877 878	ret = kstrtoint(buf, 10, &msecs);879	if (ret)880		return ret;881	if (msecs < 0 || msecs > 10000)882		return -EINVAL;883	jiffies = msecs_to_jiffies(msecs);884 885	mutex_lock(&stats->lock);886	stats->lifespan = jiffies;887	mutex_unlock(&stats->lock);888 889	return count;890}891 892static struct hw_stats_device_data *893alloc_hw_stats_device(struct ib_device *ibdev)894{895	struct hw_stats_device_data *data;896	struct rdma_hw_stats *stats;897 898	if (!ibdev->ops.alloc_hw_device_stats)899		return ERR_PTR(-EOPNOTSUPP);900	stats = ibdev->ops.alloc_hw_device_stats(ibdev);901	if (!stats)902		return ERR_PTR(-ENOMEM);903	if (!stats->descs || stats->num_counters <= 0)904		goto err_free_stats;905 906	/*907	 * Two extra attribue elements here, one for the lifespan entry and908	 * one to NULL terminate the list for the sysfs core code909	 */910	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),911		       GFP_KERNEL);912	if (!data)913		goto err_free_stats;914	data->group.attrs = kcalloc(stats->num_counters + 2,915				    sizeof(*data->group.attrs), GFP_KERNEL);916	if (!data->group.attrs)917		goto err_free_data;918 919	data->group.name = "hw_counters";920	data->stats = stats;921	return data;922 923err_free_data:924	kfree(data);925err_free_stats:926	rdma_free_hw_stats_struct(stats);927	return ERR_PTR(-ENOMEM);928}929 930void ib_device_release_hw_stats(struct hw_stats_device_data *data)931{932	kfree(data->group.attrs);933	rdma_free_hw_stats_struct(data->stats);934	kfree(data);935}936 937int ib_setup_device_attrs(struct ib_device *ibdev)938{939	struct hw_stats_device_attribute *attr;940	struct hw_stats_device_data *data;941	bool opstat_skipped = false;942	int i, ret, pos = 0;943 944	data = alloc_hw_stats_device(ibdev);945	if (IS_ERR(data)) {946		if (PTR_ERR(data) == -EOPNOTSUPP)947			return 0;948		return PTR_ERR(data);949	}950	ibdev->hw_stats_data = data;951 952	ret = ibdev->ops.get_hw_stats(ibdev, data->stats, 0,953				      data->stats->num_counters);954	if (ret != data->stats->num_counters) {955		if (WARN_ON(ret >= 0))956			return -EINVAL;957		return ret;958	}959 960	data->stats->timestamp = jiffies;961 962	for (i = 0; i < data->stats->num_counters; i++) {963		if (data->stats->descs[i].flags & IB_STAT_FLAG_OPTIONAL) {964			opstat_skipped = true;965			continue;966		}967 968		WARN_ON(opstat_skipped);969		attr = &data->attrs[pos];970		sysfs_attr_init(&attr->attr.attr);971		attr->attr.attr.name = data->stats->descs[i].name;972		attr->attr.attr.mode = 0444;973		attr->attr.show = hw_stat_device_show;974		attr->show = show_hw_stats;975		data->group.attrs[pos] = &attr->attr.attr;976		pos++;977	}978 979	attr = &data->attrs[pos];980	sysfs_attr_init(&attr->attr.attr);981	attr->attr.attr.name = "lifespan";982	attr->attr.attr.mode = 0644;983	attr->attr.show = hw_stat_device_show;984	attr->show = show_stats_lifespan;985	attr->attr.store = hw_stat_device_store;986	attr->store = set_stats_lifespan;987	data->group.attrs[pos] = &attr->attr.attr;988	for (i = 0; i != ARRAY_SIZE(ibdev->groups); i++)989		if (!ibdev->groups[i]) {990			ibdev->groups[i] = &data->group;991			return 0;992		}993	WARN(true, "struct ib_device->groups is too small");994	return -EINVAL;995}996 997static struct hw_stats_port_data *998alloc_hw_stats_port(struct ib_port *port, struct attribute_group *group)999{1000	struct ib_device *ibdev = port->ibdev;1001	struct hw_stats_port_data *data;1002	struct rdma_hw_stats *stats;1003 1004	if (!ibdev->ops.alloc_hw_port_stats)1005		return ERR_PTR(-EOPNOTSUPP);1006	stats = ibdev->ops.alloc_hw_port_stats(port->ibdev, port->port_num);1007	if (!stats)1008		return ERR_PTR(-ENOMEM);1009	if (!stats->descs || stats->num_counters <= 0)1010		goto err_free_stats;1011 1012	/*1013	 * Two extra attribue elements here, one for the lifespan entry and1014	 * one to NULL terminate the list for the sysfs core code1015	 */1016	data = kzalloc(struct_size(data, attrs, size_add(stats->num_counters, 1)),1017		       GFP_KERNEL);1018	if (!data)1019		goto err_free_stats;1020	group->attrs = kcalloc(stats->num_counters + 2,1021				    sizeof(*group->attrs), GFP_KERNEL);1022	if (!group->attrs)1023		goto err_free_data;1024 1025	group->name = "hw_counters";1026	data->stats = stats;1027	return data;1028 1029err_free_data:1030	kfree(data);1031err_free_stats:1032	rdma_free_hw_stats_struct(stats);1033	return ERR_PTR(-ENOMEM);1034}1035 1036static int setup_hw_port_stats(struct ib_port *port,1037			       struct attribute_group *group)1038{1039	struct hw_stats_port_attribute *attr;1040	struct hw_stats_port_data *data;1041	bool opstat_skipped = false;1042	int i, ret, pos = 0;1043 1044	data = alloc_hw_stats_port(port, group);1045	if (IS_ERR(data))1046		return PTR_ERR(data);1047 1048	ret = port->ibdev->ops.get_hw_stats(port->ibdev, data->stats,1049					    port->port_num,1050					    data->stats->num_counters);1051	if (ret != data->stats->num_counters) {1052		if (WARN_ON(ret >= 0))1053			return -EINVAL;1054		return ret;1055	}1056 1057	data->stats->timestamp = jiffies;1058 1059	for (i = 0; i < data->stats->num_counters; i++) {1060		if (data->stats->descs[i].flags & IB_STAT_FLAG_OPTIONAL) {1061			opstat_skipped = true;1062			continue;1063		}1064 1065		WARN_ON(opstat_skipped);1066		attr = &data->attrs[pos];1067		sysfs_attr_init(&attr->attr.attr);1068		attr->attr.attr.name = data->stats->descs[i].name;1069		attr->attr.attr.mode = 0444;1070		attr->attr.show = hw_stat_port_show;1071		attr->show = show_hw_stats;1072		group->attrs[pos] = &attr->attr.attr;1073		pos++;1074	}1075 1076	attr = &data->attrs[pos];1077	sysfs_attr_init(&attr->attr.attr);1078	attr->attr.attr.name = "lifespan";1079	attr->attr.attr.mode = 0644;1080	attr->attr.show = hw_stat_port_show;1081	attr->show = show_stats_lifespan;1082	attr->attr.store = hw_stat_port_store;1083	attr->store = set_stats_lifespan;1084	group->attrs[pos] = &attr->attr.attr;1085 1086	port->hw_stats_data = data;1087	return 0;1088}1089 1090struct rdma_hw_stats *ib_get_hw_stats_port(struct ib_device *ibdev,1091					   u32 port_num)1092{1093	if (!ibdev->port_data || !rdma_is_port_valid(ibdev, port_num) ||1094	    !ibdev->port_data[port_num].sysfs->hw_stats_data)1095		return NULL;1096	return ibdev->port_data[port_num].sysfs->hw_stats_data->stats;1097}1098 1099static int1100alloc_port_table_group(const char *name, struct attribute_group *group,1101		       struct port_table_attribute *attrs, size_t num,1102		       ssize_t (*show)(struct ib_device *ibdev, u32 port_num,1103				       struct ib_port_attribute *, char *buf))1104{1105	struct attribute **attr_list;1106	int i;1107 1108	attr_list = kcalloc(num + 1, sizeof(*attr_list), GFP_KERNEL);1109	if (!attr_list)1110		return -ENOMEM;1111 1112	for (i = 0; i < num; i++) {1113		struct port_table_attribute *element = &attrs[i];1114 1115		if (snprintf(element->name, sizeof(element->name), "%d", i) >=1116		    sizeof(element->name))1117			goto err;1118 1119		sysfs_attr_init(&element->attr.attr);1120		element->attr.attr.name = element->name;1121		element->attr.attr.mode = 0444;1122		element->attr.show = show;1123		element->index = i;1124 1125		attr_list[i] = &element->attr.attr;1126	}1127	group->name = name;1128	group->attrs = attr_list;1129	return 0;1130err:1131	kfree(attr_list);1132	return -EINVAL;1133}1134 1135/*1136 * Create the sysfs:1137 *  ibp0s9/ports/XX/gid_attrs/{ndevs,types}/YYY1138 * YYY is the gid table index in decimal1139 */1140static int setup_gid_attrs(struct ib_port *port,1141			   const struct ib_port_attr *attr)1142{1143	struct gid_attr_group *gid_attr_group;1144	int ret;1145 1146	gid_attr_group = kzalloc(struct_size(gid_attr_group, attrs_list,1147					     size_mul(attr->gid_tbl_len, 2)),1148				 GFP_KERNEL);1149	if (!gid_attr_group)1150		return -ENOMEM;1151	gid_attr_group->port = port;1152	kobject_init(&gid_attr_group->kobj, &gid_attr_type);1153 1154	ret = alloc_port_table_group("ndevs", &gid_attr_group->groups[0],1155				     gid_attr_group->attrs_list,1156				     attr->gid_tbl_len,1157				     show_port_gid_attr_ndev);1158	if (ret)1159		goto err_put;1160	gid_attr_group->groups_list[0] = &gid_attr_group->groups[0];1161 1162	ret = alloc_port_table_group(1163		"types", &gid_attr_group->groups[1],1164		gid_attr_group->attrs_list + attr->gid_tbl_len,1165		attr->gid_tbl_len, show_port_gid_attr_gid_type);1166	if (ret)1167		goto err_put;1168	gid_attr_group->groups_list[1] = &gid_attr_group->groups[1];1169 1170	ret = kobject_add(&gid_attr_group->kobj, &port->kobj, "gid_attrs");1171	if (ret)1172		goto err_put;1173	ret = sysfs_create_groups(&gid_attr_group->kobj,1174				  gid_attr_group->groups_list);1175	if (ret)1176		goto err_del;1177	port->gid_attr_group = gid_attr_group;1178	return 0;1179 1180err_del:1181	kobject_del(&gid_attr_group->kobj);1182err_put:1183	kobject_put(&gid_attr_group->kobj);1184	return ret;1185}1186 1187static void destroy_gid_attrs(struct ib_port *port)1188{1189	struct gid_attr_group *gid_attr_group = port->gid_attr_group;1190 1191	if (!gid_attr_group)1192		return;1193	sysfs_remove_groups(&gid_attr_group->kobj, gid_attr_group->groups_list);1194	kobject_del(&gid_attr_group->kobj);1195	kobject_put(&gid_attr_group->kobj);1196}1197 1198/*1199 * Create the sysfs:1200 *  ibp0s9/ports/XX/{gids,pkeys,counters}/YYY1201 */1202static struct ib_port *setup_port(struct ib_core_device *coredev, int port_num,1203				  const struct ib_port_attr *attr)1204{1205	struct ib_device *device = rdma_device_to_ibdev(&coredev->dev);1206	bool is_full_dev = &device->coredev == coredev;1207	const struct attribute_group **cur_group;1208	struct ib_port *p;1209	int ret;1210 1211	p = kvzalloc(struct_size(p, attrs_list,1212				size_add(attr->gid_tbl_len, attr->pkey_tbl_len)),1213		     GFP_KERNEL);1214	if (!p)1215		return ERR_PTR(-ENOMEM);1216	p->ibdev = device;1217	p->port_num = port_num;1218	kobject_init(&p->kobj, &port_type);1219 1220	if (device->port_data && is_full_dev)1221		device->port_data[port_num].sysfs = p;1222 1223	cur_group = p->groups_list;1224	ret = alloc_port_table_group("gids", &p->groups[0], p->attrs_list,1225				     attr->gid_tbl_len, show_port_gid);1226	if (ret)1227		goto err_put;1228	*cur_group++ = &p->groups[0];1229 1230	if (attr->pkey_tbl_len) {1231		ret = alloc_port_table_group("pkeys", &p->groups[1],1232					     p->attrs_list + attr->gid_tbl_len,1233					     attr->pkey_tbl_len, show_port_pkey);1234		if (ret)1235			goto err_put;1236		*cur_group++ = &p->groups[1];1237	}1238 1239	/*1240	 * If port == 0, it means hw_counters are per device and not per1241	 * port, so holder should be device. Therefore skip per port1242	 * counter initialization.1243	 */1244	if (port_num && is_full_dev) {1245		ret = setup_hw_port_stats(p, &p->groups[2]);1246		if (ret && ret != -EOPNOTSUPP)1247			goto err_put;1248		if (!ret)1249			*cur_group++ = &p->groups[2];1250	}1251 1252	if (device->ops.process_mad && is_full_dev)1253		*cur_group++ = get_counter_table(device, port_num);1254 1255	ret = kobject_add(&p->kobj, coredev->ports_kobj, "%d", port_num);1256	if (ret)1257		goto err_put;1258	ret = sysfs_create_groups(&p->kobj, p->groups_list);1259	if (ret)1260		goto err_del;1261	if (is_full_dev) {1262		ret = sysfs_create_groups(&p->kobj, device->ops.port_groups);1263		if (ret)1264			goto err_groups;1265	}1266 1267	list_add_tail(&p->kobj.entry, &coredev->port_list);1268	return p;1269 1270err_groups:1271	sysfs_remove_groups(&p->kobj, p->groups_list);1272err_del:1273	kobject_del(&p->kobj);1274err_put:1275	if (device->port_data && is_full_dev)1276		device->port_data[port_num].sysfs = NULL;1277	kobject_put(&p->kobj);1278	return ERR_PTR(ret);1279}1280 1281static void destroy_port(struct ib_core_device *coredev, struct ib_port *port)1282{1283	bool is_full_dev = &port->ibdev->coredev == coredev;1284 1285	list_del(&port->kobj.entry);1286	if (is_full_dev)1287		sysfs_remove_groups(&port->kobj, port->ibdev->ops.port_groups);1288 1289	sysfs_remove_groups(&port->kobj, port->groups_list);1290	kobject_del(&port->kobj);1291 1292	if (port->ibdev->port_data &&1293	    port->ibdev->port_data[port->port_num].sysfs == port)1294		port->ibdev->port_data[port->port_num].sysfs = NULL;1295 1296	kobject_put(&port->kobj);1297}1298 1299static const char *node_type_string(int node_type)1300{1301	switch (node_type) {1302	case RDMA_NODE_IB_CA:1303		return "CA";1304	case RDMA_NODE_IB_SWITCH:1305		return "switch";1306	case RDMA_NODE_IB_ROUTER:1307		return "router";1308	case RDMA_NODE_RNIC:1309		return "RNIC";1310	case RDMA_NODE_USNIC:1311		return "usNIC";1312	case RDMA_NODE_USNIC_UDP:1313		return "usNIC UDP";1314	case RDMA_NODE_UNSPECIFIED:1315		return "unspecified";1316	}1317	return "<unknown>";1318}1319 1320static ssize_t node_type_show(struct device *device,1321			      struct device_attribute *attr, char *buf)1322{1323	struct ib_device *dev = rdma_device_to_ibdev(device);1324 1325	return sysfs_emit(buf, "%u: %s\n", dev->node_type,1326			  node_type_string(dev->node_type));1327}1328static DEVICE_ATTR_RO(node_type);1329 1330static ssize_t sys_image_guid_show(struct device *device,1331				   struct device_attribute *dev_attr, char *buf)1332{1333	struct ib_device *dev = rdma_device_to_ibdev(device);1334	__be16 *guid = (__be16 *)&dev->attrs.sys_image_guid;1335 1336	return sysfs_emit(buf, "%04x:%04x:%04x:%04x\n",1337			  be16_to_cpu(guid[0]),1338			  be16_to_cpu(guid[1]),1339			  be16_to_cpu(guid[2]),1340			  be16_to_cpu(guid[3]));1341}1342static DEVICE_ATTR_RO(sys_image_guid);1343 1344static ssize_t node_guid_show(struct device *device,1345			      struct device_attribute *attr, char *buf)1346{1347	struct ib_device *dev = rdma_device_to_ibdev(device);1348	__be16 *node_guid = (__be16 *)&dev->node_guid;1349 1350	return sysfs_emit(buf, "%04x:%04x:%04x:%04x\n",1351			  be16_to_cpu(node_guid[0]),1352			  be16_to_cpu(node_guid[1]),1353			  be16_to_cpu(node_guid[2]),1354			  be16_to_cpu(node_guid[3]));1355}1356static DEVICE_ATTR_RO(node_guid);1357 1358static ssize_t node_desc_show(struct device *device,1359			      struct device_attribute *attr, char *buf)1360{1361	struct ib_device *dev = rdma_device_to_ibdev(device);1362 1363	return sysfs_emit(buf, "%.64s\n", dev->node_desc);1364}1365 1366static ssize_t node_desc_store(struct device *device,1367			       struct device_attribute *attr,1368			       const char *buf, size_t count)1369{1370	struct ib_device *dev = rdma_device_to_ibdev(device);1371	struct ib_device_modify desc = {};1372	int ret;1373 1374	if (!dev->ops.modify_device)1375		return -EOPNOTSUPP;1376 1377	memcpy(desc.node_desc, buf, min_t(int, count, IB_DEVICE_NODE_DESC_MAX));1378	ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc);1379	if (ret)1380		return ret;1381 1382	return count;1383}1384static DEVICE_ATTR_RW(node_desc);1385 1386static ssize_t fw_ver_show(struct device *device, struct device_attribute *attr,1387			   char *buf)1388{1389	struct ib_device *dev = rdma_device_to_ibdev(device);1390	char version[IB_FW_VERSION_NAME_MAX] = {};1391 1392	ib_get_device_fw_str(dev, version);1393 1394	return sysfs_emit(buf, "%s\n", version);1395}1396static DEVICE_ATTR_RO(fw_ver);1397 1398static struct attribute *ib_dev_attrs[] = {1399	&dev_attr_node_type.attr,1400	&dev_attr_node_guid.attr,1401	&dev_attr_sys_image_guid.attr,1402	&dev_attr_fw_ver.attr,1403	&dev_attr_node_desc.attr,1404	NULL,1405};1406 1407const struct attribute_group ib_dev_attr_group = {1408	.attrs = ib_dev_attrs,1409};1410 1411void ib_free_port_attrs(struct ib_core_device *coredev)1412{1413	struct kobject *p, *t;1414 1415	list_for_each_entry_safe(p, t, &coredev->port_list, entry) {1416		struct ib_port *port = container_of(p, struct ib_port, kobj);1417 1418		destroy_gid_attrs(port);1419		destroy_port(coredev, port);1420	}1421 1422	kobject_put(coredev->ports_kobj);1423}1424 1425int ib_setup_port_attrs(struct ib_core_device *coredev)1426{1427	struct ib_device *device = rdma_device_to_ibdev(&coredev->dev);1428	u32 port_num;1429	int ret;1430 1431	coredev->ports_kobj = kobject_create_and_add("ports",1432						     &coredev->dev.kobj);1433	if (!coredev->ports_kobj)1434		return -ENOMEM;1435 1436	rdma_for_each_port (device, port_num) {1437		struct ib_port_attr attr;1438		struct ib_port *port;1439 1440		ret = ib_query_port(device, port_num, &attr);1441		if (ret)1442			goto err_put;1443 1444		port = setup_port(coredev, port_num, &attr);1445		if (IS_ERR(port)) {1446			ret = PTR_ERR(port);1447			goto err_put;1448		}1449 1450		ret = setup_gid_attrs(port, &attr);1451		if (ret)1452			goto err_put;1453	}1454	return 0;1455 1456err_put:1457	ib_free_port_attrs(coredev);1458	return ret;1459}1460 1461/**1462 * ib_port_register_client_groups - Add an ib_client's attributes to the port1463 *1464 * @ibdev: IB device to add counters1465 * @port_num: valid port number1466 * @groups: Group list of attributes1467 *1468 * Do not use. Only for legacy sysfs compatibility.1469 */1470int ib_port_register_client_groups(struct ib_device *ibdev, u32 port_num,1471				   const struct attribute_group **groups)1472{1473	return sysfs_create_groups(&ibdev->port_data[port_num].sysfs->kobj,1474				   groups);1475}1476EXPORT_SYMBOL(ib_port_register_client_groups);1477 1478void ib_port_unregister_client_groups(struct ib_device *ibdev, u32 port_num,1479				      const struct attribute_group **groups)1480{1481	return sysfs_remove_groups(&ibdev->port_data[port_num].sysfs->kobj,1482				   groups);1483}1484EXPORT_SYMBOL(ib_port_unregister_client_groups);1485