| #include "amd64_edac.h" |
| |
| /* |
| * accept a hex value and store it into the virtual error register file, field: |
| * nbeal and nbeah. Assume virtual error values have already been set for: NBSL, |
| * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and |
| * CHANNEL |
| */ |
| static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data, |
| size_t count) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| unsigned long long value; |
| int ret = 0; |
| |
| ret = strict_strtoull(data, 16, &value); |
| if (ret != -EINVAL) { |
| debugf0("received NBEA= 0x%llx\n", value); |
| |
| /* place the value into the virtual error packet */ |
| pvt->ctl_error_info.nbeal = (u32) value; |
| value >>= 32; |
| pvt->ctl_error_info.nbeah = (u32) value; |
| |
| /* Process the Mapping request */ |
| /* TODO: Add race prevention */ |
| amd_decode_nb_mce(pvt->mc_node_id, &pvt->ctl_error_info, 1); |
| |
| return count; |
| } |
| return ret; |
| } |
| |
| /* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */ |
| static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| u64 value; |
| |
| value = pvt->ctl_error_info.nbeah; |
| value <<= 32; |
| value |= pvt->ctl_error_info.nbeal; |
| |
| return sprintf(data, "%llx\n", value); |
| } |
| |
| /* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */ |
| static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data, |
| size_t count) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| unsigned long value; |
| int ret = 0; |
| |
| ret = strict_strtoul(data, 16, &value); |
| if (ret != -EINVAL) { |
| debugf0("received NBSL= 0x%lx\n", value); |
| |
| pvt->ctl_error_info.nbsl = (u32) value; |
| |
| return count; |
| } |
| return ret; |
| } |
| |
| /* display back what the last NBSL value written */ |
| static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| u32 value; |
| |
| value = pvt->ctl_error_info.nbsl; |
| |
| return sprintf(data, "%x\n", value); |
| } |
| |
| /* store the NBSH (MCA NB Status High) value user desires */ |
| static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data, |
| size_t count) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| unsigned long value; |
| int ret = 0; |
| |
| ret = strict_strtoul(data, 16, &value); |
| if (ret != -EINVAL) { |
| debugf0("received NBSH= 0x%lx\n", value); |
| |
| pvt->ctl_error_info.nbsh = (u32) value; |
| |
| return count; |
| } |
| return ret; |
| } |
| |
| /* display back what the last NBSH value written */ |
| static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| u32 value; |
| |
| value = pvt->ctl_error_info.nbsh; |
| |
| return sprintf(data, "%x\n", value); |
| } |
| |
| /* accept and store the NBCFG (MCA NB Configuration) value user desires */ |
| static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci, |
| const char *data, size_t count) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| unsigned long value; |
| int ret = 0; |
| |
| ret = strict_strtoul(data, 16, &value); |
| if (ret != -EINVAL) { |
| debugf0("received NBCFG= 0x%lx\n", value); |
| |
| pvt->ctl_error_info.nbcfg = (u32) value; |
| |
| return count; |
| } |
| return ret; |
| } |
| |
| /* various show routines for the controls of a MCI */ |
| static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| |
| return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg); |
| } |
| |
| |
| static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| |
| return sprintf(data, "%x\n", pvt->dhar); |
| } |
| |
| |
| static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| |
| return sprintf(data, "%x\n", pvt->dbam0); |
| } |
| |
| |
| static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| |
| return sprintf(data, "%llx\n", pvt->top_mem); |
| } |
| |
| |
| static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data) |
| { |
| struct amd64_pvt *pvt = mci->pvt_info; |
| |
| return sprintf(data, "%llx\n", pvt->top_mem2); |
| } |
| |
| static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) |
| { |
| u64 hole_base = 0; |
| u64 hole_offset = 0; |
| u64 hole_size = 0; |
| |
| amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size); |
| |
| return sprintf(data, "%llx %llx %llx\n", hole_base, hole_offset, |
| hole_size); |
| } |
| |
| /* |
| * update NUM_DBG_ATTRS in case you add new members |
| */ |
| struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { |
| |
| { |
| .attr = { |
| .name = "nbea_ctl", |
| .mode = (S_IRUGO | S_IWUSR) |
| }, |
| .show = amd64_nbea_show, |
| .store = amd64_nbea_store, |
| }, |
| { |
| .attr = { |
| .name = "nbsl_ctl", |
| .mode = (S_IRUGO | S_IWUSR) |
| }, |
| .show = amd64_nbsl_show, |
| .store = amd64_nbsl_store, |
| }, |
| { |
| .attr = { |
| .name = "nbsh_ctl", |
| .mode = (S_IRUGO | S_IWUSR) |
| }, |
| .show = amd64_nbsh_show, |
| .store = amd64_nbsh_store, |
| }, |
| { |
| .attr = { |
| .name = "nbcfg_ctl", |
| .mode = (S_IRUGO | S_IWUSR) |
| }, |
| .show = amd64_nbcfg_show, |
| .store = amd64_nbcfg_store, |
| }, |
| { |
| .attr = { |
| .name = "dhar", |
| .mode = (S_IRUGO) |
| }, |
| .show = amd64_dhar_show, |
| .store = NULL, |
| }, |
| { |
| .attr = { |
| .name = "dbam", |
| .mode = (S_IRUGO) |
| }, |
| .show = amd64_dbam_show, |
| .store = NULL, |
| }, |
| { |
| .attr = { |
| .name = "topmem", |
| .mode = (S_IRUGO) |
| }, |
| .show = amd64_topmem_show, |
| .store = NULL, |
| }, |
| { |
| .attr = { |
| .name = "topmem2", |
| .mode = (S_IRUGO) |
| }, |
| .show = amd64_topmem2_show, |
| .store = NULL, |
| }, |
| { |
| .attr = { |
| .name = "dram_hole", |
| .mode = (S_IRUGO) |
| }, |
| .show = amd64_hole_show, |
| .store = NULL, |
| }, |
| }; |