Commit da62aa69 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/i7core

* 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/i7core: (34 commits)
  i7core_edac: return -ENODEV when devices were already probed
  i7core_edac: properly terminate pci_dev_table
  i7core_edac: Avoid PCI refcount to reach zero on successive load/reload
  i7core_edac: Fix refcount error at PCI devices
  i7core_edac: it is safe to i7core_unregister_mci() when mci=NULL
  i7core_edac: Fix an oops at i7core probe
  i7core_edac: Remove unused member channels in i7core_pvt
  i7core_edac: Remove unused arg csrow from get_dimm_config
  i7core_edac: Reduce args of i7core_register_mci
  i7core_edac: Introduce i7core_unregister_mci
  i7core_edac: Use saved pointers
  i7core_edac: Check probe counter in i7core_remove
  i7core_edac: Call pci_dev_put() when alloc_i7core_dev()  failed
  i7core_edac: Fix error path of i7core_register_mci
  i7core_edac: Fix order of lines in i7core_register_mci
  i7core_edac: Always do get/put for all devices
  i7core_edac: Introduce i7core_pci_ctl_create/release
  i7core_edac: Introduce free_i7core_dev
  i7core_edac: Introduce alloc_i7core_dev
  i7core_edac: Reduce args of i7core_get_onedevice
  ...
parents f1ebdd60 76a7bd81
......@@ -42,8 +42,10 @@
#if PAGE_SHIFT < 20
#define PAGES_TO_MiB( pages ) ( ( pages ) >> ( 20 - PAGE_SHIFT ) )
#define MiB_TO_PAGES(mb) ((mb) >> (20 - PAGE_SHIFT))
#else /* PAGE_SHIFT > 20 */
#define PAGES_TO_MiB( pages ) ( ( pages ) << ( PAGE_SHIFT - 20 ) )
#define MiB_TO_PAGES(mb) ((mb) >> (PAGE_SHIFT - 20))
#endif
#define edac_printk(level, prefix, fmt, arg...) \
......@@ -328,7 +330,7 @@ struct csrow_info {
struct mcidev_sysfs_group {
const char *name; /* group name */
struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
const struct mcidev_sysfs_attribute *mcidev_attr; /* group attributes */
};
struct mcidev_sysfs_group_kobj {
......@@ -336,7 +338,7 @@ struct mcidev_sysfs_group_kobj {
struct kobject kobj; /* kobj for the group */
struct mcidev_sysfs_group *grp; /* group description table */
const struct mcidev_sysfs_group *grp; /* group description table */
struct mem_ctl_info *mci; /* the parent */
};
......@@ -347,7 +349,7 @@ struct mcidev_sysfs_group_kobj {
struct mcidev_sysfs_attribute {
/* It should use either attr or grp */
struct attribute attr;
struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
const struct mcidev_sysfs_group *grp; /* Points to a group of attributes */
/* Ops for show/store values at the attribute - not used on group */
ssize_t (*show)(struct mem_ctl_info *,char *);
......@@ -440,7 +442,7 @@ struct mem_ctl_info {
* If attributes are desired, then set to array of attributes
* If no attributes are desired, leave NULL
*/
struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
const struct mcidev_sysfs_attribute *mc_driver_sysfs_attributes;
/* work struct for this MC */
struct delayed_work work;
......@@ -810,6 +812,7 @@ extern struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
extern int edac_mc_add_mc(struct mem_ctl_info *mci);
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);
extern struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
unsigned long page);
......
......@@ -207,6 +207,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned sz_pvt, unsigned nr_csrows,
}
mci->op_state = OP_ALLOC;
INIT_LIST_HEAD(&mci->grp_kobj_list);
/*
* Initialize the 'root' kobj for the edac_mc controller
......@@ -234,18 +235,24 @@ EXPORT_SYMBOL_GPL(edac_mc_alloc);
*/
void edac_mc_free(struct mem_ctl_info *mci)
{
debugf1("%s()\n", __func__);
edac_mc_unregister_sysfs_main_kobj(mci);
/* free the mci instance memory here */
kfree(mci);
}
EXPORT_SYMBOL_GPL(edac_mc_free);
/*
/**
* find_mci_by_dev
*
* scan list of controllers looking for the one that manages
* the 'dev' device
* @dev: pointer to a struct device related with the MCI
*/
static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
struct mem_ctl_info *find_mci_by_dev(struct device *dev)
{
struct mem_ctl_info *mci;
struct list_head *item;
......@@ -261,6 +268,7 @@ static struct mem_ctl_info *find_mci_by_dev(struct device *dev)
return NULL;
}
EXPORT_SYMBOL_GPL(find_mci_by_dev);
/*
* handler for EDAC to check if NMI type handler has asserted interrupt
......
......@@ -631,9 +631,6 @@ static void edac_mci_control_release(struct kobject *kobj)
/* decrement the module ref count */
module_put(mci->owner);
/* free the mci instance memory here */
kfree(mci);
}
static struct kobj_type ktype_mci = {
......@@ -713,6 +710,8 @@ int edac_mc_register_sysfs_main_kobj(struct mem_ctl_info *mci)
*/
void edac_mc_unregister_sysfs_main_kobj(struct mem_ctl_info *mci)
{
debugf1("%s()\n", __func__);
/* delete the kobj from the mc_kset */
kobject_put(&mci->edac_mci_kobj);
}
......@@ -760,8 +759,6 @@ static void edac_inst_grp_release(struct kobject *kobj)
grp = container_of(kobj, struct mcidev_sysfs_group_kobj, kobj);
mci = grp->mci;
kobject_put(&mci->edac_mci_kobj);
}
/* Intermediate show/store table */
......@@ -784,7 +781,7 @@ static struct kobj_type ktype_inst_grp = {
* object tree.
*/
static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
struct mcidev_sysfs_attribute *sysfs_attrib,
const struct mcidev_sysfs_attribute *sysfs_attrib,
struct kobject *kobj)
{
int err;
......@@ -792,6 +789,7 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
debugf1("%s()\n", __func__);
while (sysfs_attrib) {
debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
if (sysfs_attrib->grp) {
struct mcidev_sysfs_group_kobj *grp_kobj;
......@@ -799,10 +797,9 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
if (!grp_kobj)
return -ENOMEM;
list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
grp_kobj->grp = sysfs_attrib->grp;
grp_kobj->mci = mci;
list_add_tail(&grp_kobj->list, &mci->grp_kobj_list);
debugf0("%s() grp %s, mci %p\n", __func__,
sysfs_attrib->grp->name, mci);
......@@ -811,26 +808,28 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
&ktype_inst_grp,
&mci->edac_mci_kobj,
sysfs_attrib->grp->name);
if (err)
if (err < 0) {
printk(KERN_ERR "kobject_init_and_add failed: %d\n", err);
return err;
}
err = edac_create_mci_instance_attributes(mci,
grp_kobj->grp->mcidev_attr,
&grp_kobj->kobj);
if (err)
if (err < 0)
return err;
} else if (sysfs_attrib->attr.name) {
debugf0("%s() file %s\n", __func__,
sysfs_attrib->attr.name);
err = sysfs_create_file(kobj, &sysfs_attrib->attr);
if (err < 0) {
printk(KERN_ERR "sysfs_create_file failed: %d\n", err);
return err;
}
} else
break;
if (err) {
return err;
}
sysfs_attrib++;
}
......@@ -843,7 +842,7 @@ static int edac_create_mci_instance_attributes(struct mem_ctl_info *mci,
* directory of this mci instance.
*/
static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
struct mcidev_sysfs_attribute *sysfs_attrib,
const struct mcidev_sysfs_attribute *sysfs_attrib,
struct kobject *kobj, int count)
{
struct mcidev_sysfs_group_kobj *grp_kobj, *tmp;
......@@ -855,13 +854,24 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
* Remove first all the atributes
*/
while (sysfs_attrib) {
debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
if (sysfs_attrib->grp) {
list_for_each_entry(grp_kobj, &mci->grp_kobj_list,
list)
if (grp_kobj->grp == sysfs_attrib->grp)
debugf1("%s() seeking for group %s\n",
__func__, sysfs_attrib->grp->name);
list_for_each_entry(grp_kobj,
&mci->grp_kobj_list, list) {
debugf1("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
if (grp_kobj->grp == sysfs_attrib->grp) {
edac_remove_mci_instance_attributes(mci,
grp_kobj->grp->mcidev_attr,
&grp_kobj->kobj, count + 1);
debugf0("%s() group %s\n", __func__,
sysfs_attrib->grp->name);
kobject_put(&grp_kobj->kobj);
}
}
debugf1("%s() end of seeking for group %s\n",
__func__, sysfs_attrib->grp->name);
} else if (sysfs_attrib->attr.name) {
debugf0("%s() file %s\n", __func__,
sysfs_attrib->attr.name);
......@@ -871,14 +881,13 @@ static void edac_remove_mci_instance_attributes(struct mem_ctl_info *mci,
sysfs_attrib++;
}
/*
* Now that all attributes got removed, it is save to remove all groups
*/
if (!count)
list_for_each_entry_safe(grp_kobj, tmp, &mci->grp_kobj_list,
list) {
debugf0("%s() grp %s\n", __func__, grp_kobj->grp->name);
kobject_put(&grp_kobj->kobj);
/* Remove the group objects */
if (count)
return;
list_for_each_entry_safe(grp_kobj, tmp,
&mci->grp_kobj_list, list) {
list_del(&grp_kobj->list);
kfree(grp_kobj);
}
}
......@@ -971,6 +980,7 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
debugf0("%s()\n", __func__);
/* remove all csrow kobjects */
debugf0("%s() unregister this mci kobj\n", __func__);
for (i = 0; i < mci->nr_csrows; i++) {
if (mci->csrows[i].nr_pages > 0) {
debugf0("%s() unreg csrow-%d\n", __func__, i);
......@@ -978,20 +988,20 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info *mci)
}
}
debugf0("%s() remove_link\n", __func__);
/* remove the symlink */
sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
debugf0("%s() remove_mci_instance\n", __func__);
/* remove this mci instance's attribtes */
if (mci->mc_driver_sysfs_attributes) {
debugf0("%s() unregister mci private attributes\n", __func__);
edac_remove_mci_instance_attributes(mci,
mci->mc_driver_sysfs_attributes,
&mci->edac_mci_kobj, 0);
debugf0("%s() unregister this mci kobj\n", __func__);
}
/* remove the symlink */
debugf0("%s() remove_link\n", __func__);
sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
/* unregister this instance's kobject */
debugf0("%s() remove_mci_instance\n", __func__);
kobject_put(&mci->edac_mci_kobj);
}
......
This diff is collapsed.
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