brintos

brintos / linux-shallow public Read only

0
0
Text · 23.0 KiB · 88f534c Raw
873 lines · c
1/*2 * Copyright (c) 2012 Mellanox Technologies.  All rights reserved.3 *4 * This software is available to you under a choice of one of two5 * licenses.  You may choose to be licensed under the terms of the GNU6 * General Public License (GPL) Version 2, available from the file7 * COPYING in the main directory of this source tree, or the8 * OpenIB.org BSD license below:9 *10 *     Redistribution and use in source and binary forms, with or11 *     without modification, are permitted provided that the following12 *     conditions are met:13 *14 *      - Redistributions of source code must retain the above15 *        copyright notice, this list of conditions and the following16 *        disclaimer.17 *18 *      - Redistributions in binary form must reproduce the above19 *        copyright notice, this list of conditions and the following20 *        disclaimer in the documentation and/or other materials21 *        provided with the distribution.22 *23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE30 * SOFTWARE.31 */32 33/*#include "core_priv.h"*/34#include "mlx4_ib.h"35#include <linux/slab.h>36#include <linux/string.h>37#include <linux/stat.h>38 39#include <rdma/ib_mad.h>40/*show_admin_alias_guid returns the administratively assigned value of that GUID.41 * Values returned in buf parameter string:42 *	0			- requests opensm to assign a value.43 *	ffffffffffffffff	- delete this entry.44 *	other			- value assigned by administrator.45 */46static ssize_t show_admin_alias_guid(struct device *dev,47			      struct device_attribute *attr, char *buf)48{49	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =50		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);51	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;52	struct mlx4_ib_dev *mdev = port->dev;53	__be64 sysadmin_ag_val;54 55	sysadmin_ag_val = mlx4_get_admin_guid(mdev->dev,56					      mlx4_ib_iov_dentry->entry_num,57					      port->num);58 59	return sysfs_emit(buf, "%llx\n", be64_to_cpu(sysadmin_ag_val));60}61 62/* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.63 * Values in buf parameter string:64 *	0			- requests opensm to assign a value.65 *	0xffffffffffffffff	- delete this entry.66 *	other			- guid value assigned by the administrator.67 */68static ssize_t store_admin_alias_guid(struct device *dev,69				      struct device_attribute *attr,70				      const char *buf, size_t count)71{72	int record_num;/*0-15*/73	int guid_index_in_rec; /*0 - 7*/74	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =75		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);76	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;77	struct mlx4_ib_dev *mdev = port->dev;78	u64 sysadmin_ag_val;79	unsigned long flags;80 81	record_num = mlx4_ib_iov_dentry->entry_num / 8;82	guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;83	if (0 == record_num && 0 == guid_index_in_rec) {84		pr_err("GUID 0 block 0 is RO\n");85		return count;86	}87	spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags);88	sscanf(buf, "%llx", &sysadmin_ag_val);89	*(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].90		all_rec_per_port[record_num].91		all_recs[GUID_REC_SIZE * guid_index_in_rec] =92			cpu_to_be64(sysadmin_ag_val);93 94	/* Change the state to be pending for update */95	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status96		= MLX4_GUID_INFO_STATUS_IDLE ;97	mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val),98			    mlx4_ib_iov_dentry->entry_num,99			    port->num);100 101	/* set the record index */102	mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes103		|= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);104 105	spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags);106	mlx4_ib_init_alias_guid_work(mdev, port->num - 1);107 108	return count;109}110 111static ssize_t show_port_gid(struct device *dev,112			     struct device_attribute *attr,113			     char *buf)114{115	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =116		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);117	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;118	struct mlx4_ib_dev *mdev = port->dev;119	union ib_gid gid;120	int ret;121	__be16 *raw;122 123	ret = __mlx4_ib_query_gid(&mdev->ib_dev, port->num,124				  mlx4_ib_iov_dentry->entry_num, &gid, 1);125	if (ret)126		return ret;127 128	raw = (__be16 *)gid.raw;129	return sysfs_emit(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",130			  be16_to_cpu(raw[0]),131			  be16_to_cpu(raw[1]),132			  be16_to_cpu(raw[2]),133			  be16_to_cpu(raw[3]),134			  be16_to_cpu(raw[4]),135			  be16_to_cpu(raw[5]),136			  be16_to_cpu(raw[6]),137			  be16_to_cpu(raw[7]));138}139 140static ssize_t show_phys_port_pkey(struct device *dev,141				   struct device_attribute *attr,142				   char *buf)143{144	struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =145		container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);146	struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;147	struct mlx4_ib_dev *mdev = port->dev;148	u16 pkey;149	ssize_t ret;150 151	ret = __mlx4_ib_query_pkey(&mdev->ib_dev, port->num,152				   mlx4_ib_iov_dentry->entry_num, &pkey, 1);153	if (ret)154		return ret;155 156	return sysfs_emit(buf, "0x%04x\n", pkey);157}158 159#define DENTRY_REMOVE(_dentry)						\160do {									\161	sysfs_remove_file((_dentry)->kobj, &(_dentry)->dentry.attr);	\162} while (0);163 164static int create_sysfs_entry(void *_ctx, struct mlx4_ib_iov_sysfs_attr *_dentry,165			      char *_name, struct kobject *_kobj,166			      ssize_t (*show)(struct device *dev,167					      struct device_attribute *attr,168					      char *buf),169			      ssize_t (*store)(struct device *dev,170					       struct device_attribute *attr,171					       const char *buf, size_t count)172			      )173{174	int ret = 0;175	struct mlx4_ib_iov_sysfs_attr *vdentry = _dentry;176 177	vdentry->ctx = _ctx;178	vdentry->dentry.show = show;179	vdentry->dentry.store = store;180	sysfs_attr_init(&vdentry->dentry.attr);181	vdentry->dentry.attr.name = vdentry->name;182	vdentry->dentry.attr.mode = 0;183	vdentry->kobj = _kobj;184	snprintf(vdentry->name, 15, "%s", _name);185 186	if (vdentry->dentry.store)187		vdentry->dentry.attr.mode |= S_IWUSR;188 189	if (vdentry->dentry.show)190		vdentry->dentry.attr.mode |= S_IRUGO;191 192	ret = sysfs_create_file(vdentry->kobj, &vdentry->dentry.attr);193	if (ret) {194		pr_err("failed to create %s\n", vdentry->dentry.attr.name);195		vdentry->ctx = NULL;196		return ret;197	}198 199	return ret;200}201 202int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,203		struct attribute *attr)204{205	struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];206	int ret;207 208	ret = sysfs_create_file(port->mcgs_parent, attr);209	if (ret)210		pr_err("failed to create %s\n", attr->name);211 212	return ret;213}214 215void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,216		struct attribute *attr)217{218	struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];219 220	sysfs_remove_file(port->mcgs_parent, attr);221}222 223static int add_port_entries(struct mlx4_ib_dev *device, int port_num)224{225	int i;226	char buff[12];227	struct mlx4_ib_iov_port *port = NULL;228	int ret = 0 ;229	struct ib_port_attr attr;230 231	memset(&attr, 0, sizeof(attr));232	/* get the physical gid and pkey table sizes.*/233	ret = __mlx4_ib_query_port(&device->ib_dev, port_num, &attr, 1);234	if (ret)235		goto err;236 237	port = &device->iov_ports[port_num - 1];238	port->dev = device;239	port->num = port_num;240	/* Directory structure:241	 * iov -242	 *   port num -243	 *	admin_guids244	 *	gids (operational)245	 *	mcg_table246	 */247	port->dentr_ar = kzalloc(sizeof (struct mlx4_ib_iov_sysfs_attr_ar),248				 GFP_KERNEL);249	if (!port->dentr_ar) {250		ret = -ENOMEM;251		goto err;252	}253	sprintf(buff, "%d", port_num);254	port->cur_port = kobject_create_and_add(buff,255				 kobject_get(device->ports_parent));256	if (!port->cur_port) {257		ret = -ENOMEM;258		goto kobj_create_err;259	}260	/* admin GUIDs */261	port->admin_alias_parent = kobject_create_and_add("admin_guids",262						  kobject_get(port->cur_port));263	if (!port->admin_alias_parent) {264		ret = -ENOMEM;265		goto err_admin_guids;266	}267	for (i = 0 ; i < attr.gid_tbl_len; i++) {268		sprintf(buff, "%d", i);269		port->dentr_ar->dentries[i].entry_num = i;270		ret = create_sysfs_entry(port, &port->dentr_ar->dentries[i],271					  buff, port->admin_alias_parent,272					  show_admin_alias_guid, store_admin_alias_guid);273		if (ret)274			goto err_admin_alias_parent;275	}276 277	/* gids subdirectory (operational gids) */278	port->gids_parent = kobject_create_and_add("gids",279						  kobject_get(port->cur_port));280	if (!port->gids_parent) {281		ret = -ENOMEM;282		goto err_gids;283	}284 285	for (i = 0 ; i < attr.gid_tbl_len; i++) {286		sprintf(buff, "%d", i);287		port->dentr_ar->dentries[attr.gid_tbl_len + i].entry_num = i;288		ret = create_sysfs_entry(port,289					 &port->dentr_ar->dentries[attr.gid_tbl_len + i],290					 buff,291					 port->gids_parent, show_port_gid, NULL);292		if (ret)293			goto err_gids_parent;294	}295 296	/* physical port pkey table */297	port->pkeys_parent =298		kobject_create_and_add("pkeys", kobject_get(port->cur_port));299	if (!port->pkeys_parent) {300		ret = -ENOMEM;301		goto err_pkeys;302	}303 304	for (i = 0 ; i < attr.pkey_tbl_len; i++) {305		sprintf(buff, "%d", i);306		port->dentr_ar->dentries[2 * attr.gid_tbl_len + i].entry_num = i;307		ret = create_sysfs_entry(port,308					 &port->dentr_ar->dentries[2 * attr.gid_tbl_len + i],309					 buff, port->pkeys_parent,310					 show_phys_port_pkey, NULL);311		if (ret)312			goto err_pkeys_parent;313	}314 315	/* MCGs table */316	port->mcgs_parent =317		kobject_create_and_add("mcgs", kobject_get(port->cur_port));318	if (!port->mcgs_parent) {319		ret = -ENOMEM;320		goto err_mcgs;321	}322	return 0;323 324err_mcgs:325	kobject_put(port->cur_port);326 327err_pkeys_parent:328	kobject_put(port->pkeys_parent);329 330err_pkeys:331	kobject_put(port->cur_port);332 333err_gids_parent:334	kobject_put(port->gids_parent);335 336err_gids:337	kobject_put(port->cur_port);338 339err_admin_alias_parent:340	kobject_put(port->admin_alias_parent);341 342err_admin_guids:343	kobject_put(port->cur_port);344	kobject_put(port->cur_port); /* once more for create_and_add buff */345 346kobj_create_err:347	kobject_put(device->ports_parent);348	kfree(port->dentr_ar);349 350err:351	pr_err("add_port_entries FAILED: for port:%d, error: %d\n",352	       port_num, ret);353	return ret;354}355 356static void get_name(struct mlx4_ib_dev *dev, char *name, int i, int max)357{358	/* pci_name format is: bus:dev:func -> xxxx:yy:zz.n359	 * with no ARI only 3 last bits are used so when the fn is higher than 8360	 * need to add it to the dev num, so count in the last number will be361	 * modulo 8 */362	snprintf(name, max, "%.8s%.2d.%d", pci_name(dev->dev->persist->pdev),363		 i / 8, i % 8);364}365 366struct mlx4_port {367	struct kobject         kobj;368	struct mlx4_ib_dev    *dev;369	struct attribute_group pkey_group;370	struct attribute_group gid_group;371	struct device_attribute	enable_smi_admin;372	struct device_attribute	smi_enabled;373	int		       slave;374	u8                     port_num;375};376 377 378static void mlx4_port_release(struct kobject *kobj)379{380	struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);381	struct attribute *a;382	int i;383 384	for (i = 0; (a = p->pkey_group.attrs[i]); ++i)385		kfree(a);386	kfree(p->pkey_group.attrs);387	for (i = 0; (a = p->gid_group.attrs[i]); ++i)388		kfree(a);389	kfree(p->gid_group.attrs);390	kfree(p);391}392 393struct port_attribute {394	struct attribute attr;395	ssize_t (*show)(struct mlx4_port *, struct port_attribute *, char *buf);396	ssize_t (*store)(struct mlx4_port *, struct port_attribute *,397			 const char *buf, size_t count);398};399 400static ssize_t port_attr_show(struct kobject *kobj,401			      struct attribute *attr, char *buf)402{403	struct port_attribute *port_attr =404		container_of(attr, struct port_attribute, attr);405	struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);406 407	if (!port_attr->show)408		return -EIO;409	return port_attr->show(p, port_attr, buf);410}411 412static ssize_t port_attr_store(struct kobject *kobj,413			       struct attribute *attr,414			       const char *buf, size_t size)415{416	struct port_attribute *port_attr =417		container_of(attr, struct port_attribute, attr);418	struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);419 420	if (!port_attr->store)421		return -EIO;422	return port_attr->store(p, port_attr, buf, size);423}424 425static const struct sysfs_ops port_sysfs_ops = {426	.show = port_attr_show,427	.store = port_attr_store,428};429 430static struct kobj_type port_type = {431	.release    = mlx4_port_release,432	.sysfs_ops  = &port_sysfs_ops,433};434 435struct port_table_attribute {436	struct port_attribute	attr;437	char			name[8];438	int			index;439};440 441static ssize_t show_port_pkey(struct mlx4_port *p, struct port_attribute *attr,442			      char *buf)443{444	struct port_table_attribute *tab_attr =445		container_of(attr, struct port_table_attribute, attr);446	struct pkey_mgt *m = &p->dev->pkeys;447	u8 key = m->virt2phys_pkey[p->slave][p->port_num - 1][tab_attr->index];448 449	if (key >= p->dev->dev->caps.pkey_table_len[p->port_num])450		return sysfs_emit(buf, "none\n");451	return sysfs_emit(buf, "%d\n", key);452}453 454static ssize_t store_port_pkey(struct mlx4_port *p, struct port_attribute *attr,455			       const char *buf, size_t count)456{457	struct port_table_attribute *tab_attr =458		container_of(attr, struct port_table_attribute, attr);459	int idx;460	int err;461 462	/* do not allow remapping Dom0 virtual pkey table */463	if (p->slave == mlx4_master_func_num(p->dev->dev))464		return -EINVAL;465 466	if (!strncasecmp(buf, "no", 2))467		idx = p->dev->dev->phys_caps.pkey_phys_table_len[p->port_num] - 1;468	else if (sscanf(buf, "%i", &idx) != 1 ||469		 idx >= p->dev->dev->caps.pkey_table_len[p->port_num] ||470		 idx < 0)471		return -EINVAL;472 473	p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1]474				    [tab_attr->index] = idx;475	mlx4_sync_pkey_table(p->dev->dev, p->slave, p->port_num,476			     tab_attr->index, idx);477	err = mlx4_gen_pkey_eqe(p->dev->dev, p->slave, p->port_num);478	if (err) {479		pr_err("mlx4_gen_pkey_eqe failed for slave %d,"480		       " port %d, index %d\n", p->slave, p->port_num, idx);481		return err;482	}483	return count;484}485 486static ssize_t show_port_gid_idx(struct mlx4_port *p,487				 struct port_attribute *attr, char *buf)488{489	return sysfs_emit(buf, "%d\n", p->slave);490}491 492static struct attribute **493alloc_group_attrs(ssize_t (*show)(struct mlx4_port *,494				  struct port_attribute *, char *buf),495		  ssize_t (*store)(struct mlx4_port *, struct port_attribute *,496				   const char *buf, size_t count),497		  int len)498{499	struct attribute **tab_attr;500	struct port_table_attribute *element;501	int i;502 503	tab_attr = kcalloc(1 + len, sizeof (struct attribute *), GFP_KERNEL);504	if (!tab_attr)505		return NULL;506 507	for (i = 0; i < len; i++) {508		element = kzalloc(sizeof (struct port_table_attribute),509				  GFP_KERNEL);510		if (!element)511			goto err;512		if (snprintf(element->name, sizeof (element->name),513			     "%d", i) >= sizeof (element->name)) {514			kfree(element);515			goto err;516		}517		sysfs_attr_init(&element->attr.attr);518		element->attr.attr.name  = element->name;519		if (store) {520			element->attr.attr.mode  = S_IWUSR | S_IRUGO;521			element->attr.store	 = store;522		} else523			element->attr.attr.mode  = S_IRUGO;524 525		element->attr.show       = show;526		element->index		 = i;527		tab_attr[i] = &element->attr.attr;528	}529	return tab_attr;530 531err:532	while (--i >= 0)533		kfree(tab_attr[i]);534	kfree(tab_attr);535	return NULL;536}537 538static ssize_t sysfs_show_smi_enabled(struct device *dev,539				      struct device_attribute *attr, char *buf)540{541	struct mlx4_port *p =542		container_of(attr, struct mlx4_port, smi_enabled);543 544	return sysfs_emit(buf, "%d\n",545			  !!mlx4_vf_smi_enabled(p->dev->dev, p->slave,546						p->port_num));547}548 549static ssize_t sysfs_show_enable_smi_admin(struct device *dev,550					   struct device_attribute *attr,551					   char *buf)552{553	struct mlx4_port *p =554		container_of(attr, struct mlx4_port, enable_smi_admin);555 556	return sysfs_emit(buf, "%d\n",557			  !!mlx4_vf_get_enable_smi_admin(p->dev->dev, p->slave,558							 p->port_num));559}560 561static ssize_t sysfs_store_enable_smi_admin(struct device *dev,562					    struct device_attribute *attr,563					    const char *buf, size_t count)564{565	struct mlx4_port *p =566		container_of(attr, struct mlx4_port, enable_smi_admin);567	int enable;568 569	if (sscanf(buf, "%i", &enable) != 1 ||570	    enable < 0 || enable > 1)571		return -EINVAL;572 573	if (mlx4_vf_set_enable_smi_admin(p->dev->dev, p->slave, p->port_num, enable))574		return -EINVAL;575	return count;576}577 578static int add_vf_smi_entries(struct mlx4_port *p)579{580	int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) ==581			IB_LINK_LAYER_ETHERNET;582	int ret;583 584	/* do not display entries if eth transport, or if master */585	if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev))586		return 0;587 588	sysfs_attr_init(&p->smi_enabled.attr);589	p->smi_enabled.show = sysfs_show_smi_enabled;590	p->smi_enabled.store = NULL;591	p->smi_enabled.attr.name = "smi_enabled";592	p->smi_enabled.attr.mode = 0444;593	ret = sysfs_create_file(&p->kobj, &p->smi_enabled.attr);594	if (ret) {595		pr_err("failed to create smi_enabled\n");596		return ret;597	}598 599	sysfs_attr_init(&p->enable_smi_admin.attr);600	p->enable_smi_admin.show = sysfs_show_enable_smi_admin;601	p->enable_smi_admin.store = sysfs_store_enable_smi_admin;602	p->enable_smi_admin.attr.name = "enable_smi_admin";603	p->enable_smi_admin.attr.mode = 0644;604	ret = sysfs_create_file(&p->kobj, &p->enable_smi_admin.attr);605	if (ret) {606		pr_err("failed to create enable_smi_admin\n");607		sysfs_remove_file(&p->kobj, &p->smi_enabled.attr);608		return ret;609	}610	return 0;611}612 613static void remove_vf_smi_entries(struct mlx4_port *p)614{615	int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) ==616			IB_LINK_LAYER_ETHERNET;617 618	if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev))619		return;620 621	sysfs_remove_file(&p->kobj, &p->smi_enabled.attr);622	sysfs_remove_file(&p->kobj, &p->enable_smi_admin.attr);623}624 625static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)626{627	struct mlx4_port *p;628	int i;629	int ret;630	int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port_num) ==631			IB_LINK_LAYER_ETHERNET;632 633	p = kzalloc(sizeof *p, GFP_KERNEL);634	if (!p)635		return -ENOMEM;636 637	p->dev = dev;638	p->port_num = port_num;639	p->slave = slave;640 641	ret = kobject_init_and_add(&p->kobj, &port_type,642				   kobject_get(dev->dev_ports_parent[slave]),643				   "%d", port_num);644	if (ret)645		goto err_alloc;646 647	p->pkey_group.name  = "pkey_idx";648	p->pkey_group.attrs =649		alloc_group_attrs(show_port_pkey,650				  is_eth ? NULL : store_port_pkey,651				  dev->dev->caps.pkey_table_len[port_num]);652	if (!p->pkey_group.attrs) {653		ret = -ENOMEM;654		goto err_alloc;655	}656 657	ret = sysfs_create_group(&p->kobj, &p->pkey_group);658	if (ret)659		goto err_free_pkey;660 661	p->gid_group.name  = "gid_idx";662	p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1);663	if (!p->gid_group.attrs) {664		ret = -ENOMEM;665		goto err_free_pkey;666	}667 668	ret = sysfs_create_group(&p->kobj, &p->gid_group);669	if (ret)670		goto err_free_gid;671 672	ret = add_vf_smi_entries(p);673	if (ret)674		goto err_free_gid;675 676	list_add_tail(&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]);677	return 0;678 679err_free_gid:680	kfree(p->gid_group.attrs[0]);681	kfree(p->gid_group.attrs);682 683err_free_pkey:684	for (i = 0; i < dev->dev->caps.pkey_table_len[port_num]; ++i)685		kfree(p->pkey_group.attrs[i]);686	kfree(p->pkey_group.attrs);687 688err_alloc:689	kobject_put(dev->dev_ports_parent[slave]);690	kfree(p);691	return ret;692}693 694static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)695{696	char name[32];697	int err;698	int port;699	struct kobject *p, *t;700	struct mlx4_port *mport;701	struct mlx4_active_ports actv_ports;702 703	get_name(dev, name, slave, sizeof name);704 705	dev->pkeys.device_parent[slave] =706		kobject_create_and_add(name, kobject_get(dev->iov_parent));707 708	if (!dev->pkeys.device_parent[slave]) {709		err = -ENOMEM;710		goto fail_dev;711	}712 713	INIT_LIST_HEAD(&dev->pkeys.pkey_port_list[slave]);714 715	dev->dev_ports_parent[slave] =716		kobject_create_and_add("ports",717				       kobject_get(dev->pkeys.device_parent[slave]));718 719	if (!dev->dev_ports_parent[slave]) {720		err = -ENOMEM;721		goto err_ports;722	}723 724	actv_ports = mlx4_get_active_ports(dev->dev, slave);725 726	for (port = 1; port <= dev->dev->caps.num_ports; ++port) {727		if (!test_bit(port - 1, actv_ports.ports))728			continue;729		err = add_port(dev, port, slave);730		if (err)731			goto err_add;732	}733	return 0;734 735err_add:736	list_for_each_entry_safe(p, t,737				 &dev->pkeys.pkey_port_list[slave],738				 entry) {739		list_del(&p->entry);740		mport = container_of(p, struct mlx4_port, kobj);741		sysfs_remove_group(p, &mport->pkey_group);742		sysfs_remove_group(p, &mport->gid_group);743		remove_vf_smi_entries(mport);744		kobject_put(p);745	}746	kobject_put(dev->dev_ports_parent[slave]);747 748err_ports:749	kobject_put(dev->pkeys.device_parent[slave]);750	/* extra put for the device_parent create_and_add */751	kobject_put(dev->pkeys.device_parent[slave]);752 753fail_dev:754	kobject_put(dev->iov_parent);755	return err;756}757 758static int register_pkey_tree(struct mlx4_ib_dev *device)759{760	int i;761 762	if (!mlx4_is_master(device->dev))763		return 0;764 765	for (i = 0; i <= device->dev->persist->num_vfs; ++i)766		register_one_pkey_tree(device, i);767 768	return 0;769}770 771static void unregister_pkey_tree(struct mlx4_ib_dev *device)772{773	int slave;774	struct kobject *p, *t;775	struct mlx4_port *port;776 777	if (!mlx4_is_master(device->dev))778		return;779 780	for (slave = device->dev->persist->num_vfs; slave >= 0; --slave) {781		list_for_each_entry_safe(p, t,782					 &device->pkeys.pkey_port_list[slave],783					 entry) {784			list_del(&p->entry);785			port = container_of(p, struct mlx4_port, kobj);786			sysfs_remove_group(p, &port->pkey_group);787			sysfs_remove_group(p, &port->gid_group);788			remove_vf_smi_entries(port);789			kobject_put(p);790			kobject_put(device->dev_ports_parent[slave]);791		}792		kobject_put(device->dev_ports_parent[slave]);793		kobject_put(device->pkeys.device_parent[slave]);794		kobject_put(device->pkeys.device_parent[slave]);795		kobject_put(device->iov_parent);796	}797}798 799int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *dev)800{801	unsigned int i;802	int ret = 0;803 804	if (!mlx4_is_master(dev->dev))805		return 0;806 807	dev->iov_parent = kobject_create_and_add("iov", &dev->ib_dev.dev.kobj);808	if (!dev->iov_parent) {809		ret = -ENOMEM;810		goto err;811	}812	dev->ports_parent =813		kobject_create_and_add("ports",814				       kobject_get(dev->iov_parent));815	if (!dev->ports_parent) {816		ret = -ENOMEM;817		goto err_ports;818	}819 820	rdma_for_each_port(&dev->ib_dev, i) {821		ret = add_port_entries(dev, i);822		if (ret)823			goto err_add_entries;824	}825 826	ret = register_pkey_tree(dev);827	if (ret)828		goto err_add_entries;829	return 0;830 831err_add_entries:832	kobject_put(dev->ports_parent);833 834err_ports:835	kobject_put(dev->iov_parent);836err:837	pr_err("mlx4_ib_device_register_sysfs error (%d)\n", ret);838	return ret;839}840 841static void unregister_alias_guid_tree(struct mlx4_ib_dev *device)842{843	struct mlx4_ib_iov_port *p;844	int i;845 846	if (!mlx4_is_master(device->dev))847		return;848 849	for (i = 0; i < device->dev->caps.num_ports; i++) {850		p = &device->iov_ports[i];851		kobject_put(p->admin_alias_parent);852		kobject_put(p->gids_parent);853		kobject_put(p->pkeys_parent);854		kobject_put(p->mcgs_parent);855		kobject_put(p->cur_port);856		kobject_put(p->cur_port);857		kobject_put(p->cur_port);858		kobject_put(p->cur_port);859		kobject_put(p->cur_port);860		kobject_put(p->dev->ports_parent);861		kfree(p->dentr_ar);862	}863}864 865void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device)866{867	unregister_alias_guid_tree(device);868	unregister_pkey_tree(device);869	kobject_put(device->ports_parent);870	kobject_put(device->iov_parent);871	kobject_put(device->iov_parent);872}873