1f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
2f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
3f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * All rights reserved.
4f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
5f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
6f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * This software is available to you under a choice of one of two
7f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * licenses.  You may choose to be licensed under the terms of the GNU
8f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * General Public License (GPL) Version 2, available from the file
9f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * COPYING in the main directory of this source tree, or the
10f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * OpenIB.org BSD license below:
11f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
12f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     Redistribution and use in source and binary forms, with or
13f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     without modification, are permitted provided that the following
14f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *     conditions are met:
15f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
16f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *      - Redistributions of source code must retain the above
17f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        copyright notice, this list of conditions and the following
18f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        disclaimer.
19f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
20f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *      - Redistributions in binary form must reproduce the above
21f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        copyright notice, this list of conditions and the following
22f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        disclaimer in the documentation and/or other materials
23f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *        provided with the distribution.
24f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell *
25f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * SOFTWARE.
33f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
34f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
35f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/pci.h>
36f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include <linux/delay.h>
37f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
38f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include "qib.h"
39f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell#include "qib_common.h"
40f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
41f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
42f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_format_hwmsg - format a single hwerror message
43f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @msg message buffer
44f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @msgl length of message buffer
45f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @hwmsg message to add to message buffer
46f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
47f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void qib_format_hwmsg(char *msg, size_t msgl, const char *hwmsg)
48f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
49f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	strlcat(msg, "[", msgl);
50f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	strlcat(msg, hwmsg, msgl);
51f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	strlcat(msg, "]", msgl);
52f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
53f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
54f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/**
55f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * qib_format_hwerrors - format hardware error messages for display
56f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @hwerrs hardware errors bit vector
57f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @hwerrmsgs hardware error descriptions
58f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @nhwerrmsgs number of hwerrmsgs
59f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @msg message buffer
60f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * @msgl message buffer length
61f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
62f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_format_hwerrors(u64 hwerrs, const struct qib_hwerror_msgs *hwerrmsgs,
63f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			 size_t nhwerrmsgs, char *msg, size_t msgl)
64f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
65f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
66f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
67f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = 0; i < nhwerrmsgs; i++)
68f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (hwerrs & hwerrmsgs[i].mask)
69f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_format_hwmsg(msg, msgl, hwerrmsgs[i].msg);
70f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
71f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
72f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellstatic void signal_ib_event(struct qib_pportdata *ppd, enum ib_event_type ev)
73f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
74f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct ib_event event;
75f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
76f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
77f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	event.device = &dd->verbs_dev.ibdev;
78f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	event.element.port_num = ppd->port;
79f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	event.event = ev;
80f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ib_dispatch_event(&event);
81f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
82f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
83f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_handle_e_ibstatuschanged(struct qib_pportdata *ppd, u64 ibcs)
84f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
85f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_devdata *dd = ppd->dd;
86f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
87f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u32 lstate;
88f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	u8 ltstate;
89f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	enum ib_event_type ev = 0;
90f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
91f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	lstate = dd->f_iblink_state(ibcs); /* linkstate */
92f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ltstate = dd->f_ibphys_portstate(ibcs);
93f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
94f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
95f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * If linkstate transitions into INIT from any of the various down
96f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * states, or if it transitions from any of the up (INIT or better)
97f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * states into any of the down states (except link recovery), then
98f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * call the chip-specific code to take appropriate actions.
993126448451105fae59de0058c68692aa09aa4c37Mitko Haralanov	 *
1003126448451105fae59de0058c68692aa09aa4c37Mitko Haralanov	 * ppd->lflags could be 0 if this is the first time the interrupt
1013126448451105fae59de0058c68692aa09aa4c37Mitko Haralanov	 * handlers has been called but the link is already up.
102f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
1033126448451105fae59de0058c68692aa09aa4c37Mitko Haralanov	if (lstate >= IB_PORT_INIT &&
1043126448451105fae59de0058c68692aa09aa4c37Mitko Haralanov	    (!ppd->lflags || (ppd->lflags & QIBL_LINKDOWN)) &&
105f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	    ltstate == IB_PHYSPORTSTATE_LINKUP) {
106f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* transitioned to UP */
107f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (dd->f_ib_updown(ppd, 1, ibcs))
108f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto skip_ibchange; /* chip-code handled */
109f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else if (ppd->lflags & (QIBL_LINKINIT | QIBL_LINKARMED |
110f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		   QIBL_LINKACTIVE | QIBL_IB_FORCE_NOTIFY)) {
111f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ltstate != IB_PHYSPORTSTATE_LINKUP &&
112f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    ltstate <= IB_PHYSPORTSTATE_CFG_TRAIN &&
113f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		    dd->f_ib_updown(ppd, 0, ibcs))
114f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			goto skip_ibchange; /* chip-code handled */
115f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		qib_set_uevent_bits(ppd, _QIB_EVENT_LINKDOWN_BIT);
116f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
117f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
118f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (lstate != IB_PORT_DOWN) {
119f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* lstate is INIT, ARMED, or ACTIVE */
120f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (lstate != IB_PORT_ACTIVE) {
121f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			*ppd->statusp &= ~QIB_STATUS_IB_READY;
122f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (ppd->lflags & QIBL_LINKACTIVE)
123f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ev = IB_EVENT_PORT_ERR;
124f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irqsave(&ppd->lflags_lock, flags);
125f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (lstate == IB_PORT_ARMED) {
126f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->lflags |= QIBL_LINKARMED | QIBL_LINKV;
127f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->lflags &= ~(QIBL_LINKINIT |
128f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					QIBL_LINKDOWN | QIBL_LINKACTIVE);
129f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			} else {
130f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->lflags |= QIBL_LINKINIT | QIBL_LINKV;
131f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				ppd->lflags &= ~(QIBL_LINKARMED |
132f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					QIBL_LINKDOWN | QIBL_LINKACTIVE);
133f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			}
134f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
135f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* start a 75msec timer to clear symbol errors */
136f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			mod_timer(&ppd->symerr_clear_timer,
137f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				  msecs_to_jiffies(75));
138b3d5cb2f2067b30da53aa67e42fdd733030fb411Mike Marciniszyn		} else if (ltstate == IB_PHYSPORTSTATE_LINKUP &&
139b3d5cb2f2067b30da53aa67e42fdd733030fb411Mike Marciniszyn			   !(ppd->lflags & QIBL_LINKACTIVE)) {
140f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			/* active, but not active defered */
141f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_hol_up(ppd); /* useful only for 6120 now */
142f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			*ppd->statusp |=
143f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				QIB_STATUS_IB_READY | QIB_STATUS_IB_CONF;
144f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			qib_clear_symerror_on_linkup((unsigned long)ppd);
145f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_lock_irqsave(&ppd->lflags_lock, flags);
146f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->lflags |= QIBL_LINKACTIVE | QIBL_LINKV;
147f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ppd->lflags &= ~(QIBL_LINKINIT |
148f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				QIBL_LINKDOWN | QIBL_LINKARMED);
149f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			spin_unlock_irqrestore(&ppd->lflags_lock, flags);
150f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			if (dd->flags & QIB_HAS_SEND_DMA)
151f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				qib_sdma_process_event(ppd,
152f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					qib_sdma_event_e30_go_running);
153f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ev = IB_EVENT_PORT_ACTIVE;
154f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->f_setextled(ppd, 1);
155f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
156f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	} else { /* down */
157f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (ppd->lflags & QIBL_LINKACTIVE)
158f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			ev = IB_EVENT_PORT_ERR;
159f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_lock_irqsave(&ppd->lflags_lock, flags);
160f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->lflags |= QIBL_LINKDOWN | QIBL_LINKV;
161f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->lflags &= ~(QIBL_LINKINIT |
162f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				 QIBL_LINKACTIVE | QIBL_LINKARMED);
163f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		spin_unlock_irqrestore(&ppd->lflags_lock, flags);
164f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		*ppd->statusp &= ~QIB_STATUS_IB_READY;
165f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
166f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
167f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellskip_ibchange:
168f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->lastibcstat = ibcs;
169f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ev)
170f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		signal_ib_event(ppd, ev);
171f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	return;
172f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
173f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
174f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_clear_symerror_on_linkup(unsigned long opaque)
175f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
176f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_pportdata *ppd = (struct qib_pportdata *)opaque;
177f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
178f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (ppd->lflags & QIBL_LINKACTIVE)
179f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		return;
180f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
181f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	ppd->ibport_data.z_symbol_error_counter =
182f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		ppd->dd->f_portcntr(ppd, QIBPORTCNTR_IBSYMBOLERR);
183f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
184f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
185f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell/*
186f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * Handle receive interrupts for user ctxts; this means a user
187f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * process was waiting for a packet to arrive, and didn't want
188f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell * to poll.
189f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell */
190f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_handle_urcv(struct qib_devdata *dd, u64 ctxtr)
191f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
192f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	struct qib_ctxtdata *rcd;
193f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	unsigned long flags;
194f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	int i;
195f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
196f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_lock_irqsave(&dd->uctxt_lock, flags);
197f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	for (i = dd->first_user_ctxt; dd->rcd && i < dd->cfgctxts; i++) {
198f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!(ctxtr & (1ULL << i)))
199f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			continue;
200f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		rcd = dd->rcd[i];
201f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (!rcd || !rcd->cnt)
202f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			continue;
203f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
204f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (test_and_clear_bit(QIB_CTXT_WAITING_RCV, &rcd->flag)) {
205f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			wake_up_interruptible(&rcd->wait);
206f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->f_rcvctrl(rcd->ppd, QIB_RCVCTRL_INTRAVAIL_DIS,
207f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell				      rcd->ctxt);
208f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		} else if (test_and_clear_bit(QIB_CTXT_WAITING_URG,
209f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell					      &rcd->flag)) {
210f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			rcd->urgent++;
211f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			wake_up_interruptible(&rcd->wait);
212f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
213f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
214f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	spin_unlock_irqrestore(&dd->uctxt_lock, flags);
215f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
216f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
217f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbellvoid qib_bad_intrstatus(struct qib_devdata *dd)
218f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell{
219f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	static int allbits;
220f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
221f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/* separate routine, for better optimization of qib_intr() */
222f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell
223f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	/*
224f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * We print the message and disable interrupts, in hope of
225f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 * having a better chance of debugging the problem.
226f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	 */
2277fac33014f54c26bb1b1b4282b27c7988116d639Mike Marciniszyn	qib_dev_err(dd,
2287fac33014f54c26bb1b1b4282b27c7988116d639Mike Marciniszyn		"Read of chip interrupt status failed disabling interrupts\n");
229f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	if (allbits++) {
230f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		/* disable interrupt delivery, something is very wrong */
231f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (allbits == 2)
232f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->f_set_intr_state(dd, 0);
233f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		if (allbits == 3) {
2347fac33014f54c26bb1b1b4282b27c7988116d639Mike Marciniszyn			qib_dev_err(dd,
2357fac33014f54c26bb1b1b4282b27c7988116d639Mike Marciniszyn				"2nd bad interrupt status, unregistering interrupts\n");
236f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->flags |= QIB_BADINTR;
237f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->flags &= ~QIB_INITTED;
238f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell			dd->f_free_irq(dd);
239f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell		}
240f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell	}
241f931551bafe1f10ded7f5282e2aa162c267a2e5dRalph Campbell}
242