blob: bb1c34a4817e0160766a12661c3d358048d066f4 [file] [log] [blame]
Jack Morgensteinc1e7e462012-08-03 08:40:51 +00001/*
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/stat.h>
38
39#include <rdma/ib_mad.h>
40/*show_admin_alias_guid returns the administratively assigned value of that GUID.
41 * Values returned in buf parameter string:
42 * 0 - requests opensm to assign a value.
43 * ffffffffffffffff - delete this entry.
44 * other - value assigned by administrator.
45 */
46static ssize_t show_admin_alias_guid(struct device *dev,
47 struct device_attribute *attr, char *buf)
48{
Jack Morgensteinc1e7e462012-08-03 08:40:51 +000049 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;
Yishai Hadas2350f242015-03-01 18:17:22 +020053 __be64 sysadmin_ag_val;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +000054
Yishai Hadas2350f242015-03-01 18:17:22 +020055 sysadmin_ag_val = mlx4_get_admin_guid(mdev->dev,
56 mlx4_ib_iov_dentry->entry_num,
57 port->num);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +000058
Yishai Hadas2350f242015-03-01 18:17:22 +020059 return sprintf(buf, "%llx\n", be64_to_cpu(sysadmin_ag_val));
Jack Morgensteinc1e7e462012-08-03 08:40:51 +000060}
61
62/* store_admin_alias_guid stores the (new) administratively assigned value of that GUID.
63 * Values in buf parameter string:
64 * 0 - requests opensm to assign a value.
65 * 0xffffffffffffffff - delete this entry.
66 * other - guid value assigned by the administrator.
67 */
68static ssize_t store_admin_alias_guid(struct device *dev,
69 struct device_attribute *attr,
70 const char *buf, size_t count)
71{
72 int record_num;/*0-15*/
73 int guid_index_in_rec; /*0 - 7*/
74 struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
75 container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
76 struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
77 struct mlx4_ib_dev *mdev = port->dev;
78 u64 sysadmin_ag_val;
Yishai Hadas99ee4df2015-02-03 18:32:53 +020079 unsigned long flags;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +000080
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 }
Yishai Hadas99ee4df2015-02-03 18:32:53 +020087 spin_lock_irqsave(&mdev->sriov.alias_guid.ag_work_lock, flags);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +000088 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 ;
Yishai Hadas2350f242015-03-01 18:17:22 +020097 mlx4_set_admin_guid(mdev->dev, cpu_to_be64(sysadmin_ag_val),
98 mlx4_ib_iov_dentry->entry_num,
99 port->num);
100
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000101 switch (sysadmin_ag_val) {
102 case MLX4_GUID_FOR_DELETE_VAL:
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000103 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
104 = MLX4_GUID_SYSADMIN_ASSIGN;
105 break;
106 /* The sysadmin requests the SM to re-assign */
107 case MLX4_NOT_SET_GUID:
108 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
109 = MLX4_GUID_DRIVER_ASSIGN;
110 break;
111 /* The sysadmin requests a specific value.*/
112 default:
113 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].ownership
114 = MLX4_GUID_SYSADMIN_ASSIGN;
115 break;
116 }
117
118 /* set the record index */
119 mdev->sriov.alias_guid.ports_guid[port->num - 1].all_rec_per_port[record_num].guid_indexes
Yishai Hadas99ee4df2015-02-03 18:32:53 +0200120 |= mlx4_ib_get_aguid_comp_mask_from_ix(guid_index_in_rec);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000121
Yishai Hadas99ee4df2015-02-03 18:32:53 +0200122 spin_unlock_irqrestore(&mdev->sriov.alias_guid.ag_work_lock, flags);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000123 mlx4_ib_init_alias_guid_work(mdev, port->num - 1);
124
125 return count;
126}
127
128static ssize_t show_port_gid(struct device *dev,
129 struct device_attribute *attr,
130 char *buf)
131{
132 struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
133 container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
134 struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
135 struct mlx4_ib_dev *mdev = port->dev;
136 union ib_gid gid;
137 ssize_t ret;
138
139 ret = __mlx4_ib_query_gid(&mdev->ib_dev, port->num,
140 mlx4_ib_iov_dentry->entry_num, &gid, 1);
141 if (ret)
142 return ret;
143 ret = sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
144 be16_to_cpu(((__be16 *) gid.raw)[0]),
145 be16_to_cpu(((__be16 *) gid.raw)[1]),
146 be16_to_cpu(((__be16 *) gid.raw)[2]),
147 be16_to_cpu(((__be16 *) gid.raw)[3]),
148 be16_to_cpu(((__be16 *) gid.raw)[4]),
149 be16_to_cpu(((__be16 *) gid.raw)[5]),
150 be16_to_cpu(((__be16 *) gid.raw)[6]),
151 be16_to_cpu(((__be16 *) gid.raw)[7]));
152 return ret;
153}
154
155static ssize_t show_phys_port_pkey(struct device *dev,
156 struct device_attribute *attr,
157 char *buf)
158{
159 struct mlx4_ib_iov_sysfs_attr *mlx4_ib_iov_dentry =
160 container_of(attr, struct mlx4_ib_iov_sysfs_attr, dentry);
161 struct mlx4_ib_iov_port *port = mlx4_ib_iov_dentry->ctx;
162 struct mlx4_ib_dev *mdev = port->dev;
163 u16 pkey;
164 ssize_t ret;
165
166 ret = __mlx4_ib_query_pkey(&mdev->ib_dev, port->num,
167 mlx4_ib_iov_dentry->entry_num, &pkey, 1);
168 if (ret)
169 return ret;
170
171 return sprintf(buf, "0x%04x\n", pkey);
172}
173
174#define DENTRY_REMOVE(_dentry) \
175do { \
176 sysfs_remove_file((_dentry)->kobj, &(_dentry)->dentry.attr); \
177} while (0);
178
179static int create_sysfs_entry(void *_ctx, struct mlx4_ib_iov_sysfs_attr *_dentry,
180 char *_name, struct kobject *_kobj,
181 ssize_t (*show)(struct device *dev,
182 struct device_attribute *attr,
183 char *buf),
184 ssize_t (*store)(struct device *dev,
185 struct device_attribute *attr,
186 const char *buf, size_t count)
187 )
188{
189 int ret = 0;
190 struct mlx4_ib_iov_sysfs_attr *vdentry = _dentry;
191
192 vdentry->ctx = _ctx;
193 vdentry->dentry.show = show;
194 vdentry->dentry.store = store;
195 sysfs_attr_init(&vdentry->dentry.attr);
196 vdentry->dentry.attr.name = vdentry->name;
197 vdentry->dentry.attr.mode = 0;
198 vdentry->kobj = _kobj;
199 snprintf(vdentry->name, 15, "%s", _name);
200
201 if (vdentry->dentry.store)
202 vdentry->dentry.attr.mode |= S_IWUSR;
203
204 if (vdentry->dentry.show)
205 vdentry->dentry.attr.mode |= S_IRUGO;
206
207 ret = sysfs_create_file(vdentry->kobj, &vdentry->dentry.attr);
208 if (ret) {
209 pr_err("failed to create %s\n", vdentry->dentry.attr.name);
210 vdentry->ctx = NULL;
211 return ret;
212 }
213
214 return ret;
215}
216
217int add_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
218 struct attribute *attr)
219{
220 struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];
221 int ret;
222
223 ret = sysfs_create_file(port->mcgs_parent, attr);
224 if (ret)
225 pr_err("failed to create %s\n", attr->name);
226
227 return ret;
228}
229
230void del_sysfs_port_mcg_attr(struct mlx4_ib_dev *device, int port_num,
231 struct attribute *attr)
232{
233 struct mlx4_ib_iov_port *port = &device->iov_ports[port_num - 1];
234
235 sysfs_remove_file(port->mcgs_parent, attr);
236}
237
238static int add_port_entries(struct mlx4_ib_dev *device, int port_num)
239{
240 int i;
241 char buff[10];
242 struct mlx4_ib_iov_port *port = NULL;
243 int ret = 0 ;
244 struct ib_port_attr attr;
245
246 /* get the physical gid and pkey table sizes.*/
247 ret = __mlx4_ib_query_port(&device->ib_dev, port_num, &attr, 1);
248 if (ret)
249 goto err;
250
251 port = &device->iov_ports[port_num - 1];
252 port->dev = device;
253 port->num = port_num;
254 /* Directory structure:
255 * iov -
256 * port num -
257 * admin_guids
258 * gids (operational)
259 * mcg_table
260 */
261 port->dentr_ar = kzalloc(sizeof (struct mlx4_ib_iov_sysfs_attr_ar),
262 GFP_KERNEL);
263 if (!port->dentr_ar) {
264 ret = -ENOMEM;
265 goto err;
266 }
267 sprintf(buff, "%d", port_num);
268 port->cur_port = kobject_create_and_add(buff,
269 kobject_get(device->ports_parent));
270 if (!port->cur_port) {
271 ret = -ENOMEM;
272 goto kobj_create_err;
273 }
274 /* admin GUIDs */
275 port->admin_alias_parent = kobject_create_and_add("admin_guids",
276 kobject_get(port->cur_port));
277 if (!port->admin_alias_parent) {
278 ret = -ENOMEM;
279 goto err_admin_guids;
280 }
281 for (i = 0 ; i < attr.gid_tbl_len; i++) {
282 sprintf(buff, "%d", i);
283 port->dentr_ar->dentries[i].entry_num = i;
284 ret = create_sysfs_entry(port, &port->dentr_ar->dentries[i],
285 buff, port->admin_alias_parent,
286 show_admin_alias_guid, store_admin_alias_guid);
287 if (ret)
288 goto err_admin_alias_parent;
289 }
290
291 /* gids subdirectory (operational gids) */
292 port->gids_parent = kobject_create_and_add("gids",
293 kobject_get(port->cur_port));
294 if (!port->gids_parent) {
295 ret = -ENOMEM;
296 goto err_gids;
297 }
298
299 for (i = 0 ; i < attr.gid_tbl_len; i++) {
300 sprintf(buff, "%d", i);
301 port->dentr_ar->dentries[attr.gid_tbl_len + i].entry_num = i;
302 ret = create_sysfs_entry(port,
303 &port->dentr_ar->dentries[attr.gid_tbl_len + i],
304 buff,
305 port->gids_parent, show_port_gid, NULL);
306 if (ret)
307 goto err_gids_parent;
308 }
309
310 /* physical port pkey table */
311 port->pkeys_parent =
312 kobject_create_and_add("pkeys", kobject_get(port->cur_port));
313 if (!port->pkeys_parent) {
314 ret = -ENOMEM;
315 goto err_pkeys;
316 }
317
318 for (i = 0 ; i < attr.pkey_tbl_len; i++) {
319 sprintf(buff, "%d", i);
320 port->dentr_ar->dentries[2 * attr.gid_tbl_len + i].entry_num = i;
321 ret = create_sysfs_entry(port,
322 &port->dentr_ar->dentries[2 * attr.gid_tbl_len + i],
323 buff, port->pkeys_parent,
324 show_phys_port_pkey, NULL);
325 if (ret)
326 goto err_pkeys_parent;
327 }
328
329 /* MCGs table */
330 port->mcgs_parent =
331 kobject_create_and_add("mcgs", kobject_get(port->cur_port));
332 if (!port->mcgs_parent) {
333 ret = -ENOMEM;
334 goto err_mcgs;
335 }
336 return 0;
337
338err_mcgs:
339 kobject_put(port->cur_port);
340
341err_pkeys_parent:
342 kobject_put(port->pkeys_parent);
343
344err_pkeys:
345 kobject_put(port->cur_port);
346
347err_gids_parent:
348 kobject_put(port->gids_parent);
349
350err_gids:
351 kobject_put(port->cur_port);
352
353err_admin_alias_parent:
354 kobject_put(port->admin_alias_parent);
355
356err_admin_guids:
357 kobject_put(port->cur_port);
358 kobject_put(port->cur_port); /* once more for create_and_add buff */
359
360kobj_create_err:
361 kobject_put(device->ports_parent);
362 kfree(port->dentr_ar);
363
364err:
365 pr_err("add_port_entries FAILED: for port:%d, error: %d\n",
366 port_num, ret);
367 return ret;
368}
369
370static void get_name(struct mlx4_ib_dev *dev, char *name, int i, int max)
371{
372 char base_name[9];
373
374 /* pci_name format is: bus:dev:func -> xxxx:yy:zz.n */
Yishai Hadas872bf2f2015-01-25 16:59:35 +0200375 strlcpy(name, pci_name(dev->dev->persist->pdev), max);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000376 strncpy(base_name, name, 8); /*till xxxx:yy:*/
377 base_name[8] = '\0';
378 /* with no ARI only 3 last bits are used so when the fn is higher than 8
379 * need to add it to the dev num, so count in the last number will be
380 * modulo 8 */
381 sprintf(name, "%s%.2d.%d", base_name, (i/8), (i%8));
382}
383
384struct mlx4_port {
385 struct kobject kobj;
386 struct mlx4_ib_dev *dev;
387 struct attribute_group pkey_group;
388 struct attribute_group gid_group;
Jack Morgenstein65fed8a2014-05-29 16:31:04 +0300389 struct device_attribute enable_smi_admin;
390 struct device_attribute smi_enabled;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000391 int slave;
Jack Morgenstein65fed8a2014-05-29 16:31:04 +0300392 u8 port_num;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000393};
394
395
396static void mlx4_port_release(struct kobject *kobj)
397{
398 struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
399 struct attribute *a;
400 int i;
401
402 for (i = 0; (a = p->pkey_group.attrs[i]); ++i)
403 kfree(a);
404 kfree(p->pkey_group.attrs);
405 for (i = 0; (a = p->gid_group.attrs[i]); ++i)
406 kfree(a);
407 kfree(p->gid_group.attrs);
408 kfree(p);
409}
410
411struct port_attribute {
412 struct attribute attr;
413 ssize_t (*show)(struct mlx4_port *, struct port_attribute *, char *buf);
414 ssize_t (*store)(struct mlx4_port *, struct port_attribute *,
415 const char *buf, size_t count);
416};
417
418static ssize_t port_attr_show(struct kobject *kobj,
419 struct attribute *attr, char *buf)
420{
421 struct port_attribute *port_attr =
422 container_of(attr, struct port_attribute, attr);
423 struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
424
425 if (!port_attr->show)
426 return -EIO;
427 return port_attr->show(p, port_attr, buf);
428}
429
430static ssize_t port_attr_store(struct kobject *kobj,
431 struct attribute *attr,
432 const char *buf, size_t size)
433{
434 struct port_attribute *port_attr =
435 container_of(attr, struct port_attribute, attr);
436 struct mlx4_port *p = container_of(kobj, struct mlx4_port, kobj);
437
438 if (!port_attr->store)
439 return -EIO;
440 return port_attr->store(p, port_attr, buf, size);
441}
442
443static const struct sysfs_ops port_sysfs_ops = {
444 .show = port_attr_show,
445 .store = port_attr_store,
446};
447
448static struct kobj_type port_type = {
449 .release = mlx4_port_release,
450 .sysfs_ops = &port_sysfs_ops,
451};
452
453struct port_table_attribute {
454 struct port_attribute attr;
455 char name[8];
456 int index;
457};
458
459static ssize_t show_port_pkey(struct mlx4_port *p, struct port_attribute *attr,
460 char *buf)
461{
462 struct port_table_attribute *tab_attr =
463 container_of(attr, struct port_table_attribute, attr);
464 ssize_t ret = -ENODEV;
465
466 if (p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1][tab_attr->index] >=
467 (p->dev->dev->caps.pkey_table_len[p->port_num]))
468 ret = sprintf(buf, "none\n");
469 else
470 ret = sprintf(buf, "%d\n",
471 p->dev->pkeys.virt2phys_pkey[p->slave]
472 [p->port_num - 1][tab_attr->index]);
473 return ret;
474}
475
476static ssize_t store_port_pkey(struct mlx4_port *p, struct port_attribute *attr,
477 const char *buf, size_t count)
478{
479 struct port_table_attribute *tab_attr =
480 container_of(attr, struct port_table_attribute, attr);
481 int idx;
482 int err;
483
484 /* do not allow remapping Dom0 virtual pkey table */
485 if (p->slave == mlx4_master_func_num(p->dev->dev))
486 return -EINVAL;
487
488 if (!strncasecmp(buf, "no", 2))
489 idx = p->dev->dev->phys_caps.pkey_phys_table_len[p->port_num] - 1;
490 else if (sscanf(buf, "%i", &idx) != 1 ||
491 idx >= p->dev->dev->caps.pkey_table_len[p->port_num] ||
492 idx < 0)
493 return -EINVAL;
494
495 p->dev->pkeys.virt2phys_pkey[p->slave][p->port_num - 1]
496 [tab_attr->index] = idx;
497 mlx4_sync_pkey_table(p->dev->dev, p->slave, p->port_num,
498 tab_attr->index, idx);
499 err = mlx4_gen_pkey_eqe(p->dev->dev, p->slave, p->port_num);
500 if (err) {
501 pr_err("mlx4_gen_pkey_eqe failed for slave %d,"
502 " port %d, index %d\n", p->slave, p->port_num, idx);
503 return err;
504 }
505 return count;
506}
507
508static ssize_t show_port_gid_idx(struct mlx4_port *p,
509 struct port_attribute *attr, char *buf)
510{
511 return sprintf(buf, "%d\n", p->slave);
512}
513
514static struct attribute **
515alloc_group_attrs(ssize_t (*show)(struct mlx4_port *,
516 struct port_attribute *, char *buf),
517 ssize_t (*store)(struct mlx4_port *, struct port_attribute *,
518 const char *buf, size_t count),
519 int len)
520{
521 struct attribute **tab_attr;
522 struct port_table_attribute *element;
523 int i;
524
525 tab_attr = kcalloc(1 + len, sizeof (struct attribute *), GFP_KERNEL);
526 if (!tab_attr)
527 return NULL;
528
529 for (i = 0; i < len; i++) {
530 element = kzalloc(sizeof (struct port_table_attribute),
531 GFP_KERNEL);
532 if (!element)
533 goto err;
534 if (snprintf(element->name, sizeof (element->name),
535 "%d", i) >= sizeof (element->name)) {
536 kfree(element);
537 goto err;
538 }
539 sysfs_attr_init(&element->attr.attr);
540 element->attr.attr.name = element->name;
541 if (store) {
542 element->attr.attr.mode = S_IWUSR | S_IRUGO;
543 element->attr.store = store;
544 } else
545 element->attr.attr.mode = S_IRUGO;
546
547 element->attr.show = show;
548 element->index = i;
549 tab_attr[i] = &element->attr.attr;
550 }
551 return tab_attr;
552
553err:
554 while (--i >= 0)
555 kfree(tab_attr[i]);
556 kfree(tab_attr);
557 return NULL;
558}
559
Jack Morgenstein65fed8a2014-05-29 16:31:04 +0300560static ssize_t sysfs_show_smi_enabled(struct device *dev,
561 struct device_attribute *attr, char *buf)
562{
563 struct mlx4_port *p =
564 container_of(attr, struct mlx4_port, smi_enabled);
565 ssize_t len = 0;
566
567 if (mlx4_vf_smi_enabled(p->dev->dev, p->slave, p->port_num))
568 len = sprintf(buf, "%d\n", 1);
569 else
570 len = sprintf(buf, "%d\n", 0);
571
572 return len;
573}
574
575static ssize_t sysfs_show_enable_smi_admin(struct device *dev,
576 struct device_attribute *attr,
577 char *buf)
578{
579 struct mlx4_port *p =
580 container_of(attr, struct mlx4_port, enable_smi_admin);
581 ssize_t len = 0;
582
583 if (mlx4_vf_get_enable_smi_admin(p->dev->dev, p->slave, p->port_num))
584 len = sprintf(buf, "%d\n", 1);
585 else
586 len = sprintf(buf, "%d\n", 0);
587
588 return len;
589}
590
591static ssize_t sysfs_store_enable_smi_admin(struct device *dev,
592 struct device_attribute *attr,
593 const char *buf, size_t count)
594{
595 struct mlx4_port *p =
596 container_of(attr, struct mlx4_port, enable_smi_admin);
597 int enable;
598
599 if (sscanf(buf, "%i", &enable) != 1 ||
600 enable < 0 || enable > 1)
601 return -EINVAL;
602
603 if (mlx4_vf_set_enable_smi_admin(p->dev->dev, p->slave, p->port_num, enable))
604 return -EINVAL;
605 return count;
606}
607
608static int add_vf_smi_entries(struct mlx4_port *p)
609{
610 int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) ==
611 IB_LINK_LAYER_ETHERNET;
612 int ret;
613
614 /* do not display entries if eth transport, or if master */
615 if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev))
616 return 0;
617
618 sysfs_attr_init(&p->smi_enabled.attr);
619 p->smi_enabled.show = sysfs_show_smi_enabled;
620 p->smi_enabled.store = NULL;
621 p->smi_enabled.attr.name = "smi_enabled";
622 p->smi_enabled.attr.mode = 0444;
623 ret = sysfs_create_file(&p->kobj, &p->smi_enabled.attr);
624 if (ret) {
625 pr_err("failed to create smi_enabled\n");
626 return ret;
627 }
628
629 sysfs_attr_init(&p->enable_smi_admin.attr);
630 p->enable_smi_admin.show = sysfs_show_enable_smi_admin;
631 p->enable_smi_admin.store = sysfs_store_enable_smi_admin;
632 p->enable_smi_admin.attr.name = "enable_smi_admin";
633 p->enable_smi_admin.attr.mode = 0644;
634 ret = sysfs_create_file(&p->kobj, &p->enable_smi_admin.attr);
635 if (ret) {
636 pr_err("failed to create enable_smi_admin\n");
637 sysfs_remove_file(&p->kobj, &p->smi_enabled.attr);
638 return ret;
639 }
640 return 0;
641}
642
643static void remove_vf_smi_entries(struct mlx4_port *p)
644{
645 int is_eth = rdma_port_get_link_layer(&p->dev->ib_dev, p->port_num) ==
646 IB_LINK_LAYER_ETHERNET;
647
648 if (is_eth || p->slave == mlx4_master_func_num(p->dev->dev))
649 return;
650
651 sysfs_remove_file(&p->kobj, &p->smi_enabled.attr);
652 sysfs_remove_file(&p->kobj, &p->enable_smi_admin.attr);
653}
654
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000655static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave)
656{
657 struct mlx4_port *p;
658 int i;
659 int ret;
660
661 p = kzalloc(sizeof *p, GFP_KERNEL);
662 if (!p)
663 return -ENOMEM;
664
665 p->dev = dev;
666 p->port_num = port_num;
667 p->slave = slave;
668
669 ret = kobject_init_and_add(&p->kobj, &port_type,
670 kobject_get(dev->dev_ports_parent[slave]),
671 "%d", port_num);
672 if (ret)
673 goto err_alloc;
674
675 p->pkey_group.name = "pkey_idx";
676 p->pkey_group.attrs =
677 alloc_group_attrs(show_port_pkey, store_port_pkey,
678 dev->dev->caps.pkey_table_len[port_num]);
Julia Lawallaf2e2e32013-12-29 23:47:20 +0100679 if (!p->pkey_group.attrs) {
680 ret = -ENOMEM;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000681 goto err_alloc;
Julia Lawallaf2e2e32013-12-29 23:47:20 +0100682 }
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000683
684 ret = sysfs_create_group(&p->kobj, &p->pkey_group);
685 if (ret)
686 goto err_free_pkey;
687
688 p->gid_group.name = "gid_idx";
689 p->gid_group.attrs = alloc_group_attrs(show_port_gid_idx, NULL, 1);
Julia Lawallaf2e2e32013-12-29 23:47:20 +0100690 if (!p->gid_group.attrs) {
691 ret = -ENOMEM;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000692 goto err_free_pkey;
Julia Lawallaf2e2e32013-12-29 23:47:20 +0100693 }
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000694
695 ret = sysfs_create_group(&p->kobj, &p->gid_group);
696 if (ret)
697 goto err_free_gid;
698
Jack Morgenstein65fed8a2014-05-29 16:31:04 +0300699 ret = add_vf_smi_entries(p);
700 if (ret)
701 goto err_free_gid;
702
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000703 list_add_tail(&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]);
704 return 0;
705
706err_free_gid:
707 kfree(p->gid_group.attrs[0]);
708 kfree(p->gid_group.attrs);
709
710err_free_pkey:
711 for (i = 0; i < dev->dev->caps.pkey_table_len[port_num]; ++i)
712 kfree(p->pkey_group.attrs[i]);
713 kfree(p->pkey_group.attrs);
714
715err_alloc:
716 kobject_put(dev->dev_ports_parent[slave]);
717 kfree(p);
718 return ret;
719}
720
721static int register_one_pkey_tree(struct mlx4_ib_dev *dev, int slave)
722{
723 char name[32];
724 int err;
725 int port;
726 struct kobject *p, *t;
727 struct mlx4_port *mport;
Matan Barak449fc482014-03-19 18:11:52 +0200728 struct mlx4_active_ports actv_ports;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000729
730 get_name(dev, name, slave, sizeof name);
731
732 dev->pkeys.device_parent[slave] =
733 kobject_create_and_add(name, kobject_get(dev->iov_parent));
734
735 if (!dev->pkeys.device_parent[slave]) {
736 err = -ENOMEM;
737 goto fail_dev;
738 }
739
740 INIT_LIST_HEAD(&dev->pkeys.pkey_port_list[slave]);
741
742 dev->dev_ports_parent[slave] =
743 kobject_create_and_add("ports",
744 kobject_get(dev->pkeys.device_parent[slave]));
745
746 if (!dev->dev_ports_parent[slave]) {
747 err = -ENOMEM;
748 goto err_ports;
749 }
750
Matan Barak449fc482014-03-19 18:11:52 +0200751 actv_ports = mlx4_get_active_ports(dev->dev, slave);
752
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000753 for (port = 1; port <= dev->dev->caps.num_ports; ++port) {
Matan Barak449fc482014-03-19 18:11:52 +0200754 if (!test_bit(port - 1, actv_ports.ports))
755 continue;
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000756 err = add_port(dev, port, slave);
757 if (err)
758 goto err_add;
759 }
760 return 0;
761
762err_add:
763 list_for_each_entry_safe(p, t,
764 &dev->pkeys.pkey_port_list[slave],
765 entry) {
766 list_del(&p->entry);
767 mport = container_of(p, struct mlx4_port, kobj);
768 sysfs_remove_group(p, &mport->pkey_group);
769 sysfs_remove_group(p, &mport->gid_group);
Jack Morgenstein65fed8a2014-05-29 16:31:04 +0300770 remove_vf_smi_entries(mport);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000771 kobject_put(p);
772 }
773 kobject_put(dev->dev_ports_parent[slave]);
774
775err_ports:
776 kobject_put(dev->pkeys.device_parent[slave]);
777 /* extra put for the device_parent create_and_add */
778 kobject_put(dev->pkeys.device_parent[slave]);
779
780fail_dev:
781 kobject_put(dev->iov_parent);
782 return err;
783}
784
785static int register_pkey_tree(struct mlx4_ib_dev *device)
786{
787 int i;
788
789 if (!mlx4_is_master(device->dev))
790 return 0;
791
Yishai Hadas872bf2f2015-01-25 16:59:35 +0200792 for (i = 0; i <= device->dev->persist->num_vfs; ++i)
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000793 register_one_pkey_tree(device, i);
794
795 return 0;
796}
797
798static void unregister_pkey_tree(struct mlx4_ib_dev *device)
799{
800 int slave;
801 struct kobject *p, *t;
802 struct mlx4_port *port;
803
804 if (!mlx4_is_master(device->dev))
805 return;
806
Yishai Hadas872bf2f2015-01-25 16:59:35 +0200807 for (slave = device->dev->persist->num_vfs; slave >= 0; --slave) {
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000808 list_for_each_entry_safe(p, t,
809 &device->pkeys.pkey_port_list[slave],
810 entry) {
811 list_del(&p->entry);
812 port = container_of(p, struct mlx4_port, kobj);
813 sysfs_remove_group(p, &port->pkey_group);
814 sysfs_remove_group(p, &port->gid_group);
Jack Morgenstein65fed8a2014-05-29 16:31:04 +0300815 remove_vf_smi_entries(port);
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000816 kobject_put(p);
817 kobject_put(device->dev_ports_parent[slave]);
818 }
819 kobject_put(device->dev_ports_parent[slave]);
820 kobject_put(device->pkeys.device_parent[slave]);
821 kobject_put(device->pkeys.device_parent[slave]);
822 kobject_put(device->iov_parent);
823 }
824}
825
826int mlx4_ib_device_register_sysfs(struct mlx4_ib_dev *dev)
827{
828 int i;
829 int ret = 0;
830
831 if (!mlx4_is_master(dev->dev))
832 return 0;
833
834 dev->iov_parent =
835 kobject_create_and_add("iov",
836 kobject_get(dev->ib_dev.ports_parent->parent));
837 if (!dev->iov_parent) {
838 ret = -ENOMEM;
839 goto err;
840 }
841 dev->ports_parent =
842 kobject_create_and_add("ports",
843 kobject_get(dev->iov_parent));
Julia Lawall6950a232013-01-21 13:02:58 +0000844 if (!dev->ports_parent) {
Jack Morgensteinc1e7e462012-08-03 08:40:51 +0000845 ret = -ENOMEM;
846 goto err_ports;
847 }
848
849 for (i = 1; i <= dev->ib_dev.phys_port_cnt; ++i) {
850 ret = add_port_entries(dev, i);
851 if (ret)
852 goto err_add_entries;
853 }
854
855 ret = register_pkey_tree(dev);
856 if (ret)
857 goto err_add_entries;
858 return 0;
859
860err_add_entries:
861 kobject_put(dev->ports_parent);
862
863err_ports:
864 kobject_put(dev->iov_parent);
865err:
866 kobject_put(dev->ib_dev.ports_parent->parent);
867 pr_err("mlx4_ib_device_register_sysfs error (%d)\n", ret);
868 return ret;
869}
870
871static void unregister_alias_guid_tree(struct mlx4_ib_dev *device)
872{
873 struct mlx4_ib_iov_port *p;
874 int i;
875
876 if (!mlx4_is_master(device->dev))
877 return;
878
879 for (i = 0; i < device->dev->caps.num_ports; i++) {
880 p = &device->iov_ports[i];
881 kobject_put(p->admin_alias_parent);
882 kobject_put(p->gids_parent);
883 kobject_put(p->pkeys_parent);
884 kobject_put(p->mcgs_parent);
885 kobject_put(p->cur_port);
886 kobject_put(p->cur_port);
887 kobject_put(p->cur_port);
888 kobject_put(p->cur_port);
889 kobject_put(p->cur_port);
890 kobject_put(p->dev->ports_parent);
891 kfree(p->dentr_ar);
892 }
893}
894
895void mlx4_ib_device_unregister_sysfs(struct mlx4_ib_dev *device)
896{
897 unregister_alias_guid_tree(device);
898 unregister_pkey_tree(device);
899 kobject_put(device->ports_parent);
900 kobject_put(device->iov_parent);
901 kobject_put(device->iov_parent);
902 kobject_put(device->ib_dev.ports_parent->parent);
903}