162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2012 Intel Corporation. All rights reserved. 362306a36Sopenharmony_ci * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 462306a36Sopenharmony_ci * Copyright (c) 2006 PathScale, Inc. All rights reserved. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * This software is available to you under a choice of one of two 762306a36Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 862306a36Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 962306a36Sopenharmony_ci * COPYING in the main directory of this source tree, or the 1062306a36Sopenharmony_ci * OpenIB.org BSD license below: 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or 1362306a36Sopenharmony_ci * without modification, are permitted provided that the following 1462306a36Sopenharmony_ci * conditions are met: 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * - Redistributions of source code must retain the above 1762306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 1862306a36Sopenharmony_ci * disclaimer. 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * - Redistributions in binary form must reproduce the above 2162306a36Sopenharmony_ci * copyright notice, this list of conditions and the following 2262306a36Sopenharmony_ci * disclaimer in the documentation and/or other materials 2362306a36Sopenharmony_ci * provided with the distribution. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2662306a36Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2762306a36Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2862306a36Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2962306a36Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 3062306a36Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 3162306a36Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 3262306a36Sopenharmony_ci * SOFTWARE. 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci#include <linux/ctype.h> 3562306a36Sopenharmony_ci#include <rdma/ib_sysfs.h> 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#include "qib.h" 3862306a36Sopenharmony_ci#include "qib_mad.h" 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistatic struct qib_pportdata *qib_get_pportdata_kobj(struct kobject *kobj) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci u32 port_num; 4362306a36Sopenharmony_ci struct ib_device *ibdev = ib_port_sysfs_get_ibdev_kobj(kobj, &port_num); 4462306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return &dd->pport[port_num - 1]; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/* 5062306a36Sopenharmony_ci * Get/Set heartbeat enable. OR of 1=enabled, 2=auto 5162306a36Sopenharmony_ci */ 5262306a36Sopenharmony_cistatic ssize_t hrtbt_enable_show(struct ib_device *ibdev, u32 port_num, 5362306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 5662306a36Sopenharmony_ci struct qib_pportdata *ppd = &dd->pport[port_num - 1]; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci return sysfs_emit(buf, "%d\n", dd->f_get_ib_cfg(ppd, QIB_IB_CFG_HRTBT)); 5962306a36Sopenharmony_ci} 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic ssize_t hrtbt_enable_store(struct ib_device *ibdev, u32 port_num, 6262306a36Sopenharmony_ci struct ib_port_attribute *attr, 6362306a36Sopenharmony_ci const char *buf, size_t count) 6462306a36Sopenharmony_ci{ 6562306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 6662306a36Sopenharmony_ci struct qib_pportdata *ppd = &dd->pport[port_num - 1]; 6762306a36Sopenharmony_ci int ret; 6862306a36Sopenharmony_ci u16 val; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ret = kstrtou16(buf, 0, &val); 7162306a36Sopenharmony_ci if (ret) { 7262306a36Sopenharmony_ci qib_dev_err(dd, "attempt to set invalid Heartbeat enable\n"); 7362306a36Sopenharmony_ci return ret; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci /* 7762306a36Sopenharmony_ci * Set the "intentional" heartbeat enable per either of 7862306a36Sopenharmony_ci * "Enable" and "Auto", as these are normally set together. 7962306a36Sopenharmony_ci * This bit is consulted when leaving loopback mode, 8062306a36Sopenharmony_ci * because entering loopback mode overrides it and automatically 8162306a36Sopenharmony_ci * disables heartbeat. 8262306a36Sopenharmony_ci */ 8362306a36Sopenharmony_ci ret = dd->f_set_ib_cfg(ppd, QIB_IB_CFG_HRTBT, val); 8462306a36Sopenharmony_ci return ret < 0 ? ret : count; 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_cistatic IB_PORT_ATTR_RW(hrtbt_enable); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic ssize_t loopback_store(struct ib_device *ibdev, u32 port_num, 8962306a36Sopenharmony_ci struct ib_port_attribute *attr, const char *buf, 9062306a36Sopenharmony_ci size_t count) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 9362306a36Sopenharmony_ci struct qib_pportdata *ppd = &dd->pport[port_num - 1]; 9462306a36Sopenharmony_ci int ret = count, r; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci r = dd->f_set_ib_loopback(ppd, buf); 9762306a36Sopenharmony_ci if (r < 0) 9862306a36Sopenharmony_ci ret = r; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci return ret; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_cistatic IB_PORT_ATTR_WO(loopback); 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic ssize_t led_override_store(struct ib_device *ibdev, u32 port_num, 10562306a36Sopenharmony_ci struct ib_port_attribute *attr, 10662306a36Sopenharmony_ci const char *buf, size_t count) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 10962306a36Sopenharmony_ci struct qib_pportdata *ppd = &dd->pport[port_num - 1]; 11062306a36Sopenharmony_ci int ret; 11162306a36Sopenharmony_ci u16 val; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci ret = kstrtou16(buf, 0, &val); 11462306a36Sopenharmony_ci if (ret) { 11562306a36Sopenharmony_ci qib_dev_err(dd, "attempt to set invalid LED override\n"); 11662306a36Sopenharmony_ci return ret; 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci qib_set_led_override(ppd, val); 12062306a36Sopenharmony_ci return count; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_cistatic IB_PORT_ATTR_WO(led_override); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic ssize_t status_show(struct ib_device *ibdev, u32 port_num, 12562306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 12862306a36Sopenharmony_ci struct qib_pportdata *ppd = &dd->pport[port_num - 1]; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci if (!ppd->statusp) 13162306a36Sopenharmony_ci return -EINVAL; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci return sysfs_emit(buf, "0x%llx\n", (unsigned long long)*(ppd->statusp)); 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_cistatic IB_PORT_ATTR_RO(status); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/* 13862306a36Sopenharmony_ci * For userland compatibility, these offsets must remain fixed. 13962306a36Sopenharmony_ci * They are strings for QIB_STATUS_* 14062306a36Sopenharmony_ci */ 14162306a36Sopenharmony_cistatic const char * const qib_status_str[] = { 14262306a36Sopenharmony_ci "Initted", 14362306a36Sopenharmony_ci "", 14462306a36Sopenharmony_ci "", 14562306a36Sopenharmony_ci "", 14662306a36Sopenharmony_ci "", 14762306a36Sopenharmony_ci "Present", 14862306a36Sopenharmony_ci "IB_link_up", 14962306a36Sopenharmony_ci "IB_configured", 15062306a36Sopenharmony_ci "", 15162306a36Sopenharmony_ci "Fatal_Hardware_Error", 15262306a36Sopenharmony_ci NULL, 15362306a36Sopenharmony_ci}; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_cistatic ssize_t status_str_show(struct ib_device *ibdev, u32 port_num, 15662306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 15962306a36Sopenharmony_ci struct qib_pportdata *ppd = &dd->pport[port_num - 1]; 16062306a36Sopenharmony_ci int i, any; 16162306a36Sopenharmony_ci u64 s; 16262306a36Sopenharmony_ci ssize_t ret; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci if (!ppd->statusp) { 16562306a36Sopenharmony_ci ret = -EINVAL; 16662306a36Sopenharmony_ci goto bail; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci s = *(ppd->statusp); 17062306a36Sopenharmony_ci *buf = '\0'; 17162306a36Sopenharmony_ci for (any = i = 0; s && qib_status_str[i]; i++) { 17262306a36Sopenharmony_ci if (s & 1) { 17362306a36Sopenharmony_ci /* if overflow */ 17462306a36Sopenharmony_ci if (any && strlcat(buf, " ", PAGE_SIZE) >= PAGE_SIZE) 17562306a36Sopenharmony_ci break; 17662306a36Sopenharmony_ci if (strlcat(buf, qib_status_str[i], PAGE_SIZE) >= 17762306a36Sopenharmony_ci PAGE_SIZE) 17862306a36Sopenharmony_ci break; 17962306a36Sopenharmony_ci any = 1; 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci s >>= 1; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci if (any) 18462306a36Sopenharmony_ci strlcat(buf, "\n", PAGE_SIZE); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci ret = strlen(buf); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cibail: 18962306a36Sopenharmony_ci return ret; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_cistatic IB_PORT_ATTR_RO(status_str); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci/* end of per-port functions */ 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic struct attribute *port_linkcontrol_attributes[] = { 19662306a36Sopenharmony_ci &ib_port_attr_loopback.attr, 19762306a36Sopenharmony_ci &ib_port_attr_led_override.attr, 19862306a36Sopenharmony_ci &ib_port_attr_hrtbt_enable.attr, 19962306a36Sopenharmony_ci &ib_port_attr_status.attr, 20062306a36Sopenharmony_ci &ib_port_attr_status_str.attr, 20162306a36Sopenharmony_ci NULL 20262306a36Sopenharmony_ci}; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic const struct attribute_group port_linkcontrol_group = { 20562306a36Sopenharmony_ci .name = "linkcontrol", 20662306a36Sopenharmony_ci .attrs = port_linkcontrol_attributes, 20762306a36Sopenharmony_ci}; 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* 21062306a36Sopenharmony_ci * Start of per-port congestion control structures and support code 21162306a36Sopenharmony_ci */ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci/* 21462306a36Sopenharmony_ci * Congestion control table size followed by table entries 21562306a36Sopenharmony_ci */ 21662306a36Sopenharmony_cistatic ssize_t cc_table_bin_read(struct file *filp, struct kobject *kobj, 21762306a36Sopenharmony_ci struct bin_attribute *bin_attr, char *buf, 21862306a36Sopenharmony_ci loff_t pos, size_t count) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj); 22162306a36Sopenharmony_ci int ret; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (!qib_cc_table_size || !ppd->ccti_entries_shadow) 22462306a36Sopenharmony_ci return -EINVAL; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci ret = ppd->total_cct_entry * sizeof(struct ib_cc_table_entry_shadow) 22762306a36Sopenharmony_ci + sizeof(__be16); 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci if (pos > ret) 23062306a36Sopenharmony_ci return -EINVAL; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci if (count > ret - pos) 23362306a36Sopenharmony_ci count = ret - pos; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (!count) 23662306a36Sopenharmony_ci return count; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci spin_lock(&ppd->cc_shadow_lock); 23962306a36Sopenharmony_ci memcpy(buf, ppd->ccti_entries_shadow, count); 24062306a36Sopenharmony_ci spin_unlock(&ppd->cc_shadow_lock); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci return count; 24362306a36Sopenharmony_ci} 24462306a36Sopenharmony_cistatic BIN_ATTR_RO(cc_table_bin, PAGE_SIZE); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/* 24762306a36Sopenharmony_ci * Congestion settings: port control, control map and an array of 16 24862306a36Sopenharmony_ci * entries for the congestion entries - increase, timer, event log 24962306a36Sopenharmony_ci * trigger threshold and the minimum injection rate delay. 25062306a36Sopenharmony_ci */ 25162306a36Sopenharmony_cistatic ssize_t cc_setting_bin_read(struct file *filp, struct kobject *kobj, 25262306a36Sopenharmony_ci struct bin_attribute *bin_attr, char *buf, 25362306a36Sopenharmony_ci loff_t pos, size_t count) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj); 25662306a36Sopenharmony_ci int ret; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci if (!qib_cc_table_size || !ppd->congestion_entries_shadow) 25962306a36Sopenharmony_ci return -EINVAL; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci ret = sizeof(struct ib_cc_congestion_setting_attr_shadow); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (pos > ret) 26462306a36Sopenharmony_ci return -EINVAL; 26562306a36Sopenharmony_ci if (count > ret - pos) 26662306a36Sopenharmony_ci count = ret - pos; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (!count) 26962306a36Sopenharmony_ci return count; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci spin_lock(&ppd->cc_shadow_lock); 27262306a36Sopenharmony_ci memcpy(buf, ppd->congestion_entries_shadow, count); 27362306a36Sopenharmony_ci spin_unlock(&ppd->cc_shadow_lock); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci return count; 27662306a36Sopenharmony_ci} 27762306a36Sopenharmony_cistatic BIN_ATTR_RO(cc_setting_bin, PAGE_SIZE); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic struct bin_attribute *port_ccmgta_attributes[] = { 28062306a36Sopenharmony_ci &bin_attr_cc_setting_bin, 28162306a36Sopenharmony_ci &bin_attr_cc_table_bin, 28262306a36Sopenharmony_ci NULL, 28362306a36Sopenharmony_ci}; 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_cistatic umode_t qib_ccmgta_is_bin_visible(struct kobject *kobj, 28662306a36Sopenharmony_ci struct bin_attribute *attr, int n) 28762306a36Sopenharmony_ci{ 28862306a36Sopenharmony_ci struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci if (!qib_cc_table_size || !ppd->congestion_entries_shadow) 29162306a36Sopenharmony_ci return 0; 29262306a36Sopenharmony_ci return attr->attr.mode; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic const struct attribute_group port_ccmgta_attribute_group = { 29662306a36Sopenharmony_ci .name = "CCMgtA", 29762306a36Sopenharmony_ci .is_bin_visible = qib_ccmgta_is_bin_visible, 29862306a36Sopenharmony_ci .bin_attrs = port_ccmgta_attributes, 29962306a36Sopenharmony_ci}; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci/* Start sl2vl */ 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistruct qib_sl2vl_attr { 30462306a36Sopenharmony_ci struct ib_port_attribute attr; 30562306a36Sopenharmony_ci int sl; 30662306a36Sopenharmony_ci}; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_cistatic ssize_t sl2vl_attr_show(struct ib_device *ibdev, u32 port_num, 30962306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 31062306a36Sopenharmony_ci{ 31162306a36Sopenharmony_ci struct qib_sl2vl_attr *sattr = 31262306a36Sopenharmony_ci container_of(attr, struct qib_sl2vl_attr, attr); 31362306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 31462306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", qibp->sl_to_vl[sattr->sl]); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci#define QIB_SL2VL_ATTR(N) \ 32062306a36Sopenharmony_ci static struct qib_sl2vl_attr qib_sl2vl_attr_##N = { \ 32162306a36Sopenharmony_ci .attr = __ATTR(N, 0444, sl2vl_attr_show, NULL), \ 32262306a36Sopenharmony_ci .sl = N, \ 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ciQIB_SL2VL_ATTR(0); 32662306a36Sopenharmony_ciQIB_SL2VL_ATTR(1); 32762306a36Sopenharmony_ciQIB_SL2VL_ATTR(2); 32862306a36Sopenharmony_ciQIB_SL2VL_ATTR(3); 32962306a36Sopenharmony_ciQIB_SL2VL_ATTR(4); 33062306a36Sopenharmony_ciQIB_SL2VL_ATTR(5); 33162306a36Sopenharmony_ciQIB_SL2VL_ATTR(6); 33262306a36Sopenharmony_ciQIB_SL2VL_ATTR(7); 33362306a36Sopenharmony_ciQIB_SL2VL_ATTR(8); 33462306a36Sopenharmony_ciQIB_SL2VL_ATTR(9); 33562306a36Sopenharmony_ciQIB_SL2VL_ATTR(10); 33662306a36Sopenharmony_ciQIB_SL2VL_ATTR(11); 33762306a36Sopenharmony_ciQIB_SL2VL_ATTR(12); 33862306a36Sopenharmony_ciQIB_SL2VL_ATTR(13); 33962306a36Sopenharmony_ciQIB_SL2VL_ATTR(14); 34062306a36Sopenharmony_ciQIB_SL2VL_ATTR(15); 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic struct attribute *port_sl2vl_attributes[] = { 34362306a36Sopenharmony_ci &qib_sl2vl_attr_0.attr.attr, 34462306a36Sopenharmony_ci &qib_sl2vl_attr_1.attr.attr, 34562306a36Sopenharmony_ci &qib_sl2vl_attr_2.attr.attr, 34662306a36Sopenharmony_ci &qib_sl2vl_attr_3.attr.attr, 34762306a36Sopenharmony_ci &qib_sl2vl_attr_4.attr.attr, 34862306a36Sopenharmony_ci &qib_sl2vl_attr_5.attr.attr, 34962306a36Sopenharmony_ci &qib_sl2vl_attr_6.attr.attr, 35062306a36Sopenharmony_ci &qib_sl2vl_attr_7.attr.attr, 35162306a36Sopenharmony_ci &qib_sl2vl_attr_8.attr.attr, 35262306a36Sopenharmony_ci &qib_sl2vl_attr_9.attr.attr, 35362306a36Sopenharmony_ci &qib_sl2vl_attr_10.attr.attr, 35462306a36Sopenharmony_ci &qib_sl2vl_attr_11.attr.attr, 35562306a36Sopenharmony_ci &qib_sl2vl_attr_12.attr.attr, 35662306a36Sopenharmony_ci &qib_sl2vl_attr_13.attr.attr, 35762306a36Sopenharmony_ci &qib_sl2vl_attr_14.attr.attr, 35862306a36Sopenharmony_ci &qib_sl2vl_attr_15.attr.attr, 35962306a36Sopenharmony_ci NULL 36062306a36Sopenharmony_ci}; 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic const struct attribute_group port_sl2vl_group = { 36362306a36Sopenharmony_ci .name = "sl2vl", 36462306a36Sopenharmony_ci .attrs = port_sl2vl_attributes, 36562306a36Sopenharmony_ci}; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci/* End sl2vl */ 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/* Start diag_counters */ 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_cistruct qib_diagc_attr { 37262306a36Sopenharmony_ci struct ib_port_attribute attr; 37362306a36Sopenharmony_ci size_t counter; 37462306a36Sopenharmony_ci}; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic ssize_t diagc_attr_show(struct ib_device *ibdev, u32 port_num, 37762306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci struct qib_diagc_attr *dattr = 38062306a36Sopenharmony_ci container_of(attr, struct qib_diagc_attr, attr); 38162306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 38262306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", *((u64 *)qibp + dattr->counter)); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic ssize_t diagc_attr_store(struct ib_device *ibdev, u32 port_num, 38862306a36Sopenharmony_ci struct ib_port_attribute *attr, const char *buf, 38962306a36Sopenharmony_ci size_t count) 39062306a36Sopenharmony_ci{ 39162306a36Sopenharmony_ci struct qib_diagc_attr *dattr = 39262306a36Sopenharmony_ci container_of(attr, struct qib_diagc_attr, attr); 39362306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 39462306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 39562306a36Sopenharmony_ci u64 val; 39662306a36Sopenharmony_ci int ret; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci ret = kstrtou64(buf, 0, &val); 39962306a36Sopenharmony_ci if (ret) 40062306a36Sopenharmony_ci return ret; 40162306a36Sopenharmony_ci *((u64 *)qibp + dattr->counter) = val; 40262306a36Sopenharmony_ci return count; 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci#define QIB_DIAGC_ATTR(N) \ 40662306a36Sopenharmony_ci static_assert(__same_type(((struct qib_ibport *)0)->rvp.n_##N, u64)); \ 40762306a36Sopenharmony_ci static struct qib_diagc_attr qib_diagc_attr_##N = { \ 40862306a36Sopenharmony_ci .attr = __ATTR(N, 0664, diagc_attr_show, diagc_attr_store), \ 40962306a36Sopenharmony_ci .counter = \ 41062306a36Sopenharmony_ci offsetof(struct qib_ibport, rvp.n_##N) / sizeof(u64) \ 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_ciQIB_DIAGC_ATTR(rc_resends); 41462306a36Sopenharmony_ciQIB_DIAGC_ATTR(seq_naks); 41562306a36Sopenharmony_ciQIB_DIAGC_ATTR(rdma_seq); 41662306a36Sopenharmony_ciQIB_DIAGC_ATTR(rnr_naks); 41762306a36Sopenharmony_ciQIB_DIAGC_ATTR(other_naks); 41862306a36Sopenharmony_ciQIB_DIAGC_ATTR(rc_timeouts); 41962306a36Sopenharmony_ciQIB_DIAGC_ATTR(loop_pkts); 42062306a36Sopenharmony_ciQIB_DIAGC_ATTR(pkt_drops); 42162306a36Sopenharmony_ciQIB_DIAGC_ATTR(dmawait); 42262306a36Sopenharmony_ciQIB_DIAGC_ATTR(unaligned); 42362306a36Sopenharmony_ciQIB_DIAGC_ATTR(rc_dupreq); 42462306a36Sopenharmony_ciQIB_DIAGC_ATTR(rc_seqnak); 42562306a36Sopenharmony_ciQIB_DIAGC_ATTR(rc_crwaits); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic u64 get_all_cpu_total(u64 __percpu *cntr) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci int cpu; 43062306a36Sopenharmony_ci u64 counter = 0; 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci for_each_possible_cpu(cpu) 43362306a36Sopenharmony_ci counter += *per_cpu_ptr(cntr, cpu); 43462306a36Sopenharmony_ci return counter; 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic ssize_t qib_store_per_cpu(struct qib_devdata *dd, const char *buf, 43862306a36Sopenharmony_ci size_t count, u64 *zero, u64 cur) 43962306a36Sopenharmony_ci{ 44062306a36Sopenharmony_ci u32 val; 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci ret = kstrtou32(buf, 0, &val); 44462306a36Sopenharmony_ci if (ret) 44562306a36Sopenharmony_ci return ret; 44662306a36Sopenharmony_ci if (val != 0) { 44762306a36Sopenharmony_ci qib_dev_err(dd, "Per CPU cntrs can only be zeroed"); 44862306a36Sopenharmony_ci return count; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci *zero = cur; 45162306a36Sopenharmony_ci return count; 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic ssize_t rc_acks_show(struct ib_device *ibdev, u32 port_num, 45562306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 45862306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 46162306a36Sopenharmony_ci get_all_cpu_total(qibp->rvp.rc_acks) - 46262306a36Sopenharmony_ci qibp->rvp.z_rc_acks); 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic ssize_t rc_acks_store(struct ib_device *ibdev, u32 port_num, 46662306a36Sopenharmony_ci struct ib_port_attribute *attr, const char *buf, 46762306a36Sopenharmony_ci size_t count) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 47062306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci return qib_store_per_cpu(dd, buf, count, &qibp->rvp.z_rc_acks, 47362306a36Sopenharmony_ci get_all_cpu_total(qibp->rvp.rc_acks)); 47462306a36Sopenharmony_ci} 47562306a36Sopenharmony_cistatic IB_PORT_ATTR_RW(rc_acks); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_cistatic ssize_t rc_qacks_show(struct ib_device *ibdev, u32 port_num, 47862306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 47962306a36Sopenharmony_ci{ 48062306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 48162306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 48462306a36Sopenharmony_ci get_all_cpu_total(qibp->rvp.rc_qacks) - 48562306a36Sopenharmony_ci qibp->rvp.z_rc_qacks); 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic ssize_t rc_qacks_store(struct ib_device *ibdev, u32 port_num, 48962306a36Sopenharmony_ci struct ib_port_attribute *attr, const char *buf, 49062306a36Sopenharmony_ci size_t count) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 49362306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci return qib_store_per_cpu(dd, buf, count, &qibp->rvp.z_rc_qacks, 49662306a36Sopenharmony_ci get_all_cpu_total(qibp->rvp.rc_qacks)); 49762306a36Sopenharmony_ci} 49862306a36Sopenharmony_cistatic IB_PORT_ATTR_RW(rc_qacks); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_cistatic ssize_t rc_delayed_comp_show(struct ib_device *ibdev, u32 port_num, 50162306a36Sopenharmony_ci struct ib_port_attribute *attr, char *buf) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 50462306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci return sysfs_emit(buf, "%llu\n", 50762306a36Sopenharmony_ci get_all_cpu_total(qibp->rvp.rc_delayed_comp) - 50862306a36Sopenharmony_ci qibp->rvp.z_rc_delayed_comp); 50962306a36Sopenharmony_ci} 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_cistatic ssize_t rc_delayed_comp_store(struct ib_device *ibdev, u32 port_num, 51262306a36Sopenharmony_ci struct ib_port_attribute *attr, 51362306a36Sopenharmony_ci const char *buf, size_t count) 51462306a36Sopenharmony_ci{ 51562306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_ibdev(ibdev); 51662306a36Sopenharmony_ci struct qib_ibport *qibp = &dd->pport[port_num - 1].ibport_data; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci return qib_store_per_cpu(dd, buf, count, &qibp->rvp.z_rc_delayed_comp, 51962306a36Sopenharmony_ci get_all_cpu_total(qibp->rvp.rc_delayed_comp)); 52062306a36Sopenharmony_ci} 52162306a36Sopenharmony_cistatic IB_PORT_ATTR_RW(rc_delayed_comp); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic struct attribute *port_diagc_attributes[] = { 52462306a36Sopenharmony_ci &qib_diagc_attr_rc_resends.attr.attr, 52562306a36Sopenharmony_ci &qib_diagc_attr_seq_naks.attr.attr, 52662306a36Sopenharmony_ci &qib_diagc_attr_rdma_seq.attr.attr, 52762306a36Sopenharmony_ci &qib_diagc_attr_rnr_naks.attr.attr, 52862306a36Sopenharmony_ci &qib_diagc_attr_other_naks.attr.attr, 52962306a36Sopenharmony_ci &qib_diagc_attr_rc_timeouts.attr.attr, 53062306a36Sopenharmony_ci &qib_diagc_attr_loop_pkts.attr.attr, 53162306a36Sopenharmony_ci &qib_diagc_attr_pkt_drops.attr.attr, 53262306a36Sopenharmony_ci &qib_diagc_attr_dmawait.attr.attr, 53362306a36Sopenharmony_ci &qib_diagc_attr_unaligned.attr.attr, 53462306a36Sopenharmony_ci &qib_diagc_attr_rc_dupreq.attr.attr, 53562306a36Sopenharmony_ci &qib_diagc_attr_rc_seqnak.attr.attr, 53662306a36Sopenharmony_ci &qib_diagc_attr_rc_crwaits.attr.attr, 53762306a36Sopenharmony_ci &ib_port_attr_rc_acks.attr, 53862306a36Sopenharmony_ci &ib_port_attr_rc_qacks.attr, 53962306a36Sopenharmony_ci &ib_port_attr_rc_delayed_comp.attr, 54062306a36Sopenharmony_ci NULL 54162306a36Sopenharmony_ci}; 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic const struct attribute_group port_diagc_group = { 54462306a36Sopenharmony_ci .name = "diag_counters", 54562306a36Sopenharmony_ci .attrs = port_diagc_attributes, 54662306a36Sopenharmony_ci}; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci/* End diag_counters */ 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ciconst struct attribute_group *qib_attr_port_groups[] = { 55162306a36Sopenharmony_ci &port_linkcontrol_group, 55262306a36Sopenharmony_ci &port_ccmgta_attribute_group, 55362306a36Sopenharmony_ci &port_sl2vl_group, 55462306a36Sopenharmony_ci &port_diagc_group, 55562306a36Sopenharmony_ci NULL, 55662306a36Sopenharmony_ci}; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci/* end of per-port file structures and support code */ 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci/* 56162306a36Sopenharmony_ci * Start of per-unit (or driver, in some cases, but replicated 56262306a36Sopenharmony_ci * per unit) functions (these get a device *) 56362306a36Sopenharmony_ci */ 56462306a36Sopenharmony_cistatic ssize_t hw_rev_show(struct device *device, struct device_attribute *attr, 56562306a36Sopenharmony_ci char *buf) 56662306a36Sopenharmony_ci{ 56762306a36Sopenharmony_ci struct qib_ibdev *dev = 56862306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci return sysfs_emit(buf, "%x\n", dd_from_dev(dev)->minrev); 57162306a36Sopenharmony_ci} 57262306a36Sopenharmony_cistatic DEVICE_ATTR_RO(hw_rev); 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cistatic ssize_t hca_type_show(struct device *device, 57562306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci struct qib_ibdev *dev = 57862306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 57962306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (!dd->boardname) 58262306a36Sopenharmony_ci return -EINVAL; 58362306a36Sopenharmony_ci return sysfs_emit(buf, "%s\n", dd->boardname); 58462306a36Sopenharmony_ci} 58562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(hca_type); 58662306a36Sopenharmony_cistatic DEVICE_ATTR(board_id, 0444, hca_type_show, NULL); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_cistatic ssize_t version_show(struct device *device, 58962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 59062306a36Sopenharmony_ci{ 59162306a36Sopenharmony_ci /* The string printed here is already newline-terminated. */ 59262306a36Sopenharmony_ci return sysfs_emit(buf, "%s", (char *)ib_qib_version); 59362306a36Sopenharmony_ci} 59462306a36Sopenharmony_cistatic DEVICE_ATTR_RO(version); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_cistatic ssize_t boardversion_show(struct device *device, 59762306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci struct qib_ibdev *dev = 60062306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 60162306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 60262306a36Sopenharmony_ci 60362306a36Sopenharmony_ci /* The string printed here is already newline-terminated. */ 60462306a36Sopenharmony_ci return sysfs_emit(buf, "%s", dd->boardversion); 60562306a36Sopenharmony_ci} 60662306a36Sopenharmony_cistatic DEVICE_ATTR_RO(boardversion); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_cistatic ssize_t localbus_info_show(struct device *device, 60962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci struct qib_ibdev *dev = 61262306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 61362306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci /* The string printed here is already newline-terminated. */ 61662306a36Sopenharmony_ci return sysfs_emit(buf, "%s", dd->lbus_info); 61762306a36Sopenharmony_ci} 61862306a36Sopenharmony_cistatic DEVICE_ATTR_RO(localbus_info); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_cistatic ssize_t nctxts_show(struct device *device, 62162306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 62262306a36Sopenharmony_ci{ 62362306a36Sopenharmony_ci struct qib_ibdev *dev = 62462306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 62562306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* Return the number of user ports (contexts) available. */ 62862306a36Sopenharmony_ci /* The calculation below deals with a special case where 62962306a36Sopenharmony_ci * cfgctxts is set to 1 on a single-port board. */ 63062306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", 63162306a36Sopenharmony_ci (dd->first_user_ctxt > dd->cfgctxts) ? 63262306a36Sopenharmony_ci 0 : 63362306a36Sopenharmony_ci (dd->cfgctxts - dd->first_user_ctxt)); 63462306a36Sopenharmony_ci} 63562306a36Sopenharmony_cistatic DEVICE_ATTR_RO(nctxts); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_cistatic ssize_t nfreectxts_show(struct device *device, 63862306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci struct qib_ibdev *dev = 64162306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 64262306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci /* Return the number of free user ports (contexts) available. */ 64562306a36Sopenharmony_ci return sysfs_emit(buf, "%u\n", dd->freectxts); 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_cistatic DEVICE_ATTR_RO(nfreectxts); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cistatic ssize_t serial_show(struct device *device, struct device_attribute *attr, 65062306a36Sopenharmony_ci char *buf) 65162306a36Sopenharmony_ci{ 65262306a36Sopenharmony_ci struct qib_ibdev *dev = 65362306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 65462306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 65562306a36Sopenharmony_ci const u8 *end = memchr(dd->serial, 0, ARRAY_SIZE(dd->serial)); 65662306a36Sopenharmony_ci int size = end ? end - dd->serial : ARRAY_SIZE(dd->serial); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci return sysfs_emit(buf, ".%*s\n", size, dd->serial); 65962306a36Sopenharmony_ci} 66062306a36Sopenharmony_cistatic DEVICE_ATTR_RO(serial); 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic ssize_t chip_reset_store(struct device *device, 66362306a36Sopenharmony_ci struct device_attribute *attr, const char *buf, 66462306a36Sopenharmony_ci size_t count) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci struct qib_ibdev *dev = 66762306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 66862306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 66962306a36Sopenharmony_ci int ret; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (count < 5 || memcmp(buf, "reset", 5) || !dd->diag_client) { 67262306a36Sopenharmony_ci ret = -EINVAL; 67362306a36Sopenharmony_ci goto bail; 67462306a36Sopenharmony_ci } 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci ret = qib_reset_device(dd->unit); 67762306a36Sopenharmony_cibail: 67862306a36Sopenharmony_ci return ret < 0 ? ret : count; 67962306a36Sopenharmony_ci} 68062306a36Sopenharmony_cistatic DEVICE_ATTR_WO(chip_reset); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci/* 68362306a36Sopenharmony_ci * Dump tempsense regs. in decimal, to ease shell-scripts. 68462306a36Sopenharmony_ci */ 68562306a36Sopenharmony_cistatic ssize_t tempsense_show(struct device *device, 68662306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct qib_ibdev *dev = 68962306a36Sopenharmony_ci rdma_device_to_drv_device(device, struct qib_ibdev, rdi.ibdev); 69062306a36Sopenharmony_ci struct qib_devdata *dd = dd_from_dev(dev); 69162306a36Sopenharmony_ci int i; 69262306a36Sopenharmony_ci u8 regvals[8]; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 69562306a36Sopenharmony_ci int ret; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci if (i == 6) 69862306a36Sopenharmony_ci continue; 69962306a36Sopenharmony_ci ret = dd->f_tempsense_rd(dd, i); 70062306a36Sopenharmony_ci if (ret < 0) 70162306a36Sopenharmony_ci return ret; /* return error on bad read */ 70262306a36Sopenharmony_ci regvals[i] = ret; 70362306a36Sopenharmony_ci } 70462306a36Sopenharmony_ci return sysfs_emit(buf, "%d %d %02X %02X %d %d\n", 70562306a36Sopenharmony_ci (signed char)regvals[0], 70662306a36Sopenharmony_ci (signed char)regvals[1], 70762306a36Sopenharmony_ci regvals[2], 70862306a36Sopenharmony_ci regvals[3], 70962306a36Sopenharmony_ci (signed char)regvals[5], 71062306a36Sopenharmony_ci (signed char)regvals[7]); 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_cistatic DEVICE_ATTR_RO(tempsense); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci/* 71562306a36Sopenharmony_ci * end of per-unit (or driver, in some cases, but replicated 71662306a36Sopenharmony_ci * per unit) functions 71762306a36Sopenharmony_ci */ 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci/* start of per-unit file structures and support code */ 72062306a36Sopenharmony_cistatic struct attribute *qib_attributes[] = { 72162306a36Sopenharmony_ci &dev_attr_hw_rev.attr, 72262306a36Sopenharmony_ci &dev_attr_hca_type.attr, 72362306a36Sopenharmony_ci &dev_attr_board_id.attr, 72462306a36Sopenharmony_ci &dev_attr_version.attr, 72562306a36Sopenharmony_ci &dev_attr_nctxts.attr, 72662306a36Sopenharmony_ci &dev_attr_nfreectxts.attr, 72762306a36Sopenharmony_ci &dev_attr_serial.attr, 72862306a36Sopenharmony_ci &dev_attr_boardversion.attr, 72962306a36Sopenharmony_ci &dev_attr_tempsense.attr, 73062306a36Sopenharmony_ci &dev_attr_localbus_info.attr, 73162306a36Sopenharmony_ci &dev_attr_chip_reset.attr, 73262306a36Sopenharmony_ci NULL, 73362306a36Sopenharmony_ci}; 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ciconst struct attribute_group qib_attr_group = { 73662306a36Sopenharmony_ci .attrs = qib_attributes, 73762306a36Sopenharmony_ci}; 738