2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved.
9 #include <linux/types.h>
10 #include <linux/interrupt.h>
11 #include <asm/delay.h>
12 #include <asm/sn/sn_sal.h>
14 #include <asm/sn/addrs.h>
15 #include <asm/sn/shubio.h>
16 #include <asm/sn/geo.h>
17 #include "xtalk/xwidgetdev.h"
18 #include "xtalk/hubdev.h"
19 #include <asm/sn/bte.h>
21 void hubiio_crb_error_handler(struct hubdev_info
*hubdev_info
);
22 extern void bte_crb_error_handler(cnodeid_t
, int, int, ioerror_t
*,
24 static irqreturn_t
hub_eint_handler(int irq
, void *arg
)
26 struct hubdev_info
*hubdev_info
;
27 struct ia64_sal_retval ret_stuff
;
32 hubdev_info
= (struct hubdev_info
*)arg
;
33 nasid
= hubdev_info
->hdi_nasid
;
36 SAL_CALL_NOLOCK(ret_stuff
, SN_SAL_HUB_ERROR_INTERRUPT
,
37 (u64
) nasid
, 0, 0, 0, 0, 0, 0);
39 if ((int)ret_stuff
.v0
)
40 <<<<<<< HEAD
:arch
/ia64
/sn
/kernel
/huberror
.c
41 panic("%s: Fatal %s Error", __FUNCTION__
,
43 panic("%s: Fatal %s Error", __func__
,
44 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:arch
/ia64
/sn
/kernel
/huberror
.c
45 ((nasid
& 1) ? "TIO" : "HUBII"));
47 if (!(nasid
& 1)) /* Not a TIO, handle CRB errors */
48 (void)hubiio_crb_error_handler(hubdev_info
);
50 if (nasid
& 1) { /* TIO errors */
51 SAL_CALL_NOLOCK(ret_stuff
, SN_SAL_HUB_ERROR_INTERRUPT
,
52 (u64
) nasid
, 0, 0, 0, 0, 0, 0);
54 if ((int)ret_stuff
.v0
)
55 <<<<<<< HEAD
:arch
/ia64
/sn
/kernel
/huberror
.c
56 panic("%s: Fatal TIO Error", __FUNCTION__
);
58 panic("%s: Fatal TIO Error", __func__
);
59 >>>>>>> 264e3e889d86e552b4191d69bb60f4f3b383135a
:arch
/ia64
/sn
/kernel
/huberror
.c
61 bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid
)));
67 * Free the hub CRB "crbnum" which encountered an error.
68 * Assumption is, error handling was successfully done,
69 * and we now want to return the CRB back to Hub for normal usage.
71 * In order to free the CRB, all that's needed is to de-allocate it
74 * No other processor is mucking around with the hub control register.
75 * So, upper layer has to single thread this.
77 void hubiio_crb_free(struct hubdev_info
*hubdev_info
, int crbnum
)
82 * The hardware does NOT clear the mark bit, so it must get cleared
83 * here to be sure the error is not processed twice.
85 icrbb
.ii_icrb0_b_regval
= REMOTE_HUB_L(hubdev_info
->hdi_nasid
,
88 REMOTE_HUB_S(hubdev_info
->hdi_nasid
, IIO_ICRB_B(crbnum
),
89 icrbb
.ii_icrb0_b_regval
);
91 * Deallocate the register wait till hub indicates it's done.
93 REMOTE_HUB_S(hubdev_info
->hdi_nasid
, IIO_ICDR
, (IIO_ICDR_PND
| crbnum
));
94 while (REMOTE_HUB_L(hubdev_info
->hdi_nasid
, IIO_ICDR
) & IIO_ICDR_PND
)
100 * hubiio_crb_error_handler
102 * This routine gets invoked when a hub gets an error
103 * interrupt. So, the routine is running in interrupt context
104 * at error interrupt level.
106 * It's responsible for identifying ALL the CRBs that are marked
107 * with error, and process them.
109 * If you find the CRB that's marked with error, map this to the
110 * reason it caused error, and invoke appropriate error handler.
112 * XXX Be aware of the information in the context register.
115 * Use REMOTE_HUB_* macro instead of LOCAL_HUB_* so that the interrupt
116 * handler can be run on any node. (not necessarily the node
117 * corresponding to the hub that encountered error).
120 void hubiio_crb_error_handler(struct hubdev_info
*hubdev_info
)
123 ii_icrb0_a_u_t icrba
; /* II CRB Register A */
124 ii_icrb0_b_u_t icrbb
; /* II CRB Register B */
125 ii_icrb0_c_u_t icrbc
; /* II CRB Register C */
126 ii_icrb0_d_u_t icrbd
; /* II CRB Register D */
127 ii_icrb0_e_u_t icrbe
; /* II CRB Register D */
129 int num_errors
= 0; /* Num of errors handled */
132 nasid
= hubdev_info
->hdi_nasid
;
135 * XXX - Add locking for any recovery actions
138 * Scan through all CRBs in the Hub, and handle the errors
139 * in any of the CRBs marked.
141 for (i
= 0; i
< IIO_NUM_CRBS
; i
++) {
142 /* Check this crb entry to see if it is in error. */
143 icrbb
.ii_icrb0_b_regval
= REMOTE_HUB_L(nasid
, IIO_ICRB_B(i
));
145 if (icrbb
.b_mark
== 0) {
149 icrba
.ii_icrb0_a_regval
= REMOTE_HUB_L(nasid
, IIO_ICRB_A(i
));
151 IOERROR_INIT(&ioerror
);
153 /* read other CRB error registers. */
154 icrbc
.ii_icrb0_c_regval
= REMOTE_HUB_L(nasid
, IIO_ICRB_C(i
));
155 icrbd
.ii_icrb0_d_regval
= REMOTE_HUB_L(nasid
, IIO_ICRB_D(i
));
156 icrbe
.ii_icrb0_e_regval
= REMOTE_HUB_L(nasid
, IIO_ICRB_E(i
));
158 IOERROR_SETVALUE(&ioerror
, errortype
, icrbb
.b_ecode
);
160 /* Check if this error is due to BTE operation,
161 * and handle it separately.
164 ((icrbb
.b_initiator
== IIO_ICRB_INIT_BTE0
||
165 icrbb
.b_initiator
== IIO_ICRB_INIT_BTE1
) &&
166 (icrbb
.b_imsgtype
== IIO_ICRB_IMSGT_BTE
||
167 icrbb
.b_imsgtype
== IIO_ICRB_IMSGT_SN1NET
))) {
172 bte_num
= icrbc
.c_btenum
;
173 else /* b_initiator bit 2 gives BTE number */
174 bte_num
= (icrbb
.b_initiator
& 0x4) >> 2;
176 hubiio_crb_free(hubdev_info
, i
);
178 bte_crb_error_handler(nasid_to_cnodeid(nasid
), bte_num
,
179 i
, &ioerror
, icrbd
.d_bteop
);
187 * Function : hub_error_init
188 * Purpose : initialize the error handling requirements for a given hub.
189 * Parameters : cnode, the compact nodeid.
190 * Assumptions : Called only once per hub, either by a local cpu. Or by a
191 * remote cpu, when this hub is headless.(cpuless)
194 void hub_error_init(struct hubdev_info
*hubdev_info
)
197 if (request_irq(SGI_II_ERROR
, hub_eint_handler
, IRQF_SHARED
,
198 "SN_hub_error", (void *)hubdev_info
)) {
199 printk("hub_error_init: Failed to request_irq for 0x%p\n",
203 sn_set_err_irq_affinity(SGI_II_ERROR
);
208 * Function : ice_error_init
209 * Purpose : initialize the error handling requirements for a given tio.
210 * Parameters : cnode, the compact nodeid.
211 * Assumptions : Called only once per tio.
214 void ice_error_init(struct hubdev_info
*hubdev_info
)
218 (SGI_TIO_ERROR
, (void *)hub_eint_handler
, IRQF_SHARED
, "SN_TIO_error",
219 (void *)hubdev_info
)) {
220 printk("ice_error_init: request_irq() error hubdev_info 0x%p\n",
224 sn_set_err_irq_affinity(SGI_TIO_ERROR
);