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