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) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
10 #include <linux/types.h>
11 #include <linux/slab.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/io.h>
15 #include <asm/sn/hcl.h>
16 #include <asm/sn/labelcl.h>
17 #include <asm/sn/sn_private.h>
18 #include <asm/sn/klconfig.h>
19 #include <asm/sn/sn_cpuid.h>
20 #include <asm/sn/pci/pciio.h>
21 #include <asm/sn/pci/pcibr.h>
22 #include <asm/sn/xtalk/xtalk.h>
23 #include <asm/sn/pci/pcibr_private.h>
24 #include <asm/sn/intr.h>
25 #include <asm/sn/ioerror.h>
26 #include <asm/sn/sn2/shubio.h>
27 #include <asm/sn/bte.h>
31 * Bte error handling is done in two parts. The first captures
32 * any crb related errors. Since there can be multiple crbs per
33 * interface and multiple interfaces active, we need to wait until
34 * all active crbs are completed. This is the first job of the
35 * second part error handler. When all bte related CRBs are cleanly
36 * completed, it resets the interfaces and gets them ready for new
37 * transfers to be queued.
41 void bte_error_handler(unsigned long);
45 * First part error handler. This is called whenever any error CRB interrupt
46 * is generated by the II.
49 bte_crb_error_handler(vertex_hdl_t hub_v, int btenum,
50 int crbnum, ioerror_t * ioe, int bteop)
53 struct bteinfo_s *bte;
56 hubinfo_get(hub_v, &hinfo);
57 bte = &hinfo->h_nodepda->bte_if[btenum];
60 * The caller has already figured out the error type, we save that
61 * in the bte handle structure for the thread excercising the
62 * interface to consume.
64 bte->bh_error = ioe->ie_errortype + BTEFAIL_OFFSET;
65 bte->bte_error_count++;
67 BTE_PRINTK(("Got an error on cnode %d bte %d: HW error type 0x%x\n",
68 bte->bte_cnode, bte->bte_num, ioe->ie_errortype));
69 bte_error_handler((unsigned long) hinfo->h_nodepda);
74 * Second part error handler. Wait until all BTE related CRBs are completed
75 * and then reset the interfaces.
78 bte_error_handler(unsigned long _nodepda)
80 struct nodepda_s *err_nodepda = (struct nodepda_s *) _nodepda;
81 spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
82 struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
86 unsigned long irq_flags;
88 bte_result_t bh_error;
89 ii_imem_u_t imem; /* II IMEM Register */
90 ii_icrb0_d_u_t icrbd; /* II CRB Register D */
96 BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
99 spin_lock_irqsave(recovery_lock, irq_flags);
101 if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
102 (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
103 BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
104 smp_processor_id()));
105 spin_unlock_irqrestore(recovery_lock, irq_flags);
109 * Lock all interfaces on this node to prevent new transfers
112 for (i = 0; i < BTES_PER_NODE; i++) {
113 if (err_nodepda->bte_if[i].cleanup_active) {
116 spin_lock(&err_nodepda->bte_if[i].spinlock);
117 BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
118 smp_processor_id(), i));
119 err_nodepda->bte_if[i].cleanup_active = 1;
122 /* Determine information about our hub */
123 nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
127 * A BTE transfer can use multiple CRBs. We need to make sure
128 * that all the BTE CRBs are complete (or timed out) before
129 * attempting to clean up the error. Resetting the BTE while
130 * there are still BTE CRBs active will hang the BTE.
131 * We should look at all the CRBs to see if they are allocated
132 * to the BTE and see if they are still active. When none
133 * are active, we can continue with the cleanup.
135 * We also want to make sure that the local NI port is up.
136 * When a router resets the NI port can go down, while it
137 * goes through the LLP handshake, but then comes back up.
139 icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
140 if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
142 * There are errors which still need to be cleaned up by
143 * hubiio_crb_error_handler
145 mod_timer(recovery_timer, HZ * 5);
146 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
147 smp_processor_id()));
148 spin_unlock_irqrestore(recovery_lock, irq_flags);
151 if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
153 valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;
155 for (i = 0; i < IIO_NUM_CRBS; i++) {
156 if (!((1 << i) & valid_crbs)) {
157 /* This crb was not marked as valid, ignore */
160 icrbd.ii_icrb0_d_regval =
161 REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
163 mod_timer(recovery_timer, HZ * 5);
164 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
165 err_nodepda, smp_processor_id(), i));
166 spin_unlock_irqrestore(recovery_lock,
174 BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda,
175 smp_processor_id()));
176 /* Reenable both bte interfaces */
177 imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
178 imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
179 REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
181 /* Clear IBLS0/1 error bits */
182 ieclr.ii_ieclr_regval = 0;
183 if (err_nodepda->bte_if[0].bh_error != BTE_SUCCESS)
184 ieclr.ii_ieclr_fld_s.i_e_bte_0 = 1;
185 if (err_nodepda->bte_if[1].bh_error != BTE_SUCCESS)
186 ieclr.ii_ieclr_fld_s.i_e_bte_1 = 1;
187 REMOTE_HUB_S(nasid, IIO_IECLR, ieclr.ii_ieclr_regval);
189 /* Reinitialize both BTE state machines. */
190 ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
191 ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
192 REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
195 for (i = 0; i < BTES_PER_NODE; i++) {
196 bh_error = err_nodepda->bte_if[i].bh_error;
197 if (bh_error != BTE_SUCCESS) {
198 /* There is an error which needs to be notified */
199 notify = err_nodepda->bte_if[i].most_rcnt_na;
200 BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
201 err_nodepda->bte_if[i].bte_cnode,
202 err_nodepda->bte_if[i].bte_num,
203 IBLS_ERROR | (u64) bh_error));
204 *notify = IBLS_ERROR | bh_error;
205 err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
208 err_nodepda->bte_if[i].cleanup_active = 0;
209 BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
210 smp_processor_id(), i));
211 spin_unlock(&err_nodepda->bte_if[i].spinlock);
214 del_timer(recovery_timer);
216 spin_unlock_irqrestore(recovery_lock, irq_flags);