huberror.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  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. *
  6. * Copyright (C) 1992 - 1997, 2000,2002-2007 Silicon Graphics, Inc. All rights reserved.
  7. */
  8. #include <linux/types.h>
  9. #include <linux/interrupt.h>
  10. #include <linux/pci.h>
  11. #include <asm/delay.h>
  12. #include <asm/sn/sn_sal.h>
  13. #include "ioerror.h"
  14. #include <asm/sn/addrs.h>
  15. #include <asm/sn/shubio.h>
  16. #include <asm/sn/geo.h>
  17. #include "xtalk/xwidgetdev.h"
  18. #include "xtalk/hubdev.h"
  19. #include <asm/sn/bte.h>
  20. void hubiio_crb_error_handler(struct hubdev_info *hubdev_info);
  21. extern void bte_crb_error_handler(cnodeid_t, int, int, ioerror_t *,
  22. int);
  23. static irqreturn_t hub_eint_handler(int irq, void *arg)
  24. {
  25. struct hubdev_info *hubdev_info;
  26. struct ia64_sal_retval ret_stuff;
  27. nasid_t nasid;
  28. ret_stuff.status = 0;
  29. ret_stuff.v0 = 0;
  30. hubdev_info = (struct hubdev_info *)arg;
  31. nasid = hubdev_info->hdi_nasid;
  32. if (is_shub1()) {
  33. SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
  34. (u64) nasid, 0, 0, 0, 0, 0, 0);
  35. if ((int)ret_stuff.v0)
  36. panic("%s: Fatal %s Error", __FUNCTION__,
  37. ((nasid & 1) ? "TIO" : "HUBII"));
  38. if (!(nasid & 1)) /* Not a TIO, handle CRB errors */
  39. (void)hubiio_crb_error_handler(hubdev_info);
  40. } else
  41. if (nasid & 1) { /* TIO errors */
  42. SAL_CALL_NOLOCK(ret_stuff, SN_SAL_HUB_ERROR_INTERRUPT,
  43. (u64) nasid, 0, 0, 0, 0, 0, 0);
  44. if ((int)ret_stuff.v0)
  45. panic("%s: Fatal TIO Error", __FUNCTION__);
  46. } else
  47. bte_error_handler((unsigned long)NODEPDA(nasid_to_cnodeid(nasid)));
  48. return IRQ_HANDLED;
  49. }
  50. /*
  51. * Free the hub CRB "crbnum" which encountered an error.
  52. * Assumption is, error handling was successfully done,
  53. * and we now want to return the CRB back to Hub for normal usage.
  54. *
  55. * In order to free the CRB, all that's needed is to de-allocate it
  56. *
  57. * Assumption:
  58. * No other processor is mucking around with the hub control register.
  59. * So, upper layer has to single thread this.
  60. */
  61. void hubiio_crb_free(struct hubdev_info *hubdev_info, int crbnum)
  62. {
  63. ii_icrb0_b_u_t icrbb;
  64. /*
  65. * The hardware does NOT clear the mark bit, so it must get cleared
  66. * here to be sure the error is not processed twice.
  67. */
  68. icrbb.ii_icrb0_b_regval = REMOTE_HUB_L(hubdev_info->hdi_nasid,
  69. IIO_ICRB_B(crbnum));
  70. icrbb.b_mark = 0;
  71. REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICRB_B(crbnum),
  72. icrbb.ii_icrb0_b_regval);
  73. /*
  74. * Deallocate the register wait till hub indicates it's done.
  75. */
  76. REMOTE_HUB_S(hubdev_info->hdi_nasid, IIO_ICDR, (IIO_ICDR_PND | crbnum));
  77. while (REMOTE_HUB_L(hubdev_info->hdi_nasid, IIO_ICDR) & IIO_ICDR_PND)
  78. cpu_relax();
  79. }
  80. /*
  81. * hubiio_crb_error_handler
  82. *
  83. * This routine gets invoked when a hub gets an error
  84. * interrupt. So, the routine is running in interrupt context
  85. * at error interrupt level.
  86. * Action:
  87. * It's responsible for identifying ALL the CRBs that are marked
  88. * with error, and process them.
  89. *
  90. * If you find the CRB that's marked with error, map this to the
  91. * reason it caused error, and invoke appropriate error handler.
  92. *
  93. * XXX Be aware of the information in the context register.
  94. *
  95. * NOTE:
  96. * Use REMOTE_HUB_* macro instead of LOCAL_HUB_* so that the interrupt
  97. * handler can be run on any node. (not necessarily the node
  98. * corresponding to the hub that encountered error).
  99. */
  100. void hubiio_crb_error_handler(struct hubdev_info *hubdev_info)
  101. {
  102. nasid_t nasid;
  103. ii_icrb0_a_u_t icrba; /* II CRB Register A */
  104. ii_icrb0_b_u_t icrbb; /* II CRB Register B */
  105. ii_icrb0_c_u_t icrbc; /* II CRB Register C */
  106. ii_icrb0_d_u_t icrbd; /* II CRB Register D */
  107. ii_icrb0_e_u_t icrbe; /* II CRB Register D */
  108. int i;
  109. int num_errors = 0; /* Num of errors handled */
  110. ioerror_t ioerror;
  111. nasid = hubdev_info->hdi_nasid;
  112. /*
  113. * XXX - Add locking for any recovery actions
  114. */
  115. /*
  116. * Scan through all CRBs in the Hub, and handle the errors
  117. * in any of the CRBs marked.
  118. */
  119. for (i = 0; i < IIO_NUM_CRBS; i++) {
  120. /* Check this crb entry to see if it is in error. */
  121. icrbb.ii_icrb0_b_regval = REMOTE_HUB_L(nasid, IIO_ICRB_B(i));
  122. if (icrbb.b_mark == 0) {
  123. continue;
  124. }
  125. icrba.ii_icrb0_a_regval = REMOTE_HUB_L(nasid, IIO_ICRB_A(i));
  126. IOERROR_INIT(&ioerror);
  127. /* read other CRB error registers. */
  128. icrbc.ii_icrb0_c_regval = REMOTE_HUB_L(nasid, IIO_ICRB_C(i));
  129. icrbd.ii_icrb0_d_regval = REMOTE_HUB_L(nasid, IIO_ICRB_D(i));
  130. icrbe.ii_icrb0_e_regval = REMOTE_HUB_L(nasid, IIO_ICRB_E(i));
  131. IOERROR_SETVALUE(&ioerror, errortype, icrbb.b_ecode);
  132. /* Check if this error is due to BTE operation,
  133. * and handle it separately.
  134. */
  135. if (icrbd.d_bteop ||
  136. ((icrbb.b_initiator == IIO_ICRB_INIT_BTE0 ||
  137. icrbb.b_initiator == IIO_ICRB_INIT_BTE1) &&
  138. (icrbb.b_imsgtype == IIO_ICRB_IMSGT_BTE ||
  139. icrbb.b_imsgtype == IIO_ICRB_IMSGT_SN1NET))) {
  140. int bte_num;
  141. if (icrbd.d_bteop)
  142. bte_num = icrbc.c_btenum;
  143. else /* b_initiator bit 2 gives BTE number */
  144. bte_num = (icrbb.b_initiator & 0x4) >> 2;
  145. hubiio_crb_free(hubdev_info, i);
  146. bte_crb_error_handler(nasid_to_cnodeid(nasid), bte_num,
  147. i, &ioerror, icrbd.d_bteop);
  148. num_errors++;
  149. continue;
  150. }
  151. }
  152. }
  153. /*
  154. * Function : hub_error_init
  155. * Purpose : initialize the error handling requirements for a given hub.
  156. * Parameters : cnode, the compact nodeid.
  157. * Assumptions : Called only once per hub, either by a local cpu. Or by a
  158. * remote cpu, when this hub is headless.(cpuless)
  159. * Returns : None
  160. */
  161. void hub_error_init(struct hubdev_info *hubdev_info)
  162. {
  163. if (request_irq(SGI_II_ERROR, hub_eint_handler, IRQF_SHARED,
  164. "SN_hub_error", (void *)hubdev_info))
  165. printk("hub_error_init: Failed to request_irq for 0x%p\n",
  166. hubdev_info);
  167. return;
  168. }
  169. /*
  170. * Function : ice_error_init
  171. * Purpose : initialize the error handling requirements for a given tio.
  172. * Parameters : cnode, the compact nodeid.
  173. * Assumptions : Called only once per tio.
  174. * Returns : None
  175. */
  176. void ice_error_init(struct hubdev_info *hubdev_info)
  177. {
  178. if (request_irq
  179. (SGI_TIO_ERROR, (void *)hub_eint_handler, IRQF_SHARED, "SN_TIO_error",
  180. (void *)hubdev_info))
  181. printk("ice_error_init: request_irq() error hubdev_info 0x%p\n",
  182. hubdev_info);
  183. return;
  184. }