ipath_sysfs.c revision 657c2f2cbccbac88689ac5174fc13dd3f9aece34
1/* 2 * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. 3 * Copyright (c) 2006 PathScale, Inc. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 */ 33 34#include <linux/ctype.h> 35 36#include "ipath_kernel.h" 37#include "ipath_common.h" 38 39/** 40 * ipath_parse_ushort - parse an unsigned short value in an arbitrary base 41 * @str: the string containing the number 42 * @valp: where to put the result 43 * 44 * returns the number of bytes consumed, or negative value on error 45 */ 46int ipath_parse_ushort(const char *str, unsigned short *valp) 47{ 48 unsigned long val; 49 char *end; 50 int ret; 51 52 if (!isdigit(str[0])) { 53 ret = -EINVAL; 54 goto bail; 55 } 56 57 val = simple_strtoul(str, &end, 0); 58 59 if (val > 0xffff) { 60 ret = -EINVAL; 61 goto bail; 62 } 63 64 *valp = val; 65 66 ret = end + 1 - str; 67 if (ret == 0) 68 ret = -EINVAL; 69 70bail: 71 return ret; 72} 73 74static ssize_t show_version(struct device_driver *dev, char *buf) 75{ 76 /* The string printed here is already newline-terminated. */ 77 return scnprintf(buf, PAGE_SIZE, "%s", ib_ipath_version); 78} 79 80static ssize_t show_num_units(struct device_driver *dev, char *buf) 81{ 82 return scnprintf(buf, PAGE_SIZE, "%d\n", 83 ipath_count_units(NULL, NULL, NULL)); 84} 85 86static ssize_t show_status(struct device *dev, 87 struct device_attribute *attr, 88 char *buf) 89{ 90 struct ipath_devdata *dd = dev_get_drvdata(dev); 91 ssize_t ret; 92 93 if (!dd->ipath_statusp) { 94 ret = -EINVAL; 95 goto bail; 96 } 97 98 ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n", 99 (unsigned long long) *(dd->ipath_statusp)); 100 101bail: 102 return ret; 103} 104 105static const char *ipath_status_str[] = { 106 "Initted", 107 "Disabled", 108 "Admin_Disabled", 109 "", /* This used to be the old "OIB_SMA" status. */ 110 "", /* This used to be the old "SMA" status. */ 111 "Present", 112 "IB_link_up", 113 "IB_configured", 114 "NoIBcable", 115 "Fatal_Hardware_Error", 116 NULL, 117}; 118 119static ssize_t show_status_str(struct device *dev, 120 struct device_attribute *attr, 121 char *buf) 122{ 123 struct ipath_devdata *dd = dev_get_drvdata(dev); 124 int i, any; 125 u64 s; 126 ssize_t ret; 127 128 if (!dd->ipath_statusp) { 129 ret = -EINVAL; 130 goto bail; 131 } 132 133 s = *(dd->ipath_statusp); 134 *buf = '\0'; 135 for (any = i = 0; s && ipath_status_str[i]; i++) { 136 if (s & 1) { 137 if (any && strlcat(buf, " ", PAGE_SIZE) >= 138 PAGE_SIZE) 139 /* overflow */ 140 break; 141 if (strlcat(buf, ipath_status_str[i], 142 PAGE_SIZE) >= PAGE_SIZE) 143 break; 144 any = 1; 145 } 146 s >>= 1; 147 } 148 if (any) 149 strlcat(buf, "\n", PAGE_SIZE); 150 151 ret = strlen(buf); 152 153bail: 154 return ret; 155} 156 157static ssize_t show_boardversion(struct device *dev, 158 struct device_attribute *attr, 159 char *buf) 160{ 161 struct ipath_devdata *dd = dev_get_drvdata(dev); 162 /* The string printed here is already newline-terminated. */ 163 return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion); 164} 165 166static ssize_t show_lmc(struct device *dev, 167 struct device_attribute *attr, 168 char *buf) 169{ 170 struct ipath_devdata *dd = dev_get_drvdata(dev); 171 172 return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_lmc); 173} 174 175static ssize_t store_lmc(struct device *dev, 176 struct device_attribute *attr, 177 const char *buf, 178 size_t count) 179{ 180 struct ipath_devdata *dd = dev_get_drvdata(dev); 181 u16 lmc = 0; 182 int ret; 183 184 ret = ipath_parse_ushort(buf, &lmc); 185 if (ret < 0) 186 goto invalid; 187 188 if (lmc > 7) { 189 ret = -EINVAL; 190 goto invalid; 191 } 192 193 ipath_set_lid(dd, dd->ipath_lid, lmc); 194 195 goto bail; 196invalid: 197 ipath_dev_err(dd, "attempt to set invalid LMC %u\n", lmc); 198bail: 199 return ret; 200} 201 202static ssize_t show_lid(struct device *dev, 203 struct device_attribute *attr, 204 char *buf) 205{ 206 struct ipath_devdata *dd = dev_get_drvdata(dev); 207 208 return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid); 209} 210 211static ssize_t store_lid(struct device *dev, 212 struct device_attribute *attr, 213 const char *buf, 214 size_t count) 215{ 216 struct ipath_devdata *dd = dev_get_drvdata(dev); 217 u16 lid = 0; 218 int ret; 219 220 ret = ipath_parse_ushort(buf, &lid); 221 if (ret < 0) 222 goto invalid; 223 224 if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) { 225 ret = -EINVAL; 226 goto invalid; 227 } 228 229 ipath_set_lid(dd, lid, dd->ipath_lmc); 230 231 goto bail; 232invalid: 233 ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid); 234bail: 235 return ret; 236} 237 238static ssize_t show_mlid(struct device *dev, 239 struct device_attribute *attr, 240 char *buf) 241{ 242 struct ipath_devdata *dd = dev_get_drvdata(dev); 243 244 return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid); 245} 246 247static ssize_t store_mlid(struct device *dev, 248 struct device_attribute *attr, 249 const char *buf, 250 size_t count) 251{ 252 struct ipath_devdata *dd = dev_get_drvdata(dev); 253 u16 mlid; 254 int ret; 255 256 ret = ipath_parse_ushort(buf, &mlid); 257 if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE) 258 goto invalid; 259 260 dd->ipath_mlid = mlid; 261 262 goto bail; 263invalid: 264 ipath_dev_err(dd, "attempt to set invalid MLID\n"); 265bail: 266 return ret; 267} 268 269static ssize_t show_guid(struct device *dev, 270 struct device_attribute *attr, 271 char *buf) 272{ 273 struct ipath_devdata *dd = dev_get_drvdata(dev); 274 u8 *guid; 275 276 guid = (u8 *) & (dd->ipath_guid); 277 278 return scnprintf(buf, PAGE_SIZE, 279 "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", 280 guid[0], guid[1], guid[2], guid[3], 281 guid[4], guid[5], guid[6], guid[7]); 282} 283 284static ssize_t store_guid(struct device *dev, 285 struct device_attribute *attr, 286 const char *buf, 287 size_t count) 288{ 289 struct ipath_devdata *dd = dev_get_drvdata(dev); 290 ssize_t ret; 291 unsigned short guid[8]; 292 __be64 new_guid; 293 u8 *ng; 294 int i; 295 296 if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx", 297 &guid[0], &guid[1], &guid[2], &guid[3], 298 &guid[4], &guid[5], &guid[6], &guid[7]) != 8) 299 goto invalid; 300 301 ng = (u8 *) &new_guid; 302 303 for (i = 0; i < 8; i++) { 304 if (guid[i] > 0xff) 305 goto invalid; 306 ng[i] = guid[i]; 307 } 308 309 if (new_guid == 0) 310 goto invalid; 311 312 dd->ipath_guid = new_guid; 313 dd->ipath_nguid = 1; 314 315 ret = strlen(buf); 316 goto bail; 317 318invalid: 319 ipath_dev_err(dd, "attempt to set invalid GUID\n"); 320 ret = -EINVAL; 321 322bail: 323 return ret; 324} 325 326static ssize_t show_nguid(struct device *dev, 327 struct device_attribute *attr, 328 char *buf) 329{ 330 struct ipath_devdata *dd = dev_get_drvdata(dev); 331 332 return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid); 333} 334 335static ssize_t show_nports(struct device *dev, 336 struct device_attribute *attr, 337 char *buf) 338{ 339 struct ipath_devdata *dd = dev_get_drvdata(dev); 340 341 /* Return the number of user ports available. */ 342 return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1); 343} 344 345static ssize_t show_serial(struct device *dev, 346 struct device_attribute *attr, 347 char *buf) 348{ 349 struct ipath_devdata *dd = dev_get_drvdata(dev); 350 351 buf[sizeof dd->ipath_serial] = '\0'; 352 memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial); 353 strcat(buf, "\n"); 354 return strlen(buf); 355} 356 357static ssize_t show_unit(struct device *dev, 358 struct device_attribute *attr, 359 char *buf) 360{ 361 struct ipath_devdata *dd = dev_get_drvdata(dev); 362 363 return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit); 364} 365 366#define DEVICE_COUNTER(name, attr) \ 367 static ssize_t show_counter_##name(struct device *dev, \ 368 struct device_attribute *attr, \ 369 char *buf) \ 370 { \ 371 struct ipath_devdata *dd = dev_get_drvdata(dev); \ 372 return scnprintf(\ 373 buf, PAGE_SIZE, "%llu\n", (unsigned long long) \ 374 ipath_snap_cntr( \ 375 dd, offsetof(struct infinipath_counters, \ 376 attr) / sizeof(u64))); \ 377 } \ 378 static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL); 379 380DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt); 381DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt); 382DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt); 383DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt); 384DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt); 385DEVICE_COUNTER(lb_ints, LBIntCnt); 386DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt); 387DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt); 388DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt); 389DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt); 390DEVICE_COUNTER(rx_dwords, RxDwordCnt); 391DEVICE_COUNTER(rx_ebps, RxEBPCnt); 392DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt); 393DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt); 394DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt); 395DEVICE_COUNTER(rx_len_errs, RxLenErrCnt); 396DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt); 397DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt); 398DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt); 399DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt); 400DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt); 401DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt); 402DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt); 403DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt); 404DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt); 405DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt); 406DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt); 407DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt); 408DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt); 409DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt); 410DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt); 411DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt); 412DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt); 413DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt); 414DEVICE_COUNTER(tx_dwords, TxDwordCnt); 415DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt); 416DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt); 417DEVICE_COUNTER(tx_len_errs, TxLenErrCnt); 418DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt); 419DEVICE_COUNTER(tx_underruns, TxUnderrunCnt); 420DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt); 421 422static struct attribute *dev_counter_attributes[] = { 423 &dev_attr_ib_link_downeds.attr, 424 &dev_attr_ib_link_err_recoveries.attr, 425 &dev_attr_ib_status_changes.attr, 426 &dev_attr_ib_symbol_errs.attr, 427 &dev_attr_lb_flow_stalls.attr, 428 &dev_attr_lb_ints.attr, 429 &dev_attr_rx_bad_formats.attr, 430 &dev_attr_rx_buf_ovfls.attr, 431 &dev_attr_rx_data_pkts.attr, 432 &dev_attr_rx_dropped_pkts.attr, 433 &dev_attr_rx_dwords.attr, 434 &dev_attr_rx_ebps.attr, 435 &dev_attr_rx_flow_ctrl_errs.attr, 436 &dev_attr_rx_flow_pkts.attr, 437 &dev_attr_rx_icrc_errs.attr, 438 &dev_attr_rx_len_errs.attr, 439 &dev_attr_rx_link_problems.attr, 440 &dev_attr_rx_lpcrc_errs.attr, 441 &dev_attr_rx_max_min_len_errs.attr, 442 &dev_attr_rx_p0_hdr_egr_ovfls.attr, 443 &dev_attr_rx_p1_hdr_egr_ovfls.attr, 444 &dev_attr_rx_p2_hdr_egr_ovfls.attr, 445 &dev_attr_rx_p3_hdr_egr_ovfls.attr, 446 &dev_attr_rx_p4_hdr_egr_ovfls.attr, 447 &dev_attr_rx_p5_hdr_egr_ovfls.attr, 448 &dev_attr_rx_p6_hdr_egr_ovfls.attr, 449 &dev_attr_rx_p7_hdr_egr_ovfls.attr, 450 &dev_attr_rx_p8_hdr_egr_ovfls.attr, 451 &dev_attr_rx_pkey_mismatches.attr, 452 &dev_attr_rx_tid_full_errs.attr, 453 &dev_attr_rx_tid_valid_errs.attr, 454 &dev_attr_rx_vcrc_errs.attr, 455 &dev_attr_tx_data_pkts.attr, 456 &dev_attr_tx_dropped_pkts.attr, 457 &dev_attr_tx_dwords.attr, 458 &dev_attr_tx_flow_pkts.attr, 459 &dev_attr_tx_flow_stalls.attr, 460 &dev_attr_tx_len_errs.attr, 461 &dev_attr_tx_max_min_len_errs.attr, 462 &dev_attr_tx_underruns.attr, 463 &dev_attr_tx_unsup_vl_errs.attr, 464 NULL 465}; 466 467static struct attribute_group dev_counter_attr_group = { 468 .name = "counters", 469 .attrs = dev_counter_attributes 470}; 471 472static ssize_t store_reset(struct device *dev, 473 struct device_attribute *attr, 474 const char *buf, 475 size_t count) 476{ 477 struct ipath_devdata *dd = dev_get_drvdata(dev); 478 int ret; 479 480 if (count < 5 || memcmp(buf, "reset", 5)) { 481 ret = -EINVAL; 482 goto bail; 483 } 484 485 if (dd->ipath_flags & IPATH_DISABLED) { 486 /* 487 * post-reset init would re-enable interrupts, etc. 488 * so don't allow reset on disabled devices. Not 489 * perfect error, but about the best choice. 490 */ 491 dev_info(dev,"Unit %d is disabled, can't reset\n", 492 dd->ipath_unit); 493 ret = -EINVAL; 494 } 495 ret = ipath_reset_device(dd->ipath_unit); 496bail: 497 return ret<0 ? ret : count; 498} 499 500static ssize_t store_link_state(struct device *dev, 501 struct device_attribute *attr, 502 const char *buf, 503 size_t count) 504{ 505 struct ipath_devdata *dd = dev_get_drvdata(dev); 506 int ret, r; 507 u16 state; 508 509 ret = ipath_parse_ushort(buf, &state); 510 if (ret < 0) 511 goto invalid; 512 513 r = ipath_set_linkstate(dd, state); 514 if (r < 0) { 515 ret = r; 516 goto bail; 517 } 518 519 goto bail; 520invalid: 521 ipath_dev_err(dd, "attempt to set invalid link state\n"); 522bail: 523 return ret; 524} 525 526static ssize_t show_mtu(struct device *dev, 527 struct device_attribute *attr, 528 char *buf) 529{ 530 struct ipath_devdata *dd = dev_get_drvdata(dev); 531 return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu); 532} 533 534static ssize_t store_mtu(struct device *dev, 535 struct device_attribute *attr, 536 const char *buf, 537 size_t count) 538{ 539 struct ipath_devdata *dd = dev_get_drvdata(dev); 540 ssize_t ret; 541 u16 mtu = 0; 542 int r; 543 544 ret = ipath_parse_ushort(buf, &mtu); 545 if (ret < 0) 546 goto invalid; 547 548 r = ipath_set_mtu(dd, mtu); 549 if (r < 0) 550 ret = r; 551 552 goto bail; 553invalid: 554 ipath_dev_err(dd, "attempt to set invalid MTU\n"); 555bail: 556 return ret; 557} 558 559static ssize_t show_enabled(struct device *dev, 560 struct device_attribute *attr, 561 char *buf) 562{ 563 struct ipath_devdata *dd = dev_get_drvdata(dev); 564 return scnprintf(buf, PAGE_SIZE, "%u\n", 565 (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1); 566} 567 568static ssize_t store_enabled(struct device *dev, 569 struct device_attribute *attr, 570 const char *buf, 571 size_t count) 572{ 573 struct ipath_devdata *dd = dev_get_drvdata(dev); 574 ssize_t ret; 575 u16 enable = 0; 576 577 ret = ipath_parse_ushort(buf, &enable); 578 if (ret < 0) { 579 ipath_dev_err(dd, "attempt to use non-numeric on enable\n"); 580 goto bail; 581 } 582 583 if (enable) { 584 if (!(dd->ipath_flags & IPATH_DISABLED)) 585 goto bail; 586 587 dev_info(dev, "Enabling unit %d\n", dd->ipath_unit); 588 /* same as post-reset */ 589 ret = ipath_init_chip(dd, 1); 590 if (ret) 591 ipath_dev_err(dd, "Failed to enable unit %d\n", 592 dd->ipath_unit); 593 else { 594 dd->ipath_flags &= ~IPATH_DISABLED; 595 *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED; 596 } 597 } 598 else if (!(dd->ipath_flags & IPATH_DISABLED)) { 599 dev_info(dev, "Disabling unit %d\n", dd->ipath_unit); 600 ipath_shutdown_device(dd); 601 dd->ipath_flags |= IPATH_DISABLED; 602 *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED; 603 } 604 605bail: 606 return ret; 607} 608 609static ssize_t store_rx_pol_inv(struct device *dev, 610 struct device_attribute *attr, 611 const char *buf, 612 size_t count) 613{ 614 struct ipath_devdata *dd = dev_get_drvdata(dev); 615 int ret, r; 616 u16 val; 617 618 ret = ipath_parse_ushort(buf, &val); 619 if (ret < 0) 620 goto invalid; 621 622 r = ipath_set_rx_pol_inv(dd, val); 623 if (r < 0) { 624 ret = r; 625 goto bail; 626 } 627 628 goto bail; 629invalid: 630 ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n"); 631bail: 632 return ret; 633} 634 635static ssize_t store_led_override(struct device *dev, 636 struct device_attribute *attr, 637 const char *buf, 638 size_t count) 639{ 640 struct ipath_devdata *dd = dev_get_drvdata(dev); 641 int ret; 642 u16 val; 643 644 ret = ipath_parse_ushort(buf, &val); 645 if (ret > 0) 646 ipath_set_led_override(dd, val); 647 else 648 ipath_dev_err(dd, "attempt to set invalid LED override\n"); 649 return ret; 650} 651 652static ssize_t show_logged_errs(struct device *dev, 653 struct device_attribute *attr, 654 char *buf) 655{ 656 struct ipath_devdata *dd = dev_get_drvdata(dev); 657 int idx, count; 658 659 /* force consistency with actual EEPROM */ 660 if (ipath_update_eeprom_log(dd) != 0) 661 return -ENXIO; 662 663 count = 0; 664 for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) { 665 count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", 666 dd->ipath_eep_st_errs[idx], 667 idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' '); 668 } 669 670 return count; 671} 672 673static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL); 674static DRIVER_ATTR(version, S_IRUGO, show_version, NULL); 675 676static struct attribute *driver_attributes[] = { 677 &driver_attr_num_units.attr, 678 &driver_attr_version.attr, 679 NULL 680}; 681 682static struct attribute_group driver_attr_group = { 683 .attrs = driver_attributes 684}; 685 686struct attribute_group *ipath_driver_attr_groups[] = { 687 &driver_attr_group, 688 NULL, 689}; 690 691static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid); 692static DEVICE_ATTR(lmc, S_IWUSR | S_IRUGO, show_lmc, store_lmc); 693static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid); 694static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state); 695static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid); 696static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu); 697static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled); 698static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL); 699static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL); 700static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset); 701static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); 702static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); 703static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL); 704static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); 705static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL); 706static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv); 707static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override); 708static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); 709 710static struct attribute *dev_attributes[] = { 711 &dev_attr_guid.attr, 712 &dev_attr_lmc.attr, 713 &dev_attr_lid.attr, 714 &dev_attr_link_state.attr, 715 &dev_attr_mlid.attr, 716 &dev_attr_mtu.attr, 717 &dev_attr_nguid.attr, 718 &dev_attr_nports.attr, 719 &dev_attr_serial.attr, 720 &dev_attr_status.attr, 721 &dev_attr_status_str.attr, 722 &dev_attr_boardversion.attr, 723 &dev_attr_unit.attr, 724 &dev_attr_enabled.attr, 725 &dev_attr_rx_pol_inv.attr, 726 &dev_attr_led_override.attr, 727 &dev_attr_logged_errors.attr, 728 NULL 729}; 730 731static struct attribute_group dev_attr_group = { 732 .attrs = dev_attributes 733}; 734 735/** 736 * ipath_expose_reset - create a device reset file 737 * @dev: the device structure 738 * 739 * Only expose a file that lets us reset the device after someone 740 * enters diag mode. A device reset is quite likely to crash the 741 * machine entirely, so we don't want to normally make it 742 * available. 743 * 744 * Called with ipath_mutex held. 745 */ 746int ipath_expose_reset(struct device *dev) 747{ 748 static int exposed; 749 int ret; 750 751 if (!exposed) { 752 ret = device_create_file(dev, &dev_attr_reset); 753 exposed = 1; 754 } 755 else 756 ret = 0; 757 758 return ret; 759} 760 761int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd) 762{ 763 int ret; 764 765 ret = sysfs_create_group(&dev->kobj, &dev_attr_group); 766 if (ret) 767 goto bail; 768 769 ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group); 770 if (ret) 771 goto bail_attrs; 772 773 return 0; 774 775bail_attrs: 776 sysfs_remove_group(&dev->kobj, &dev_attr_group); 777bail: 778 return ret; 779} 780 781void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd) 782{ 783 sysfs_remove_group(&dev->kobj, &dev_counter_attr_group); 784 sysfs_remove_group(&dev->kobj, &dev_attr_group); 785 786 device_remove_file(dev, &dev_attr_reset); 787} 788