Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 939747bd authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

i7core_edac: Be sure that the edac pci handler will be properly released



With multi-sockets, more than one edac pci handler is enabled. Be sure to
un-register all instances.

Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent f6f94e2a
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -810,6 +810,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 int edac_mc_add_mc(struct mem_ctl_info *mci);
extern void edac_mc_free(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 *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 struct mem_ctl_info *edac_mc_del_mc(struct device *dev);
extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
extern int edac_mc_find_csrow_by_page(struct mem_ctl_info *mci,
				      unsigned long page);
				      unsigned long page);
+4 −2
Original line number Original line Diff line number Diff line
@@ -239,13 +239,14 @@ void edac_mc_free(struct mem_ctl_info *mci)
EXPORT_SYMBOL_GPL(edac_mc_free);
EXPORT_SYMBOL_GPL(edac_mc_free);




/*
/**
 * find_mci_by_dev
 * find_mci_by_dev
 *
 *
 *	scan list of controllers looking for the one that manages
 *	scan list of controllers looking for the one that manages
 *	the 'dev' device
 *	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 mem_ctl_info *mci;
	struct list_head *item;
	struct list_head *item;
@@ -261,6 +262,7 @@ static struct mem_ctl_info *find_mci_by_dev(struct device *dev)


	return NULL;
	return NULL;
}
}
EXPORT_SYMBOL_GPL(find_mci_by_dev);


/*
/*
 * handler for EDAC to check if NMI type handler has asserted interrupt
 * handler for EDAC to check if NMI type handler has asserted interrupt
+23 −15
Original line number Original line Diff line number Diff line
@@ -261,6 +261,9 @@ struct i7core_pvt {


	/* Count indicator to show errors not got */
	/* Count indicator to show errors not got */
	unsigned		mce_overrun;
	unsigned		mce_overrun;

	/* Struct to control EDAC polling */
	struct edac_pci_ctl_info *i7core_pci;
};
};


/* Static vars */
/* Static vars */
@@ -378,8 +381,6 @@ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = {
	{0,}			/* 0 terminated list. */
	{0,}			/* 0 terminated list. */
};
};


static struct edac_pci_ctl_info *i7core_pci;

/****************************************************************************
/****************************************************************************
			Anciliary status routines
			Anciliary status routines
 ****************************************************************************/
 ****************************************************************************/
@@ -1906,9 +1907,9 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev,
	}
	}


	/* allocating generic PCI control info */
	/* allocating generic PCI control info */
	i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
	pvt->i7core_pci = edac_pci_create_generic_ctl(&i7core_dev->pdev[0]->dev,
						 EDAC_MOD_STR);
						 EDAC_MOD_STR);
	if (unlikely(!i7core_pci)) {
	if (unlikely(!pvt->i7core_pci)) {
		printk(KERN_WARNING
		printk(KERN_WARNING
			"%s(): Unable to create PCI control\n",
			"%s(): Unable to create PCI control\n",
			__func__);
			__func__);
@@ -2008,12 +2009,10 @@ static void __devexit i7core_remove(struct pci_dev *pdev)
{
{
	struct mem_ctl_info *mci;
	struct mem_ctl_info *mci;
	struct i7core_dev *i7core_dev, *tmp;
	struct i7core_dev *i7core_dev, *tmp;
	struct i7core_pvt *pvt;


	debugf0(__FILE__ ": %s()\n", __func__);
	debugf0(__FILE__ ": %s()\n", __func__);


	if (i7core_pci)
		edac_pci_release_generic_ctl(i7core_pci);

	/*
	/*
	 * we have a trouble here: pdev value for removal will be wrong, since
	 * we have a trouble here: pdev value for removal will be wrong, since
	 * it will point to the X58 register used to detect that the machine
	 * it will point to the X58 register used to detect that the machine
@@ -2024,19 +2023,28 @@ static void __devexit i7core_remove(struct pci_dev *pdev)


	mutex_lock(&i7core_edac_lock);
	mutex_lock(&i7core_edac_lock);
	list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
	list_for_each_entry_safe(i7core_dev, tmp, &i7core_edac_list, list) {
		mci = edac_mc_del_mc(&i7core_dev->pdev[0]->dev);
		mci = find_mci_by_dev(&i7core_dev->pdev[0]->dev);
		if (mci) {
		if (unlikely(!mci || !mci->pvt_info)) {
			struct i7core_pvt *pvt = mci->pvt_info;
			i7core_printk(KERN_ERR,

				      "Couldn't find mci hanler\n");
		} else {
			pvt = mci->pvt_info;
			i7core_dev = pvt->i7core_dev;
			i7core_dev = pvt->i7core_dev;

			if (likely(pvt->i7core_pci))
				edac_pci_release_generic_ctl(pvt->i7core_pci);
			else
				i7core_printk(KERN_ERR,
					      "Couldn't find mem_ctl_info for socket %d\n",
					      i7core_dev->socket);
			pvt->i7core_pci = NULL;

			edac_mc_del_mc(&i7core_dev->pdev[0]->dev);

			edac_mce_unregister(&pvt->edac_mce);
			edac_mce_unregister(&pvt->edac_mce);
			kfree(mci->ctl_name);
			kfree(mci->ctl_name);
			edac_mc_free(mci);
			edac_mc_free(mci);
			i7core_put_devices(i7core_dev);
			i7core_put_devices(i7core_dev);
		} else {
			i7core_printk(KERN_ERR,
				      "Couldn't find mci for socket %d\n",
				      i7core_dev->socket);
		}
		}
	}
	}
	probed--;
	probed--;