18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2012 Intel Corporation. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2006 PathScale, Inc. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 78c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 138c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 178c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 188c2ecf20Sopenharmony_ci * disclaimer. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 218c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 228c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 238c2ecf20Sopenharmony_ci * provided with the distribution. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 328c2ecf20Sopenharmony_ci * SOFTWARE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci#include <linux/ctype.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "qib.h" 378c2ecf20Sopenharmony_ci#include "qib_mad.h" 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci/* start of per-port functions */ 408c2ecf20Sopenharmony_ci/* 418c2ecf20Sopenharmony_ci * Get/Set heartbeat enable. OR of 1=enabled, 2=auto 428c2ecf20Sopenharmony_ci */ 438c2ecf20Sopenharmony_cistatic ssize_t show_hrtbt_enb(struct qib_pportdata *ppd, char *buf) 448c2ecf20Sopenharmony_ci{ 458c2ecf20Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 468c2ecf20Sopenharmony_ci int ret; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci ret = dd->f_get_ib_cfg(ppd, QIB_IB_CFG_HRTBT); 498c2ecf20Sopenharmony_ci ret = scnprintf(buf, PAGE_SIZE, "%d\n", ret); 508c2ecf20Sopenharmony_ci return ret; 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic ssize_t store_hrtbt_enb(struct qib_pportdata *ppd, const char *buf, 548c2ecf20Sopenharmony_ci size_t count) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 578c2ecf20Sopenharmony_ci int ret; 588c2ecf20Sopenharmony_ci u16 val; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci ret = kstrtou16(buf, 0, &val); 618c2ecf20Sopenharmony_ci if (ret) { 628c2ecf20Sopenharmony_ci qib_dev_err(dd, "attempt to set invalid Heartbeat enable\n"); 638c2ecf20Sopenharmony_ci return ret; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci /* 678c2ecf20Sopenharmony_ci * Set the "intentional" heartbeat enable per either of 688c2ecf20Sopenharmony_ci * "Enable" and "Auto", as these are normally set together. 698c2ecf20Sopenharmony_ci * This bit is consulted when leaving loopback mode, 708c2ecf20Sopenharmony_ci * because entering loopback mode overrides it and automatically 718c2ecf20Sopenharmony_ci * disables heartbeat. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci ret = dd->f_set_ib_cfg(ppd, QIB_IB_CFG_HRTBT, val); 748c2ecf20Sopenharmony_ci return ret < 0 ? ret : count; 758c2ecf20Sopenharmony_ci} 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_cistatic ssize_t store_loopback(struct qib_pportdata *ppd, const char *buf, 788c2ecf20Sopenharmony_ci size_t count) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 818c2ecf20Sopenharmony_ci int ret = count, r; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci r = dd->f_set_ib_loopback(ppd, buf); 848c2ecf20Sopenharmony_ci if (r < 0) 858c2ecf20Sopenharmony_ci ret = r; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci return ret; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_cistatic ssize_t store_led_override(struct qib_pportdata *ppd, const char *buf, 918c2ecf20Sopenharmony_ci size_t count) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci struct qib_devdata *dd = ppd->dd; 948c2ecf20Sopenharmony_ci int ret; 958c2ecf20Sopenharmony_ci u16 val; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci ret = kstrtou16(buf, 0, &val); 988c2ecf20Sopenharmony_ci if (ret) { 998c2ecf20Sopenharmony_ci qib_dev_err(dd, "attempt to set invalid LED override\n"); 1008c2ecf20Sopenharmony_ci return ret; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci qib_set_led_override(ppd, val); 1048c2ecf20Sopenharmony_ci return count; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic ssize_t show_status(struct qib_pportdata *ppd, char *buf) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci ssize_t ret; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (!ppd->statusp) 1128c2ecf20Sopenharmony_ci ret = -EINVAL; 1138c2ecf20Sopenharmony_ci else 1148c2ecf20Sopenharmony_ci ret = scnprintf(buf, PAGE_SIZE, "0x%llx\n", 1158c2ecf20Sopenharmony_ci (unsigned long long) *(ppd->statusp)); 1168c2ecf20Sopenharmony_ci return ret; 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci/* 1208c2ecf20Sopenharmony_ci * For userland compatibility, these offsets must remain fixed. 1218c2ecf20Sopenharmony_ci * They are strings for QIB_STATUS_* 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cistatic const char * const qib_status_str[] = { 1248c2ecf20Sopenharmony_ci "Initted", 1258c2ecf20Sopenharmony_ci "", 1268c2ecf20Sopenharmony_ci "", 1278c2ecf20Sopenharmony_ci "", 1288c2ecf20Sopenharmony_ci "", 1298c2ecf20Sopenharmony_ci "Present", 1308c2ecf20Sopenharmony_ci "IB_link_up", 1318c2ecf20Sopenharmony_ci "IB_configured", 1328c2ecf20Sopenharmony_ci "", 1338c2ecf20Sopenharmony_ci "Fatal_Hardware_Error", 1348c2ecf20Sopenharmony_ci NULL, 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic ssize_t show_status_str(struct qib_pportdata *ppd, char *buf) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci int i, any; 1408c2ecf20Sopenharmony_ci u64 s; 1418c2ecf20Sopenharmony_ci ssize_t ret; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (!ppd->statusp) { 1448c2ecf20Sopenharmony_ci ret = -EINVAL; 1458c2ecf20Sopenharmony_ci goto bail; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci s = *(ppd->statusp); 1498c2ecf20Sopenharmony_ci *buf = '\0'; 1508c2ecf20Sopenharmony_ci for (any = i = 0; s && qib_status_str[i]; i++) { 1518c2ecf20Sopenharmony_ci if (s & 1) { 1528c2ecf20Sopenharmony_ci /* if overflow */ 1538c2ecf20Sopenharmony_ci if (any && strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) 1548c2ecf20Sopenharmony_ci break; 1558c2ecf20Sopenharmony_ci if (strlcat(buf, qib_status_str[i], PAGE_SIZE) >= 1568c2ecf20Sopenharmony_ci PAGE_SIZE) 1578c2ecf20Sopenharmony_ci break; 1588c2ecf20Sopenharmony_ci any = 1; 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci s >>= 1; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci if (any) 1638c2ecf20Sopenharmony_ci strlcat(buf, "\n", PAGE_SIZE); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci ret = strlen(buf); 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cibail: 1688c2ecf20Sopenharmony_ci return ret; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/* end of per-port functions */ 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* 1748c2ecf20Sopenharmony_ci * Start of per-port file structures and support code 1758c2ecf20Sopenharmony_ci * Because we are fitting into other infrastructure, we have to supply the 1768c2ecf20Sopenharmony_ci * full set of kobject/sysfs_ops structures and routines. 1778c2ecf20Sopenharmony_ci */ 1788c2ecf20Sopenharmony_ci#define QIB_PORT_ATTR(name, mode, show, store) \ 1798c2ecf20Sopenharmony_ci static struct qib_port_attr qib_port_attr_##name = \ 1808c2ecf20Sopenharmony_ci __ATTR(name, mode, show, store) 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistruct qib_port_attr { 1838c2ecf20Sopenharmony_ci struct attribute attr; 1848c2ecf20Sopenharmony_ci ssize_t (*show)(struct qib_pportdata *, char *); 1858c2ecf20Sopenharmony_ci ssize_t (*store)(struct qib_pportdata *, const char *, size_t); 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ciQIB_PORT_ATTR(loopback, S_IWUSR, NULL, store_loopback); 1898c2ecf20Sopenharmony_ciQIB_PORT_ATTR(led_override, S_IWUSR, NULL, store_led_override); 1908c2ecf20Sopenharmony_ciQIB_PORT_ATTR(hrtbt_enable, S_IWUSR | S_IRUGO, show_hrtbt_enb, 1918c2ecf20Sopenharmony_ci store_hrtbt_enb); 1928c2ecf20Sopenharmony_ciQIB_PORT_ATTR(status, S_IRUGO, show_status, NULL); 1938c2ecf20Sopenharmony_ciQIB_PORT_ATTR(status_str, S_IRUGO, show_status_str, NULL); 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_cistatic struct attribute *port_default_attributes[] = { 1968c2ecf20Sopenharmony_ci &qib_port_attr_loopback.attr, 1978c2ecf20Sopenharmony_ci &qib_port_attr_led_override.attr, 1988c2ecf20Sopenharmony_ci &qib_port_attr_hrtbt_enable.attr, 1998c2ecf20Sopenharmony_ci &qib_port_attr_status.attr, 2008c2ecf20Sopenharmony_ci &qib_port_attr_status_str.attr, 2018c2ecf20Sopenharmony_ci NULL 2028c2ecf20Sopenharmony_ci}; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci/* 2058c2ecf20Sopenharmony_ci * Start of per-port congestion control structures and support code 2068c2ecf20Sopenharmony_ci */ 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci/* 2098c2ecf20Sopenharmony_ci * Congestion control table size followed by table entries 2108c2ecf20Sopenharmony_ci */ 2118c2ecf20Sopenharmony_cistatic ssize_t read_cc_table_bin(struct file *filp, struct kobject *kobj, 2128c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 2138c2ecf20Sopenharmony_ci char *buf, loff_t pos, size_t count) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci int ret; 2168c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 2178c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, pport_cc_kobj); 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci if (!qib_cc_table_size || !ppd->ccti_entries_shadow) 2208c2ecf20Sopenharmony_ci return -EINVAL; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow) 2238c2ecf20Sopenharmony_ci + sizeof(__be16); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (pos > ret) 2268c2ecf20Sopenharmony_ci return -EINVAL; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (count > ret - pos) 2298c2ecf20Sopenharmony_ci count = ret - pos; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (!count) 2328c2ecf20Sopenharmony_ci return count; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci spin_lock(&ppd->cc_shadow_lock); 2358c2ecf20Sopenharmony_ci memcpy(buf, ppd->ccti_entries_shadow, count); 2368c2ecf20Sopenharmony_ci spin_unlock(&ppd->cc_shadow_lock); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci return count; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic void qib_port_release(struct kobject *kobj) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci /* nothing to do since memory is freed by qib_free_devdata() */ 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic struct kobj_type qib_port_cc_ktype = { 2478c2ecf20Sopenharmony_ci .release = qib_port_release, 2488c2ecf20Sopenharmony_ci}; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic const struct bin_attribute cc_table_bin_attr = { 2518c2ecf20Sopenharmony_ci .attr = {.name = "cc_table_bin", .mode = 0444}, 2528c2ecf20Sopenharmony_ci .read = read_cc_table_bin, 2538c2ecf20Sopenharmony_ci .size = PAGE_SIZE, 2548c2ecf20Sopenharmony_ci}; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/* 2578c2ecf20Sopenharmony_ci * Congestion settings: port control, control map and an array of 16 2588c2ecf20Sopenharmony_ci * entries for the congestion entries - increase, timer, event log 2598c2ecf20Sopenharmony_ci * trigger threshold and the minimum injection rate delay. 2608c2ecf20Sopenharmony_ci */ 2618c2ecf20Sopenharmony_cistatic ssize_t read_cc_setting_bin(struct file *filp, struct kobject *kobj, 2628c2ecf20Sopenharmony_ci struct bin_attribute *bin_attr, 2638c2ecf20Sopenharmony_ci char *buf, loff_t pos, size_t count) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci int ret; 2668c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 2678c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, pport_cc_kobj); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci if (!qib_cc_table_size || !ppd->congestion_entries_shadow) 2708c2ecf20Sopenharmony_ci return -EINVAL; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci ret = sizeof(struct ib_cc_congestion_setting_attr_shadow); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci if (pos > ret) 2758c2ecf20Sopenharmony_ci return -EINVAL; 2768c2ecf20Sopenharmony_ci if (count > ret - pos) 2778c2ecf20Sopenharmony_ci count = ret - pos; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (!count) 2808c2ecf20Sopenharmony_ci return count; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci spin_lock(&ppd->cc_shadow_lock); 2838c2ecf20Sopenharmony_ci memcpy(buf, ppd->congestion_entries_shadow, count); 2848c2ecf20Sopenharmony_ci spin_unlock(&ppd->cc_shadow_lock); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return count; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic const struct bin_attribute cc_setting_bin_attr = { 2908c2ecf20Sopenharmony_ci .attr = {.name = "cc_settings_bin", .mode = 0444}, 2918c2ecf20Sopenharmony_ci .read = read_cc_setting_bin, 2928c2ecf20Sopenharmony_ci .size = PAGE_SIZE, 2938c2ecf20Sopenharmony_ci}; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_cistatic ssize_t qib_portattr_show(struct kobject *kobj, 2978c2ecf20Sopenharmony_ci struct attribute *attr, char *buf) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct qib_port_attr *pattr = 3008c2ecf20Sopenharmony_ci container_of(attr, struct qib_port_attr, attr); 3018c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 3028c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, pport_kobj); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (!pattr->show) 3058c2ecf20Sopenharmony_ci return -EIO; 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci return pattr->show(ppd, buf); 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_cistatic ssize_t qib_portattr_store(struct kobject *kobj, 3118c2ecf20Sopenharmony_ci struct attribute *attr, const char *buf, size_t len) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci struct qib_port_attr *pattr = 3148c2ecf20Sopenharmony_ci container_of(attr, struct qib_port_attr, attr); 3158c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 3168c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, pport_kobj); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci if (!pattr->store) 3198c2ecf20Sopenharmony_ci return -EIO; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return pattr->store(ppd, buf, len); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic const struct sysfs_ops qib_port_ops = { 3268c2ecf20Sopenharmony_ci .show = qib_portattr_show, 3278c2ecf20Sopenharmony_ci .store = qib_portattr_store, 3288c2ecf20Sopenharmony_ci}; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic struct kobj_type qib_port_ktype = { 3318c2ecf20Sopenharmony_ci .release = qib_port_release, 3328c2ecf20Sopenharmony_ci .sysfs_ops = &qib_port_ops, 3338c2ecf20Sopenharmony_ci .default_attrs = port_default_attributes 3348c2ecf20Sopenharmony_ci}; 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci/* Start sl2vl */ 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci#define QIB_SL2VL_ATTR(N) \ 3398c2ecf20Sopenharmony_ci static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \ 3408c2ecf20Sopenharmony_ci .attr = { .name = __stringify(N), .mode = 0444 }, \ 3418c2ecf20Sopenharmony_ci .sl = N \ 3428c2ecf20Sopenharmony_ci } 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_cistruct qib_sl2vl_attr { 3458c2ecf20Sopenharmony_ci struct attribute attr; 3468c2ecf20Sopenharmony_ci int sl; 3478c2ecf20Sopenharmony_ci}; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(0); 3508c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(1); 3518c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(2); 3528c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(3); 3538c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(4); 3548c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(5); 3558c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(6); 3568c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(7); 3578c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(8); 3588c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(9); 3598c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(10); 3608c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(11); 3618c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(12); 3628c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(13); 3638c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(14); 3648c2ecf20Sopenharmony_ciQIB_SL2VL_ATTR(15); 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic struct attribute *sl2vl_default_attributes[] = { 3678c2ecf20Sopenharmony_ci &qib_sl2vl_attr_0.attr, 3688c2ecf20Sopenharmony_ci &qib_sl2vl_attr_1.attr, 3698c2ecf20Sopenharmony_ci &qib_sl2vl_attr_2.attr, 3708c2ecf20Sopenharmony_ci &qib_sl2vl_attr_3.attr, 3718c2ecf20Sopenharmony_ci &qib_sl2vl_attr_4.attr, 3728c2ecf20Sopenharmony_ci &qib_sl2vl_attr_5.attr, 3738c2ecf20Sopenharmony_ci &qib_sl2vl_attr_6.attr, 3748c2ecf20Sopenharmony_ci &qib_sl2vl_attr_7.attr, 3758c2ecf20Sopenharmony_ci &qib_sl2vl_attr_8.attr, 3768c2ecf20Sopenharmony_ci &qib_sl2vl_attr_9.attr, 3778c2ecf20Sopenharmony_ci &qib_sl2vl_attr_10.attr, 3788c2ecf20Sopenharmony_ci &qib_sl2vl_attr_11.attr, 3798c2ecf20Sopenharmony_ci &qib_sl2vl_attr_12.attr, 3808c2ecf20Sopenharmony_ci &qib_sl2vl_attr_13.attr, 3818c2ecf20Sopenharmony_ci &qib_sl2vl_attr_14.attr, 3828c2ecf20Sopenharmony_ci &qib_sl2vl_attr_15.attr, 3838c2ecf20Sopenharmony_ci NULL 3848c2ecf20Sopenharmony_ci}; 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic ssize_t sl2vl_attr_show(struct kobject *kobj, struct attribute *attr, 3878c2ecf20Sopenharmony_ci char *buf) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct qib_sl2vl_attr *sattr = 3908c2ecf20Sopenharmony_ci container_of(attr, struct qib_sl2vl_attr, attr); 3918c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 3928c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, sl2vl_kobj); 3938c2ecf20Sopenharmony_ci struct qib_ibport *qibp = &ppd->ibport_data; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", qibp->sl_to_vl[sattr->sl]); 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic const struct sysfs_ops qib_sl2vl_ops = { 3998c2ecf20Sopenharmony_ci .show = sl2vl_attr_show, 4008c2ecf20Sopenharmony_ci}; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic struct kobj_type qib_sl2vl_ktype = { 4038c2ecf20Sopenharmony_ci .release = qib_port_release, 4048c2ecf20Sopenharmony_ci .sysfs_ops = &qib_sl2vl_ops, 4058c2ecf20Sopenharmony_ci .default_attrs = sl2vl_default_attributes 4068c2ecf20Sopenharmony_ci}; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci/* End sl2vl */ 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci/* Start diag_counters */ 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci#define QIB_DIAGC_ATTR(N) \ 4138c2ecf20Sopenharmony_ci static struct qib_diagc_attr qib_diagc_attr_##N = { \ 4148c2ecf20Sopenharmony_ci .attr = { .name = __stringify(N), .mode = 0664 }, \ 4158c2ecf20Sopenharmony_ci .counter = offsetof(struct qib_ibport, rvp.n_##N) \ 4168c2ecf20Sopenharmony_ci } 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci#define QIB_DIAGC_ATTR_PER_CPU(N) \ 4198c2ecf20Sopenharmony_ci static struct qib_diagc_attr qib_diagc_attr_##N = { \ 4208c2ecf20Sopenharmony_ci .attr = { .name = __stringify(N), .mode = 0664 }, \ 4218c2ecf20Sopenharmony_ci .counter = offsetof(struct qib_ibport, rvp.z_##N) \ 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cistruct qib_diagc_attr { 4258c2ecf20Sopenharmony_ci struct attribute attr; 4268c2ecf20Sopenharmony_ci size_t counter; 4278c2ecf20Sopenharmony_ci}; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR_PER_CPU(rc_acks); 4308c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR_PER_CPU(rc_qacks); 4318c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR_PER_CPU(rc_delayed_comp); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rc_resends); 4348c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(seq_naks); 4358c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rdma_seq); 4368c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rnr_naks); 4378c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(other_naks); 4388c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rc_timeouts); 4398c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(loop_pkts); 4408c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(pkt_drops); 4418c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(dmawait); 4428c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(unaligned); 4438c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rc_dupreq); 4448c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rc_seqnak); 4458c2ecf20Sopenharmony_ciQIB_DIAGC_ATTR(rc_crwaits); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic struct attribute *diagc_default_attributes[] = { 4488c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_resends.attr, 4498c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_acks.attr, 4508c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_qacks.attr, 4518c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_delayed_comp.attr, 4528c2ecf20Sopenharmony_ci &qib_diagc_attr_seq_naks.attr, 4538c2ecf20Sopenharmony_ci &qib_diagc_attr_rdma_seq.attr, 4548c2ecf20Sopenharmony_ci &qib_diagc_attr_rnr_naks.attr, 4558c2ecf20Sopenharmony_ci &qib_diagc_attr_other_naks.attr, 4568c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_timeouts.attr, 4578c2ecf20Sopenharmony_ci &qib_diagc_attr_loop_pkts.attr, 4588c2ecf20Sopenharmony_ci &qib_diagc_attr_pkt_drops.attr, 4598c2ecf20Sopenharmony_ci &qib_diagc_attr_dmawait.attr, 4608c2ecf20Sopenharmony_ci &qib_diagc_attr_unaligned.attr, 4618c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_dupreq.attr, 4628c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_seqnak.attr, 4638c2ecf20Sopenharmony_ci &qib_diagc_attr_rc_crwaits.attr, 4648c2ecf20Sopenharmony_ci NULL 4658c2ecf20Sopenharmony_ci}; 4668c2ecf20Sopenharmony_ci 4678c2ecf20Sopenharmony_cistatic u64 get_all_cpu_total(u64 __percpu *cntr) 4688c2ecf20Sopenharmony_ci{ 4698c2ecf20Sopenharmony_ci int cpu; 4708c2ecf20Sopenharmony_ci u64 counter = 0; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci for_each_possible_cpu(cpu) 4738c2ecf20Sopenharmony_ci counter += *per_cpu_ptr(cntr, cpu); 4748c2ecf20Sopenharmony_ci return counter; 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci#define def_write_per_cpu(cntr) \ 4788c2ecf20Sopenharmony_cistatic void write_per_cpu_##cntr(struct qib_pportdata *ppd, u32 data) \ 4798c2ecf20Sopenharmony_ci{ \ 4808c2ecf20Sopenharmony_ci struct qib_devdata *dd = ppd->dd; \ 4818c2ecf20Sopenharmony_ci struct qib_ibport *qibp = &ppd->ibport_data; \ 4828c2ecf20Sopenharmony_ci /* A write can only zero the counter */ \ 4838c2ecf20Sopenharmony_ci if (data == 0) \ 4848c2ecf20Sopenharmony_ci qibp->rvp.z_##cntr = get_all_cpu_total(qibp->rvp.cntr); \ 4858c2ecf20Sopenharmony_ci else \ 4868c2ecf20Sopenharmony_ci qib_dev_err(dd, "Per CPU cntrs can only be zeroed"); \ 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_cidef_write_per_cpu(rc_acks) 4908c2ecf20Sopenharmony_cidef_write_per_cpu(rc_qacks) 4918c2ecf20Sopenharmony_cidef_write_per_cpu(rc_delayed_comp) 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci#define READ_PER_CPU_CNTR(cntr) (get_all_cpu_total(qibp->rvp.cntr) - \ 4948c2ecf20Sopenharmony_ci qibp->rvp.z_##cntr) 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic ssize_t diagc_attr_show(struct kobject *kobj, struct attribute *attr, 4978c2ecf20Sopenharmony_ci char *buf) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci struct qib_diagc_attr *dattr = 5008c2ecf20Sopenharmony_ci container_of(attr, struct qib_diagc_attr, attr); 5018c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 5028c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, diagc_kobj); 5038c2ecf20Sopenharmony_ci struct qib_ibport *qibp = &ppd->ibport_data; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (!strncmp(dattr->attr.name, "rc_acks", 7)) 5068c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", READ_PER_CPU_CNTR(rc_acks)); 5078c2ecf20Sopenharmony_ci else if (!strncmp(dattr->attr.name, "rc_qacks", 8)) 5088c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", READ_PER_CPU_CNTR(rc_qacks)); 5098c2ecf20Sopenharmony_ci else if (!strncmp(dattr->attr.name, "rc_delayed_comp", 15)) 5108c2ecf20Sopenharmony_ci return sprintf(buf, "%llu\n", 5118c2ecf20Sopenharmony_ci READ_PER_CPU_CNTR(rc_delayed_comp)); 5128c2ecf20Sopenharmony_ci else 5138c2ecf20Sopenharmony_ci return sprintf(buf, "%u\n", 5148c2ecf20Sopenharmony_ci *(u32 *)((char *)qibp + dattr->counter)); 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_cistatic ssize_t diagc_attr_store(struct kobject *kobj, struct attribute *attr, 5188c2ecf20Sopenharmony_ci const char *buf, size_t size) 5198c2ecf20Sopenharmony_ci{ 5208c2ecf20Sopenharmony_ci struct qib_diagc_attr *dattr = 5218c2ecf20Sopenharmony_ci container_of(attr, struct qib_diagc_attr, attr); 5228c2ecf20Sopenharmony_ci struct qib_pportdata *ppd = 5238c2ecf20Sopenharmony_ci container_of(kobj, struct qib_pportdata, diagc_kobj); 5248c2ecf20Sopenharmony_ci struct qib_ibport *qibp = &ppd->ibport_data; 5258c2ecf20Sopenharmony_ci u32 val; 5268c2ecf20Sopenharmony_ci int ret; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci ret = kstrtou32(buf, 0, &val); 5298c2ecf20Sopenharmony_ci if (ret) 5308c2ecf20Sopenharmony_ci return ret; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci if (!strncmp(dattr->attr.name, "rc_acks", 7)) 5338c2ecf20Sopenharmony_ci write_per_cpu_rc_acks(ppd, val); 5348c2ecf20Sopenharmony_ci else if (!strncmp(dattr->attr.name, "rc_qacks", 8)) 5358c2ecf20Sopenharmony_ci write_per_cpu_rc_qacks(ppd, val); 5368c2ecf20Sopenharmony_ci else if (!strncmp(dattr->attr.name, "rc_delayed_comp", 15)) 5378c2ecf20Sopenharmony_ci write_per_cpu_rc_delayed_comp(ppd, val); 5388c2ecf20Sopenharmony_ci else 5398c2ecf20Sopenharmony_ci *(u32 *)((char *)qibp + dattr->counter) = val; 5408c2ecf20Sopenharmony_ci return size; 5418c2ecf20Sopenharmony_ci} 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_cistatic const struct sysfs_ops qib_diagc_ops = { 5448c2ecf20Sopenharmony_ci .show = diagc_attr_show, 5458c2ecf20Sopenharmony_ci .store = diagc_attr_store, 5468c2ecf20Sopenharmony_ci}; 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_cistatic struct kobj_type qib_diagc_ktype = { 5498c2ecf20Sopenharmony_ci .release = qib_port_release, 5508c2ecf20Sopenharmony_ci .sysfs_ops = &qib_diagc_ops, 5518c2ecf20Sopenharmony_ci .default_attrs = diagc_default_attributes 5528c2ecf20Sopenharmony_ci}; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci/* End diag_counters */ 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci/* end of per-port file structures and support code */ 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci/* 5598c2ecf20Sopenharmony_ci * Start of per-unit (or driver, in some cases, but replicated 5608c2ecf20Sopenharmony_ci * per unit) functions (these get a device *) 5618c2ecf20Sopenharmony_ci */ 5628c2ecf20Sopenharmony_cistatic ssize_t hw_rev_show(struct device *device, struct device_attribute *attr, 5638c2ecf20Sopenharmony_ci char *buf) 5648c2ecf20Sopenharmony_ci{ 5658c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 5668c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci return sprintf(buf, "%x\n", dd_from_dev(dev)->minrev); 5698c2ecf20Sopenharmony_ci} 5708c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(hw_rev); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic ssize_t hca_type_show(struct device *device, 5738c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 5748c2ecf20Sopenharmony_ci{ 5758c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 5768c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 5778c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 5788c2ecf20Sopenharmony_ci int ret; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci if (!dd->boardname) 5818c2ecf20Sopenharmony_ci ret = -EINVAL; 5828c2ecf20Sopenharmony_ci else 5838c2ecf20Sopenharmony_ci ret = scnprintf(buf, PAGE_SIZE, "%s\n", dd->boardname); 5848c2ecf20Sopenharmony_ci return ret; 5858c2ecf20Sopenharmony_ci} 5868c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(hca_type); 5878c2ecf20Sopenharmony_cistatic DEVICE_ATTR(board_id, 0444, hca_type_show, NULL); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_cistatic ssize_t version_show(struct device *device, 5908c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 5918c2ecf20Sopenharmony_ci{ 5928c2ecf20Sopenharmony_ci /* The string printed here is already newline-terminated. */ 5938c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s", (char *)ib_qib_version); 5948c2ecf20Sopenharmony_ci} 5958c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(version); 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic ssize_t boardversion_show(struct device *device, 5988c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 5998c2ecf20Sopenharmony_ci{ 6008c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6018c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6028c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci /* The string printed here is already newline-terminated. */ 6058c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s", dd->boardversion); 6068c2ecf20Sopenharmony_ci} 6078c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(boardversion); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_cistatic ssize_t localbus_info_show(struct device *device, 6108c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6118c2ecf20Sopenharmony_ci{ 6128c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6138c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6148c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci /* The string printed here is already newline-terminated. */ 6178c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%s", dd->lbus_info); 6188c2ecf20Sopenharmony_ci} 6198c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(localbus_info); 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistatic ssize_t nctxts_show(struct device *device, 6228c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6258c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6268c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci /* Return the number of user ports (contexts) available. */ 6298c2ecf20Sopenharmony_ci /* The calculation below deals with a special case where 6308c2ecf20Sopenharmony_ci * cfgctxts is set to 1 on a single-port board. */ 6318c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%u\n", 6328c2ecf20Sopenharmony_ci (dd->first_user_ctxt > dd->cfgctxts) ? 0 : 6338c2ecf20Sopenharmony_ci (dd->cfgctxts - dd->first_user_ctxt)); 6348c2ecf20Sopenharmony_ci} 6358c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(nctxts); 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic ssize_t nfreectxts_show(struct device *device, 6388c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6398c2ecf20Sopenharmony_ci{ 6408c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6418c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6428c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci /* Return the number of free user ports (contexts) available. */ 6458c2ecf20Sopenharmony_ci return scnprintf(buf, PAGE_SIZE, "%u\n", dd->freectxts); 6468c2ecf20Sopenharmony_ci} 6478c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(nfreectxts); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_cistatic ssize_t serial_show(struct device *device, 6508c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6518c2ecf20Sopenharmony_ci{ 6528c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6538c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6548c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci buf[sizeof(dd->serial)] = '\0'; 6578c2ecf20Sopenharmony_ci memcpy(buf, dd->serial, sizeof(dd->serial)); 6588c2ecf20Sopenharmony_ci strcat(buf, "\n"); 6598c2ecf20Sopenharmony_ci return strlen(buf); 6608c2ecf20Sopenharmony_ci} 6618c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(serial); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_cistatic ssize_t chip_reset_store(struct device *device, 6648c2ecf20Sopenharmony_ci struct device_attribute *attr, const char *buf, 6658c2ecf20Sopenharmony_ci size_t count) 6668c2ecf20Sopenharmony_ci{ 6678c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6688c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6698c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6708c2ecf20Sopenharmony_ci int ret; 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ci if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) { 6738c2ecf20Sopenharmony_ci ret = -EINVAL; 6748c2ecf20Sopenharmony_ci goto bail; 6758c2ecf20Sopenharmony_ci } 6768c2ecf20Sopenharmony_ci 6778c2ecf20Sopenharmony_ci ret = qib_reset_device(dd->unit); 6788c2ecf20Sopenharmony_cibail: 6798c2ecf20Sopenharmony_ci return ret < 0 ? ret : count; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_cistatic DEVICE_ATTR_WO(chip_reset); 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci/* 6848c2ecf20Sopenharmony_ci * Dump tempsense regs. in decimal, to ease shell-scripts. 6858c2ecf20Sopenharmony_ci */ 6868c2ecf20Sopenharmony_cistatic ssize_t tempsense_show(struct device *device, 6878c2ecf20Sopenharmony_ci struct device_attribute *attr, char *buf) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci struct qib_ibdev *dev = 6908c2ecf20Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 6918c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 6928c2ecf20Sopenharmony_ci int ret; 6938c2ecf20Sopenharmony_ci int idx; 6948c2ecf20Sopenharmony_ci u8 regvals[8]; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci ret = -ENXIO; 6978c2ecf20Sopenharmony_ci for (idx = 0; idx < 8; ++idx) { 6988c2ecf20Sopenharmony_ci if (idx == 6) 6998c2ecf20Sopenharmony_ci continue; 7008c2ecf20Sopenharmony_ci ret = dd->f_tempsense_rd(dd, idx); 7018c2ecf20Sopenharmony_ci if (ret < 0) 7028c2ecf20Sopenharmony_ci break; 7038c2ecf20Sopenharmony_ci regvals[idx] = ret; 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci if (idx == 8) 7068c2ecf20Sopenharmony_ci ret = scnprintf(buf, PAGE_SIZE, "%d %d %02X %02X %d %d\n", 7078c2ecf20Sopenharmony_ci *(signed char *)(regvals), 7088c2ecf20Sopenharmony_ci *(signed char *)(regvals + 1), 7098c2ecf20Sopenharmony_ci regvals[2], regvals[3], 7108c2ecf20Sopenharmony_ci *(signed char *)(regvals + 5), 7118c2ecf20Sopenharmony_ci *(signed char *)(regvals + 7)); 7128c2ecf20Sopenharmony_ci return ret; 7138c2ecf20Sopenharmony_ci} 7148c2ecf20Sopenharmony_cistatic DEVICE_ATTR_RO(tempsense); 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci/* 7178c2ecf20Sopenharmony_ci * end of per-unit (or driver, in some cases, but replicated 7188c2ecf20Sopenharmony_ci * per unit) functions 7198c2ecf20Sopenharmony_ci */ 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci/* start of per-unit file structures and support code */ 7228c2ecf20Sopenharmony_cistatic struct attribute *qib_attributes[] = { 7238c2ecf20Sopenharmony_ci &dev_attr_hw_rev.attr, 7248c2ecf20Sopenharmony_ci &dev_attr_hca_type.attr, 7258c2ecf20Sopenharmony_ci &dev_attr_board_id.attr, 7268c2ecf20Sopenharmony_ci &dev_attr_version.attr, 7278c2ecf20Sopenharmony_ci &dev_attr_nctxts.attr, 7288c2ecf20Sopenharmony_ci &dev_attr_nfreectxts.attr, 7298c2ecf20Sopenharmony_ci &dev_attr_serial.attr, 7308c2ecf20Sopenharmony_ci &dev_attr_boardversion.attr, 7318c2ecf20Sopenharmony_ci &dev_attr_tempsense.attr, 7328c2ecf20Sopenharmony_ci &dev_attr_localbus_info.attr, 7338c2ecf20Sopenharmony_ci &dev_attr_chip_reset.attr, 7348c2ecf20Sopenharmony_ci NULL, 7358c2ecf20Sopenharmony_ci}; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ciconst struct attribute_group qib_attr_group = { 7388c2ecf20Sopenharmony_ci .attrs = qib_attributes, 7398c2ecf20Sopenharmony_ci}; 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ciint qib_create_port_files(struct ib_device *ibdev, u8 port_num, 7428c2ecf20Sopenharmony_ci struct kobject *kobj) 7438c2ecf20Sopenharmony_ci{ 7448c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 7458c2ecf20Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 7468c2ecf20Sopenharmony_ci int ret; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (!port_num || port_num > dd->num_pports) { 7498c2ecf20Sopenharmony_ci qib_dev_err(dd, 7508c2ecf20Sopenharmony_ci "Skipping infiniband class with invalid port %u\n", 7518c2ecf20Sopenharmony_ci port_num); 7528c2ecf20Sopenharmony_ci ret = -ENODEV; 7538c2ecf20Sopenharmony_ci goto bail; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci ppd = &dd->pport[port_num - 1]; 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci ret = kobject_init_and_add(&ppd->pport_kobj, &qib_port_ktype, kobj, 7588c2ecf20Sopenharmony_ci "linkcontrol"); 7598c2ecf20Sopenharmony_ci if (ret) { 7608c2ecf20Sopenharmony_ci qib_dev_err(dd, 7618c2ecf20Sopenharmony_ci "Skipping linkcontrol sysfs info, (err %d) port %u\n", 7628c2ecf20Sopenharmony_ci ret, port_num); 7638c2ecf20Sopenharmony_ci goto bail_link; 7648c2ecf20Sopenharmony_ci } 7658c2ecf20Sopenharmony_ci kobject_uevent(&ppd->pport_kobj, KOBJ_ADD); 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci ret = kobject_init_and_add(&ppd->sl2vl_kobj, &qib_sl2vl_ktype, kobj, 7688c2ecf20Sopenharmony_ci "sl2vl"); 7698c2ecf20Sopenharmony_ci if (ret) { 7708c2ecf20Sopenharmony_ci qib_dev_err(dd, 7718c2ecf20Sopenharmony_ci "Skipping sl2vl sysfs info, (err %d) port %u\n", 7728c2ecf20Sopenharmony_ci ret, port_num); 7738c2ecf20Sopenharmony_ci goto bail_sl; 7748c2ecf20Sopenharmony_ci } 7758c2ecf20Sopenharmony_ci kobject_uevent(&ppd->sl2vl_kobj, KOBJ_ADD); 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci ret = kobject_init_and_add(&ppd->diagc_kobj, &qib_diagc_ktype, kobj, 7788c2ecf20Sopenharmony_ci "diag_counters"); 7798c2ecf20Sopenharmony_ci if (ret) { 7808c2ecf20Sopenharmony_ci qib_dev_err(dd, 7818c2ecf20Sopenharmony_ci "Skipping diag_counters sysfs info, (err %d) port %u\n", 7828c2ecf20Sopenharmony_ci ret, port_num); 7838c2ecf20Sopenharmony_ci goto bail_diagc; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci kobject_uevent(&ppd->diagc_kobj, KOBJ_ADD); 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci if (!qib_cc_table_size || !ppd->congestion_entries_shadow) 7888c2ecf20Sopenharmony_ci return 0; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ret = kobject_init_and_add(&ppd->pport_cc_kobj, &qib_port_cc_ktype, 7918c2ecf20Sopenharmony_ci kobj, "CCMgtA"); 7928c2ecf20Sopenharmony_ci if (ret) { 7938c2ecf20Sopenharmony_ci qib_dev_err(dd, 7948c2ecf20Sopenharmony_ci "Skipping Congestion Control sysfs info, (err %d) port %u\n", 7958c2ecf20Sopenharmony_ci ret, port_num); 7968c2ecf20Sopenharmony_ci goto bail_cc; 7978c2ecf20Sopenharmony_ci } 7988c2ecf20Sopenharmony_ci 7998c2ecf20Sopenharmony_ci kobject_uevent(&ppd->pport_cc_kobj, KOBJ_ADD); 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, 8028c2ecf20Sopenharmony_ci &cc_setting_bin_attr); 8038c2ecf20Sopenharmony_ci if (ret) { 8048c2ecf20Sopenharmony_ci qib_dev_err(dd, 8058c2ecf20Sopenharmony_ci "Skipping Congestion Control setting sysfs info, (err %d) port %u\n", 8068c2ecf20Sopenharmony_ci ret, port_num); 8078c2ecf20Sopenharmony_ci goto bail_cc; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci ret = sysfs_create_bin_file(&ppd->pport_cc_kobj, 8118c2ecf20Sopenharmony_ci &cc_table_bin_attr); 8128c2ecf20Sopenharmony_ci if (ret) { 8138c2ecf20Sopenharmony_ci qib_dev_err(dd, 8148c2ecf20Sopenharmony_ci "Skipping Congestion Control table sysfs info, (err %d) port %u\n", 8158c2ecf20Sopenharmony_ci ret, port_num); 8168c2ecf20Sopenharmony_ci goto bail_cc_entry_bin; 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci qib_devinfo(dd->pcidev, 8208c2ecf20Sopenharmony_ci "IB%u: Congestion Control Agent enabled for port %d\n", 8218c2ecf20Sopenharmony_ci dd->unit, port_num); 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci return 0; 8248c2ecf20Sopenharmony_ci 8258c2ecf20Sopenharmony_cibail_cc_entry_bin: 8268c2ecf20Sopenharmony_ci sysfs_remove_bin_file(&ppd->pport_cc_kobj, &cc_setting_bin_attr); 8278c2ecf20Sopenharmony_cibail_cc: 8288c2ecf20Sopenharmony_ci kobject_put(&ppd->pport_cc_kobj); 8298c2ecf20Sopenharmony_cibail_diagc: 8308c2ecf20Sopenharmony_ci kobject_put(&ppd->diagc_kobj); 8318c2ecf20Sopenharmony_cibail_sl: 8328c2ecf20Sopenharmony_ci kobject_put(&ppd->sl2vl_kobj); 8338c2ecf20Sopenharmony_cibail_link: 8348c2ecf20Sopenharmony_ci kobject_put(&ppd->pport_kobj); 8358c2ecf20Sopenharmony_cibail: 8368c2ecf20Sopenharmony_ci return ret; 8378c2ecf20Sopenharmony_ci} 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci/* 8408c2ecf20Sopenharmony_ci * Unregister and remove our files in /sys/class/infiniband. 8418c2ecf20Sopenharmony_ci */ 8428c2ecf20Sopenharmony_civoid qib_verbs_unregister_sysfs(struct qib_devdata *dd) 8438c2ecf20Sopenharmony_ci{ 8448c2ecf20Sopenharmony_ci struct qib_pportdata *ppd; 8458c2ecf20Sopenharmony_ci int i; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci for (i = 0; i < dd->num_pports; i++) { 8488c2ecf20Sopenharmony_ci ppd = &dd->pport[i]; 8498c2ecf20Sopenharmony_ci if (qib_cc_table_size && 8508c2ecf20Sopenharmony_ci ppd->congestion_entries_shadow) { 8518c2ecf20Sopenharmony_ci sysfs_remove_bin_file(&ppd->pport_cc_kobj, 8528c2ecf20Sopenharmony_ci &cc_setting_bin_attr); 8538c2ecf20Sopenharmony_ci sysfs_remove_bin_file(&ppd->pport_cc_kobj, 8548c2ecf20Sopenharmony_ci &cc_table_bin_attr); 8558c2ecf20Sopenharmony_ci kobject_put(&ppd->pport_cc_kobj); 8568c2ecf20Sopenharmony_ci } 8578c2ecf20Sopenharmony_ci kobject_put(&ppd->diagc_kobj); 8588c2ecf20Sopenharmony_ci kobject_put(&ppd->sl2vl_kobj); 8598c2ecf20Sopenharmony_ci kobject_put(&ppd->pport_kobj); 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci} 862