static ssize_t edac_fake_inject_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) { struct device *dev = file->private_data; struct mem_ctl_info *mci = to_mci(dev); static enum hw_event_mc_err_type type; u16 errcount = mci->fake_inject_count; if (!errcount) errcount = 1; type = mci->fake_inject_ue ? HW_EVENT_ERR_UNCORRECTED : HW_EVENT_ERR_CORRECTED; printk(KERN_DEBUG "Generating %d %s fake error%s to %d.%d.%d to test core handling. NOTE: this won't test the driver-specific decoding logic.\n", errcount, (type == HW_EVENT_ERR_UNCORRECTED) ? "UE" : "CE", errcount > 1 ? "s" : "", mci->fake_inject_layer[0], mci->fake_inject_layer[1], mci->fake_inject_layer[2] ); edac_mc_handle_error(type, mci, errcount, 0, 0, 0, mci->fake_inject_layer[0], mci->fake_inject_layer[1], mci->fake_inject_layer[2], "FAKE ERROR", "for EDAC testing only"); return count; }
static ssize_t mci_reset_counters_store(struct device *dev, struct device_attribute *mattr, const char *data, size_t count) { struct mem_ctl_info *mci = to_mci(dev); int cnt, row, chan, i; mci->ue_mc = 0; mci->ce_mc = 0; mci->ue_noinfo_count = 0; mci->ce_noinfo_count = 0; for (row = 0; row < mci->nr_csrows; row++) { struct csrow_info *ri = mci->csrows[row]; ri->ue_count = 0; ri->ce_count = 0; for (chan = 0; chan < ri->nr_channels; chan++) ri->channels[chan]->ce_count = 0; } cnt = 1; for (i = 0; i < mci->n_layers; i++) { cnt *= mci->layers[i].size; memset(mci->ce_per_layer[i], 0, cnt * sizeof(u32)); memset(mci->ue_per_layer[i], 0, cnt * sizeof(u32)); } mci->start_time = jiffies; return count; }
static ssize_t mci_ctl_name_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); return sprintf(data, "%s\n", mci->ctl_name); }
static ssize_t mci_seconds_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); return sprintf(data, "%ld\n", (jiffies - mci->start_time) / HZ); }
static ssize_t mci_ue_noinfo_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); return sprintf(data, "%d\n", mci->ue_noinfo_count); }
static ssize_t inject_enable_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) { struct device *dev = file->private_data; struct mem_ctl_info *mci = to_mci(dev); i5100_do_inject(mci); return count; }
static ssize_t octeon_mc_inject_error_type_show(struct device *dev, struct device_attribute *attr, char *data) { struct mem_ctl_info *mci = to_mci(dev); struct octeon_lmc_pvt *pvt = mci->pvt_info; if (pvt->error_type == 1) return sprintf(data, "single"); else if (pvt->error_type == 2) return sprintf(data, "double"); return 0; }
/* * ->get_sdram_scrub_rate() return value semantics same as above. */ static ssize_t mci_sdram_scrub_rate_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); int bandwidth = 0; bandwidth = mci->get_sdram_scrub_rate(mci); if (bandwidth < 0) { edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"); return bandwidth; } return sprintf(data, "%d\n", bandwidth); }
static umode_t mci_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx) { struct device *dev = kobj_to_dev(kobj); struct mem_ctl_info *mci = to_mci(dev); umode_t mode = 0; if (attr != &dev_attr_sdram_scrub_rate.attr) return attr->mode; if (mci->get_sdram_scrub_rate) mode |= S_IRUGO; if (mci->set_sdram_scrub_rate) mode |= S_IWUSR; return mode; }
static ssize_t octeon_mc_inject_error_type_store(struct device *dev, struct device_attribute *attr, const char *data, size_t count) { struct mem_ctl_info *mci = to_mci(dev); struct octeon_lmc_pvt *pvt = mci->pvt_info; if (!strncmp(data, "single", 6)) pvt->error_type = 1; else if (!strncmp(data, "double", 6)) pvt->error_type = 2; return count; }
static ssize_t amd64_hole_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); 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); }
static ssize_t mci_max_location_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); int i; char *p = data; for (i = 0; i < mci->n_layers; i++) { p += sprintf(p, "%s %d ", edac_layer_name[mci->layers[i].type], mci->layers[i].size - 1); } return p - data; }
static ssize_t mci_size_mb_show(struct device *dev, struct device_attribute *mattr, char *data) { struct mem_ctl_info *mci = to_mci(dev); int total_pages = 0, csrow_idx, j; for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { struct csrow_info *csrow = mci->csrows[csrow_idx]; for (j = 0; j < csrow->nr_channels; j++) { struct dimm_info *dimm = csrow->channels[j]->dimm; total_pages += dimm->nr_pages; } } return sprintf(data, "%u\n", PAGES_TO_MiB(total_pages)); }
/* Memory scrubbing interface: * * A MC driver can limit the scrubbing bandwidth based on the CPU type. * Therefore, ->set_sdram_scrub_rate should be made to return the actual * bandwidth that is accepted or 0 when scrubbing is to be disabled. * * Negative value still means that an error has occurred while setting * the scrub rate. */ static ssize_t mci_sdram_scrub_rate_store(struct device *dev, struct device_attribute *mattr, const char *data, size_t count) { struct mem_ctl_info *mci = to_mci(dev); unsigned long bandwidth = 0; int new_bw = 0; if (kstrtoul(data, 10, &bandwidth) < 0) return -EINVAL; new_bw = mci->set_sdram_scrub_rate(mci, bandwidth); if (new_bw < 0) { edac_printk(KERN_WARNING, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth); return -EINVAL; } return count; }