The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/mlx4/mlx4_ib/mlx4_ib_sysfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: ece941817e21306791de68f0bf562040


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.