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