1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause OR GPL-2.0 3 * 4 * Copyright (c) 2004, 2005 Topspin Communications. All rights reserved. 5 * Copyright (c) 2005 Mellanox Technologies Ltd. All rights reserved. 6 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved. 7 * 8 * This software is available to you under a choice of one of two 9 * licenses. You may choose to be licensed under the terms of the GNU 10 * General Public License (GPL) Version 2, available from the file 11 * COPYING in the main directory of this source tree, or the 12 * OpenIB.org BSD license below: 13 * 14 * Redistribution and use in source and binary forms, with or 15 * without modification, are permitted provided that the following 16 * conditions are met: 17 * 18 * - Redistributions of source code must retain the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer. 21 * 22 * - Redistributions in binary form must reproduce the above 23 * copyright notice, this list of conditions and the following 24 * disclaimer in the documentation and/or other materials 25 * provided with the distribution. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 * SOFTWARE. 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include "core_priv.h" 41 42 #include <linux/slab.h> 43 #include <linux/string.h> 44 #include <linux/netdevice.h> 45 #include <linux/fs.h> 46 #include <linux/printk.h> 47 48 #include <rdma/ib_mad.h> 49 #include <rdma/ib_pma.h> 50 51 struct ib_port; 52 53 struct gid_attr_group { 54 struct ib_port *port; 55 struct kobject kobj; 56 struct attribute_group ndev; 57 struct attribute_group type; 58 }; 59 struct ib_port { 60 struct kobject kobj; 61 struct ib_device *ibdev; 62 struct gid_attr_group *gid_attr_group; 63 struct attribute_group gid_group; 64 struct attribute_group pkey_group; 65 struct attribute_group *pma_table; 66 struct attribute_group *hw_stats_ag; 67 struct rdma_hw_stats *hw_stats; 68 u8 port_num; 69 }; 70 71 struct port_attribute { 72 struct attribute attr; 73 ssize_t (*show)(struct ib_port *, struct port_attribute *, char *buf); 74 ssize_t (*store)(struct ib_port *, struct port_attribute *, 75 const char *buf, size_t count); 76 }; 77 78 #define PORT_ATTR(_name, _mode, _show, _store) \ 79 struct port_attribute port_attr_##_name = __ATTR(_name, _mode, _show, _store) 80 81 #define PORT_ATTR_RO(_name) \ 82 struct port_attribute port_attr_##_name = __ATTR_RO(_name) 83 84 struct port_table_attribute { 85 struct port_attribute attr; 86 char name[8]; 87 int index; 88 __be16 attr_id; 89 }; 90 91 struct hw_stats_attribute { 92 struct attribute attr; 93 ssize_t (*show)(struct kobject *kobj, 94 struct attribute *attr, char *buf); 95 ssize_t (*store)(struct kobject *kobj, 96 struct attribute *attr, 97 const char *buf, 98 size_t count); 99 int index; 100 u8 port_num; 101 }; 102 103 static ssize_t port_attr_show(struct kobject *kobj, 104 struct attribute *attr, char *buf) 105 { 106 struct port_attribute *port_attr = 107 container_of(attr, struct port_attribute, attr); 108 struct ib_port *p = container_of(kobj, struct ib_port, kobj); 109 110 if (!port_attr->show) 111 return -EIO; 112 113 return port_attr->show(p, port_attr, buf); 114 } 115 116 static const struct sysfs_ops port_sysfs_ops = { 117 .show = port_attr_show 118 }; 119 120 static ssize_t gid_attr_show(struct kobject *kobj, 121 struct attribute *attr, char *buf) 122 { 123 struct port_attribute *port_attr = 124 container_of(attr, struct port_attribute, attr); 125 struct ib_port *p = container_of(kobj, struct gid_attr_group, 126 kobj)->port; 127 128 if (!port_attr->show) 129 return -EIO; 130 131 return port_attr->show(p, port_attr, buf); 132 } 133 134 static const struct sysfs_ops gid_attr_sysfs_ops = { 135 .show = gid_attr_show 136 }; 137 138 static ssize_t state_show(struct ib_port *p, struct port_attribute *unused, 139 char *buf) 140 { 141 struct ib_port_attr attr; 142 ssize_t ret; 143 144 static const char *state_name[] = { 145 [IB_PORT_NOP] = "NOP", 146 [IB_PORT_DOWN] = "DOWN", 147 [IB_PORT_INIT] = "INIT", 148 [IB_PORT_ARMED] = "ARMED", 149 [IB_PORT_ACTIVE] = "ACTIVE", 150 [IB_PORT_ACTIVE_DEFER] = "ACTIVE_DEFER" 151 }; 152 153 ret = ib_query_port(p->ibdev, p->port_num, &attr); 154 if (ret) 155 return ret; 156 157 return sprintf(buf, "%d: %s\n", attr.state, 158 attr.state >= 0 && attr.state < ARRAY_SIZE(state_name) ? 159 state_name[attr.state] : "UNKNOWN"); 160 } 161 162 static ssize_t lid_show(struct ib_port *p, struct port_attribute *unused, 163 char *buf) 164 { 165 struct ib_port_attr attr; 166 ssize_t ret; 167 168 ret = ib_query_port(p->ibdev, p->port_num, &attr); 169 if (ret) 170 return ret; 171 172 return sprintf(buf, "0x%x\n", attr.lid); 173 } 174 175 static ssize_t lid_mask_count_show(struct ib_port *p, 176 struct port_attribute *unused, 177 char *buf) 178 { 179 struct ib_port_attr attr; 180 ssize_t ret; 181 182 ret = ib_query_port(p->ibdev, p->port_num, &attr); 183 if (ret) 184 return ret; 185 186 return sprintf(buf, "%d\n", attr.lmc); 187 } 188 189 static ssize_t sm_lid_show(struct ib_port *p, struct port_attribute *unused, 190 char *buf) 191 { 192 struct ib_port_attr attr; 193 ssize_t ret; 194 195 ret = ib_query_port(p->ibdev, p->port_num, &attr); 196 if (ret) 197 return ret; 198 199 return sprintf(buf, "0x%x\n", attr.sm_lid); 200 } 201 202 static ssize_t sm_sl_show(struct ib_port *p, struct port_attribute *unused, 203 char *buf) 204 { 205 struct ib_port_attr attr; 206 ssize_t ret; 207 208 ret = ib_query_port(p->ibdev, p->port_num, &attr); 209 if (ret) 210 return ret; 211 212 return sprintf(buf, "%d\n", attr.sm_sl); 213 } 214 215 static ssize_t cap_mask_show(struct ib_port *p, struct port_attribute *unused, 216 char *buf) 217 { 218 struct ib_port_attr attr; 219 ssize_t ret; 220 221 ret = ib_query_port(p->ibdev, p->port_num, &attr); 222 if (ret) 223 return ret; 224 225 return sprintf(buf, "0x%08x\n", attr.port_cap_flags); 226 } 227 228 static ssize_t rate_show(struct ib_port *p, struct port_attribute *unused, 229 char *buf) 230 { 231 struct ib_port_attr attr; 232 char *speed = ""; 233 int rate; /* in deci-Gb/sec */ 234 ssize_t ret; 235 236 ret = ib_query_port(p->ibdev, p->port_num, &attr); 237 if (ret) 238 return ret; 239 240 switch (attr.active_speed) { 241 case IB_SPEED_DDR: 242 speed = " DDR"; 243 rate = 50; 244 break; 245 case IB_SPEED_QDR: 246 speed = " QDR"; 247 rate = 100; 248 break; 249 case IB_SPEED_FDR10: 250 speed = " FDR10"; 251 rate = 100; 252 break; 253 case IB_SPEED_FDR: 254 speed = " FDR"; 255 rate = 140; 256 break; 257 case IB_SPEED_EDR: 258 speed = " EDR"; 259 rate = 250; 260 break; 261 case IB_SPEED_HDR: 262 speed = " HDR"; 263 rate = 500; 264 break; 265 case IB_SPEED_SDR: 266 default: /* default to SDR for invalid rates */ 267 speed = " SDR"; 268 rate = 25; 269 break; 270 } 271 272 rate *= ib_width_enum_to_int(attr.active_width); 273 if (rate < 0) 274 return -EINVAL; 275 276 return sprintf(buf, "%d%s Gb/sec (%dX%s)\n", 277 rate / 10, rate % 10 ? ".5" : "", 278 ib_width_enum_to_int(attr.active_width), speed); 279 } 280 281 static ssize_t phys_state_show(struct ib_port *p, struct port_attribute *unused, 282 char *buf) 283 { 284 struct ib_port_attr attr; 285 286 ssize_t ret; 287 288 ret = ib_query_port(p->ibdev, p->port_num, &attr); 289 if (ret) 290 return ret; 291 292 switch (attr.phys_state) { 293 case 1: return sprintf(buf, "1: Sleep\n"); 294 case 2: return sprintf(buf, "2: Polling\n"); 295 case 3: return sprintf(buf, "3: Disabled\n"); 296 case 4: return sprintf(buf, "4: PortConfigurationTraining\n"); 297 case 5: return sprintf(buf, "5: LinkUp\n"); 298 case 6: return sprintf(buf, "6: LinkErrorRecovery\n"); 299 case 7: return sprintf(buf, "7: Phy Test\n"); 300 default: return sprintf(buf, "%d: <unknown>\n", attr.phys_state); 301 } 302 } 303 304 static ssize_t link_layer_show(struct ib_port *p, struct port_attribute *unused, 305 char *buf) 306 { 307 switch (rdma_port_get_link_layer(p->ibdev, p->port_num)) { 308 case IB_LINK_LAYER_INFINIBAND: 309 return sprintf(buf, "%s\n", "InfiniBand"); 310 case IB_LINK_LAYER_ETHERNET: 311 return sprintf(buf, "%s\n", "Ethernet"); 312 default: 313 return sprintf(buf, "%s\n", "Unknown"); 314 } 315 } 316 317 static PORT_ATTR_RO(state); 318 static PORT_ATTR_RO(lid); 319 static PORT_ATTR_RO(lid_mask_count); 320 static PORT_ATTR_RO(sm_lid); 321 static PORT_ATTR_RO(sm_sl); 322 static PORT_ATTR_RO(cap_mask); 323 static PORT_ATTR_RO(rate); 324 static PORT_ATTR_RO(phys_state); 325 static PORT_ATTR_RO(link_layer); 326 327 static struct attribute *port_default_attrs[] = { 328 &port_attr_state.attr, 329 &port_attr_lid.attr, 330 &port_attr_lid_mask_count.attr, 331 &port_attr_sm_lid.attr, 332 &port_attr_sm_sl.attr, 333 &port_attr_cap_mask.attr, 334 &port_attr_rate.attr, 335 &port_attr_phys_state.attr, 336 &port_attr_link_layer.attr, 337 NULL 338 }; 339 340 static size_t print_ndev(struct ib_gid_attr *gid_attr, char *buf) 341 { 342 if (!gid_attr->ndev) 343 return -EINVAL; 344 345 return sprintf(buf, "%s\n", if_name(gid_attr->ndev)); 346 } 347 348 static size_t print_gid_type(struct ib_gid_attr *gid_attr, char *buf) 349 { 350 return sprintf(buf, "%s\n", ib_cache_gid_type_str(gid_attr->gid_type)); 351 } 352 353 static ssize_t _show_port_gid_attr(struct ib_port *p, 354 struct port_attribute *attr, 355 char *buf, 356 size_t (*print)(struct ib_gid_attr *gid_attr, 357 char *buf)) 358 { 359 struct port_table_attribute *tab_attr = 360 container_of(attr, struct port_table_attribute, attr); 361 union ib_gid gid; 362 struct ib_gid_attr gid_attr = {}; 363 ssize_t ret; 364 365 ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid, 366 &gid_attr); 367 if (ret) 368 goto err; 369 370 ret = print(&gid_attr, buf); 371 372 err: 373 if (gid_attr.ndev) 374 dev_put(gid_attr.ndev); 375 return ret; 376 } 377 378 static ssize_t show_port_gid(struct ib_port *p, struct port_attribute *attr, 379 char *buf) 380 { 381 struct port_table_attribute *tab_attr = 382 container_of(attr, struct port_table_attribute, attr); 383 union ib_gid gid; 384 ssize_t ret; 385 386 ret = ib_query_gid(p->ibdev, p->port_num, tab_attr->index, &gid, NULL); 387 if (ret) 388 return ret; 389 390 return sprintf(buf, GID_PRINT_FMT"\n", GID_PRINT_ARGS(gid.raw)); 391 } 392 393 static ssize_t show_port_gid_attr_ndev(struct ib_port *p, 394 struct port_attribute *attr, char *buf) 395 { 396 return _show_port_gid_attr(p, attr, buf, print_ndev); 397 } 398 399 static ssize_t show_port_gid_attr_gid_type(struct ib_port *p, 400 struct port_attribute *attr, 401 char *buf) 402 { 403 return _show_port_gid_attr(p, attr, buf, print_gid_type); 404 } 405 406 static ssize_t show_port_pkey(struct ib_port *p, struct port_attribute *attr, 407 char *buf) 408 { 409 struct port_table_attribute *tab_attr = 410 container_of(attr, struct port_table_attribute, attr); 411 u16 pkey; 412 ssize_t ret; 413 414 ret = ib_query_pkey(p->ibdev, p->port_num, tab_attr->index, &pkey); 415 if (ret) 416 return ret; 417 418 return sprintf(buf, "0x%04x\n", pkey); 419 } 420 421 #define PORT_PMA_ATTR(_name, _counter, _width, _offset) \ 422 struct port_table_attribute port_pma_attr_##_name = { \ 423 .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ 424 .index = (_offset) | ((_width) << 16) | ((_counter) << 24), \ 425 .attr_id = IB_PMA_PORT_COUNTERS , \ 426 } 427 428 #define PORT_PMA_ATTR_EXT(_name, _width, _offset) \ 429 struct port_table_attribute port_pma_attr_ext_##_name = { \ 430 .attr = __ATTR(_name, S_IRUGO, show_pma_counter, NULL), \ 431 .index = (_offset) | ((_width) << 16), \ 432 .attr_id = IB_PMA_PORT_COUNTERS_EXT , \ 433 } 434 435 /* 436 * Get a Perfmgmt MAD block of data. 437 * Returns error code or the number of bytes retrieved. 438 */ 439 static int get_perf_mad(struct ib_device *dev, int port_num, __be16 attr, 440 void *data, int offset, size_t size) 441 { 442 struct ib_mad *in_mad; 443 struct ib_mad *out_mad; 444 size_t mad_size = sizeof(*out_mad); 445 u16 out_mad_pkey_index = 0; 446 ssize_t ret; 447 448 if (!dev->process_mad) 449 return -ENOSYS; 450 451 in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 452 out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 453 if (!in_mad || !out_mad) { 454 ret = -ENOMEM; 455 goto out; 456 } 457 458 in_mad->mad_hdr.base_version = 1; 459 in_mad->mad_hdr.mgmt_class = IB_MGMT_CLASS_PERF_MGMT; 460 in_mad->mad_hdr.class_version = 1; 461 in_mad->mad_hdr.method = IB_MGMT_METHOD_GET; 462 in_mad->mad_hdr.attr_id = attr; 463 464 if (attr != IB_PMA_CLASS_PORT_INFO) 465 in_mad->data[41] = port_num; /* PortSelect field */ 466 467 if ((dev->process_mad(dev, IB_MAD_IGNORE_MKEY, 468 port_num, NULL, NULL, 469 (const struct ib_mad_hdr *)in_mad, mad_size, 470 (struct ib_mad_hdr *)out_mad, &mad_size, 471 &out_mad_pkey_index) & 472 (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) != 473 (IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY)) { 474 ret = -EINVAL; 475 goto out; 476 } 477 memcpy(data, out_mad->data + offset, size); 478 ret = size; 479 out: 480 kfree(in_mad); 481 kfree(out_mad); 482 return ret; 483 } 484 485 static ssize_t show_pma_counter(struct ib_port *p, struct port_attribute *attr, 486 char *buf) 487 { 488 struct port_table_attribute *tab_attr = 489 container_of(attr, struct port_table_attribute, attr); 490 int offset = tab_attr->index & 0xffff; 491 int width = (tab_attr->index >> 16) & 0xff; 492 ssize_t ret; 493 u8 data[8]; 494 495 ret = get_perf_mad(p->ibdev, p->port_num, tab_attr->attr_id, &data, 496 40 + offset / 8, sizeof(data)); 497 if (ret < 0) 498 return sprintf(buf, "N/A (no PMA)\n"); 499 500 switch (width) { 501 case 4: 502 ret = sprintf(buf, "%u\n", (*data >> 503 (4 - (offset % 8))) & 0xf); 504 break; 505 case 8: 506 ret = sprintf(buf, "%u\n", *data); 507 break; 508 case 16: 509 ret = sprintf(buf, "%u\n", 510 be16_to_cpup((__be16 *)data)); 511 break; 512 case 32: 513 ret = sprintf(buf, "%u\n", 514 be32_to_cpup((__be32 *)data)); 515 break; 516 case 64: 517 ret = sprintf(buf, "%llu\n", 518 (unsigned long long)be64_to_cpup((__be64 *)data)); 519 break; 520 521 default: 522 ret = 0; 523 } 524 525 return ret; 526 } 527 528 static PORT_PMA_ATTR(symbol_error , 0, 16, 32); 529 static PORT_PMA_ATTR(link_error_recovery , 1, 8, 48); 530 static PORT_PMA_ATTR(link_downed , 2, 8, 56); 531 static PORT_PMA_ATTR(port_rcv_errors , 3, 16, 64); 532 static PORT_PMA_ATTR(port_rcv_remote_physical_errors, 4, 16, 80); 533 static PORT_PMA_ATTR(port_rcv_switch_relay_errors , 5, 16, 96); 534 static PORT_PMA_ATTR(port_xmit_discards , 6, 16, 112); 535 static PORT_PMA_ATTR(port_xmit_constraint_errors , 7, 8, 128); 536 static PORT_PMA_ATTR(port_rcv_constraint_errors , 8, 8, 136); 537 static PORT_PMA_ATTR(local_link_integrity_errors , 9, 4, 152); 538 static PORT_PMA_ATTR(excessive_buffer_overrun_errors, 10, 4, 156); 539 static PORT_PMA_ATTR(VL15_dropped , 11, 16, 176); 540 static PORT_PMA_ATTR(port_xmit_data , 12, 32, 192); 541 static PORT_PMA_ATTR(port_rcv_data , 13, 32, 224); 542 static PORT_PMA_ATTR(port_xmit_packets , 14, 32, 256); 543 static PORT_PMA_ATTR(port_rcv_packets , 15, 32, 288); 544 static PORT_PMA_ATTR(port_xmit_wait , 0, 32, 320); 545 546 /* 547 * Counters added by extended set 548 */ 549 static PORT_PMA_ATTR_EXT(port_xmit_data , 64, 64); 550 static PORT_PMA_ATTR_EXT(port_rcv_data , 64, 128); 551 static PORT_PMA_ATTR_EXT(port_xmit_packets , 64, 192); 552 static PORT_PMA_ATTR_EXT(port_rcv_packets , 64, 256); 553 static PORT_PMA_ATTR_EXT(unicast_xmit_packets , 64, 320); 554 static PORT_PMA_ATTR_EXT(unicast_rcv_packets , 64, 384); 555 static PORT_PMA_ATTR_EXT(multicast_xmit_packets , 64, 448); 556 static PORT_PMA_ATTR_EXT(multicast_rcv_packets , 64, 512); 557 558 static struct attribute *pma_attrs[] = { 559 &port_pma_attr_symbol_error.attr.attr, 560 &port_pma_attr_link_error_recovery.attr.attr, 561 &port_pma_attr_link_downed.attr.attr, 562 &port_pma_attr_port_rcv_errors.attr.attr, 563 &port_pma_attr_port_rcv_remote_physical_errors.attr.attr, 564 &port_pma_attr_port_rcv_switch_relay_errors.attr.attr, 565 &port_pma_attr_port_xmit_discards.attr.attr, 566 &port_pma_attr_port_xmit_constraint_errors.attr.attr, 567 &port_pma_attr_port_rcv_constraint_errors.attr.attr, 568 &port_pma_attr_local_link_integrity_errors.attr.attr, 569 &port_pma_attr_excessive_buffer_overrun_errors.attr.attr, 570 &port_pma_attr_VL15_dropped.attr.attr, 571 &port_pma_attr_port_xmit_data.attr.attr, 572 &port_pma_attr_port_rcv_data.attr.attr, 573 &port_pma_attr_port_xmit_packets.attr.attr, 574 &port_pma_attr_port_rcv_packets.attr.attr, 575 &port_pma_attr_port_xmit_wait.attr.attr, 576 NULL 577 }; 578 579 static struct attribute *pma_attrs_ext[] = { 580 &port_pma_attr_symbol_error.attr.attr, 581 &port_pma_attr_link_error_recovery.attr.attr, 582 &port_pma_attr_link_downed.attr.attr, 583 &port_pma_attr_port_rcv_errors.attr.attr, 584 &port_pma_attr_port_rcv_remote_physical_errors.attr.attr, 585 &port_pma_attr_port_rcv_switch_relay_errors.attr.attr, 586 &port_pma_attr_port_xmit_discards.attr.attr, 587 &port_pma_attr_port_xmit_constraint_errors.attr.attr, 588 &port_pma_attr_port_rcv_constraint_errors.attr.attr, 589 &port_pma_attr_local_link_integrity_errors.attr.attr, 590 &port_pma_attr_excessive_buffer_overrun_errors.attr.attr, 591 &port_pma_attr_VL15_dropped.attr.attr, 592 &port_pma_attr_ext_port_xmit_data.attr.attr, 593 &port_pma_attr_ext_port_rcv_data.attr.attr, 594 &port_pma_attr_ext_port_xmit_packets.attr.attr, 595 &port_pma_attr_port_xmit_wait.attr.attr, 596 &port_pma_attr_ext_port_rcv_packets.attr.attr, 597 &port_pma_attr_ext_unicast_rcv_packets.attr.attr, 598 &port_pma_attr_ext_unicast_xmit_packets.attr.attr, 599 &port_pma_attr_ext_multicast_rcv_packets.attr.attr, 600 &port_pma_attr_ext_multicast_xmit_packets.attr.attr, 601 NULL 602 }; 603 604 static struct attribute *pma_attrs_noietf[] = { 605 &port_pma_attr_symbol_error.attr.attr, 606 &port_pma_attr_link_error_recovery.attr.attr, 607 &port_pma_attr_link_downed.attr.attr, 608 &port_pma_attr_port_rcv_errors.attr.attr, 609 &port_pma_attr_port_rcv_remote_physical_errors.attr.attr, 610 &port_pma_attr_port_rcv_switch_relay_errors.attr.attr, 611 &port_pma_attr_port_xmit_discards.attr.attr, 612 &port_pma_attr_port_xmit_constraint_errors.attr.attr, 613 &port_pma_attr_port_rcv_constraint_errors.attr.attr, 614 &port_pma_attr_local_link_integrity_errors.attr.attr, 615 &port_pma_attr_excessive_buffer_overrun_errors.attr.attr, 616 &port_pma_attr_VL15_dropped.attr.attr, 617 &port_pma_attr_ext_port_xmit_data.attr.attr, 618 &port_pma_attr_ext_port_rcv_data.attr.attr, 619 &port_pma_attr_ext_port_xmit_packets.attr.attr, 620 &port_pma_attr_ext_port_rcv_packets.attr.attr, 621 &port_pma_attr_port_xmit_wait.attr.attr, 622 NULL 623 }; 624 625 static struct attribute_group pma_group = { 626 .name = "counters", 627 .attrs = pma_attrs 628 }; 629 630 static struct attribute_group pma_group_ext = { 631 .name = "counters", 632 .attrs = pma_attrs_ext 633 }; 634 635 static struct attribute_group pma_group_noietf = { 636 .name = "counters", 637 .attrs = pma_attrs_noietf 638 }; 639 640 static void ib_port_release(struct kobject *kobj) 641 { 642 struct ib_port *p = container_of(kobj, struct ib_port, kobj); 643 struct attribute *a; 644 int i; 645 646 if (p->gid_group.attrs) { 647 for (i = 0; (a = p->gid_group.attrs[i]); ++i) 648 kfree(a); 649 650 kfree(p->gid_group.attrs); 651 } 652 653 if (p->pkey_group.attrs) { 654 for (i = 0; (a = p->pkey_group.attrs[i]); ++i) 655 kfree(a); 656 657 kfree(p->pkey_group.attrs); 658 } 659 660 kfree(p); 661 } 662 663 static void ib_port_gid_attr_release(struct kobject *kobj) 664 { 665 struct gid_attr_group *g = container_of(kobj, struct gid_attr_group, 666 kobj); 667 struct attribute *a; 668 int i; 669 670 if (g->ndev.attrs) { 671 for (i = 0; (a = g->ndev.attrs[i]); ++i) 672 kfree(a); 673 674 kfree(g->ndev.attrs); 675 } 676 677 if (g->type.attrs) { 678 for (i = 0; (a = g->type.attrs[i]); ++i) 679 kfree(a); 680 681 kfree(g->type.attrs); 682 } 683 684 kfree(g); 685 } 686 687 static struct kobj_type port_type = { 688 .release = ib_port_release, 689 .sysfs_ops = &port_sysfs_ops, 690 .default_attrs = port_default_attrs 691 }; 692 693 static struct kobj_type gid_attr_type = { 694 .sysfs_ops = &gid_attr_sysfs_ops, 695 .release = ib_port_gid_attr_release 696 }; 697 698 static struct attribute ** 699 alloc_group_attrs(ssize_t (*show)(struct ib_port *, 700 struct port_attribute *, char *buf), 701 int len) 702 { 703 struct attribute **tab_attr; 704 struct port_table_attribute *element; 705 int i; 706 707 tab_attr = kcalloc(1 + len, sizeof(struct attribute *), GFP_KERNEL); 708 if (!tab_attr) 709 return NULL; 710 711 for (i = 0; i < len; i++) { 712 element = kzalloc(sizeof(struct port_table_attribute), 713 GFP_KERNEL); 714 if (!element) 715 goto err; 716 717 if (snprintf(element->name, sizeof(element->name), 718 "%d", i) >= sizeof(element->name)) { 719 kfree(element); 720 goto err; 721 } 722 723 element->attr.attr.name = element->name; 724 element->attr.attr.mode = S_IRUGO; 725 element->attr.show = show; 726 element->index = i; 727 sysfs_attr_init(&element->attr.attr); 728 729 tab_attr[i] = &element->attr.attr; 730 } 731 732 return tab_attr; 733 734 err: 735 while (--i >= 0) 736 kfree(tab_attr[i]); 737 kfree(tab_attr); 738 return NULL; 739 } 740 741 /* 742 * Figure out which counter table to use depending on 743 * the device capabilities. 744 */ 745 static struct attribute_group *get_counter_table(struct ib_device *dev, 746 int port_num) 747 { 748 struct ib_class_port_info cpi; 749 750 if (get_perf_mad(dev, port_num, IB_PMA_CLASS_PORT_INFO, 751 &cpi, 40, sizeof(cpi)) >= 0) { 752 if (cpi.capability_mask & IB_PMA_CLASS_CAP_EXT_WIDTH) 753 /* We have extended counters */ 754 return &pma_group_ext; 755 756 if (cpi.capability_mask & IB_PMA_CLASS_CAP_EXT_WIDTH_NOIETF) 757 /* But not the IETF ones */ 758 return &pma_group_noietf; 759 } 760 761 /* Fall back to normal counters */ 762 return &pma_group; 763 } 764 765 static int update_hw_stats(struct ib_device *dev, struct rdma_hw_stats *stats, 766 u8 port_num, int index) 767 { 768 int ret; 769 770 if (time_is_after_eq_jiffies(stats->timestamp + stats->lifespan)) 771 return 0; 772 ret = dev->get_hw_stats(dev, stats, port_num, index); 773 if (ret < 0) 774 return ret; 775 if (ret == stats->num_counters) 776 stats->timestamp = jiffies; 777 778 return 0; 779 } 780 781 static ssize_t print_hw_stat(struct rdma_hw_stats *stats, int index, char *buf) 782 { 783 return sprintf(buf, "%llu\n", (unsigned long long)stats->value[index]); 784 } 785 786 static ssize_t show_hw_stats(struct kobject *kobj, struct attribute *attr, 787 char *buf) 788 { 789 struct ib_device *dev; 790 struct ib_port *port; 791 struct hw_stats_attribute *hsa; 792 struct rdma_hw_stats *stats; 793 int ret; 794 795 hsa = container_of(attr, struct hw_stats_attribute, attr); 796 if (!hsa->port_num) { 797 dev = container_of((struct device *)kobj, 798 struct ib_device, dev); 799 stats = dev->hw_stats; 800 } else { 801 port = container_of(kobj, struct ib_port, kobj); 802 dev = port->ibdev; 803 stats = port->hw_stats; 804 } 805 ret = update_hw_stats(dev, stats, hsa->port_num, hsa->index); 806 if (ret) 807 return ret; 808 return print_hw_stat(stats, hsa->index, buf); 809 } 810 811 static ssize_t show_stats_lifespan(struct kobject *kobj, 812 struct attribute *attr, 813 char *buf) 814 { 815 struct hw_stats_attribute *hsa; 816 int msecs; 817 818 hsa = container_of(attr, struct hw_stats_attribute, attr); 819 if (!hsa->port_num) { 820 struct ib_device *dev = container_of((struct device *)kobj, 821 struct ib_device, dev); 822 msecs = jiffies_to_msecs(dev->hw_stats->lifespan); 823 } else { 824 struct ib_port *p = container_of(kobj, struct ib_port, kobj); 825 msecs = jiffies_to_msecs(p->hw_stats->lifespan); 826 } 827 return sprintf(buf, "%d\n", msecs); 828 } 829 830 static ssize_t set_stats_lifespan(struct kobject *kobj, 831 struct attribute *attr, 832 const char *buf, size_t count) 833 { 834 struct hw_stats_attribute *hsa; 835 int msecs; 836 int jiffies; 837 int ret; 838 839 ret = kstrtoint(buf, 10, &msecs); 840 if (ret) 841 return ret; 842 if (msecs < 0 || msecs > 10000) 843 return -EINVAL; 844 jiffies = msecs_to_jiffies(msecs); 845 hsa = container_of(attr, struct hw_stats_attribute, attr); 846 if (!hsa->port_num) { 847 struct ib_device *dev = container_of((struct device *)kobj, 848 struct ib_device, dev); 849 dev->hw_stats->lifespan = jiffies; 850 } else { 851 struct ib_port *p = container_of(kobj, struct ib_port, kobj); 852 p->hw_stats->lifespan = jiffies; 853 } 854 return count; 855 } 856 857 static void free_hsag(struct kobject *kobj, struct attribute_group *attr_group) 858 { 859 struct attribute **attr; 860 861 sysfs_remove_group(kobj, attr_group); 862 863 for (attr = attr_group->attrs; *attr; attr++) 864 kfree(*attr); 865 kfree(attr_group); 866 } 867 868 static struct attribute *alloc_hsa(int index, u8 port_num, const char *name) 869 { 870 struct hw_stats_attribute *hsa; 871 872 hsa = kmalloc(sizeof(*hsa), GFP_KERNEL); 873 if (!hsa) 874 return NULL; 875 876 hsa->attr.name = __DECONST(char *, name); 877 hsa->attr.mode = S_IRUGO; 878 hsa->show = show_hw_stats; 879 hsa->store = NULL; 880 hsa->index = index; 881 hsa->port_num = port_num; 882 883 return &hsa->attr; 884 } 885 886 static struct attribute *alloc_hsa_lifespan(char *name, u8 port_num) 887 { 888 struct hw_stats_attribute *hsa; 889 890 hsa = kmalloc(sizeof(*hsa), GFP_KERNEL); 891 if (!hsa) 892 return NULL; 893 894 hsa->attr.name = name; 895 hsa->attr.mode = S_IWUSR | S_IRUGO; 896 hsa->show = show_stats_lifespan; 897 hsa->store = set_stats_lifespan; 898 hsa->index = 0; 899 hsa->port_num = port_num; 900 901 return &hsa->attr; 902 } 903 904 static void setup_hw_stats(struct ib_device *device, struct ib_port *port, 905 u8 port_num) 906 { 907 struct attribute_group *hsag; 908 struct rdma_hw_stats *stats; 909 int i, ret; 910 911 stats = device->alloc_hw_stats(device, port_num); 912 913 if (!stats) 914 return; 915 916 if (!stats->names || stats->num_counters <= 0) 917 goto err_free_stats; 918 919 /* 920 * Two extra attribue elements here, one for the lifespan entry and 921 * one to NULL terminate the list for the sysfs core code 922 */ 923 hsag = kzalloc(sizeof(*hsag) + 924 sizeof(void *) * (stats->num_counters + 2), 925 GFP_KERNEL); 926 if (!hsag) 927 goto err_free_stats; 928 929 ret = device->get_hw_stats(device, stats, port_num, 930 stats->num_counters); 931 if (ret != stats->num_counters) 932 goto err_free_hsag; 933 934 stats->timestamp = jiffies; 935 936 hsag->name = "hw_counters"; 937 hsag->attrs = (void *)((char *)hsag + sizeof(*hsag)); 938 939 for (i = 0; i < stats->num_counters; i++) { 940 hsag->attrs[i] = alloc_hsa(i, port_num, stats->names[i]); 941 if (!hsag->attrs[i]) 942 goto err; 943 sysfs_attr_init(hsag->attrs[i]); 944 } 945 946 /* treat an error here as non-fatal */ 947 hsag->attrs[i] = alloc_hsa_lifespan("lifespan", port_num); 948 if (hsag->attrs[i]) 949 sysfs_attr_init(hsag->attrs[i]); 950 951 if (port) { 952 struct kobject *kobj = &port->kobj; 953 ret = sysfs_create_group(kobj, hsag); 954 if (ret) 955 goto err; 956 port->hw_stats_ag = hsag; 957 port->hw_stats = stats; 958 } else { 959 struct kobject *kobj = &device->dev.kobj; 960 ret = sysfs_create_group(kobj, hsag); 961 if (ret) 962 goto err; 963 device->hw_stats_ag = hsag; 964 device->hw_stats = stats; 965 } 966 967 return; 968 969 err: 970 for (; i >= 0; i--) 971 kfree(hsag->attrs[i]); 972 err_free_hsag: 973 kfree(hsag); 974 err_free_stats: 975 kfree(stats); 976 return; 977 } 978 979 static int add_port(struct ib_device *device, int port_num, 980 int (*port_callback)(struct ib_device *, 981 u8, struct kobject *)) 982 { 983 struct ib_port *p; 984 struct ib_port_attr attr; 985 int i; 986 int ret; 987 988 ret = ib_query_port(device, port_num, &attr); 989 if (ret) 990 return ret; 991 992 p = kzalloc(sizeof *p, GFP_KERNEL); 993 if (!p) 994 return -ENOMEM; 995 996 p->ibdev = device; 997 p->port_num = port_num; 998 999 ret = kobject_init_and_add(&p->kobj, &port_type, 1000 device->ports_parent, 1001 "%d", port_num); 1002 if (ret) { 1003 kfree(p); 1004 return ret; 1005 } 1006 1007 p->gid_attr_group = kzalloc(sizeof(*p->gid_attr_group), GFP_KERNEL); 1008 if (!p->gid_attr_group) { 1009 ret = -ENOMEM; 1010 goto err_put; 1011 } 1012 1013 p->gid_attr_group->port = p; 1014 ret = kobject_init_and_add(&p->gid_attr_group->kobj, &gid_attr_type, 1015 &p->kobj, "gid_attrs"); 1016 if (ret) { 1017 kfree(p->gid_attr_group); 1018 goto err_put; 1019 } 1020 1021 p->pma_table = get_counter_table(device, port_num); 1022 ret = sysfs_create_group(&p->kobj, p->pma_table); 1023 if (ret) 1024 goto err_put_gid_attrs; 1025 1026 p->gid_group.name = "gids"; 1027 p->gid_group.attrs = alloc_group_attrs(show_port_gid, attr.gid_tbl_len); 1028 if (!p->gid_group.attrs) { 1029 ret = -ENOMEM; 1030 goto err_remove_pma; 1031 } 1032 1033 ret = sysfs_create_group(&p->kobj, &p->gid_group); 1034 if (ret) 1035 goto err_free_gid; 1036 1037 p->gid_attr_group->ndev.name = "ndevs"; 1038 p->gid_attr_group->ndev.attrs = alloc_group_attrs(show_port_gid_attr_ndev, 1039 attr.gid_tbl_len); 1040 if (!p->gid_attr_group->ndev.attrs) { 1041 ret = -ENOMEM; 1042 goto err_remove_gid; 1043 } 1044 1045 ret = sysfs_create_group(&p->gid_attr_group->kobj, 1046 &p->gid_attr_group->ndev); 1047 if (ret) 1048 goto err_free_gid_ndev; 1049 1050 p->gid_attr_group->type.name = "types"; 1051 p->gid_attr_group->type.attrs = alloc_group_attrs(show_port_gid_attr_gid_type, 1052 attr.gid_tbl_len); 1053 if (!p->gid_attr_group->type.attrs) { 1054 ret = -ENOMEM; 1055 goto err_remove_gid_ndev; 1056 } 1057 1058 ret = sysfs_create_group(&p->gid_attr_group->kobj, 1059 &p->gid_attr_group->type); 1060 if (ret) 1061 goto err_free_gid_type; 1062 1063 p->pkey_group.name = "pkeys"; 1064 p->pkey_group.attrs = alloc_group_attrs(show_port_pkey, 1065 attr.pkey_tbl_len); 1066 if (!p->pkey_group.attrs) { 1067 ret = -ENOMEM; 1068 goto err_remove_gid_type; 1069 } 1070 1071 ret = sysfs_create_group(&p->kobj, &p->pkey_group); 1072 if (ret) 1073 goto err_free_pkey; 1074 1075 if (port_callback) { 1076 ret = port_callback(device, port_num, &p->kobj); 1077 if (ret) 1078 goto err_remove_pkey; 1079 } 1080 1081 /* 1082 * If port == 0, it means we have only one port and the parent 1083 * device, not this port device, should be the holder of the 1084 * hw_counters 1085 */ 1086 if (device->alloc_hw_stats && port_num) 1087 setup_hw_stats(device, p, port_num); 1088 1089 list_add_tail(&p->kobj.entry, &device->port_list); 1090 1091 return 0; 1092 1093 err_remove_pkey: 1094 sysfs_remove_group(&p->kobj, &p->pkey_group); 1095 1096 err_free_pkey: 1097 for (i = 0; i < attr.pkey_tbl_len; ++i) 1098 kfree(p->pkey_group.attrs[i]); 1099 1100 kfree(p->pkey_group.attrs); 1101 p->pkey_group.attrs = NULL; 1102 1103 err_remove_gid_type: 1104 sysfs_remove_group(&p->gid_attr_group->kobj, 1105 &p->gid_attr_group->type); 1106 1107 err_free_gid_type: 1108 for (i = 0; i < attr.gid_tbl_len; ++i) 1109 kfree(p->gid_attr_group->type.attrs[i]); 1110 1111 kfree(p->gid_attr_group->type.attrs); 1112 p->gid_attr_group->type.attrs = NULL; 1113 1114 err_remove_gid_ndev: 1115 sysfs_remove_group(&p->gid_attr_group->kobj, 1116 &p->gid_attr_group->ndev); 1117 1118 err_free_gid_ndev: 1119 for (i = 0; i < attr.gid_tbl_len; ++i) 1120 kfree(p->gid_attr_group->ndev.attrs[i]); 1121 1122 kfree(p->gid_attr_group->ndev.attrs); 1123 p->gid_attr_group->ndev.attrs = NULL; 1124 1125 err_remove_gid: 1126 sysfs_remove_group(&p->kobj, &p->gid_group); 1127 1128 err_free_gid: 1129 for (i = 0; i < attr.gid_tbl_len; ++i) 1130 kfree(p->gid_group.attrs[i]); 1131 1132 kfree(p->gid_group.attrs); 1133 p->gid_group.attrs = NULL; 1134 1135 err_remove_pma: 1136 sysfs_remove_group(&p->kobj, p->pma_table); 1137 1138 err_put_gid_attrs: 1139 kobject_put(&p->gid_attr_group->kobj); 1140 1141 err_put: 1142 kobject_put(&p->kobj); 1143 return ret; 1144 } 1145 1146 static ssize_t show_node_type(struct device *device, 1147 struct device_attribute *attr, char *buf) 1148 { 1149 struct ib_device *dev = container_of(device, struct ib_device, dev); 1150 1151 switch (dev->node_type) { 1152 case RDMA_NODE_IB_CA: return sprintf(buf, "%d: CA\n", dev->node_type); 1153 case RDMA_NODE_RNIC: return sprintf(buf, "%d: RNIC\n", dev->node_type); 1154 case RDMA_NODE_USNIC: return sprintf(buf, "%d: usNIC\n", dev->node_type); 1155 case RDMA_NODE_USNIC_UDP: return sprintf(buf, "%d: usNIC UDP\n", dev->node_type); 1156 case RDMA_NODE_IB_SWITCH: return sprintf(buf, "%d: switch\n", dev->node_type); 1157 case RDMA_NODE_IB_ROUTER: return sprintf(buf, "%d: router\n", dev->node_type); 1158 default: return sprintf(buf, "%d: <unknown>\n", dev->node_type); 1159 } 1160 } 1161 1162 static ssize_t show_sys_image_guid(struct device *device, 1163 struct device_attribute *dev_attr, char *buf) 1164 { 1165 struct ib_device *dev = container_of(device, struct ib_device, dev); 1166 1167 return sprintf(buf, "%04x:%04x:%04x:%04x\n", 1168 be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[0]), 1169 be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[1]), 1170 be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[2]), 1171 be16_to_cpu(((__be16 *) &dev->attrs.sys_image_guid)[3])); 1172 } 1173 1174 static ssize_t show_node_guid(struct device *device, 1175 struct device_attribute *attr, char *buf) 1176 { 1177 struct ib_device *dev = container_of(device, struct ib_device, dev); 1178 1179 return sprintf(buf, "%04x:%04x:%04x:%04x\n", 1180 be16_to_cpu(((__be16 *) &dev->node_guid)[0]), 1181 be16_to_cpu(((__be16 *) &dev->node_guid)[1]), 1182 be16_to_cpu(((__be16 *) &dev->node_guid)[2]), 1183 be16_to_cpu(((__be16 *) &dev->node_guid)[3])); 1184 } 1185 1186 static ssize_t show_node_desc(struct device *device, 1187 struct device_attribute *attr, char *buf) 1188 { 1189 struct ib_device *dev = container_of(device, struct ib_device, dev); 1190 1191 return sprintf(buf, "%.64s\n", dev->node_desc); 1192 } 1193 1194 static ssize_t set_node_desc(struct device *device, 1195 struct device_attribute *attr, 1196 const char *buf, size_t count) 1197 { 1198 struct ib_device *dev = container_of(device, struct ib_device, dev); 1199 struct ib_device_modify desc = {}; 1200 int ret; 1201 1202 if (!dev->modify_device) 1203 return -EIO; 1204 1205 memcpy(desc.node_desc, buf, min_t(int, count, IB_DEVICE_NODE_DESC_MAX)); 1206 ret = ib_modify_device(dev, IB_DEVICE_MODIFY_NODE_DESC, &desc); 1207 if (ret) 1208 return ret; 1209 1210 return count; 1211 } 1212 1213 static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr, 1214 char *buf) 1215 { 1216 struct ib_device *dev = container_of(device, struct ib_device, dev); 1217 1218 ib_get_device_fw_str(dev, buf, PAGE_SIZE); 1219 strlcat(buf, "\n", PAGE_SIZE); 1220 return strlen(buf); 1221 } 1222 1223 static DEVICE_ATTR(node_type, S_IRUGO, show_node_type, NULL); 1224 static DEVICE_ATTR(sys_image_guid, S_IRUGO, show_sys_image_guid, NULL); 1225 static DEVICE_ATTR(node_guid, S_IRUGO, show_node_guid, NULL); 1226 static DEVICE_ATTR(node_desc, S_IRUGO | S_IWUSR, show_node_desc, set_node_desc); 1227 static DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); 1228 1229 static struct device_attribute *ib_class_attributes[] = { 1230 &dev_attr_node_type, 1231 &dev_attr_sys_image_guid, 1232 &dev_attr_node_guid, 1233 &dev_attr_node_desc, 1234 &dev_attr_fw_ver, 1235 }; 1236 1237 static void free_port_list_attributes(struct ib_device *device) 1238 { 1239 struct kobject *p, *t; 1240 1241 list_for_each_entry_safe(p, t, &device->port_list, entry) { 1242 struct ib_port *port = container_of(p, struct ib_port, kobj); 1243 list_del(&p->entry); 1244 if (port->hw_stats) { 1245 kfree(port->hw_stats); 1246 free_hsag(&port->kobj, port->hw_stats_ag); 1247 } 1248 sysfs_remove_group(p, port->pma_table); 1249 sysfs_remove_group(p, &port->pkey_group); 1250 sysfs_remove_group(p, &port->gid_group); 1251 sysfs_remove_group(&port->gid_attr_group->kobj, 1252 &port->gid_attr_group->ndev); 1253 sysfs_remove_group(&port->gid_attr_group->kobj, 1254 &port->gid_attr_group->type); 1255 kobject_put(&port->gid_attr_group->kobj); 1256 kobject_put(p); 1257 } 1258 1259 kobject_put(device->ports_parent); 1260 } 1261 1262 int ib_device_register_sysfs(struct ib_device *device, 1263 int (*port_callback)(struct ib_device *, 1264 u8, struct kobject *)) 1265 { 1266 struct device *class_dev = &device->dev; 1267 int ret; 1268 int i; 1269 1270 device->dev.parent = device->dma_device; 1271 ret = dev_set_name(class_dev, "%s", device->name); 1272 if (ret) 1273 return ret; 1274 1275 ret = device_add(class_dev); 1276 if (ret) 1277 goto err; 1278 1279 for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) { 1280 ret = device_create_file(class_dev, ib_class_attributes[i]); 1281 if (ret) 1282 goto err_unregister; 1283 } 1284 1285 device->ports_parent = kobject_create_and_add("ports", 1286 &class_dev->kobj); 1287 if (!device->ports_parent) { 1288 ret = -ENOMEM; 1289 goto err_put; 1290 } 1291 1292 if (rdma_cap_ib_switch(device)) { 1293 ret = add_port(device, 0, port_callback); 1294 if (ret) 1295 goto err_put; 1296 } else { 1297 for (i = 1; i <= device->phys_port_cnt; ++i) { 1298 ret = add_port(device, i, port_callback); 1299 if (ret) 1300 goto err_put; 1301 } 1302 } 1303 1304 if (device->alloc_hw_stats) 1305 setup_hw_stats(device, NULL, 0); 1306 1307 return 0; 1308 1309 err_put: 1310 free_port_list_attributes(device); 1311 1312 err_unregister: 1313 device_unregister(class_dev); 1314 1315 err: 1316 return ret; 1317 } 1318 1319 void ib_device_unregister_sysfs(struct ib_device *device) 1320 { 1321 int i; 1322 1323 /* Hold kobject until ib_dealloc_device() */ 1324 kobject_get(&device->dev.kobj); 1325 1326 free_port_list_attributes(device); 1327 1328 if (device->hw_stats) { 1329 kfree(device->hw_stats); 1330 free_hsag(&device->dev.kobj, device->hw_stats_ag); 1331 } 1332 1333 for (i = 0; i < ARRAY_SIZE(ib_class_attributes); ++i) 1334 device_remove_file(&device->dev, ib_class_attributes[i]); 1335 1336 device_unregister(&device->dev); 1337 } 1338