at v2.6.12 762 lines 20 kB view raw
1/* 2 * Copyright (c) 2004, 2005 Topspin Communications. 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 * $Id: sysfs.c 1349 2004-12-16 21:09:43Z roland $ 33 */ 34 35#include "core_priv.h" 36 37#include <ib_mad.h> 38 39struct ib_port { 40 struct kobject kobj; 41 struct ib_device *ibdev; 42 struct attribute_group gid_group; 43 struct attribute **gid_attr; 44 struct attribute_group pkey_group; 45 struct attribute **pkey_attr; 46 u8 port_num; 47}; 48 49struct port_attribute { 50 struct attribute attr; 51 ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf); 52 ssize_t (*store)(struct ib_port *, struct port_attribute *, 53 const char *buf, size_t count); 54}; 55 56#define PORT_ATTR(_name, _mode, _show, _store) \ 57struct port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store) 58 59#define PORT_ATTR_RO(_name) \ 60struct port_attribute port_attr_##_name = __ATTR_RO(_name) 61 62struct port_table_attribute { 63 struct port_attribute attr; 64 int index; 65}; 66 67static ssize_t port_attr_show(struct kobject *kobj, 68 struct attribute *attr, char *buf) 69{ 70 struct port_attribute *port_attr = 71 container_of(attr, struct port_attribute, attr); 72 struct ib_port *p = container_of(kobj, struct ib_port, kobj); 73 74 if (!port_attr->show) 75 return 0; 76 77 return port_attr->show(p, port_attr, buf); 78} 79 80static struct sysfs_ops port_sysfs_ops = { 81 .show = port_attr_show 82}; 83 84static ssize_t state_show(struct ib_port *p, struct port_attribute *unused, 85 char *buf) 86{ 87 struct ib_port_attr attr; 88 ssize_t ret; 89 90 static const char *state_name[] = { 91 [IB_PORT_NOP] = "NOP", 92 [IB_PORT_DOWN] = "DOWN", 93 [IB_PORT_INIT] = "INIT", 94 [IB_PORT_ARMED] = "ARMED", 95 [IB_PORT_ACTIVE] = "ACTIVE", 96 [IB_PORT_ACTIVE_DEFER] = "ACTIVE_DEFER" 97 }; 98 99 ret = ib_query_port(p->ibdev, p->port_num, &attr); 100 if (ret) 101 return ret; 102 103 return sprintf(buf, "%d: %s\n", attr.state, 104 attr.state >= 0 && attr.state <= ARRAY_SIZE(state_name) ? 105 state_name[attr.state] : "UNKNOWN"); 106} 107 108static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused, 109 char *buf) 110{ 111 struct ib_port_attr attr; 112 ssize_t ret; 113 114 ret = ib_query_port(p->ibdev, p->port_num, &attr); 115 if (ret) 116 return ret; 117 118 return sprintf(buf, "0x%x\n", attr.lid); 119} 120 121static ssize_t lid_mask_count_show(struct ib_port *p, 122 struct port_attribute *unused, 123 char *buf) 124{ 125 struct ib_port_attr attr; 126 ssize_t ret; 127 128 ret = ib_query_port(p->ibdev, p->port_num, &attr); 129 if (ret) 130 return ret; 131 132 return sprintf(buf, "%d\n", attr.lmc); 133} 134 135static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused, 136 char *buf) 137{ 138 struct ib_port_attr attr; 139 ssize_t ret; 140 141 ret = ib_query_port(p->ibdev, p->port_num, &attr); 142 if (ret) 143 return ret; 144 145 return sprintf(buf, "0x%x\n", attr.sm_lid); 146} 147 148static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused, 149 char *buf) 150{ 151 struct ib_port_attr attr; 152 ssize_t ret; 153 154 ret = ib_query_port(p->ibdev, p->port_num, &attr); 155 if (ret) 156 return ret; 157 158 return sprintf(buf, "%d\n", attr.sm_sl); 159} 160 161static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused, 162 char *buf) 163{ 164 struct ib_port_attr attr; 165 ssize_t ret; 166 167 ret = ib_query_port(p->ibdev, p->port_num, &attr); 168 if (ret) 169 return ret; 170 171 return sprintf(buf, "0x%08x\n", attr.port_cap_flags); 172} 173 174static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, 175 char *buf) 176{ 177 struct ib_port_attr attr; 178 char *speed = ""; 179 int rate; 180 ssize_t ret; 181 182 ret = ib_query_port(p->ibdev, p->port_num, &attr); 183 if (ret) 184 return ret; 185 186 switch (attr.active_speed) { 187 case 2: speed = " DDR"; break; 188 case 4: speed = " QDR"; break; 189 } 190 191 rate = 25 * ib_width_enum_to_int(attr.active_width) * attr.active_speed; 192 if (rate < 0) 193 return -EINVAL; 194 195 return sprintf(buf, "%d%s Gb/sec (%dX%s)\n", 196 rate / 10, rate % 10 ? ".5" : "", 197 ib_width_enum_to_int(attr.active_width), speed); 198} 199 200static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused, 201 char *buf) 202{ 203 struct ib_port_attr attr; 204 205 ssize_t ret; 206 207 ret = ib_query_port(p->ibdev, p->port_num, &attr); 208 if (ret) 209 return ret; 210 211 switch (attr.phys_state) { 212 case 1: return sprintf(buf, "1: Sleep\n"); 213 case 2: return sprintf(buf, "2: Polling\n"); 214 case 3: return sprintf(buf, "3: Disabled\n"); 215 case 4: return sprintf(buf, "4: PortConfigurationTraining\n"); 216 case 5: return sprintf(buf, "5: LinkUp\n"); 217 case 6: return sprintf(buf, "6: LinkErrorRecovery\n"); 218 case 7: return sprintf(buf, "7: Phy Test\n"); 219 default: return sprintf(buf, "%d: <unknown>\n", attr.phys_state); 220 } 221} 222 223static PORT_ATTR_RO(state); 224static PORT_ATTR_RO(lid); 225static PORT_ATTR_RO(lid_mask_count); 226static PORT_ATTR_RO(sm_lid); 227static PORT_ATTR_RO(sm_sl); 228static PORT_ATTR_RO(cap_mask); 229static PORT_ATTR_RO(rate); 230static PORT_ATTR_RO(phys_state); 231 232static struct attribute *port_default_attrs[] = { 233 &port_attr_state.attr, 234 &port_attr_lid.attr, 235 &port_attr_lid_mask_count.attr, 236 &port_attr_sm_lid.attr, 237 &port_attr_sm_sl.attr, 238 &port_attr_cap_mask.attr, 239 &port_attr_rate.attr, 240 &port_attr_phys_state.attr, 241 NULL 242}; 243 244static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr, 245 char *buf) 246{ 247 struct port_table_attribute *tab_attr = 248 container_of(attr, struct port_table_attribute, attr); 249 union ib_gid gid; 250 ssize_t ret; 251 252 ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid); 253 if (ret) 254 return ret; 255 256 return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n", 257 be16_to_cpu(((u16 *) gid.raw)[0]), 258 be16_to_cpu(((u16 *) gid.raw)[1]), 259 be16_to_cpu(((u16 *) gid.raw)[2]), 260 be16_to_cpu(((u16 *) gid.raw)[3]), 261 be16_to_cpu(((u16 *) gid.raw)[4]), 262 be16_to_cpu(((u16 *) gid.raw)[5]), 263 be16_to_cpu(((u16 *) gid.raw)[6]), 264 be16_to_cpu(((u16 *) gid.raw)[7])); 265} 266 267static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr, 268 char *buf) 269{ 270 struct port_table_attribute *tab_attr = 271 container_of(attr, struct port_table_attribute, attr); 272 u16 pkey; 273 ssize_t ret; 274 275 ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey); 276 if (ret) 277 return ret; 278 279 return sprintf(buf, "0x%04x\n", pkey); 280} 281 282#define PORT_PMA_ATTR(_name, _counter, _width, _offset) \ 283struct port_table_attribute port_pma_attr_##_name = { \ 284 .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ 285 .index = (_offset) | ((_width) << 16) | ((_counter) << 24) \ 286} 287 288static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, 289 char *buf) 290{ 291 struct port_table_attribute *tab_attr = 292 container_of(attr, struct port_table_attribute, attr); 293 int offset = tab_attr->index & 0xffff; 294 int width = (tab_attr->index >> 16) & 0xff; 295 struct ib_mad *in_mad = NULL; 296 struct ib_mad *out_mad = NULL; 297 ssize_t ret; 298 299 if (!p->ibdev->process_mad) 300 return sprintf(buf, "N/A (no PMA)\n"); 301 302 in_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); 303 out_mad = kmalloc(sizeof *in_mad, GFP_KERNEL); 304 if (!in_mad || !out_mad) { 305 ret = -ENOMEM; 306 goto out; 307 } 308 309 memset(in_mad, 0, sizeof *in_mad); 310 in_mad->mad_hdr.base_version = 1; 311 in_mad->mad_hdr.mgmt_class = IB_MGMT_CLASS_PERF_MGMT; 312 in_mad->mad_hdr.class_version = 1; 313 in_mad->mad_hdr.method = IB_MGMT_METHOD_GET; 314 in_mad->mad_hdr.attr_id = cpu_to_be16(0x12); /* PortCounters */ 315 316 in_mad->data[41] = p->port_num; /* PortSelect field */ 317 318 if ((p->ibdev->process_mad(p->ibdev, IB_MAD_IGNORE_MKEY, 319 p->port_num, NULL, NULL, in_mad, out_mad) & 320 (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) != 321 (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) { 322 ret = -EINVAL; 323 goto out; 324 } 325 326 switch (width) { 327 case 4: 328 ret = sprintf(buf, "%u\n", (out_mad->data[40 + offset / 8] >> 329 (offset % 4)) & 0xf); 330 break; 331 case 8: 332 ret = sprintf(buf, "%u\n", out_mad->data[40 + offset / 8]); 333 break; 334 case 16: 335 ret = sprintf(buf, "%u\n", 336 be16_to_cpup((u16 *)(out_mad->data + 40 + offset / 8))); 337 break; 338 case 32: 339 ret = sprintf(buf, "%u\n", 340 be32_to_cpup((u32 *)(out_mad->data + 40 + offset / 8))); 341 break; 342 default: 343 ret = 0; 344 } 345 346out: 347 kfree(in_mad); 348 kfree(out_mad); 349 350 return ret; 351} 352 353static PORT_PMA_ATTR(symbol_error , 0, 16, 32); 354static PORT_PMA_ATTR(link_error_recovery , 1, 8, 48); 355static PORT_PMA_ATTR(link_downed , 2, 8, 56); 356static PORT_PMA_ATTR(port_rcv_errors , 3, 16, 64); 357static PORT_PMA_ATTR(port_rcv_remote_physical_errors, 4, 16, 80); 358static PORT_PMA_ATTR(port_rcv_switch_relay_errors , 5, 16, 96); 359static PORT_PMA_ATTR(port_xmit_discards , 6, 16, 112); 360static PORT_PMA_ATTR(port_xmit_constraint_errors , 7, 8, 128); 361static PORT_PMA_ATTR(port_rcv_constraint_errors , 8, 8, 136); 362static PORT_PMA_ATTR(local_link_integrity_errors , 9, 4, 152); 363static PORT_PMA_ATTR(excessive_buffer_overrun_errors, 10, 4, 156); 364static PORT_PMA_ATTR(VL15_dropped , 11, 16, 176); 365static PORT_PMA_ATTR(port_xmit_data , 12, 32, 192); 366static PORT_PMA_ATTR(port_rcv_data , 13, 32, 224); 367static PORT_PMA_ATTR(port_xmit_packets , 14, 32, 256); 368static PORT_PMA_ATTR(port_rcv_packets , 15, 32, 288); 369 370static struct attribute *pma_attrs[] = { 371 &port_pma_attr_symbol_error.attr.attr, 372 &port_pma_attr_link_error_recovery.attr.attr, 373 &port_pma_attr_link_downed.attr.attr, 374 &port_pma_attr_port_rcv_errors.attr.attr, 375 &port_pma_attr_port_rcv_remote_physical_errors.attr.attr, 376 &port_pma_attr_port_rcv_switch_relay_errors.attr.attr, 377 &port_pma_attr_port_xmit_discards.attr.attr, 378 &port_pma_attr_port_xmit_constraint_errors.attr.attr, 379 &port_pma_attr_port_rcv_constraint_errors.attr.attr, 380 &port_pma_attr_local_link_integrity_errors.attr.attr, 381 &port_pma_attr_excessive_buffer_overrun_errors.attr.attr, 382 &port_pma_attr_VL15_dropped.attr.attr, 383 &port_pma_attr_port_xmit_data.attr.attr, 384 &port_pma_attr_port_rcv_data.attr.attr, 385 &port_pma_attr_port_xmit_packets.attr.attr, 386 &port_pma_attr_port_rcv_packets.attr.attr, 387 NULL 388}; 389 390static struct attribute_group pma_group = { 391 .name = "counters", 392 .attrs = pma_attrs 393}; 394 395static void ib_port_release(struct kobject *kobj) 396{ 397 struct ib_port *p = container_of(kobj, struct ib_port, kobj); 398 struct attribute *a; 399 int i; 400 401 for (i = 0; (a = p->gid_attr[i]); ++i) { 402 kfree(a->name); 403 kfree(a); 404 } 405 406 for (i = 0; (a = p->pkey_attr[i]); ++i) { 407 kfree(a->name); 408 kfree(a); 409 } 410 411 kfree(p->gid_attr); 412 kfree(p); 413} 414 415static struct kobj_type port_type = { 416 .release = ib_port_release, 417 .sysfs_ops = &port_sysfs_ops, 418 .default_attrs = port_default_attrs 419}; 420 421static void ib_device_release(struct class_device *cdev) 422{ 423 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 424 425 kfree(dev); 426} 427 428static int ib_device_hotplug(struct class_device *cdev, char **envp, 429 int num_envp, char *buf, int size) 430{ 431 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 432 int i = 0, len = 0; 433 434 if (add_hotplug_env_var(envp, num_envp, &i, buf, size, &len, 435 "NAME=%s", dev->name)) 436 return -ENOMEM; 437 438 /* 439 * It might be nice to pass the node GUID to hotplug, but 440 * right now the only way to get it is to query the device 441 * provider, and this can crash during device removal because 442 * we are will be running after driver removal has started. 443 * We could add a node_guid field to struct ib_device, or we 444 * could just let the hotplug script read the node GUID from 445 * sysfs when devices are added. 446 */ 447 448 envp[i] = NULL; 449 return 0; 450} 451 452static int alloc_group(struct attribute ***attr, 453 ssize_t (*show)(struct ib_port *, 454 struct port_attribute *, char *buf), 455 int len) 456{ 457 struct port_table_attribute ***tab_attr = 458 (struct port_table_attribute ***) attr; 459 int i; 460 int ret; 461 462 *tab_attr = kmalloc((1 + len) * sizeof *tab_attr, GFP_KERNEL); 463 if (!*tab_attr) 464 return -ENOMEM; 465 466 memset(*tab_attr, 0, (1 + len) * sizeof *tab_attr); 467 468 for (i = 0; i < len; ++i) { 469 (*tab_attr)[i] = kmalloc(sizeof *(*tab_attr)[i], GFP_KERNEL); 470 if (!(*tab_attr)[i]) { 471 ret = -ENOMEM; 472 goto err; 473 } 474 memset((*tab_attr)[i], 0, sizeof *(*tab_attr)[i]); 475 (*tab_attr)[i]->attr.attr.name = kmalloc(8, GFP_KERNEL); 476 if (!(*tab_attr)[i]->attr.attr.name) { 477 ret = -ENOMEM; 478 goto err; 479 } 480 481 if (snprintf((*tab_attr)[i]->attr.attr.name, 8, "%d", i) >= 8) { 482 ret = -ENOMEM; 483 goto err; 484 } 485 486 (*tab_attr)[i]->attr.attr.mode = S_IRUGO; 487 (*tab_attr)[i]->attr.attr.owner = THIS_MODULE; 488 (*tab_attr)[i]->attr.show = show; 489 (*tab_attr)[i]->index = i; 490 } 491 492 return 0; 493 494err: 495 for (i = 0; i < len; ++i) { 496 if ((*tab_attr)[i]) 497 kfree((*tab_attr)[i]->attr.attr.name); 498 kfree((*tab_attr)[i]); 499 } 500 501 kfree(*tab_attr); 502 503 return ret; 504} 505 506static int add_port(struct ib_device *device, int port_num) 507{ 508 struct ib_port *p; 509 struct ib_port_attr attr; 510 int i; 511 int ret; 512 513 ret = ib_query_port(device, port_num, &attr); 514 if (ret) 515 return ret; 516 517 p = kmalloc(sizeof *p, GFP_KERNEL); 518 if (!p) 519 return -ENOMEM; 520 memset(p, 0, sizeof *p); 521 522 p->ibdev = device; 523 p->port_num = port_num; 524 p->kobj.ktype = &port_type; 525 526 p->kobj.parent = kobject_get(&device->ports_parent); 527 if (!p->kobj.parent) { 528 ret = -EBUSY; 529 goto err; 530 } 531 532 ret = kobject_set_name(&p->kobj, "%d", port_num); 533 if (ret) 534 goto err_put; 535 536 ret = kobject_register(&p->kobj); 537 if (ret) 538 goto err_put; 539 540 ret = sysfs_create_group(&p->kobj, &pma_group); 541 if (ret) 542 goto err_put; 543 544 ret = alloc_group(&p->gid_attr, show_port_gid, attr.gid_tbl_len); 545 if (ret) 546 goto err_remove_pma; 547 548 p->gid_group.name = "gids"; 549 p->gid_group.attrs = p->gid_attr; 550 551 ret = sysfs_create_group(&p->kobj, &p->gid_group); 552 if (ret) 553 goto err_free_gid; 554 555 ret = alloc_group(&p->pkey_attr, show_port_pkey, attr.pkey_tbl_len); 556 if (ret) 557 goto err_remove_gid; 558 559 p->pkey_group.name = "pkeys"; 560 p->pkey_group.attrs = p->pkey_attr; 561 562 ret = sysfs_create_group(&p->kobj, &p->pkey_group); 563 if (ret) 564 goto err_free_pkey; 565 566 list_add_tail(&p->kobj.entry, &device->port_list); 567 568 return 0; 569 570err_free_pkey: 571 for (i = 0; i < attr.pkey_tbl_len; ++i) { 572 kfree(p->pkey_attr[i]->name); 573 kfree(p->pkey_attr[i]); 574 } 575 576 kfree(p->pkey_attr); 577 578err_remove_gid: 579 sysfs_remove_group(&p->kobj, &p->gid_group); 580 581err_free_gid: 582 for (i = 0; i < attr.gid_tbl_len; ++i) { 583 kfree(p->gid_attr[i]->name); 584 kfree(p->gid_attr[i]); 585 } 586 587 kfree(p->gid_attr); 588 589err_remove_pma: 590 sysfs_remove_group(&p->kobj, &pma_group); 591 592err_put: 593 kobject_put(&device->ports_parent); 594 595err: 596 kfree(p); 597 return ret; 598} 599 600static ssize_t show_node_type(struct class_device *cdev, char *buf) 601{ 602 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 603 604 switch (dev->node_type) { 605 case IB_NODE_CA: return sprintf(buf, "%d: CA\n", dev->node_type); 606 case IB_NODE_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type); 607 case IB_NODE_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type); 608 default: return sprintf(buf, "%d: <unknown>\n", dev->node_type); 609 } 610} 611 612static ssize_t show_sys_image_guid(struct class_device *cdev, char *buf) 613{ 614 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 615 struct ib_device_attr attr; 616 ssize_t ret; 617 618 ret = ib_query_device(dev, &attr); 619 if (ret) 620 return ret; 621 622 return sprintf(buf, "%04x:%04x:%04x:%04x\n", 623 be16_to_cpu(((u16 *) &attr.sys_image_guid)[0]), 624 be16_to_cpu(((u16 *) &attr.sys_image_guid)[1]), 625 be16_to_cpu(((u16 *) &attr.sys_image_guid)[2]), 626 be16_to_cpu(((u16 *) &attr.sys_image_guid)[3])); 627} 628 629static ssize_t show_node_guid(struct class_device *cdev, char *buf) 630{ 631 struct ib_device *dev = container_of(cdev, struct ib_device, class_dev); 632 struct ib_device_attr attr; 633 ssize_t ret; 634 635 ret = ib_query_device(dev, &attr); 636 if (ret) 637 return ret; 638 639 return sprintf(buf, "%04x:%04x:%04x:%04x\n", 640 be16_to_cpu(((u16 *) &attr.node_guid)[0]), 641 be16_to_cpu(((u16 *) &attr.node_guid)[1]), 642 be16_to_cpu(((u16 *) &attr.node_guid)[2]), 643 be16_to_cpu(((u16 *) &attr.node_guid)[3])); 644} 645 646static CLASS_DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); 647static CLASS_DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL); 648static CLASS_DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL); 649 650static struct class_device_attribute *ib_class_attributes[] = { 651 &class_device_attr_node_type, 652 &class_device_attr_sys_image_guid, 653 &class_device_attr_node_guid 654}; 655 656static struct class ib_class = { 657 .name = "infiniband", 658 .release = ib_device_release, 659 .hotplug = ib_device_hotplug, 660}; 661 662int ib_device_register_sysfs(struct ib_device *device) 663{ 664 struct class_device *class_dev = &device->class_dev; 665 int ret; 666 int i; 667 668 class_dev->class = &ib_class; 669 class_dev->class_data = device; 670 strlcpy(class_dev->class_id, device->name, BUS_ID_SIZE); 671 672 INIT_LIST_HEAD(&device->port_list); 673 674 ret = class_device_register(class_dev); 675 if (ret) 676 goto err; 677 678 for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) { 679 ret = class_device_create_file(class_dev, ib_class_attributes[i]); 680 if (ret) 681 goto err_unregister; 682 } 683 684 device->ports_parent.parent = kobject_get(&class_dev->kobj); 685 if (!device->ports_parent.parent) { 686 ret = -EBUSY; 687 goto err_unregister; 688 } 689 ret = kobject_set_name(&device->ports_parent, "ports"); 690 if (ret) 691 goto err_put; 692 ret = kobject_register(&device->ports_parent); 693 if (ret) 694 goto err_put; 695 696 if (device->node_type == IB_NODE_SWITCH) { 697 ret = add_port(device, 0); 698 if (ret) 699 goto err_put; 700 } else { 701 int i; 702 703 for (i = 1; i <= device->phys_port_cnt; ++i) { 704 ret = add_port(device, i); 705 if (ret) 706 goto err_put; 707 } 708 } 709 710 return 0; 711 712err_put: 713 { 714 struct kobject *p, *t; 715 struct ib_port *port; 716 717 list_for_each_entry_safe(p, t, &device->port_list, entry) { 718 list_del(&p->entry); 719 port = container_of(p, struct ib_port, kobj); 720 sysfs_remove_group(p, &pma_group); 721 sysfs_remove_group(p, &port->pkey_group); 722 sysfs_remove_group(p, &port->gid_group); 723 kobject_unregister(p); 724 } 725 } 726 727 kobject_put(&class_dev->kobj); 728 729err_unregister: 730 class_device_unregister(class_dev); 731 732err: 733 return ret; 734} 735 736void ib_device_unregister_sysfs(struct ib_device *device) 737{ 738 struct kobject *p, *t; 739 struct ib_port *port; 740 741 list_for_each_entry_safe(p, t, &device->port_list, entry) { 742 list_del(&p->entry); 743 port = container_of(p, struct ib_port, kobj); 744 sysfs_remove_group(p, &pma_group); 745 sysfs_remove_group(p, &port->pkey_group); 746 sysfs_remove_group(p, &port->gid_group); 747 kobject_unregister(p); 748 } 749 750 kobject_unregister(&device->ports_parent); 751 class_device_unregister(&device->class_dev); 752} 753 754int ib_sysfs_setup(void) 755{ 756 return class_register(&ib_class); 757} 758 759void ib_sysfs_cleanup(void) 760{ 761 class_unregister(&ib_class); 762}