Update ia64 patch to 2.5.72-030619
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / sn / io / sn2 / xbow.c
1 /* $Id$
2  *
3  * This file is subject to the terms and conditions of the GNU General Public
4  * License.  See the file "COPYING" in the main directory of this archive
5  * for more details.
6  *
7  * Copyright (c) 1992-1997,2000-2003 Silicon Graphics, Inc. All rights reserved.
8  */
9
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <linux/module.h>
13 #include <linux/sched.h>
14 #include <linux/interrupt.h>
15 #include <asm/sn/sgi.h>
16 #include <asm/sn/intr.h>
17 #include <asm/sn/sn2/sn_private.h>
18 #include <asm/sn/sn2/shubio.h>
19 #include <asm/sn/iograph.h>
20 #include <asm/sn/invent.h>
21 #include <asm/sn/hcl.h>
22 #include <asm/sn/labelcl.h>
23 #include <asm/sn/pci/bridge.h>
24 #include <asm/sn/xtalk/xtalk_private.h>
25 #include <asm/sn/simulator.h>
26
27 /* #define DEBUG                1 */
28 /* #define XBOW_DEBUG   1 */
29 /* #define DEBUG_ERROR  1 */
30
31
32 /*
33  * Files needed to get the device driver entry points
34  */
35
36 #include <asm/sn/xtalk/xbow.h>
37 #include <asm/sn/xtalk/xtalk.h>
38 #include <asm/sn/xtalk/xswitch.h>
39 #include <asm/sn/xtalk/xwidget.h>
40
41 #include <asm/sn/prio.h>
42 #include <asm/sn/hcl_util.h>
43
44
45 #define NEW(ptr)        (ptr = kmalloc(sizeof (*(ptr)), GFP_KERNEL))
46 #define DEL(ptr)        (kfree(ptr))
47
48 /*
49  * This file supports the Xbow chip.  Main functions: initializtion,
50  * error handling, and GBR.
51  */
52
53 /*
54  * each vertex corresponding to an xbow chip
55  * has a "fastinfo" pointer pointing at one
56  * of these things.
57  */
58 typedef struct xbow_soft_s *xbow_soft_t;
59
60 struct xbow_soft_s {
61     vertex_hdl_t            conn;       /* our connection point */
62     vertex_hdl_t            vhdl;       /* xbow's private vertex */
63     vertex_hdl_t            busv;       /* the xswitch vertex */
64     xbow_t                 *base;       /* PIO pointer to crossbow chip */
65     char                   *name;       /* hwgraph name */
66
67     xbow_perf_t             xbow_perfcnt[XBOW_PERF_COUNTERS];
68     xbow_perf_link_t        xbow_perflink[MAX_XBOW_PORTS];
69     xbow_link_status_t      xbow_link_status[MAX_XBOW_PORTS];
70     spinlock_t              xbow_perf_lock;
71     int                     link_monitor;
72     widget_cfg_t           *wpio[MAX_XBOW_PORTS];       /* cached PIO pointer */
73
74     /* Bandwidth allocation state. Bandwidth values are for the
75      * destination port since contention happens there.
76      * Implicit mapping from xbow ports (8..f) -> (0..7) array indices.
77      */
78     spinlock_t              xbow_bw_alloc_lock;         /* bw allocation lock */
79     unsigned long long      bw_hiwm[MAX_XBOW_PORTS];    /* hiwater mark values */
80     unsigned long long      bw_cur_used[MAX_XBOW_PORTS]; /* bw used currently */
81 };
82
83 #define xbow_soft_set(v,i)      hwgraph_fastinfo_set((v), (arbitrary_info_t)(i))
84 #define xbow_soft_get(v)        ((xbow_soft_t)hwgraph_fastinfo_get((v)))
85
86 /*
87  * Function Table of Contents
88  */
89
90 void                    xbow_mlreset(xbow_t *);
91 int                     xbow_attach(vertex_hdl_t);
92
93 int                     xbow_widget_present(xbow_t *, int);
94 static int              xbow_link_alive(xbow_t *, int);
95 vertex_hdl_t            xbow_widget_lookup(vertex_hdl_t, int);
96
97 void                    xbow_intr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
98
99
100
101 void                    xbow_update_perf_counters(vertex_hdl_t);
102 xbow_perf_link_t       *xbow_get_perf_counters(vertex_hdl_t);
103 int                     xbow_enable_perf_counter(vertex_hdl_t, int, int, int);
104 xbow_link_status_t     *xbow_get_llp_status(vertex_hdl_t);
105 void                    xbow_update_llp_status(vertex_hdl_t);
106
107 int                     xbow_disable_llp_monitor(vertex_hdl_t);
108 int                     xbow_enable_llp_monitor(vertex_hdl_t);
109 int                     xbow_prio_bw_alloc(vertex_hdl_t, xwidgetnum_t, xwidgetnum_t,
110                                 unsigned long long, unsigned long long);
111 static void             xbow_setwidint(xtalk_intr_t);
112
113 xswitch_reset_link_f    xbow_reset_link;
114
115 xswitch_provider_t      xbow_provider =
116 {
117     xbow_reset_link,
118 };
119
120
121 static int
122 xbow_mmap(struct file * file, struct vm_area_struct * vma)
123 {
124         unsigned long           phys_addr;
125         int                     error = 0;
126
127         phys_addr = (unsigned long)file->private_data & ~0xc000000000000000; /* Mask out the Uncache bits */
128         vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
129         vma->vm_flags |= VM_RESERVED | VM_IO;
130         error = io_remap_page_range(vma, phys_addr, vma->vm_start,
131                                    vma->vm_end-vma->vm_start,
132                                    vma->vm_page_prot);
133         return(error);
134 }
135
136 /*
137  * This is the file operation table for the pcibr driver.
138  * As each of the functions are implemented, put the
139  * appropriate function name below.
140  */
141 struct file_operations xbow_fops = {
142         .owner          = THIS_MODULE,
143         .mmap           = xbow_mmap,
144 };
145
146 /*
147  *    xbow_mlreset: called at mlreset time if the
148  *      platform specific code determines that there is
149  *      a crossbow in a critical path that must be
150  *      functional before the driver would normally get
151  *      the device properly set up.
152  *
153  *      what do we need to do, that the boot prom can
154  *      not be counted on to have already done, that is
155  *      generic across all platforms using crossbows?
156  */
157 /*ARGSUSED */
158 void
159 xbow_mlreset(xbow_t * xbow)
160 {
161 }
162
163 #ifdef XBRIDGE_REGS_SIM
164 /*    xbow_set_simulated_regs: sets xbow regs as needed
165  *      for powering through the boot
166  */
167 void
168 xbow_set_simulated_regs(xbow_t *xbow, int port)
169 {
170     /*
171      * turn on link
172      */
173     xbow->xb_link(port).link_status = (1<<31);
174     /*
175      * and give it a live widget too
176      */
177     xbow->xb_link(port).link_aux_status = XB_AUX_STAT_PRESENT;
178     /*
179      * zero the link control reg
180      */
181     xbow->xb_link(port).link_control = 0x0;
182 }
183 #endif /* XBRIDGE_REGS_SIM */
184
185 /*
186  *    xbow_attach: the crosstalk provider has
187  *      determined that there is a crossbow widget
188  *      present, and has handed us the connection
189  *      point for that vertex.
190  *
191  *      We not only add our own vertex, but add
192  *      some "xtalk switch" data to the switch
193  *      vertex (at the connect point's parent) if
194  *      it does not have any.
195  */
196
197 /*ARGSUSED */
198 int
199 xbow_attach(vertex_hdl_t conn)
200 {
201     /*REFERENCED */
202     vertex_hdl_t            vhdl;
203     vertex_hdl_t            busv;
204     xbow_t                 *xbow;
205     xbow_soft_t             soft;
206     int                     port;
207     xswitch_info_t          info;
208     xtalk_intr_t            intr_hdl;
209     char                    devnm[MAXDEVNAME], *s;
210     xbowreg_t               id;
211     int                     rev;
212     int                     i;
213     int                     xbow_num;
214     static void xbow_errintr_handler(int, void *, struct pt_regs *);
215
216         
217 #if DEBUG && ATTACH_DEBUG
218 #if defined(SUPPORT_PRINTING_V_FORMAT)
219     printk("%v: xbow_attach\n", conn);
220 #else
221     printk("0x%x: xbow_attach\n", conn);
222 #endif
223 #endif
224
225     /*
226      * Get a PIO pointer to the base of the crossbow
227      * chip.
228      */
229 #ifdef XBRIDGE_REGS_SIM
230     printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: allocating %ld bytes for xbow_s\n", sizeof(xbow_t));
231     xbow = (xbow_t *) kmalloc(sizeof(xbow_t), GFP_KERNEL);
232     /*
233      * turn on ports e and f like in a real live ibrick
234      */
235     xbow_set_simulated_regs(xbow, 0xe);
236     xbow_set_simulated_regs(xbow, 0xf);
237 #else
238     xbow = (xbow_t *) xtalk_piotrans_addr(conn, 0, 0, sizeof(xbow_t), 0);
239 #endif /* XBRIDGE_REGS_SIM */
240
241     /*
242      * Locate the "switch" vertex: it is the parent
243      * of our connection point.
244      */
245     busv = hwgraph_connectpt_get(conn);
246 #if DEBUG && ATTACH_DEBUG
247     printk("xbow_attach: Bus Vertex 0x%p, conn 0x%p, xbow register 0x%p wid= 0x%x\n", busv, conn, xbow, *(volatile u32 *)xbow);
248 #endif
249
250     ASSERT(busv != GRAPH_VERTEX_NONE);
251
252     /*
253      * Create our private vertex, and connect our
254      * driver information to it. This makes it possible
255      * for diagnostic drivers to open the crossbow
256      * vertex for access to registers.
257      */
258
259     /*
260      * Register a xbow driver with devfs.
261      * file ops.
262      */
263     vhdl = NULL;
264     vhdl = hwgraph_register(conn, EDGE_LBL_XBOW, 0,
265            0, 0, 0,
266            S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
267            (struct file_operations *)&xbow_fops, (void *)xbow);
268     if (!vhdl) {
269         printk(KERN_WARNING "xbow_attach: Unable to create char device for xbow conn %p\n",
270                 (void *)conn);
271     }
272
273     /*
274      * Allocate the soft state structure and attach
275      * it to the xbow's vertex
276      */
277     NEW(soft);
278     soft->conn = conn;
279     soft->vhdl = vhdl;
280     soft->busv = busv;
281     soft->base = xbow;
282     /* does the universe really need another macro?  */
283     /* xbow_soft_set(vhdl, (arbitrary_info_t) soft); */
284     /* hwgraph_fastinfo_set(vhdl, (arbitrary_info_t) soft); */
285
286 #define XBOW_NUM_SUFFIX_FORMAT  "[xbow# %d]"
287
288     /* Add xbow number as a suffix to the hwgraph name of the xbow.
289      * This is helpful while looking at the error/warning messages.
290      */
291     xbow_num = 0;
292
293     /*
294      * get the name of this xbow vertex and keep the info.
295      * This is needed during errors and interupts, but as
296      * long as we have it, we can use it elsewhere.
297      */
298     s = dev_to_name(vhdl, devnm, MAXDEVNAME);
299     soft->name = kmalloc(strlen(s) + strlen(XBOW_NUM_SUFFIX_FORMAT) + 1, 
300                             GFP_KERNEL);
301     sprintf(soft->name,"%s"XBOW_NUM_SUFFIX_FORMAT, s,xbow_num);
302
303 #ifdef XBRIDGE_REGS_SIM
304     /* my o200/ibrick has id=0x2d002049, but XXBOW_WIDGET_PART_NUM is defined
305      * as 0xd000, so I'm using that for the partnum bitfield.
306      */
307     printk("xbow_attach: XBRIDGE_REGS_SIM FIXME: need xb_wid_id value!!\n");
308     id = 0x2d000049;
309 #else
310     id = xbow->xb_wid_id;
311 #endif /* XBRIDGE_REGS_SIM */
312     rev = XWIDGET_PART_REV_NUM(id);
313
314     mutex_spinlock_init(&soft->xbow_perf_lock);
315     soft->xbow_perfcnt[0].xp_perf_reg = &xbow->xb_perf_ctr_a;
316     soft->xbow_perfcnt[1].xp_perf_reg = &xbow->xb_perf_ctr_b;
317
318     /* Initialization for GBR bw allocation */
319     mutex_spinlock_init(&soft->xbow_bw_alloc_lock);
320
321 #define XBOW_8_BIT_PORT_BW_MAX          (400 * 1000 * 1000)     /* 400 MB/s */
322 #define XBOW_16_BIT_PORT_BW_MAX         (800 * 1000 * 1000)     /* 800 MB/s */
323
324     /* Set bandwidth hiwatermark and current values */
325     for (i = 0; i < MAX_XBOW_PORTS; i++) {
326         soft->bw_hiwm[i] = XBOW_16_BIT_PORT_BW_MAX;     /* for now */
327         soft->bw_cur_used[i] = 0;
328     }
329
330      /*
331       * attach the crossbow error interrupt.
332       */
333      intr_hdl = xtalk_intr_alloc(conn, (device_desc_t)0, vhdl);
334      ASSERT(intr_hdl != NULL);
335
336         {
337                 int irq = ((hub_intr_t)intr_hdl)->i_bit;
338                 int cpu = ((hub_intr_t)intr_hdl)->i_cpuid;
339
340                 intr_unreserve_level(cpu, irq);
341                 ((hub_intr_t)intr_hdl)->i_bit = SGI_XBOW_ERROR;
342         }
343  
344      xtalk_intr_connect(intr_hdl,
345                         (intr_func_t) xbow_errintr_handler,
346                         (intr_arg_t) soft,
347                         (xtalk_intr_setfunc_t) xbow_setwidint,
348                         (void *) xbow);
349
350      request_irq(SGI_XBOW_ERROR, (void *)xbow_errintr_handler, SA_SHIRQ, "XBOW error",
351                         (intr_arg_t) soft);
352
353  
354     /*
355      * Enable xbow error interrupts
356      */
357     xbow->xb_wid_control = (XB_WID_CTRL_REG_ACC_IE | XB_WID_CTRL_XTALK_IE);
358
359     /*
360      * take a census of the widgets present,
361      * leaving notes at the switch vertex.
362      */
363     info = xswitch_info_new(busv);
364
365     for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
366          port < MAX_PORT_NUM; ++port) {
367         if (!xbow_link_alive(xbow, port)) {
368 #if DEBUG && XBOW_DEBUG
369             printk(KERN_INFO "0x%p link %d is not alive\n",
370                     (void *)busv, port);
371 #endif
372             continue;
373         }
374         if (!xbow_widget_present(xbow, port)) {
375 #if DEBUG && XBOW_DEBUG
376             printk(KERN_INFO "0x%p link %d is alive but no widget is present\n", (void *)busv, port);
377 #endif
378             continue;
379         }
380 #if DEBUG && XBOW_DEBUG
381         printk(KERN_INFO "0x%p link %d has a widget\n",
382                 (void *)busv, port);
383 #endif
384
385         xswitch_info_link_is_ok(info, port);
386         /*
387          * Turn some error interrupts on
388          * and turn others off. The PROM has
389          * some things turned on we don't
390          * want to see (bandwidth allocation
391          * errors for instance); so if it
392          * is not listed here, it is not on.
393          */
394         xbow->xb_link(port).link_control =
395             ( (xbow->xb_link(port).link_control
396         /*
397          * Turn off these bits; they are non-fatal,
398          * but we might want to save some statistics
399          * on the frequency of these errors.
400          * XXX FIXME XXX
401          */
402             & ~XB_CTRL_RCV_CNT_OFLOW_IE
403             & ~XB_CTRL_XMT_CNT_OFLOW_IE
404             & ~XB_CTRL_BNDWDTH_ALLOC_IE
405             & ~XB_CTRL_RCV_IE)
406         /*
407          * These are the ones we want to turn on.
408          */
409             | (XB_CTRL_ILLEGAL_DST_IE
410             | XB_CTRL_OALLOC_IBUF_IE
411             | XB_CTRL_XMT_MAX_RTRY_IE
412             | XB_CTRL_MAXREQ_TOUT_IE
413             | XB_CTRL_XMT_RTRY_IE
414             | XB_CTRL_SRC_TOUT_IE) );
415     }
416
417     xswitch_provider_register(busv, &xbow_provider);
418
419     return 0;                           /* attach successful */
420 }
421
422 /* This contains special-case code for grio. There are plans to make
423  * this general sometime in the future, but till then this should
424  * be good enough.
425  */
426 xwidgetnum_t
427 xbow_widget_num_get(vertex_hdl_t dev)
428 {
429         vertex_hdl_t    tdev;
430         char            devname[MAXDEVNAME];
431         xwidget_info_t  xwidget_info;
432         int             i;
433
434         vertex_to_name(dev, devname, MAXDEVNAME);
435
436         /* If this is a pci controller vertex, traverse up using
437          * the ".." links to get to the widget.
438          */
439         if (strstr(devname, EDGE_LBL_PCI) &&
440                         strstr(devname, EDGE_LBL_CONTROLLER)) {
441                 tdev = dev;
442                 for (i=0; i< 2; i++) {
443                         if (hwgraph_edge_get(tdev,
444                                 HWGRAPH_EDGELBL_DOTDOT, &tdev) !=
445                                         GRAPH_SUCCESS)
446                                 return XWIDGET_NONE;
447                 }
448
449                 if ((xwidget_info = xwidget_info_chk(tdev)) != NULL) {
450                         return (xwidget_info_id_get(xwidget_info));
451                 } else {
452                         return XWIDGET_NONE;
453                 }
454         }
455
456         return XWIDGET_NONE;
457 }
458
459 /*
460  * xbow_widget_present: See if a device is present
461  * on the specified port of this crossbow.
462  */
463 int
464 xbow_widget_present(xbow_t *xbow, int port)
465 {
466         if ( IS_RUNNING_ON_SIMULATOR() ) {
467                 if ( (port == 14) || (port == 15) ) {
468                         return 1;
469                 }
470                 else {
471                         return 0;
472                 }
473         }
474         else {
475                 /* WAR: port 0xf on PIC is missing present bit */
476                 if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
477                                         IS_PIC_XBOW(xbow->xb_wid_id) && port==0xf) {
478                         return 1;
479                 }
480                 return xbow->xb_link(port).link_aux_status & XB_AUX_STAT_PRESENT;
481         }
482 }
483
484 static int
485 xbow_link_alive(xbow_t * xbow, int port)
486 {
487     xbwX_stat_t             xbow_linkstat;
488
489     xbow_linkstat.linkstatus = xbow->xb_link(port).link_status;
490     return (xbow_linkstat.link_alive);
491 }
492
493 /*
494  * xbow_widget_lookup
495  *      Lookup the edges connected to the xbow specified, and
496  *      retrieve the handle corresponding to the widgetnum
497  *      specified.
498  *      If not found, return 0.
499  */
500 vertex_hdl_t
501 xbow_widget_lookup(vertex_hdl_t vhdl,
502                    int widgetnum)
503 {
504     xswitch_info_t          xswitch_info;
505     vertex_hdl_t            conn;
506
507     xswitch_info = xswitch_info_get(vhdl);
508     conn = xswitch_info_vhdl_get(xswitch_info, widgetnum);
509     return conn;
510 }
511
512 /*
513  * xbow_setwidint: called when xtalk
514  * is establishing or migrating our
515  * interrupt service.
516  */
517 static void
518 xbow_setwidint(xtalk_intr_t intr)
519 {
520     xwidgetnum_t            targ = xtalk_intr_target_get(intr);
521     iopaddr_t               addr = xtalk_intr_addr_get(intr);
522     xtalk_intr_vector_t     vect = xtalk_intr_vector_get(intr);
523     xbow_t                 *xbow = (xbow_t *) xtalk_intr_sfarg_get(intr);
524
525     xbow_intr_preset((void *) xbow, 0, targ, addr, vect);
526 }
527
528 /*
529  * xbow_intr_preset: called during mlreset time
530  * if the platform specific code needs to route
531  * an xbow interrupt before the xtalk infrastructure
532  * is available for use.
533  *
534  * Also called from xbow_setwidint, so we don't
535  * replicate the guts of the routine.
536  *
537  * XXX- probably should be renamed xbow_wid_intr_set or
538  * something to reduce confusion.
539  */
540 /*ARGSUSED3 */
541 void
542 xbow_intr_preset(void *which_widget,
543                  int which_widget_intr,
544                  xwidgetnum_t targ,
545                  iopaddr_t addr,
546                  xtalk_intr_vector_t vect)
547 {
548     xbow_t                 *xbow = (xbow_t *) which_widget;
549
550     xbow->xb_wid_int_upper = ((0xFF000000 & (vect << 24)) |
551                               (0x000F0000 & (targ << 16)) |
552                               XTALK_ADDR_TO_UPPER(addr));
553     xbow->xb_wid_int_lower = XTALK_ADDR_TO_LOWER(addr);
554
555 }
556
557 #define XEM_ADD_STR(s)          printk("%s", (s))
558 #define XEM_ADD_NVAR(n,v)       printk("\t%20s: 0x%llx\n", (n), ((unsigned long long)v))
559 #define XEM_ADD_VAR(v)          XEM_ADD_NVAR(#v,(v))
560 #define XEM_ADD_IOEF(p,n)       if (IOERROR_FIELDVALID(ioe,n)) {        \
561                                     IOERROR_GETVALUE(p,ioe,n);          \
562                                     XEM_ADD_NVAR("ioe." #n, p);         \
563                                 }
564
565 int                     xbow_xmit_retry_errors;
566
567 int
568 xbow_xmit_retry_error(xbow_soft_t soft,
569                       int port)
570 {
571     xswitch_info_t          info;
572     vertex_hdl_t            vhdl;
573     widget_cfg_t           *wid;
574     widgetreg_t             id;
575     int                     part;
576     int                     mfgr;
577
578     wid = soft->wpio[port - BASE_XBOW_PORT];
579     if (wid == NULL) {
580         /* If we can't track down a PIO
581          * pointer to our widget yet,
582          * leave our caller knowing that
583          * we are interested in this
584          * interrupt if it occurs in
585          * the future.
586          */
587         info = xswitch_info_get(soft->busv);
588         if (!info)
589             return 1;
590         vhdl = xswitch_info_vhdl_get(info, port);
591         if (vhdl == GRAPH_VERTEX_NONE)
592             return 1;
593         wid = (widget_cfg_t *) xtalk_piotrans_addr
594             (vhdl, 0, 0, sizeof *wid, 0);
595         if (!wid)
596             return 1;
597         soft->wpio[port - BASE_XBOW_PORT] = wid;
598     }
599     id = wid->w_id;
600     part = XWIDGET_PART_NUM(id);
601     mfgr = XWIDGET_MFG_NUM(id);
602
603     /* If this thing is not a Bridge,
604      * do not activate the WAR, and
605      * tell our caller we do not need
606      * to be called again.
607      */
608     if ((part != BRIDGE_WIDGET_PART_NUM) ||
609         (mfgr != BRIDGE_WIDGET_MFGR_NUM)) {
610                 /* FIXME: add Xbridge to the WAR.
611                  * Shouldn't hurt anything.  Later need to
612                  * check if we can remove this.
613                  */
614                 if ((part != XBRIDGE_WIDGET_PART_NUM) ||
615                     (mfgr != XBRIDGE_WIDGET_MFGR_NUM))
616                         return 0;
617     }
618
619     /* count how many times we
620      * have picked up after
621      * LLP Transmit problems.
622      */
623     xbow_xmit_retry_errors++;
624
625     /* rewrite the control register
626      * to fix things up.
627      */
628     wid->w_control = wid->w_control;
629     wid->w_control;
630
631     return 1;
632 }
633
634 /*
635  * xbow_errintr_handler will be called if the xbow
636  * sends an interrupt request to report an error.
637  */
638 static void
639 xbow_errintr_handler(int irq, void *arg, struct pt_regs *ep)
640 {
641     ioerror_t               ioe[1];
642     xbow_soft_t             soft = (xbow_soft_t) arg;
643     xbow_t                 *xbow = soft->base;
644     xbowreg_t               wid_control;
645     xbowreg_t               wid_stat;
646     xbowreg_t               wid_err_cmdword;
647     xbowreg_t               wid_err_upper;
648     xbowreg_t               wid_err_lower;
649     w_err_cmd_word_u        wid_err;
650     unsigned long long      wid_err_addr;
651
652     int                     fatal = 0;
653     int                     dump_ioe = 0;
654     static int xbow_error_handler(void *, int, ioerror_mode_t, ioerror_t *);
655
656     wid_control = xbow->xb_wid_control;
657     wid_stat = xbow->xb_wid_stat_clr;
658     wid_err_cmdword = xbow->xb_wid_err_cmdword;
659     wid_err_upper = xbow->xb_wid_err_upper;
660     wid_err_lower = xbow->xb_wid_err_lower;
661     xbow->xb_wid_err_cmdword = 0;
662
663     wid_err_addr = wid_err_lower | (((iopaddr_t) wid_err_upper & WIDGET_ERR_UPPER_ADDR_ONLY) << 32);
664
665     if (wid_stat & XB_WID_STAT_LINK_INTR_MASK) {
666         int                     port;
667
668         wid_err.r = wid_err_cmdword;
669
670         for (port = MAX_PORT_NUM - MAX_XBOW_PORTS;
671              port < MAX_PORT_NUM; port++) {
672             if (wid_stat & XB_WID_STAT_LINK_INTR(port)) {
673                 xb_linkregs_t          *link = &(xbow->xb_link(port));
674                 xbowreg_t               link_control = link->link_control;
675                 xbowreg_t               link_status = link->link_status_clr;
676                 xbowreg_t               link_aux_status = link->link_aux_status;
677                 xbowreg_t               link_pend;
678
679                 link_pend = link_status & link_control &
680                     (XB_STAT_ILLEGAL_DST_ERR
681                      | XB_STAT_OALLOC_IBUF_ERR
682                      | XB_STAT_RCV_CNT_OFLOW_ERR
683                      | XB_STAT_XMT_CNT_OFLOW_ERR
684                      | XB_STAT_XMT_MAX_RTRY_ERR
685                      | XB_STAT_RCV_ERR
686                      | XB_STAT_XMT_RTRY_ERR
687                      | XB_STAT_MAXREQ_TOUT_ERR
688                      | XB_STAT_SRC_TOUT_ERR
689                     );
690
691                 if (link_pend & XB_STAT_ILLEGAL_DST_ERR) {
692                     if (wid_err.f.sidn == port) {
693                         IOERROR_INIT(ioe);
694                         IOERROR_SETVALUE(ioe, widgetnum, port);
695                         IOERROR_SETVALUE(ioe, xtalkaddr, wid_err_addr);
696                         if (IOERROR_HANDLED ==
697                             xbow_error_handler(soft,
698                                                IOECODE_DMA,
699                                                MODE_DEVERROR,
700                                                ioe)) {
701                             link_pend &= ~XB_STAT_ILLEGAL_DST_ERR;
702                         } else {
703                             dump_ioe++;
704                         }
705                     }
706                 }
707                 /* Xbow/Bridge WAR:
708                  * if the bridge signals an LLP Transmitter Retry,
709                  * rewrite its control register.
710                  * If someone else triggers this interrupt,
711                  * ignore (and disable) the interrupt.
712                  */
713                 if (link_pend & XB_STAT_XMT_RTRY_ERR) {
714                     if (!xbow_xmit_retry_error(soft, port)) {
715                         link_control &= ~XB_CTRL_XMT_RTRY_IE;
716                         link->link_control = link_control;
717                         link->link_control;     /* stall until written */
718                     }
719                     link_pend &= ~XB_STAT_XMT_RTRY_ERR;
720                 }
721                 if (link_pend) {
722                     vertex_hdl_t        xwidget_vhdl;
723                     char                *xwidget_name;
724                     
725                     /* Get the widget name corresponding to the current
726                      * xbow link.
727                      */
728                     xwidget_vhdl = xbow_widget_lookup(soft->busv,port);
729                     xwidget_name = xwidget_name_get(xwidget_vhdl);
730
731                     printk("%s port %X[%s] XIO Bus Error",
732                             soft->name, port, xwidget_name);
733                     if (link_status & XB_STAT_MULTI_ERR)
734                         XEM_ADD_STR("\tMultiple Errors\n");
735                     if (link_status & XB_STAT_ILLEGAL_DST_ERR)
736                         XEM_ADD_STR("\tInvalid Packet Destination\n");
737                     if (link_status & XB_STAT_OALLOC_IBUF_ERR)
738                         XEM_ADD_STR("\tInput Overallocation Error\n");
739                     if (link_status & XB_STAT_RCV_CNT_OFLOW_ERR)
740                         XEM_ADD_STR("\tLLP receive error counter overflow\n");
741                     if (link_status & XB_STAT_XMT_CNT_OFLOW_ERR)
742                         XEM_ADD_STR("\tLLP transmit retry counter overflow\n");
743                     if (link_status & XB_STAT_XMT_MAX_RTRY_ERR)
744                         XEM_ADD_STR("\tLLP Max Transmitter Retry\n");
745                     if (link_status & XB_STAT_RCV_ERR)
746                         XEM_ADD_STR("\tLLP Receiver error\n");
747                     if (link_status & XB_STAT_XMT_RTRY_ERR)
748                         XEM_ADD_STR("\tLLP Transmitter Retry\n");
749                     if (link_status & XB_STAT_MAXREQ_TOUT_ERR)
750                         XEM_ADD_STR("\tMaximum Request Timeout\n");
751                     if (link_status & XB_STAT_SRC_TOUT_ERR)
752                         XEM_ADD_STR("\tSource Timeout Error\n");
753
754                     {
755                         int                     other_port;
756
757                         for (other_port = 8; other_port < 16; ++other_port) {
758                             if (link_aux_status & (1 << other_port)) {
759                                 /* XXX- need to go to "other_port"
760                                  * and clean up after the timeout?
761                                  */
762                                 XEM_ADD_VAR(other_port);
763                             }
764                         }
765                     }
766
767 #if !DEBUG
768                     if (kdebug) {
769 #endif
770                         XEM_ADD_VAR(link_control);
771                         XEM_ADD_VAR(link_status);
772                         XEM_ADD_VAR(link_aux_status);
773
774 #if !DEBUG
775                     }
776 #endif
777                     fatal++;
778                 }
779             }
780         }
781     }
782     if (wid_stat & wid_control & XB_WID_STAT_WIDGET0_INTR) {
783         /* we have a "widget zero" problem */
784
785         if (wid_stat & (XB_WID_STAT_MULTI_ERR
786                         | XB_WID_STAT_XTALK_ERR
787                         | XB_WID_STAT_REG_ACC_ERR)) {
788
789             printk("%s Port 0 XIO Bus Error",
790                     soft->name);
791             if (wid_stat & XB_WID_STAT_MULTI_ERR)
792                 XEM_ADD_STR("\tMultiple Error\n");
793             if (wid_stat & XB_WID_STAT_XTALK_ERR)
794                 XEM_ADD_STR("\tXIO Error\n");
795             if (wid_stat & XB_WID_STAT_REG_ACC_ERR)
796                 XEM_ADD_STR("\tRegister Access Error\n");
797
798             fatal++;
799         }
800     }
801     if (fatal) {
802         XEM_ADD_VAR(wid_stat);
803         XEM_ADD_VAR(wid_control);
804         XEM_ADD_VAR(wid_err_cmdword);
805         XEM_ADD_VAR(wid_err_upper);
806         XEM_ADD_VAR(wid_err_lower);
807         XEM_ADD_VAR(wid_err_addr);
808         PRINT_PANIC("XIO Bus Error");
809     }
810 }
811
812 /*
813  * XBOW ERROR Handling routines.
814  * These get invoked as part of walking down the error handling path
815  * from hub/heart towards the I/O device that caused the error.
816  */
817
818 /*
819  * xbow_error_handler
820  *      XBow error handling dispatch routine.
821  *      This is the primary interface used by external world to invoke
822  *      in case of an error related to a xbow.
823  *      Only functionality in this layer is to identify the widget handle
824  *      given the widgetnum. Otherwise, xbow does not gathers any error
825  *      data.
826  */
827 static int
828 xbow_error_handler(
829                       void *einfo,
830                       int error_code,
831                       ioerror_mode_t mode,
832                       ioerror_t *ioerror)
833 {
834     int                     retval = IOERROR_WIDGETLEVEL;
835
836     xbow_soft_t             soft = (xbow_soft_t) einfo;
837     int                     port;
838     vertex_hdl_t          conn;
839     vertex_hdl_t          busv;
840
841     xbow_t                 *xbow = soft->base;
842     xbowreg_t               wid_stat;
843     xbowreg_t               wid_err_cmdword;
844     xbowreg_t               wid_err_upper;
845     xbowreg_t               wid_err_lower;
846     unsigned long long      wid_err_addr;
847
848     xb_linkregs_t          *link;
849     xbowreg_t               link_control;
850     xbowreg_t               link_status;
851     xbowreg_t               link_aux_status;
852
853     ASSERT(soft != 0);
854     busv = soft->busv;
855
856 #if DEBUG && ERROR_DEBUG
857     printk("%s: xbow_error_handler\n", soft->name, busv);
858 #endif
859
860     IOERROR_GETVALUE(port, ioerror, widgetnum);
861
862     if (port == 0) {
863         /* error during access to xbow:
864          * do NOT attempt to access xbow regs.
865          */
866         if (mode == MODE_DEVPROBE)
867             return IOERROR_HANDLED;
868
869         if (error_code & IOECODE_DMA) {
870             printk(KERN_ALERT
871                     "DMA error blamed on Crossbow at %s\n"
872                     "\tbut Crosbow never initiates DMA!",
873                     soft->name);
874         }
875         if (error_code & IOECODE_PIO) {
876             iopaddr_t tmp;
877             IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
878             printk(KERN_ALERT "PIO Error on XIO Bus %s\n"
879                     "\tattempting to access XIO controller\n"
880                     "\twith offset 0x%lx",
881                     soft->name, tmp);
882         }
883         /* caller will dump contents of ioerror
884          * in DEBUG and kdebug kernels.
885          */
886
887         return retval;
888     }
889     /*
890      * error not on port zero:
891      * safe to read xbow registers.
892      */
893     wid_stat = xbow->xb_wid_stat;
894     wid_err_cmdword = xbow->xb_wid_err_cmdword;
895     wid_err_upper = xbow->xb_wid_err_upper;
896     wid_err_lower = xbow->xb_wid_err_lower;
897
898     wid_err_addr =
899         wid_err_lower
900         | (((iopaddr_t) wid_err_upper
901             & WIDGET_ERR_UPPER_ADDR_ONLY)
902            << 32);
903
904     if ((port < BASE_XBOW_PORT) ||
905         (port >= MAX_PORT_NUM)) {
906
907         if (mode == MODE_DEVPROBE)
908             return IOERROR_HANDLED;
909
910         if (error_code & IOECODE_DMA) {
911             printk(KERN_ALERT
912                     "DMA error blamed on XIO port at %s/%d\n"
913                     "\tbut Crossbow does not support that port",
914                     soft->name, port);
915         }
916         if (error_code & IOECODE_PIO) {
917             iopaddr_t tmp;
918             IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
919             printk(KERN_ALERT
920                     "PIO Error on XIO Bus %s\n"
921                     "\tattempting to access XIO port %d\n"
922                     "\t(which Crossbow does not support)"
923                     "\twith offset 0x%lx",
924                     soft->name, port, tmp);
925         }
926 #if !DEBUG
927         if (kdebug) {
928 #endif
929             XEM_ADD_STR("Raw status values for Crossbow:\n");
930             XEM_ADD_VAR(wid_stat);
931             XEM_ADD_VAR(wid_err_cmdword);
932             XEM_ADD_VAR(wid_err_upper);
933             XEM_ADD_VAR(wid_err_lower);
934             XEM_ADD_VAR(wid_err_addr);
935 #if !DEBUG
936         }
937 #endif
938
939         /* caller will dump contents of ioerror
940          * in DEBUG and kdebug kernels.
941          */
942
943         return retval;
944     }
945     /* access to valid port:
946      * ok to check port status.
947      */
948
949     link = &(xbow->xb_link(port));
950     link_control = link->link_control;
951     link_status = link->link_status;
952     link_aux_status = link->link_aux_status;
953
954     /* Check that there is something present
955      * in that XIO port.
956      */
957     /* WAR: PIC widget 0xf is missing prescense bit */
958     if (XBOW_WAR_ENABLED(PV854827, xbow->xb_wid_id) &&
959                 IS_PIC_XBOW(xbow->xb_wid_id) && (port==0xf))
960                 ;
961     else
962     if (!(link_aux_status & XB_AUX_STAT_PRESENT)) {
963         /* nobody connected. */
964         if (mode == MODE_DEVPROBE)
965             return IOERROR_HANDLED;
966
967         if (error_code & IOECODE_DMA) {
968             printk(KERN_ALERT
969                     "DMA error blamed on XIO port at %s/%d\n"
970                     "\tbut there is no device connected there.",
971                     soft->name, port);
972         }
973         if (error_code & IOECODE_PIO) {
974             iopaddr_t tmp;
975             IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
976             printk(KERN_ALERT
977                     "PIO Error on XIO Bus %s\n"
978                     "\tattempting to access XIO port %d\n"
979                     "\t(which has no device connected)"
980                     "\twith offset 0x%lx",
981                     soft->name, port, tmp);
982         }
983 #if !DEBUG
984         if (kdebug) {
985 #endif
986             XEM_ADD_STR("Raw status values for Crossbow:\n");
987             XEM_ADD_VAR(wid_stat);
988             XEM_ADD_VAR(wid_err_cmdword);
989             XEM_ADD_VAR(wid_err_upper);
990             XEM_ADD_VAR(wid_err_lower);
991             XEM_ADD_VAR(wid_err_addr);
992             XEM_ADD_VAR(port);
993             XEM_ADD_VAR(link_control);
994             XEM_ADD_VAR(link_status);
995             XEM_ADD_VAR(link_aux_status);
996 #if !DEBUG
997         }
998 #endif
999         return retval;
1000
1001     }
1002     /* Check that the link is alive.
1003      */
1004     if (!(link_status & XB_STAT_LINKALIVE)) {
1005         iopaddr_t tmp;
1006         /* nobody connected. */
1007         if (mode == MODE_DEVPROBE)
1008             return IOERROR_HANDLED;
1009
1010         printk(KERN_ALERT
1011                 "%s%sError on XIO Bus %s port %d",
1012                 (error_code & IOECODE_DMA) ? "DMA " : "",
1013                 (error_code & IOECODE_PIO) ? "PIO " : "",
1014                 soft->name, port);
1015
1016         IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
1017         if ((error_code & IOECODE_PIO) &&
1018             (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
1019                 printk("\tAccess attempted to offset 0x%lx\n", tmp);
1020         }
1021         if (link_aux_status & XB_AUX_LINKFAIL_RST_BAD)
1022             XEM_ADD_STR("\tLink never came out of reset\n");
1023         else
1024             XEM_ADD_STR("\tLink failed while transferring data\n");
1025
1026     }
1027     /* get the connection point for the widget
1028      * involved in this error; if it exists and
1029      * is not our connectpoint, cycle back through
1030      * xtalk_error_handler to deliver control to
1031      * the proper handler (or to report a generic
1032      * crosstalk error).
1033      *
1034      * If the downstream handler won't handle
1035      * the problem, we let our upstream caller
1036      * deal with it, after (in DEBUG and kdebug
1037      * kernels) dumping the xbow state for this
1038      * port.
1039      */
1040     conn = xbow_widget_lookup(busv, port);
1041     if ((conn != GRAPH_VERTEX_NONE) &&
1042         (conn != soft->conn)) {
1043         retval = xtalk_error_handler(conn, error_code, mode, ioerror);
1044         if (retval == IOERROR_HANDLED)
1045             return IOERROR_HANDLED;
1046     }
1047     if (mode == MODE_DEVPROBE)
1048         return IOERROR_HANDLED;
1049
1050     if (retval == IOERROR_UNHANDLED) {
1051         iopaddr_t tmp;
1052         retval = IOERROR_PANIC;
1053
1054         printk(KERN_ALERT
1055                 "%s%sError on XIO Bus %s port %d",
1056                 (error_code & IOECODE_DMA) ? "DMA " : "",
1057                 (error_code & IOECODE_PIO) ? "PIO " : "",
1058                 soft->name, port);
1059
1060         IOERROR_GETVALUE(tmp, ioerror, xtalkaddr);
1061         if ((error_code & IOECODE_PIO) &&
1062             (IOERROR_FIELDVALID(ioerror, xtalkaddr))) {
1063             printk("\tAccess attempted to offset 0x%lx\n", tmp);
1064         }
1065     }
1066
1067 #if !DEBUG
1068     if (kdebug) {
1069 #endif
1070         XEM_ADD_STR("Raw status values for Crossbow:\n");
1071         XEM_ADD_VAR(wid_stat);
1072         XEM_ADD_VAR(wid_err_cmdword);
1073         XEM_ADD_VAR(wid_err_upper);
1074         XEM_ADD_VAR(wid_err_lower);
1075         XEM_ADD_VAR(wid_err_addr);
1076         XEM_ADD_VAR(port);
1077         XEM_ADD_VAR(link_control);
1078         XEM_ADD_VAR(link_status);
1079         XEM_ADD_VAR(link_aux_status);
1080 #if !DEBUG
1081     }
1082 #endif
1083     /* caller will dump raw ioerror data
1084      * in DEBUG and kdebug kernels.
1085      */
1086
1087     return retval;
1088 }
1089
1090 void
1091 xbow_update_perf_counters(vertex_hdl_t vhdl)
1092 {
1093     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1094     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
1095     xbow_perf_link_t       *xbow_plink = xbow_soft->xbow_perflink;
1096     xbow_perfcount_t        perf_reg;
1097     unsigned long           s;
1098     int                     link, i;
1099
1100     for (i = 0; i < XBOW_PERF_COUNTERS; i++, xbow_perf++) {
1101         if (xbow_perf->xp_mode == XBOW_MONITOR_NONE)
1102             continue;
1103
1104         s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
1105
1106         perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
1107
1108         link = perf_reg.xb_perf.link_select;
1109
1110         (xbow_plink + link)->xlp_cumulative[xbow_perf->xp_curmode] +=
1111             ((perf_reg.xb_perf.count - xbow_perf->xp_current) & XBOW_COUNTER_MASK);
1112         xbow_perf->xp_current = perf_reg.xb_perf.count;
1113
1114         mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
1115     }
1116 }
1117
1118 xbow_perf_link_t       *
1119 xbow_get_perf_counters(vertex_hdl_t vhdl)
1120 {
1121     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1122     xbow_perf_link_t       *xbow_perf_link = xbow_soft->xbow_perflink;
1123
1124     return xbow_perf_link;
1125 }
1126
1127 int
1128 xbow_enable_perf_counter(vertex_hdl_t vhdl, int link, int mode, int counter)
1129 {
1130     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1131     xbow_perf_t            *xbow_perf = xbow_soft->xbow_perfcnt;
1132     xbow_linkctrl_t         xbow_link_ctrl;
1133     xbow_t                 *xbow = xbow_soft->base;
1134     xbow_perfcount_t        perf_reg;
1135     unsigned long           s;
1136     int                     i;
1137
1138     link -= BASE_XBOW_PORT;
1139     if ((link < 0) || (link >= MAX_XBOW_PORTS))
1140         return -1;
1141
1142     if ((mode < XBOW_MONITOR_NONE) || (mode > XBOW_MONITOR_DEST_LINK))
1143         return -1;
1144
1145     if ((counter < 0) || (counter >= XBOW_PERF_COUNTERS))
1146         return -1;
1147
1148     s = mutex_spinlock(&xbow_soft->xbow_perf_lock);
1149
1150     if ((xbow_perf + counter)->xp_mode && mode) {
1151         mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
1152         return -1;
1153     }
1154     for (i = 0; i < XBOW_PERF_COUNTERS; i++) {
1155         if (i == counter)
1156             continue;
1157         if (((xbow_perf + i)->xp_link == link) &&
1158             ((xbow_perf + i)->xp_mode)) {
1159             mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
1160             return -1;
1161         }
1162     }
1163     xbow_perf += counter;
1164
1165     xbow_perf->xp_curlink = xbow_perf->xp_link = link;
1166     xbow_perf->xp_curmode = xbow_perf->xp_mode = mode;
1167
1168     xbow_link_ctrl.xbl_ctrlword = xbow->xb_link_raw[link].link_control;
1169     xbow_link_ctrl.xb_linkcontrol.perf_mode = mode;
1170     xbow->xb_link_raw[link].link_control = xbow_link_ctrl.xbl_ctrlword;
1171
1172     perf_reg.xb_counter_val = *(xbowreg_t *) xbow_perf->xp_perf_reg;
1173     perf_reg.xb_perf.link_select = link;
1174     *(xbowreg_t *) xbow_perf->xp_perf_reg = perf_reg.xb_counter_val;
1175     xbow_perf->xp_current = perf_reg.xb_perf.count;
1176
1177     mutex_spinunlock(&xbow_soft->xbow_perf_lock, s);
1178     return 0;
1179 }
1180
1181 xbow_link_status_t     *
1182 xbow_get_llp_status(vertex_hdl_t vhdl)
1183 {
1184     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1185     xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
1186
1187     return xbow_llp_status;
1188 }
1189
1190 void
1191 xbow_update_llp_status(vertex_hdl_t vhdl)
1192 {
1193     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1194     xbow_link_status_t     *xbow_llp_status = xbow_soft->xbow_link_status;
1195     xbow_t                 *xbow;
1196     xbwX_stat_t             lnk_sts;
1197     xbow_aux_link_status_t  aux_sts;
1198     int                     link;
1199     vertex_hdl_t            xwidget_vhdl;
1200     char                   *xwidget_name;       
1201
1202     xbow = (xbow_t *) xbow_soft->base;
1203     for (link = 0; link < MAX_XBOW_PORTS; link++, xbow_llp_status++) {
1204         /* Get the widget name corresponding the current link.
1205          * Note : 0 <= link < MAX_XBOW_PORTS(8).
1206          *        BASE_XBOW_PORT(0x8) <= xwidget number < MAX_PORT_NUM (0x10)
1207          */
1208         xwidget_vhdl = xbow_widget_lookup(xbow_soft->busv,link+BASE_XBOW_PORT);
1209         xwidget_name = xwidget_name_get(xwidget_vhdl);
1210         aux_sts.aux_linkstatus
1211             = xbow->xb_link_raw[link].link_aux_status;
1212         lnk_sts.linkstatus = xbow->xb_link_raw[link].link_status_clr;
1213
1214         if (lnk_sts.link_alive == 0)
1215             continue;
1216
1217         xbow_llp_status->rx_err_count +=
1218             aux_sts.xb_aux_linkstatus.rx_err_cnt;
1219
1220         xbow_llp_status->tx_retry_count +=
1221             aux_sts.xb_aux_linkstatus.tx_retry_cnt;
1222
1223         if (lnk_sts.linkstatus & ~(XB_STAT_RCV_ERR | XB_STAT_XMT_RTRY_ERR | XB_STAT_LINKALIVE)) {
1224 #ifdef  LATER
1225             printk(KERN_WARNING  "link %d[%s]: bad status 0x%x\n",
1226                     link, xwidget_name, lnk_sts.linkstatus);
1227 #endif
1228         }
1229     }
1230 }
1231
1232 int
1233 xbow_disable_llp_monitor(vertex_hdl_t vhdl)
1234 {
1235     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1236     int                     port;
1237
1238     for (port = 0; port < MAX_XBOW_PORTS; port++) {
1239         xbow_soft->xbow_link_status[port].rx_err_count = 0;
1240         xbow_soft->xbow_link_status[port].tx_retry_count = 0;
1241     }
1242
1243     xbow_soft->link_monitor = 0;
1244     return 0;
1245 }
1246
1247 int
1248 xbow_enable_llp_monitor(vertex_hdl_t vhdl)
1249 {
1250     xbow_soft_t             xbow_soft = xbow_soft_get(vhdl);
1251
1252     xbow_soft->link_monitor = 1;
1253     return 0;
1254 }
1255
1256
1257 int
1258 xbow_reset_link(vertex_hdl_t xconn_vhdl)
1259 {
1260     xwidget_info_t          widget_info;
1261     xwidgetnum_t            port;
1262     xbow_t                 *xbow;
1263     xbowreg_t               ctrl;
1264     xbwX_stat_t             stat;
1265     unsigned                itick;
1266     unsigned                dtick;
1267     static int              ticks_per_ms = 0;
1268
1269     if (!ticks_per_ms) {
1270         itick = get_timestamp();
1271         us_delay(1000);
1272         ticks_per_ms = get_timestamp() - itick;
1273     }
1274     widget_info = xwidget_info_get(xconn_vhdl);
1275     port = xwidget_info_id_get(widget_info);
1276
1277 #ifdef XBOW_K1PTR                       /* defined if we only have one xbow ... */
1278     xbow = XBOW_K1PTR;
1279 #else
1280     {
1281         vertex_hdl_t            xbow_vhdl;
1282         xbow_soft_t             xbow_soft;
1283
1284         hwgraph_traverse(xconn_vhdl, ".master/xtalk/0/xbow", &xbow_vhdl);
1285         xbow_soft = xbow_soft_get(xbow_vhdl);
1286         xbow = xbow_soft->base;
1287     }
1288 #endif
1289
1290     /*
1291      * This requires three PIOs (reset the link, check for the
1292      * reset, restore the control register for the link) plus
1293      * 10us to wait for the reset. We allow up to 1ms for the
1294      * widget to come out of reset before giving up and
1295      * returning a failure.
1296      */
1297     ctrl = xbow->xb_link(port).link_control;
1298     xbow->xb_link(port).link_reset = 0;
1299     itick = get_timestamp();
1300     while (1) {
1301         stat.linkstatus = xbow->xb_link(port).link_status;
1302         if (stat.link_alive)
1303             break;
1304         dtick = get_timestamp() - itick;
1305         if (dtick > ticks_per_ms) {
1306             return -1;                  /* never came out of reset */
1307         }
1308         DELAY(2);                       /* don't beat on link_status */
1309     }
1310     xbow->xb_link(port).link_control = ctrl;
1311     return 0;
1312 }
1313
1314 #define XBOW_ARB_RELOAD_TICKS           25
1315                                         /* granularity: 4 MB/s, max: 124 MB/s */
1316 #define GRANULARITY                     ((100 * 1000000) / XBOW_ARB_RELOAD_TICKS)
1317
1318 #define XBOW_BYTES_TO_GBR(BYTES_per_s)  (int) (BYTES_per_s / GRANULARITY)
1319
1320 #define XBOW_GBR_TO_BYTES(cnt)          (bandwidth_t) ((cnt) * GRANULARITY)
1321
1322 #define CEILING_BYTES_TO_GBR(gbr, bytes_per_sec)        \
1323                         ((XBOW_GBR_TO_BYTES(gbr) < bytes_per_sec) ? gbr+1 : gbr)
1324
1325 #define XBOW_ARB_GBR_MAX                31
1326
1327 #define ABS(x)                          ((x > 0) ? (x) : (-1 * x))
1328                                         /* absolute value */
1329
1330 int
1331 xbow_bytes_to_gbr(bandwidth_t old_bytes_per_sec, bandwidth_t bytes_per_sec)
1332 {
1333     int                     gbr_granted;
1334     int                     new_total_gbr;
1335     int                     change_gbr;
1336     bandwidth_t             new_total_bw;
1337
1338 #ifdef GRIO_DEBUG
1339     printk("xbow_bytes_to_gbr: old_bytes_per_sec %lld bytes_per_sec %lld\n",
1340                 old_bytes_per_sec, bytes_per_sec);
1341 #endif  /* GRIO_DEBUG */
1342
1343     gbr_granted = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(old_bytes_per_sec)),
1344                         old_bytes_per_sec);
1345     new_total_bw = old_bytes_per_sec + bytes_per_sec;
1346     new_total_gbr = CEILING_BYTES_TO_GBR((XBOW_BYTES_TO_GBR(new_total_bw)),
1347                         new_total_bw);
1348
1349     change_gbr = new_total_gbr - gbr_granted;
1350
1351 #ifdef GRIO_DEBUG
1352     printk("xbow_bytes_to_gbr: gbr_granted %d new_total_gbr %d change_gbr %d\n",
1353                 gbr_granted, new_total_gbr, change_gbr);
1354 #endif  /* GRIO_DEBUG */
1355
1356     return (change_gbr);
1357 }
1358
1359 /* Conversion from GBR to bytes */
1360 bandwidth_t
1361 xbow_gbr_to_bytes(int gbr)
1362 {
1363     return (XBOW_GBR_TO_BYTES(gbr));
1364 }
1365
1366 /* Given the vhdl for the desired xbow, the src and dest. widget ids
1367  * and the req_bw value, this xbow driver entry point accesses the
1368  * xbow registers and allocates the desired bandwidth if available.
1369  *
1370  * If bandwidth allocation is successful, return success else return failure.
1371  */
1372 int
1373 xbow_prio_bw_alloc(vertex_hdl_t vhdl,
1374                 xwidgetnum_t src_wid,
1375                 xwidgetnum_t dest_wid,
1376                 unsigned long long old_alloc_bw,
1377                 unsigned long long req_bw)
1378 {
1379     xbow_soft_t             soft = xbow_soft_get(vhdl);
1380     volatile xbowreg_t     *xreg;
1381     xbowreg_t               mask;
1382     unsigned long           s;
1383     int                     error = 0;
1384     bandwidth_t             old_bw_BYTES, req_bw_BYTES;
1385     xbowreg_t               old_xreg;
1386     int                     old_bw_GBR, req_bw_GBR, new_bw_GBR;
1387
1388 #ifdef GRIO_DEBUG
1389     printk("xbow_prio_bw_alloc: vhdl %d src_wid %d dest_wid %d req_bw %lld\n",
1390                 (int) vhdl, (int) src_wid, (int) dest_wid, req_bw);
1391 #endif
1392
1393     ASSERT(XBOW_WIDGET_IS_VALID(src_wid));
1394     ASSERT(XBOW_WIDGET_IS_VALID(dest_wid));
1395
1396     s = mutex_spinlock(&soft->xbow_bw_alloc_lock);
1397
1398     /* Get pointer to the correct register */
1399     xreg = XBOW_PRIO_ARBREG_PTR(soft->base, dest_wid, src_wid);
1400
1401     /* Get mask for GBR count value */
1402     mask = XB_ARB_GBR_MSK << XB_ARB_GBR_SHFT(src_wid);
1403
1404     req_bw_GBR = xbow_bytes_to_gbr(old_alloc_bw, req_bw);
1405     req_bw_BYTES = (req_bw_GBR < 0) ? (-1 * xbow_gbr_to_bytes(ABS(req_bw_GBR)))
1406                 : xbow_gbr_to_bytes(req_bw_GBR);
1407
1408 #ifdef GRIO_DEBUG
1409     printk("req_bw %lld req_bw_BYTES %lld req_bw_GBR %d\n",
1410                 req_bw, req_bw_BYTES, req_bw_GBR);
1411 #endif  /* GRIO_DEBUG */
1412
1413     old_bw_BYTES = soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS];
1414     old_xreg = *xreg;
1415     old_bw_GBR = (((*xreg) & mask) >> XB_ARB_GBR_SHFT(src_wid));
1416
1417 #ifdef GRIO_DEBUG
1418     ASSERT(XBOW_BYTES_TO_GBR(old_bw_BYTES) == old_bw_GBR);
1419
1420     printk("old_bw_BYTES %lld old_bw_GBR %d\n", old_bw_BYTES, old_bw_GBR);
1421
1422     printk("req_bw_BYTES %lld old_bw_BYTES %lld soft->bw_hiwm %lld\n",
1423                 req_bw_BYTES, old_bw_BYTES,
1424                 soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]);
1425            
1426 #endif                          /* GRIO_DEBUG */
1427
1428     /* Accept the request only if we don't exceed the destination
1429      * port HIWATER_MARK *AND* the max. link GBR arbitration count
1430      */
1431     if (((old_bw_BYTES + req_bw_BYTES) <=
1432                 soft->bw_hiwm[(int) dest_wid - MAX_XBOW_PORTS]) &&
1433                 (req_bw_GBR + old_bw_GBR <= XBOW_ARB_GBR_MAX)) {
1434
1435         new_bw_GBR = (old_bw_GBR + req_bw_GBR);
1436
1437         /* Set this in the xbow link register */
1438         *xreg = (old_xreg & ~mask) | \
1439             (new_bw_GBR << XB_ARB_GBR_SHFT(src_wid) & mask);
1440
1441         soft->bw_cur_used[(int) dest_wid - MAX_XBOW_PORTS] =
1442                         xbow_gbr_to_bytes(new_bw_GBR);
1443     } else {
1444         error = 1;
1445     }
1446
1447     mutex_spinunlock(&soft->xbow_bw_alloc_lock, s);
1448
1449     return (error);
1450 }