1 /*
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
4 * for more details.
5 *
6 * Copyright (c) 2000-2007 Silicon Graphics, Inc. All Rights Reserved.
7 */
8
9 #include <linux/types.h>
10 #include <asm/sn/sn_sal.h>
11 #include "ioerror.h"
12 #include <asm/sn/addrs.h>
13 #include <asm/sn/shubio.h>
14 #include <asm/sn/geo.h>
15 #include "xtalk/xwidgetdev.h"
16 #include "xtalk/hubdev.h"
17 #include <asm/sn/bte.h>
18 #include <asm/param.h>
19
20 /*
21 * Bte error handling is done in two parts. The first captures
22 * any crb related errors. Since there can be multiple crbs per
23 * interface and multiple interfaces active, we need to wait until
24 * all active crbs are completed. This is the first job of the
25 * second part error handler. When all bte related CRBs are cleanly
26 * completed, it resets the interfaces and gets them ready for new
27 * transfers to be queued.
28 */
29
30 /*
31 * Wait until all BTE related CRBs are completed
32 * and then reset the interfaces.
33 */
shub1_bte_error_handler(struct nodepda_s * err_nodepda)34 static int shub1_bte_error_handler(struct nodepda_s *err_nodepda)
35 {
36 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
37 nasid_t nasid;
38 int i;
39 int valid_crbs;
40 ii_imem_u_t imem; /* II IMEM Register */
41 ii_icrb0_d_u_t icrbd; /* II CRB Register D */
42 ii_ibcr_u_t ibcr;
43 ii_icmr_u_t icmr;
44 ii_ieclr_u_t ieclr;
45
46 BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
47 smp_processor_id()));
48
49 if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
50 (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
51 BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
52 smp_processor_id()));
53 return 1;
54 }
55
56 /* Determine information about our hub */
57 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
58
59 /*
60 * A BTE transfer can use multiple CRBs. We need to make sure
61 * that all the BTE CRBs are complete (or timed out) before
62 * attempting to clean up the error. Resetting the BTE while
63 * there are still BTE CRBs active will hang the BTE.
64 * We should look at all the CRBs to see if they are allocated
65 * to the BTE and see if they are still active. When none
66 * are active, we can continue with the cleanup.
67 *
68 * We also want to make sure that the local NI port is up.
69 * When a router resets the NI port can go down, while it
70 * goes through the LLP handshake, but then comes back up.
71 */
72 icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
73 if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
74 /*
75 * There are errors which still need to be cleaned up by
76 * hubiio_crb_error_handler
77 */
78 mod_timer(recovery_timer, jiffies + (HZ * 5));
79 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
80 smp_processor_id()));
81 return 1;
82 }
83 if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
84
85 valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;
86
87 for (i = 0; i < IIO_NUM_CRBS; i++) {
88 if (!((1 << i) & valid_crbs)) {
89 /* This crb was not marked as valid, ignore */
90 continue;
91 }
92 icrbd.ii_icrb0_d_regval =
93 REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
94 if (icrbd.d_bteop) {
95 mod_timer(recovery_timer, jiffies + (HZ * 5));
96 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
97 err_nodepda, smp_processor_id(),
98 i));
99 return 1;
100 }
101 }
102 }
103
104 BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, smp_processor_id()));
105 /* Re-enable both bte interfaces */
106 imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
107 imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
108 REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
109
110 /* Clear BTE0/1 error bits */
111 ieclr.ii_ieclr_regval = 0;
112 if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
113 ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
114 if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
115 ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
116 REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);
117
118 /* Reinitialize both BTE state machines. */
119 ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
120 ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
121 REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
122
123 del_timer(recovery_timer);
124 return 0;
125 }
126
127 /*
128 * Wait until all BTE related CRBs are completed
129 * and then reset the interfaces.
130 */
shub2_bte_error_handler(struct nodepda_s * err_nodepda)131 static int shub2_bte_error_handler(struct nodepda_s *err_nodepda)
132 {
133 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
134 struct bteinfo_s *bte;
135 nasid_t nasid;
136 u64 status;
137 int i;
138
139 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
140
141 /*
142 * Verify that all the BTEs are complete
143 */
144 for (i = 0; i < BTES_PER_NODE; i++) {
145 bte = &err_nodepda->bte_if[i];
146 status = BTE_LNSTAT_LOAD(bte);
147 if (status & IBLS_ERROR) {
148 bte->bh_error = BTE_SHUB2_ERROR(status);
149 continue;
150 }
151 if (!(status & IBLS_BUSY))
152 continue;
153 mod_timer(recovery_timer, jiffies + (HZ * 5));
154 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
155 smp_processor_id()));
156 return 1;
157 }
158 if (ia64_sn_bte_recovery(nasid))
159 panic("bte_error_handler(): Fatal BTE Error");
160
161 del_timer(recovery_timer);
162 return 0;
163 }
164
165 /*
166 * Wait until all BTE related CRBs are completed
167 * and then reset the interfaces.
168 */
bte_error_handler(struct nodepda_s * err_nodepda)169 void bte_error_handler(struct nodepda_s *err_nodepda)
170 {
171 spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
172 int i;
173 unsigned long irq_flags;
174 volatile u64 *notify;
175 bte_result_t bh_error;
176
177 BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
178 smp_processor_id()));
179
180 spin_lock_irqsave(recovery_lock, irq_flags);
181
182 /*
183 * Lock all interfaces on this node to prevent new transfers
184 * from being queued.
185 */
186 for (i = 0; i < BTES_PER_NODE; i++) {
187 if (err_nodepda->bte_if[i].cleanup_active) {
188 continue;
189 }
190 spin_lock(&err_nodepda->bte_if[i].spinlock);
191 BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
192 smp_processor_id(), i));
193 err_nodepda->bte_if[i].cleanup_active = 1;
194 }
195
196 if (is_shub1()) {
197 if (shub1_bte_error_handler(err_nodepda)) {
198 spin_unlock_irqrestore(recovery_lock, irq_flags);
199 return;
200 }
201 } else {
202 if (shub2_bte_error_handler(err_nodepda)) {
203 spin_unlock_irqrestore(recovery_lock, irq_flags);
204 return;
205 }
206 }
207
208 for (i = 0; i < BTES_PER_NODE; i++) {
209 bh_error = err_nodepda->bte_if[i].bh_error;
210 if (bh_error != BTE_SUCCESS) {
211 /* There is an error which needs to be notified */
212 notify = err_nodepda->bte_if[i].most_rcnt_na;
213 BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
214 err_nodepda->bte_if[i].bte_cnode,
215 err_nodepda->bte_if[i].bte_num,
216 IBLS_ERROR | (u64) bh_error));
217 *notify = IBLS_ERROR | bh_error;
218 err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
219 }
220
221 err_nodepda->bte_if[i].cleanup_active = 0;
222 BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
223 smp_processor_id(), i));
224 spin_unlock(&err_nodepda->bte_if[i].spinlock);
225 }
226
227 spin_unlock_irqrestore(recovery_lock, irq_flags);
228 }
229
230 /*
231 * First part error handler. This is called whenever any error CRB interrupt
232 * is generated by the II.
233 */
234 void
bte_crb_error_handler(cnodeid_t cnode,int btenum,int crbnum,ioerror_t * ioe,int bteop)235 bte_crb_error_handler(cnodeid_t cnode, int btenum,
236 int crbnum, ioerror_t * ioe, int bteop)
237 {
238 struct bteinfo_s *bte;
239
240
241 bte = &(NODEPDA(cnode)->bte_if[btenum]);
242
243 /*
244 * The caller has already figured out the error type, we save that
245 * in the bte handle structure for the thread exercising the
246 * interface to consume.
247 */
248 bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET;
249 bte->bte_error_count++;
250
251 BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n",
252 bte->bte_cnode, bte->bte_num, ioe->ie_errortype));
253 bte_error_handler(NODEPDA(cnode));
254 }
255
256