Update ia64 patch to 2.5.72-030619
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / sn / io / sn2 / bte_error.c
1 /*
2  *
3  *
4  * Copyright (c) 2000-2003 Silicon Graphics, Inc.  All Rights Reserved.
5  * 
6  * This program is free software; you can redistribute it and/or modify it 
7  * under the terms of version 2 of the GNU General Public License 
8  * as published by the Free Software Foundation.
9  * 
10  * This program is distributed in the hope that it would be useful, but 
11  * WITHOUT ANY WARRANTY; without even the implied warranty of 
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
13  * 
14  * Further, this software is distributed without any warranty that it is 
15  * free of the rightful claim of any third person regarding infringement 
16  * or the like.  Any license provided herein, whether implied or 
17  * otherwise, applies only to this software file.  Patent licenses, if 
18  * any, provided herein do not apply to combinations of this program with 
19  * other software, or any other product whatsoever.
20  * 
21  * You should have received a copy of the GNU General Public 
22  * License along with this program; if not, write the Free Software 
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
24  * 
25  * Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 
26  * Mountain View, CA  94043, or:
27  * 
28  * http://www.sgi.com 
29  * 
30  * For further information regarding this notice, see: 
31  * 
32  * http://oss.sgi.com/projects/GenInfo/NoticeExplan
33  */
34
35
36 #include <linux/types.h>
37 #include <linux/slab.h>
38 #include <asm/smp.h>
39 #include <asm/sn/sgi.h>
40 #include <asm/sn/io.h>
41 #include <asm/sn/iograph.h>
42 #include <asm/sn/invent.h>
43 #include <asm/sn/hcl.h>
44 #include <asm/sn/labelcl.h>
45 #include <asm/sn/sn_private.h>
46 #include <asm/sn/klconfig.h>
47 #include <asm/sn/sn_cpuid.h>
48 #include <asm/sn/pci/pciio.h>
49 #include <asm/sn/pci/pcibr.h>
50 #include <asm/sn/xtalk/xtalk.h>
51 #include <asm/sn/pci/pcibr_private.h>
52 #include <asm/sn/intr.h>
53 #include <asm/sn/ioerror.h>
54 #include <asm/sn/sn2/shubio.h>
55 #include <asm/sn/bte.h>
56
57
58 /*
59  * Bte error handling is done in two parts.  The first captures
60  * any crb related errors.  Since there can be multiple crbs per
61  * interface and multiple interfaces active, we need to wait until
62  * all active crbs are completed.  This is the first job of the
63  * second part error handler.  When all bte related CRBs are cleanly
64  * completed, it resets the interfaces and gets them ready for new
65  * transfers to be queued.
66  */
67
68
69 void bte_error_handler(unsigned long);
70
71
72 /*
73  * First part error handler.  This is called whenever any error CRB interrupt
74  * is generated by the II.
75  */
76 void
77 bte_crb_error_handler(vertex_hdl_t hub_v, int btenum,
78                       int crbnum, ioerror_t * ioe, int bteop)
79 {
80         hubinfo_t hinfo;
81         struct bteinfo_s *bte;
82
83
84         hubinfo_get(hub_v, &hinfo);
85         bte = &hinfo->h_nodepda->bte_if[btenum];
86
87         /*
88          * The caller has already figured out the error type, we save that
89          * in the bte handle structure for the thread excercising the
90          * interface to consume.
91          */
92         switch (ioe->ie_errortype) {
93         case IIO_ICRB_ECODE_PERR:
94                 bte->bh_error = BTEFAIL_POISON;
95                 break;
96         case IIO_ICRB_ECODE_WERR:
97                 bte->bh_error = BTEFAIL_PROT;
98                 break;
99         case IIO_ICRB_ECODE_AERR:
100                 bte->bh_error = BTEFAIL_ACCESS;
101                 break;
102         case IIO_ICRB_ECODE_TOUT:
103                 bte->bh_error = BTEFAIL_TOUT;
104                 break;
105         case IIO_ICRB_ECODE_XTERR:
106                 bte->bh_error = BTEFAIL_XTERR;
107                 break;
108         case IIO_ICRB_ECODE_DERR:
109                 bte->bh_error = BTEFAIL_DIR;
110                 break;
111         case IIO_ICRB_ECODE_PWERR:
112         case IIO_ICRB_ECODE_PRERR:
113                 /* NO BREAK */
114         default:
115                 bte->bh_error = BTEFAIL_ERROR;
116         }
117
118         bte->bte_error_count++;
119
120         BTE_PRINTK(("Got an error on cnode %d bte %d\n",
121                     bte->bte_cnode, bte->bte_num));
122         bte_error_handler((unsigned long) hinfo->h_nodepda);
123 }
124
125
126 /*
127  * Second part error handler.  Wait until all BTE related CRBs are completed
128  * and then reset the interfaces.
129  */
130 void
131 bte_error_handler(unsigned long _nodepda)
132 {
133         struct nodepda_s *err_nodepda = (struct nodepda_s *) _nodepda;
134         spinlock_t *recovery_lock = &err_nodepda->bte_recovery_lock;
135         struct timer_list *recovery_timer = &err_nodepda->bte_recovery_timer;
136         nasid_t nasid;
137         int i;
138         int valid_crbs;
139         unsigned long irq_flags;
140         volatile u64 *notify;
141         bte_result_t bh_error;
142         ii_imem_u_t imem;       /* II IMEM Register */
143         ii_icrb0_d_u_t icrbd;   /* II CRB Register D */
144         ii_ibcr_u_t ibcr;
145         ii_icmr_u_t icmr;
146
147
148         BTE_PRINTK(("bte_error_handler(%p) - %d\n", err_nodepda,
149                     smp_processor_id()));
150
151         spin_lock_irqsave(recovery_lock, irq_flags);
152
153         if ((err_nodepda->bte_if[0].bh_error == BTE_SUCCESS) &&
154             (err_nodepda->bte_if[1].bh_error == BTE_SUCCESS)) {
155                 BTE_PRINTK(("eh:%p:%d Nothing to do.\n", err_nodepda,
156                             smp_processor_id()));
157                 spin_unlock_irqrestore(recovery_lock, irq_flags);
158                 return;
159         }
160         /*
161          * Lock all interfaces on this node to prevent new transfers
162          * from being queued.
163          */
164         for (i = 0; i < BTES_PER_NODE; i++) {
165                 if (err_nodepda->bte_if[i].cleanup_active) {
166                         continue;
167                 }
168                 spin_lock(&err_nodepda->bte_if[i].spinlock);
169                 BTE_PRINTK(("eh:%p:%d locked %d\n", err_nodepda,
170                             smp_processor_id(), i));
171                 err_nodepda->bte_if[i].cleanup_active = 1;
172         }
173
174         /* Determine information about our hub */
175         nasid = cnodeid_to_nasid(err_nodepda->bte_if[0].bte_cnode);
176
177
178         /*
179          * A BTE transfer can use multiple CRBs.  We need to make sure
180          * that all the BTE CRBs are complete (or timed out) before
181          * attempting to clean up the error.  Resetting the BTE while
182          * there are still BTE CRBs active will hang the BTE.
183          * We should look at all the CRBs to see if they are allocated
184          * to the BTE and see if they are still active.  When none
185          * are active, we can continue with the cleanup.
186          *
187          * We also want to make sure that the local NI port is up.
188          * When a router resets the NI port can go down, while it
189          * goes through the LLP handshake, but then comes back up.
190          */
191         icmr.ii_icmr_regval = REMOTE_HUB_L(nasid, IIO_ICMR);
192         if (icmr.ii_icmr_fld_s.i_crb_mark != 0) {
193                 /*
194                  * There are errors which still need to be cleaned up by
195                  * hubiio_crb_error_handler
196                  */
197                 mod_timer(recovery_timer, HZ * 5);
198                 BTE_PRINTK(("eh:%p:%d Marked Giving up\n", err_nodepda,
199                             smp_processor_id()));
200                 spin_unlock_irqrestore(recovery_lock, irq_flags);
201                 return;
202         }
203         if (icmr.ii_icmr_fld_s.i_crb_vld != 0) {
204
205                 valid_crbs = icmr.ii_icmr_fld_s.i_crb_vld;
206
207                 for (i = 0; i < IIO_NUM_CRBS; i++) {
208                         if (!((1 << i) & valid_crbs)) {
209                                 /* This crb was not marked as valid, ignore */
210                                 continue;
211                         }
212                         icrbd.ii_icrb0_d_regval =
213                             REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
214                         if (icrbd.d_bteop) {
215                                 mod_timer(recovery_timer, HZ * 5);
216                                 BTE_PRINTK(("eh:%p:%d Valid %d, Giving up\n",
217                                          err_nodepda, smp_processor_id(), i));
218                                 spin_unlock_irqrestore(recovery_lock,
219                                                        irq_flags);
220                                 return;
221                         }
222                 }
223         }
224
225
226         BTE_PRINTK(("eh:%p:%d Cleaning up\n", err_nodepda,
227                     smp_processor_id()));
228         /* Reenable both bte interfaces */
229         imem.ii_imem_regval = REMOTE_HUB_L(nasid, IIO_IMEM);
230         imem.ii_imem_fld_s.i_b0_esd = imem.ii_imem_fld_s.i_b1_esd = 1;
231         REMOTE_HUB_S(nasid, IIO_IMEM, imem.ii_imem_regval);
232
233         /* Reinitialize both BTE state machines. */
234         ibcr.ii_ibcr_regval = REMOTE_HUB_L(nasid, IIO_IBCR);
235         ibcr.ii_ibcr_fld_s.i_soft_reset = 1;
236         REMOTE_HUB_S(nasid, IIO_IBCR, ibcr.ii_ibcr_regval);
237
238
239         for (i = 0; i < BTES_PER_NODE; i++) {
240                 bh_error = err_nodepda->bte_if[i].bh_error;
241                 if (bh_error != BTE_SUCCESS) {
242                         /* There is an error which needs to be notified */
243                         notify = err_nodepda->bte_if[i].most_rcnt_na;
244                         BTE_PRINTK(("cnode %d bte %d error=0x%lx\n",
245                                     err_nodepda->bte_if[i].bte_cnode,
246                                     err_nodepda->bte_if[i].bte_num,
247                                     IBLS_ERROR | (u64) bh_error));
248                         *notify = IBLS_ERROR | bh_error;
249                         err_nodepda->bte_if[i].bh_error = BTE_SUCCESS;
250                 }
251
252                 err_nodepda->bte_if[i].cleanup_active = 0;
253                 BTE_PRINTK(("eh:%p:%d Unlocked %d\n", err_nodepda,
254                             smp_processor_id(), i));
255                 spin_unlock(&pda->cpu_bte_if[i]->spinlock);
256         }
257
258         del_timer(recovery_timer);
259
260         spin_unlock_irqrestore(recovery_lock, irq_flags);
261 }