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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* $Id: hubcounters.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 - 2001 Silicon Graphics, Inc.
  8.  * All rights reserved.
  9.  */
  10. #include <linux/kernel.h>
  11. #include <linux/slab.h>
  12. #include <asm/types.h>
  13. #include <asm/sn/io.h>
  14. #include <asm/sn/nodepda.h>
  15. #include <asm/sn/iograph.h>
  16. #include <asm/sn/sn_cpuid.h>
  17. #include <asm/sn/router.h>
  18. #include <asm/sn/snconfig.h>
  19. #include <asm/sn/slotnum.h>
  20. #include <asm/sn/clksupport.h>
  21. #include <asm/sn/sndrv.h>
  22. extern void hubni_error_handler(char *, int); /* huberror.c */
  23. static int hubstats_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
  24. struct file_operations hub_mon_fops = {
  25.         ioctl:          hubstats_ioctl,
  26. };
  27. #define HUB_CAPTURE_TICKS (2 * HZ)
  28. #define HUB_ERR_THRESH 500
  29. #define USEC_PER_SEC 1000000
  30. #define NSEC_PER_SEC USEC_PER_SEC*1000
  31. volatile int hub_print_usecs = 600 * USEC_PER_SEC;
  32. /* Return success if the hub's crosstalk link is working */
  33. int
  34. hub_xtalk_link_up(nasid_t nasid)
  35. {
  36. hubreg_t llp_csr_reg;
  37. /* Read the IO LLP control status register */
  38. llp_csr_reg = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
  39. /* Check if the xtalk link is working */
  40. if (llp_csr_reg & IIO_LLP_CSR_IS_UP) 
  41. return(1);
  42. return(0);
  43. }
  44. static char *error_flag_to_type(unsigned char error_flag)
  45. {
  46.     switch(error_flag) {
  47.     case 0x1: return ("NI retries");
  48.     case 0x2: return ("NI SN errors");
  49.     case 0x4: return ("NI CB errors");
  50.     case 0x8: return ("II CB errors");
  51.     case 0x10: return ("II SN errors");
  52.     default: return ("Errors");
  53.     }
  54. }
  55. int
  56. print_hub_error(hubstat_t *hsp, hubreg_t reg,
  57. int64_t delta, unsigned char error_flag)
  58. {
  59. int64_t rate;
  60. reg *= hsp->hs_per_minute; /* Convert to minutes */
  61. rate = reg / delta;
  62. if (rate > HUB_ERR_THRESH) {
  63. if(hsp->hs_maint & error_flag) 
  64. {
  65. printk( "Excessive %s (%ld/min) on %s",
  66. error_flag_to_type(error_flag), rate, hsp->hs_name); 
  67. }
  68. else 
  69. {
  70.    hsp->hs_maint |= error_flag;
  71. printk( "Excessive %s (%ld/min) on %s",
  72. error_flag_to_type(error_flag), rate, hsp->hs_name); 
  73. }
  74. return 1;
  75. } else {
  76. return 0;
  77. }
  78. }
  79. int
  80. check_hub_error_rates(hubstat_t *hsp)
  81. {
  82. int64_t delta = hsp->hs_timestamp - hsp->hs_timebase;
  83. int printed = 0;
  84. printed += print_hub_error(hsp, hsp->hs_ni_retry_errors,
  85.    delta, 0x1);
  86. #if 0
  87. printed += print_hub_error(hsp, hsp->hs_ni_sn_errors,
  88.    delta, 0x2);
  89. #endif
  90. printed += print_hub_error(hsp, hsp->hs_ni_cb_errors,
  91.    delta, 0x4);
  92. /* If the hub's xtalk link is not working there is 
  93.  * no need to print the "Excessive..." warning 
  94.  * messages
  95.  */
  96. if (!hub_xtalk_link_up(hsp->hs_nasid))
  97. return(printed);
  98. printed += print_hub_error(hsp, hsp->hs_ii_cb_errors,
  99.    delta, 0x8);
  100. printed += print_hub_error(hsp, hsp->hs_ii_sn_errors,
  101.    delta, 0x10);
  102. return printed;
  103. }
  104. void
  105. capture_hub_stats(cnodeid_t cnodeid, struct nodepda_s *npda)
  106. {
  107. nasid_t nasid;
  108. hubstat_t *hsp = &(npda->hubstats);
  109. hubreg_t port_error;
  110. ii_illr_u_t illr;
  111. int count;
  112. int overflow = 0;
  113. /*
  114.  * If our link wasn't up at boot time, don't worry about error rates.
  115.  */
  116. if (!(hsp->hs_ni_port_status & NPS_LINKUP_MASK)) {
  117. printk("capture_hub_stats: cnode=%d hs_ni_port_status=0x%016lx : link is not upn",
  118. cnodeid, hsp->hs_ni_port_status);
  119. return;
  120. }
  121. nasid = COMPACT_TO_NASID_NODEID(cnodeid);
  122. hsp->hs_timestamp = GET_RTC_COUNTER();
  123. port_error = REMOTE_HUB_L(nasid, NI_PORT_ERROR_CLEAR);
  124. count = ((port_error & NPE_RETRYCOUNT_MASK) >> NPE_RETRYCOUNT_SHFT);
  125. hsp->hs_ni_retry_errors += count;
  126. if (count == NPE_COUNT_MAX)
  127. overflow = 1;
  128. count = ((port_error & NPE_SNERRCOUNT_MASK) >> NPE_SNERRCOUNT_SHFT);
  129. hsp->hs_ni_sn_errors += count;
  130. if (count == NPE_COUNT_MAX)
  131. overflow = 1;
  132. count = ((port_error & NPE_CBERRCOUNT_MASK) >> NPE_CBERRCOUNT_SHFT);
  133. hsp->hs_ni_cb_errors += count;
  134. if (overflow || count == NPE_COUNT_MAX)
  135. hsp->hs_ni_overflows++;
  136. if (port_error & NPE_FATAL_ERRORS) {
  137. #ifdef ajm
  138. hubni_error_handler("capture_hub_stats", 1);
  139. #else
  140. printk("Error: hubni_error_handler in capture_hub_stats");
  141. #endif
  142. }
  143. illr.ii_illr_regval = REMOTE_HUB_L(nasid, IIO_LLP_LOG);
  144. REMOTE_HUB_S(nasid, IIO_LLP_LOG, 0);
  145. hsp->hs_ii_sn_errors += illr.ii_illr_fld_s.i_sn_cnt;
  146. hsp->hs_ii_cb_errors += illr.ii_illr_fld_s.i_cb_cnt;
  147. if ((illr.ii_illr_fld_s.i_sn_cnt == IIO_LLP_SN_MAX) ||
  148.     (illr.ii_illr_fld_s.i_cb_cnt == IIO_LLP_CB_MAX))
  149. hsp->hs_ii_overflows++;
  150. if (hsp->hs_print) {
  151. if (check_hub_error_rates(hsp)) {
  152. hsp->hs_last_print = GET_RTC_COUNTER();
  153. hsp->hs_print = 0;
  154. }
  155. } else {
  156. if ((GET_RTC_COUNTER() -
  157.     hsp->hs_last_print) > hub_print_usecs)
  158. hsp->hs_print = 1;
  159. }
  160. npda->hubticks = HUB_CAPTURE_TICKS;
  161. }
  162. void
  163. init_hub_stats(cnodeid_t cnodeid, struct nodepda_s *npda)
  164. {
  165. hubstat_t *hsp = &(npda->hubstats);
  166. nasid_t nasid = cnodeid_to_nasid(cnodeid);
  167. bzero(&(npda->hubstats), sizeof(hubstat_t));
  168. hsp->hs_version = HUBSTAT_VERSION;
  169. hsp->hs_cnode = cnodeid;
  170. hsp->hs_nasid = nasid;
  171. hsp->hs_timebase = GET_RTC_COUNTER();
  172. hsp->hs_ni_port_status = REMOTE_HUB_L(nasid, NI_PORT_STATUS);
  173. /* Clear the II error counts. */
  174. REMOTE_HUB_S(nasid, IIO_LLP_LOG, 0);
  175. /* Clear the NI counts. */
  176. REMOTE_HUB_L(nasid, NI_PORT_ERROR_CLEAR);
  177. hsp->hs_per_minute = (long long)RTC_CYCLES_PER_SEC * 60LL;
  178. npda->hubticks = HUB_CAPTURE_TICKS;
  179. /* XX should use kmem_alloc_node */
  180. hsp->hs_name = (char *)kmalloc(MAX_HUB_PATH, GFP_KERNEL);
  181. ASSERT_ALWAYS(hsp->hs_name);
  182. sprintf(hsp->hs_name, "/dev/hw/" EDGE_LBL_MODULE "/%03d/"
  183.         EDGE_LBL_NODE "/" EDGE_LBL_HUB,
  184. npda->module_id);
  185. hsp->hs_last_print = 0;
  186. hsp->hs_print = 1;
  187. hub_print_usecs = hub_print_usecs;
  188. #if 0
  189. printk("init_hub_stats: cnode=%d nasid=%d hs_version=%d hs_ni_port_status=0x%016lxn",
  190. cnodeid, nasid, hsp->hs_version, hsp->hs_ni_port_status);
  191. #endif
  192. }
  193. static int
  194. hubstats_ioctl(struct inode *inode, struct file *file,
  195.         unsigned int cmd, unsigned long arg)
  196. {
  197.         cnodeid_t       cnode;
  198.         nodepda_t       *npdap;
  199.         uint64_t        longarg;
  200.         devfs_handle_t  d;
  201.         if ((d = devfs_get_handle_from_inode(inode)) == NULL)
  202.                 return -ENODEV;
  203.         cnode = (cnodeid_t)hwgraph_fastinfo_get(d);
  204.         npdap = NODEPDA(cnode);
  205. if (npdap->hubstats.hs_version != HUBSTAT_VERSION) {
  206. init_hub_stats(cnode, npdap);
  207. }
  208.         switch (cmd) {
  209. case SNDRV_GET_INFOSIZE:
  210. longarg = sizeof(hubstat_t);
  211. if (copy_to_user((void *)arg, &longarg, sizeof(longarg))) {
  212.     return -EFAULT;
  213. }
  214. break;
  215. case SNDRV_GET_HUBINFO:
  216. /* refresh npda->hubstats */
  217. capture_hub_stats(cnode, npdap);
  218. if (copy_to_user((void *)arg, &npdap->hubstats, sizeof(hubstat_t))) {
  219.     return -EFAULT;
  220. }
  221. break;
  222. default:
  223. return -EINVAL;
  224. }
  225. return 0;
  226. }