Commit 1a370f4c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'edac_for_4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp

Pull EDAC updates from Borislav Petkov:

 - convert a bunch of drivers to static attribute groups (Takashi Iwai)

 - misc cleanups

* tag 'edac_for_4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  EDAC: Constify of_device_id array
  EDAC, i82443bxgx: Don't export static symbol
  EDAC, amd64_edac: Get rid of per-node driver instances
  EDAC: Properly unwind on failure path in edac_init()
  EDAC: highbank: Use static attribute groups for sysfs entries
  EDAC: octeon: Use static attribute groups for sysfs entries
  EDAC: mpc85xx: Use static attribute groups for sysfs entries
  EDAC: i7core: Use static attribute groups for sysfs entries
  EDAC: i7core: Return proper error codes for kzalloc() errors
  EDAC: amd64: Use static attribute groups
  EDAC: Allow to pass driver-specific attribute groups
  EDAC: Use static attribute groups for managing sysfs entries
  EDAC: Delete unnecessary checks before pci_dev_put()
parents 4b5ca741 1afaa055
......@@ -20,8 +20,7 @@ static struct msr __percpu *msrs;
*/
static atomic_t drv_instances = ATOMIC_INIT(0);
/* Per-node driver instances */
static struct mem_ctl_info **mcis;
/* Per-node stuff */
static struct ecc_settings **ecc_stngs;
/*
......@@ -903,9 +902,17 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
/* On F10h and later ErrAddr is MC4_ADDR[47:1] */
static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
{
u64 addr;
u16 mce_nid = amd_get_nb_id(m->extcpu);
struct mem_ctl_info *mci;
u8 start_bit = 1;
u8 end_bit = 47;
u64 addr;
mci = edac_mc_find(mce_nid);
if (!mci)
return 0;
pvt = mci->pvt_info;
if (pvt->fam == 0xf) {
start_bit = 3;
......@@ -918,17 +925,13 @@ static u64 get_error_address(struct amd64_pvt *pvt, struct mce *m)
* Erratum 637 workaround
*/
if (pvt->fam == 0x15) {
struct amd64_pvt *pvt;
u64 cc6_base, tmp_addr;
u32 tmp;
u16 mce_nid;
u8 intlv_en;
if ((addr & GENMASK_ULL(47, 24)) >> 24 != 0x00fdf7)
return addr;
mce_nid = amd_get_nb_id(m->extcpu);
pvt = mcis[mce_nid]->pvt_info;
amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp);
intlv_en = tmp >> 21 & 0x7;
......@@ -1511,7 +1514,7 @@ static int f1x_lookup_addr_in_dct(u64 in_addr, u8 nid, u8 dct)
int cs_found = -EINVAL;
int csrow;
mci = mcis[nid];
mci = edac_mc_find(nid);
if (!mci)
return cs_found;
......@@ -2663,34 +2666,6 @@ static bool ecc_enabled(struct pci_dev *F3, u16 nid)
return true;
}
static int set_mc_sysfs_attrs(struct mem_ctl_info *mci)
{
struct amd64_pvt *pvt = mci->pvt_info;
int rc;
rc = amd64_create_sysfs_dbg_files(mci);
if (rc < 0)
return rc;
if (pvt->fam >= 0x10) {
rc = amd64_create_sysfs_inject_files(mci);
if (rc < 0)
return rc;
}
return 0;
}
static void del_mc_sysfs_attrs(struct mem_ctl_info *mci)
{
struct amd64_pvt *pvt = mci->pvt_info;
amd64_remove_sysfs_dbg_files(mci);
if (pvt->fam >= 0x10)
amd64_remove_sysfs_inject_files(mci);
}
static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
struct amd64_family_type *fam)
{
......@@ -2778,6 +2753,16 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt)
return fam_type;
}
static const struct attribute_group *amd64_edac_attr_groups[] = {
#ifdef CONFIG_EDAC_DEBUG
&amd64_edac_dbg_group,
#endif
#ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION
&amd64_edac_inj_group,
#endif
NULL
};
static int init_one_instance(struct pci_dev *F2)
{
struct amd64_pvt *pvt = NULL;
......@@ -2844,14 +2829,10 @@ static int init_one_instance(struct pci_dev *F2)
mci->edac_cap = EDAC_FLAG_NONE;
ret = -ENODEV;
if (edac_mc_add_mc(mci)) {
if (edac_mc_add_mc_with_groups(mci, amd64_edac_attr_groups)) {
edac_dbg(1, "failed edac_mc_add_mc()\n");
goto err_add_mc;
}
if (set_mc_sysfs_attrs(mci)) {
edac_dbg(1, "failed edac_mc_add_mc()\n");
goto err_add_sysfs;
}
/* register stuff with EDAC MCE */
if (report_gart_errors)
......@@ -2859,14 +2840,10 @@ static int init_one_instance(struct pci_dev *F2)
amd_register_ecc_decoder(decode_bus_error);
mcis[nid] = mci;
atomic_inc(&drv_instances);
return 0;
err_add_sysfs:
edac_mc_del_mc(mci->pdev);
err_add_mc:
edac_mc_free(mci);
......@@ -2940,7 +2917,6 @@ static void remove_one_instance(struct pci_dev *pdev)
mci = find_mci_by_dev(&pdev->dev);
WARN_ON(!mci);
del_mc_sysfs_attrs(mci);
/* Remove from EDAC CORE tracking list */
mci = edac_mc_del_mc(&pdev->dev);
if (!mci)
......@@ -2961,7 +2937,6 @@ static void remove_one_instance(struct pci_dev *pdev)
/* Free the EDAC CORE resources */
mci->pvt_info = NULL;
mcis[nid] = NULL;
kfree(pvt);
edac_mc_free(mci);
......@@ -2999,7 +2974,7 @@ static void setup_pci_device(void)
if (pci_ctl)
return;
mci = mcis[0];
mci = edac_mc_find(0);
if (!mci)
return;
......@@ -3023,9 +2998,8 @@ static int __init amd64_edac_init(void)
goto err_ret;
err = -ENOMEM;
mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
if (!(mcis && ecc_stngs))
if (!ecc_stngs)
goto err_free;
msrs = msrs_alloc();
......@@ -3056,9 +3030,6 @@ static int __init amd64_edac_init(void)
msrs = NULL;
err_free:
kfree(mcis);
mcis = NULL;
kfree(ecc_stngs);
ecc_stngs = NULL;
......@@ -3076,9 +3047,6 @@ static void __exit amd64_edac_exit(void)
kfree(ecc_stngs);
ecc_stngs = NULL;
kfree(mcis);
mcis = NULL;
msrs_free(msrs);
msrs = NULL;
}
......
......@@ -453,31 +453,11 @@ struct ecc_settings {
};
#ifdef CONFIG_EDAC_DEBUG
int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci);
void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci);
#else
static inline int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci)
{
return 0;
}
static void inline amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci)
{
}
extern const struct attribute_group amd64_edac_dbg_group;
#endif
#ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION
int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci);
void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci);
#else
static inline int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci)
{
return 0;
}
static inline void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
{
}
extern const struct attribute_group amd64_edac_inj_group;
#endif
/*
......
......@@ -40,34 +40,15 @@ static DEVICE_ATTR(topmem, S_IRUGO, amd64_top_mem_show, NULL);
static DEVICE_ATTR(topmem2, S_IRUGO, amd64_top_mem2_show, NULL);
static DEVICE_ATTR(dram_hole, S_IRUGO, amd64_hole_show, NULL);
int amd64_create_sysfs_dbg_files(struct mem_ctl_info *mci)
{
int rc;
rc = device_create_file(&mci->dev, &dev_attr_dhar);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_dbam);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_topmem);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_topmem2);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_dram_hole);
if (rc < 0)
return rc;
return 0;
}
void amd64_remove_sysfs_dbg_files(struct mem_ctl_info *mci)
{
device_remove_file(&mci->dev, &dev_attr_dhar);
device_remove_file(&mci->dev, &dev_attr_dbam);
device_remove_file(&mci->dev, &dev_attr_topmem);
device_remove_file(&mci->dev, &dev_attr_topmem2);
device_remove_file(&mci->dev, &dev_attr_dram_hole);
}
static struct attribute *amd64_edac_dbg_attrs[] = {
&dev_attr_dhar.attr,
&dev_attr_dbam.attr,
&dev_attr_topmem.attr,
&dev_attr_topmem2.attr,
&dev_attr_dram_hole.attr,
NULL
};
const struct attribute_group amd64_edac_dbg_group = {
.attrs = amd64_edac_dbg_attrs,
};
......@@ -207,35 +207,28 @@ static DEVICE_ATTR(inject_write, S_IWUSR,
static DEVICE_ATTR(inject_read, S_IWUSR,
NULL, amd64_inject_read_store);
int amd64_create_sysfs_inject_files(struct mem_ctl_info *mci)
static struct attribute *amd64_edac_inj_attrs[] = {
&dev_attr_inject_section.attr,
&dev_attr_inject_word.attr,
&dev_attr_inject_ecc_vector.attr,
&dev_attr_inject_write.attr,
&dev_attr_inject_read.attr,
NULL
};
static umode_t amd64_edac_inj_is_visible(struct kobject *kobj,
struct attribute *attr, int idx)
{
int rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_section);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_word);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_ecc_vector);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_write);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_read);
if (rc < 0)
return rc;
return 0;
}
struct device *dev = kobj_to_dev(kobj);
struct mem_ctl_info *mci = container_of(dev, struct mem_ctl_info, dev);
struct amd64_pvt *pvt = mci->pvt_info;
void amd64_remove_sysfs_inject_files(struct mem_ctl_info *mci)
{
device_remove_file(&mci->dev, &dev_attr_inject_section);
device_remove_file(&mci->dev, &dev_attr_inject_word);
device_remove_file(&mci->dev, &dev_attr_inject_ecc_vector);
device_remove_file(&mci->dev, &dev_attr_inject_write);
device_remove_file(&mci->dev, &dev_attr_inject_read);
if (pvt->fam < 0x10)
return 0;
return attr->mode;
}
const struct attribute_group amd64_edac_inj_group = {
.attrs = amd64_edac_inj_attrs,
.is_visible = amd64_edac_inj_is_visible,
};
......@@ -446,7 +446,9 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
unsigned n_layers,
struct edac_mc_layer *layers,
unsigned sz_pvt);
extern int edac_mc_add_mc(struct mem_ctl_info *mci);
extern int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
const struct attribute_group **groups);
#define edac_mc_add_mc(mci) edac_mc_add_mc_with_groups(mci, NULL)
extern void edac_mc_free(struct mem_ctl_info *mci);
extern struct mem_ctl_info *edac_mc_find(int idx);
extern struct mem_ctl_info *find_mci_by_dev(struct device *dev);
......
......@@ -710,9 +710,10 @@ struct mem_ctl_info *edac_mc_find(int idx)
EXPORT_SYMBOL(edac_mc_find);
/**
* edac_mc_add_mc: Insert the 'mci' structure into the mci global list and
* create sysfs entries associated with mci structure
* edac_mc_add_mc_with_groups: Insert the 'mci' structure into the mci
* global list and create sysfs entries associated with mci structure
* @mci: pointer to the mci structure to be added to the list
* @groups: optional attribute groups for the driver-specific sysfs entries
*
* Return:
* 0 Success
......@@ -720,7 +721,8 @@ EXPORT_SYMBOL(edac_mc_find);
*/
/* FIXME - should a warning be printed if no error detection? correction? */
int edac_mc_add_mc(struct mem_ctl_info *mci)
int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
const struct attribute_group **groups)
{
int ret = -EINVAL;
edac_dbg(0, "\n");
......@@ -771,7 +773,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
mci->bus = &mc_bus[mci->mc_idx];
if (edac_create_sysfs_mci_device(mci)) {
if (edac_create_sysfs_mci_device(mci, groups)) {
edac_mc_printk(mci, KERN_WARNING,
"failed to create sysfs device\n");
goto fail1;
......@@ -805,7 +807,7 @@ int edac_mc_add_mc(struct mem_ctl_info *mci)
mutex_unlock(&mem_ctls_mutex);
return ret;
}
EXPORT_SYMBOL_GPL(edac_mc_add_mc);
EXPORT_SYMBOL_GPL(edac_mc_add_mc_with_groups);
/**
* edac_mc_del_mc: Remove sysfs entries for specified mci structure and
......
......@@ -323,13 +323,14 @@ DEVICE_CHANNEL(ch5_dimm_label, S_IRUGO | S_IWUSR,
channel_dimm_label_show, channel_dimm_label_store, 5);
/* Total possible dynamic DIMM Label attribute file table */
static struct device_attribute *dynamic_csrow_dimm_attr[] = {
&dev_attr_legacy_ch0_dimm_label.attr,
&dev_attr_legacy_ch1_dimm_label.attr,
&dev_attr_legacy_ch2_dimm_label.attr,
&dev_attr_legacy_ch3_dimm_label.attr,
&dev_attr_legacy_ch4_dimm_label.attr,
&dev_attr_legacy_ch5_dimm_label.attr
static struct attribute *dynamic_csrow_dimm_attr[] = {
&dev_attr_legacy_ch0_dimm_label.attr.attr,
&dev_attr_legacy_ch1_dimm_label.attr.attr,
&dev_attr_legacy_ch2_dimm_label.attr.attr,
&dev_attr_legacy_ch3_dimm_label.attr.attr,
&dev_attr_legacy_ch4_dimm_label.attr.attr,
&dev_attr_legacy_ch5_dimm_label.attr.attr,
NULL
};
/* possible dynamic channel ce_count attribute files */
......@@ -347,13 +348,45 @@ DEVICE_CHANNEL(ch5_ce_count, S_IRUGO,
channel_ce_count_show, NULL, 5);
/* Total possible dynamic ce_count attribute file table */
static struct device_attribute *dynamic_csrow_ce_count_attr[] = {
&dev_attr_legacy_ch0_ce_count.attr,
&dev_attr_legacy_ch1_ce_count.attr,
&dev_attr_legacy_ch2_ce_count.attr,
&dev_attr_legacy_ch3_ce_count.attr,
&dev_attr_legacy_ch4_ce_count.attr,
&dev_attr_legacy_ch5_ce_count.attr
static struct attribute *dynamic_csrow_ce_count_attr[] = {
&dev_attr_legacy_ch0_ce_count.attr.attr,
&dev_attr_legacy_ch1_ce_count.attr.attr,
&dev_attr_legacy_ch2_ce_count.attr.attr,
&dev_attr_legacy_ch3_ce_count.attr.attr,
&dev_attr_legacy_ch4_ce_count.attr.attr,
&dev_attr_legacy_ch5_ce_count.attr.attr,
NULL
};
static umode_t csrow_dev_is_visible(struct kobject *kobj,
struct attribute *attr, int idx)
{
struct device *dev = kobj_to_dev(kobj);
struct csrow_info *csrow = container_of(dev, struct csrow_info, dev);
if (idx >= csrow->nr_channels)
return 0;
/* Only expose populated DIMMs */
if (!csrow->channels[idx]->dimm->nr_pages)
return 0;
return attr->mode;
}
static const struct attribute_group csrow_dev_dimm_group = {
.attrs = dynamic_csrow_dimm_attr,
.is_visible = csrow_dev_is_visible,
};
static const struct attribute_group csrow_dev_ce_count_group = {
.attrs = dynamic_csrow_ce_count_attr,
.is_visible = csrow_dev_is_visible,
};
static const struct attribute_group *csrow_dev_groups[] = {
&csrow_dev_dimm_group,
&csrow_dev_ce_count_group,
NULL
};
static inline int nr_pages_per_csrow(struct csrow_info *csrow)
......@@ -370,13 +403,12 @@ static inline int nr_pages_per_csrow(struct csrow_info *csrow)
static int edac_create_csrow_object(struct mem_ctl_info *mci,
struct csrow_info *csrow, int index)
{
int err, chan;
if (csrow->nr_channels > EDAC_NR_CHANNELS)
return -ENODEV;
csrow->dev.type = &csrow_attr_type;
csrow->dev.bus = mci->bus;
csrow->dev.groups = csrow_dev_groups;
device_initialize(&csrow->dev);
csrow->dev.parent = &mci->dev;
csrow->mci = mci;
......@@ -386,45 +418,13 @@ static int edac_create_csrow_object(struct mem_ctl_info *mci,
edac_dbg(0, "creating (virtual) csrow node %s\n",
dev_name(&csrow->dev));
err = device_add(&csrow->dev);
if (err < 0)
return err;
for (chan = 0; chan < csrow->nr_channels; chan++) {
/* Only expose populated DIMMs */
if (!csrow->channels[chan]->dimm->nr_pages)
continue;
err = device_create_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]);
if (err < 0)
goto error;
err = device_create_file(&csrow->dev,
dynamic_csrow_ce_count_attr[chan]);
if (err < 0) {
device_remove_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]);
goto error;
}
}
return 0;
error:
for (--chan; chan >= 0; chan--) {
device_remove_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]);
device_remove_file(&csrow->dev,
dynamic_csrow_ce_count_attr[chan]);
}
put_device(&csrow->dev);
return err;
return device_add(&csrow->dev);
}
/* Create a CSROW object under specifed edac_mc_device */
static int edac_create_csrow_objects(struct mem_ctl_info *mci)
{
int err, i, chan;
int err, i;
struct csrow_info *csrow;
for (i = 0; i < mci->nr_csrows; i++) {
......@@ -446,14 +446,6 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
csrow = mci->csrows[i];
if (!nr_pages_per_csrow(csrow))
continue;
for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
if (!csrow->channels[chan]->dimm->nr_pages)
continue;
device_remove_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]);
device_remove_file(&csrow->dev,
dynamic_csrow_ce_count_attr[chan]);
}
put_device(&mci->csrows[i]->dev);
}
......@@ -462,23 +454,13 @@ static int edac_create_csrow_objects(struct mem_ctl_info *mci)
static void edac_delete_csrow_objects(struct mem_ctl_info *mci)
{
int i, chan;
int i;
struct csrow_info *csrow;
for (i = mci->nr_csrows - 1; i >= 0; i--) {
csrow = mci->csrows[i];
if (!nr_pages_per_csrow(csrow))
continue;
for (chan = csrow->nr_channels - 1; chan >= 0; chan--) {
if (!csrow->channels[chan]->dimm->nr_pages)
continue;
edac_dbg(1, "Removing csrow %d channel %d sysfs nodes\n",
i, chan);
device_remove_file(&csrow->dev,
dynamic_csrow_dimm_attr[chan]);
device_remove_file(&csrow->dev,
dynamic_csrow_ce_count_attr[chan]);
}
device_unregister(&mci->csrows[i]->dev);
}
}
......@@ -863,7 +845,8 @@ static DEVICE_ATTR(ce_count, S_IRUGO, mci_ce_count_show, NULL);
static DEVICE_ATTR(max_location, S_IRUGO, mci_max_location_show, NULL);
/* memory scrubber attribute file */
static DEVICE_ATTR(sdram_scrub_rate, 0, NULL, NULL);
DEVICE_ATTR(sdram_scrub_rate, 0, mci_sdram_scrub_rate_show,
mci_sdram_scrub_rate_store); /* umode set later in is_visible */
static struct attribute *mci_attrs[] = {
&dev_attr_reset_counters.attr,
......@@ -875,11 +858,29 @@ static struct attribute *mci_attrs[] = {
&dev_attr_ue_count.attr,
&dev_attr_ce_count.attr,
&dev_attr_max_location.attr,
&dev_attr_sdram_scrub_rate.attr,
NULL
};
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 struct attribute_group mci_attr_grp = {
.attrs = mci_attrs,
.is_visible = mci_attr_is_visible,
};
static const struct attribute_group *mci_attr_groups[] = {
......@@ -913,7 +914,7 @@ int __init edac_debugfs_init(void)
return 0;
}
void __exit edac_debugfs_exit(void)
void edac_debugfs_exit(void)
{
debugfs_remove(edac_debugfs);
}
......@@ -973,7 +974,8 @@ static int edac_create_debug_nodes(struct mem_ctl_info *mci)
* 0 Success
* !0 Failure
*/
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
const struct attribute_group **groups)
{
int i, err;
......@@ -997,6 +999,7 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
mci->dev.parent = mci_pdev;
mci->dev.bus = mci->bus;
mci->dev.groups = groups;
dev_set_name(&mci->dev, "mc%d", mci->mc_idx);
dev_set_drvdata(&mci->dev, mci);
pm_runtime_forbid(&mci->dev);
......@@ -1008,23 +1011,6 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
goto fail_unregister_bus;
}
if (mci->set_sdram_scrub_rate || mci->get_sdram_scrub_rate) {
if (mci->get_sdram_scrub_rate) {
dev_attr_sdram_scrub_rate.attr.mode |= S_IRUGO;
dev_attr_sdram_scrub_rate.show = &mci_sdram_scrub_rate_show;
}
if (mci->set_sdram_scrub_rate) {
dev_attr_sdram_scrub_rate.attr.mode |= S_IWUSR;
dev_attr_sdram_scrub_rate.store = &mci_sdram_scrub_rate_store;
}
err = device_create_file(&mci->dev, &dev_attr_sdram_scrub_rate);
if (err) {
edac_dbg(1, "failure: create sdram_scrub_rate\n");
goto fail_unregister_dev;
}
}
/*
* Create the dimm/rank devices
*/
......@@ -1071,7 +1057,6 @@ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
device_unregister(&dimm->dev);
}
fail_unregister_dev:
device_unregister(&mci->dev);
fail_unregister_bus:
bus_unregister(mci->bus);
......@@ -1170,7 +1155,7 @@ int __init edac_mc_sysfs_init(void)
return err;
}
void __exit edac_mc_sysfs_exit(void)
void edac_mc_sysfs_exit(void)
{
device_unregister(mci_pdev);
edac_put_sysfs_subsys();
......
......@@ -112,20 +112,23 @@ static int __init edac_init(void)
err = edac_mc_sysfs_init();
if (err)
goto error;
goto err_sysfs;
edac_debugfs_init();
/* Setup/Initialize the workq for this core */
err = edac_workqueue_setup();
if (err) {
edac_printk(KERN_ERR, EDAC_MC, "init WorkQueue failure\n");
goto error;
edac_printk(KERN_ERR, EDAC_MC, "Failure initializing workqueue\n");
goto err_wq;
}
return 0;
error:
err_wq:
edac_debugfs_exit();
edac_mc_sysfs_exit();
err_sysfs:
return err;
}
......
......@@ -22,7 +22,8 @@
/* on edac_mc_sysfs.c */
int edac_mc_sysfs_init(void);
void edac_mc_sysfs_exit(void);
extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci);
extern int edac_create_sysfs_mci_device(struct mem_ctl_info *mci,
const struct attribute_group **groups);
extern void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci);
void edac_unregister_sysfs(struct mem_ctl_info *mci);
extern int edac_get_log_ue(void);
......
......@@ -124,6 +124,13 @@ static ssize_t highbank_mc_inject_ctrl(struct device *dev,
static DEVICE_ATTR(inject_ctrl, S_IWUSR, NULL, highbank_mc_inject_ctrl);
static struct attribute *highbank_dev_attrs[] = {
&dev_attr_inject_ctrl.attr,
NULL
};
ATTRIBUTE_GROUPS(highbank_dev);
struct hb_mc_settings {
int err_offset;
int int_offset;
......@@ -139,7 +146,7 @@ static struct hb_mc_settings mw_settings = {
.int_offset = MW_DDR_ECC_INT_BASE,
};
static struct of_device_id hb_ddr_ctrl_of_match[] = {
static const struct of_device_id hb_ddr_ctrl_of_match[] = {
{ .compatible = "calxeda,hb-ddr-ctrl", .data = &hb_settings },
{ .compatible = "calxeda,ecx-2000-ddr-ctrl", .data = &mw_settings },
{},
......@@ -231,7 +238,7 @@ static int highbank_mc_probe(struct platform_device *pdev)
dimm->mtype = MEM_DDR3;
dimm->edac_mode = EDAC_SECDED;
res = edac_mc_add_mc(mci);
res = edac_mc_add_mc_with_groups(mci, highbank_dev_groups);
if (res < 0)
goto err;
......@@ -243,8 +250,6 @@ static int highbank_mc_probe(struct platform_device *pdev)
goto err2;
}
device_create_file(&mci->dev, &dev_attr_inject_ctrl);
devres_close_group(&pdev->dev, NULL);
return 0;
err2:
......@@ -259,7 +264,6 @@ static int highbank_mc_remove(struct platform_device *pdev)
{
struct mem_ctl_info *mci = platform_get_drvdata(pdev);
device_remove_file(&mci->dev, &dev_attr_inject_ctrl);
edac_mc_del_mc(&pdev->dev);
edac_mc_free(mci);
return 0;
......
......@@ -1157,27 +1157,24 @@ static DEVICE_ATTR(inject_eccmask, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(inject_enable, S_IRUGO | S_IWUSR,
i7core_inject_enable_show, i7core_inject_enable_store);
static struct attribute *i7core_dev_attrs[] = {
&dev_attr_inject_section.attr,
&dev_attr_inject_type.attr,
&dev_attr_inject_eccmask.attr,
&dev_attr_inject_enable.attr,
NULL
};
ATTRIBUTE_GROUPS(i7core_dev);
static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
{
struct i7core_pvt *pvt = mci->pvt_info;
int rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_section);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_type);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_eccmask);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_enable);
if (rc < 0)
return rc;
pvt->addrmatch_dev = kzalloc(sizeof(*pvt->addrmatch_dev), GFP_KERNEL);
if (!pvt->addrmatch_dev)
return rc;
return -ENOMEM;
pvt->addrmatch_dev->type = &addrmatch_type;
pvt->addrmatch_dev->bus = mci->dev.bus;
......@@ -1198,7 +1195,7 @@ static int i7core_create_sysfs_devices(struct mem_ctl_info *mci)
if (!pvt->chancounts_dev) {
put_device(pvt->addrmatch_dev);
device_del(pvt->addrmatch_dev);
return rc;
return -ENOMEM;
}
pvt->chancounts_dev->type = &all_channel_counts_type;
......@@ -1223,11 +1220,6 @@ static void i7core_delete_sysfs_devices(struct mem_ctl_info *mci)
edac_dbg(1, "\n");
device_remove_file(&mci->dev, &dev_attr_inject_section);
device_remove_file(&mci->dev, &dev_attr_inject_type);
device_remove_file(&mci->dev, &dev_attr_inject_eccmask);
device_remove_file(&mci->dev, &dev_attr_inject_enable);
if (!pvt->is_registered) {
put_device(pvt->chancounts_dev);
device_del(pvt->chancounts_dev);
......@@ -2259,7 +2251,7 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
enable_sdram_scrub_setting(mci);
/* add this new MC control structure to EDAC's list of MCs */
if (unlikely(edac_mc_add_mc(mci))) {
if (unlikely(edac_mc_add_mc_with_groups(mci, i7core_dev_groups))) {
edac_dbg(0, "MC: failed edac_mc_add_mc()\n");
/* FIXME: perhaps some code should go here that disables error
* reporting if we just enabled it
......
......@@ -350,8 +350,6 @@ static int i82443bxgx_edacmc_probe1(struct pci_dev *pdev, int dev_idx)
return -ENODEV;
}
EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_probe1);
/* returns count (>= 0), or negative on error */
static int i82443bxgx_edacmc_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
......@@ -384,8 +382,6 @@ static void i82443bxgx_edacmc_remove_one(struct pci_dev *pdev)
edac_mc_free(mci);
}
EXPORT_SYMBOL_GPL(i82443bxgx_edacmc_remove_one);
static const struct pci_device_id i82443bxgx_pci_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_0)},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2)},
......@@ -445,9 +441,7 @@ static int __init i82443bxgx_edacmc_init(void)
pci_unregister_driver(&i82443bxgx_edacmc_driver);
fail0:
if (mci_pdev != NULL)
pci_dev_put(mci_pdev);
pci_dev_put(mci_pdev);
return pci_rc;
}
......
......@@ -343,20 +343,15 @@ static int __init i82860_init(void)
pci_unregister_driver(&i82860_driver);
fail0:
if (mci_pdev != NULL)
pci_dev_put(mci_pdev);
pci_dev_put(mci_pdev);
return pci_rc;
}
static void __exit i82860_exit(void)
{
edac_dbg(3, "\n");
pci_unregister_driver(&i82860_driver);
if (mci_pdev != NULL)
pci_dev_put(mci_pdev);
pci_dev_put(mci_pdev);
}
module_init(i82860_init);
......
......@@ -576,9 +576,7 @@ static int __init i82875p_init(void)
pci_unregister_driver(&i82875p_driver);
fail0:
if (mci_pdev != NULL)
pci_dev_put(mci_pdev);
pci_dev_put(mci_pdev);
return pci_rc;
}
......
......@@ -685,9 +685,7 @@ static int __init i82975x_init(void)
pci_unregister_driver(&i82975x_driver);
fail0:
if (mci_pdev != NULL)
pci_dev_put(mci_pdev);
pci_dev_put(mci_pdev);
return pci_rc;
}
......
......@@ -134,29 +134,14 @@ DEVICE_ATTR(inject_data_lo, S_IRUGO | S_IWUSR,
DEVICE_ATTR(inject_ctrl, S_IRUGO | S_IWUSR,
mpc85xx_mc_inject_ctrl_show, mpc85xx_mc_inject_ctrl_store);
static int mpc85xx_create_sysfs_attributes(struct mem_ctl_info *mci)
{
int rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_data_hi);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_data_lo);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_inject_ctrl);
if (rc < 0)
return rc;
static struct attribute *mpc85xx_dev_attrs[] = {
&dev_attr_inject_data_hi.attr,
&dev_attr_inject_data_lo.attr,
&dev_attr_inject_ctrl.attr,
NULL
};
return 0;
}
static void mpc85xx_remove_sysfs_attributes(struct mem_ctl_info *mci)
{
device_remove_file(&mci->dev, &dev_attr_inject_data_hi);
device_remove_file(&mci->dev, &dev_attr_inject_data_lo);
device_remove_file(&mci->dev, &dev_attr_inject_ctrl);
}
ATTRIBUTE_GROUPS(mpc85xx_dev);
/**************************** PCI Err device ***************************/
#ifdef CONFIG_PCI
......@@ -685,7 +670,7 @@ static int mpc85xx_l2_err_remove(struct platform_device *op)
return 0;
}
static struct of_device_id mpc85xx_l2_err_of_match[] = {
static const struct of_device_id mpc85xx_l2_err_of_match[] = {
/* deprecate the fsl,85.. forms in the future, 2.6.30? */
{ .compatible = "fsl,8540-l2-cache-controller", },
{ .compatible = "fsl,8541-l2-cache-controller", },
......@@ -1106,13 +1091,7 @@ static int mpc85xx_mc_err_probe(struct platform_device *op)
/* clear all error bits */
out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_DETECT, ~0);
if (edac_mc_add_mc(mci)) {
edac_dbg(3, "failed edac_mc_add_mc()\n");
goto err;
}
if (mpc85xx_create_sysfs_attributes(mci)) {
edac_mc_del_mc(mci->pdev);
if (edac_mc_add_mc_with_groups(mci, mpc85xx_dev_groups)) {
edac_dbg(3, "failed edac_mc_add_mc()\n");
goto err;
}
......@@ -1176,13 +1155,12 @@ static int mpc85xx_mc_err_remove(struct platform_device *op)
orig_ddr_err_disable);
out_be32(pdata->mc_vbase + MPC85XX_MC_ERR_SBE, orig_ddr_err_sbe);
mpc85xx_remove_sysfs_attributes(mci);
edac_mc_del_mc(&op->dev);
edac_mc_free(mci);
return 0;
}
static struct of_device_id mpc85xx_mc_err_of_match[] = {
static const struct of_device_id mpc85xx_mc_err_of_match[] = {
/* deprecate the fsl,85.. forms in the future, 2.6.30? */
{ .compatible = "fsl,8540-memory-controller", },
{ .compatible = "fsl,8541-memory-controller", },
......
......@@ -209,35 +209,18 @@ static DEVICE_ATTR(row, S_IRUGO | S_IWUSR,
static DEVICE_ATTR(col, S_IRUGO | S_IWUSR,
octeon_mc_inject_col_show, octeon_mc_inject_col_store);
static struct attribute *octeon_dev_attrs[] = {
&dev_attr_inject.attr,
&dev_attr_error_type.attr,
&dev_attr_dimm.attr,
&dev_attr_rank.attr,
&dev_attr_bank.attr,
&dev_attr_row.attr,
&dev_attr_col.attr,
NULL
};
static int octeon_set_mc_sysfs_attributes(struct mem_ctl_info *mci)
{
int rc;
rc = device_create_file(&mci->dev, &dev_attr_inject);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_error_type);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_dimm);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_rank);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_bank);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_row);
if (rc < 0)
return rc;
rc = device_create_file(&mci->dev, &dev_attr_col);
if (rc < 0)
return rc;
return 0;
}
ATTRIBUTE_GROUPS(octeon_dev);
static int octeon_lmc_edac_probe(struct platform_device *pdev)
{
......@@ -271,18 +254,12 @@ static int octeon_lmc_edac_probe(struct platform_device *pdev)
mci->ctl_name = "octeon-lmc-err";
mci->edac_check = octeon_lmc_edac_poll;
if (edac_mc_add_mc(mci)) {
if (edac_mc_add_mc_with_groups(mci, octeon_dev_groups)) {
dev_err(&pdev->dev, "edac_mc_add_mc() failed\n");
edac_mc_free(mci);
return -ENXIO;
}
if (octeon_set_mc_sysfs_attributes(mci)) {
dev_err(&pdev->dev, "octeon_set_mc_sysfs_attributes() failed\n");
return -ENXIO;
}
cfg0.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc));
cfg0.s.intr_ded_ena = 0; /* We poll */
cfg0.s.intr_sec_ena = 0;
......@@ -309,18 +286,12 @@ static int octeon_lmc_edac_probe(struct platform_device *pdev)
mci->ctl_name = "co_lmc_err";
mci->edac_check = octeon_lmc_edac_poll_o2;
if (edac_mc_add_mc(mci)) {
if (edac_mc_add_mc_with_groups(mci, octeon_dev_groups)) {
dev_err(&pdev->dev, "edac_mc_add_mc() failed\n");
edac_mc_free(mci);
return -ENXIO;
}
if (octeon_set_mc_sysfs_attributes(mci)) {
dev_err(&pdev->dev, "octeon_set_mc_sysfs_attributes() failed\n");
return -ENXIO;
}
en.u64 = cvmx_read_csr(CVMX_LMCX_MEM_CFG0(mc));
en.s.intr_ded_ena = 0; /* We poll */
en.s.intr_sec_ena = 0;
......
......@@ -193,7 +193,7 @@ static int ppc4xx_edac_remove(struct platform_device *device);
* Device tree node type and compatible tuples this driver can match
* on.
*/
static struct of_device_id ppc4xx_edac_match[] = {
static const struct of_device_id ppc4xx_edac_match[] = {
{
.compatible = "ibm,sdram-4xx-ddr2"
},
......
......@@ -512,7 +512,7 @@ static int synps_edac_mc_remove(struct platform_device *pdev)
return 0;
}
static struct of_device_id synps_edac_match[] = {
static const struct of_device_id synps_edac_match[] = {
{ .compatible = "xlnx,zynq-ddrc-a05", },
{ /* end of table */ }
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment