1f931551bSRalph Campbell /* 2*36a8f01cSMike Marciniszyn * Copyright (c) 2012 Intel Corporation. All rights reserved. 3*36a8f01cSMike Marciniszyn * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 4f931551bSRalph Campbell * Copyright (c) 2006 PathScale, Inc. All rights reserved. 5f931551bSRalph Campbell * 6f931551bSRalph Campbell * This software is available to you under a choice of one of two 7f931551bSRalph Campbell * licenses. You may choose to be licensed under the terms of the GNU 8f931551bSRalph Campbell * General Public License (GPL) Version 2, available from the file 9f931551bSRalph Campbell * COPYING in the main directory of this source tree, or the 10f931551bSRalph Campbell * OpenIB.org BSD license below: 11f931551bSRalph Campbell * 12f931551bSRalph Campbell * Redistribution and use in source and binary forms, with or 13f931551bSRalph Campbell * without modification, are permitted provided that the following 14f931551bSRalph Campbell * conditions are met: 15f931551bSRalph Campbell * 16f931551bSRalph Campbell * - Redistributions of source code must retain the above 17f931551bSRalph Campbell * copyright notice, this list of conditions and the following 18f931551bSRalph Campbell * disclaimer. 19f931551bSRalph Campbell * 20f931551bSRalph Campbell * - Redistributions in binary form must reproduce the above 21f931551bSRalph Campbell * copyright notice, this list of conditions and the following 22f931551bSRalph Campbell * disclaimer in the documentation and/or other materials 23f931551bSRalph Campbell * provided with the distribution. 24f931551bSRalph Campbell * 25f931551bSRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26f931551bSRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27f931551bSRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28f931551bSRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29f931551bSRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30f931551bSRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31f931551bSRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32f931551bSRalph Campbell * SOFTWARE. 33f931551bSRalph Campbell */ 34f931551bSRalph Campbell #include <linux/ctype.h> 35f931551bSRalph Campbell 36f931551bSRalph Campbell #include "qib.h" 37*36a8f01cSMike Marciniszyn #include "qib_mad.h" 38f931551bSRalph Campbell 39f931551bSRalph Campbell /** 40f931551bSRalph Campbell * qib_parse_ushort - parse an unsigned short value in an arbitrary base 41f931551bSRalph Campbell * @str: the string containing the number 42f931551bSRalph Campbell * @valp: where to put the result 43f931551bSRalph Campbell * 44f931551bSRalph Campbell * Returns the number of bytes consumed, or negative value on error. 45f931551bSRalph Campbell */ 46f931551bSRalph Campbell static int qib_parse_ushort(const char *str, unsigned short *valp) 47f931551bSRalph Campbell { 48f931551bSRalph Campbell unsigned long val; 49f931551bSRalph Campbell char *end; 50f931551bSRalph Campbell int ret; 51f931551bSRalph Campbell 52f931551bSRalph Campbell if (!isdigit(str[0])) { 53f931551bSRalph Campbell ret = -EINVAL; 54f931551bSRalph Campbell goto bail; 55f931551bSRalph Campbell } 56f931551bSRalph Campbell 57f931551bSRalph Campbell val = simple_strtoul(str, &end, 0); 58f931551bSRalph Campbell 59f931551bSRalph Campbell if (val > 0xffff) { 60f931551bSRalph Campbell ret = -EINVAL; 61f931551bSRalph Campbell goto bail; 62f931551bSRalph Campbell } 63f931551bSRalph Campbell 64f931551bSRalph Campbell *valp = val; 65f931551bSRalph Campbell 66f931551bSRalph Campbell ret = end + 1 - str; 67f931551bSRalph Campbell if (ret == 0) 68f931551bSRalph Campbell ret = -EINVAL; 69f931551bSRalph Campbell 70f931551bSRalph Campbell bail: 71f931551bSRalph Campbell return ret; 72f931551bSRalph Campbell } 73f931551bSRalph Campbell 74f931551bSRalph Campbell /* start of per-port functions */ 75f931551bSRalph Campbell /* 76f931551bSRalph Campbell * Get/Set heartbeat enable. OR of 1=enabled, 2=auto 77f931551bSRalph Campbell */ 78f931551bSRalph Campbell static ssize_t show_hrtbt_enb(struct qib_pportdata *ppd, char *buf) 79f931551bSRalph Campbell { 80f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 81f931551bSRalph Campbell int ret; 82f931551bSRalph Campbell 83f931551bSRalph Campbell ret = dd->f_get_ib_cfg(ppd, QIB_IB_CFG_HRTBT); 84f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); 85f931551bSRalph Campbell return ret; 86f931551bSRalph Campbell } 87f931551bSRalph Campbell 88f931551bSRalph Campbell static ssize_t store_hrtbt_enb(struct qib_pportdata *ppd, const char *buf, 89f931551bSRalph Campbell size_t count) 90f931551bSRalph Campbell { 91f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 92f931551bSRalph Campbell int ret; 93f931551bSRalph Campbell u16 val; 94f931551bSRalph Campbell 95f931551bSRalph Campbell ret = qib_parse_ushort(buf, &val); 96f931551bSRalph Campbell 97f931551bSRalph Campbell /* 98f931551bSRalph Campbell * Set the "intentional" heartbeat enable per either of 99f931551bSRalph Campbell * "Enable" and "Auto", as these are normally set together. 100f931551bSRalph Campbell * This bit is consulted when leaving loopback mode, 101f931551bSRalph Campbell * because entering loopback mode overrides it and automatically 102f931551bSRalph Campbell * disables heartbeat. 103f931551bSRalph Campbell */ 104f931551bSRalph Campbell if (ret >= 0) 105f931551bSRalph Campbell ret = dd->f_set_ib_cfg(ppd, QIB_IB_CFG_HRTBT, val); 106f931551bSRalph Campbell if (ret < 0) 107f931551bSRalph Campbell qib_dev_err(dd, "attempt to set invalid Heartbeat enable\n"); 108f931551bSRalph Campbell return ret < 0 ? ret : count; 109f931551bSRalph Campbell } 110f931551bSRalph Campbell 111f931551bSRalph Campbell static ssize_t store_loopback(struct qib_pportdata *ppd, const char *buf, 112f931551bSRalph Campbell size_t count) 113f931551bSRalph Campbell { 114f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 115f931551bSRalph Campbell int ret = count, r; 116f931551bSRalph Campbell 117f931551bSRalph Campbell r = dd->f_set_ib_loopback(ppd, buf); 118f931551bSRalph Campbell if (r < 0) 119f931551bSRalph Campbell ret = r; 120f931551bSRalph Campbell 121f931551bSRalph Campbell return ret; 122f931551bSRalph Campbell } 123f931551bSRalph Campbell 124f931551bSRalph Campbell static ssize_t store_led_override(struct qib_pportdata *ppd, const char *buf, 125f931551bSRalph Campbell size_t count) 126f931551bSRalph Campbell { 127f931551bSRalph Campbell struct qib_devdata *dd = ppd->dd; 128f931551bSRalph Campbell int ret; 129f931551bSRalph Campbell u16 val; 130f931551bSRalph Campbell 131f931551bSRalph Campbell ret = qib_parse_ushort(buf, &val); 132f931551bSRalph Campbell if (ret > 0) 133f931551bSRalph Campbell qib_set_led_override(ppd, val); 134f931551bSRalph Campbell else 135f931551bSRalph Campbell qib_dev_err(dd, "attempt to set invalid LED override\n"); 136f931551bSRalph Campbell return ret < 0 ? ret : count; 137f931551bSRalph Campbell } 138f931551bSRalph Campbell 139f931551bSRalph Campbell static ssize_t show_status(struct qib_pportdata *ppd, char *buf) 140f931551bSRalph Campbell { 141f931551bSRalph Campbell ssize_t ret; 142f931551bSRalph Campbell 143f931551bSRalph Campbell if (!ppd->statusp) 144f931551bSRalph Campbell ret = -EINVAL; 145f931551bSRalph Campbell else 146f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n", 147f931551bSRalph Campbell (unsigned long long) *(ppd->statusp)); 148f931551bSRalph Campbell return ret; 149f931551bSRalph Campbell } 150f931551bSRalph Campbell 151f931551bSRalph Campbell /* 152f931551bSRalph Campbell * For userland compatibility, these offsets must remain fixed. 153f931551bSRalph Campbell * They are strings for QIB_STATUS_* 154f931551bSRalph Campbell */ 155865b64beSMike Marciniszyn static const char * const qib_status_str[] = { 156f931551bSRalph Campbell "Initted", 157f931551bSRalph Campbell "", 158f931551bSRalph Campbell "", 159f931551bSRalph Campbell "", 160f931551bSRalph Campbell "", 161f931551bSRalph Campbell "Present", 162f931551bSRalph Campbell "IB_link_up", 163f931551bSRalph Campbell "IB_configured", 164f931551bSRalph Campbell "", 165f931551bSRalph Campbell "Fatal_Hardware_Error", 166f931551bSRalph Campbell NULL, 167f931551bSRalph Campbell }; 168f931551bSRalph Campbell 169f931551bSRalph Campbell static ssize_t show_status_str(struct qib_pportdata *ppd, char *buf) 170f931551bSRalph Campbell { 171f931551bSRalph Campbell int i, any; 172f931551bSRalph Campbell u64 s; 173f931551bSRalph Campbell ssize_t ret; 174f931551bSRalph Campbell 175f931551bSRalph Campbell if (!ppd->statusp) { 176f931551bSRalph Campbell ret = -EINVAL; 177f931551bSRalph Campbell goto bail; 178f931551bSRalph Campbell } 179f931551bSRalph Campbell 180f931551bSRalph Campbell s = *(ppd->statusp); 181f931551bSRalph Campbell *buf = '\0'; 182f931551bSRalph Campbell for (any = i = 0; s && qib_status_str[i]; i++) { 183f931551bSRalph Campbell if (s & 1) { 184f931551bSRalph Campbell /* if overflow */ 185f931551bSRalph Campbell if (any && strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) 186f931551bSRalph Campbell break; 187f931551bSRalph Campbell if (strlcat(buf, qib_status_str[i], PAGE_SIZE) >= 188f931551bSRalph Campbell PAGE_SIZE) 189f931551bSRalph Campbell break; 190f931551bSRalph Campbell any = 1; 191f931551bSRalph Campbell } 192f931551bSRalph Campbell s >>= 1; 193f931551bSRalph Campbell } 194f931551bSRalph Campbell if (any) 195f931551bSRalph Campbell strlcat(buf, "\n", PAGE_SIZE); 196f931551bSRalph Campbell 197f931551bSRalph Campbell ret = strlen(buf); 198f931551bSRalph Campbell 199f931551bSRalph Campbell bail: 200f931551bSRalph Campbell return ret; 201f931551bSRalph Campbell } 202f931551bSRalph Campbell 203f931551bSRalph Campbell /* end of per-port functions */ 204f931551bSRalph Campbell 205f931551bSRalph Campbell /* 206f931551bSRalph Campbell * Start of per-port file structures and support code 207f931551bSRalph Campbell * Because we are fitting into other infrastructure, we have to supply the 208f931551bSRalph Campbell * full set of kobject/sysfs_ops structures and routines. 209f931551bSRalph Campbell */ 210f931551bSRalph Campbell #define QIB_PORT_ATTR(name, mode, show, store) \ 211f931551bSRalph Campbell static struct qib_port_attr qib_port_attr_##name = \ 212f931551bSRalph Campbell __ATTR(name, mode, show, store) 213f931551bSRalph Campbell 214f931551bSRalph Campbell struct qib_port_attr { 215f931551bSRalph Campbell struct attribute attr; 216f931551bSRalph Campbell ssize_t (*show)(struct qib_pportdata *, char *); 217f931551bSRalph Campbell ssize_t (*store)(struct qib_pportdata *, const char *, size_t); 218f931551bSRalph Campbell }; 219f931551bSRalph Campbell 220f931551bSRalph Campbell QIB_PORT_ATTR(loopback, S_IWUSR, NULL, store_loopback); 221f931551bSRalph Campbell QIB_PORT_ATTR(led_override, S_IWUSR, NULL, store_led_override); 222f931551bSRalph Campbell QIB_PORT_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb, 223f931551bSRalph Campbell store_hrtbt_enb); 224f931551bSRalph Campbell QIB_PORT_ATTR(status, S_IRUGO, show_status, NULL); 225f931551bSRalph Campbell QIB_PORT_ATTR(status_str, S_IRUGO, show_status_str, NULL); 226f931551bSRalph Campbell 227f931551bSRalph Campbell static struct attribute *port_default_attributes[] = { 228f931551bSRalph Campbell &qib_port_attr_loopback.attr, 229f931551bSRalph Campbell &qib_port_attr_led_override.attr, 230f931551bSRalph Campbell &qib_port_attr_hrtbt_enable.attr, 231f931551bSRalph Campbell &qib_port_attr_status.attr, 232f931551bSRalph Campbell &qib_port_attr_status_str.attr, 233f931551bSRalph Campbell NULL 234f931551bSRalph Campbell }; 235f931551bSRalph Campbell 236*36a8f01cSMike Marciniszyn /* 237*36a8f01cSMike Marciniszyn * Start of per-port congestion control structures and support code 238*36a8f01cSMike Marciniszyn */ 239*36a8f01cSMike Marciniszyn 240*36a8f01cSMike Marciniszyn /* 241*36a8f01cSMike Marciniszyn * Congestion control table size followed by table entries 242*36a8f01cSMike Marciniszyn */ 243*36a8f01cSMike Marciniszyn static ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj, 244*36a8f01cSMike Marciniszyn struct bin_attribute *bin_attr, 245*36a8f01cSMike Marciniszyn char *buf, loff_t pos, size_t count) 246*36a8f01cSMike Marciniszyn { 247*36a8f01cSMike Marciniszyn int ret; 248*36a8f01cSMike Marciniszyn struct qib_pportdata *ppd = 249*36a8f01cSMike Marciniszyn container_of(kobj, struct qib_pportdata, pport_cc_kobj); 250*36a8f01cSMike Marciniszyn 251*36a8f01cSMike Marciniszyn if (!qib_cc_table_size || !ppd->ccti_entries_shadow) 252*36a8f01cSMike Marciniszyn return -EINVAL; 253*36a8f01cSMike Marciniszyn 254*36a8f01cSMike Marciniszyn ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow) 255*36a8f01cSMike Marciniszyn + sizeof(__be16); 256*36a8f01cSMike Marciniszyn 257*36a8f01cSMike Marciniszyn if (pos > ret) 258*36a8f01cSMike Marciniszyn return -EINVAL; 259*36a8f01cSMike Marciniszyn 260*36a8f01cSMike Marciniszyn if (count > ret - pos) 261*36a8f01cSMike Marciniszyn count = ret - pos; 262*36a8f01cSMike Marciniszyn 263*36a8f01cSMike Marciniszyn if (!count) 264*36a8f01cSMike Marciniszyn return count; 265*36a8f01cSMike Marciniszyn 266*36a8f01cSMike Marciniszyn spin_lock(&ppd->cc_shadow_lock); 267*36a8f01cSMike Marciniszyn memcpy(buf, ppd->ccti_entries_shadow, count); 268*36a8f01cSMike Marciniszyn spin_unlock(&ppd->cc_shadow_lock); 269*36a8f01cSMike Marciniszyn 270*36a8f01cSMike Marciniszyn return count; 271*36a8f01cSMike Marciniszyn } 272*36a8f01cSMike Marciniszyn 273*36a8f01cSMike Marciniszyn static void qib_port_release(struct kobject *kobj) 274*36a8f01cSMike Marciniszyn { 275*36a8f01cSMike Marciniszyn /* nothing to do since memory is freed by qib_free_devdata() */ 276*36a8f01cSMike Marciniszyn } 277*36a8f01cSMike Marciniszyn 278*36a8f01cSMike Marciniszyn static struct kobj_type qib_port_cc_ktype = { 279*36a8f01cSMike Marciniszyn .release = qib_port_release, 280*36a8f01cSMike Marciniszyn }; 281*36a8f01cSMike Marciniszyn 282*36a8f01cSMike Marciniszyn static struct bin_attribute cc_table_bin_attr = { 283*36a8f01cSMike Marciniszyn .attr = {.name = "cc_table_bin", .mode = 0444}, 284*36a8f01cSMike Marciniszyn .read = read_cc_table_bin, 285*36a8f01cSMike Marciniszyn .size = PAGE_SIZE, 286*36a8f01cSMike Marciniszyn }; 287*36a8f01cSMike Marciniszyn 288*36a8f01cSMike Marciniszyn /* 289*36a8f01cSMike Marciniszyn * Congestion settings: port control, control map and an array of 16 290*36a8f01cSMike Marciniszyn * entries for the congestion entries - increase, timer, event log 291*36a8f01cSMike Marciniszyn * trigger threshold and the minimum injection rate delay. 292*36a8f01cSMike Marciniszyn */ 293*36a8f01cSMike Marciniszyn static ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj, 294*36a8f01cSMike Marciniszyn struct bin_attribute *bin_attr, 295*36a8f01cSMike Marciniszyn char *buf, loff_t pos, size_t count) 296*36a8f01cSMike Marciniszyn { 297*36a8f01cSMike Marciniszyn int ret; 298*36a8f01cSMike Marciniszyn struct qib_pportdata *ppd = 299*36a8f01cSMike Marciniszyn container_of(kobj, struct qib_pportdata, pport_cc_kobj); 300*36a8f01cSMike Marciniszyn 301*36a8f01cSMike Marciniszyn if (!qib_cc_table_size || !ppd->congestion_entries_shadow) 302*36a8f01cSMike Marciniszyn return -EINVAL; 303*36a8f01cSMike Marciniszyn 304*36a8f01cSMike Marciniszyn ret = sizeof(struct ib_cc_congestion_setting_attr_shadow); 305*36a8f01cSMike Marciniszyn 306*36a8f01cSMike Marciniszyn if (pos > ret) 307*36a8f01cSMike Marciniszyn return -EINVAL; 308*36a8f01cSMike Marciniszyn if (count > ret - pos) 309*36a8f01cSMike Marciniszyn count = ret - pos; 310*36a8f01cSMike Marciniszyn 311*36a8f01cSMike Marciniszyn if (!count) 312*36a8f01cSMike Marciniszyn return count; 313*36a8f01cSMike Marciniszyn 314*36a8f01cSMike Marciniszyn spin_lock(&ppd->cc_shadow_lock); 315*36a8f01cSMike Marciniszyn memcpy(buf, ppd->congestion_entries_shadow, count); 316*36a8f01cSMike Marciniszyn spin_unlock(&ppd->cc_shadow_lock); 317*36a8f01cSMike Marciniszyn 318*36a8f01cSMike Marciniszyn return count; 319*36a8f01cSMike Marciniszyn } 320*36a8f01cSMike Marciniszyn 321*36a8f01cSMike Marciniszyn static struct bin_attribute cc_setting_bin_attr = { 322*36a8f01cSMike Marciniszyn .attr = {.name = "cc_settings_bin", .mode = 0444}, 323*36a8f01cSMike Marciniszyn .read = read_cc_setting_bin, 324*36a8f01cSMike Marciniszyn .size = PAGE_SIZE, 325*36a8f01cSMike Marciniszyn }; 326*36a8f01cSMike Marciniszyn 327*36a8f01cSMike Marciniszyn 328f931551bSRalph Campbell static ssize_t qib_portattr_show(struct kobject *kobj, 329f931551bSRalph Campbell struct attribute *attr, char *buf) 330f931551bSRalph Campbell { 331f931551bSRalph Campbell struct qib_port_attr *pattr = 332f931551bSRalph Campbell container_of(attr, struct qib_port_attr, attr); 333f931551bSRalph Campbell struct qib_pportdata *ppd = 334f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, pport_kobj); 335f931551bSRalph Campbell 336f931551bSRalph Campbell return pattr->show(ppd, buf); 337f931551bSRalph Campbell } 338f931551bSRalph Campbell 339f931551bSRalph Campbell static ssize_t qib_portattr_store(struct kobject *kobj, 340f931551bSRalph Campbell struct attribute *attr, const char *buf, size_t len) 341f931551bSRalph Campbell { 342f931551bSRalph Campbell struct qib_port_attr *pattr = 343f931551bSRalph Campbell container_of(attr, struct qib_port_attr, attr); 344f931551bSRalph Campbell struct qib_pportdata *ppd = 345f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, pport_kobj); 346f931551bSRalph Campbell 347f931551bSRalph Campbell return pattr->store(ppd, buf, len); 348f931551bSRalph Campbell } 349f931551bSRalph Campbell 350f931551bSRalph Campbell 351f931551bSRalph Campbell static const struct sysfs_ops qib_port_ops = { 352f931551bSRalph Campbell .show = qib_portattr_show, 353f931551bSRalph Campbell .store = qib_portattr_store, 354f931551bSRalph Campbell }; 355f931551bSRalph Campbell 356f931551bSRalph Campbell static struct kobj_type qib_port_ktype = { 357f931551bSRalph Campbell .release = qib_port_release, 358f931551bSRalph Campbell .sysfs_ops = &qib_port_ops, 359f931551bSRalph Campbell .default_attrs = port_default_attributes 360f931551bSRalph Campbell }; 361f931551bSRalph Campbell 362f931551bSRalph Campbell /* Start sl2vl */ 363f931551bSRalph Campbell 364f931551bSRalph Campbell #define QIB_SL2VL_ATTR(N) \ 365f931551bSRalph Campbell static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \ 366f931551bSRalph Campbell .attr = { .name = __stringify(N), .mode = 0444 }, \ 367f931551bSRalph Campbell .sl = N \ 368f931551bSRalph Campbell } 369f931551bSRalph Campbell 370f931551bSRalph Campbell struct qib_sl2vl_attr { 371f931551bSRalph Campbell struct attribute attr; 372f931551bSRalph Campbell int sl; 373f931551bSRalph Campbell }; 374f931551bSRalph Campbell 375f931551bSRalph Campbell QIB_SL2VL_ATTR(0); 376f931551bSRalph Campbell QIB_SL2VL_ATTR(1); 377f931551bSRalph Campbell QIB_SL2VL_ATTR(2); 378f931551bSRalph Campbell QIB_SL2VL_ATTR(3); 379f931551bSRalph Campbell QIB_SL2VL_ATTR(4); 380f931551bSRalph Campbell QIB_SL2VL_ATTR(5); 381f931551bSRalph Campbell QIB_SL2VL_ATTR(6); 382f931551bSRalph Campbell QIB_SL2VL_ATTR(7); 383f931551bSRalph Campbell QIB_SL2VL_ATTR(8); 384f931551bSRalph Campbell QIB_SL2VL_ATTR(9); 385f931551bSRalph Campbell QIB_SL2VL_ATTR(10); 386f931551bSRalph Campbell QIB_SL2VL_ATTR(11); 387f931551bSRalph Campbell QIB_SL2VL_ATTR(12); 388f931551bSRalph Campbell QIB_SL2VL_ATTR(13); 389f931551bSRalph Campbell QIB_SL2VL_ATTR(14); 390f931551bSRalph Campbell QIB_SL2VL_ATTR(15); 391f931551bSRalph Campbell 392f931551bSRalph Campbell static struct attribute *sl2vl_default_attributes[] = { 393f931551bSRalph Campbell &qib_sl2vl_attr_0.attr, 394f931551bSRalph Campbell &qib_sl2vl_attr_1.attr, 395f931551bSRalph Campbell &qib_sl2vl_attr_2.attr, 396f931551bSRalph Campbell &qib_sl2vl_attr_3.attr, 397f931551bSRalph Campbell &qib_sl2vl_attr_4.attr, 398f931551bSRalph Campbell &qib_sl2vl_attr_5.attr, 399f931551bSRalph Campbell &qib_sl2vl_attr_6.attr, 400f931551bSRalph Campbell &qib_sl2vl_attr_7.attr, 401f931551bSRalph Campbell &qib_sl2vl_attr_8.attr, 402f931551bSRalph Campbell &qib_sl2vl_attr_9.attr, 403f931551bSRalph Campbell &qib_sl2vl_attr_10.attr, 404f931551bSRalph Campbell &qib_sl2vl_attr_11.attr, 405f931551bSRalph Campbell &qib_sl2vl_attr_12.attr, 406f931551bSRalph Campbell &qib_sl2vl_attr_13.attr, 407f931551bSRalph Campbell &qib_sl2vl_attr_14.attr, 408f931551bSRalph Campbell &qib_sl2vl_attr_15.attr, 409f931551bSRalph Campbell NULL 410f931551bSRalph Campbell }; 411f931551bSRalph Campbell 412f931551bSRalph Campbell static ssize_t sl2vl_attr_show(struct kobject *kobj, struct attribute *attr, 413f931551bSRalph Campbell char *buf) 414f931551bSRalph Campbell { 415f931551bSRalph Campbell struct qib_sl2vl_attr *sattr = 416f931551bSRalph Campbell container_of(attr, struct qib_sl2vl_attr, attr); 417f931551bSRalph Campbell struct qib_pportdata *ppd = 418f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, sl2vl_kobj); 419f931551bSRalph Campbell struct qib_ibport *qibp = &ppd->ibport_data; 420f931551bSRalph Campbell 421f931551bSRalph Campbell return sprintf(buf, "%u\n", qibp->sl_to_vl[sattr->sl]); 422f931551bSRalph Campbell } 423f931551bSRalph Campbell 424f931551bSRalph Campbell static const struct sysfs_ops qib_sl2vl_ops = { 425f931551bSRalph Campbell .show = sl2vl_attr_show, 426f931551bSRalph Campbell }; 427f931551bSRalph Campbell 428f931551bSRalph Campbell static struct kobj_type qib_sl2vl_ktype = { 429f931551bSRalph Campbell .release = qib_port_release, 430f931551bSRalph Campbell .sysfs_ops = &qib_sl2vl_ops, 431f931551bSRalph Campbell .default_attrs = sl2vl_default_attributes 432f931551bSRalph Campbell }; 433f931551bSRalph Campbell 434f931551bSRalph Campbell /* End sl2vl */ 435f931551bSRalph Campbell 436f931551bSRalph Campbell /* Start diag_counters */ 437f931551bSRalph Campbell 438f931551bSRalph Campbell #define QIB_DIAGC_ATTR(N) \ 439f931551bSRalph Campbell static struct qib_diagc_attr qib_diagc_attr_##N = { \ 4404c6931f5SIra Weiny .attr = { .name = __stringify(N), .mode = 0664 }, \ 441f931551bSRalph Campbell .counter = offsetof(struct qib_ibport, n_##N) \ 442f931551bSRalph Campbell } 443f931551bSRalph Campbell 444f931551bSRalph Campbell struct qib_diagc_attr { 445f931551bSRalph Campbell struct attribute attr; 446f931551bSRalph Campbell size_t counter; 447f931551bSRalph Campbell }; 448f931551bSRalph Campbell 449f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_resends); 450f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_acks); 451f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_qacks); 452f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_delayed_comp); 453f931551bSRalph Campbell QIB_DIAGC_ATTR(seq_naks); 454f931551bSRalph Campbell QIB_DIAGC_ATTR(rdma_seq); 455f931551bSRalph Campbell QIB_DIAGC_ATTR(rnr_naks); 456f931551bSRalph Campbell QIB_DIAGC_ATTR(other_naks); 457f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_timeouts); 458f931551bSRalph Campbell QIB_DIAGC_ATTR(loop_pkts); 459f931551bSRalph Campbell QIB_DIAGC_ATTR(pkt_drops); 460f931551bSRalph Campbell QIB_DIAGC_ATTR(dmawait); 461f931551bSRalph Campbell QIB_DIAGC_ATTR(unaligned); 462f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_dupreq); 463f931551bSRalph Campbell QIB_DIAGC_ATTR(rc_seqnak); 464f931551bSRalph Campbell 465f931551bSRalph Campbell static struct attribute *diagc_default_attributes[] = { 466f931551bSRalph Campbell &qib_diagc_attr_rc_resends.attr, 467f931551bSRalph Campbell &qib_diagc_attr_rc_acks.attr, 468f931551bSRalph Campbell &qib_diagc_attr_rc_qacks.attr, 469f931551bSRalph Campbell &qib_diagc_attr_rc_delayed_comp.attr, 470f931551bSRalph Campbell &qib_diagc_attr_seq_naks.attr, 471f931551bSRalph Campbell &qib_diagc_attr_rdma_seq.attr, 472f931551bSRalph Campbell &qib_diagc_attr_rnr_naks.attr, 473f931551bSRalph Campbell &qib_diagc_attr_other_naks.attr, 474f931551bSRalph Campbell &qib_diagc_attr_rc_timeouts.attr, 475f931551bSRalph Campbell &qib_diagc_attr_loop_pkts.attr, 476f931551bSRalph Campbell &qib_diagc_attr_pkt_drops.attr, 477f931551bSRalph Campbell &qib_diagc_attr_dmawait.attr, 478f931551bSRalph Campbell &qib_diagc_attr_unaligned.attr, 479f931551bSRalph Campbell &qib_diagc_attr_rc_dupreq.attr, 480f931551bSRalph Campbell &qib_diagc_attr_rc_seqnak.attr, 481f931551bSRalph Campbell NULL 482f931551bSRalph Campbell }; 483f931551bSRalph Campbell 484f931551bSRalph Campbell static ssize_t diagc_attr_show(struct kobject *kobj, struct attribute *attr, 485f931551bSRalph Campbell char *buf) 486f931551bSRalph Campbell { 487f931551bSRalph Campbell struct qib_diagc_attr *dattr = 488f931551bSRalph Campbell container_of(attr, struct qib_diagc_attr, attr); 489f931551bSRalph Campbell struct qib_pportdata *ppd = 490f931551bSRalph Campbell container_of(kobj, struct qib_pportdata, diagc_kobj); 491f931551bSRalph Campbell struct qib_ibport *qibp = &ppd->ibport_data; 492f931551bSRalph Campbell 493f931551bSRalph Campbell return sprintf(buf, "%u\n", *(u32 *)((char *)qibp + dattr->counter)); 494f931551bSRalph Campbell } 495f931551bSRalph Campbell 4964c6931f5SIra Weiny static ssize_t diagc_attr_store(struct kobject *kobj, struct attribute *attr, 4974c6931f5SIra Weiny const char *buf, size_t size) 4984c6931f5SIra Weiny { 4994c6931f5SIra Weiny struct qib_diagc_attr *dattr = 5004c6931f5SIra Weiny container_of(attr, struct qib_diagc_attr, attr); 5014c6931f5SIra Weiny struct qib_pportdata *ppd = 5024c6931f5SIra Weiny container_of(kobj, struct qib_pportdata, diagc_kobj); 5034c6931f5SIra Weiny struct qib_ibport *qibp = &ppd->ibport_data; 5044c6931f5SIra Weiny char *endp; 5054c6931f5SIra Weiny long val = simple_strtol(buf, &endp, 0); 5064c6931f5SIra Weiny 5074c6931f5SIra Weiny if (val < 0 || endp == buf) 5084c6931f5SIra Weiny return -EINVAL; 5094c6931f5SIra Weiny 5104c6931f5SIra Weiny *(u32 *)((char *) qibp + dattr->counter) = val; 5114c6931f5SIra Weiny return size; 5124c6931f5SIra Weiny } 5134c6931f5SIra Weiny 514f931551bSRalph Campbell static const struct sysfs_ops qib_diagc_ops = { 515f931551bSRalph Campbell .show = diagc_attr_show, 5164c6931f5SIra Weiny .store = diagc_attr_store, 517f931551bSRalph Campbell }; 518f931551bSRalph Campbell 519f931551bSRalph Campbell static struct kobj_type qib_diagc_ktype = { 520f931551bSRalph Campbell .release = qib_port_release, 521f931551bSRalph Campbell .sysfs_ops = &qib_diagc_ops, 522f931551bSRalph Campbell .default_attrs = diagc_default_attributes 523f931551bSRalph Campbell }; 524f931551bSRalph Campbell 525f931551bSRalph Campbell /* End diag_counters */ 526f931551bSRalph Campbell 527f931551bSRalph Campbell /* end of per-port file structures and support code */ 528f931551bSRalph Campbell 529f931551bSRalph Campbell /* 530f931551bSRalph Campbell * Start of per-unit (or driver, in some cases, but replicated 531f931551bSRalph Campbell * per unit) functions (these get a device *) 532f931551bSRalph Campbell */ 533f931551bSRalph Campbell static ssize_t show_rev(struct device *device, struct device_attribute *attr, 534f931551bSRalph Campbell char *buf) 535f931551bSRalph Campbell { 536f931551bSRalph Campbell struct qib_ibdev *dev = 537f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 538f931551bSRalph Campbell 539f931551bSRalph Campbell return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev); 540f931551bSRalph Campbell } 541f931551bSRalph Campbell 542f931551bSRalph Campbell static ssize_t show_hca(struct device *device, struct device_attribute *attr, 543f931551bSRalph Campbell 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 ret; 549f931551bSRalph Campbell 550f931551bSRalph Campbell if (!dd->boardname) 551f931551bSRalph Campbell ret = -EINVAL; 552f931551bSRalph Campbell else 553f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname); 554f931551bSRalph Campbell return ret; 555f931551bSRalph Campbell } 556f931551bSRalph Campbell 557f931551bSRalph Campbell static ssize_t show_version(struct device *device, 558f931551bSRalph Campbell struct device_attribute *attr, char *buf) 559f931551bSRalph Campbell { 560f931551bSRalph Campbell /* The string printed here is already newline-terminated. */ 561f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%s", (char *)ib_qib_version); 562f931551bSRalph Campbell } 563f931551bSRalph Campbell 564f931551bSRalph Campbell static ssize_t show_boardversion(struct device *device, 565f931551bSRalph Campbell struct device_attribute *attr, char *buf) 566f931551bSRalph Campbell { 567f931551bSRalph Campbell struct qib_ibdev *dev = 568f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 569f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 570f931551bSRalph Campbell 571f931551bSRalph Campbell /* The string printed here is already newline-terminated. */ 572f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion); 573f931551bSRalph Campbell } 574f931551bSRalph Campbell 575f931551bSRalph Campbell 576f931551bSRalph Campbell static ssize_t show_localbus_info(struct device *device, 577f931551bSRalph Campbell struct device_attribute *attr, char *buf) 578f931551bSRalph Campbell { 579f931551bSRalph Campbell struct qib_ibdev *dev = 580f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 581f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 582f931551bSRalph Campbell 583f931551bSRalph Campbell /* The string printed here is already newline-terminated. */ 584f931551bSRalph Campbell return scnprintf(buf, PAGE_SIZE, "%s", dd->lbus_info); 585f931551bSRalph Campbell } 586f931551bSRalph Campbell 587f931551bSRalph Campbell 588f931551bSRalph Campbell static ssize_t show_nctxts(struct device *device, 589f931551bSRalph Campbell struct device_attribute *attr, char *buf) 590f931551bSRalph Campbell { 591f931551bSRalph Campbell struct qib_ibdev *dev = 592f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 593f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 594f931551bSRalph Campbell 595f931551bSRalph Campbell /* Return the number of user ports (contexts) available. */ 5966ceaadeeSMitko Haralanov /* The calculation below deals with a special case where 5976ceaadeeSMitko Haralanov * cfgctxts is set to 1 on a single-port board. */ 5986ceaadeeSMitko Haralanov return scnprintf(buf, PAGE_SIZE, "%u\n", 5996ceaadeeSMitko Haralanov (dd->first_user_ctxt > dd->cfgctxts) ? 0 : 6006ceaadeeSMitko Haralanov (dd->cfgctxts - dd->first_user_ctxt)); 601f931551bSRalph Campbell } 602f931551bSRalph Campbell 6032df4f757SRam Vepa static ssize_t show_nfreectxts(struct device *device, 6042df4f757SRam Vepa struct device_attribute *attr, char *buf) 6052df4f757SRam Vepa { 6062df4f757SRam Vepa struct qib_ibdev *dev = 6072df4f757SRam Vepa container_of(device, struct qib_ibdev, ibdev.dev); 6082df4f757SRam Vepa struct qib_devdata *dd = dd_from_dev(dev); 6092df4f757SRam Vepa 6102df4f757SRam Vepa /* Return the number of free user ports (contexts) available. */ 61153ab1c64SMike Marciniszyn return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts); 6122df4f757SRam Vepa } 6132df4f757SRam Vepa 614f931551bSRalph Campbell static ssize_t show_serial(struct device *device, 615f931551bSRalph Campbell struct device_attribute *attr, char *buf) 616f931551bSRalph Campbell { 617f931551bSRalph Campbell struct qib_ibdev *dev = 618f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 619f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 620f931551bSRalph Campbell 621f931551bSRalph Campbell buf[sizeof dd->serial] = '\0'; 622f931551bSRalph Campbell memcpy(buf, dd->serial, sizeof dd->serial); 623f931551bSRalph Campbell strcat(buf, "\n"); 624f931551bSRalph Campbell return strlen(buf); 625f931551bSRalph Campbell } 626f931551bSRalph Campbell 627f931551bSRalph Campbell static ssize_t store_chip_reset(struct device *device, 628f931551bSRalph Campbell struct device_attribute *attr, const char *buf, 629f931551bSRalph Campbell size_t count) 630f931551bSRalph Campbell { 631f931551bSRalph Campbell struct qib_ibdev *dev = 632f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 633f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 634f931551bSRalph Campbell int ret; 635f931551bSRalph Campbell 636f931551bSRalph Campbell if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) { 637f931551bSRalph Campbell ret = -EINVAL; 638f931551bSRalph Campbell goto bail; 639f931551bSRalph Campbell } 640f931551bSRalph Campbell 641f931551bSRalph Campbell ret = qib_reset_device(dd->unit); 642f931551bSRalph Campbell bail: 643f931551bSRalph Campbell return ret < 0 ? ret : count; 644f931551bSRalph Campbell } 645f931551bSRalph Campbell 646f931551bSRalph Campbell static ssize_t show_logged_errs(struct device *device, 647f931551bSRalph Campbell struct device_attribute *attr, char *buf) 648f931551bSRalph Campbell { 649f931551bSRalph Campbell struct qib_ibdev *dev = 650f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 651f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 652f931551bSRalph Campbell int idx, count; 653f931551bSRalph Campbell 654f931551bSRalph Campbell /* force consistency with actual EEPROM */ 655f931551bSRalph Campbell if (qib_update_eeprom_log(dd) != 0) 656f931551bSRalph Campbell return -ENXIO; 657f931551bSRalph Campbell 658f931551bSRalph Campbell count = 0; 659f931551bSRalph Campbell for (idx = 0; idx < QIB_EEP_LOG_CNT; ++idx) { 660f931551bSRalph Campbell count += scnprintf(buf + count, PAGE_SIZE - count, "%d%c", 661f931551bSRalph Campbell dd->eep_st_errs[idx], 662f931551bSRalph Campbell idx == (QIB_EEP_LOG_CNT - 1) ? '\n' : ' '); 663f931551bSRalph Campbell } 664f931551bSRalph Campbell 665f931551bSRalph Campbell return count; 666f931551bSRalph Campbell } 667f931551bSRalph Campbell 668f931551bSRalph Campbell /* 669f931551bSRalph Campbell * Dump tempsense regs. in decimal, to ease shell-scripts. 670f931551bSRalph Campbell */ 671f931551bSRalph Campbell static ssize_t show_tempsense(struct device *device, 672f931551bSRalph Campbell struct device_attribute *attr, char *buf) 673f931551bSRalph Campbell { 674f931551bSRalph Campbell struct qib_ibdev *dev = 675f931551bSRalph Campbell container_of(device, struct qib_ibdev, ibdev.dev); 676f931551bSRalph Campbell struct qib_devdata *dd = dd_from_dev(dev); 677f931551bSRalph Campbell int ret; 678f931551bSRalph Campbell int idx; 679f931551bSRalph Campbell u8 regvals[8]; 680f931551bSRalph Campbell 681f931551bSRalph Campbell ret = -ENXIO; 682f931551bSRalph Campbell for (idx = 0; idx < 8; ++idx) { 683f931551bSRalph Campbell if (idx == 6) 684f931551bSRalph Campbell continue; 685f931551bSRalph Campbell ret = dd->f_tempsense_rd(dd, idx); 686f931551bSRalph Campbell if (ret < 0) 687f931551bSRalph Campbell break; 688f931551bSRalph Campbell regvals[idx] = ret; 689f931551bSRalph Campbell } 690f931551bSRalph Campbell if (idx == 8) 691f931551bSRalph Campbell ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n", 692f931551bSRalph Campbell *(signed char *)(regvals), 693f931551bSRalph Campbell *(signed char *)(regvals + 1), 694f931551bSRalph Campbell regvals[2], regvals[3], 695f931551bSRalph Campbell *(signed char *)(regvals + 5), 696f931551bSRalph Campbell *(signed char *)(regvals + 7)); 697f931551bSRalph Campbell return ret; 698f931551bSRalph Campbell } 699f931551bSRalph Campbell 700f931551bSRalph Campbell /* 701f931551bSRalph Campbell * end of per-unit (or driver, in some cases, but replicated 702f931551bSRalph Campbell * per unit) functions 703f931551bSRalph Campbell */ 704f931551bSRalph Campbell 705f931551bSRalph Campbell /* start of per-unit file structures and support code */ 706f931551bSRalph Campbell static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); 707f931551bSRalph Campbell static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); 708f931551bSRalph Campbell static DEVICE_ATTR(board_id, S_IRUGO, show_hca, NULL); 709f931551bSRalph Campbell static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); 710f931551bSRalph Campbell static DEVICE_ATTR(nctxts, S_IRUGO, show_nctxts, NULL); 7112df4f757SRam Vepa static DEVICE_ATTR(nfreectxts, S_IRUGO, show_nfreectxts, NULL); 712f931551bSRalph Campbell static DEVICE_ATTR(serial, S_IRUGO, show_serial, NULL); 713f931551bSRalph Campbell static DEVICE_ATTR(boardversion, S_IRUGO, show_boardversion, NULL); 714f931551bSRalph Campbell static DEVICE_ATTR(logged_errors, S_IRUGO, show_logged_errs, NULL); 715f931551bSRalph Campbell static DEVICE_ATTR(tempsense, S_IRUGO, show_tempsense, NULL); 716f931551bSRalph Campbell static DEVICE_ATTR(localbus_info, S_IRUGO, show_localbus_info, NULL); 717f931551bSRalph Campbell static DEVICE_ATTR(chip_reset, S_IWUSR, NULL, store_chip_reset); 718f931551bSRalph Campbell 719f931551bSRalph Campbell static struct device_attribute *qib_attributes[] = { 720f931551bSRalph Campbell &dev_attr_hw_rev, 721f931551bSRalph Campbell &dev_attr_hca_type, 722f931551bSRalph Campbell &dev_attr_board_id, 723f931551bSRalph Campbell &dev_attr_version, 724f931551bSRalph Campbell &dev_attr_nctxts, 7252df4f757SRam Vepa &dev_attr_nfreectxts, 726f931551bSRalph Campbell &dev_attr_serial, 727f931551bSRalph Campbell &dev_attr_boardversion, 728f931551bSRalph Campbell &dev_attr_logged_errors, 729f931551bSRalph Campbell &dev_attr_tempsense, 730f931551bSRalph Campbell &dev_attr_localbus_info, 731f931551bSRalph Campbell &dev_attr_chip_reset, 732f931551bSRalph Campbell }; 733f931551bSRalph Campbell 734f931551bSRalph Campbell int qib_create_port_files(struct ib_device *ibdev, u8 port_num, 735f931551bSRalph Campbell struct kobject *kobj) 736f931551bSRalph Campbell { 737f931551bSRalph Campbell struct qib_pportdata *ppd; 738f931551bSRalph Campbell struct qib_devdata *dd = dd_from_ibdev(ibdev); 739f931551bSRalph Campbell int ret; 740f931551bSRalph Campbell 741f931551bSRalph Campbell if (!port_num || port_num > dd->num_pports) { 742f931551bSRalph Campbell qib_dev_err(dd, "Skipping infiniband class with " 743f931551bSRalph Campbell "invalid port %u\n", port_num); 744f931551bSRalph Campbell ret = -ENODEV; 745f931551bSRalph Campbell goto bail; 746f931551bSRalph Campbell } 747f931551bSRalph Campbell ppd = &dd->pport[port_num - 1]; 748f931551bSRalph Campbell 749f931551bSRalph Campbell ret = kobject_init_and_add(&ppd->pport_kobj, &qib_port_ktype, kobj, 750f931551bSRalph Campbell "linkcontrol"); 751f931551bSRalph Campbell if (ret) { 752f931551bSRalph Campbell qib_dev_err(dd, "Skipping linkcontrol sysfs info, " 753f931551bSRalph Campbell "(err %d) port %u\n", ret, port_num); 754f931551bSRalph Campbell goto bail; 755f931551bSRalph Campbell } 756f931551bSRalph Campbell kobject_uevent(&ppd->pport_kobj, KOBJ_ADD); 757f931551bSRalph Campbell 758f931551bSRalph Campbell ret = kobject_init_and_add(&ppd->sl2vl_kobj, &qib_sl2vl_ktype, kobj, 759f931551bSRalph Campbell "sl2vl"); 760f931551bSRalph Campbell if (ret) { 761f931551bSRalph Campbell qib_dev_err(dd, "Skipping sl2vl sysfs info, " 762f931551bSRalph Campbell "(err %d) port %u\n", ret, port_num); 763*36a8f01cSMike Marciniszyn goto bail_link; 764f931551bSRalph Campbell } 765f931551bSRalph Campbell kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); 766f931551bSRalph Campbell 767f931551bSRalph Campbell ret = kobject_init_and_add(&ppd->diagc_kobj, &qib_diagc_ktype, kobj, 768f931551bSRalph Campbell "diag_counters"); 769f931551bSRalph Campbell if (ret) { 770f931551bSRalph Campbell qib_dev_err(dd, "Skipping diag_counters sysfs info, " 771f931551bSRalph Campbell "(err %d) port %u\n", ret, port_num); 772*36a8f01cSMike Marciniszyn goto bail_sl; 773f931551bSRalph Campbell } 774f931551bSRalph Campbell kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); 775f931551bSRalph Campbell 776*36a8f01cSMike Marciniszyn if (!qib_cc_table_size || !ppd->congestion_entries_shadow) 777f931551bSRalph Campbell return 0; 778f931551bSRalph Campbell 779*36a8f01cSMike Marciniszyn ret = kobject_init_and_add(&ppd->pport_cc_kobj, &qib_port_cc_ktype, 780*36a8f01cSMike Marciniszyn kobj, "CCMgtA"); 781*36a8f01cSMike Marciniszyn if (ret) { 782*36a8f01cSMike Marciniszyn qib_dev_err(dd, 783*36a8f01cSMike Marciniszyn "Skipping Congestion Control sysfs info, (err %d) port %u\n", 784*36a8f01cSMike Marciniszyn ret, port_num); 785*36a8f01cSMike Marciniszyn goto bail_diagc; 786*36a8f01cSMike Marciniszyn } 787*36a8f01cSMike Marciniszyn 788*36a8f01cSMike Marciniszyn kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD); 789*36a8f01cSMike Marciniszyn 790*36a8f01cSMike Marciniszyn ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, 791*36a8f01cSMike Marciniszyn &cc_setting_bin_attr); 792*36a8f01cSMike Marciniszyn if (ret) { 793*36a8f01cSMike Marciniszyn qib_dev_err(dd, 794*36a8f01cSMike Marciniszyn "Skipping Congestion Control setting sysfs info, (err %d) port %u\n", 795*36a8f01cSMike Marciniszyn ret, port_num); 796*36a8f01cSMike Marciniszyn goto bail_cc; 797*36a8f01cSMike Marciniszyn } 798*36a8f01cSMike Marciniszyn 799*36a8f01cSMike Marciniszyn ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, 800*36a8f01cSMike Marciniszyn &cc_table_bin_attr); 801*36a8f01cSMike Marciniszyn if (ret) { 802*36a8f01cSMike Marciniszyn qib_dev_err(dd, 803*36a8f01cSMike Marciniszyn "Skipping Congestion Control table sysfs info, (err %d) port %u\n", 804*36a8f01cSMike Marciniszyn ret, port_num); 805*36a8f01cSMike Marciniszyn goto bail_cc_entry_bin; 806*36a8f01cSMike Marciniszyn } 807*36a8f01cSMike Marciniszyn 808*36a8f01cSMike Marciniszyn qib_devinfo(dd->pcidev, 809*36a8f01cSMike Marciniszyn "IB%u: Congestion Control Agent enabled for port %d\n", 810*36a8f01cSMike Marciniszyn dd->unit, port_num); 811*36a8f01cSMike Marciniszyn 812*36a8f01cSMike Marciniszyn return 0; 813*36a8f01cSMike Marciniszyn 814*36a8f01cSMike Marciniszyn bail_cc_entry_bin: 815*36a8f01cSMike Marciniszyn sysfs_remove_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr); 816*36a8f01cSMike Marciniszyn bail_cc: 817*36a8f01cSMike Marciniszyn kobject_put(&ppd->pport_cc_kobj); 818f931551bSRalph Campbell bail_diagc: 819*36a8f01cSMike Marciniszyn kobject_put(&ppd->diagc_kobj); 820f931551bSRalph Campbell bail_sl: 821*36a8f01cSMike Marciniszyn kobject_put(&ppd->sl2vl_kobj); 822*36a8f01cSMike Marciniszyn bail_link: 823f931551bSRalph Campbell kobject_put(&ppd->pport_kobj); 824f931551bSRalph Campbell bail: 825f931551bSRalph Campbell return ret; 826f931551bSRalph Campbell } 827f931551bSRalph Campbell 828f931551bSRalph Campbell /* 829f931551bSRalph Campbell * Register and create our files in /sys/class/infiniband. 830f931551bSRalph Campbell */ 831f931551bSRalph Campbell int qib_verbs_register_sysfs(struct qib_devdata *dd) 832f931551bSRalph Campbell { 833f931551bSRalph Campbell struct ib_device *dev = &dd->verbs_dev.ibdev; 834f931551bSRalph Campbell int i, ret; 835f931551bSRalph Campbell 836f931551bSRalph Campbell for (i = 0; i < ARRAY_SIZE(qib_attributes); ++i) { 837f931551bSRalph Campbell ret = device_create_file(&dev->dev, qib_attributes[i]); 838f931551bSRalph Campbell if (ret) 839f931551bSRalph Campbell return ret; 840f931551bSRalph Campbell } 841f931551bSRalph Campbell 842f931551bSRalph Campbell return 0; 843f931551bSRalph Campbell } 844f931551bSRalph Campbell 845f931551bSRalph Campbell /* 846f931551bSRalph Campbell * Unregister and remove our files in /sys/class/infiniband. 847f931551bSRalph Campbell */ 848f931551bSRalph Campbell void qib_verbs_unregister_sysfs(struct qib_devdata *dd) 849f931551bSRalph Campbell { 850f931551bSRalph Campbell struct qib_pportdata *ppd; 851f931551bSRalph Campbell int i; 852f931551bSRalph Campbell 853f931551bSRalph Campbell for (i = 0; i < dd->num_pports; i++) { 854f931551bSRalph Campbell ppd = &dd->pport[i]; 855*36a8f01cSMike Marciniszyn if (qib_cc_table_size && 856*36a8f01cSMike Marciniszyn ppd->congestion_entries_shadow) { 857*36a8f01cSMike Marciniszyn sysfs_remove_bin_file(&ppd->pport_cc_kobj, 858*36a8f01cSMike Marciniszyn &cc_setting_bin_attr); 859*36a8f01cSMike Marciniszyn sysfs_remove_bin_file(&ppd->pport_cc_kobj, 860*36a8f01cSMike Marciniszyn &cc_table_bin_attr); 861*36a8f01cSMike Marciniszyn kobject_put(&ppd->pport_cc_kobj); 862*36a8f01cSMike Marciniszyn } 863f931551bSRalph Campbell kobject_put(&ppd->sl2vl_kobj); 864*36a8f01cSMike Marciniszyn kobject_put(&ppd->pport_kobj); 865f931551bSRalph Campbell } 866f931551bSRalph Campbell } 867