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