linux/drivers/infiniband/hw/ipath/ipath_sysfs.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2006, 2007, 2008 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#include <linux/stat.h>
  36
  37#include "ipath_kernel.h"
  38#include "ipath_verbs.h"
  39#include "ipath_common.h"
  40
  41/**
  42 * ipath_parse_ushort - parse an unsigned short value in an arbitrary base
  43 * @str: the string containing the number
  44 * @valp: where to put the result
  45 *
  46 * returns the number of bytes consumed, or negative value on error
  47 */
  48int ipath_parse_ushort(const char *str, unsigned short *valp)
  49{
  50        unsigned long val;
  51        char *end;
  52        int ret;
  53
  54        if (!isdigit(str[0])) {
  55                ret = -EINVAL;
  56                goto bail;
  57        }
  58
  59        val = simple_strtoul(str, &end, 0);
  60
  61        if (val > 0xffff) {
  62                ret = -EINVAL;
  63                goto bail;
  64        }
  65
  66        *valp = val;
  67
  68        ret = end + 1 - str;
  69        if (ret == 0)
  70                ret = -EINVAL;
  71
  72bail:
  73        return ret;
  74}
  75
  76static ssize_t show_version(struct device_driver *dev, char *buf)
  77{
  78        /* The string printed here is already newline-terminated. */
  79        return scnprintf(buf, PAGE_SIZE, "%s", ib_ipath_version);
  80}
  81
  82static ssize_t show_num_units(struct device_driver *dev, char *buf)
  83{
  84        return scnprintf(buf, PAGE_SIZE, "%d\n",
  85                         ipath_count_units(NULL, NULL, NULL));
  86}
  87
  88static ssize_t show_status(struct device *dev,
  89                           struct device_attribute *attr,
  90                           char *buf)
  91{
  92        struct ipath_devdata *dd = dev_get_drvdata(dev);
  93        ssize_t ret;
  94
  95        if (!dd->ipath_statusp) {
  96                ret = -EINVAL;
  97                goto bail;
  98        }
  99
 100        ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n",
 101                        (unsigned long long) *(dd->ipath_statusp));
 102
 103bail:
 104        return ret;
 105}
 106
 107static const char *ipath_status_str[] = {
 108        "Initted",
 109        "Disabled",
 110        "Admin_Disabled",
 111        "", /* This used to be the old "OIB_SMA" status. */
 112        "", /* This used to be the old "SMA" status. */
 113        "Present",
 114        "IB_link_up",
 115        "IB_configured",
 116        "NoIBcable",
 117        "Fatal_Hardware_Error",
 118        NULL,
 119};
 120
 121static ssize_t show_status_str(struct device *dev,
 122                               struct device_attribute *attr,
 123                               char *buf)
 124{
 125        struct ipath_devdata *dd = dev_get_drvdata(dev);
 126        int i, any;
 127        u64 s;
 128        ssize_t ret;
 129
 130        if (!dd->ipath_statusp) {
 131                ret = -EINVAL;
 132                goto bail;
 133        }
 134
 135        s = *(dd->ipath_statusp);
 136        *buf = '\0';
 137        for (any = i = 0; s && ipath_status_str[i]; i++) {
 138                if (s & 1) {
 139                        if (any && strlcat(buf, " ", PAGE_SIZE) >=
 140                            PAGE_SIZE)
 141                                /* overflow */
 142                                break;
 143                        if (strlcat(buf, ipath_status_str[i],
 144                                    PAGE_SIZE) >= PAGE_SIZE)
 145                                break;
 146                        any = 1;
 147                }
 148                s >>= 1;
 149        }
 150        if (any)
 151                strlcat(buf, "\n", PAGE_SIZE);
 152
 153        ret = strlen(buf);
 154
 155bail:
 156        return ret;
 157}
 158
 159static ssize_t show_boardversion(struct device *dev,
 160                               struct device_attribute *attr,
 161                               char *buf)
 162{
 163        struct ipath_devdata *dd = dev_get_drvdata(dev);
 164        /* The string printed here is already newline-terminated. */
 165        return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_boardversion);
 166}
 167
 168static ssize_t show_localbus_info(struct device *dev,
 169                               struct device_attribute *attr,
 170                               char *buf)
 171{
 172        struct ipath_devdata *dd = dev_get_drvdata(dev);
 173        /* The string printed here is already newline-terminated. */
 174        return scnprintf(buf, PAGE_SIZE, "%s", dd->ipath_lbus_info);
 175}
 176
 177static ssize_t show_lmc(struct device *dev,
 178                        struct device_attribute *attr,
 179                        char *buf)
 180{
 181        struct ipath_devdata *dd = dev_get_drvdata(dev);
 182
 183        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_lmc);
 184}
 185
 186static ssize_t store_lmc(struct device *dev,
 187                         struct device_attribute *attr,
 188                         const char *buf,
 189                         size_t count)
 190{
 191        struct ipath_devdata *dd = dev_get_drvdata(dev);
 192        u16 lmc = 0;
 193        int ret;
 194
 195        ret = ipath_parse_ushort(buf, &lmc);
 196        if (ret < 0)
 197                goto invalid;
 198
 199        if (lmc > 7) {
 200                ret = -EINVAL;
 201                goto invalid;
 202        }
 203
 204        ipath_set_lid(dd, dd->ipath_lid, lmc);
 205
 206        goto bail;
 207invalid:
 208        ipath_dev_err(dd, "attempt to set invalid LMC %u\n", lmc);
 209bail:
 210        return ret;
 211}
 212
 213static ssize_t show_lid(struct device *dev,
 214                        struct device_attribute *attr,
 215                        char *buf)
 216{
 217        struct ipath_devdata *dd = dev_get_drvdata(dev);
 218
 219        return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_lid);
 220}
 221
 222static ssize_t store_lid(struct device *dev,
 223                         struct device_attribute *attr,
 224                          const char *buf,
 225                          size_t count)
 226{
 227        struct ipath_devdata *dd = dev_get_drvdata(dev);
 228        u16 lid = 0;
 229        int ret;
 230
 231        ret = ipath_parse_ushort(buf, &lid);
 232        if (ret < 0)
 233                goto invalid;
 234
 235        if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE) {
 236                ret = -EINVAL;
 237                goto invalid;
 238        }
 239
 240        ipath_set_lid(dd, lid, dd->ipath_lmc);
 241
 242        goto bail;
 243invalid:
 244        ipath_dev_err(dd, "attempt to set invalid LID 0x%x\n", lid);
 245bail:
 246        return ret;
 247}
 248
 249static ssize_t show_mlid(struct device *dev,
 250                         struct device_attribute *attr,
 251                         char *buf)
 252{
 253        struct ipath_devdata *dd = dev_get_drvdata(dev);
 254
 255        return scnprintf(buf, PAGE_SIZE, "0x%x\n", dd->ipath_mlid);
 256}
 257
 258static ssize_t store_mlid(struct device *dev,
 259                         struct device_attribute *attr,
 260                          const char *buf,
 261                          size_t count)
 262{
 263        struct ipath_devdata *dd = dev_get_drvdata(dev);
 264        u16 mlid;
 265        int ret;
 266
 267        ret = ipath_parse_ushort(buf, &mlid);
 268        if (ret < 0 || mlid < IPATH_MULTICAST_LID_BASE)
 269                goto invalid;
 270
 271        dd->ipath_mlid = mlid;
 272
 273        goto bail;
 274invalid:
 275        ipath_dev_err(dd, "attempt to set invalid MLID\n");
 276bail:
 277        return ret;
 278}
 279
 280static ssize_t show_guid(struct device *dev,
 281                         struct device_attribute *attr,
 282                         char *buf)
 283{
 284        struct ipath_devdata *dd = dev_get_drvdata(dev);
 285        u8 *guid;
 286
 287        guid = (u8 *) & (dd->ipath_guid);
 288
 289        return scnprintf(buf, PAGE_SIZE,
 290                         "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 291                         guid[0], guid[1], guid[2], guid[3],
 292                         guid[4], guid[5], guid[6], guid[7]);
 293}
 294
 295static ssize_t store_guid(struct device *dev,
 296                         struct device_attribute *attr,
 297                          const char *buf,
 298                          size_t count)
 299{
 300        struct ipath_devdata *dd = dev_get_drvdata(dev);
 301        ssize_t ret;
 302        unsigned short guid[8];
 303        __be64 new_guid;
 304        u8 *ng;
 305        int i;
 306
 307        if (sscanf(buf, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
 308                   &guid[0], &guid[1], &guid[2], &guid[3],
 309                   &guid[4], &guid[5], &guid[6], &guid[7]) != 8)
 310                goto invalid;
 311
 312        ng = (u8 *) &new_guid;
 313
 314        for (i = 0; i < 8; i++) {
 315                if (guid[i] > 0xff)
 316                        goto invalid;
 317                ng[i] = guid[i];
 318        }
 319
 320        if (new_guid == 0)
 321                goto invalid;
 322
 323        dd->ipath_guid = new_guid;
 324        dd->ipath_nguid = 1;
 325        if (dd->verbs_dev)
 326                dd->verbs_dev->ibdev.node_guid = new_guid;
 327
 328        ret = strlen(buf);
 329        goto bail;
 330
 331invalid:
 332        ipath_dev_err(dd, "attempt to set invalid GUID\n");
 333        ret = -EINVAL;
 334
 335bail:
 336        return ret;
 337}
 338
 339static ssize_t show_nguid(struct device *dev,
 340                          struct device_attribute *attr,
 341                          char *buf)
 342{
 343        struct ipath_devdata *dd = dev_get_drvdata(dev);
 344
 345        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_nguid);
 346}
 347
 348static ssize_t show_nports(struct device *dev,
 349                           struct device_attribute *attr,
 350                           char *buf)
 351{
 352        struct ipath_devdata *dd = dev_get_drvdata(dev);
 353
 354        /* Return the number of user ports available. */
 355        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_cfgports - 1);
 356}
 357
 358static ssize_t show_serial(struct device *dev,
 359                           struct device_attribute *attr,
 360                           char *buf)
 361{
 362        struct ipath_devdata *dd = dev_get_drvdata(dev);
 363
 364        buf[sizeof dd->ipath_serial] = '\0';
 365        memcpy(buf, dd->ipath_serial, sizeof dd->ipath_serial);
 366        strcat(buf, "\n");
 367        return strlen(buf);
 368}
 369
 370static ssize_t show_unit(struct device *dev,
 371                         struct device_attribute *attr,
 372                         char *buf)
 373{
 374        struct ipath_devdata *dd = dev_get_drvdata(dev);
 375
 376        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_unit);
 377}
 378
 379static ssize_t show_jint_max_packets(struct device *dev,
 380                                     struct device_attribute *attr,
 381                                     char *buf)
 382{
 383        struct ipath_devdata *dd = dev_get_drvdata(dev);
 384
 385        return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_max_packets);
 386}
 387
 388static ssize_t store_jint_max_packets(struct device *dev,
 389                                      struct device_attribute *attr,
 390                                      const char *buf,
 391                                      size_t count)
 392{
 393        struct ipath_devdata *dd = dev_get_drvdata(dev);
 394        u16 v = 0;
 395        int ret;
 396
 397        ret = ipath_parse_ushort(buf, &v);
 398        if (ret < 0)
 399                ipath_dev_err(dd, "invalid jint_max_packets.\n");
 400        else
 401                dd->ipath_f_config_jint(dd, dd->ipath_jint_idle_ticks, v);
 402
 403        return ret;
 404}
 405
 406static ssize_t show_jint_idle_ticks(struct device *dev,
 407                                    struct device_attribute *attr,
 408                                    char *buf)
 409{
 410        struct ipath_devdata *dd = dev_get_drvdata(dev);
 411
 412        return scnprintf(buf, PAGE_SIZE, "%hu\n", dd->ipath_jint_idle_ticks);
 413}
 414
 415static ssize_t store_jint_idle_ticks(struct device *dev,
 416                                     struct device_attribute *attr,
 417                                     const char *buf,
 418                                     size_t count)
 419{
 420        struct ipath_devdata *dd = dev_get_drvdata(dev);
 421        u16 v = 0;
 422        int ret;
 423
 424        ret = ipath_parse_ushort(buf, &v);
 425        if (ret < 0)
 426                ipath_dev_err(dd, "invalid jint_idle_ticks.\n");
 427        else
 428                dd->ipath_f_config_jint(dd, v, dd->ipath_jint_max_packets);
 429
 430        return ret;
 431}
 432
 433#define DEVICE_COUNTER(name, attr) \
 434        static ssize_t show_counter_##name(struct device *dev, \
 435                                           struct device_attribute *attr, \
 436                                           char *buf) \
 437        { \
 438                struct ipath_devdata *dd = dev_get_drvdata(dev); \
 439                return scnprintf(\
 440                        buf, PAGE_SIZE, "%llu\n", (unsigned long long) \
 441                        ipath_snap_cntr( \
 442                                dd, offsetof(struct infinipath_counters, \
 443                                             attr) / sizeof(u64)));     \
 444        } \
 445        static DEVICE_ATTR(name, S_IRUGO, show_counter_##name, NULL);
 446
 447DEVICE_COUNTER(ib_link_downeds, IBLinkDownedCnt);
 448DEVICE_COUNTER(ib_link_err_recoveries, IBLinkErrRecoveryCnt);
 449DEVICE_COUNTER(ib_status_changes, IBStatusChangeCnt);
 450DEVICE_COUNTER(ib_symbol_errs, IBSymbolErrCnt);
 451DEVICE_COUNTER(lb_flow_stalls, LBFlowStallCnt);
 452DEVICE_COUNTER(lb_ints, LBIntCnt);
 453DEVICE_COUNTER(rx_bad_formats, RxBadFormatCnt);
 454DEVICE_COUNTER(rx_buf_ovfls, RxBufOvflCnt);
 455DEVICE_COUNTER(rx_data_pkts, RxDataPktCnt);
 456DEVICE_COUNTER(rx_dropped_pkts, RxDroppedPktCnt);
 457DEVICE_COUNTER(rx_dwords, RxDwordCnt);
 458DEVICE_COUNTER(rx_ebps, RxEBPCnt);
 459DEVICE_COUNTER(rx_flow_ctrl_errs, RxFlowCtrlErrCnt);
 460DEVICE_COUNTER(rx_flow_pkts, RxFlowPktCnt);
 461DEVICE_COUNTER(rx_icrc_errs, RxICRCErrCnt);
 462DEVICE_COUNTER(rx_len_errs, RxLenErrCnt);
 463DEVICE_COUNTER(rx_link_problems, RxLinkProblemCnt);
 464DEVICE_COUNTER(rx_lpcrc_errs, RxLPCRCErrCnt);
 465DEVICE_COUNTER(rx_max_min_len_errs, RxMaxMinLenErrCnt);
 466DEVICE_COUNTER(rx_p0_hdr_egr_ovfls, RxP0HdrEgrOvflCnt);
 467DEVICE_COUNTER(rx_p1_hdr_egr_ovfls, RxP1HdrEgrOvflCnt);
 468DEVICE_COUNTER(rx_p2_hdr_egr_ovfls, RxP2HdrEgrOvflCnt);
 469DEVICE_COUNTER(rx_p3_hdr_egr_ovfls, RxP3HdrEgrOvflCnt);
 470DEVICE_COUNTER(rx_p4_hdr_egr_ovfls, RxP4HdrEgrOvflCnt);
 471DEVICE_COUNTER(rx_p5_hdr_egr_ovfls, RxP5HdrEgrOvflCnt);
 472DEVICE_COUNTER(rx_p6_hdr_egr_ovfls, RxP6HdrEgrOvflCnt);
 473DEVICE_COUNTER(rx_p7_hdr_egr_ovfls, RxP7HdrEgrOvflCnt);
 474DEVICE_COUNTER(rx_p8_hdr_egr_ovfls, RxP8HdrEgrOvflCnt);
 475DEVICE_COUNTER(rx_pkey_mismatches, RxPKeyMismatchCnt);
 476DEVICE_COUNTER(rx_tid_full_errs, RxTIDFullErrCnt);
 477DEVICE_COUNTER(rx_tid_valid_errs, RxTIDValidErrCnt);
 478DEVICE_COUNTER(rx_vcrc_errs, RxVCRCErrCnt);
 479DEVICE_COUNTER(tx_data_pkts, TxDataPktCnt);
 480DEVICE_COUNTER(tx_dropped_pkts, TxDroppedPktCnt);
 481DEVICE_COUNTER(tx_dwords, TxDwordCnt);
 482DEVICE_COUNTER(tx_flow_pkts, TxFlowPktCnt);
 483DEVICE_COUNTER(tx_flow_stalls, TxFlowStallCnt);
 484DEVICE_COUNTER(tx_len_errs, TxLenErrCnt);
 485DEVICE_COUNTER(tx_max_min_len_errs, TxMaxMinLenErrCnt);
 486DEVICE_COUNTER(tx_underruns, TxUnderrunCnt);
 487DEVICE_COUNTER(tx_unsup_vl_errs, TxUnsupVLErrCnt);
 488
 489static struct attribute *dev_counter_attributes[] = {
 490        &dev_attr_ib_link_downeds.attr,
 491        &dev_attr_ib_link_err_recoveries.attr,
 492        &dev_attr_ib_status_changes.attr,
 493        &dev_attr_ib_symbol_errs.attr,
 494        &dev_attr_lb_flow_stalls.attr,
 495        &dev_attr_lb_ints.attr,
 496        &dev_attr_rx_bad_formats.attr,
 497        &dev_attr_rx_buf_ovfls.attr,
 498        &dev_attr_rx_data_pkts.attr,
 499        &dev_attr_rx_dropped_pkts.attr,
 500        &dev_attr_rx_dwords.attr,
 501        &dev_attr_rx_ebps.attr,
 502        &dev_attr_rx_flow_ctrl_errs.attr,
 503        &dev_attr_rx_flow_pkts.attr,
 504        &dev_attr_rx_icrc_errs.attr,
 505        &dev_attr_rx_len_errs.attr,
 506        &dev_attr_rx_link_problems.attr,
 507        &dev_attr_rx_lpcrc_errs.attr,
 508        &dev_attr_rx_max_min_len_errs.attr,
 509        &dev_attr_rx_p0_hdr_egr_ovfls.attr,
 510        &dev_attr_rx_p1_hdr_egr_ovfls.attr,
 511        &dev_attr_rx_p2_hdr_egr_ovfls.attr,
 512        &dev_attr_rx_p3_hdr_egr_ovfls.attr,
 513        &dev_attr_rx_p4_hdr_egr_ovfls.attr,
 514        &dev_attr_rx_p5_hdr_egr_ovfls.attr,
 515        &dev_attr_rx_p6_hdr_egr_ovfls.attr,
 516        &dev_attr_rx_p7_hdr_egr_ovfls.attr,
 517        &dev_attr_rx_p8_hdr_egr_ovfls.attr,
 518        &dev_attr_rx_pkey_mismatches.attr,
 519        &dev_attr_rx_tid_full_errs.attr,
 520        &dev_attr_rx_tid_valid_errs.attr,
 521        &dev_attr_rx_vcrc_errs.attr,
 522        &dev_attr_tx_data_pkts.attr,
 523        &dev_attr_tx_dropped_pkts.attr,
 524        &dev_attr_tx_dwords.attr,
 525        &dev_attr_tx_flow_pkts.attr,
 526        &dev_attr_tx_flow_stalls.attr,
 527        &dev_attr_tx_len_errs.attr,
 528        &dev_attr_tx_max_min_len_errs.attr,
 529        &dev_attr_tx_underruns.attr,
 530        &dev_attr_tx_unsup_vl_errs.attr,
 531        NULL
 532};
 533
 534static struct attribute_group dev_counter_attr_group = {
 535        .name = "counters",
 536        .attrs = dev_counter_attributes
 537};
 538
 539static ssize_t store_reset(struct device *dev,
 540                         struct device_attribute *attr,
 541                          const char *buf,
 542                          size_t count)
 543{
 544        struct ipath_devdata *dd = dev_get_drvdata(dev);
 545        int ret;
 546
 547        if (count < 5 || memcmp(buf, "reset", 5)) {
 548                ret = -EINVAL;
 549                goto bail;
 550        }
 551
 552        if (dd->ipath_flags & IPATH_DISABLED) {
 553                /*
 554                 * post-reset init would re-enable interrupts, etc.
 555                 * so don't allow reset on disabled devices.  Not
 556                 * perfect error, but about the best choice.
 557                 */
 558                dev_info(dev,"Unit %d is disabled, can't reset\n",
 559                         dd->ipath_unit);
 560                ret = -EINVAL;
 561                goto bail;
 562        }
 563        ret = ipath_reset_device(dd->ipath_unit);
 564bail:
 565        return ret<0 ? ret : count;
 566}
 567
 568static ssize_t store_link_state(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        int ret, r;
 575        u16 state;
 576
 577        ret = ipath_parse_ushort(buf, &state);
 578        if (ret < 0)
 579                goto invalid;
 580
 581        r = ipath_set_linkstate(dd, state);
 582        if (r < 0) {
 583                ret = r;
 584                goto bail;
 585        }
 586
 587        goto bail;
 588invalid:
 589        ipath_dev_err(dd, "attempt to set invalid link state\n");
 590bail:
 591        return ret;
 592}
 593
 594static ssize_t show_mtu(struct device *dev,
 595                         struct device_attribute *attr,
 596                         char *buf)
 597{
 598        struct ipath_devdata *dd = dev_get_drvdata(dev);
 599        return scnprintf(buf, PAGE_SIZE, "%u\n", dd->ipath_ibmtu);
 600}
 601
 602static ssize_t store_mtu(struct device *dev,
 603                         struct device_attribute *attr,
 604                          const char *buf,
 605                          size_t count)
 606{
 607        struct ipath_devdata *dd = dev_get_drvdata(dev);
 608        ssize_t ret;
 609        u16 mtu = 0;
 610        int r;
 611
 612        ret = ipath_parse_ushort(buf, &mtu);
 613        if (ret < 0)
 614                goto invalid;
 615
 616        r = ipath_set_mtu(dd, mtu);
 617        if (r < 0)
 618                ret = r;
 619
 620        goto bail;
 621invalid:
 622        ipath_dev_err(dd, "attempt to set invalid MTU\n");
 623bail:
 624        return ret;
 625}
 626
 627static ssize_t show_enabled(struct device *dev,
 628                         struct device_attribute *attr,
 629                         char *buf)
 630{
 631        struct ipath_devdata *dd = dev_get_drvdata(dev);
 632        return scnprintf(buf, PAGE_SIZE, "%u\n",
 633                         (dd->ipath_flags & IPATH_DISABLED) ? 0 : 1);
 634}
 635
 636static ssize_t store_enabled(struct device *dev,
 637                         struct device_attribute *attr,
 638                          const char *buf,
 639                          size_t count)
 640{
 641        struct ipath_devdata *dd = dev_get_drvdata(dev);
 642        ssize_t ret;
 643        u16 enable = 0;
 644
 645        ret = ipath_parse_ushort(buf, &enable);
 646        if (ret < 0) {
 647                ipath_dev_err(dd, "attempt to use non-numeric on enable\n");
 648                goto bail;
 649        }
 650
 651        if (enable) {
 652                if (!(dd->ipath_flags & IPATH_DISABLED))
 653                        goto bail;
 654
 655                dev_info(dev, "Enabling unit %d\n", dd->ipath_unit);
 656                /* same as post-reset */
 657                ret = ipath_init_chip(dd, 1);
 658                if (ret)
 659                        ipath_dev_err(dd, "Failed to enable unit %d\n",
 660                                      dd->ipath_unit);
 661                else {
 662                        dd->ipath_flags &= ~IPATH_DISABLED;
 663                        *dd->ipath_statusp &= ~IPATH_STATUS_ADMIN_DISABLED;
 664                }
 665        }
 666        else if (!(dd->ipath_flags & IPATH_DISABLED)) {
 667                dev_info(dev, "Disabling unit %d\n", dd->ipath_unit);
 668                ipath_shutdown_device(dd);
 669                dd->ipath_flags |= IPATH_DISABLED;
 670                *dd->ipath_statusp |= IPATH_STATUS_ADMIN_DISABLED;
 671        }
 672
 673bail:
 674        return ret;
 675}
 676
 677static ssize_t store_rx_pol_inv(struct device *dev,
 678                          struct device_attribute *attr,
 679                          const char *buf,
 680                          size_t count)
 681{
 682        struct ipath_devdata *dd = dev_get_drvdata(dev);
 683        int ret, r;
 684        u16 val;
 685
 686        ret = ipath_parse_ushort(buf, &val);
 687        if (ret < 0)
 688                goto invalid;
 689
 690        r = ipath_set_rx_pol_inv(dd, val);
 691        if (r < 0) {
 692                ret = r;
 693                goto bail;
 694        }
 695
 696        goto bail;
 697invalid:
 698        ipath_dev_err(dd, "attempt to set invalid Rx Polarity invert\n");
 699bail:
 700        return ret;
 701}
 702
 703static ssize_t store_led_override(struct device *dev,
 704                          struct device_attribute *attr,
 705                          const char *buf,
 706                          size_t count)
 707{
 708        struct ipath_devdata *dd = dev_get_drvdata(dev);
 709        int ret;
 710        u16 val;
 711
 712        ret = ipath_parse_ushort(buf, &val);
 713        if (ret > 0)
 714                ipath_set_led_override(dd, val);
 715        else
 716                ipath_dev_err(dd, "attempt to set invalid LED override\n");
 717        return ret;
 718}
 719
 720static ssize_t show_logged_errs(struct device *dev,
 721                                struct device_attribute *attr,
 722                                char *buf)
 723{
 724        struct ipath_devdata *dd = dev_get_drvdata(dev);
 725        int idx, count;
 726
 727        /* force consistency with actual EEPROM */
 728        if (ipath_update_eeprom_log(dd) != 0)
 729                return -ENXIO;
 730
 731        count = 0;
 732        for (idx = 0; idx < IPATH_EEP_LOG_CNT; ++idx) {
 733                count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c",
 734                        dd->ipath_eep_st_errs[idx],
 735                        idx == (IPATH_EEP_LOG_CNT - 1) ? '\n' : ' ');
 736        }
 737
 738        return count;
 739}
 740
 741/*
 742 * New sysfs entries to control various IB config. These all turn into
 743 * accesses via ipath_f_get/set_ib_cfg.
 744 *
 745 * Get/Set heartbeat enable. Or of 1=enabled, 2=auto
 746 */
 747static ssize_t show_hrtbt_enb(struct device *dev,
 748                         struct device_attribute *attr,
 749                         char *buf)
 750{
 751        struct ipath_devdata *dd = dev_get_drvdata(dev);
 752        int ret;
 753
 754        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_HRTBT);
 755        if (ret >= 0)
 756                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 757        return ret;
 758}
 759
 760static ssize_t store_hrtbt_enb(struct device *dev,
 761                          struct device_attribute *attr,
 762                          const char *buf,
 763                          size_t count)
 764{
 765        struct ipath_devdata *dd = dev_get_drvdata(dev);
 766        int ret, r;
 767        u16 val;
 768
 769        ret = ipath_parse_ushort(buf, &val);
 770        if (ret >= 0 && val > 3)
 771                ret = -EINVAL;
 772        if (ret < 0) {
 773                ipath_dev_err(dd, "attempt to set invalid Heartbeat enable\n");
 774                goto bail;
 775        }
 776
 777        /*
 778         * Set the "intentional" heartbeat enable per either of
 779         * "Enable" and "Auto", as these are normally set together.
 780         * This bit is consulted when leaving loopback mode,
 781         * because entering loopback mode overrides it and automatically
 782         * disables heartbeat.
 783         */
 784        r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_HRTBT, val);
 785        if (r < 0)
 786                ret = r;
 787        else if (val == IPATH_IB_HRTBT_OFF)
 788                dd->ipath_flags |= IPATH_NO_HRTBT;
 789        else
 790                dd->ipath_flags &= ~IPATH_NO_HRTBT;
 791
 792bail:
 793        return ret;
 794}
 795
 796/*
 797 * Get/Set Link-widths enabled. Or of 1=1x, 2=4x (this is human/IB centric,
 798 * _not_ the particular encoding of any given chip)
 799 */
 800static ssize_t show_lwid_enb(struct device *dev,
 801                         struct device_attribute *attr,
 802                         char *buf)
 803{
 804        struct ipath_devdata *dd = dev_get_drvdata(dev);
 805        int ret;
 806
 807        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB);
 808        if (ret >= 0)
 809                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 810        return ret;
 811}
 812
 813static ssize_t store_lwid_enb(struct device *dev,
 814                          struct device_attribute *attr,
 815                          const char *buf,
 816                          size_t count)
 817{
 818        struct ipath_devdata *dd = dev_get_drvdata(dev);
 819        int ret, r;
 820        u16 val;
 821
 822        ret = ipath_parse_ushort(buf, &val);
 823        if (ret >= 0 && (val == 0 || val > 3))
 824                ret = -EINVAL;
 825        if (ret < 0) {
 826                ipath_dev_err(dd,
 827                        "attempt to set invalid Link Width (enable)\n");
 828                goto bail;
 829        }
 830
 831        r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, val);
 832        if (r < 0)
 833                ret = r;
 834
 835bail:
 836        return ret;
 837}
 838
 839/* Get current link width */
 840static ssize_t show_lwid(struct device *dev,
 841                         struct device_attribute *attr,
 842                         char *buf)
 843
 844{
 845        struct ipath_devdata *dd = dev_get_drvdata(dev);
 846        int ret;
 847
 848        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LWID);
 849        if (ret >= 0)
 850                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 851        return ret;
 852}
 853
 854/*
 855 * Get/Set Link-speeds enabled. Or of 1=SDR 2=DDR.
 856 */
 857static ssize_t show_spd_enb(struct device *dev,
 858                         struct device_attribute *attr,
 859                         char *buf)
 860{
 861        struct ipath_devdata *dd = dev_get_drvdata(dev);
 862        int ret;
 863
 864        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB);
 865        if (ret >= 0)
 866                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 867        return ret;
 868}
 869
 870static ssize_t store_spd_enb(struct device *dev,
 871                          struct device_attribute *attr,
 872                          const char *buf,
 873                          size_t count)
 874{
 875        struct ipath_devdata *dd = dev_get_drvdata(dev);
 876        int ret, r;
 877        u16 val;
 878
 879        ret = ipath_parse_ushort(buf, &val);
 880        if (ret >= 0 && (val == 0 || val > (IPATH_IB_SDR | IPATH_IB_DDR)))
 881                ret = -EINVAL;
 882        if (ret < 0) {
 883                ipath_dev_err(dd,
 884                        "attempt to set invalid Link Speed (enable)\n");
 885                goto bail;
 886        }
 887
 888        r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, val);
 889        if (r < 0)
 890                ret = r;
 891
 892bail:
 893        return ret;
 894}
 895
 896/* Get current link speed */
 897static ssize_t show_spd(struct device *dev,
 898                         struct device_attribute *attr,
 899                         char *buf)
 900{
 901        struct ipath_devdata *dd = dev_get_drvdata(dev);
 902        int ret;
 903
 904        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_SPD);
 905        if (ret >= 0)
 906                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 907        return ret;
 908}
 909
 910/*
 911 * Get/Set RX polarity-invert enable. 0=no, 1=yes.
 912 */
 913static ssize_t show_rx_polinv_enb(struct device *dev,
 914                         struct device_attribute *attr,
 915                         char *buf)
 916{
 917        struct ipath_devdata *dd = dev_get_drvdata(dev);
 918        int ret;
 919
 920        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB);
 921        if (ret >= 0)
 922                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 923        return ret;
 924}
 925
 926static ssize_t store_rx_polinv_enb(struct device *dev,
 927                          struct device_attribute *attr,
 928                          const char *buf,
 929                          size_t count)
 930{
 931        struct ipath_devdata *dd = dev_get_drvdata(dev);
 932        int ret, r;
 933        u16 val;
 934
 935        ret = ipath_parse_ushort(buf, &val);
 936        if (ret >= 0 && val > 1) {
 937                ipath_dev_err(dd,
 938                        "attempt to set invalid Rx Polarity (enable)\n");
 939                ret = -EINVAL;
 940                goto bail;
 941        }
 942
 943        r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_RXPOL_ENB, val);
 944        if (r < 0)
 945                ret = r;
 946
 947bail:
 948        return ret;
 949}
 950
 951/*
 952 * Get/Set RX lane-reversal enable. 0=no, 1=yes.
 953 */
 954static ssize_t show_lanerev_enb(struct device *dev,
 955                         struct device_attribute *attr,
 956                         char *buf)
 957{
 958        struct ipath_devdata *dd = dev_get_drvdata(dev);
 959        int ret;
 960
 961        ret = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB);
 962        if (ret >= 0)
 963                ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret);
 964        return ret;
 965}
 966
 967static ssize_t store_lanerev_enb(struct device *dev,
 968                          struct device_attribute *attr,
 969                          const char *buf,
 970                          size_t count)
 971{
 972        struct ipath_devdata *dd = dev_get_drvdata(dev);
 973        int ret, r;
 974        u16 val;
 975
 976        ret = ipath_parse_ushort(buf, &val);
 977        if (ret >= 0 && val > 1) {
 978                ret = -EINVAL;
 979                ipath_dev_err(dd,
 980                        "attempt to set invalid Lane reversal (enable)\n");
 981                goto bail;
 982        }
 983
 984        r = dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LREV_ENB, val);
 985        if (r < 0)
 986                ret = r;
 987
 988bail:
 989        return ret;
 990}
 991
 992static DRIVER_ATTR(num_units, S_IRUGO, show_num_units, NULL);
 993static DRIVER_ATTR(version, S_IRUGO, show_version, NULL);
 994
 995static struct attribute *driver_attributes[] = {
 996        &driver_attr_num_units.attr,
 997        &driver_attr_version.attr,
 998        NULL
 999};
1000
1001static struct attribute_group driver_attr_group = {
1002        .attrs = driver_attributes
1003};
1004
1005static ssize_t store_tempsense(struct device *dev,
1006                               struct device_attribute *attr,
1007                               const char *buf,
1008                               size_t count)
1009{
1010        struct ipath_devdata *dd = dev_get_drvdata(dev);
1011        int ret, stat;
1012        u16 val;
1013
1014        ret = ipath_parse_ushort(buf, &val);
1015        if (ret <= 0) {
1016                ipath_dev_err(dd, "attempt to set invalid tempsense config\n");
1017                goto bail;
1018        }
1019        /* If anything but the highest limit, enable T_CRIT_A "interrupt" */
1020        stat = ipath_tempsense_write(dd, 9, (val == 0x7f7f) ? 0x80 : 0);
1021        if (stat) {
1022                ipath_dev_err(dd, "Unable to set tempsense config\n");
1023                ret = -1;
1024                goto bail;
1025        }
1026        stat = ipath_tempsense_write(dd, 0xB, (u8) (val & 0xFF));
1027        if (stat) {
1028                ipath_dev_err(dd, "Unable to set local Tcrit\n");
1029                ret = -1;
1030                goto bail;
1031        }
1032        stat = ipath_tempsense_write(dd, 0xD, (u8) (val >> 8));
1033        if (stat) {
1034                ipath_dev_err(dd, "Unable to set remote Tcrit\n");
1035                ret = -1;
1036                goto bail;
1037        }
1038
1039bail:
1040        return ret;
1041}
1042
1043/*
1044 * dump tempsense regs. in decimal, to ease shell-scripts.
1045 */
1046static ssize_t show_tempsense(struct device *dev,
1047                              struct device_attribute *attr,
1048                              char *buf)
1049{
1050        struct ipath_devdata *dd = dev_get_drvdata(dev);
1051        int ret;
1052        int idx;
1053        u8 regvals[8];
1054
1055        ret = -ENXIO;
1056        for (idx = 0; idx < 8; ++idx) {
1057                if (idx == 6)
1058                        continue;
1059                ret = ipath_tempsense_read(dd, idx);
1060                if (ret < 0)
1061                        break;
1062                regvals[idx] = ret;
1063        }
1064        if (idx == 8)
1065                ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n",
1066                        *(signed char *)(regvals),
1067                        *(signed char *)(regvals + 1),
1068                        regvals[2], regvals[3],
1069                        *(signed char *)(regvals + 5),
1070                        *(signed char *)(regvals + 7));
1071        return ret;
1072}
1073
1074const struct attribute_group *ipath_driver_attr_groups[] = {
1075        &driver_attr_group,
1076        NULL,
1077};
1078
1079static DEVICE_ATTR(guid, S_IWUSR | S_IRUGO, show_guid, store_guid);
1080static DEVICE_ATTR(lmc, S_IWUSR | S_IRUGO, show_lmc, store_lmc);
1081static DEVICE_ATTR(lid, S_IWUSR | S_IRUGO, show_lid, store_lid);
1082static DEVICE_ATTR(link_state, S_IWUSR, NULL, store_link_state);
1083static DEVICE_ATTR(mlid, S_IWUSR | S_IRUGO, show_mlid, store_mlid);
1084static DEVICE_ATTR(mtu, S_IWUSR | S_IRUGO, show_mtu, store_mtu);
1085static DEVICE_ATTR(enabled, S_IWUSR | S_IRUGO, show_enabled, store_enabled);
1086static DEVICE_ATTR(nguid, S_IRUGO, show_nguid, NULL);
1087static DEVICE_ATTR(nports, S_IRUGO, show_nports, NULL);
1088static DEVICE_ATTR(reset, S_IWUSR, NULL, store_reset);
1089static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL);
1090static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
1091static DEVICE_ATTR(status_str, S_IRUGO, show_status_str, NULL);
1092static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL);
1093static DEVICE_ATTR(unit, S_IRUGO, show_unit, NULL);
1094static DEVICE_ATTR(rx_pol_inv, S_IWUSR, NULL, store_rx_pol_inv);
1095static DEVICE_ATTR(led_override, S_IWUSR, NULL, store_led_override);
1096static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL);
1097static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL);
1098static DEVICE_ATTR(jint_max_packets, S_IWUSR | S_IRUGO,
1099                   show_jint_max_packets, store_jint_max_packets);
1100static DEVICE_ATTR(jint_idle_ticks, S_IWUSR | S_IRUGO,
1101                   show_jint_idle_ticks, store_jint_idle_ticks);
1102static DEVICE_ATTR(tempsense, S_IWUSR | S_IRUGO,
1103                   show_tempsense, store_tempsense);
1104
1105static struct attribute *dev_attributes[] = {
1106        &dev_attr_guid.attr,
1107        &dev_attr_lmc.attr,
1108        &dev_attr_lid.attr,
1109        &dev_attr_link_state.attr,
1110        &dev_attr_mlid.attr,
1111        &dev_attr_mtu.attr,
1112        &dev_attr_nguid.attr,
1113        &dev_attr_nports.attr,
1114        &dev_attr_serial.attr,
1115        &dev_attr_status.attr,
1116        &dev_attr_status_str.attr,
1117        &dev_attr_boardversion.attr,
1118        &dev_attr_unit.attr,
1119        &dev_attr_enabled.attr,
1120        &dev_attr_rx_pol_inv.attr,
1121        &dev_attr_led_override.attr,
1122        &dev_attr_logged_errors.attr,
1123        &dev_attr_tempsense.attr,
1124        &dev_attr_localbus_info.attr,
1125        NULL
1126};
1127
1128static struct attribute_group dev_attr_group = {
1129        .attrs = dev_attributes
1130};
1131
1132static DEVICE_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb,
1133                   store_hrtbt_enb);
1134static DEVICE_ATTR(link_width_enable, S_IWUSR | S_IRUGO, show_lwid_enb,
1135                   store_lwid_enb);
1136static DEVICE_ATTR(link_width, S_IRUGO, show_lwid, NULL);
1137static DEVICE_ATTR(link_speed_enable, S_IWUSR | S_IRUGO, show_spd_enb,
1138                   store_spd_enb);
1139static DEVICE_ATTR(link_speed, S_IRUGO, show_spd, NULL);
1140static DEVICE_ATTR(rx_pol_inv_enable, S_IWUSR | S_IRUGO, show_rx_polinv_enb,
1141                   store_rx_polinv_enb);
1142static DEVICE_ATTR(rx_lane_rev_enable, S_IWUSR | S_IRUGO, show_lanerev_enb,
1143                   store_lanerev_enb);
1144
1145static struct attribute *dev_ibcfg_attributes[] = {
1146        &dev_attr_hrtbt_enable.attr,
1147        &dev_attr_link_width_enable.attr,
1148        &dev_attr_link_width.attr,
1149        &dev_attr_link_speed_enable.attr,
1150        &dev_attr_link_speed.attr,
1151        &dev_attr_rx_pol_inv_enable.attr,
1152        &dev_attr_rx_lane_rev_enable.attr,
1153        NULL
1154};
1155
1156static struct attribute_group dev_ibcfg_attr_group = {
1157        .attrs = dev_ibcfg_attributes
1158};
1159
1160/**
1161 * ipath_expose_reset - create a device reset file
1162 * @dev: the device structure
1163 *
1164 * Only expose a file that lets us reset the device after someone
1165 * enters diag mode.  A device reset is quite likely to crash the
1166 * machine entirely, so we don't want to normally make it
1167 * available.
1168 *
1169 * Called with ipath_mutex held.
1170 */
1171int ipath_expose_reset(struct device *dev)
1172{
1173        static int exposed;
1174        int ret;
1175
1176        if (!exposed) {
1177                ret = device_create_file(dev, &dev_attr_reset);
1178                exposed = 1;
1179        }
1180        else
1181                ret = 0;
1182
1183        return ret;
1184}
1185
1186int ipath_device_create_group(struct device *dev, struct ipath_devdata *dd)
1187{
1188        int ret;
1189
1190        ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
1191        if (ret)
1192                goto bail;
1193
1194        ret = sysfs_create_group(&dev->kobj, &dev_counter_attr_group);
1195        if (ret)
1196                goto bail_attrs;
1197
1198        if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
1199                ret = device_create_file(dev, &dev_attr_jint_idle_ticks);
1200                if (ret)
1201                        goto bail_counter;
1202                ret = device_create_file(dev, &dev_attr_jint_max_packets);
1203                if (ret)
1204                        goto bail_idle;
1205
1206                ret = sysfs_create_group(&dev->kobj, &dev_ibcfg_attr_group);
1207                if (ret)
1208                        goto bail_max;
1209        }
1210
1211        return 0;
1212
1213bail_max:
1214        device_remove_file(dev, &dev_attr_jint_max_packets);
1215bail_idle:
1216        device_remove_file(dev, &dev_attr_jint_idle_ticks);
1217bail_counter:
1218        sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
1219bail_attrs:
1220        sysfs_remove_group(&dev->kobj, &dev_attr_group);
1221bail:
1222        return ret;
1223}
1224
1225void ipath_device_remove_group(struct device *dev, struct ipath_devdata *dd)
1226{
1227        sysfs_remove_group(&dev->kobj, &dev_counter_attr_group);
1228
1229        if (dd->ipath_flags & IPATH_HAS_MULT_IB_SPEED) {
1230                sysfs_remove_group(&dev->kobj, &dev_ibcfg_attr_group);
1231                device_remove_file(dev, &dev_attr_jint_idle_ticks);
1232                device_remove_file(dev, &dev_attr_jint_max_packets);
1233        }
1234
1235        sysfs_remove_group(&dev->kobj, &dev_attr_group);
1236
1237        device_remove_file(dev, &dev_attr_reset);
1238}
1239