Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2012 Mellanox Technologies.  All rights reserved.
0003  *
0004  * This software is available to you under a choice of one of two
0005  * licenses.  You may choose to be licensed under the terms of the GNU
0006  * General Public License (GPL) Version 2, available from the file
0007  * COPYING in the main directory of this source tree, or the
0008  * OpenIB.org BSD license below:
0009  *
0010  *     Redistribution and use in source and binary forms, with or
0011  *     without modification, are permitted provided that the following
0012  *     conditions are met:
0013  *
0014  *      - Redistributions of source code must retain the above
0015  *        copyright notice, this list of conditions and the following
0016  *        disclaimer.
0017  *
0018  *      - Redistributions in binary form must reproduce the above
0019  *        copyright notice, this list of conditions and the following
0020  *        disclaimer in the documentation and/or other materials
0021  *        provided with the distribution.
0022  *
0023  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0024  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0025  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0026  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0027  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0028  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0029  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0030  * SOFTWARE.
0031  */
0032 
0033 /*#include "core_priv.h"*/
0034 #include "mlx4_ib.h"
0035 #include <linux/slab.h>
0036 #include <linux/string.h>
0037 #include <linux/stat.h>
0038 
0039 #include <rdma/ib_mad.h>
0040 /*show_admin_alias_guid returns the administratively assigned value of that GUID.
0041  * Values returned in buf parameter string:
0042  *  0           - requests opensm to assign a value.
0043  *  ffffffffffffffff    - delete this entry.
0044  *  other           - value assigned by administrator.
0045  */
0046 static ssize_t show_admin_alias_guid(struct device *dev,
0047                   struct device_attribute *attr, char *buf)
0048 {
0049     struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
0050         container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
0051     struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
0052     struct mlx4_ib_dev *mdev = port->dev;
0053     __be64 sysadmin_ag_val;
0054 
0055     sysadmin_ag_val = mlx4_get_admin_guid(mdev->dev,
0056                           mlx4_ib_iov_dentry->entry_num,
0057                           port->num);
0058 
0059     return sysfs_emit(buf, "%llx\n", be64_to_cpu(sysadmin_ag_val));
0060 }
0061 
0062 /* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.
0063  * Values in buf parameter string:
0064  *  0           - requests opensm to assign a value.
0065  *  0xffffffffffffffff  - delete this entry.
0066  *  other           - guid value assigned by the administrator.
0067  */
0068 static ssize_t store_admin_alias_guid(struct device *dev,
0069                       struct device_attribute *attr,
0070                       const char *buf, size_t count)
0071 {
0072     int record_num;/*0-15*/
0073     int guid_index_in_rec; /*0 - 7*/
0074     struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
0075         container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
0076     struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
0077     struct mlx4_ib_dev *mdev = port->dev;
0078     u64 sysadmin_ag_val;
0079     unsigned long flags;
0080 
0081     record_num = mlx4_ib_iov_dentry->entry_num / 8;
0082     guid_index_in_rec = mlx4_ib_iov_dentry->entry_num % 8;
0083     if (0 == record_num && 0 == guid_index_in_rec) {
0084         pr_err("GUID 0 block 0 is RO\n");
0085         return count;
0086     }
0087     spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags);
0088     sscanf(buf, "%llx", &sysadmin_ag_val);
0089     *(__be64 *)&mdev->sriov.alias_guid.ports_guid[port->num - 1].
0090         all_rec_per_port[record_num].
0091         all_recs[GUID_REC_SIZE * guid_index_in_rec] =
0092             cpu_to_be64(sysadmin_ag_val);
0093 
0094     /* Change the state to be pending for update */
0095     mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].status
0096         = MLX4_GUID_INFO_STATUS_IDLE ;
0097     mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val),
0098                 mlx4_ib_iov_dentry->entry_num,
0099                 port->num);
0100 
0101     /* set the record index */
0102     mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
0103         |= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);
0104 
0105     spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags);
0106     mlx4_ib_init_alias_guid_work(mdev, port->num - 1);
0107 
0108     return count;
0109 }
0110 
0111 static ssize_t show_port_gid(struct device *dev,
0112                  struct device_attribute *attr,
0113                  char *buf)
0114 {
0115     struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
0116         container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
0117     struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
0118     struct mlx4_ib_dev *mdev = port->dev;
0119     union ib_gid gid;
0120     int ret;
0121     __be16 *raw;
0122 
0123     ret = __mlx4_ib_query_gid(&mdev->ib_dev, port->num,
0124                   mlx4_ib_iov_dentry->entry_num, &gid, 1);
0125     if (ret)
0126         return ret;
0127 
0128     raw = (__be16 *)gid.raw;
0129     return sysfs_emit(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
0130               be16_to_cpu(raw[0]),
0131               be16_to_cpu(raw[1]),
0132               be16_to_cpu(raw[2]),
0133               be16_to_cpu(raw[3]),
0134               be16_to_cpu(raw[4]),
0135               be16_to_cpu(raw[5]),
0136               be16_to_cpu(raw[6]),
0137               be16_to_cpu(raw[7]));
0138 }
0139 
0140 static ssize_t show_phys_port_pkey(struct device *dev,
0141                    struct device_attribute *attr,
0142                    char *buf)
0143 {
0144     struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
0145         container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
0146     struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
0147     struct mlx4_ib_dev *mdev = port->dev;
0148     u16 pkey;
0149     ssize_t ret;
0150 
0151     ret = __mlx4_ib_query_pkey(&mdev->ib_dev, port->num,
0152                    mlx4_ib_iov_dentry->entry_num, &pkey, 1);
0153     if (ret)
0154         return ret;
0155 
0156     return sysfs_emit(buf, "0x%04x\n", pkey);
0157 }
0158 
0159 #define DENTRY_REMOVE(_dentry)                      \
0160 do {                                    \
0161     sysfs_remove_file((_dentry)->kobj, &(_dentry)->dentry.attr);    \
0162 } while (0);
0163 
0164 static int create_sysfs_entry(void *_ctx, struct mlx4_ib_iov_sysfs_attr *_dentry,
0165                   char *_name, struct kobject *_kobj,
0166                   ssize_t (*show)(struct device *dev,
0167                           struct device_attribute *attr,
0168                           char *buf),
0169                   ssize_t (*store)(struct device *dev,
0170                            struct device_attribute *attr,
0171                            const char *buf, size_t count)
0172                   )
0173 {
0174     int ret = 0;
0175     struct mlx4_ib_iov_sysfs_attr *vdentry = _dentry;
0176 
0177     vdentry->ctx = _ctx;
0178     vdentry->dentry.show = show;
0179     vdentry->dentry.store = store;
0180     sysfs_attr_init(&vdentry->dentry.attr);
0181     vdentry->dentry.attr.name = vdentry->name;
0182     vdentry->dentry.attr.mode = 0;
0183     vdentry->kobj = _kobj;
0184     snprintf(vdentry->name, 15, "%s", _name);
0185 
0186     if (vdentry->dentry.store)
0187         vdentry->dentry.attr.mode |= S_IWUSR;
0188 
0189     if (vdentry->dentry.show)
0190         vdentry->dentry.attr.mode |= S_IRUGO;
0191 
0192     ret = sysfs_create_file(vdentry->kobj, &vdentry->dentry.attr);
0193     if (ret) {
0194         pr_err("failed to create %s\n", vdentry->dentry.attr.name);
0195         vdentry->ctx = NULL;
0196         return ret;
0197     }
0198 
0199     return ret;
0200 }
0201 
0202 int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
0203         struct attribute *attr)
0204 {
0205     struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];
0206     int ret;
0207 
0208     ret = sysfs_create_file(port->mcgs_parent, attr);
0209     if (ret)
0210         pr_err("failed to create %s\n", attr->name);
0211 
0212     return ret;
0213 }
0214 
0215 void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
0216         struct attribute *attr)
0217 {
0218     struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];
0219 
0220     sysfs_remove_file(port->mcgs_parent, attr);
0221 }
0222 
0223 static int add_port_entries(struct mlx4_ib_dev *device, int port_num)
0224 {
0225     int i;
0226     char buff[11];
0227     struct mlx4_ib_iov_port *port = NULL;
0228     int ret = 0 ;
0229     struct ib_port_attr attr;
0230 
0231     memset(&attr, 0, sizeof(attr));
0232     /* get the physical gid and pkey table sizes.*/
0233     ret = __mlx4_ib_query_port(&device->ib_dev, port_num, &attr, 1);
0234     if (ret)
0235         goto err;
0236 
0237     port = &device->iov_ports[port_num - 1];
0238     port->dev = device;
0239     port->num = port_num;
0240     /* Directory structure:
0241      * iov -
0242      *   port num -
0243      *  admin_guids
0244      *  gids (operational)
0245      *  mcg_table
0246      */
0247     port->dentr_ar = kzalloc(sizeof (struct mlx4_ib_iov_sysfs_attr_ar),
0248                  GFP_KERNEL);
0249     if (!port->dentr_ar) {
0250         ret = -ENOMEM;
0251         goto err;
0252     }
0253     sprintf(buff, "%d", port_num);
0254     port->cur_port = kobject_create_and_add(buff,
0255                  kobject_get(device->ports_parent));
0256     if (!port->cur_port) {
0257         ret = -ENOMEM;
0258         goto kobj_create_err;
0259     }
0260     /* admin GUIDs */
0261     port->admin_alias_parent = kobject_create_and_add("admin_guids",
0262                           kobject_get(port->cur_port));
0263     if (!port->admin_alias_parent) {
0264         ret = -ENOMEM;
0265         goto err_admin_guids;
0266     }
0267     for (i = 0 ; i < attr.gid_tbl_len; i++) {
0268         sprintf(buff, "%d", i);
0269         port->dentr_ar->dentries[i].entry_num = i;
0270         ret = create_sysfs_entry(port, &port->dentr_ar->dentries[i],
0271                       buff, port->admin_alias_parent,
0272                       show_admin_alias_guid, store_admin_alias_guid);
0273         if (ret)
0274             goto err_admin_alias_parent;
0275     }
0276 
0277     /* gids subdirectory (operational gids) */
0278     port->gids_parent = kobject_create_and_add("gids",
0279                           kobject_get(port->cur_port));
0280     if (!port->gids_parent) {
0281         ret = -ENOMEM;
0282         goto err_gids;
0283     }
0284 
0285     for (i = 0 ; i < attr.gid_tbl_len; i++) {
0286         sprintf(buff, "%d", i);
0287         port->dentr_ar->dentries[attr.gid_tbl_len + i].entry_num = i;
0288         ret = create_sysfs_entry(port,
0289                      &port->dentr_ar->dentries[attr.gid_tbl_len + i],
0290                      buff,
0291                      port->gids_parent, show_port_gid, NULL);
0292         if (ret)
0293             goto err_gids_parent;
0294     }
0295 
0296     /* physical port pkey table */
0297     port->pkeys_parent =
0298         kobject_create_and_add("pkeys", kobject_get(port->cur_port));
0299     if (!port->pkeys_parent) {
0300         ret = -ENOMEM;
0301         goto err_pkeys;
0302     }
0303 
0304     for (i = 0 ; i < attr.pkey_tbl_len; i++) {
0305         sprintf(buff, "%d", i);
0306         port->dentr_ar->dentries[2 * attr.gid_tbl_len + i].entry_num = i;
0307         ret = create_sysfs_entry(port,
0308                      &port->dentr_ar->dentries[2 * attr.gid_tbl_len + i],
0309                      buff, port->pkeys_parent,
0310                      show_phys_port_pkey, NULL);
0311         if (ret)
0312             goto err_pkeys_parent;
0313     }
0314 
0315     /* MCGs table */
0316     port->mcgs_parent =
0317         kobject_create_and_add("mcgs", kobject_get(port->cur_port));
0318     if (!port->mcgs_parent) {
0319         ret = -ENOMEM;
0320         goto err_mcgs;
0321     }
0322     return 0;
0323 
0324 err_mcgs:
0325     kobject_put(port->cur_port);
0326 
0327 err_pkeys_parent:
0328     kobject_put(port->pkeys_parent);
0329 
0330 err_pkeys:
0331     kobject_put(port->cur_port);
0332 
0333 err_gids_parent:
0334     kobject_put(port->gids_parent);
0335 
0336 err_gids:
0337     kobject_put(port->cur_port);
0338 
0339 err_admin_alias_parent:
0340     kobject_put(port->admin_alias_parent);
0341 
0342 err_admin_guids:
0343     kobject_put(port->cur_port);
0344     kobject_put(port->cur_port); /* once more for create_and_add buff */
0345 
0346 kobj_create_err:
0347     kobject_put(device->ports_parent);
0348     kfree(port->dentr_ar);
0349 
0350 err:
0351     pr_err("add_port_entries FAILED: for port:%d, error: %d\n",
0352            port_num, ret);
0353     return ret;
0354 }
0355 
0356 static void get_name(struct mlx4_ib_dev *dev, char *name, int i, int max)
0357 {
0358     /* pci_name format is: bus:dev:func -> xxxx:yy:zz.n
0359      * with no ARI only 3 last bits are used so when the fn is higher than 8
0360      * need to add it to the dev num, so count in the last number will be
0361      * modulo 8 */
0362     snprintf(name, max, "%.8s%.2d.%d", pci_name(dev->dev->persist->pdev),
0363          i / 8, i % 8);
0364 }
0365 
0366 struct mlx4_port {
0367     struct kobject         kobj;
0368     struct mlx4_ib_dev    *dev;
0369     struct attribute_group pkey_group;
0370     struct attribute_group gid_group;
0371     struct device_attribute enable_smi_admin;
0372     struct device_attribute smi_enabled;
0373     int            slave;
0374     u8                     port_num;
0375 };
0376 
0377 
0378 static void mlx4_port_release(struct kobject *kobj)
0379 {
0380     struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
0381     struct attribute *a;
0382     int i;
0383 
0384     for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
0385         kfree(a);
0386     kfree(p->pkey_group.attrs);
0387     for (i = 0; (a = p->gid_group.attrs[i]); ++i)
0388         kfree(a);
0389     kfree(p->gid_group.attrs);
0390     kfree(p);
0391 }
0392 
0393 struct port_attribute {
0394     struct attribute attr;
0395     ssize_t (*show)(struct mlx4_port *, struct port_attribute *, char *buf);
0396     ssize_t (*store)(struct mlx4_port *, struct port_attribute *,
0397              const char *buf, size_t count);
0398 };
0399 
0400 static ssize_t port_attr_show(struct kobject *kobj,
0401                   struct attribute *attr, char *buf)
0402 {
0403     struct port_attribute *port_attr =
0404         container_of(attr, struct port_attribute, attr);
0405     struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
0406 
0407     if (!port_attr->show)
0408         return -EIO;
0409     return port_attr->show(p, port_attr, buf);
0410 }
0411 
0412 static ssize_t port_attr_store(struct kobject *kobj,
0413                    struct attribute *attr,
0414                    const char *buf, size_t size)
0415 {
0416     struct port_attribute *port_attr =
0417         container_of(attr, struct port_attribute, attr);
0418     struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
0419 
0420     if (!port_attr->store)
0421         return -EIO;
0422     return port_attr->store(p, port_attr, buf, size);
0423 }
0424 
0425 static const struct sysfs_ops port_sysfs_ops = {
0426     .show = port_attr_show,
0427     .store = port_attr_store,
0428 };
0429 
0430 static struct kobj_type port_type = {
0431     .release    = mlx4_port_release,
0432     .sysfs_ops  = &port_sysfs_ops,
0433 };
0434 
0435 struct port_table_attribute {
0436     struct port_attribute   attr;
0437     char            name[8];
0438     int         index;
0439 };
0440 
0441 static ssize_t show_port_pkey(struct mlx4_port *p, struct port_attribute *attr,
0442                   char *buf)
0443 {
0444     struct port_table_attribute *tab_attr =
0445         container_of(attr, struct port_table_attribute, attr);
0446     struct pkey_mgt *m = &p->dev->pkeys;
0447     u8 key = m->virt2phys_pkey[p->slave][p->port_num - 1][tab_attr->index];
0448 
0449     if (key >= p->dev->dev->caps.pkey_table_len[p->port_num])
0450         return sysfs_emit(buf, "none\n");
0451     return sysfs_emit(buf, "%d\n", key);
0452 }
0453 
0454 static ssize_t store_port_pkey(struct mlx4_port *p, struct port_attribute *attr,
0455                    const char *buf, size_t count)
0456 {
0457     struct port_table_attribute *tab_attr =
0458         container_of(attr, struct port_table_attribute, attr);
0459     int idx;
0460     int err;
0461 
0462     /* do not allow remapping Dom0 virtual pkey table */
0463     if (p->slave == mlx4_master_func_num(p->dev->dev))
0464         return -EINVAL;
0465 
0466     if (!strncasecmp(buf, "no", 2))
0467         idx = p->dev->dev->phys_caps.pkey_phys_table_len[p->port_num] - 1;
0468     else if (sscanf(buf, "%i", &idx) != 1 ||
0469          idx >= p->dev->dev->caps.pkey_table_len[p->port_num] ||
0470          idx < 0)
0471         return -EINVAL;
0472 
0473     p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1]
0474                     [tab_attr->index] = idx;
0475     mlx4_sync_pkey_table(p->dev->dev, p->slave, p->port_num,
0476                  tab_attr->index, idx);
0477     err = mlx4_gen_pkey_eqe(p->dev->dev, p->slave, p->port_num);
0478     if (err) {
0479         pr_err("mlx4_gen_pkey_eqe failed for slave %d,"
0480                " port %d, index %d\n", p->slave, p->port_num, idx);
0481         return err;
0482     }
0483     return count;
0484 }
0485 
0486 static ssize_t show_port_gid_idx(struct mlx4_port *p,
0487                  struct port_attribute *attr, char *buf)
0488 {
0489     return sysfs_emit(buf, "%d\n", p->slave);
0490 }
0491 
0492 static struct attribute **
0493 alloc_group_attrs(ssize_t (*show)(struct mlx4_port *,
0494                   struct port_attribute *, char *buf),
0495           ssize_t (*store)(struct mlx4_port *, struct port_attribute *,
0496                    const char *buf, size_t count),
0497           int len)
0498 {
0499     struct attribute **tab_attr;
0500     struct port_table_attribute *element;
0501     int i;
0502 
0503     tab_attr = kcalloc(1 + len, sizeof (struct attribute *), GFP_KERNEL);
0504     if (!tab_attr)
0505         return NULL;
0506 
0507     for (i = 0; i < len; i++) {
0508         element = kzalloc(sizeof (struct port_table_attribute),
0509                   GFP_KERNEL);
0510         if (!element)
0511             goto err;
0512         if (snprintf(element->name, sizeof (element->name),
0513                  "%d", i) >= sizeof (element->name)) {
0514             kfree(element);
0515             goto err;
0516         }
0517         sysfs_attr_init(&element->attr.attr);
0518         element->attr.attr.name  = element->name;
0519         if (store) {
0520             element->attr.attr.mode  = S_IWUSR | S_IRUGO;
0521             element->attr.store  = store;
0522         } else
0523             element->attr.attr.mode  = S_IRUGO;
0524 
0525         element->attr.show       = show;
0526         element->index       = i;
0527         tab_attr[i] = &element->attr.attr;
0528     }
0529     return tab_attr;
0530 
0531 err:
0532     while (--i >= 0)
0533         kfree(tab_attr[i]);
0534     kfree(tab_attr);
0535     return NULL;
0536 }
0537 
0538 static ssize_t sysfs_show_smi_enabled(struct device *dev,
0539                       struct device_attribute *attr, char *buf)
0540 {
0541     struct mlx4_port *p =
0542         container_of(attr, struct mlx4_port, smi_enabled);
0543 
0544     return sysfs_emit(buf, "%d\n",
0545               !!mlx4_vf_smi_enabled(p->dev->dev, p->slave,
0546                         p->port_num));
0547 }
0548 
0549 static ssize_t sysfs_show_enable_smi_admin(struct device *dev,
0550                        struct device_attribute *attr,
0551                        char *buf)
0552 {
0553     struct mlx4_port *p =
0554         container_of(attr, struct mlx4_port, enable_smi_admin);
0555 
0556     return sysfs_emit(buf, "%d\n",
0557               !!mlx4_vf_get_enable_smi_admin(p->dev->dev, p->slave,
0558                              p->port_num));
0559 }
0560 
0561 static ssize_t sysfs_store_enable_smi_admin(struct device *dev,
0562                         struct device_attribute *attr,
0563                         const char *buf, size_t count)
0564 {
0565     struct mlx4_port *p =
0566         container_of(attr, struct mlx4_port, enable_smi_admin);
0567     int enable;
0568 
0569     if (sscanf(buf, "%i", &enable) != 1 ||
0570         enable < 0 || enable > 1)
0571         return -EINVAL;
0572 
0573     if (mlx4_vf_set_enable_smi_admin(p->dev->dev, p->slave, p->port_num, enable))
0574         return -EINVAL;
0575     return count;
0576 }
0577 
0578 static int add_vf_smi_entries(struct mlx4_port *p)
0579 {
0580     int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) ==
0581             IB_LINK_LAYER_ETHERNET;
0582     int ret;
0583 
0584     /* do not display entries if eth transport, or if master */
0585     if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev))
0586         return 0;
0587 
0588     sysfs_attr_init(&p->smi_enabled.attr);
0589     p->smi_enabled.show = sysfs_show_smi_enabled;
0590     p->smi_enabled.store = NULL;
0591     p->smi_enabled.attr.name = "smi_enabled";
0592     p->smi_enabled.attr.mode = 0444;
0593     ret = sysfs_create_file(&p->kobj, &p->smi_enabled.attr);
0594     if (ret) {
0595         pr_err("failed to create smi_enabled\n");
0596         return ret;
0597     }
0598 
0599     sysfs_attr_init(&p->enable_smi_admin.attr);
0600     p->enable_smi_admin.show = sysfs_show_enable_smi_admin;
0601     p->enable_smi_admin.store = sysfs_store_enable_smi_admin;
0602     p->enable_smi_admin.attr.name = "enable_smi_admin";
0603     p->enable_smi_admin.attr.mode = 0644;
0604     ret = sysfs_create_file(&p->kobj, &p->enable_smi_admin.attr);
0605     if (ret) {
0606         pr_err("failed to create enable_smi_admin\n");
0607         sysfs_remove_file(&p->kobj, &p->smi_enabled.attr);
0608         return ret;
0609     }
0610     return 0;
0611 }
0612 
0613 static void remove_vf_smi_entries(struct mlx4_port *p)
0614 {
0615     int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) ==
0616             IB_LINK_LAYER_ETHERNET;
0617 
0618     if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev))
0619         return;
0620 
0621     sysfs_remove_file(&p->kobj, &p->smi_enabled.attr);
0622     sysfs_remove_file(&p->kobj, &p->enable_smi_admin.attr);
0623 }
0624 
0625 static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)
0626 {
0627     struct mlx4_port *p;
0628     int i;
0629     int ret;
0630     int is_eth = rdma_port_get_link_layer(&dev->ib_dev, port_num) ==
0631             IB_LINK_LAYER_ETHERNET;
0632 
0633     p = kzalloc(sizeof *p, GFP_KERNEL);
0634     if (!p)
0635         return -ENOMEM;
0636 
0637     p->dev = dev;
0638     p->port_num = port_num;
0639     p->slave = slave;
0640 
0641     ret = kobject_init_and_add(&p->kobj, &port_type,
0642                    kobject_get(dev->dev_ports_parent[slave]),
0643                    "%d", port_num);
0644     if (ret)
0645         goto err_alloc;
0646 
0647     p->pkey_group.name  = "pkey_idx";
0648     p->pkey_group.attrs =
0649         alloc_group_attrs(show_port_pkey,
0650                   is_eth ? NULL : store_port_pkey,
0651                   dev->dev->caps.pkey_table_len[port_num]);
0652     if (!p->pkey_group.attrs) {
0653         ret = -ENOMEM;
0654         goto err_alloc;
0655     }
0656 
0657     ret = sysfs_create_group(&p->kobj, &p->pkey_group);
0658     if (ret)
0659         goto err_free_pkey;
0660 
0661     p->gid_group.name  = "gid_idx";
0662     p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1);
0663     if (!p->gid_group.attrs) {
0664         ret = -ENOMEM;
0665         goto err_free_pkey;
0666     }
0667 
0668     ret = sysfs_create_group(&p->kobj, &p->gid_group);
0669     if (ret)
0670         goto err_free_gid;
0671 
0672     ret = add_vf_smi_entries(p);
0673     if (ret)
0674         goto err_free_gid;
0675 
0676     list_add_tail(&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]);
0677     return 0;
0678 
0679 err_free_gid:
0680     kfree(p->gid_group.attrs[0]);
0681     kfree(p->gid_group.attrs);
0682 
0683 err_free_pkey:
0684     for (i = 0; i < dev->dev->caps.pkey_table_len[port_num]; ++i)
0685         kfree(p->pkey_group.attrs[i]);
0686     kfree(p->pkey_group.attrs);
0687 
0688 err_alloc:
0689     kobject_put(dev->dev_ports_parent[slave]);
0690     kfree(p);
0691     return ret;
0692 }
0693 
0694 static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
0695 {
0696     char name[32];
0697     int err;
0698     int port;
0699     struct kobject *p, *t;
0700     struct mlx4_port *mport;
0701     struct mlx4_active_ports actv_ports;
0702 
0703     get_name(dev, name, slave, sizeof name);
0704 
0705     dev->pkeys.device_parent[slave] =
0706         kobject_create_and_add(name, kobject_get(dev->iov_parent));
0707 
0708     if (!dev->pkeys.device_parent[slave]) {
0709         err = -ENOMEM;
0710         goto fail_dev;
0711     }
0712 
0713     INIT_LIST_HEAD(&dev->pkeys.pkey_port_list[slave]);
0714 
0715     dev->dev_ports_parent[slave] =
0716         kobject_create_and_add("ports",
0717                        kobject_get(dev->pkeys.device_parent[slave]));
0718 
0719     if (!dev->dev_ports_parent[slave]) {
0720         err = -ENOMEM;
0721         goto err_ports;
0722     }
0723 
0724     actv_ports = mlx4_get_active_ports(dev->dev, slave);
0725 
0726     for (port = 1; port <= dev->dev->caps.num_ports; ++port) {
0727         if (!test_bit(port - 1, actv_ports.ports))
0728             continue;
0729         err = add_port(dev, port, slave);
0730         if (err)
0731             goto err_add;
0732     }
0733     return 0;
0734 
0735 err_add:
0736     list_for_each_entry_safe(p, t,
0737                  &dev->pkeys.pkey_port_list[slave],
0738                  entry) {
0739         list_del(&p->entry);
0740         mport = container_of(p, struct mlx4_port, kobj);
0741         sysfs_remove_group(p, &mport->pkey_group);
0742         sysfs_remove_group(p, &mport->gid_group);
0743         remove_vf_smi_entries(mport);
0744         kobject_put(p);
0745     }
0746     kobject_put(dev->dev_ports_parent[slave]);
0747 
0748 err_ports:
0749     kobject_put(dev->pkeys.device_parent[slave]);
0750     /* extra put for the device_parent create_and_add */
0751     kobject_put(dev->pkeys.device_parent[slave]);
0752 
0753 fail_dev:
0754     kobject_put(dev->iov_parent);
0755     return err;
0756 }
0757 
0758 static int register_pkey_tree(struct mlx4_ib_dev *device)
0759 {
0760     int i;
0761 
0762     if (!mlx4_is_master(device->dev))
0763         return 0;
0764 
0765     for (i = 0; i <= device->dev->persist->num_vfs; ++i)
0766         register_one_pkey_tree(device, i);
0767 
0768     return 0;
0769 }
0770 
0771 static void unregister_pkey_tree(struct mlx4_ib_dev *device)
0772 {
0773     int slave;
0774     struct kobject *p, *t;
0775     struct mlx4_port *port;
0776 
0777     if (!mlx4_is_master(device->dev))
0778         return;
0779 
0780     for (slave = device->dev->persist->num_vfs; slave >= 0; --slave) {
0781         list_for_each_entry_safe(p, t,
0782                      &device->pkeys.pkey_port_list[slave],
0783                      entry) {
0784             list_del(&p->entry);
0785             port = container_of(p, struct mlx4_port, kobj);
0786             sysfs_remove_group(p, &port->pkey_group);
0787             sysfs_remove_group(p, &port->gid_group);
0788             remove_vf_smi_entries(port);
0789             kobject_put(p);
0790             kobject_put(device->dev_ports_parent[slave]);
0791         }
0792         kobject_put(device->dev_ports_parent[slave]);
0793         kobject_put(device->pkeys.device_parent[slave]);
0794         kobject_put(device->pkeys.device_parent[slave]);
0795         kobject_put(device->iov_parent);
0796     }
0797 }
0798 
0799 int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *dev)
0800 {
0801     unsigned int i;
0802     int ret = 0;
0803 
0804     if (!mlx4_is_master(dev->dev))
0805         return 0;
0806 
0807     dev->iov_parent = kobject_create_and_add("iov", &dev->ib_dev.dev.kobj);
0808     if (!dev->iov_parent) {
0809         ret = -ENOMEM;
0810         goto err;
0811     }
0812     dev->ports_parent =
0813         kobject_create_and_add("ports",
0814                        kobject_get(dev->iov_parent));
0815     if (!dev->ports_parent) {
0816         ret = -ENOMEM;
0817         goto err_ports;
0818     }
0819 
0820     rdma_for_each_port(&dev->ib_dev, i) {
0821         ret = add_port_entries(dev, i);
0822         if (ret)
0823             goto err_add_entries;
0824     }
0825 
0826     ret = register_pkey_tree(dev);
0827     if (ret)
0828         goto err_add_entries;
0829     return 0;
0830 
0831 err_add_entries:
0832     kobject_put(dev->ports_parent);
0833 
0834 err_ports:
0835     kobject_put(dev->iov_parent);
0836 err:
0837     pr_err("mlx4_ib_device_register_sysfs error (%d)\n", ret);
0838     return ret;
0839 }
0840 
0841 static void unregister_alias_guid_tree(struct mlx4_ib_dev *device)
0842 {
0843     struct mlx4_ib_iov_port *p;
0844     int i;
0845 
0846     if (!mlx4_is_master(device->dev))
0847         return;
0848 
0849     for (i = 0; i < device->dev->caps.num_ports; i++) {
0850         p = &device->iov_ports[i];
0851         kobject_put(p->admin_alias_parent);
0852         kobject_put(p->gids_parent);
0853         kobject_put(p->pkeys_parent);
0854         kobject_put(p->mcgs_parent);
0855         kobject_put(p->cur_port);
0856         kobject_put(p->cur_port);
0857         kobject_put(p->cur_port);
0858         kobject_put(p->cur_port);
0859         kobject_put(p->cur_port);
0860         kobject_put(p->dev->ports_parent);
0861         kfree(p->dentr_ar);
0862     }
0863 }
0864 
0865 void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device)
0866 {
0867     unregister_alias_guid_tree(device);
0868     unregister_pkey_tree(device);
0869     kobject_put(device->ports_parent);
0870     kobject_put(device->iov_parent);
0871     kobject_put(device->iov_parent);
0872 }