ipath_mad.c revision b3b8128fd3b0966830ee90f1162173d07cb496a0
1e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan/*
287427da55bc03dbce7906a5b09ed50279d654d28John Gregor * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved.
3e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
4e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
5e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * This software is available to you under a choice of one of two
6e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * licenses.  You may choose to be licensed under the terms of the GNU
7e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * General Public License (GPL) Version 2, available from the file
8e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * COPYING in the main directory of this source tree, or the
9e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * OpenIB.org BSD license below:
10e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
11e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *     Redistribution and use in source and binary forms, with or
12e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *     without modification, are permitted provided that the following
13e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *     conditions are met:
14e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
15e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *      - Redistributions of source code must retain the above
16e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *        copyright notice, this list of conditions and the following
17e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *        disclaimer.
18e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
19e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *      - Redistributions in binary form must reproduce the above
20e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *        copyright notice, this list of conditions and the following
21e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *        disclaimer in the documentation and/or other materials
22e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *        provided with the distribution.
23e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
24e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * SOFTWARE.
32e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan */
33e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
34e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#include <rdma/ib_smi.h>
35e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
36e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#include "ipath_kernel.h"
37e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#include "ipath_verbs.h"
3827b678dd04a636f2c351816f4b3042c8815d4e9dBryan O'Sullivan#include "ipath_common.h"
39e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
40e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_SMP_UNSUP_VERSION	__constant_htons(0x0004)
41e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_SMP_UNSUP_METHOD	__constant_htons(0x0008)
42e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_SMP_UNSUP_METH_ATTR	__constant_htons(0x000C)
43e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_SMP_INVALID_FIELD	__constant_htons(0x001C)
44e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
45e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int reply(struct ib_smp *smp)
46e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
47e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
48e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * The verbs framework will handle the directed/LID route
49e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * packet changes.
50e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
51e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	smp->method = IB_MGMT_METHOD_GET_RESP;
52e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (smp->mgmt_class == IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
53e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_DIRECTION;
54e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_REPLY;
55e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
56e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
57e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_get_nodedescription(struct ib_smp *smp,
58e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					 struct ib_device *ibdev)
59e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
60e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (smp->attr_mod)
61e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_INVALID_FIELD;
62e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
63e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	strncpy(smp->data, ibdev->node_desc, sizeof(smp->data));
64e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
65e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply(smp);
66e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
67e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
68e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct nodeinfo {
69e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 base_version;
70e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 class_version;
71e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 node_type;
72e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 num_ports;
73e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 sys_guid;
74e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 node_guid;
75e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_guid;
76e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 partition_cap;
77e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 device_id;
78e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 revision;
79e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 local_port_num;
80e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 vendor_id[3];
81e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
82e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
83e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_get_nodeinfo(struct ib_smp *smp,
84e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				  struct ib_device *ibdev, u8 port)
85e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
86e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct nodeinfo *nip = (struct nodeinfo *)&smp->data;
87e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_devdata *dd = to_idev(ibdev)->dd;
88e8a88f09f21c55a7e7f570290ecde570e2c37771Bryan O'Sullivan	u32 vendor, majrev, minrev;
89e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
9011b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan	/* GUID 0 is illegal */
9111b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan	if (smp->attr_mod || (dd->ipath_guid == 0))
92e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_INVALID_FIELD;
93e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
94e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->base_version = 1;
95e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->class_version = 1;
96e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->node_type = 1;	/* channel adapter */
97e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
98e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * XXX The num_ports value will need a layer function to get
99e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * the value if we ever have more than one IB port on a chip.
100e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * We will also need to get the GUID for the port.
101e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
102e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->num_ports = ibdev->phys_port_cnt;
103e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* This is already in network order */
104e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->sys_guid = to_idev(ibdev)->sys_image_guid;
10534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	nip->node_guid = dd->ipath_guid;
106f41d229865c984015914221959675b1c8723f6a7Sean Hefty	nip->port_guid = dd->ipath_guid;
10734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	nip->partition_cap = cpu_to_be16(ipath_get_npkeys(dd));
10834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	nip->device_id = cpu_to_be16(dd->ipath_deviceid);
10934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	majrev = dd->ipath_majrev;
11034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	minrev = dd->ipath_minrev;
111e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->revision = cpu_to_be32((majrev << 16) | minrev);
112e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->local_port_num = port;
11334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	vendor = dd->ipath_vendorid;
114e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->vendor_id[0] = 0;
115e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->vendor_id[1] = vendor >> 8;
116e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	nip->vendor_id[2] = vendor;
117e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
118e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply(smp);
119e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
120e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
121e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_get_guidinfo(struct ib_smp *smp,
122e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				  struct ib_device *ibdev)
123e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
124e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u32 startgx = 8 * be32_to_cpu(smp->attr_mod);
125e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 *p = (__be64 *) smp->data;
126e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
127e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* 32 blocks of 8 64-bit GUIDs per block */
128e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
129e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(smp->data, 0, sizeof(smp->data));
130e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
131e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
132e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * We only support one GUID for now.  If this changes, the
133e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * portinfo.guid_cap field needs to be updated too.
134e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
13511b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan	if (startgx == 0) {
13611b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan		__be64 g = to_idev(ibdev)->dd->ipath_guid;
13711b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan		if (g == 0)
13811b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan			/* GUID 0 is illegal */
13911b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan			smp->status |= IB_SMP_INVALID_FIELD;
14011b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan		else
14111b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan			/* The first is a copy of the read-only HW GUID. */
14211b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan			*p = g;
14311b054fe1d453954449a86de178bb98274bb86efBryan O'Sullivan	} else
144e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_INVALID_FIELD;
145e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
146e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply(smp);
147e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
148e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
149a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbellstatic void set_link_width_enabled(struct ipath_devdata *dd, u32 w)
150a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell{
151a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	(void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_LWID_ENB, w);
152a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell}
153a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell
154a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbellstatic void set_link_speed_enabled(struct ipath_devdata *dd, u32 s)
155a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell{
156a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	(void) dd->ipath_f_set_ib_cfg(dd, IPATH_IB_CFG_SPD_ENB, s);
157a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell}
15834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
15934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int get_overrunthreshold(struct ipath_devdata *dd)
16034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
16134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return (dd->ipath_ibcctrl >>
16234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
16334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
16434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
16534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
16634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
16734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * set_overrunthreshold - set the overrun threshold
16834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
16934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @n: the new threshold
17034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan *
17134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * Note that this will only take effect when the link state changes.
17234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
17334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int set_overrunthreshold(struct ipath_devdata *dd, unsigned n)
17434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
17534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	unsigned v;
17634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
17734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT) &
17834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK;
17934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (v != n) {
18034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		dd->ipath_ibcctrl &=
18134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			~(INFINIPATH_IBCC_OVERRUNTHRESHOLD_MASK <<
18234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			  INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT);
18334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		dd->ipath_ibcctrl |=
18434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			(u64) n << INFINIPATH_IBCC_OVERRUNTHRESHOLD_SHIFT;
18534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
18634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				 dd->ipath_ibcctrl);
18734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
18834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return 0;
18934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
19034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
19134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int get_phyerrthreshold(struct ipath_devdata *dd)
19234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
19334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return (dd->ipath_ibcctrl >>
19434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
19534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
19634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
19734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
19834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
19934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * set_phyerrthreshold - set the physical error threshold
20034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
20134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @n: the new threshold
20234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan *
20334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * Note that this will only take effect when the link state changes.
20434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
20534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int set_phyerrthreshold(struct ipath_devdata *dd, unsigned n)
20634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
20734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	unsigned v;
20834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
20934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	v = (dd->ipath_ibcctrl >> INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT) &
21034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK;
21134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (v != n) {
21234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		dd->ipath_ibcctrl &=
21334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			~(INFINIPATH_IBCC_PHYERRTHRESHOLD_MASK <<
21434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			  INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT);
21534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		dd->ipath_ibcctrl |=
21634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			(u64) n << INFINIPATH_IBCC_PHYERRTHRESHOLD_SHIFT;
21734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
21834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				 dd->ipath_ibcctrl);
21934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
22034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return 0;
22134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
22234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
22334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
22434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * get_linkdowndefaultstate - get the default linkdown state
22534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
22634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan *
22734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * Returns zero if the default is POLL, 1 if the default is SLEEP.
22834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
22934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int get_linkdowndefaultstate(struct ipath_devdata *dd)
23034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
23134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return !!(dd->ipath_ibcctrl & INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE);
23234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
23334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
234e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_get_portinfo(struct ib_smp *smp,
235e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				  struct ib_device *ibdev, u8 port)
236e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
237e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev;
238a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	struct ipath_devdata *dd;
239da2ab62ab5e430e6ffafc2d0e6046dcd2780f570Leonid Arsh	struct ib_port_info *pip = (struct ib_port_info *)smp->data;
240e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u16 lid;
241e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 ibcstat;
242e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 mtu;
243e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int ret;
244e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
245e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt) {
246e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_INVALID_FIELD;
247e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = reply(smp);
248e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
249e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
250e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
251e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev = to_idev(ibdev);
252a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	dd = dev->dd;
253e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
254e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Clear all fields.  Only set the non-zero fields. */
255e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(smp->data, 0, sizeof(smp->data));
256e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
257e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Only return the mkey if the protection field allows it. */
258e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (smp->method == IB_MGMT_METHOD_SET || dev->mkey == smp->mkey ||
259542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	    dev->mkeyprot == 0)
260e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pip->mkey = dev->mkey;
261e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->gid_prefix = dev->gid_prefix;
262a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	lid = dd->ipath_lid;
263e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->lid = lid ? cpu_to_be16(lid) : IB_LID_PERMISSIVE;
264e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->sm_lid = cpu_to_be16(dev->sm_lid);
265e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->cap_mask = cpu_to_be32(dev->port_cap_flags);
266e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* pip->diag_code; */
267e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->mkey_lease_period = cpu_to_be16(dev->mkey_lease_period);
268e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->local_port_num = port;
269a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->link_width_enabled = dd->ipath_link_width_enabled;
270a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->link_width_supported = dd->ipath_link_width_supported;
271a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->link_width_active = dd->ipath_link_width_active;
272a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->linkspeed_portstate = dd->ipath_link_speed_supported << 4;
273a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	ibcstat = dd->ipath_lastibcstat;
274a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	/* map LinkState to IB portinfo values.  */
275a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->linkspeed_portstate |= ipath_ib_linkstate(dd, ibcstat) + 1;
276a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell
277e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->portphysstate_linkdown =
278a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		(ipath_cvt_physportstate[ibcstat & dd->ibcs_lts_mask] << 4) |
279a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		(get_linkdowndefaultstate(dd) ? 1 : 2);
280a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->mkeyprot_resv_lmc = (dev->mkeyprot << 6) | dd->ipath_lmc;
281a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	pip->linkspeedactive_enabled = (dd->ipath_link_speed_active << 4) |
282a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		dd->ipath_link_speed_enabled;
283a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	switch (dd->ipath_ibmtu) {
284e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 4096:
285e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = IB_MTU_4096;
286e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
287e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 2048:
288e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = IB_MTU_2048;
289e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
290e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 1024:
291e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = IB_MTU_1024;
292e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
293e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 512:
294e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = IB_MTU_512;
295e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
296e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 256:
297e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = IB_MTU_256;
298e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
299e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:		/* oops, something is wrong */
300e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = IB_MTU_2048;
301e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
302e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
303e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->neighbormtu_mastersmsl = (mtu << 4) | dev->sm_sl;
304e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->vlcap_inittype = 0x10;	/* VLCap = VL0, InitType = 0 */
305e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->vl_high_limit = dev->vl_high_limit;
306e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* pip->vl_arb_high_cap; // only one VL */
307e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* pip->vl_arb_low_cap; // only one VL */
308e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* InitTypeReply = 0 */
309826d801009fb3c82832f2d92149446cce354bf61Dave Olson	/* our mtu cap depends on whether 4K MTU enabled or not */
310826d801009fb3c82832f2d92149446cce354bf61Dave Olson	pip->inittypereply_mtucap = ipath_mtu4096 ? IB_MTU_4096 : IB_MTU_2048;
311826d801009fb3c82832f2d92149446cce354bf61Dave Olson	/* HCAs ignore VLStallCount and HOQLife */
312e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* pip->vlstallcnt_hoqlife; */
313e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->operationalvl_pei_peo_fpi_fpo = 0x10;	/* OVLs = 1 */
314e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->mkey_violations = cpu_to_be16(dev->mkey_violations);
315e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* P_KeyViolations are counted by hardware. */
316e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->pkey_violations =
317a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		cpu_to_be16((ipath_get_cr_errpkey(dd) -
318443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan			     dev->z_pkey_violations) & 0xFFFF);
319e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->qkey_violations = cpu_to_be16(dev->qkey_violations);
320e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Only the hardware GUID is supported for now */
321e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->guid_cap = 1;
322e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->clientrereg_resv_subnetto = dev->subnet_timeout;
323e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* 32.768 usec. response time (guessing) */
324e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->resv_resptimevalue = 3;
325e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	pip->localphyerrors_overrunerrors =
326a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		(get_phyerrthreshold(dd) << 4) |
327a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		get_overrunthreshold(dd);
328e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* pip->max_credit_hint; */
329a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	if (dev->port_cap_flags & IB_PORT_LINK_LATENCY_SUP) {
330a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		u32 v;
331a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell
332a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		v = dd->ipath_f_get_ib_cfg(dd, IPATH_IB_CFG_LINKLATENCY);
333a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		pip->link_roundtrip_latency[0] = v >> 16;
334a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		pip->link_roundtrip_latency[1] = v >> 8;
335a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		pip->link_roundtrip_latency[2] = v;
336a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	}
337e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
338e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	ret = reply(smp);
339e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
340e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanbail:
341e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
342e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
343e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
34434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
34534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * get_pkeys - return the PKEY table for port 0
34634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
34734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @pkeys: the pkey table is placed here
34834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
34934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int get_pkeys(struct ipath_devdata *dd, u16 * pkeys)
35034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
35134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	struct ipath_portdata *pd = dd->ipath_pd[0];
35234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
35334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	memcpy(pkeys, pd->port_pkeys, sizeof(pd->port_pkeys));
35434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
35534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return 0;
35634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
35734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
358e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_get_pkeytable(struct ib_smp *smp,
359e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				   struct ib_device *ibdev)
360e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
361e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
362e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u16 *p = (u16 *) smp->data;
363e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 *q = (__be16 *) smp->data;
364e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
365e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* 64 blocks of 32 16-bit P_Key entries */
366e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
367e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(smp->data, 0, sizeof(smp->data));
368e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (startpx == 0) {
369e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		struct ipath_ibdev *dev = to_idev(ibdev);
37034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		unsigned i, n = ipath_get_npkeys(dev->dd);
371e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
37234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		get_pkeys(dev->dd, p);
373e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
374e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		for (i = 0; i < n; i++)
375e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			q[i] = cpu_to_be16(p[i]);
376e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	} else
377e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_INVALID_FIELD;
378e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
379e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply(smp);
380e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
381e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
382e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_set_guidinfo(struct ib_smp *smp,
383e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				  struct ib_device *ibdev)
384e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
385e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* The only GUID we support is the first read-only entry. */
386e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return recv_subn_get_guidinfo(smp, ibdev);
387e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
388e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
389e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan/**
39034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * set_linkdowndefaultstate - set the default linkdown state
39134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
39234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @sleep: the new state
39334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan *
39434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * Note that this will only take effect when the link state changes.
39534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
39634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int set_linkdowndefaultstate(struct ipath_devdata *dd, int sleep)
39734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
39834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (sleep)
39934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		dd->ipath_ibcctrl |= INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
40034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	else
40134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		dd->ipath_ibcctrl &= ~INFINIPATH_IBCC_LINKDOWNDEFAULTSTATE;
40234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
40334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			 dd->ipath_ibcctrl);
40434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return 0;
40534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
40634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
40734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
408e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * recv_subn_set_portinfo - set port information
409e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @smp: the incoming SM packet
410e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @ibdev: the infiniband device
411e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @port: the port on the device
412e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
413e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * Set Portinfo (see ch. 14.2.5.6).
414e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan */
415e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_set_portinfo(struct ib_smp *smp,
416e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				  struct ib_device *ibdev, u8 port)
417e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
418da2ab62ab5e430e6ffafc2d0e6046dcd2780f570Leonid Arsh	struct ib_port_info *pip = (struct ib_port_info *)smp->data;
419e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_event event;
420e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev;
421542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	struct ipath_devdata *dd;
422e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	char clientrereg = 0;
423e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u16 lid, smlid;
424e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 lwe;
425e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 lse;
426e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 state;
427e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u16 lstate;
428e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u32 mtu;
42934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int ret, ore;
430e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
431e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (be32_to_cpu(smp->attr_mod) > ibdev->phys_port_cnt)
432e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
433e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
434e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev = to_idev(ibdev);
435542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	dd = dev->dd;
436e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	event.device = ibdev;
437e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	event.element.port_num = port;
438e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
439e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev->mkey = pip->mkey;
440e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev->gid_prefix = pip->gid_prefix;
441e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev->mkey_lease_period = be16_to_cpu(pip->mkey_lease_period);
442e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
443e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	lid = be16_to_cpu(pip->lid);
444542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	if (dd->ipath_lid != lid ||
445542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	    dd->ipath_lmc != (pip->mkeyprot_resv_lmc & 7)) {
446e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* Must be a valid unicast LID address. */
44727b678dd04a636f2c351816f4b3042c8815d4e9dBryan O'Sullivan		if (lid == 0 || lid >= IPATH_MULTICAST_LID_BASE)
448e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto err;
449542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		ipath_set_lid(dd, lid, pip->mkeyprot_resv_lmc & 7);
450e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		event.event = IB_EVENT_LID_CHANGE;
451e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ib_dispatch_event(&event);
452e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
453e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
454e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	smlid = be16_to_cpu(pip->sm_lid);
455e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (smlid != dev->sm_lid) {
456e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* Must be a valid unicast LID address. */
45727b678dd04a636f2c351816f4b3042c8815d4e9dBryan O'Sullivan		if (smlid == 0 || smlid >= IPATH_MULTICAST_LID_BASE)
458e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto err;
459e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->sm_lid = smlid;
460e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		event.event = IB_EVENT_SM_CHANGE;
461e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ib_dispatch_event(&event);
462e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
463e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
464a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	/* Allow 1x or 4x to be set (see 14.2.6.6). */
465e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	lwe = pip->link_width_enabled;
466a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	if (lwe) {
467a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		if (lwe == 0xFF)
468a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell			lwe = dd->ipath_link_width_supported;
469a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		else if (lwe >= 16 || (lwe & ~dd->ipath_link_width_supported))
470a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell			goto err;
471a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		set_link_width_enabled(dd, lwe);
472a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	}
473e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
474a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	/* Allow 2.5 or 5.0 Gbs. */
475e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	lse = pip->linkspeedactive_enabled & 0xF;
476a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	if (lse) {
477a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		if (lse == 15)
478a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell			lse = dd->ipath_link_speed_supported;
479a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		else if (lse >= 8 || (lse & ~dd->ipath_link_speed_supported))
480a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell			goto err;
481a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		set_link_speed_enabled(dd, lse);
482a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	}
483e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
484e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Set link down default state. */
485e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch (pip->portphysstate_linkdown & 0xF) {
486e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 0: /* NOP */
487e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
488e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 1: /* SLEEP */
489542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		if (set_linkdowndefaultstate(dd, 1))
490e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto err;
491e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
492e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case 2: /* POLL */
493542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		if (set_linkdowndefaultstate(dd, 0))
494e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto err;
495e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
496e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
497e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
498e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
499e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
500542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	dev->mkeyprot = pip->mkeyprot_resv_lmc >> 6;
501e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev->vl_high_limit = pip->vl_high_limit;
502e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
503e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch ((pip->neighbormtu_mastersmsl >> 4) & 0xF) {
504e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MTU_256:
505e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = 256;
506e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
507e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MTU_512:
508e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = 512;
509e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
510e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MTU_1024:
511e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = 1024;
512e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
513e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MTU_2048:
514e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = 2048;
515e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
516e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MTU_4096:
517826d801009fb3c82832f2d92149446cce354bf61Dave Olson		if (!ipath_mtu4096)
518826d801009fb3c82832f2d92149446cce354bf61Dave Olson			goto err;
519e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		mtu = 4096;
520e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
521e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
522e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* XXX We have already partially updated our state! */
523e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
524e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
525542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	ipath_set_mtu(dd, mtu);
526e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
527e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev->sm_sl = pip->neighbormtu_mastersmsl & 0xF;
528e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
529e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* We only support VL0 */
530e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (((pip->operationalvl_pei_peo_fpi_fpo >> 4) & 0xF) > 1)
531e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
532e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
533e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pip->mkey_violations == 0)
534e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->mkey_violations = 0;
535e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
536e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
537e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Hardware counter can't be reset so snapshot and subtract
538e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * later.
539e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
540e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pip->pkey_violations == 0)
541542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		dev->z_pkey_violations = ipath_get_cr_errpkey(dd);
542e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
543e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pip->qkey_violations == 0)
544e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->qkey_violations = 0;
545e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
54634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ore = pip->localphyerrors_overrunerrors;
547542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	if (set_phyerrthreshold(dd, (ore >> 4) & 0xF))
548e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
549e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
550542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	if (set_overrunthreshold(dd, (ore & 0xF)))
551e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
552e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
553e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	dev->subnet_timeout = pip->clientrereg_resv_subnetto & 0x1F;
554e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
555e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pip->clientrereg_resv_subnetto & 0x80) {
556e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		clientrereg = 1;
5576eddb5cb906ac5c9a17a1b76464eadacd88b6c92Roland Dreier		event.event = IB_EVENT_CLIENT_REREGISTER;
558e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ib_dispatch_event(&event);
559e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
560e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
561e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
562e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Do the port state change now that the other link parameters
563e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * have been set.
564e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Changing the port physical state only makes sense if the link
565e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * is down or is being set to down.
566e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
567e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	state = pip->linkspeed_portstate & 0xF;
568e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	lstate = (pip->portphysstate_linkdown >> 4) & 0xF;
569e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (lstate && !(state == IB_PORT_DOWN || state == IB_PORT_NOP))
570e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
571e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
572e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
573e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Only state changes of DOWN, ARM, and ACTIVE are valid
574e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * and must be in the correct state to take effect (see 7.2.6).
575e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
576e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch (state) {
577e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PORT_NOP:
578e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		if (lstate == 0)
579e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			break;
580e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* FALLTHROUGH */
581e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PORT_DOWN:
582e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		if (lstate == 0)
583140277e9a710202608914b5b731948d2769399bcRalph Campbell			lstate = IPATH_IB_LINKDOWN_ONLY;
584e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		else if (lstate == 1)
585e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			lstate = IPATH_IB_LINKDOWN_SLEEP;
586e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		else if (lstate == 2)
587e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			lstate = IPATH_IB_LINKDOWN;
588e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		else if (lstate == 3)
589e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			lstate = IPATH_IB_LINKDOWN_DISABLE;
590e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		else
591e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto err;
592542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		ipath_set_linkstate(dd, lstate);
5934330e4dad780467d930b394b5119c0218a1e2dbeMichael Albaugh		if (lstate == IPATH_IB_LINKDOWN_DISABLE) {
5944330e4dad780467d930b394b5119c0218a1e2dbeMichael Albaugh			ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
5954330e4dad780467d930b394b5119c0218a1e2dbeMichael Albaugh			goto done;
5964330e4dad780467d930b394b5119c0218a1e2dbeMichael Albaugh		}
597140277e9a710202608914b5b731948d2769399bcRalph Campbell		ipath_wait_linkstate(dd, IPATH_LINKINIT | IPATH_LINKARMED |
598140277e9a710202608914b5b731948d2769399bcRalph Campbell				IPATH_LINKACTIVE, 1000);
599e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
600e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PORT_ARMED:
601542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		ipath_set_linkstate(dd, IPATH_IB_LINKARM);
602e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
603e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PORT_ACTIVE:
604542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		ipath_set_linkstate(dd, IPATH_IB_LINKACTIVE);
605e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
606e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
607e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* XXX We have already partially updated our state! */
608e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto err;
609e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
610e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
611e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	ret = recv_subn_get_portinfo(smp, ibdev, port);
612e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
613e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (clientrereg)
614e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pip->clientrereg_resv_subnetto |= 0x80;
615e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
616e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	goto done;
617e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
618e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanerr:
619e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	smp->status |= IB_SMP_INVALID_FIELD;
620e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	ret = recv_subn_get_portinfo(smp, ibdev, port);
621e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
622e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivandone:
623e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
624e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
625e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
62634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
62734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * rm_pkey - decrecment the reference count for the given PKEY
62834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
62934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @key: the PKEY index
63034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan *
63134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * Return true if this was the last reference and the hardware table entry
63234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * needs to be changed.
63334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
63434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int rm_pkey(struct ipath_devdata *dd, u16 key)
63534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
63634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int i;
63734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int ret;
63834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
63934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
64034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (dd->ipath_pkeys[i] != key)
64134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			continue;
64234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (atomic_dec_and_test(&dd->ipath_pkeyrefs[i])) {
64334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			dd->ipath_pkeys[i] = 0;
64434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			ret = 1;
64534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			goto bail;
64634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		}
64734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		break;
64834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
64934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
65034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ret = 0;
65134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
65234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanbail:
65334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return ret;
65434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
65534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
65634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
65734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * add_pkey - add the given PKEY to the hardware table
65834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
65934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @key: the PKEY
66034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan *
66134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * Return an error code if unable to add the entry, zero if no change,
66234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * or 1 if the hardware PKEY register needs to be updated.
66334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
66434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int add_pkey(struct ipath_devdata *dd, u16 key)
66534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
66634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int i;
66734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	u16 lkey = key & 0x7FFF;
66834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int any = 0;
66934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int ret;
67034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
67134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (lkey == 0x7FFF) {
67234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		ret = 0;
67334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		goto bail;
67434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
67534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
67634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	/* Look for an empty slot or a matching PKEY. */
67734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
67834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (!dd->ipath_pkeys[i]) {
67934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			any++;
68034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			continue;
68134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		}
68234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		/* If it matches exactly, try to increment the ref count */
68334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (dd->ipath_pkeys[i] == key) {
68434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			if (atomic_inc_return(&dd->ipath_pkeyrefs[i]) > 1) {
68534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				ret = 0;
68634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				goto bail;
68734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			}
68834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			/* Lost the race. Look for an empty slot below. */
68934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			atomic_dec(&dd->ipath_pkeyrefs[i]);
69034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			any++;
69134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		}
69234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		/*
69334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 * It makes no sense to have both the limited and unlimited
69434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 * PKEY set at the same time since the unlimited one will
69534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 * disable the limited one.
69634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 */
69734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if ((dd->ipath_pkeys[i] & 0x7FFF) == lkey) {
69834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			ret = -EEXIST;
69934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			goto bail;
70034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		}
70134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
70234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (!any) {
70334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		ret = -EBUSY;
70434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		goto bail;
70534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
70634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	for (i = 0; i < ARRAY_SIZE(dd->ipath_pkeys); i++) {
70734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (!dd->ipath_pkeys[i] &&
70834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		    atomic_inc_return(&dd->ipath_pkeyrefs[i]) == 1) {
70934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			/* for ipathstats, etc. */
71034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			ipath_stats.sps_pkeys[i] = lkey;
71134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			dd->ipath_pkeys[i] = key;
71234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			ret = 1;
71334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			goto bail;
71434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		}
71534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
71634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ret = -EBUSY;
71734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
71834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanbail:
71934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return ret;
72034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
72134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
72234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan/**
72334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * set_pkeys - set the PKEY table for port 0
72434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @dd: the infinipath device
72534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan * @pkeys: the PKEY table
72634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan */
72734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivanstatic int set_pkeys(struct ipath_devdata *dd, u16 *pkeys)
72834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan{
72934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	struct ipath_portdata *pd;
73034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int i;
73134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	int changed = 0;
73234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
73334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	pd = dd->ipath_pd[0];
73434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
73534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	for (i = 0; i < ARRAY_SIZE(pd->port_pkeys); i++) {
73634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		u16 key = pkeys[i];
73734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		u16 okey = pd->port_pkeys[i];
73834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
73934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (key == okey)
74034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			continue;
74134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		/*
74234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 * The value of this PKEY table entry is changing.
74334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 * Remove the old entry in the hardware's array of PKEYs.
74434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		 */
74534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (okey & 0x7FFF)
74634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			changed |= rm_pkey(dd, okey);
74734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		if (key & 0x7FFF) {
74834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			int ret = add_pkey(dd, key);
74934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
75034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			if (ret < 0)
75134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				key = 0;
75234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			else
75334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				changed |= ret;
75434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		}
75534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		pd->port_pkeys[i] = key;
75634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
75734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (changed) {
75834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		u64 pkey;
75934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
76034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		pkey = (u64) dd->ipath_pkeys[0] |
76134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			((u64) dd->ipath_pkeys[1] << 16) |
76234b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			((u64) dd->ipath_pkeys[2] << 32) |
76334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			((u64) dd->ipath_pkeys[3] << 48);
76434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		ipath_cdbg(VERBOSE, "p0 new pkey reg %llx\n",
76534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan			   (unsigned long long) pkey);
76634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan		ipath_write_kreg(dd, dd->ipath_kregs->kr_partitionkey,
76734b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				 pkey);
76834b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	}
76934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	return 0;
77034b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan}
77134b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan
772e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_subn_set_pkeytable(struct ib_smp *smp,
773e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				   struct ib_device *ibdev)
774e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
775e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u32 startpx = 32 * (be32_to_cpu(smp->attr_mod) & 0xffff);
776e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 *p = (__be16 *) smp->data;
777e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u16 *q = (u16 *) smp->data;
778e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
77934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	unsigned i, n = ipath_get_npkeys(dev->dd);
780e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
781e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	for (i = 0; i < n; i++)
782e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		q[i] = be16_to_cpu(p[i]);
783e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
78434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	if (startpx != 0 || set_pkeys(dev->dd, q) != 0)
785e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_INVALID_FIELD;
786e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
787e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return recv_subn_get_pkeytable(smp, ibdev);
788e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
789e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
790e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_CLASS_PORT_INFO		__constant_htons(0x0001)
791e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_PORT_SAMPLES_CONTROL	__constant_htons(0x0010)
792e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_PORT_SAMPLES_RESULT	__constant_htons(0x0011)
793e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_PORT_COUNTERS		__constant_htons(0x0012)
794e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_PORT_COUNTERS_EXT	__constant_htons(0x001D)
795e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_PORT_SAMPLES_RESULT_EXT	__constant_htons(0x001E)
796e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
797e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_perf {
798e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 base_version;
799e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 mgmt_class;
800e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 class_version;
801e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 method;
802e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 status;
803e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 unused;
804e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 tid;
805e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 attr_id;
806e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 resv;
807e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 attr_mod;
808e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 reserved[40];
809e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 data[192];
810e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
811e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
812e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_pma_classportinfo {
813e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 base_version;
814e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 class_version;
815e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 cap_mask;
816e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 reserved[3];
817e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 resp_time_value;	/* only lower 5 bits */
818e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	union ib_gid redirect_gid;
819e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 redirect_tc_sl_fl;	/* 8, 4, 20 bits respectively */
820e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 redirect_lid;
821e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 redirect_pkey;
822e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 redirect_qp;	/* only lower 24 bits */
823e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 redirect_qkey;
824e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	union ib_gid trap_gid;
825e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 trap_tc_sl_fl;	/* 8, 4, 20 bits respectively */
826e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 trap_lid;
827e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 trap_pkey;
828e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 trap_hl_qp;	/* 8, 24 bits respectively */
829e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 trap_qkey;
830e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
831e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
832e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_pma_portsamplescontrol {
833e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 opcode;
834e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_select;
835e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 tick;
836e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 counter_width;	/* only lower 3 bits */
837e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 counter_mask0_9;	/* 2, 10 * 3, bits */
838e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 counter_mask10_14;	/* 1, 5 * 3, bits */
839e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 sample_mechanisms;
840e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 sample_status;	/* only lower 2 bits */
841e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 option_mask;
842e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 vendor_mask;
843e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 sample_start;
844e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 sample_interval;
845e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 tag;
846e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 counter_select[15];
847e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
848e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
849e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_pma_portsamplesresult {
850e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 tag;
851e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 sample_status;	/* only lower 2 bits */
852e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 counter[15];
853e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
854e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
855e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_pma_portsamplesresult_ext {
856e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 tag;
857e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 sample_status;	/* only lower 2 bits */
858e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 extended_width;	/* only upper 2 bits */
859e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 counter[15];
860e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
861e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
862e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_pma_portcounters {
863e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 reserved;
864e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_select;
865e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 counter_select;
866e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 symbol_error_counter;
867e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 link_error_recovery_counter;
868e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 link_downed_counter;
869e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 port_rcv_errors;
870e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 port_rcv_remphys_errors;
871e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 port_rcv_switch_relay_errors;
872e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 port_xmit_discards;
873e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_xmit_constraint_errors;
874e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_rcv_constraint_errors;
875e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 reserved1;
876e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 lli_ebor_errors;	/* 4, 4, bits */
877e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 reserved2;
878e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 vl15_dropped;
879e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 port_xmit_data;
880e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 port_rcv_data;
881e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 port_xmit_packets;
882e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 port_rcv_packets;
883e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
884e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
885e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_SYMBOL_ERROR			__constant_htons(0x0001)
886e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_LINK_ERROR_RECOVERY		__constant_htons(0x0002)
887e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_LINK_DOWNED			__constant_htons(0x0004)
888e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_RCV_ERRORS		__constant_htons(0x0008)
889e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS	__constant_htons(0x0010)
890e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_XMIT_DISCARDS		__constant_htons(0x0040)
891fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan#define IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS	__constant_htons(0x0200)
892fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan#define IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS	__constant_htons(0x0400)
893fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan#define IB_PMA_SEL_PORT_VL15_DROPPED		__constant_htons(0x0800)
894e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_XMIT_DATA		__constant_htons(0x1000)
895e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_RCV_DATA		__constant_htons(0x2000)
896e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_XMIT_PACKETS		__constant_htons(0x4000)
897e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SEL_PORT_RCV_PACKETS		__constant_htons(0x8000)
898e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
899e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstruct ib_pma_portcounters_ext {
900e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 reserved;
901e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_select;
902e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be16 counter_select;
903e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be32 reserved1;
904e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_xmit_data;
905e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_rcv_data;
906e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_xmit_packets;
907e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_rcv_packets;
908e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_unicast_xmit_packets;
909e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_unicast_rcv_packets;
910e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_multicast_xmit_packets;
911e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__be64 port_multicast_rcv_packets;
912e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan} __attribute__ ((packed));
913e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
914e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_XMIT_DATA		__constant_htons(0x0001)
915e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_RCV_DATA		__constant_htons(0x0002)
916e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_XMIT_PACKETS		__constant_htons(0x0004)
917e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_RCV_PACKETS		__constant_htons(0x0008)
918e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_UNI_XMIT_PACKETS	__constant_htons(0x0010)
919e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_UNI_RCV_PACKETS	__constant_htons(0x0020)
920e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS	__constant_htons(0x0040)
921e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define IB_PMA_SELX_PORT_MULTI_RCV_PACKETS	__constant_htons(0x0080)
922e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
923e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_get_classportinfo(struct ib_perf *pmp)
924e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
925e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_classportinfo *p =
926e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		(struct ib_pma_classportinfo *)pmp->data;
927e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
928e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(pmp->data, 0, sizeof(pmp->data));
929e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
930e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pmp->attr_mod != 0)
931e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_INVALID_FIELD;
932e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
933e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Indicate AllPortSelect is valid (only one port anyway) */
934e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->cap_mask = __constant_cpu_to_be16(1 << 8);
935e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->base_version = 1;
936e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->class_version = 1;
937e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
938e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Expected response time is 4.096 usec. * 2^18 == 1.073741824
939e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * sec.
940e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
941e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->resp_time_value = 18;
942e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
943e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply((struct ib_smp *) pmp);
944e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
945e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
946e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan/*
947e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * The PortSamplesControl.CounterMasks field is an array of 3 bit fields
948e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * which specify the N'th counter's capabilities. See ch. 16.1.3.2.
949e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * We support 5 counters which only count the mandatory quantities.
950e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan */
951e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define COUNTER_MASK(q, n) (q << ((9 - n) * 3))
952e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan#define COUNTER_MASK0_9 \
953e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	__constant_cpu_to_be32(COUNTER_MASK(1, 0) | \
954e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			       COUNTER_MASK(1, 1) | \
955e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			       COUNTER_MASK(1, 2) | \
956e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			       COUNTER_MASK(1, 3) | \
957e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			       COUNTER_MASK(1, 4))
958e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
959e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_get_portsamplescontrol(struct ib_perf *pmp,
960e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					   struct ib_device *ibdev, u8 port)
961e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
962e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portsamplescontrol *p =
963e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		(struct ib_pma_portsamplescontrol *)pmp->data;
964e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
9656c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
966e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	unsigned long flags;
967e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_select = p->port_select;
968e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
969e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(pmp->data, 0, sizeof(pmp->data));
970e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
971e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_select = port_select;
972e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pmp->attr_mod != 0 ||
973e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	    (port_select != port && port_select != 0xFF))
974e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_INVALID_FIELD;
975e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
976e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Ticks are 10x the link transfer period which for 2.5Gbs is 4
977e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * nsec.  0 == 4 nsec., 1 == 8 nsec., ..., 255 == 1020 nsec.  Sample
978e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * intervals are counted in ticks.  Since we use Linux timers, that
979e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * count in jiffies, we can't sample for less than 1000 ticks if HZ
980a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	 * == 1000 (4000 ticks if HZ is 250).  link_speed_active returns 2 for
981a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	 * DDR, 1 for SDR, set the tick to 1 for DDR, 0 for SDR on chips that
982a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	 * have hardware support for delaying packets.
983e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
984a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	if (crp->cr_psstat)
985a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		p->tick = dev->dd->ipath_link_speed_active - 1;
986a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell	else
987a51a2513a8cb201f02d83c37e106909938d2f761Ralph Campbell		p->tick = 250;		/* 1 usec. */
988e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_width = 4;	/* 32 bit counters */
989e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_mask0_9 = COUNTER_MASK0_9;
990e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	spin_lock_irqsave(&dev->pending_lock, flags);
9916c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (crp->cr_psstat)
9926c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		p->sample_status = ipath_read_creg32(dev->dd, crp->cr_psstat);
9936c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	else
9946c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		p->sample_status = dev->pma_sample_status;
995e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->sample_start = cpu_to_be32(dev->pma_sample_start);
996e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->sample_interval = cpu_to_be32(dev->pma_sample_interval);
997e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->tag = cpu_to_be16(dev->pma_tag);
998e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_select[0] = dev->pma_counter_select[0];
999e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_select[1] = dev->pma_counter_select[1];
1000e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_select[2] = dev->pma_counter_select[2];
1001e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_select[3] = dev->pma_counter_select[3];
1002e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->counter_select[4] = dev->pma_counter_select[4];
1003e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	spin_unlock_irqrestore(&dev->pending_lock, flags);
1004e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1005e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply((struct ib_smp *) pmp);
1006e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1007e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1008e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_set_portsamplescontrol(struct ib_perf *pmp,
1009e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					   struct ib_device *ibdev, u8 port)
1010e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1011e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portsamplescontrol *p =
1012e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		(struct ib_pma_portsamplescontrol *)pmp->data;
1013e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
10146c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
1015e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	unsigned long flags;
10166c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	u8 status;
1017e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int ret;
1018e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1019e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pmp->attr_mod != 0 ||
1020e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	    (p->port_select != port && p->port_select != 0xFF)) {
1021e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_INVALID_FIELD;
1022e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = reply((struct ib_smp *) pmp);
1023e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1024e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1025e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
10266c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	spin_lock_irqsave(&dev->pending_lock, flags);
10276c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (crp->cr_psstat)
10286c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
10296c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	else
10306c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		status = dev->pma_sample_status;
10316c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (status == IB_PMA_SAMPLE_STATUS_DONE) {
10326c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_sample_start = be32_to_cpu(p->sample_start);
10336c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_sample_interval = be32_to_cpu(p->sample_interval);
10346c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_tag = be16_to_cpu(p->tag);
10356c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_counter_select[0] = p->counter_select[0];
10366c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_counter_select[1] = p->counter_select[1];
10376c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_counter_select[2] = p->counter_select[2];
10386c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_counter_select[3] = p->counter_select[3];
10396c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->pma_counter_select[4] = p->counter_select[4];
10406c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		if (crp->cr_psstat) {
10416c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_write_creg(dev->dd, crp->cr_psinterval,
10426c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell					 dev->pma_sample_interval);
10436c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_write_creg(dev->dd, crp->cr_psstart,
10446c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell					 dev->pma_sample_start);
10456c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		} else
10466c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			dev->pma_sample_status = IB_PMA_SAMPLE_STATUS_STARTED;
1047e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
10486c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	spin_unlock_irqrestore(&dev->pending_lock, flags);
10496c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell
1050e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	ret = recv_pma_get_portsamplescontrol(pmp, ibdev, port);
1051e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1052e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanbail:
1053e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
1054e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1055e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
10566c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbellstatic u64 get_counter(struct ipath_ibdev *dev,
10576c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		       struct ipath_cregs const *crp,
10586c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		       __be16 sel)
1059e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1060e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u64 ret;
1061e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1062e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch (sel) {
1063e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PMA_PORT_XMIT_DATA:
10646c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		ret = (crp->cr_psxmitdatacount) ?
10656c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_read_creg32(dev->dd, crp->cr_psxmitdatacount) :
10666c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			dev->ipath_sword;
1067e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
1068e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PMA_PORT_RCV_DATA:
10696c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		ret = (crp->cr_psrcvdatacount) ?
10706c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_read_creg32(dev->dd, crp->cr_psrcvdatacount) :
10716c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			dev->ipath_rword;
1072e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
1073e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PMA_PORT_XMIT_PKTS:
10746c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		ret = (crp->cr_psxmitpktscount) ?
10756c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_read_creg32(dev->dd, crp->cr_psxmitpktscount) :
10766c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			dev->ipath_spkts;
1077e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
1078e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PMA_PORT_RCV_PKTS:
10796c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		ret = (crp->cr_psrcvpktscount) ?
10806c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_read_creg32(dev->dd, crp->cr_psrcvpktscount) :
10816c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			dev->ipath_rpkts;
1082e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
1083e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_PMA_PORT_XMIT_WAIT:
10846c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		ret = (crp->cr_psxmitwaitcount) ?
10856c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			ipath_read_creg32(dev->dd, crp->cr_psxmitwaitcount) :
10866c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			dev->ipath_xmit_wait;
1087e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		break;
1088e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
1089e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = 0;
1090e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1091e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1092e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
1093e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1094e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1095e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_get_portsamplesresult(struct ib_perf *pmp,
1096e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					  struct ib_device *ibdev)
1097e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1098e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portsamplesresult *p =
1099e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		(struct ib_pma_portsamplesresult *)pmp->data;
1100e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
11016c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
11026c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	u8 status;
1103e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int i;
1104e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1105e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(pmp->data, 0, sizeof(pmp->data));
1106e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->tag = cpu_to_be16(dev->pma_tag);
11076c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (crp->cr_psstat)
11086c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
11096c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	else
11106c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		status = dev->pma_sample_status;
11116c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	p->sample_status = cpu_to_be16(status);
1112e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
11136c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
11146c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		    cpu_to_be32(
11156c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			get_counter(dev, crp, dev->pma_counter_select[i]));
1116e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1117e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply((struct ib_smp *) pmp);
1118e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1119e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1120e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_get_portsamplesresult_ext(struct ib_perf *pmp,
1121e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					      struct ib_device *ibdev)
1122e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1123e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portsamplesresult_ext *p =
1124e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		(struct ib_pma_portsamplesresult_ext *)pmp->data;
1125e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
11266c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	struct ipath_cregs const *crp = dev->dd->ipath_cregs;
11276c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	u8 status;
1128e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int i;
1129e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1130e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(pmp->data, 0, sizeof(pmp->data));
1131e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->tag = cpu_to_be16(dev->pma_tag);
11326c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (crp->cr_psstat)
11336c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		status = ipath_read_creg32(dev->dd, crp->cr_psstat);
11346c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	else
11356c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		status = dev->pma_sample_status;
11366c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	p->sample_status = cpu_to_be16(status);
1137e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* 64 bits */
1138e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->extended_width = __constant_cpu_to_be32(0x80000000);
1139e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	for (i = 0; i < ARRAY_SIZE(dev->pma_counter_select); i++)
11406c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		p->counter[i] = (status != IB_PMA_SAMPLE_STATUS_DONE) ? 0 :
11416c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		    cpu_to_be64(
11426c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell			get_counter(dev, crp, dev->pma_counter_select[i]));
1143e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1144e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply((struct ib_smp *) pmp);
1145e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1146e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1147e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_get_portcounters(struct ib_perf *pmp,
1148e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				     struct ib_device *ibdev, u8 port)
1149e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1150e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
1151e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->data;
1152e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
115334b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	struct ipath_verbs_counters cntrs;
1154e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_select = p->port_select;
1155e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
115634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ipath_get_counters(dev->dd, &cntrs);
1157e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1158e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Adjust counters for any resets done. */
1159443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.symbol_error_counter -= dev->z_symbol_error_counter;
1160e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	cntrs.link_error_recovery_counter -=
1161443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_link_error_recovery_counter;
1162443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.link_downed_counter -= dev->z_link_downed_counter;
1163e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	cntrs.port_rcv_errors += dev->rcv_errors;
1164443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_rcv_errors -= dev->z_port_rcv_errors;
1165443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_rcv_remphys_errors -= dev->z_port_rcv_remphys_errors;
1166443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_xmit_discards -= dev->z_port_xmit_discards;
1167443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_xmit_data -= dev->z_port_xmit_data;
1168443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_rcv_data -= dev->z_port_rcv_data;
1169443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_xmit_packets -= dev->z_port_xmit_packets;
1170443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	cntrs.port_rcv_packets -= dev->z_port_rcv_packets;
1171fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	cntrs.local_link_integrity_errors -=
1172fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		dev->z_local_link_integrity_errors;
1173fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	cntrs.excessive_buffer_overrun_errors -=
1174fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		dev->z_excessive_buffer_overrun_errors;
11756c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	cntrs.vl15_dropped -= dev->z_vl15_dropped;
11766c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	cntrs.vl15_dropped += dev->n_vl15_dropped;
1177e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1178e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(pmp->data, 0, sizeof(pmp->data));
1179e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1180e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_select = port_select;
1181e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pmp->attr_mod != 0 ||
1182e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	    (port_select != port && port_select != 0xFF))
1183e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_INVALID_FIELD;
1184e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1185e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.symbol_error_counter > 0xFFFFUL)
1186e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->symbol_error_counter = __constant_cpu_to_be16(0xFFFF);
1187e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1188e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->symbol_error_counter =
1189e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cpu_to_be16((u16)cntrs.symbol_error_counter);
1190e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.link_error_recovery_counter > 0xFFUL)
1191e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->link_error_recovery_counter = 0xFF;
1192e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1193e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->link_error_recovery_counter =
1194e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			(u8)cntrs.link_error_recovery_counter;
1195e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.link_downed_counter > 0xFFUL)
1196e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->link_downed_counter = 0xFF;
1197e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1198e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->link_downed_counter = (u8)cntrs.link_downed_counter;
1199e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_rcv_errors > 0xFFFFUL)
1200e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_errors = __constant_cpu_to_be16(0xFFFF);
1201e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1202e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_errors =
1203e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cpu_to_be16((u16) cntrs.port_rcv_errors);
1204e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_rcv_remphys_errors > 0xFFFFUL)
1205e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_remphys_errors = __constant_cpu_to_be16(0xFFFF);
1206e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1207e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_remphys_errors =
1208e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cpu_to_be16((u16)cntrs.port_rcv_remphys_errors);
1209e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_xmit_discards > 0xFFFFUL)
1210e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_xmit_discards = __constant_cpu_to_be16(0xFFFF);
1211e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1212e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_xmit_discards =
1213e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cpu_to_be16((u16)cntrs.port_xmit_discards);
1214fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	if (cntrs.local_link_integrity_errors > 0xFUL)
1215fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		cntrs.local_link_integrity_errors = 0xFUL;
1216fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	if (cntrs.excessive_buffer_overrun_errors > 0xFUL)
1217fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		cntrs.excessive_buffer_overrun_errors = 0xFUL;
1218fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	p->lli_ebor_errors = (cntrs.local_link_integrity_errors << 4) |
1219fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		cntrs.excessive_buffer_overrun_errors;
12206c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (cntrs.vl15_dropped > 0xFFFFUL)
1221fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		p->vl15_dropped = __constant_cpu_to_be16(0xFFFF);
1222fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	else
12236c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		p->vl15_dropped = cpu_to_be16((u16)cntrs.vl15_dropped);
1224e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_xmit_data > 0xFFFFFFFFUL)
1225e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_xmit_data = __constant_cpu_to_be32(0xFFFFFFFF);
1226e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1227e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_xmit_data = cpu_to_be32((u32)cntrs.port_xmit_data);
1228e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_rcv_data > 0xFFFFFFFFUL)
1229e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_data = __constant_cpu_to_be32(0xFFFFFFFF);
1230e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1231e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_data = cpu_to_be32((u32)cntrs.port_rcv_data);
1232e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_xmit_packets > 0xFFFFFFFFUL)
1233e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_xmit_packets = __constant_cpu_to_be32(0xFFFFFFFF);
1234e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1235e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_xmit_packets =
1236e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cpu_to_be32((u32)cntrs.port_xmit_packets);
1237e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (cntrs.port_rcv_packets > 0xFFFFFFFFUL)
1238e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_packets = __constant_cpu_to_be32(0xFFFFFFFF);
1239e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	else
1240e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		p->port_rcv_packets =
1241e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cpu_to_be32((u32) cntrs.port_rcv_packets);
1242e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1243e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply((struct ib_smp *) pmp);
1244e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1245e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1246e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_get_portcounters_ext(struct ib_perf *pmp,
1247e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					 struct ib_device *ibdev, u8 port)
1248e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1249e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portcounters_ext *p =
1250e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		(struct ib_pma_portcounters_ext *)pmp->data;
1251e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
1252e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u64 swords, rwords, spkts, rpkts, xwait;
1253e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u8 port_select = p->port_select;
1254e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
125534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ipath_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
125634b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				&rpkts, &xwait);
1257e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1258e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Adjust counters for any resets done. */
1259443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	swords -= dev->z_port_xmit_data;
1260443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	rwords -= dev->z_port_rcv_data;
1261443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	spkts -= dev->z_port_xmit_packets;
1262443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan	rpkts -= dev->z_port_rcv_packets;
1263e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1264e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	memset(pmp->data, 0, sizeof(pmp->data));
1265e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1266e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_select = port_select;
1267e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pmp->attr_mod != 0 ||
1268e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	    (port_select != port && port_select != 0xFF))
1269e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_INVALID_FIELD;
1270e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1271e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_xmit_data = cpu_to_be64(swords);
1272e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_rcv_data = cpu_to_be64(rwords);
1273e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_xmit_packets = cpu_to_be64(spkts);
1274e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_rcv_packets = cpu_to_be64(rpkts);
1275e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_unicast_xmit_packets = cpu_to_be64(dev->n_unicast_xmit);
1276e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_unicast_rcv_packets = cpu_to_be64(dev->n_unicast_rcv);
1277e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_multicast_xmit_packets = cpu_to_be64(dev->n_multicast_xmit);
1278e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	p->port_multicast_rcv_packets = cpu_to_be64(dev->n_multicast_rcv);
1279e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1280e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return reply((struct ib_smp *) pmp);
1281e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1282e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1283e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_set_portcounters(struct ib_perf *pmp,
1284e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				     struct ib_device *ibdev, u8 port)
1285e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1286e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
1287e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->data;
1288e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
128934b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	struct ipath_verbs_counters cntrs;
1290e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1291e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
1292e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Since the HW doesn't support clearing counters, we save the
1293e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * current count and subtract it from future responses.
1294e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
129534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ipath_get_counters(dev->dd, &cntrs);
1296e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1297e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_SYMBOL_ERROR)
1298443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_symbol_error_counter = cntrs.symbol_error_counter;
1299e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1300e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_LINK_ERROR_RECOVERY)
1301443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_link_error_recovery_counter =
1302e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cntrs.link_error_recovery_counter;
1303e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1304e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_LINK_DOWNED)
1305443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_link_downed_counter = cntrs.link_downed_counter;
1306e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1307e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_RCV_ERRORS)
1308443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_rcv_errors =
1309e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cntrs.port_rcv_errors + dev->rcv_errors;
1310e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1311e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_RCV_REMPHYS_ERRORS)
1312443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_rcv_remphys_errors =
1313e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			cntrs.port_rcv_remphys_errors;
1314e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1315e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DISCARDS)
1316443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_xmit_discards = cntrs.port_xmit_discards;
1317e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1318fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_LOCAL_LINK_INTEGRITY_ERRORS)
1319fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		dev->z_local_link_integrity_errors =
1320fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan			cntrs.local_link_integrity_errors;
1321fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan
1322fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_EXCESSIVE_BUFFER_OVERRUNS)
1323fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		dev->z_excessive_buffer_overrun_errors =
1324fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan			cntrs.excessive_buffer_overrun_errors;
1325fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan
13266c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	if (p->counter_select & IB_PMA_SEL_PORT_VL15_DROPPED) {
1327fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan		dev->n_vl15_dropped = 0;
13286c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell		dev->z_vl15_dropped = cntrs.vl15_dropped;
13296c719cae0b91f577738dfb4007baee28f03e48a5Ralph Campbell	}
1330fba75200ad92892bf32d8d6f1443c6f1e4f48676Bryan O'Sullivan
1331e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_DATA)
1332443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_xmit_data = cntrs.port_xmit_data;
1333e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1334e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_RCV_DATA)
1335443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_rcv_data = cntrs.port_rcv_data;
1336e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1337e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_XMIT_PACKETS)
1338443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_xmit_packets = cntrs.port_xmit_packets;
1339e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1340e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SEL_PORT_RCV_PACKETS)
1341443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_rcv_packets = cntrs.port_rcv_packets;
1342e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1343e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return recv_pma_get_portcounters(pmp, ibdev, port);
1344e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1345e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1346e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int recv_pma_set_portcounters_ext(struct ib_perf *pmp,
1347e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					 struct ib_device *ibdev, u8 port)
1348e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1349e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_pma_portcounters *p = (struct ib_pma_portcounters *)
1350e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->data;
1351e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
1352e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	u64 swords, rwords, spkts, rpkts, xwait;
1353e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
135434b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan	ipath_snapshot_counters(dev->dd, &swords, &rwords, &spkts,
135534b2aafea38efdf02cd8107a6e1057e2a297c447Bryan O'Sullivan				&rpkts, &xwait);
1356e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1357e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_XMIT_DATA)
1358443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_xmit_data = swords;
1359e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1360e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_RCV_DATA)
1361443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_rcv_data = rwords;
1362e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1363e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_XMIT_PACKETS)
1364443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_xmit_packets = spkts;
1365e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1366e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_RCV_PACKETS)
1367443a64abbcb130caa315eb1110d7146365846235Bryan O'Sullivan		dev->z_port_rcv_packets = rpkts;
1368e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1369e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_UNI_XMIT_PACKETS)
1370e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->n_unicast_xmit = 0;
1371e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1372e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_UNI_RCV_PACKETS)
1373e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->n_unicast_rcv = 0;
1374e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1375e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_XMIT_PACKETS)
1376e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->n_multicast_xmit = 0;
1377e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1378e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (p->counter_select & IB_PMA_SELX_PORT_MULTI_RCV_PACKETS)
1379e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->n_multicast_rcv = 0;
1380e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1381e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return recv_pma_get_portcounters_ext(pmp, ibdev, port);
1382e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1383e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1384e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int process_subn(struct ib_device *ibdev, int mad_flags,
1385e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			u8 port_num, struct ib_mad *in_mad,
1386e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			struct ib_mad *out_mad)
1387e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1388e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_smp *smp = (struct ib_smp *)out_mad;
1389e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ipath_ibdev *dev = to_idev(ibdev);
1390e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int ret;
1391e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1392e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	*out_mad = *in_mad;
1393e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (smp->class_version != 1) {
1394e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_UNSUP_VERSION;
1395e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = reply(smp);
1396e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1397e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1398e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1399e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/* Is the mkey in the process of expiring? */
1400b3b8128fd3b0966830ee90f1162173d07cb496a0Robert P. J. Day	if (dev->mkey_lease_timeout &&
1401b3b8128fd3b0966830ee90f1162173d07cb496a0Robert P. J. Day	    time_after_eq(jiffies, dev->mkey_lease_timeout)) {
1402e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* Clear timeout and mkey protection field. */
1403e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->mkey_lease_timeout = 0;
1404542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell		dev->mkeyprot = 0;
1405e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1406e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1407e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	/*
1408e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * M_Key checking depends on
1409e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 * Portinfo:M_Key_protect_bits
1410e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	 */
1411e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if ((mad_flags & IB_MAD_IGNORE_MKEY) == 0 && dev->mkey != 0 &&
1412e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	    dev->mkey != smp->mkey &&
1413e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	    (smp->method == IB_MGMT_METHOD_SET ||
1414e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	     (smp->method == IB_MGMT_METHOD_GET &&
1415542869a17eee2edf389273f40f757aa4e662b3daRalph Campbell	      dev->mkeyprot >= 2))) {
1416e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		if (dev->mkey_violations != 0xFFFF)
1417e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			++dev->mkey_violations;
1418e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		if (dev->mkey_lease_timeout ||
1419e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		    dev->mkey_lease_period == 0) {
1420e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = IB_MAD_RESULT_SUCCESS |
1421e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				IB_MAD_RESULT_CONSUMED;
1422e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1423e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		}
1424e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->mkey_lease_timeout = jiffies +
1425e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			dev->mkey_lease_period * HZ;
1426e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/* Future: Generate a trap notice. */
1427e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED;
1428e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1429e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	} else if (dev->mkey_lease_timeout)
1430e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		dev->mkey_lease_timeout = 0;
1431e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1432e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch (smp->method) {
1433e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_METHOD_GET:
1434e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		switch (smp->attr_id) {
1435e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_NODE_DESC:
1436e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_get_nodedescription(smp, ibdev);
1437e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1438e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_NODE_INFO:
1439e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_get_nodeinfo(smp, ibdev, port_num);
1440e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1441e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_GUID_INFO:
1442e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_get_guidinfo(smp, ibdev);
1443e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1444e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_PORT_INFO:
1445e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_get_portinfo(smp, ibdev, port_num);
1446e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1447e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_PKEY_TABLE:
1448e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_get_pkeytable(smp, ibdev);
1449e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1450e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_SM_INFO:
1451e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
1452e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				ret = IB_MAD_RESULT_SUCCESS |
1453e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					IB_MAD_RESULT_CONSUMED;
1454e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				goto bail;
1455e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			}
1456e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			if (dev->port_cap_flags & IB_PORT_SM) {
1457e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				ret = IB_MAD_RESULT_SUCCESS;
1458e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				goto bail;
1459e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			}
1460e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			/* FALLTHROUGH */
1461e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		default:
1462e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			smp->status |= IB_SMP_UNSUP_METH_ATTR;
1463e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = reply(smp);
1464e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1465e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		}
1466e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1467e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_METHOD_SET:
1468e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		switch (smp->attr_id) {
1469e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_GUID_INFO:
1470e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_set_guidinfo(smp, ibdev);
1471e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1472e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_PORT_INFO:
1473e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_set_portinfo(smp, ibdev, port_num);
1474e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1475e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_PKEY_TABLE:
1476e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_subn_set_pkeytable(smp, ibdev);
1477e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1478e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_SMP_ATTR_SM_INFO:
1479e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			if (dev->port_cap_flags & IB_PORT_SM_DISABLED) {
1480e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				ret = IB_MAD_RESULT_SUCCESS |
1481e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan					IB_MAD_RESULT_CONSUMED;
1482e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				goto bail;
1483e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			}
1484e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			if (dev->port_cap_flags & IB_PORT_SM) {
1485e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				ret = IB_MAD_RESULT_SUCCESS;
1486e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				goto bail;
1487e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			}
1488e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			/* FALLTHROUGH */
1489e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		default:
1490e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			smp->status |= IB_SMP_UNSUP_METH_ATTR;
1491e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = reply(smp);
1492e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1493e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		}
1494e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1495e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_METHOD_GET_RESP:
1496e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/*
1497e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 * The ib_mad module will call us to process responses
1498e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 * before checking for other consumers.
1499e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 * Just tell the caller to process it normally.
1500e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 */
1501f9b403532235520ec248c024f621efcaf6ba7b93Ralph Campbell		ret = IB_MAD_RESULT_SUCCESS;
1502e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1503e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
1504e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		smp->status |= IB_SMP_UNSUP_METHOD;
1505e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = reply(smp);
1506e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1507e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1508e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanbail:
1509e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
1510e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1511e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1512e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanstatic int process_perf(struct ib_device *ibdev, u8 port_num,
1513e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			struct ib_mad *in_mad,
1514e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			struct ib_mad *out_mad)
1515e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1516e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	struct ib_perf *pmp = (struct ib_perf *)out_mad;
1517e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int ret;
1518e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1519e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	*out_mad = *in_mad;
1520e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	if (pmp->class_version != 1) {
1521e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_UNSUP_VERSION;
1522e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = reply((struct ib_smp *) pmp);
1523e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1524e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1525e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1526e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch (pmp->method) {
1527e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_METHOD_GET:
1528e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		switch (pmp->attr_id) {
1529e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_CLASS_PORT_INFO:
1530e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_get_classportinfo(pmp);
1531e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1532e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_SAMPLES_CONTROL:
1533e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_get_portsamplescontrol(pmp, ibdev,
1534e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan							      port_num);
1535e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1536e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_SAMPLES_RESULT:
1537e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_get_portsamplesresult(pmp, ibdev);
1538e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1539e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_SAMPLES_RESULT_EXT:
1540e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_get_portsamplesresult_ext(pmp,
1541e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan								 ibdev);
1542e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1543e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_COUNTERS:
1544e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_get_portcounters(pmp, ibdev,
1545e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan							port_num);
1546e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1547e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_COUNTERS_EXT:
1548e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_get_portcounters_ext(pmp, ibdev,
1549e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan							    port_num);
1550e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1551e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		default:
1552e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
1553e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = reply((struct ib_smp *) pmp);
1554e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1555e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		}
1556e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1557e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_METHOD_SET:
1558e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		switch (pmp->attr_id) {
1559e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_SAMPLES_CONTROL:
1560e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_set_portsamplescontrol(pmp, ibdev,
1561e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan							      port_num);
1562e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1563e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_COUNTERS:
1564e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_set_portcounters(pmp, ibdev,
1565e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan							port_num);
1566e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1567e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		case IB_PMA_PORT_COUNTERS_EXT:
1568e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = recv_pma_set_portcounters_ext(pmp, ibdev,
1569e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan							    port_num);
1570e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1571e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		default:
1572e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			pmp->status |= IB_SMP_UNSUP_METH_ATTR;
1573e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			ret = reply((struct ib_smp *) pmp);
1574e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan			goto bail;
1575e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		}
1576e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1577e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_METHOD_GET_RESP:
1578e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		/*
1579e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 * The ib_mad module will call us to process responses
1580e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 * before checking for other consumers.
1581e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 * Just tell the caller to process it normally.
1582e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		 */
1583f9b403532235520ec248c024f621efcaf6ba7b93Ralph Campbell		ret = IB_MAD_RESULT_SUCCESS;
1584e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1585e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
1586e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		pmp->status |= IB_SMP_UNSUP_METHOD;
1587e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = reply((struct ib_smp *) pmp);
1588e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1589e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1590e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanbail:
1591e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
1592e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1593e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1594e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan/**
1595e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * ipath_process_mad - process an incoming MAD packet
1596e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @ibdev: the infiniband device this packet came in on
1597e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @mad_flags: MAD flags
1598e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @port_num: the port number this packet came in on
1599e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @in_wc: the work completion entry for this packet
1600e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @in_grh: the global route header for this packet
1601e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @in_mad: the incoming MAD
1602e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * @out_mad: any outgoing MAD reply
1603e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
1604e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * Returns IB_MAD_RESULT_SUCCESS if this is a MAD that we are not
1605e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * interested in processing.
1606e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
1607e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * Note that the verbs framework has already done the MAD sanity checks,
1608e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * and hop count/pointer updating for IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE
1609e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * MADs.
1610e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan *
1611e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan * This is called by the ib_mad module.
1612e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan */
1613e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanint ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num,
1614e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		      struct ib_wc *in_wc, struct ib_grh *in_grh,
1615e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		      struct ib_mad *in_mad, struct ib_mad *out_mad)
1616e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan{
1617e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	int ret;
1618e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1619e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	switch (in_mad->mad_hdr.mgmt_class) {
1620e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE:
1621e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_CLASS_SUBN_LID_ROUTED:
1622e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = process_subn(ibdev, mad_flags, port_num,
1623e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan				   in_mad, out_mad);
1624e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1625e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	case IB_MGMT_CLASS_PERF_MGMT:
1626e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = process_perf(ibdev, port_num, in_mad, out_mad);
1627e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		goto bail;
1628e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	default:
1629e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan		ret = IB_MAD_RESULT_SUCCESS;
1630e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	}
1631e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan
1632e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivanbail:
1633e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan	return ret;
1634e28c00ad67164dba688c1d19c208c5fb554465f2Bryan O'Sullivan}
1635