huberror.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: huberror.c,v 1.1 2002/02/28 17:31:25 marcelo Exp $
  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-2002 Silicon Graphics, Inc. All rights reserved.
  8.  */
  9. #include <linux/types.h>
  10. #include <linux/slab.h>
  11. #include <asm/smp.h>
  12. #include <asm/sn/sgi.h>
  13. #include <asm/sn/io.h>
  14. #include <asm/sn/iograph.h>
  15. #include <asm/sn/invent.h>
  16. #include <asm/sn/hcl.h>
  17. #include <asm/sn/labelcl.h>
  18. #include <asm/sn/sn_private.h>
  19. #include <asm/sn/klconfig.h>
  20. #include <asm/sn/sn_cpuid.h>
  21. #include <asm/sn/pci/pciio.h>
  22. #include <asm/sn/pci/pcibr.h>
  23. #include <asm/sn/xtalk/xtalk.h>
  24. #include <asm/sn/pci/pcibr_private.h>
  25. #include <asm/sn/intr.h>
  26. extern void hubni_eint_init(cnodeid_t cnode);
  27. extern void hubii_eint_init(cnodeid_t cnode);
  28. extern void hubii_eint_handler (int irq, void *arg, struct pt_regs *ep);
  29. extern void snia_error_intr_handler(int irq, void *devid, struct pt_regs *pt_regs);
  30. extern int maxcpus;
  31. #define HUB_ERROR_PERIOD        (120 * HZ)      /* 2 minutes */
  32. void
  33. hub_error_clear(nasid_t nasid)
  34. {
  35. int i;
  36. hubreg_t idsr;
  37. int sn;
  38. for(sn=0; sn<NUM_SUBNODES; sn++) {
  39. REMOTE_HUB_PI_S(nasid, sn, PI_ERR_INT_PEND, -1);
  40. REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS0_A_CLR, -1);
  41. REMOTE_HUB_PI_S(nasid, sn, PI_ERR_STATUS0_B_CLR, -1);
  42. REMOTE_HUB_PI_S(nasid, sn, PI_SPURIOUS_HDR_0, 0);
  43. REMOTE_HUB_PI_S(nasid, sn, PI_SPURIOUS_HDR_1, 0);
  44. }
  45. REMOTE_HUB_L(nasid, MD_DIR_ERROR_CLR);
  46. REMOTE_HUB_L(nasid, MD_MEM_ERROR_CLR);
  47. REMOTE_HUB_L(nasid, MD_MISC1_ERROR_CLR);
  48. REMOTE_HUB_L(nasid, MD_PROTOCOL_ERR_CLR);
  49.     /*
  50.      * Make sure spurious write response errors are cleared
  51.      * (values are from hub_set_prb())
  52.      */
  53.     for (i = 0; i <= HUB_WIDGET_ID_MAX - HUB_WIDGET_ID_MIN + 1; i++) {
  54.         iprb_t prb;
  55. prb.iprb_regval = REMOTE_HUB_L(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)));
  56.         /* Clear out some fields */
  57.         prb.iprb_ovflow = 1;
  58.         prb.iprb_bnakctr = 0;
  59.         prb.iprb_anakctr = 0;
  60. /*
  61.  * PIO reads in fire-and-forget mode on bedrock 1.0 don't
  62.  * frob the credit count properly, making the responses appear
  63.  * spurious.  So don't use fire-and-forget mode.  Bug 761802.
  64.  */
  65.         prb.iprb_ff = 0;        /* disable fire-and-forget mode by default */
  66.         prb.iprb_xtalkctr = 3;  /* approx. PIO credits for the widget */
  67.         REMOTE_HUB_S(nasid, IIO_IOPRB_0 + (i * sizeof(hubreg_t)), prb.iprb_regval);
  68.     }
  69.     REMOTE_HUB_S(nasid, IIO_IO_ERR_CLR, -1);
  70.     idsr = REMOTE_HUB_L(nasid, IIO_IIDSR);
  71.     REMOTE_HUB_S(nasid, IIO_IIDSR, (idsr & ~(IIO_IIDSR_SENT_MASK)));
  72.     REMOTE_HUB_L(nasid, NI_PORT_ERROR_CLEAR);
  73.     /* No need to clear NI_PORT_HEADER regs; they are continually overwritten*/
  74.     REMOTE_HUB_S(nasid, LB_ERROR_MASK_CLR, -1);
  75.     REMOTE_HUB_S(nasid, LB_ERROR_HDR1, 0);
  76.     /* Clear XB error regs, in order */
  77.     for (i = 0;
  78.          i <= XB_FIRST_ERROR_CLEAR - XB_POQ0_ERROR_CLEAR;
  79.          i += sizeof(hubreg_t)) {
  80.         REMOTE_HUB_S(nasid, XB_POQ0_ERROR_CLEAR + i, 0);
  81.     }
  82. }
  83. /*
  84.  * Function : hub_error_init
  85.  * Purpose : initialize the error handling requirements for a given hub.
  86.  * Parameters : cnode, the compact nodeid.
  87.  * Assumptions : Called only once per hub, either by a local cpu. Or by a 
  88.  * remote cpu, when this hub is headless.(cpuless)
  89.  * Returns : None
  90.  */
  91. void
  92. hub_error_init(cnodeid_t cnode)
  93. {
  94. nasid_t nasid;
  95.     nasid = cnodeid_to_nasid(cnode);
  96.     hub_error_clear(nasid);
  97.     /*
  98.      * Now setup the hub ii and ni error interrupt handler.
  99.      */
  100.     hubii_eint_init(cnode);
  101.     hubni_eint_init(cnode);
  102.     return;
  103. }
  104. /*
  105.  * Function : hubii_eint_init
  106.  * Parameters : cnode
  107.  * Purpose : to initialize the hub iio error interrupt.
  108.  * Assumptions : Called once per hub, by the cpu which will ultimately
  109.  * handle this interrupt.
  110.  * Returns : None.
  111.  */
  112. void
  113. hubii_eint_init(cnodeid_t cnode)
  114. {
  115.     int bit, rv;
  116.     ii_iidsr_u_t     hubio_eint;
  117.     hubinfo_t hinfo; 
  118.     cpuid_t intr_cpu;
  119.     devfs_handle_t  hub_v;
  120.     ii_ilcsr_u_t ilcsr;
  121.     int bit_pos_to_irq(int bit);
  122.     int synergy_intr_connect(int bit, int cpuid);
  123.     hub_v = (devfs_handle_t)cnodeid_to_vertex(cnode);
  124.     ASSERT_ALWAYS(hub_v);
  125.     hubinfo_get(hub_v, &hinfo);
  126.     ASSERT(hinfo);
  127.     ASSERT(hinfo->h_cnodeid == cnode);
  128.     ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(hinfo->h_nasid, IIO_ILCSR);
  129.     if ((ilcsr.ii_ilcsr_fld_s.i_llp_stat & 0x2) == 0) {
  130. /* 
  131.  * HUB II link is not up. 
  132.  * Just disable LLP, and don't connect any interrupts.
  133.  */
  134. ilcsr.ii_ilcsr_fld_s.i_llp_en = 0;
  135. REMOTE_HUB_S(hinfo->h_nasid, IIO_ILCSR, ilcsr.ii_ilcsr_regval);
  136. return;
  137.     }
  138.     /* Select a possible interrupt target where there is a free interrupt
  139.      * bit and also reserve the interrupt bit for this IO error interrupt
  140.      */
  141.     intr_cpu = intr_heuristic(hub_v,0,INTRCONNECT_ANYBIT,II_ERRORINT,hub_v,
  142.       "HUB IO error interrupt",&bit);
  143.     if (intr_cpu == CPU_NONE) {
  144. printk("hubii_eint_init: intr_reserve_level failed, cnode %d", cnode);
  145. return;
  146.     }
  147.     rv = intr_connect_level(intr_cpu, bit, 0, NULL);
  148.     synergy_intr_connect(bit, intr_cpu);
  149.     request_irq(bit_pos_to_irq(bit) + (intr_cpu << 8), hubii_eint_handler, 0, "SN hub error", (void *)hub_v);
  150.     ASSERT_ALWAYS(rv >= 0);
  151.     hubio_eint.ii_iidsr_regval = 0;
  152.     hubio_eint.ii_iidsr_fld_s.i_enable = 1;
  153.     hubio_eint.ii_iidsr_fld_s.i_level = bit;/* Take the least significant bits*/
  154.     hubio_eint.ii_iidsr_fld_s.i_node = COMPACT_TO_NASID_NODEID(cnode);
  155.     hubio_eint.ii_iidsr_fld_s.i_pi_id = cpuid_to_subnode(intr_cpu);
  156.     REMOTE_HUB_S(hinfo->h_nasid, IIO_IIDSR, hubio_eint.ii_iidsr_regval);
  157. }
  158. void
  159. hubni_eint_init(cnodeid_t cnode)
  160. {
  161.     int intr_bit;
  162.     cpuid_t targ;
  163.     if ((targ = cnodeid_to_cpuid(cnode)) == CPU_NONE)
  164. return;
  165. /* The prom chooses which cpu gets these interrupts, but we
  166. *  don't know which one it chose.  We will register all of the 
  167. *  cpus to be sure.  This only costs us an irqaction per cpu.
  168. */
  169.     for (; targ < CPUS_PER_NODE; targ++) {
  170. if (!cpu_enabled(targ) ) continue;
  171. /* connect the INTEND1 bits. */
  172. for (intr_bit = XB_ERROR; intr_bit <= MSC_PANIC_INTR; intr_bit++) {
  173. intr_connect_level(targ, intr_bit, II_ERRORINT, NULL);
  174. }
  175. request_irq(SGI_HUB_ERROR_IRQ + (targ << 8), snia_error_intr_handler, 0, "SN hub error", NULL);
  176. /* synergy masks are initialized in the prom to enable all interrupts. */
  177. /* We'll just leave them that way, here, for these interrupts. */
  178.     }
  179. }
  180. /*ARGSUSED*/
  181. void
  182. hubii_eint_handler (int irq, void *arg, struct pt_regs *ep)
  183. {
  184. panic("Hubii interruptn");
  185. }