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