1
2
3
4
5
6
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
22
23
24
25
26
27
28
29
30void bte_error_handler(unsigned long);
31
32
33
34
35
36int shub1_bte_error_handler(unsigned long _nodepda)
37{
38 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
39 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
40 nasid_t nasid;
41 int i;
42 int valid_crbs;
43 ii_imem_u_t imem;
44 ii_icrb0_d_u_t icrbd;
45 ii_ibcr_u_t ibcr;
46 ii_icmr_u_t icmr;
47 ii_ieclr_u_t ieclr;
48
49 BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
50 smp_processor_id()));
51
52 if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
53 (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
54 BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
55 smp_processor_id()));
56 return 1;
57 }
58
59
60 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
76 if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
77
78
79
80
81 mod_timer(recovery_timer, jiffies + (HZ * 5));
82 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
83 smp_processor_id()));
84 return 1;
85 }
86 if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
87
88 valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;
89
90 for (i = 0; i < IIO_NUM_CRBS; i++) {
91 if (!((1 << i) & valid_crbs)) {
92
93 continue;
94 }
95 icrbd.ii_icrb0_d_regval =
96 REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
97 if (icrbd.d_bteop) {
98 mod_timer(recovery_timer, jiffies + (HZ * 5));
99 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
100 err_nodepda, smp_processor_id(),
101 i));
102 return 1;
103 }
104 }
105 }
106
107 BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, smp_processor_id()));
108
109 imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
110 imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
111 REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
112
113
114 ieclr.ii_ieclr_regval = 0;
115 if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
116 ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
117 if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
118 ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
119 REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);
120
121
122 ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
123 ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
124 REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
125
126 del_timer(recovery_timer);
127 return 0;
128}
129
130
131
132
133
134int shub2_bte_error_handler(unsigned long _nodepda)
135{
136 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
137 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
138 struct bteinfo_s *bte;
139 nasid_t nasid;
140 u64 status;
141 int i;
142
143 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
144
145
146
147
148 for (i = 0; i < BTES_PER_NODE; i++) {
149 bte = &err_nodepda->bte_if[i];
150 status = BTE_LNSTAT_LOAD(bte);
151 if (status & IBLS_ERROR) {
152 bte->bh_error = BTE_SHUB2_ERROR(status);
153 continue;
154 }
155 if (!(status & IBLS_BUSY))
156 continue;
157 mod_timer(recovery_timer, jiffies + (HZ * 5));
158 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
159 smp_processor_id()));
160 return 1;
161 }
162 if (ia64_sn_bte_recovery(nasid))
163 panic("bte_error_handler(): Fatal BTE Error");
164
165 del_timer(recovery_timer);
166 return 0;
167}
168
169
170
171
172
173void bte_error_handler(unsigned long _nodepda)
174{
175 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
176 spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
177 int i;
178 unsigned long irq_flags;
179 volatile u64 *notify;
180 bte_result_t bh_error;
181
182 BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
183 smp_processor_id()));
184
185 spin_lock_irqsave(recovery_lock, irq_flags);
186
187
188
189
190
191 for (i = 0; i < BTES_PER_NODE; i++) {
192 if (err_nodepda->bte_if[i].cleanup_active) {
193 continue;
194 }
195 spin_lock(&err_nodepda->bte_if[i].spinlock);
196 BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
197 smp_processor_id(), i));
198 err_nodepda->bte_if[i].cleanup_active = 1;
199 }
200
201 if (is_shub1()) {
202 if (shub1_bte_error_handler(_nodepda)) {
203 spin_unlock_irqrestore(recovery_lock, irq_flags);
204 return;
205 }
206 } else {
207 if (shub2_bte_error_handler(_nodepda)) {
208 spin_unlock_irqrestore(recovery_lock, irq_flags);
209 return;
210 }
211 }
212
213 for (i = 0; i < BTES_PER_NODE; i++) {
214 bh_error = err_nodepda->bte_if[i].bh_error;
215 if (bh_error != BTE_SUCCESS) {
216
217 notify = err_nodepda->bte_if[i].most_rcnt_na;
218 BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
219 err_nodepda->bte_if[i].bte_cnode,
220 err_nodepda->bte_if[i].bte_num,
221 IBLS_ERROR | (u64) bh_error));
222 *notify = IBLS_ERROR | bh_error;
223 err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
224 }
225
226 err_nodepda->bte_if[i].cleanup_active = 0;
227 BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
228 smp_processor_id(), i));
229 spin_unlock(&err_nodepda->bte_if[i].spinlock);
230 }
231
232 spin_unlock_irqrestore(recovery_lock, irq_flags);
233}
234
235
236
237
238
239void
240bte_crb_error_handler(cnodeid_t cnode, int btenum,
241 int crbnum, ioerror_t * ioe, int bteop)
242{
243 struct bteinfo_s *bte;
244
245
246 bte = &(NODEPDA(cnode)->bte_if[btenum]);
247
248
249
250
251
252
253 bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET;
254 bte->bte_error_count++;
255
256 BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n",
257 bte->bte_cnode, bte->bte_num, ioe->ie_errortype));
258 bte_error_handler((unsigned long) NODEPDA(cnode));
259}
260
261