[IA64] Fix conversion of pal_min_state physical address
[deliverable/linux.git] / arch / ia64 / sn / kernel / bte_error.c
CommitLineData
1da177e4
LT
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 *
93a07d0a 6 * Copyright (c) 2000-2005 Silicon Graphics, Inc. All Rights Reserved.
1da177e4
LT
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
30void bte_error_handler(unsigned long);
31
32/*
33 * Wait until all BTE related CRBs are completed
34 * and then reset the interfaces.
35 */
93a07d0a 36void shub1_bte_error_handler(unsigned long _nodepda)
1da177e4
LT
37{
38 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
1da177e4
LT
39 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
40 nasid_t nasid;
41 int i;
42 int valid_crbs;
1da177e4
LT
43 ii_imem_u_t imem; /* II IMEM Register */
44 ii_icrb0_d_u_t icrbd; /* II CRB Register D */
45 ii_ibcr_u_t ibcr;
46 ii_icmr_u_t icmr;
47 ii_ieclr_u_t ieclr;
48
93a07d0a 49 BTE_PRINTK(("shub1_bte_error_handler(%p) - %d\n", err_nodepda,
1da177e4
LT
50 smp_processor_id()));
51
1da177e4
LT
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()));
1da177e4
LT
56 return;
57 }
1da177e4
LT
58
59 /* Determine information about our hub */
60 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
61
62 /*
63 * A BTE transfer can use multiple CRBs. We need to make sure
64 * that all the BTE CRBs are complete (or timed out) before
65 * attempting to clean up the error. Resetting the BTE while
66 * there are still BTE CRBs active will hang the BTE.
67 * We should look at all the CRBs to see if they are allocated
68 * to the BTE and see if they are still active. When none
69 * are active, we can continue with the cleanup.
70 *
71 * We also want to make sure that the local NI port is up.
72 * When a router resets the NI port can go down, while it
73 * goes through the LLP handshake, but then comes back up.
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 * There are errors which still need to be cleaned up by
79 * hubiio_crb_error_handler
80 */
81 mod_timer(recovery_timer, HZ * 5);
82 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
83 smp_processor_id()));
1da177e4
LT
84 return;
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 /* This crb was not marked as valid, ignore */
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, HZ * 5);
99 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
100 err_nodepda, smp_processor_id(),
101 i));
1da177e4
LT
102 return;
103 }
104 }
105 }
106
107 BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda, smp_processor_id()));
108 /* Reenable both bte interfaces */
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 /* Clear BTE0/1 error bits */
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 /* Reinitialize both BTE state machines. */
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
93a07d0a
RA
126 del_timer(recovery_timer);
127}
128
129/*
130 * Wait until all BTE related CRBs are completed
131 * and then reset the interfaces.
132 */
133void bte_error_handler(unsigned long _nodepda)
134{
135 struct nodepda_s *err_nodepda = (struct nodepda_s *)_nodepda;
136 spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
137 int i;
138 nasid_t nasid;
139 unsigned long irq_flags;
140 volatile u64 *notify;
141 bte_result_t bh_error;
142
143 BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
144 smp_processor_id()));
145
146 spin_lock_irqsave(recovery_lock, irq_flags);
147
148 /*
149 * Lock all interfaces on this node to prevent new transfers
150 * from being queued.
151 */
152 for (i = 0; i < BTES_PER_NODE; i++) {
153 if (err_nodepda->bte_if[i].cleanup_active) {
154 continue;
155 }
156 spin_lock(&err_nodepda->bte_if[i].spinlock);
157 BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
158 smp_processor_id(), i));
159 err_nodepda->bte_if[i].cleanup_active = 1;
160 }
161
162 if (is_shub1()) {
163 shub1_bte_error_handler(_nodepda);
164 } else {
165 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
166
167 if (ia64_sn_bte_recovery(nasid))
168 panic("bte_error_handler(): Fatal BTE Error");
169 }
170
1da177e4
LT
171 for (i = 0; i < BTES_PER_NODE; i++) {
172 bh_error = err_nodepda->bte_if[i].bh_error;
173 if (bh_error != BTE_SUCCESS) {
174 /* There is an error which needs to be notified */
175 notify = err_nodepda->bte_if[i].most_rcnt_na;
176 BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
177 err_nodepda->bte_if[i].bte_cnode,
178 err_nodepda->bte_if[i].bte_num,
179 IBLS_ERROR | (u64) bh_error));
180 *notify = IBLS_ERROR | bh_error;
181 err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
182 }
183
184 err_nodepda->bte_if[i].cleanup_active = 0;
185 BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
186 smp_processor_id(), i));
187 spin_unlock(&err_nodepda->bte_if[i].spinlock);
188 }
189
1da177e4
LT
190 spin_unlock_irqrestore(recovery_lock, irq_flags);
191}
192
193/*
194 * First part error handler. This is called whenever any error CRB interrupt
195 * is generated by the II.
196 */
197void
198bte_crb_error_handler(cnodeid_t cnode, int btenum,
199 int crbnum, ioerror_t * ioe, int bteop)
200{
201 struct bteinfo_s *bte;
202
203
204 bte = &(NODEPDA(cnode)->bte_if[btenum]);
205
206 /*
207 * The caller has already figured out the error type, we save that
208 * in the bte handle structure for the thread excercising the
209 * interface to consume.
210 */
211 bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET;
212 bte->bte_error_count++;
213
214 BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n",
215 bte->bte_cnode, bte->bte_num, ioe->ie_errortype));
216 bte_error_handler((unsigned long) NODEPDA(cnode));
217}
218
This page took 0.090727 seconds and 5 git commands to generate.