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