1c1e7e466SJack Morgenstein /* 2c1e7e466SJack Morgenstein * Copyright (c) 2012 Mellanox Technologies. All rights reserved. 3c1e7e466SJack Morgenstein * 4c1e7e466SJack Morgenstein * This software is available to you under a choice of one of two 5c1e7e466SJack Morgenstein * licenses. You may choose to be licensed under the terms of the GNU 6c1e7e466SJack Morgenstein * General Public License (GPL) Version 2, available from the file 7c1e7e466SJack Morgenstein * COPYING in the main directory of this source tree, or the 8c1e7e466SJack Morgenstein * OpenIB.org BSD license below: 9c1e7e466SJack Morgenstein * 10c1e7e466SJack Morgenstein * Redistribution and use in source and binary forms, with or 11c1e7e466SJack Morgenstein * without modification, are permitted provided that the following 12c1e7e466SJack Morgenstein * conditions are met: 13c1e7e466SJack Morgenstein * 14c1e7e466SJack Morgenstein * - Redistributions of source code must retain the above 15c1e7e466SJack Morgenstein * copyright notice, this list of conditions and the following 16c1e7e466SJack Morgenstein * disclaimer. 17c1e7e466SJack Morgenstein * 18c1e7e466SJack Morgenstein * - Redistributions in binary form must reproduce the above 19c1e7e466SJack Morgenstein * copyright notice, this list of conditions and the following 20c1e7e466SJack Morgenstein * disclaimer in the documentation and/or other materials 21c1e7e466SJack Morgenstein * provided with the distribution. 22c1e7e466SJack Morgenstein * 23c1e7e466SJack Morgenstein * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24c1e7e466SJack Morgenstein * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25c1e7e466SJack Morgenstein * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26c1e7e466SJack Morgenstein * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27c1e7e466SJack Morgenstein * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28c1e7e466SJack Morgenstein * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29c1e7e466SJack Morgenstein * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30c1e7e466SJack Morgenstein * SOFTWARE. 31c1e7e466SJack Morgenstein */ 32c1e7e466SJack Morgenstein 33c1e7e466SJack Morgenstein /*#include "core_priv.h"*/ 34c1e7e466SJack Morgenstein #include "mlx4_ib.h" 35c1e7e466SJack Morgenstein #include <linux/slab.h> 36c1e7e466SJack Morgenstein #include <linux/string.h> 37c1e7e466SJack Morgenstein #include <linux/stat.h> 38c1e7e466SJack Morgenstein 39c1e7e466SJack Morgenstein #include <rdma/ib_mad.h> 40c1e7e466SJack Morgenstein /*show_admin_alias_guid returns the administratively assigned value of that GUID. 41c1e7e466SJack Morgenstein * Values returned in buf parameter string: 42c1e7e466SJack Morgenstein * 0 - requests opensm to assign a value. 43c1e7e466SJack Morgenstein * ffffffffffffffff - delete this entry. 44c1e7e466SJack Morgenstein * other - value assigned by administrator. 45c1e7e466SJack Morgenstein */ 46c1e7e466SJack Morgenstein static ssize_t show_admin_alias_guid(struct device *dev, 47c1e7e466SJack Morgenstein struct device_attribute *attr, char *buf) 48c1e7e466SJack Morgenstein { 49c1e7e466SJack Morgenstein struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry = 50c1e7e466SJack Morgenstein container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry); 51c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; 52c1e7e466SJack Morgenstein struct mlx4_ib_dev *mdev = port->dev; 532350f247SYishai Hadas __be64 sysadmin_ag_val; 54c1e7e466SJack Morgenstein 552350f247SYishai Hadas sysadmin_ag_val = mlx4_get_admin_guid(mdev->dev, 562350f247SYishai Hadas mlx4_ib_iov_dentry->entry_num, 572350f247SYishai Hadas port->num); 58c1e7e466SJack Morgenstein 591c7fd726SJoe Perches return sysfs_emit(buf, "%llx\n", be64_to_cpu(sysadmin_ag_val)); 60c1e7e466SJack Morgenstein } 61c1e7e466SJack Morgenstein 62c1e7e466SJack Morgenstein /* store_admin_alias_guid stores the (new) administratively assigned value of that GUID. 63c1e7e466SJack Morgenstein * Values in buf parameter string: 64c1e7e466SJack Morgenstein * 0 - requests opensm to assign a value. 65c1e7e466SJack Morgenstein * 0xffffffffffffffff - delete this entry. 66c1e7e466SJack Morgenstein * other - guid value assigned by the administrator. 67c1e7e466SJack Morgenstein */ 68c1e7e466SJack Morgenstein static ssize_t store_admin_alias_guid(struct device *dev, 69c1e7e466SJack Morgenstein struct device_attribute *attr, 70c1e7e466SJack Morgenstein const char *buf, size_t count) 71c1e7e466SJack Morgenstein { 72c1e7e466SJack Morgenstein int record_num;/*0-15*/ 73c1e7e466SJack Morgenstein int guid_index_in_rec; /*0 - 7*/ 74c1e7e466SJack Morgenstein struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry = 75c1e7e466SJack Morgenstein container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry); 76c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; 77c1e7e466SJack Morgenstein struct mlx4_ib_dev *mdev = port->dev; 78c1e7e466SJack Morgenstein u64 sysadmin_ag_val; 7999ee4df6SYishai Hadas unsigned long flags; 80c1e7e466SJack Morgenstein 81c1e7e466SJack Morgenstein record_num = mlx4_ib_iov_dentry->entry_num / 8; 82c1e7e466SJack Morgenstein guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8; 83c1e7e466SJack Morgenstein if (0 == record_num && 0 == guid_index_in_rec) { 84c1e7e466SJack Morgenstein pr_err("GUID 0 block 0 is RO\n"); 85c1e7e466SJack Morgenstein return count; 86c1e7e466SJack Morgenstein } 8799ee4df6SYishai Hadas spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags); 88c1e7e466SJack Morgenstein sscanf(buf, "%llx", &sysadmin_ag_val); 89c1e7e466SJack Morgenstein *(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1]. 90c1e7e466SJack Morgenstein all_rec_per_port[record_num]. 91c1e7e466SJack Morgenstein all_recs[GUID_REC_SIZE * guid_index_in_rec] = 92c1e7e466SJack Morgenstein cpu_to_be64(sysadmin_ag_val); 93c1e7e466SJack Morgenstein 94c1e7e466SJack Morgenstein /* Change the state to be pending for update */ 95c1e7e466SJack Morgenstein mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status 96c1e7e466SJack Morgenstein = MLX4_GUID_INFO_STATUS_IDLE ; 972350f247SYishai Hadas mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val), 982350f247SYishai Hadas mlx4_ib_iov_dentry->entry_num, 992350f247SYishai Hadas port->num); 1002350f247SYishai Hadas 101c1e7e466SJack Morgenstein /* set the record index */ 102c1e7e466SJack Morgenstein mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes 10399ee4df6SYishai Hadas |= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec); 104c1e7e466SJack Morgenstein 10599ee4df6SYishai Hadas spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags); 106c1e7e466SJack Morgenstein mlx4_ib_init_alias_guid_work(mdev, port->num - 1); 107c1e7e466SJack Morgenstein 108c1e7e466SJack Morgenstein return count; 109c1e7e466SJack Morgenstein } 110c1e7e466SJack Morgenstein 111c1e7e466SJack Morgenstein static ssize_t show_port_gid(struct device *dev, 112c1e7e466SJack Morgenstein struct device_attribute *attr, 113c1e7e466SJack Morgenstein char *buf) 114c1e7e466SJack Morgenstein { 115c1e7e466SJack Morgenstein struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry = 116c1e7e466SJack Morgenstein container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry); 117c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; 118c1e7e466SJack Morgenstein struct mlx4_ib_dev *mdev = port->dev; 119c1e7e466SJack Morgenstein union ib_gid gid; 12045808361SJoe Perches int ret; 12145808361SJoe Perches __be16 *raw; 122c1e7e466SJack Morgenstein 123c1e7e466SJack Morgenstein ret = __mlx4_ib_query_gid(&mdev->ib_dev, port->num, 124c1e7e466SJack Morgenstein mlx4_ib_iov_dentry->entry_num, &gid, 1); 125c1e7e466SJack Morgenstein if (ret) 126c1e7e466SJack Morgenstein return ret; 12745808361SJoe Perches 12845808361SJoe Perches raw = (__be16 *)gid.raw; 12945808361SJoe Perches return sysfs_emit(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 13045808361SJoe Perches be16_to_cpu(raw[0]), 13145808361SJoe Perches be16_to_cpu(raw[1]), 13245808361SJoe Perches be16_to_cpu(raw[2]), 13345808361SJoe Perches be16_to_cpu(raw[3]), 13445808361SJoe Perches be16_to_cpu(raw[4]), 13545808361SJoe Perches be16_to_cpu(raw[5]), 13645808361SJoe Perches be16_to_cpu(raw[6]), 13745808361SJoe Perches be16_to_cpu(raw[7])); 138c1e7e466SJack Morgenstein } 139c1e7e466SJack Morgenstein 140c1e7e466SJack Morgenstein static ssize_t show_phys_port_pkey(struct device *dev, 141c1e7e466SJack Morgenstein struct device_attribute *attr, 142c1e7e466SJack Morgenstein char *buf) 143c1e7e466SJack Morgenstein { 144c1e7e466SJack Morgenstein struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry = 145c1e7e466SJack Morgenstein container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry); 146c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx; 147c1e7e466SJack Morgenstein struct mlx4_ib_dev *mdev = port->dev; 148c1e7e466SJack Morgenstein u16 pkey; 149c1e7e466SJack Morgenstein ssize_t ret; 150c1e7e466SJack Morgenstein 151c1e7e466SJack Morgenstein ret = __mlx4_ib_query_pkey(&mdev->ib_dev, port->num, 152c1e7e466SJack Morgenstein mlx4_ib_iov_dentry->entry_num, &pkey, 1); 153c1e7e466SJack Morgenstein if (ret) 154c1e7e466SJack Morgenstein return ret; 155c1e7e466SJack Morgenstein 1561c7fd726SJoe Perches return sysfs_emit(buf, "0x%04x\n", pkey); 157c1e7e466SJack Morgenstein } 158c1e7e466SJack Morgenstein 159c1e7e466SJack Morgenstein #define DENTRY_REMOVE(_dentry) \ 160c1e7e466SJack Morgenstein do { \ 161c1e7e466SJack Morgenstein sysfs_remove_file((_dentry)->kobj, &(_dentry)->dentry.attr); \ 162c1e7e466SJack Morgenstein } while (0); 163c1e7e466SJack Morgenstein 164c1e7e466SJack Morgenstein static int create_sysfs_entry(void *_ctx, struct mlx4_ib_iov_sysfs_attr *_dentry, 165c1e7e466SJack Morgenstein char *_name, struct kobject *_kobj, 166c1e7e466SJack Morgenstein ssize_t (*show)(struct device *dev, 167c1e7e466SJack Morgenstein struct device_attribute *attr, 168c1e7e466SJack Morgenstein char *buf), 169c1e7e466SJack Morgenstein ssize_t (*store)(struct device *dev, 170c1e7e466SJack Morgenstein struct device_attribute *attr, 171c1e7e466SJack Morgenstein const char *buf, size_t count) 172c1e7e466SJack Morgenstein ) 173c1e7e466SJack Morgenstein { 174c1e7e466SJack Morgenstein int ret = 0; 175c1e7e466SJack Morgenstein struct mlx4_ib_iov_sysfs_attr *vdentry = _dentry; 176c1e7e466SJack Morgenstein 177c1e7e466SJack Morgenstein vdentry->ctx = _ctx; 178c1e7e466SJack Morgenstein vdentry->dentry.show = show; 179c1e7e466SJack Morgenstein vdentry->dentry.store = store; 180c1e7e466SJack Morgenstein sysfs_attr_init(&vdentry->dentry.attr); 181c1e7e466SJack Morgenstein vdentry->dentry.attr.name = vdentry->name; 182c1e7e466SJack Morgenstein vdentry->dentry.attr.mode = 0; 183c1e7e466SJack Morgenstein vdentry->kobj = _kobj; 184c1e7e466SJack Morgenstein snprintf(vdentry->name, 15, "%s", _name); 185c1e7e466SJack Morgenstein 186c1e7e466SJack Morgenstein if (vdentry->dentry.store) 187c1e7e466SJack Morgenstein vdentry->dentry.attr.mode |= S_IWUSR; 188c1e7e466SJack Morgenstein 189c1e7e466SJack Morgenstein if (vdentry->dentry.show) 190c1e7e466SJack Morgenstein vdentry->dentry.attr.mode |= S_IRUGO; 191c1e7e466SJack Morgenstein 192c1e7e466SJack Morgenstein ret = sysfs_create_file(vdentry->kobj, &vdentry->dentry.attr); 193c1e7e466SJack Morgenstein if (ret) { 194c1e7e466SJack Morgenstein pr_err("failed to create %s\n", vdentry->dentry.attr.name); 195c1e7e466SJack Morgenstein vdentry->ctx = NULL; 196c1e7e466SJack Morgenstein return ret; 197c1e7e466SJack Morgenstein } 198c1e7e466SJack Morgenstein 199c1e7e466SJack Morgenstein return ret; 200c1e7e466SJack Morgenstein } 201c1e7e466SJack Morgenstein 202c1e7e466SJack Morgenstein int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num, 203c1e7e466SJack Morgenstein struct attribute *attr) 204c1e7e466SJack Morgenstein { 205c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1]; 206c1e7e466SJack Morgenstein int ret; 207c1e7e466SJack Morgenstein 208c1e7e466SJack Morgenstein ret = sysfs_create_file(port->mcgs_parent, attr); 209c1e7e466SJack Morgenstein if (ret) 210c1e7e466SJack Morgenstein pr_err("failed to create %s\n", attr->name); 211c1e7e466SJack Morgenstein 212c1e7e466SJack Morgenstein return ret; 213c1e7e466SJack Morgenstein } 214c1e7e466SJack Morgenstein 215c1e7e466SJack Morgenstein void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num, 216c1e7e466SJack Morgenstein struct attribute *attr) 217c1e7e466SJack Morgenstein { 218c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1]; 219c1e7e466SJack Morgenstein 220c1e7e466SJack Morgenstein sysfs_remove_file(port->mcgs_parent, attr); 221c1e7e466SJack Morgenstein } 222c1e7e466SJack Morgenstein 223c1e7e466SJack Morgenstein static int add_port_entries(struct mlx4_ib_dev *device, int port_num) 224c1e7e466SJack Morgenstein { 225c1e7e466SJack Morgenstein int i; 226d0dbf771SArnd Bergmann char buff[11]; 227c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *port = NULL; 228c1e7e466SJack Morgenstein int ret = 0 ; 229c1e7e466SJack Morgenstein struct ib_port_attr attr; 230c1e7e466SJack Morgenstein 231c4550c63SOr Gerlitz memset(&attr, 0, sizeof(attr)); 232c1e7e466SJack Morgenstein /* get the physical gid and pkey table sizes.*/ 233c1e7e466SJack Morgenstein ret = __mlx4_ib_query_port(&device->ib_dev, port_num, &attr, 1); 234c1e7e466SJack Morgenstein if (ret) 235c1e7e466SJack Morgenstein goto err; 236c1e7e466SJack Morgenstein 237c1e7e466SJack Morgenstein port = &device->iov_ports[port_num - 1]; 238c1e7e466SJack Morgenstein port->dev = device; 239c1e7e466SJack Morgenstein port->num = port_num; 240c1e7e466SJack Morgenstein /* Directory structure: 241c1e7e466SJack Morgenstein * iov - 242c1e7e466SJack Morgenstein * port num - 243c1e7e466SJack Morgenstein * admin_guids 244c1e7e466SJack Morgenstein * gids (operational) 245c1e7e466SJack Morgenstein * mcg_table 246c1e7e466SJack Morgenstein */ 247c1e7e466SJack Morgenstein port->dentr_ar = kzalloc(sizeof (struct mlx4_ib_iov_sysfs_attr_ar), 248c1e7e466SJack Morgenstein GFP_KERNEL); 249c1e7e466SJack Morgenstein if (!port->dentr_ar) { 250c1e7e466SJack Morgenstein ret = -ENOMEM; 251c1e7e466SJack Morgenstein goto err; 252c1e7e466SJack Morgenstein } 253c1e7e466SJack Morgenstein sprintf(buff, "%d", port_num); 254c1e7e466SJack Morgenstein port->cur_port = kobject_create_and_add(buff, 255c1e7e466SJack Morgenstein kobject_get(device->ports_parent)); 256c1e7e466SJack Morgenstein if (!port->cur_port) { 257c1e7e466SJack Morgenstein ret = -ENOMEM; 258c1e7e466SJack Morgenstein goto kobj_create_err; 259c1e7e466SJack Morgenstein } 260c1e7e466SJack Morgenstein /* admin GUIDs */ 261c1e7e466SJack Morgenstein port->admin_alias_parent = kobject_create_and_add("admin_guids", 262c1e7e466SJack Morgenstein kobject_get(port->cur_port)); 263c1e7e466SJack Morgenstein if (!port->admin_alias_parent) { 264c1e7e466SJack Morgenstein ret = -ENOMEM; 265c1e7e466SJack Morgenstein goto err_admin_guids; 266c1e7e466SJack Morgenstein } 267c1e7e466SJack Morgenstein for (i = 0 ; i < attr.gid_tbl_len; i++) { 268c1e7e466SJack Morgenstein sprintf(buff, "%d", i); 269c1e7e466SJack Morgenstein port->dentr_ar->dentries[i].entry_num = i; 270c1e7e466SJack Morgenstein ret = create_sysfs_entry(port, &port->dentr_ar->dentries[i], 271c1e7e466SJack Morgenstein buff, port->admin_alias_parent, 272c1e7e466SJack Morgenstein show_admin_alias_guid, store_admin_alias_guid); 273c1e7e466SJack Morgenstein if (ret) 274c1e7e466SJack Morgenstein goto err_admin_alias_parent; 275c1e7e466SJack Morgenstein } 276c1e7e466SJack Morgenstein 277c1e7e466SJack Morgenstein /* gids subdirectory (operational gids) */ 278c1e7e466SJack Morgenstein port->gids_parent = kobject_create_and_add("gids", 279c1e7e466SJack Morgenstein kobject_get(port->cur_port)); 280c1e7e466SJack Morgenstein if (!port->gids_parent) { 281c1e7e466SJack Morgenstein ret = -ENOMEM; 282c1e7e466SJack Morgenstein goto err_gids; 283c1e7e466SJack Morgenstein } 284c1e7e466SJack Morgenstein 285c1e7e466SJack Morgenstein for (i = 0 ; i < attr.gid_tbl_len; i++) { 286c1e7e466SJack Morgenstein sprintf(buff, "%d", i); 287c1e7e466SJack Morgenstein port->dentr_ar->dentries[attr.gid_tbl_len + i].entry_num = i; 288c1e7e466SJack Morgenstein ret = create_sysfs_entry(port, 289c1e7e466SJack Morgenstein &port->dentr_ar->dentries[attr.gid_tbl_len + i], 290c1e7e466SJack Morgenstein buff, 291c1e7e466SJack Morgenstein port->gids_parent, show_port_gid, NULL); 292c1e7e466SJack Morgenstein if (ret) 293c1e7e466SJack Morgenstein goto err_gids_parent; 294c1e7e466SJack Morgenstein } 295c1e7e466SJack Morgenstein 296c1e7e466SJack Morgenstein /* physical port pkey table */ 297c1e7e466SJack Morgenstein port->pkeys_parent = 298c1e7e466SJack Morgenstein kobject_create_and_add("pkeys", kobject_get(port->cur_port)); 299c1e7e466SJack Morgenstein if (!port->pkeys_parent) { 300c1e7e466SJack Morgenstein ret = -ENOMEM; 301c1e7e466SJack Morgenstein goto err_pkeys; 302c1e7e466SJack Morgenstein } 303c1e7e466SJack Morgenstein 304c1e7e466SJack Morgenstein for (i = 0 ; i < attr.pkey_tbl_len; i++) { 305c1e7e466SJack Morgenstein sprintf(buff, "%d", i); 306c1e7e466SJack Morgenstein port->dentr_ar->dentries[2 * attr.gid_tbl_len + i].entry_num = i; 307c1e7e466SJack Morgenstein ret = create_sysfs_entry(port, 308c1e7e466SJack Morgenstein &port->dentr_ar->dentries[2 * attr.gid_tbl_len + i], 309c1e7e466SJack Morgenstein buff, port->pkeys_parent, 310c1e7e466SJack Morgenstein show_phys_port_pkey, NULL); 311c1e7e466SJack Morgenstein if (ret) 312c1e7e466SJack Morgenstein goto err_pkeys_parent; 313c1e7e466SJack Morgenstein } 314c1e7e466SJack Morgenstein 315c1e7e466SJack Morgenstein /* MCGs table */ 316c1e7e466SJack Morgenstein port->mcgs_parent = 317c1e7e466SJack Morgenstein kobject_create_and_add("mcgs", kobject_get(port->cur_port)); 318c1e7e466SJack Morgenstein if (!port->mcgs_parent) { 319c1e7e466SJack Morgenstein ret = -ENOMEM; 320c1e7e466SJack Morgenstein goto err_mcgs; 321c1e7e466SJack Morgenstein } 322c1e7e466SJack Morgenstein return 0; 323c1e7e466SJack Morgenstein 324c1e7e466SJack Morgenstein err_mcgs: 325c1e7e466SJack Morgenstein kobject_put(port->cur_port); 326c1e7e466SJack Morgenstein 327c1e7e466SJack Morgenstein err_pkeys_parent: 328c1e7e466SJack Morgenstein kobject_put(port->pkeys_parent); 329c1e7e466SJack Morgenstein 330c1e7e466SJack Morgenstein err_pkeys: 331c1e7e466SJack Morgenstein kobject_put(port->cur_port); 332c1e7e466SJack Morgenstein 333c1e7e466SJack Morgenstein err_gids_parent: 334c1e7e466SJack Morgenstein kobject_put(port->gids_parent); 335c1e7e466SJack Morgenstein 336c1e7e466SJack Morgenstein err_gids: 337c1e7e466SJack Morgenstein kobject_put(port->cur_port); 338c1e7e466SJack Morgenstein 339c1e7e466SJack Morgenstein err_admin_alias_parent: 340c1e7e466SJack Morgenstein kobject_put(port->admin_alias_parent); 341c1e7e466SJack Morgenstein 342c1e7e466SJack Morgenstein err_admin_guids: 343c1e7e466SJack Morgenstein kobject_put(port->cur_port); 344c1e7e466SJack Morgenstein kobject_put(port->cur_port); /* once more for create_and_add buff */ 345c1e7e466SJack Morgenstein 346c1e7e466SJack Morgenstein kobj_create_err: 347c1e7e466SJack Morgenstein kobject_put(device->ports_parent); 348c1e7e466SJack Morgenstein kfree(port->dentr_ar); 349c1e7e466SJack Morgenstein 350c1e7e466SJack Morgenstein err: 351c1e7e466SJack Morgenstein pr_err("add_port_entries FAILED: for port:%d, error: %d\n", 352c1e7e466SJack Morgenstein port_num, ret); 353c1e7e466SJack Morgenstein return ret; 354c1e7e466SJack Morgenstein } 355c1e7e466SJack Morgenstein 356c1e7e466SJack Morgenstein static void get_name(struct mlx4_ib_dev *dev, char *name, int i, int max) 357c1e7e466SJack Morgenstein { 3580fbc9b8bSQian Cai /* pci_name format is: bus:dev:func -> xxxx:yy:zz.n 3590fbc9b8bSQian Cai * with no ARI only 3 last bits are used so when the fn is higher than 8 360c1e7e466SJack Morgenstein * need to add it to the dev num, so count in the last number will be 361c1e7e466SJack Morgenstein * modulo 8 */ 3620fbc9b8bSQian Cai snprintf(name, max, "%.8s%.2d.%d", pci_name(dev->dev->persist->pdev), 3630fbc9b8bSQian Cai i / 8, i % 8); 364c1e7e466SJack Morgenstein } 365c1e7e466SJack Morgenstein 366c1e7e466SJack Morgenstein struct mlx4_port { 367c1e7e466SJack Morgenstein struct kobject kobj; 368c1e7e466SJack Morgenstein struct mlx4_ib_dev *dev; 369c1e7e466SJack Morgenstein struct attribute_group pkey_group; 370c1e7e466SJack Morgenstein struct attribute_group gid_group; 37165fed8a8SJack Morgenstein struct device_attribute enable_smi_admin; 37265fed8a8SJack Morgenstein struct device_attribute smi_enabled; 373c1e7e466SJack Morgenstein int slave; 37465fed8a8SJack Morgenstein u8 port_num; 375c1e7e466SJack Morgenstein }; 376c1e7e466SJack Morgenstein 377c1e7e466SJack Morgenstein 378c1e7e466SJack Morgenstein static void mlx4_port_release(struct kobject *kobj) 379c1e7e466SJack Morgenstein { 380c1e7e466SJack Morgenstein struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj); 381c1e7e466SJack Morgenstein struct attribute *a; 382c1e7e466SJack Morgenstein int i; 383c1e7e466SJack Morgenstein 384c1e7e466SJack Morgenstein for (i = 0; (a = p->pkey_group.attrs[i]); ++i) 385c1e7e466SJack Morgenstein kfree(a); 386c1e7e466SJack Morgenstein kfree(p->pkey_group.attrs); 387c1e7e466SJack Morgenstein for (i = 0; (a = p->gid_group.attrs[i]); ++i) 388c1e7e466SJack Morgenstein kfree(a); 389c1e7e466SJack Morgenstein kfree(p->gid_group.attrs); 390c1e7e466SJack Morgenstein kfree(p); 391c1e7e466SJack Morgenstein } 392c1e7e466SJack Morgenstein 393c1e7e466SJack Morgenstein struct port_attribute { 394c1e7e466SJack Morgenstein struct attribute attr; 395c1e7e466SJack Morgenstein ssize_t (*show)(struct mlx4_port *, struct port_attribute *, char *buf); 396c1e7e466SJack Morgenstein ssize_t (*store)(struct mlx4_port *, struct port_attribute *, 397c1e7e466SJack Morgenstein const char *buf, size_t count); 398c1e7e466SJack Morgenstein }; 399c1e7e466SJack Morgenstein 400c1e7e466SJack Morgenstein static ssize_t port_attr_show(struct kobject *kobj, 401c1e7e466SJack Morgenstein struct attribute *attr, char *buf) 402c1e7e466SJack Morgenstein { 403c1e7e466SJack Morgenstein struct port_attribute *port_attr = 404c1e7e466SJack Morgenstein container_of(attr, struct port_attribute, attr); 405c1e7e466SJack Morgenstein struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj); 406c1e7e466SJack Morgenstein 407c1e7e466SJack Morgenstein if (!port_attr->show) 408c1e7e466SJack Morgenstein return -EIO; 409c1e7e466SJack Morgenstein return port_attr->show(p, port_attr, buf); 410c1e7e466SJack Morgenstein } 411c1e7e466SJack Morgenstein 412c1e7e466SJack Morgenstein static ssize_t port_attr_store(struct kobject *kobj, 413c1e7e466SJack Morgenstein struct attribute *attr, 414c1e7e466SJack Morgenstein const char *buf, size_t size) 415c1e7e466SJack Morgenstein { 416c1e7e466SJack Morgenstein struct port_attribute *port_attr = 417c1e7e466SJack Morgenstein container_of(attr, struct port_attribute, attr); 418c1e7e466SJack Morgenstein struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj); 419c1e7e466SJack Morgenstein 420c1e7e466SJack Morgenstein if (!port_attr->store) 421c1e7e466SJack Morgenstein return -EIO; 422c1e7e466SJack Morgenstein return port_attr->store(p, port_attr, buf, size); 423c1e7e466SJack Morgenstein } 424c1e7e466SJack Morgenstein 425c1e7e466SJack Morgenstein static const struct sysfs_ops port_sysfs_ops = { 426c1e7e466SJack Morgenstein .show = port_attr_show, 427c1e7e466SJack Morgenstein .store = port_attr_store, 428c1e7e466SJack Morgenstein }; 429c1e7e466SJack Morgenstein 430c1e7e466SJack Morgenstein static struct kobj_type port_type = { 431c1e7e466SJack Morgenstein .release = mlx4_port_release, 432c1e7e466SJack Morgenstein .sysfs_ops = &port_sysfs_ops, 433c1e7e466SJack Morgenstein }; 434c1e7e466SJack Morgenstein 435c1e7e466SJack Morgenstein struct port_table_attribute { 436c1e7e466SJack Morgenstein struct port_attribute attr; 437c1e7e466SJack Morgenstein char name[8]; 438c1e7e466SJack Morgenstein int index; 439c1e7e466SJack Morgenstein }; 440c1e7e466SJack Morgenstein 441c1e7e466SJack Morgenstein static ssize_t show_port_pkey(struct mlx4_port *p, struct port_attribute *attr, 442c1e7e466SJack Morgenstein char *buf) 443c1e7e466SJack Morgenstein { 444c1e7e466SJack Morgenstein struct port_table_attribute *tab_attr = 445c1e7e466SJack Morgenstein container_of(attr, struct port_table_attribute, attr); 446*e28bf1f0SJoe Perches struct pkey_mgt *m = &p->dev->pkeys; 447*e28bf1f0SJoe Perches u8 key = m->virt2phys_pkey[p->slave][p->port_num - 1][tab_attr->index]; 448c1e7e466SJack Morgenstein 449*e28bf1f0SJoe Perches if (key >= p->dev->dev->caps.pkey_table_len[p->port_num]) 450*e28bf1f0SJoe Perches return sysfs_emit(buf, "none\n"); 451*e28bf1f0SJoe Perches return sysfs_emit(buf, "%d\n", key); 452c1e7e466SJack Morgenstein } 453c1e7e466SJack Morgenstein 454c1e7e466SJack Morgenstein static ssize_t store_port_pkey(struct mlx4_port *p, struct port_attribute *attr, 455c1e7e466SJack Morgenstein const char *buf, size_t count) 456c1e7e466SJack Morgenstein { 457c1e7e466SJack Morgenstein struct port_table_attribute *tab_attr = 458c1e7e466SJack Morgenstein container_of(attr, struct port_table_attribute, attr); 459c1e7e466SJack Morgenstein int idx; 460c1e7e466SJack Morgenstein int err; 461c1e7e466SJack Morgenstein 462c1e7e466SJack Morgenstein /* do not allow remapping Dom0 virtual pkey table */ 463c1e7e466SJack Morgenstein if (p->slave == mlx4_master_func_num(p->dev->dev)) 464c1e7e466SJack Morgenstein return -EINVAL; 465c1e7e466SJack Morgenstein 466c1e7e466SJack Morgenstein if (!strncasecmp(buf, "no", 2)) 467c1e7e466SJack Morgenstein idx = p->dev->dev->phys_caps.pkey_phys_table_len[p->port_num] - 1; 468c1e7e466SJack Morgenstein else if (sscanf(buf, "%i", &idx) != 1 || 469c1e7e466SJack Morgenstein idx >= p->dev->dev->caps.pkey_table_len[p->port_num] || 470c1e7e466SJack Morgenstein idx < 0) 471c1e7e466SJack Morgenstein return -EINVAL; 472c1e7e466SJack Morgenstein 473c1e7e466SJack Morgenstein p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1] 474c1e7e466SJack Morgenstein [tab_attr->index] = idx; 475c1e7e466SJack Morgenstein mlx4_sync_pkey_table(p->dev->dev, p->slave, p->port_num, 476c1e7e466SJack Morgenstein tab_attr->index, idx); 477c1e7e466SJack Morgenstein err = mlx4_gen_pkey_eqe(p->dev->dev, p->slave, p->port_num); 478c1e7e466SJack Morgenstein if (err) { 479c1e7e466SJack Morgenstein pr_err("mlx4_gen_pkey_eqe failed for slave %d," 480c1e7e466SJack Morgenstein " port %d, index %d\n", p->slave, p->port_num, idx); 481c1e7e466SJack Morgenstein return err; 482c1e7e466SJack Morgenstein } 483c1e7e466SJack Morgenstein return count; 484c1e7e466SJack Morgenstein } 485c1e7e466SJack Morgenstein 486c1e7e466SJack Morgenstein static ssize_t show_port_gid_idx(struct mlx4_port *p, 487c1e7e466SJack Morgenstein struct port_attribute *attr, char *buf) 488c1e7e466SJack Morgenstein { 489*e28bf1f0SJoe Perches return sysfs_emit(buf, "%d\n", p->slave); 490c1e7e466SJack Morgenstein } 491c1e7e466SJack Morgenstein 492c1e7e466SJack Morgenstein static struct attribute ** 493c1e7e466SJack Morgenstein alloc_group_attrs(ssize_t (*show)(struct mlx4_port *, 494c1e7e466SJack Morgenstein struct port_attribute *, char *buf), 495c1e7e466SJack Morgenstein ssize_t (*store)(struct mlx4_port *, struct port_attribute *, 496c1e7e466SJack Morgenstein const char *buf, size_t count), 497c1e7e466SJack Morgenstein int len) 498c1e7e466SJack Morgenstein { 499c1e7e466SJack Morgenstein struct attribute **tab_attr; 500c1e7e466SJack Morgenstein struct port_table_attribute *element; 501c1e7e466SJack Morgenstein int i; 502c1e7e466SJack Morgenstein 503c1e7e466SJack Morgenstein tab_attr = kcalloc(1 + len, sizeof (struct attribute *), GFP_KERNEL); 504c1e7e466SJack Morgenstein if (!tab_attr) 505c1e7e466SJack Morgenstein return NULL; 506c1e7e466SJack Morgenstein 507c1e7e466SJack Morgenstein for (i = 0; i < len; i++) { 508c1e7e466SJack Morgenstein element = kzalloc(sizeof (struct port_table_attribute), 509c1e7e466SJack Morgenstein GFP_KERNEL); 510c1e7e466SJack Morgenstein if (!element) 511c1e7e466SJack Morgenstein goto err; 512c1e7e466SJack Morgenstein if (snprintf(element->name, sizeof (element->name), 513c1e7e466SJack Morgenstein "%d", i) >= sizeof (element->name)) { 514c1e7e466SJack Morgenstein kfree(element); 515c1e7e466SJack Morgenstein goto err; 516c1e7e466SJack Morgenstein } 517c1e7e466SJack Morgenstein sysfs_attr_init(&element->attr.attr); 518c1e7e466SJack Morgenstein element->attr.attr.name = element->name; 519c1e7e466SJack Morgenstein if (store) { 520c1e7e466SJack Morgenstein element->attr.attr.mode = S_IWUSR | S_IRUGO; 521c1e7e466SJack Morgenstein element->attr.store = store; 522c1e7e466SJack Morgenstein } else 523c1e7e466SJack Morgenstein element->attr.attr.mode = S_IRUGO; 524c1e7e466SJack Morgenstein 525c1e7e466SJack Morgenstein element->attr.show = show; 526c1e7e466SJack Morgenstein element->index = i; 527c1e7e466SJack Morgenstein tab_attr[i] = &element->attr.attr; 528c1e7e466SJack Morgenstein } 529c1e7e466SJack Morgenstein return tab_attr; 530c1e7e466SJack Morgenstein 531c1e7e466SJack Morgenstein err: 532c1e7e466SJack Morgenstein while (--i >= 0) 533c1e7e466SJack Morgenstein kfree(tab_attr[i]); 534c1e7e466SJack Morgenstein kfree(tab_attr); 535c1e7e466SJack Morgenstein return NULL; 536c1e7e466SJack Morgenstein } 537c1e7e466SJack Morgenstein 53865fed8a8SJack Morgenstein static ssize_t sysfs_show_smi_enabled(struct device *dev, 53965fed8a8SJack Morgenstein struct device_attribute *attr, char *buf) 54065fed8a8SJack Morgenstein { 54165fed8a8SJack Morgenstein struct mlx4_port *p = 54265fed8a8SJack Morgenstein container_of(attr, struct mlx4_port, smi_enabled); 54365fed8a8SJack Morgenstein 54445808361SJoe Perches return sysfs_emit(buf, "%d\n", 54545808361SJoe Perches !!mlx4_vf_smi_enabled(p->dev->dev, p->slave, 54645808361SJoe Perches p->port_num)); 54765fed8a8SJack Morgenstein } 54865fed8a8SJack Morgenstein 54965fed8a8SJack Morgenstein static ssize_t sysfs_show_enable_smi_admin(struct device *dev, 55065fed8a8SJack Morgenstein struct device_attribute *attr, 55165fed8a8SJack Morgenstein char *buf) 55265fed8a8SJack Morgenstein { 55365fed8a8SJack Morgenstein struct mlx4_port *p = 55465fed8a8SJack Morgenstein container_of(attr, struct mlx4_port, enable_smi_admin); 55565fed8a8SJack Morgenstein 55645808361SJoe Perches return sysfs_emit(buf, "%d\n", 55745808361SJoe Perches !!mlx4_vf_get_enable_smi_admin(p->dev->dev, p->slave, 55845808361SJoe Perches p->port_num)); 55965fed8a8SJack Morgenstein } 56065fed8a8SJack Morgenstein 56165fed8a8SJack Morgenstein static ssize_t sysfs_store_enable_smi_admin(struct device *dev, 56265fed8a8SJack Morgenstein struct device_attribute *attr, 56365fed8a8SJack Morgenstein const char *buf, size_t count) 56465fed8a8SJack Morgenstein { 56565fed8a8SJack Morgenstein struct mlx4_port *p = 56665fed8a8SJack Morgenstein container_of(attr, struct mlx4_port, enable_smi_admin); 56765fed8a8SJack Morgenstein int enable; 56865fed8a8SJack Morgenstein 56965fed8a8SJack Morgenstein if (sscanf(buf, "%i", &enable) != 1 || 57065fed8a8SJack Morgenstein enable < 0 || enable > 1) 57165fed8a8SJack Morgenstein return -EINVAL; 57265fed8a8SJack Morgenstein 57365fed8a8SJack Morgenstein if (mlx4_vf_set_enable_smi_admin(p->dev->dev, p->slave, p->port_num, enable)) 57465fed8a8SJack Morgenstein return -EINVAL; 57565fed8a8SJack Morgenstein return count; 57665fed8a8SJack Morgenstein } 57765fed8a8SJack Morgenstein 57865fed8a8SJack Morgenstein static int add_vf_smi_entries(struct mlx4_port *p) 57965fed8a8SJack Morgenstein { 58065fed8a8SJack Morgenstein int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) == 58165fed8a8SJack Morgenstein IB_LINK_LAYER_ETHERNET; 58265fed8a8SJack Morgenstein int ret; 58365fed8a8SJack Morgenstein 58465fed8a8SJack Morgenstein /* do not display entries if eth transport, or if master */ 58565fed8a8SJack Morgenstein if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev)) 58665fed8a8SJack Morgenstein return 0; 58765fed8a8SJack Morgenstein 58865fed8a8SJack Morgenstein sysfs_attr_init(&p->smi_enabled.attr); 58965fed8a8SJack Morgenstein p->smi_enabled.show = sysfs_show_smi_enabled; 59065fed8a8SJack Morgenstein p->smi_enabled.store = NULL; 59165fed8a8SJack Morgenstein p->smi_enabled.attr.name = "smi_enabled"; 59265fed8a8SJack Morgenstein p->smi_enabled.attr.mode = 0444; 59365fed8a8SJack Morgenstein ret = sysfs_create_file(&p->kobj, &p->smi_enabled.attr); 59465fed8a8SJack Morgenstein if (ret) { 59565fed8a8SJack Morgenstein pr_err("failed to create smi_enabled\n"); 59665fed8a8SJack Morgenstein return ret; 59765fed8a8SJack Morgenstein } 59865fed8a8SJack Morgenstein 59965fed8a8SJack Morgenstein sysfs_attr_init(&p->enable_smi_admin.attr); 60065fed8a8SJack Morgenstein p->enable_smi_admin.show = sysfs_show_enable_smi_admin; 60165fed8a8SJack Morgenstein p->enable_smi_admin.store = sysfs_store_enable_smi_admin; 60265fed8a8SJack Morgenstein p->enable_smi_admin.attr.name = "enable_smi_admin"; 60365fed8a8SJack Morgenstein p->enable_smi_admin.attr.mode = 0644; 60465fed8a8SJack Morgenstein ret = sysfs_create_file(&p->kobj, &p->enable_smi_admin.attr); 60565fed8a8SJack Morgenstein if (ret) { 60665fed8a8SJack Morgenstein pr_err("failed to create enable_smi_admin\n"); 60765fed8a8SJack Morgenstein sysfs_remove_file(&p->kobj, &p->smi_enabled.attr); 60865fed8a8SJack Morgenstein return ret; 60965fed8a8SJack Morgenstein } 61065fed8a8SJack Morgenstein return 0; 61165fed8a8SJack Morgenstein } 61265fed8a8SJack Morgenstein 61365fed8a8SJack Morgenstein static void remove_vf_smi_entries(struct mlx4_port *p) 61465fed8a8SJack Morgenstein { 61565fed8a8SJack Morgenstein int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) == 61665fed8a8SJack Morgenstein IB_LINK_LAYER_ETHERNET; 61765fed8a8SJack Morgenstein 61865fed8a8SJack Morgenstein if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev)) 61965fed8a8SJack Morgenstein return; 62065fed8a8SJack Morgenstein 62165fed8a8SJack Morgenstein sysfs_remove_file(&p->kobj, &p->smi_enabled.attr); 62265fed8a8SJack Morgenstein sysfs_remove_file(&p->kobj, &p->enable_smi_admin.attr); 62365fed8a8SJack Morgenstein } 62465fed8a8SJack Morgenstein 625c1e7e466SJack Morgenstein static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) 626c1e7e466SJack Morgenstein { 627c1e7e466SJack Morgenstein struct mlx4_port *p; 628c1e7e466SJack Morgenstein int i; 629c1e7e466SJack Morgenstein int ret; 6302b135db3SJack Morgenstein int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port_num) == 6312b135db3SJack Morgenstein IB_LINK_LAYER_ETHERNET; 632c1e7e466SJack Morgenstein 633c1e7e466SJack Morgenstein p = kzalloc(sizeof *p, GFP_KERNEL); 634c1e7e466SJack Morgenstein if (!p) 635c1e7e466SJack Morgenstein return -ENOMEM; 636c1e7e466SJack Morgenstein 637c1e7e466SJack Morgenstein p->dev = dev; 638c1e7e466SJack Morgenstein p->port_num = port_num; 639c1e7e466SJack Morgenstein p->slave = slave; 640c1e7e466SJack Morgenstein 641c1e7e466SJack Morgenstein ret = kobject_init_and_add(&p->kobj, &port_type, 642c1e7e466SJack Morgenstein kobject_get(dev->dev_ports_parent[slave]), 643c1e7e466SJack Morgenstein "%d", port_num); 644c1e7e466SJack Morgenstein if (ret) 645c1e7e466SJack Morgenstein goto err_alloc; 646c1e7e466SJack Morgenstein 647c1e7e466SJack Morgenstein p->pkey_group.name = "pkey_idx"; 648c1e7e466SJack Morgenstein p->pkey_group.attrs = 6492b135db3SJack Morgenstein alloc_group_attrs(show_port_pkey, 6502b135db3SJack Morgenstein is_eth ? NULL : store_port_pkey, 651c1e7e466SJack Morgenstein dev->dev->caps.pkey_table_len[port_num]); 652af2e2e35SJulia Lawall if (!p->pkey_group.attrs) { 653af2e2e35SJulia Lawall ret = -ENOMEM; 654c1e7e466SJack Morgenstein goto err_alloc; 655af2e2e35SJulia Lawall } 656c1e7e466SJack Morgenstein 657c1e7e466SJack Morgenstein ret = sysfs_create_group(&p->kobj, &p->pkey_group); 658c1e7e466SJack Morgenstein if (ret) 659c1e7e466SJack Morgenstein goto err_free_pkey; 660c1e7e466SJack Morgenstein 661c1e7e466SJack Morgenstein p->gid_group.name = "gid_idx"; 662c1e7e466SJack Morgenstein p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1); 663af2e2e35SJulia Lawall if (!p->gid_group.attrs) { 664af2e2e35SJulia Lawall ret = -ENOMEM; 665c1e7e466SJack Morgenstein goto err_free_pkey; 666af2e2e35SJulia Lawall } 667c1e7e466SJack Morgenstein 668c1e7e466SJack Morgenstein ret = sysfs_create_group(&p->kobj, &p->gid_group); 669c1e7e466SJack Morgenstein if (ret) 670c1e7e466SJack Morgenstein goto err_free_gid; 671c1e7e466SJack Morgenstein 67265fed8a8SJack Morgenstein ret = add_vf_smi_entries(p); 67365fed8a8SJack Morgenstein if (ret) 67465fed8a8SJack Morgenstein goto err_free_gid; 67565fed8a8SJack Morgenstein 676c1e7e466SJack Morgenstein list_add_tail(&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]); 677c1e7e466SJack Morgenstein return 0; 678c1e7e466SJack Morgenstein 679c1e7e466SJack Morgenstein err_free_gid: 680c1e7e466SJack Morgenstein kfree(p->gid_group.attrs[0]); 681c1e7e466SJack Morgenstein kfree(p->gid_group.attrs); 682c1e7e466SJack Morgenstein 683c1e7e466SJack Morgenstein err_free_pkey: 684c1e7e466SJack Morgenstein for (i = 0; i < dev->dev->caps.pkey_table_len[port_num]; ++i) 685c1e7e466SJack Morgenstein kfree(p->pkey_group.attrs[i]); 686c1e7e466SJack Morgenstein kfree(p->pkey_group.attrs); 687c1e7e466SJack Morgenstein 688c1e7e466SJack Morgenstein err_alloc: 689c1e7e466SJack Morgenstein kobject_put(dev->dev_ports_parent[slave]); 690c1e7e466SJack Morgenstein kfree(p); 691c1e7e466SJack Morgenstein return ret; 692c1e7e466SJack Morgenstein } 693c1e7e466SJack Morgenstein 694c1e7e466SJack Morgenstein static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave) 695c1e7e466SJack Morgenstein { 696c1e7e466SJack Morgenstein char name[32]; 697c1e7e466SJack Morgenstein int err; 698c1e7e466SJack Morgenstein int port; 699c1e7e466SJack Morgenstein struct kobject *p, *t; 700c1e7e466SJack Morgenstein struct mlx4_port *mport; 701449fc488SMatan Barak struct mlx4_active_ports actv_ports; 702c1e7e466SJack Morgenstein 703c1e7e466SJack Morgenstein get_name(dev, name, slave, sizeof name); 704c1e7e466SJack Morgenstein 705c1e7e466SJack Morgenstein dev->pkeys.device_parent[slave] = 706c1e7e466SJack Morgenstein kobject_create_and_add(name, kobject_get(dev->iov_parent)); 707c1e7e466SJack Morgenstein 708c1e7e466SJack Morgenstein if (!dev->pkeys.device_parent[slave]) { 709c1e7e466SJack Morgenstein err = -ENOMEM; 710c1e7e466SJack Morgenstein goto fail_dev; 711c1e7e466SJack Morgenstein } 712c1e7e466SJack Morgenstein 713c1e7e466SJack Morgenstein INIT_LIST_HEAD(&dev->pkeys.pkey_port_list[slave]); 714c1e7e466SJack Morgenstein 715c1e7e466SJack Morgenstein dev->dev_ports_parent[slave] = 716c1e7e466SJack Morgenstein kobject_create_and_add("ports", 717c1e7e466SJack Morgenstein kobject_get(dev->pkeys.device_parent[slave])); 718c1e7e466SJack Morgenstein 719c1e7e466SJack Morgenstein if (!dev->dev_ports_parent[slave]) { 720c1e7e466SJack Morgenstein err = -ENOMEM; 721c1e7e466SJack Morgenstein goto err_ports; 722c1e7e466SJack Morgenstein } 723c1e7e466SJack Morgenstein 724449fc488SMatan Barak actv_ports = mlx4_get_active_ports(dev->dev, slave); 725449fc488SMatan Barak 726c1e7e466SJack Morgenstein for (port = 1; port <= dev->dev->caps.num_ports; ++port) { 727449fc488SMatan Barak if (!test_bit(port - 1, actv_ports.ports)) 728449fc488SMatan Barak continue; 729c1e7e466SJack Morgenstein err = add_port(dev, port, slave); 730c1e7e466SJack Morgenstein if (err) 731c1e7e466SJack Morgenstein goto err_add; 732c1e7e466SJack Morgenstein } 733c1e7e466SJack Morgenstein return 0; 734c1e7e466SJack Morgenstein 735c1e7e466SJack Morgenstein err_add: 736c1e7e466SJack Morgenstein list_for_each_entry_safe(p, t, 737c1e7e466SJack Morgenstein &dev->pkeys.pkey_port_list[slave], 738c1e7e466SJack Morgenstein entry) { 739c1e7e466SJack Morgenstein list_del(&p->entry); 740c1e7e466SJack Morgenstein mport = container_of(p, struct mlx4_port, kobj); 741c1e7e466SJack Morgenstein sysfs_remove_group(p, &mport->pkey_group); 742c1e7e466SJack Morgenstein sysfs_remove_group(p, &mport->gid_group); 74365fed8a8SJack Morgenstein remove_vf_smi_entries(mport); 744c1e7e466SJack Morgenstein kobject_put(p); 745c1e7e466SJack Morgenstein } 746c1e7e466SJack Morgenstein kobject_put(dev->dev_ports_parent[slave]); 747c1e7e466SJack Morgenstein 748c1e7e466SJack Morgenstein err_ports: 749c1e7e466SJack Morgenstein kobject_put(dev->pkeys.device_parent[slave]); 750c1e7e466SJack Morgenstein /* extra put for the device_parent create_and_add */ 751c1e7e466SJack Morgenstein kobject_put(dev->pkeys.device_parent[slave]); 752c1e7e466SJack Morgenstein 753c1e7e466SJack Morgenstein fail_dev: 754c1e7e466SJack Morgenstein kobject_put(dev->iov_parent); 755c1e7e466SJack Morgenstein return err; 756c1e7e466SJack Morgenstein } 757c1e7e466SJack Morgenstein 758c1e7e466SJack Morgenstein static int register_pkey_tree(struct mlx4_ib_dev *device) 759c1e7e466SJack Morgenstein { 760c1e7e466SJack Morgenstein int i; 761c1e7e466SJack Morgenstein 762c1e7e466SJack Morgenstein if (!mlx4_is_master(device->dev)) 763c1e7e466SJack Morgenstein return 0; 764c1e7e466SJack Morgenstein 765872bf2fbSYishai Hadas for (i = 0; i <= device->dev->persist->num_vfs; ++i) 766c1e7e466SJack Morgenstein register_one_pkey_tree(device, i); 767c1e7e466SJack Morgenstein 768c1e7e466SJack Morgenstein return 0; 769c1e7e466SJack Morgenstein } 770c1e7e466SJack Morgenstein 771c1e7e466SJack Morgenstein static void unregister_pkey_tree(struct mlx4_ib_dev *device) 772c1e7e466SJack Morgenstein { 773c1e7e466SJack Morgenstein int slave; 774c1e7e466SJack Morgenstein struct kobject *p, *t; 775c1e7e466SJack Morgenstein struct mlx4_port *port; 776c1e7e466SJack Morgenstein 777c1e7e466SJack Morgenstein if (!mlx4_is_master(device->dev)) 778c1e7e466SJack Morgenstein return; 779c1e7e466SJack Morgenstein 780872bf2fbSYishai Hadas for (slave = device->dev->persist->num_vfs; slave >= 0; --slave) { 781c1e7e466SJack Morgenstein list_for_each_entry_safe(p, t, 782c1e7e466SJack Morgenstein &device->pkeys.pkey_port_list[slave], 783c1e7e466SJack Morgenstein entry) { 784c1e7e466SJack Morgenstein list_del(&p->entry); 785c1e7e466SJack Morgenstein port = container_of(p, struct mlx4_port, kobj); 786c1e7e466SJack Morgenstein sysfs_remove_group(p, &port->pkey_group); 787c1e7e466SJack Morgenstein sysfs_remove_group(p, &port->gid_group); 78865fed8a8SJack Morgenstein remove_vf_smi_entries(port); 789c1e7e466SJack Morgenstein kobject_put(p); 790c1e7e466SJack Morgenstein kobject_put(device->dev_ports_parent[slave]); 791c1e7e466SJack Morgenstein } 792c1e7e466SJack Morgenstein kobject_put(device->dev_ports_parent[slave]); 793c1e7e466SJack Morgenstein kobject_put(device->pkeys.device_parent[slave]); 794c1e7e466SJack Morgenstein kobject_put(device->pkeys.device_parent[slave]); 795c1e7e466SJack Morgenstein kobject_put(device->iov_parent); 796c1e7e466SJack Morgenstein } 797c1e7e466SJack Morgenstein } 798c1e7e466SJack Morgenstein 799c1e7e466SJack Morgenstein int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *dev) 800c1e7e466SJack Morgenstein { 801c1e7e466SJack Morgenstein int i; 802c1e7e466SJack Morgenstein int ret = 0; 803c1e7e466SJack Morgenstein 804c1e7e466SJack Morgenstein if (!mlx4_is_master(dev->dev)) 805c1e7e466SJack Morgenstein return 0; 806c1e7e466SJack Morgenstein 80760f1fc20SParav Pandit dev->iov_parent = kobject_create_and_add("iov", &dev->ib_dev.dev.kobj); 808c1e7e466SJack Morgenstein if (!dev->iov_parent) { 809c1e7e466SJack Morgenstein ret = -ENOMEM; 810c1e7e466SJack Morgenstein goto err; 811c1e7e466SJack Morgenstein } 812c1e7e466SJack Morgenstein dev->ports_parent = 813c1e7e466SJack Morgenstein kobject_create_and_add("ports", 814c1e7e466SJack Morgenstein kobject_get(dev->iov_parent)); 8156950a235SJulia Lawall if (!dev->ports_parent) { 816c1e7e466SJack Morgenstein ret = -ENOMEM; 817c1e7e466SJack Morgenstein goto err_ports; 818c1e7e466SJack Morgenstein } 819c1e7e466SJack Morgenstein 820c1e7e466SJack Morgenstein for (i = 1; i <= dev->ib_dev.phys_port_cnt; ++i) { 821c1e7e466SJack Morgenstein ret = add_port_entries(dev, i); 822c1e7e466SJack Morgenstein if (ret) 823c1e7e466SJack Morgenstein goto err_add_entries; 824c1e7e466SJack Morgenstein } 825c1e7e466SJack Morgenstein 826c1e7e466SJack Morgenstein ret = register_pkey_tree(dev); 827c1e7e466SJack Morgenstein if (ret) 828c1e7e466SJack Morgenstein goto err_add_entries; 829c1e7e466SJack Morgenstein return 0; 830c1e7e466SJack Morgenstein 831c1e7e466SJack Morgenstein err_add_entries: 832c1e7e466SJack Morgenstein kobject_put(dev->ports_parent); 833c1e7e466SJack Morgenstein 834c1e7e466SJack Morgenstein err_ports: 835c1e7e466SJack Morgenstein kobject_put(dev->iov_parent); 836c1e7e466SJack Morgenstein err: 837c1e7e466SJack Morgenstein pr_err("mlx4_ib_device_register_sysfs error (%d)\n", ret); 838c1e7e466SJack Morgenstein return ret; 839c1e7e466SJack Morgenstein } 840c1e7e466SJack Morgenstein 841c1e7e466SJack Morgenstein static void unregister_alias_guid_tree(struct mlx4_ib_dev *device) 842c1e7e466SJack Morgenstein { 843c1e7e466SJack Morgenstein struct mlx4_ib_iov_port *p; 844c1e7e466SJack Morgenstein int i; 845c1e7e466SJack Morgenstein 846c1e7e466SJack Morgenstein if (!mlx4_is_master(device->dev)) 847c1e7e466SJack Morgenstein return; 848c1e7e466SJack Morgenstein 849c1e7e466SJack Morgenstein for (i = 0; i < device->dev->caps.num_ports; i++) { 850c1e7e466SJack Morgenstein p = &device->iov_ports[i]; 851c1e7e466SJack Morgenstein kobject_put(p->admin_alias_parent); 852c1e7e466SJack Morgenstein kobject_put(p->gids_parent); 853c1e7e466SJack Morgenstein kobject_put(p->pkeys_parent); 854c1e7e466SJack Morgenstein kobject_put(p->mcgs_parent); 855c1e7e466SJack Morgenstein kobject_put(p->cur_port); 856c1e7e466SJack Morgenstein kobject_put(p->cur_port); 857c1e7e466SJack Morgenstein kobject_put(p->cur_port); 858c1e7e466SJack Morgenstein kobject_put(p->cur_port); 859c1e7e466SJack Morgenstein kobject_put(p->cur_port); 860c1e7e466SJack Morgenstein kobject_put(p->dev->ports_parent); 861c1e7e466SJack Morgenstein kfree(p->dentr_ar); 862c1e7e466SJack Morgenstein } 863c1e7e466SJack Morgenstein } 864c1e7e466SJack Morgenstein 865c1e7e466SJack Morgenstein void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device) 866c1e7e466SJack Morgenstein { 867c1e7e466SJack Morgenstein unregister_alias_guid_tree(device); 868c1e7e466SJack Morgenstein unregister_pkey_tree(device); 869c1e7e466SJack Morgenstein kobject_put(device->ports_parent); 870c1e7e466SJack Morgenstein kobject_put(device->iov_parent); 871c1e7e466SJack Morgenstein kobject_put(device->iov_parent); 872c1e7e466SJack Morgenstein } 873