amd64_edac_inj.c 5.0 KB

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