amd64_edac_inj.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include "amd64_edac.h"
  2. static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf)
  3. {
  4. struct amd64_pvt *pvt = mci->pvt_info;
  5. return sprintf(buf, "0x%x\n", pvt->injection.section);
  6. }
  7. /*
  8. * store error injection section value which refers to one of 4 16-byte sections
  9. * within a 64-byte cacheline
  10. *
  11. * range: 0..3
  12. */
  13. static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci,
  14. const char *data, size_t count)
  15. {
  16. struct amd64_pvt *pvt = mci->pvt_info;
  17. unsigned long value;
  18. int ret = 0;
  19. ret = strict_strtoul(data, 10, &value);
  20. if (ret != -EINVAL) {
  21. if (value > 3) {
  22. amd64_printk(KERN_WARNING,
  23. "%s: invalid section 0x%lx\n",
  24. __func__, value);
  25. return -EINVAL;
  26. }
  27. pvt->injection.section = (u32) value;
  28. return count;
  29. }
  30. return ret;
  31. }
  32. static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf)
  33. {
  34. struct amd64_pvt *pvt = mci->pvt_info;
  35. return sprintf(buf, "0x%x\n", pvt->injection.word);
  36. }
  37. /*
  38. * store error injection word value which refers to one of 9 16-bit word of the
  39. * 16-byte (128-bit + ECC bits) section
  40. *
  41. * range: 0..8
  42. */
  43. static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci,
  44. const char *data, size_t count)
  45. {
  46. struct amd64_pvt *pvt = mci->pvt_info;
  47. unsigned long value;
  48. int ret = 0;
  49. ret = strict_strtoul(data, 10, &value);
  50. if (ret != -EINVAL) {
  51. if (value > 8) {
  52. amd64_printk(KERN_WARNING,
  53. "%s: invalid word 0x%lx\n",
  54. __func__, value);
  55. return -EINVAL;
  56. }
  57. pvt->injection.word = (u32) value;
  58. return count;
  59. }
  60. return ret;
  61. }
  62. static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf)
  63. {
  64. struct amd64_pvt *pvt = mci->pvt_info;
  65. return sprintf(buf, "0x%x\n", pvt->injection.bit_map);
  66. }
  67. /*
  68. * store 16 bit error injection vector which enables injecting errors to the
  69. * corresponding bit within the error injection word above. When used during a
  70. * DRAM ECC read, it holds the contents of the of the DRAM ECC bits.
  71. */
  72. static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci,
  73. const char *data, size_t count)
  74. {
  75. struct amd64_pvt *pvt = mci->pvt_info;
  76. unsigned long value;
  77. int ret = 0;
  78. ret = strict_strtoul(data, 16, &value);
  79. if (ret != -EINVAL) {
  80. if (value & 0xFFFF0000) {
  81. amd64_printk(KERN_WARNING,
  82. "%s: invalid EccVector: 0x%lx\n",
  83. __func__, value);
  84. return -EINVAL;
  85. }
  86. pvt->injection.bit_map = (u32) value;
  87. return count;
  88. }
  89. return ret;
  90. }
  91. /*
  92. * Do a DRAM ECC read. Assemble staged values in the pvt area, format into
  93. * fields needed by the injection registers and read the NB Array Data Port.
  94. */
  95. static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci,
  96. const char *data, size_t count)
  97. {
  98. struct amd64_pvt *pvt = mci->pvt_info;
  99. unsigned long value;
  100. u32 section, word_bits;
  101. int ret = 0;
  102. ret = strict_strtoul(data, 10, &value);
  103. if (ret != -EINVAL) {
  104. /* Form value to choose 16-byte section of cacheline */
  105. section = F10_NB_ARRAY_DRAM_ECC |
  106. SET_NB_ARRAY_ADDRESS(pvt->injection.section);
  107. pci_write_config_dword(pvt->misc_f3_ctl,
  108. F10_NB_ARRAY_ADDR, section);
  109. word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word,
  110. pvt->injection.bit_map);
  111. /* Issue 'word' and 'bit' along with the READ request */
  112. pci_write_config_dword(pvt->misc_f3_ctl,
  113. F10_NB_ARRAY_DATA, word_bits);
  114. debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
  115. return count;
  116. }
  117. return ret;
  118. }
  119. /*
  120. * Do a DRAM ECC write. Assemble staged values in the pvt area and format into
  121. * fields needed by the injection registers.
  122. */
  123. static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci,
  124. const char *data, size_t count)
  125. {
  126. struct amd64_pvt *pvt = mci->pvt_info;
  127. unsigned long value;
  128. u32 section, word_bits;
  129. int ret = 0;
  130. ret = strict_strtoul(data, 10, &value);
  131. if (ret != -EINVAL) {
  132. /* Form value to choose 16-byte section of cacheline */
  133. section = F10_NB_ARRAY_DRAM_ECC |
  134. SET_NB_ARRAY_ADDRESS(pvt->injection.section);
  135. pci_write_config_dword(pvt->misc_f3_ctl,
  136. F10_NB_ARRAY_ADDR, section);
  137. word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word,
  138. pvt->injection.bit_map);
  139. /* Issue 'word' and 'bit' along with the READ request */
  140. pci_write_config_dword(pvt->misc_f3_ctl,
  141. F10_NB_ARRAY_DATA, word_bits);
  142. debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
  143. return count;
  144. }
  145. return ret;
  146. }
  147. /*
  148. * update NUM_INJ_ATTRS in case you add new members
  149. */
  150. struct mcidev_sysfs_attribute amd64_inj_attrs[] = {
  151. {
  152. .attr = {
  153. .name = "inject_section",
  154. .mode = (S_IRUGO | S_IWUSR)
  155. },
  156. .show = amd64_inject_section_show,
  157. .store = amd64_inject_section_store,
  158. },
  159. {
  160. .attr = {
  161. .name = "inject_word",
  162. .mode = (S_IRUGO | S_IWUSR)
  163. },
  164. .show = amd64_inject_word_show,
  165. .store = amd64_inject_word_store,
  166. },
  167. {
  168. .attr = {
  169. .name = "inject_ecc_vector",
  170. .mode = (S_IRUGO | S_IWUSR)
  171. },
  172. .show = amd64_inject_ecc_vector_show,
  173. .store = amd64_inject_ecc_vector_store,
  174. },
  175. {
  176. .attr = {
  177. .name = "inject_write",
  178. .mode = (S_IRUGO | S_IWUSR)
  179. },
  180. .show = NULL,
  181. .store = amd64_inject_write_store,
  182. },
  183. {
  184. .attr = {
  185. .name = "inject_read",
  186. .mode = (S_IRUGO | S_IWUSR)
  187. },
  188. .show = NULL,
  189. .store = amd64_inject_read_store,
  190. },
  191. };