1*f931551bSRalph Campbell /* 2*f931551bSRalph Campbell * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. 3*f931551bSRalph Campbell * Copyright (c) 2006 PathScale, Inc. All rights reserved. 4*f931551bSRalph Campbell * 5*f931551bSRalph Campbell * This software is available to you under a choice of one of two 6*f931551bSRalph Campbell * licenses. You may choose to be licensed under the terms of the GNU 7*f931551bSRalph Campbell * General Public License (GPL) Version 2, available from the file 8*f931551bSRalph Campbell * COPYING in the main directory of this source tree, or the 9*f931551bSRalph Campbell * OpenIB.org BSD license below: 10*f931551bSRalph Campbell * 11*f931551bSRalph Campbell * Redistribution and use in source and binary forms, with or 12*f931551bSRalph Campbell * without modification, are permitted provided that the following 13*f931551bSRalph Campbell * conditions are met: 14*f931551bSRalph Campbell * 15*f931551bSRalph Campbell * - Redistributions of source code must retain the above 16*f931551bSRalph Campbell * copyright notice, this list of conditions and the following 17*f931551bSRalph Campbell * disclaimer. 18*f931551bSRalph Campbell * 19*f931551bSRalph Campbell * - Redistributions in binary form must reproduce the above 20*f931551bSRalph Campbell * copyright notice, this list of conditions and the following 21*f931551bSRalph Campbell * disclaimer in the documentation and/or other materials 22*f931551bSRalph Campbell * provided with the distribution. 23*f931551bSRalph Campbell * 24*f931551bSRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25*f931551bSRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26*f931551bSRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27*f931551bSRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28*f931551bSRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29*f931551bSRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30*f931551bSRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31*f931551bSRalph Campbell * SOFTWARE. 32*f931551bSRalph Campbell */ 33*f931551bSRalph Campbell #include <linux/ctype.h> 34*f931551bSRalph Campbell 35*f931551bSRalph Campbell #include "qib.h" 36*f931551bSRalph Campbell 37*f931551bSRalph Campbell /** 38*f931551bSRalph Campbell * qib_parse_ushort - parse an unsigned short value in an arbitrary base 39*f931551bSRalph Campbell * @str: the string containing the number 40*f931551bSRalph Campbell * @valp: where to put the result 41*f931551bSRalph Campbell * 42*f931551bSRalph Campbell * Returns the number of bytes consumed, or negative value on error. 43*f931551bSRalph Campbell */ 44*f931551bSRalph Campbell static int qib_parse_ushort(const char *str, unsigned short *valp) 45*f931551bSRalph Campbell { 46*f931551bSRalph Campbell unsigned long val; 47*f931551bSRalph Campbell char *end; 48*f931551bSRalph Campbell int ret; 49*f931551bSRalph Campbell 50*f931551bSRalph Campbell if (!isdigit(str[0])) { 51*f931551bSRalph Campbell ret = -EINVAL; 52*f931551bSRalph Campbell goto bail; 53*f931551bSRalph Campbell } 54*f931551bSRalph Campbell 55*f931551bSRalph Campbell val = simple_strtoul(str, &end, 0); 56*f931551bSRalph Campbell 57*f931551bSRalph Campbell if (val > 0xffff) { 58*f931551bSRalph Campbell ret = -EINVAL; 59*f931551bSRalph Campbell goto bail; 60*f931551bSRalph Campbell } 61*f931551bSRalph Campbell 62*f931551bSRalph Campbell *valp = val; 63*f931551bSRalph Campbell 64*f931551bSRalph Campbell ret = end + 1 - str; 65*f931551bSRalph Campbell if (ret == 0) 66*f931551bSRalph Campbell ret = -EINVAL; 67*f931551bSRalph Campbell 68*f931551bSRalph Campbell bail: 69*f931551bSRalph Campbell return ret; 70*f931551bSRalph Campbell } 71*f931551bSRalph Campbell 72*f931551bSRalph Campbell /* start of per-port functions */ 73*f931551bSRalph Campbell /* 74*f931551bSRalph Campbell * Get/Set heartbeat enable. OR of 1=enabled, 2=auto 75*f931551bSRalph Campbell */ 76*f931551bSRalph Campbell static ssize_t show_hrtbt_enb(struct qib_pportdata *ppd, char *buf) 77*f931551bSRalph Campbell { 78*f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 79*f931551bSRalph Campbell int ret; 80*f931551bSRalph Campbell 81*f931551bSRalph Campbell ret = dd->f_get_ib_cfg(ppd, QIB_IB_CFG_HRTBT); 82*f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); 83*f931551bSRalph Campbell return ret; 84*f931551bSRalph Campbell } 85*f931551bSRalph Campbell 86*f931551bSRalph Campbell static ssize_t store_hrtbt_enb(struct qib_pportdata *ppd, const char *buf, 87*f931551bSRalph Campbell size_t count) 88*f931551bSRalph Campbell { 89*f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 90*f931551bSRalph Campbell int ret; 91*f931551bSRalph Campbell u16 val; 92*f931551bSRalph Campbell 93*f931551bSRalph Campbell ret = qib_parse_ushort(buf, &val); 94*f931551bSRalph Campbell 95*f931551bSRalph Campbell /* 96*f931551bSRalph Campbell * Set the "intentional" heartbeat enable per either of 97*f931551bSRalph Campbell * "Enable" and "Auto", as these are normally set together. 98*f931551bSRalph Campbell * This bit is consulted when leaving loopback mode, 99*f931551bSRalph Campbell * because entering loopback mode overrides it and automatically 100*f931551bSRalph Campbell * disables heartbeat. 101*f931551bSRalph Campbell */ 102*f931551bSRalph Campbell if (ret >= 0) 103*f931551bSRalph Campbell ret = dd->f_set_ib_cfg(ppd, QIB_IB_CFG_HRTBT, val); 104*f931551bSRalph Campbell if (ret < 0) 105*f931551bSRalph Campbell qib_dev_err(dd, "attempt to set invalid Heartbeat enable\n"); 106*f931551bSRalph Campbell return ret < 0 ? ret : count; 107*f931551bSRalph Campbell } 108*f931551bSRalph Campbell 109*f931551bSRalph Campbell static ssize_t store_loopback(struct qib_pportdata *ppd, const char *buf, 110*f931551bSRalph Campbell size_t count) 111*f931551bSRalph Campbell { 112*f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 113*f931551bSRalph Campbell int ret = count, r; 114*f931551bSRalph Campbell 115*f931551bSRalph Campbell r = dd->f_set_ib_loopback(ppd, buf); 116*f931551bSRalph Campbell if (r < 0) 117*f931551bSRalph Campbell ret = r; 118*f931551bSRalph Campbell 119*f931551bSRalph Campbell return ret; 120*f931551bSRalph Campbell } 121*f931551bSRalph Campbell 122*f931551bSRalph Campbell static ssize_t store_led_override(struct qib_pportdata *ppd, const char *buf, 123*f931551bSRalph Campbell size_t count) 124*f931551bSRalph Campbell { 125*f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 126*f931551bSRalph Campbell int ret; 127*f931551bSRalph Campbell u16 val; 128*f931551bSRalph Campbell 129*f931551bSRalph Campbell ret = qib_parse_ushort(buf, &val); 130*f931551bSRalph Campbell if (ret > 0) 131*f931551bSRalph Campbell qib_set_led_override(ppd, val); 132*f931551bSRalph Campbell else 133*f931551bSRalph Campbell qib_dev_err(dd, "attempt to set invalid LED override\n"); 134*f931551bSRalph Campbell return ret < 0 ? ret : count; 135*f931551bSRalph Campbell } 136*f931551bSRalph Campbell 137*f931551bSRalph Campbell static ssize_t show_status(struct qib_pportdata *ppd, char *buf) 138*f931551bSRalph Campbell { 139*f931551bSRalph Campbell ssize_t ret; 140*f931551bSRalph Campbell 141*f931551bSRalph Campbell if (!ppd->statusp) 142*f931551bSRalph Campbell ret = -EINVAL; 143*f931551bSRalph Campbell else 144*f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n", 145*f931551bSRalph Campbell (unsigned long long) *(ppd->statusp)); 146*f931551bSRalph Campbell return ret; 147*f931551bSRalph Campbell } 148*f931551bSRalph Campbell 149*f931551bSRalph Campbell /* 150*f931551bSRalph Campbell * For userland compatibility, these offsets must remain fixed. 151*f931551bSRalph Campbell * They are strings for QIB_STATUS_* 152*f931551bSRalph Campbell */ 153*f931551bSRalph Campbell static const char *qib_status_str[] = { 154*f931551bSRalph Campbell "Initted", 155*f931551bSRalph Campbell "", 156*f931551bSRalph Campbell "", 157*f931551bSRalph Campbell "", 158*f931551bSRalph Campbell "", 159*f931551bSRalph Campbell "Present", 160*f931551bSRalph Campbell "IB_link_up", 161*f931551bSRalph Campbell "IB_configured", 162*f931551bSRalph Campbell "", 163*f931551bSRalph Campbell "Fatal_Hardware_Error", 164*f931551bSRalph Campbell NULL, 165*f931551bSRalph Campbell }; 166*f931551bSRalph Campbell 167*f931551bSRalph Campbell static ssize_t show_status_str(struct qib_pportdata *ppd, char *buf) 168*f931551bSRalph Campbell { 169*f931551bSRalph Campbell int i, any; 170*f931551bSRalph Campbell u64 s; 171*f931551bSRalph Campbell ssize_t ret; 172*f931551bSRalph Campbell 173*f931551bSRalph Campbell if (!ppd->statusp) { 174*f931551bSRalph Campbell ret = -EINVAL; 175*f931551bSRalph Campbell goto bail; 176*f931551bSRalph Campbell } 177*f931551bSRalph Campbell 178*f931551bSRalph Campbell s = *(ppd->statusp); 179*f931551bSRalph Campbell *buf = '\0'; 180*f931551bSRalph Campbell for (any = i = 0; s && qib_status_str[i]; i++) { 181*f931551bSRalph Campbell if (s & 1) { 182*f931551bSRalph Campbell /* if overflow */ 183*f931551bSRalph Campbell if (any && strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) 184*f931551bSRalph Campbell break; 185*f931551bSRalph Campbell if (strlcat(buf, qib_status_str[i], PAGE_SIZE) >= 186*f931551bSRalph Campbell PAGE_SIZE) 187*f931551bSRalph Campbell break; 188*f931551bSRalph Campbell any = 1; 189*f931551bSRalph Campbell } 190*f931551bSRalph Campbell s >>= 1; 191*f931551bSRalph Campbell } 192*f931551bSRalph Campbell if (any) 193*f931551bSRalph Campbell strlcat(buf, "\n", PAGE_SIZE); 194*f931551bSRalph Campbell 195*f931551bSRalph Campbell ret = strlen(buf); 196*f931551bSRalph Campbell 197*f931551bSRalph Campbell bail: 198*f931551bSRalph Campbell return ret; 199*f931551bSRalph Campbell } 200*f931551bSRalph Campbell 201*f931551bSRalph Campbell /* end of per-port functions */ 202*f931551bSRalph Campbell 203*f931551bSRalph Campbell /* 204*f931551bSRalph Campbell * Start of per-port file structures and support code 205*f931551bSRalph Campbell * Because we are fitting into other infrastructure, we have to supply the 206*f931551bSRalph Campbell * full set of kobject/sysfs_ops structures and routines. 207*f931551bSRalph Campbell */ 208*f931551bSRalph Campbell #define QIB_PORT_ATTR(name, mode, show, store) \ 209*f931551bSRalph Campbell static struct qib_port_attr qib_port_attr_##name = \ 210*f931551bSRalph Campbell __ATTR(name, mode, show, store) 211*f931551bSRalph Campbell 212*f931551bSRalph Campbell struct qib_port_attr { 213*f931551bSRalph Campbell struct attribute attr; 214*f931551bSRalph Campbell ssize_t (*show)(struct qib_pportdata *, char *); 215*f931551bSRalph Campbell ssize_t (*store)(struct qib_pportdata *, const char *, size_t); 216*f931551bSRalph Campbell }; 217*f931551bSRalph Campbell 218*f931551bSRalph Campbell QIB_PORT_ATTR(loopback, S_IWUSR, NULL, store_loopback); 219*f931551bSRalph Campbell QIB_PORT_ATTR(led_override, S_IWUSR, NULL, store_led_override); 220*f931551bSRalph Campbell QIB_PORT_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb, 221*f931551bSRalph Campbell store_hrtbt_enb); 222*f931551bSRalph Campbell QIB_PORT_ATTR(status, S_IRUGO, show_status, NULL); 223*f931551bSRalph Campbell QIB_PORT_ATTR(status_str, S_IRUGO, show_status_str, NULL); 224*f931551bSRalph Campbell 225*f931551bSRalph Campbell static struct attribute *port_default_attributes[] = { 226*f931551bSRalph Campbell &qib_port_attr_loopback.attr, 227*f931551bSRalph Campbell &qib_port_attr_led_override.attr, 228*f931551bSRalph Campbell &qib_port_attr_hrtbt_enable.attr, 229*f931551bSRalph Campbell &qib_port_attr_status.attr, 230*f931551bSRalph Campbell &qib_port_attr_status_str.attr, 231*f931551bSRalph Campbell NULL 232*f931551bSRalph Campbell }; 233*f931551bSRalph Campbell 234*f931551bSRalph Campbell static ssize_t qib_portattr_show(struct kobject *kobj, 235*f931551bSRalph Campbell struct attribute *attr, char *buf) 236*f931551bSRalph Campbell { 237*f931551bSRalph Campbell struct qib_port_attr *pattr = 238*f931551bSRalph Campbell container_of(attr, struct qib_port_attr, attr); 239*f931551bSRalph Campbell struct qib_pportdata *ppd = 240*f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, pport_kobj); 241*f931551bSRalph Campbell 242*f931551bSRalph Campbell return pattr->show(ppd, buf); 243*f931551bSRalph Campbell } 244*f931551bSRalph Campbell 245*f931551bSRalph Campbell static ssize_t qib_portattr_store(struct kobject *kobj, 246*f931551bSRalph Campbell struct attribute *attr, const char *buf, size_t len) 247*f931551bSRalph Campbell { 248*f931551bSRalph Campbell struct qib_port_attr *pattr = 249*f931551bSRalph Campbell container_of(attr, struct qib_port_attr, attr); 250*f931551bSRalph Campbell struct qib_pportdata *ppd = 251*f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, pport_kobj); 252*f931551bSRalph Campbell 253*f931551bSRalph Campbell return pattr->store(ppd, buf, len); 254*f931551bSRalph Campbell } 255*f931551bSRalph Campbell 256*f931551bSRalph Campbell static void qib_port_release(struct kobject *kobj) 257*f931551bSRalph Campbell { 258*f931551bSRalph Campbell /* nothing to do since memory is freed by qib_free_devdata() */ 259*f931551bSRalph Campbell } 260*f931551bSRalph Campbell 261*f931551bSRalph Campbell static const struct sysfs_ops qib_port_ops = { 262*f931551bSRalph Campbell .show = qib_portattr_show, 263*f931551bSRalph Campbell .store = qib_portattr_store, 264*f931551bSRalph Campbell }; 265*f931551bSRalph Campbell 266*f931551bSRalph Campbell static struct kobj_type qib_port_ktype = { 267*f931551bSRalph Campbell .release = qib_port_release, 268*f931551bSRalph Campbell .sysfs_ops = &qib_port_ops, 269*f931551bSRalph Campbell .default_attrs = port_default_attributes 270*f931551bSRalph Campbell }; 271*f931551bSRalph Campbell 272*f931551bSRalph Campbell /* Start sl2vl */ 273*f931551bSRalph Campbell 274*f931551bSRalph Campbell #define QIB_SL2VL_ATTR(N) \ 275*f931551bSRalph Campbell static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \ 276*f931551bSRalph Campbell .attr = { .name = __stringify(N), .mode = 0444 }, \ 277*f931551bSRalph Campbell .sl = N \ 278*f931551bSRalph Campbell } 279*f931551bSRalph Campbell 280*f931551bSRalph Campbell struct qib_sl2vl_attr { 281*f931551bSRalph Campbell struct attribute attr; 282*f931551bSRalph Campbell int sl; 283*f931551bSRalph Campbell }; 284*f931551bSRalph Campbell 285*f931551bSRalph Campbell QIB_SL2VL_ATTR(0); 286*f931551bSRalph Campbell QIB_SL2VL_ATTR(1); 287*f931551bSRalph Campbell QIB_SL2VL_ATTR(2); 288*f931551bSRalph Campbell QIB_SL2VL_ATTR(3); 289*f931551bSRalph Campbell QIB_SL2VL_ATTR(4); 290*f931551bSRalph Campbell QIB_SL2VL_ATTR(5); 291*f931551bSRalph Campbell QIB_SL2VL_ATTR(6); 292*f931551bSRalph Campbell QIB_SL2VL_ATTR(7); 293*f931551bSRalph Campbell QIB_SL2VL_ATTR(8); 294*f931551bSRalph Campbell QIB_SL2VL_ATTR(9); 295*f931551bSRalph Campbell QIB_SL2VL_ATTR(10); 296*f931551bSRalph Campbell QIB_SL2VL_ATTR(11); 297*f931551bSRalph Campbell QIB_SL2VL_ATTR(12); 298*f931551bSRalph Campbell QIB_SL2VL_ATTR(13); 299*f931551bSRalph Campbell QIB_SL2VL_ATTR(14); 300*f931551bSRalph Campbell QIB_SL2VL_ATTR(15); 301*f931551bSRalph Campbell 302*f931551bSRalph Campbell static struct attribute *sl2vl_default_attributes[] = { 303*f931551bSRalph Campbell &qib_sl2vl_attr_0.attr, 304*f931551bSRalph Campbell &qib_sl2vl_attr_1.attr, 305*f931551bSRalph Campbell &qib_sl2vl_attr_2.attr, 306*f931551bSRalph Campbell &qib_sl2vl_attr_3.attr, 307*f931551bSRalph Campbell &qib_sl2vl_attr_4.attr, 308*f931551bSRalph Campbell &qib_sl2vl_attr_5.attr, 309*f931551bSRalph Campbell &qib_sl2vl_attr_6.attr, 310*f931551bSRalph Campbell &qib_sl2vl_attr_7.attr, 311*f931551bSRalph Campbell &qib_sl2vl_attr_8.attr, 312*f931551bSRalph Campbell &qib_sl2vl_attr_9.attr, 313*f931551bSRalph Campbell &qib_sl2vl_attr_10.attr, 314*f931551bSRalph Campbell &qib_sl2vl_attr_11.attr, 315*f931551bSRalph Campbell &qib_sl2vl_attr_12.attr, 316*f931551bSRalph Campbell &qib_sl2vl_attr_13.attr, 317*f931551bSRalph Campbell &qib_sl2vl_attr_14.attr, 318*f931551bSRalph Campbell &qib_sl2vl_attr_15.attr, 319*f931551bSRalph Campbell NULL 320*f931551bSRalph Campbell }; 321*f931551bSRalph Campbell 322*f931551bSRalph Campbell static ssize_t sl2vl_attr_show(struct kobject *kobj, struct attribute *attr, 323*f931551bSRalph Campbell char *buf) 324*f931551bSRalph Campbell { 325*f931551bSRalph Campbell struct qib_sl2vl_attr *sattr = 326*f931551bSRalph Campbell container_of(attr, struct qib_sl2vl_attr, attr); 327*f931551bSRalph Campbell struct qib_pportdata *ppd = 328*f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, sl2vl_kobj); 329*f931551bSRalph Campbell struct qib_ibport *qibp = &ppd->ibport_data; 330*f931551bSRalph Campbell 331*f931551bSRalph Campbell return sprintf(buf, "%u\n", qibp->sl_to_vl[sattr->sl]); 332*f931551bSRalph Campbell } 333*f931551bSRalph Campbell 334*f931551bSRalph Campbell static const struct sysfs_ops qib_sl2vl_ops = { 335*f931551bSRalph Campbell .show = sl2vl_attr_show, 336*f931551bSRalph Campbell }; 337*f931551bSRalph Campbell 338*f931551bSRalph Campbell static struct kobj_type qib_sl2vl_ktype = { 339*f931551bSRalph Campbell .release = qib_port_release, 340*f931551bSRalph Campbell .sysfs_ops = &qib_sl2vl_ops, 341*f931551bSRalph Campbell .default_attrs = sl2vl_default_attributes 342*f931551bSRalph Campbell }; 343*f931551bSRalph Campbell 344*f931551bSRalph Campbell /* End sl2vl */ 345*f931551bSRalph Campbell 346*f931551bSRalph Campbell /* Start diag_counters */ 347*f931551bSRalph Campbell 348*f931551bSRalph Campbell #define QIB_DIAGC_ATTR(N) \ 349*f931551bSRalph Campbell static struct qib_diagc_attr qib_diagc_attr_##N = { \ 350*f931551bSRalph Campbell .attr = { .name = __stringify(N), .mode = 0444 }, \ 351*f931551bSRalph Campbell .counter = offsetof(struct qib_ibport, n_##N) \ 352*f931551bSRalph Campbell } 353*f931551bSRalph Campbell 354*f931551bSRalph Campbell struct qib_diagc_attr { 355*f931551bSRalph Campbell struct attribute attr; 356*f931551bSRalph Campbell size_t counter; 357*f931551bSRalph Campbell }; 358*f931551bSRalph Campbell 359*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_resends); 360*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_acks); 361*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_qacks); 362*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_delayed_comp); 363*f931551bSRalph Campbell QIB_DIAGC_ATTR(seq_naks); 364*f931551bSRalph Campbell QIB_DIAGC_ATTR(rdma_seq); 365*f931551bSRalph Campbell QIB_DIAGC_ATTR(rnr_naks); 366*f931551bSRalph Campbell QIB_DIAGC_ATTR(other_naks); 367*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_timeouts); 368*f931551bSRalph Campbell QIB_DIAGC_ATTR(loop_pkts); 369*f931551bSRalph Campbell QIB_DIAGC_ATTR(pkt_drops); 370*f931551bSRalph Campbell QIB_DIAGC_ATTR(dmawait); 371*f931551bSRalph Campbell QIB_DIAGC_ATTR(unaligned); 372*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_dupreq); 373*f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_seqnak); 374*f931551bSRalph Campbell 375*f931551bSRalph Campbell static struct attribute *diagc_default_attributes[] = { 376*f931551bSRalph Campbell &qib_diagc_attr_rc_resends.attr, 377*f931551bSRalph Campbell &qib_diagc_attr_rc_acks.attr, 378*f931551bSRalph Campbell &qib_diagc_attr_rc_qacks.attr, 379*f931551bSRalph Campbell &qib_diagc_attr_rc_delayed_comp.attr, 380*f931551bSRalph Campbell &qib_diagc_attr_seq_naks.attr, 381*f931551bSRalph Campbell &qib_diagc_attr_rdma_seq.attr, 382*f931551bSRalph Campbell &qib_diagc_attr_rnr_naks.attr, 383*f931551bSRalph Campbell &qib_diagc_attr_other_naks.attr, 384*f931551bSRalph Campbell &qib_diagc_attr_rc_timeouts.attr, 385*f931551bSRalph Campbell &qib_diagc_attr_loop_pkts.attr, 386*f931551bSRalph Campbell &qib_diagc_attr_pkt_drops.attr, 387*f931551bSRalph Campbell &qib_diagc_attr_dmawait.attr, 388*f931551bSRalph Campbell &qib_diagc_attr_unaligned.attr, 389*f931551bSRalph Campbell &qib_diagc_attr_rc_dupreq.attr, 390*f931551bSRalph Campbell &qib_diagc_attr_rc_seqnak.attr, 391*f931551bSRalph Campbell NULL 392*f931551bSRalph Campbell }; 393*f931551bSRalph Campbell 394*f931551bSRalph Campbell static ssize_t diagc_attr_show(struct kobject *kobj, struct attribute *attr, 395*f931551bSRalph Campbell char *buf) 396*f931551bSRalph Campbell { 397*f931551bSRalph Campbell struct qib_diagc_attr *dattr = 398*f931551bSRalph Campbell container_of(attr, struct qib_diagc_attr, attr); 399*f931551bSRalph Campbell struct qib_pportdata *ppd = 400*f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, diagc_kobj); 401*f931551bSRalph Campbell struct qib_ibport *qibp = &ppd->ibport_data; 402*f931551bSRalph Campbell 403*f931551bSRalph Campbell return sprintf(buf, "%u\n", *(u32 *)((char *)qibp + dattr->counter)); 404*f931551bSRalph Campbell } 405*f931551bSRalph Campbell 406*f931551bSRalph Campbell static const struct sysfs_ops qib_diagc_ops = { 407*f931551bSRalph Campbell .show = diagc_attr_show, 408*f931551bSRalph Campbell }; 409*f931551bSRalph Campbell 410*f931551bSRalph Campbell static struct kobj_type qib_diagc_ktype = { 411*f931551bSRalph Campbell .release = qib_port_release, 412*f931551bSRalph Campbell .sysfs_ops = &qib_diagc_ops, 413*f931551bSRalph Campbell .default_attrs = diagc_default_attributes 414*f931551bSRalph Campbell }; 415*f931551bSRalph Campbell 416*f931551bSRalph Campbell /* End diag_counters */ 417*f931551bSRalph Campbell 418*f931551bSRalph Campbell /* end of per-port file structures and support code */ 419*f931551bSRalph Campbell 420*f931551bSRalph Campbell /* 421*f931551bSRalph Campbell * Start of per-unit (or driver, in some cases, but replicated 422*f931551bSRalph Campbell * per unit) functions (these get a device *) 423*f931551bSRalph Campbell */ 424*f931551bSRalph Campbell static ssize_t show_rev(struct device *device, struct device_attribute *attr, 425*f931551bSRalph Campbell char *buf) 426*f931551bSRalph Campbell { 427*f931551bSRalph Campbell struct qib_ibdev *dev = 428*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 429*f931551bSRalph Campbell 430*f931551bSRalph Campbell return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev); 431*f931551bSRalph Campbell } 432*f931551bSRalph Campbell 433*f931551bSRalph Campbell static ssize_t show_hca(struct device *device, struct device_attribute *attr, 434*f931551bSRalph Campbell char *buf) 435*f931551bSRalph Campbell { 436*f931551bSRalph Campbell struct qib_ibdev *dev = 437*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 438*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 439*f931551bSRalph Campbell int ret; 440*f931551bSRalph Campbell 441*f931551bSRalph Campbell if (!dd->boardname) 442*f931551bSRalph Campbell ret = -EINVAL; 443*f931551bSRalph Campbell else 444*f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname); 445*f931551bSRalph Campbell return ret; 446*f931551bSRalph Campbell } 447*f931551bSRalph Campbell 448*f931551bSRalph Campbell static ssize_t show_version(struct device *device, 449*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 450*f931551bSRalph Campbell { 451*f931551bSRalph Campbell /* The string printed here is already newline-terminated. */ 452*f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%s", (char *)ib_qib_version); 453*f931551bSRalph Campbell } 454*f931551bSRalph Campbell 455*f931551bSRalph Campbell static ssize_t show_boardversion(struct device *device, 456*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 457*f931551bSRalph Campbell { 458*f931551bSRalph Campbell struct qib_ibdev *dev = 459*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 460*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 461*f931551bSRalph Campbell 462*f931551bSRalph Campbell /* The string printed here is already newline-terminated. */ 463*f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion); 464*f931551bSRalph Campbell } 465*f931551bSRalph Campbell 466*f931551bSRalph Campbell 467*f931551bSRalph Campbell static ssize_t show_localbus_info(struct device *device, 468*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 469*f931551bSRalph Campbell { 470*f931551bSRalph Campbell struct qib_ibdev *dev = 471*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 472*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 473*f931551bSRalph Campbell 474*f931551bSRalph Campbell /* The string printed here is already newline-terminated. */ 475*f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%s", dd->lbus_info); 476*f931551bSRalph Campbell } 477*f931551bSRalph Campbell 478*f931551bSRalph Campbell 479*f931551bSRalph Campbell static ssize_t show_nctxts(struct device *device, 480*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 481*f931551bSRalph Campbell { 482*f931551bSRalph Campbell struct qib_ibdev *dev = 483*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 484*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 485*f931551bSRalph Campbell 486*f931551bSRalph Campbell /* Return the number of user ports (contexts) available. */ 487*f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%u\n", dd->cfgctxts - 488*f931551bSRalph Campbell dd->first_user_ctxt); 489*f931551bSRalph Campbell } 490*f931551bSRalph Campbell 491*f931551bSRalph Campbell static ssize_t show_serial(struct device *device, 492*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 493*f931551bSRalph Campbell { 494*f931551bSRalph Campbell struct qib_ibdev *dev = 495*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 496*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 497*f931551bSRalph Campbell 498*f931551bSRalph Campbell buf[sizeof dd->serial] = '\0'; 499*f931551bSRalph Campbell memcpy(buf, dd->serial, sizeof dd->serial); 500*f931551bSRalph Campbell strcat(buf, "\n"); 501*f931551bSRalph Campbell return strlen(buf); 502*f931551bSRalph Campbell } 503*f931551bSRalph Campbell 504*f931551bSRalph Campbell static ssize_t store_chip_reset(struct device *device, 505*f931551bSRalph Campbell struct device_attribute *attr, const char *buf, 506*f931551bSRalph Campbell size_t count) 507*f931551bSRalph Campbell { 508*f931551bSRalph Campbell struct qib_ibdev *dev = 509*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 510*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 511*f931551bSRalph Campbell int ret; 512*f931551bSRalph Campbell 513*f931551bSRalph Campbell if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) { 514*f931551bSRalph Campbell ret = -EINVAL; 515*f931551bSRalph Campbell goto bail; 516*f931551bSRalph Campbell } 517*f931551bSRalph Campbell 518*f931551bSRalph Campbell ret = qib_reset_device(dd->unit); 519*f931551bSRalph Campbell bail: 520*f931551bSRalph Campbell return ret < 0 ? ret : count; 521*f931551bSRalph Campbell } 522*f931551bSRalph Campbell 523*f931551bSRalph Campbell static ssize_t show_logged_errs(struct device *device, 524*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 525*f931551bSRalph Campbell { 526*f931551bSRalph Campbell struct qib_ibdev *dev = 527*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 528*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 529*f931551bSRalph Campbell int idx, count; 530*f931551bSRalph Campbell 531*f931551bSRalph Campbell /* force consistency with actual EEPROM */ 532*f931551bSRalph Campbell if (qib_update_eeprom_log(dd) != 0) 533*f931551bSRalph Campbell return -ENXIO; 534*f931551bSRalph Campbell 535*f931551bSRalph Campbell count = 0; 536*f931551bSRalph Campbell for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { 537*f931551bSRalph Campbell count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", 538*f931551bSRalph Campbell dd->eep_st_errs[idx], 539*f931551bSRalph Campbell idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' '); 540*f931551bSRalph Campbell } 541*f931551bSRalph Campbell 542*f931551bSRalph Campbell return count; 543*f931551bSRalph Campbell } 544*f931551bSRalph Campbell 545*f931551bSRalph Campbell /* 546*f931551bSRalph Campbell * Dump tempsense regs. in decimal, to ease shell-scripts. 547*f931551bSRalph Campbell */ 548*f931551bSRalph Campbell static ssize_t show_tempsense(struct device *device, 549*f931551bSRalph Campbell struct device_attribute *attr, char *buf) 550*f931551bSRalph Campbell { 551*f931551bSRalph Campbell struct qib_ibdev *dev = 552*f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 553*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 554*f931551bSRalph Campbell int ret; 555*f931551bSRalph Campbell int idx; 556*f931551bSRalph Campbell u8 regvals[8]; 557*f931551bSRalph Campbell 558*f931551bSRalph Campbell ret = -ENXIO; 559*f931551bSRalph Campbell for (idx = 0; idx < 8; ++idx) { 560*f931551bSRalph Campbell if (idx == 6) 561*f931551bSRalph Campbell continue; 562*f931551bSRalph Campbell ret = dd->f_tempsense_rd(dd, idx); 563*f931551bSRalph Campbell if (ret < 0) 564*f931551bSRalph Campbell break; 565*f931551bSRalph Campbell regvals[idx] = ret; 566*f931551bSRalph Campbell } 567*f931551bSRalph Campbell if (idx == 8) 568*f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n", 569*f931551bSRalph Campbell *(signed char *)(regvals), 570*f931551bSRalph Campbell *(signed char *)(regvals + 1), 571*f931551bSRalph Campbell regvals[2], regvals[3], 572*f931551bSRalph Campbell *(signed char *)(regvals + 5), 573*f931551bSRalph Campbell *(signed char *)(regvals + 7)); 574*f931551bSRalph Campbell return ret; 575*f931551bSRalph Campbell } 576*f931551bSRalph Campbell 577*f931551bSRalph Campbell /* 578*f931551bSRalph Campbell * end of per-unit (or driver, in some cases, but replicated 579*f931551bSRalph Campbell * per unit) functions 580*f931551bSRalph Campbell */ 581*f931551bSRalph Campbell 582*f931551bSRalph Campbell /* start of per-unit file structures and support code */ 583*f931551bSRalph Campbell static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); 584*f931551bSRalph Campbell static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); 585*f931551bSRalph Campbell static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL); 586*f931551bSRalph Campbell static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); 587*f931551bSRalph Campbell static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL); 588*f931551bSRalph Campbell static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); 589*f931551bSRalph Campbell static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); 590*f931551bSRalph Campbell static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); 591*f931551bSRalph Campbell static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL); 592*f931551bSRalph Campbell static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL); 593*f931551bSRalph Campbell static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset); 594*f931551bSRalph Campbell 595*f931551bSRalph Campbell static struct device_attribute *qib_attributes[] = { 596*f931551bSRalph Campbell &dev_attr_hw_rev, 597*f931551bSRalph Campbell &dev_attr_hca_type, 598*f931551bSRalph Campbell &dev_attr_board_id, 599*f931551bSRalph Campbell &dev_attr_version, 600*f931551bSRalph Campbell &dev_attr_nctxts, 601*f931551bSRalph Campbell &dev_attr_serial, 602*f931551bSRalph Campbell &dev_attr_boardversion, 603*f931551bSRalph Campbell &dev_attr_logged_errors, 604*f931551bSRalph Campbell &dev_attr_tempsense, 605*f931551bSRalph Campbell &dev_attr_localbus_info, 606*f931551bSRalph Campbell &dev_attr_chip_reset, 607*f931551bSRalph Campbell }; 608*f931551bSRalph Campbell 609*f931551bSRalph Campbell int qib_create_port_files(struct ib_device *ibdev, u8 port_num, 610*f931551bSRalph Campbell struct kobject *kobj) 611*f931551bSRalph Campbell { 612*f931551bSRalph Campbell struct qib_pportdata *ppd; 613*f931551bSRalph Campbell struct qib_devdata *dd = dd_from_ibdev(ibdev); 614*f931551bSRalph Campbell int ret; 615*f931551bSRalph Campbell 616*f931551bSRalph Campbell if (!port_num || port_num > dd->num_pports) { 617*f931551bSRalph Campbell qib_dev_err(dd, "Skipping infiniband class with " 618*f931551bSRalph Campbell "invalid port %u\n", port_num); 619*f931551bSRalph Campbell ret = -ENODEV; 620*f931551bSRalph Campbell goto bail; 621*f931551bSRalph Campbell } 622*f931551bSRalph Campbell ppd = &dd->pport[port_num - 1]; 623*f931551bSRalph Campbell 624*f931551bSRalph Campbell ret = kobject_init_and_add(&ppd->pport_kobj, &qib_port_ktype, kobj, 625*f931551bSRalph Campbell "linkcontrol"); 626*f931551bSRalph Campbell if (ret) { 627*f931551bSRalph Campbell qib_dev_err(dd, "Skipping linkcontrol sysfs info, " 628*f931551bSRalph Campbell "(err %d) port %u\n", ret, port_num); 629*f931551bSRalph Campbell goto bail; 630*f931551bSRalph Campbell } 631*f931551bSRalph Campbell kobject_uevent(&ppd->pport_kobj, KOBJ_ADD); 632*f931551bSRalph Campbell 633*f931551bSRalph Campbell ret = kobject_init_and_add(&ppd->sl2vl_kobj, &qib_sl2vl_ktype, kobj, 634*f931551bSRalph Campbell "sl2vl"); 635*f931551bSRalph Campbell if (ret) { 636*f931551bSRalph Campbell qib_dev_err(dd, "Skipping sl2vl sysfs info, " 637*f931551bSRalph Campbell "(err %d) port %u\n", ret, port_num); 638*f931551bSRalph Campbell goto bail_sl; 639*f931551bSRalph Campbell } 640*f931551bSRalph Campbell kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); 641*f931551bSRalph Campbell 642*f931551bSRalph Campbell ret = kobject_init_and_add(&ppd->diagc_kobj, &qib_diagc_ktype, kobj, 643*f931551bSRalph Campbell "diag_counters"); 644*f931551bSRalph Campbell if (ret) { 645*f931551bSRalph Campbell qib_dev_err(dd, "Skipping diag_counters sysfs info, " 646*f931551bSRalph Campbell "(err %d) port %u\n", ret, port_num); 647*f931551bSRalph Campbell goto bail_diagc; 648*f931551bSRalph Campbell } 649*f931551bSRalph Campbell kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); 650*f931551bSRalph Campbell 651*f931551bSRalph Campbell return 0; 652*f931551bSRalph Campbell 653*f931551bSRalph Campbell bail_diagc: 654*f931551bSRalph Campbell kobject_put(&ppd->sl2vl_kobj); 655*f931551bSRalph Campbell bail_sl: 656*f931551bSRalph Campbell kobject_put(&ppd->pport_kobj); 657*f931551bSRalph Campbell bail: 658*f931551bSRalph Campbell return ret; 659*f931551bSRalph Campbell } 660*f931551bSRalph Campbell 661*f931551bSRalph Campbell /* 662*f931551bSRalph Campbell * Register and create our files in /sys/class/infiniband. 663*f931551bSRalph Campbell */ 664*f931551bSRalph Campbell int qib_verbs_register_sysfs(struct qib_devdata *dd) 665*f931551bSRalph Campbell { 666*f931551bSRalph Campbell struct ib_device *dev = &dd->verbs_dev.ibdev; 667*f931551bSRalph Campbell int i, ret; 668*f931551bSRalph Campbell 669*f931551bSRalph Campbell for (i = 0; i < ARRAY_SIZE(qib_attributes); ++i) { 670*f931551bSRalph Campbell ret = device_create_file(&dev->dev, qib_attributes[i]); 671*f931551bSRalph Campbell if (ret) 672*f931551bSRalph Campbell return ret; 673*f931551bSRalph Campbell } 674*f931551bSRalph Campbell 675*f931551bSRalph Campbell return 0; 676*f931551bSRalph Campbell } 677*f931551bSRalph Campbell 678*f931551bSRalph Campbell /* 679*f931551bSRalph Campbell * Unregister and remove our files in /sys/class/infiniband. 680*f931551bSRalph Campbell */ 681*f931551bSRalph Campbell void qib_verbs_unregister_sysfs(struct qib_devdata *dd) 682*f931551bSRalph Campbell { 683*f931551bSRalph Campbell struct qib_pportdata *ppd; 684*f931551bSRalph Campbell int i; 685*f931551bSRalph Campbell 686*f931551bSRalph Campbell for (i = 0; i < dd->num_pports; i++) { 687*f931551bSRalph Campbell ppd = &dd->pport[i]; 688*f931551bSRalph Campbell kobject_put(&ppd->pport_kobj); 689*f931551bSRalph Campbell kobject_put(&ppd->sl2vl_kobj); 690*f931551bSRalph Campbell } 691*f931551bSRalph Campbell } 692