EDAC: Balance workqueue setup and teardown
We use the ->edac_check function pointers to determine whether we need to setup a polling workqueue. However, the destroy path is not balanced and we might try to teardown an unitialized workqueue. Balance init and destroy paths by looking at ->edac_check in both cases. Set op_state to OP_OFFLINE *before* destroying anything. Reported-by: Zhiqiang Hou <Zhiqiang.Hou@freescale.com> Cc: Varun Sethi <Varun.Sethi@freescale.com> Signed-off-by: Borislav Petkov <bp@suse.de>
This commit is contained in:
parent
f5793c9708
commit
0966760619
|
@ -583,8 +583,6 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
|
|||
*/
|
||||
static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
|
||||
{
|
||||
mci->op_state = OP_OFFLINE;
|
||||
|
||||
edac_stop_work(&mci->work);
|
||||
}
|
||||
|
||||
|
@ -772,7 +770,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
|
|||
}
|
||||
|
||||
/* If there IS a check routine, then we are running POLLED */
|
||||
if (mci->edac_check != NULL) {
|
||||
if (mci->edac_check) {
|
||||
/* This instance is NOW RUNNING */
|
||||
mci->op_state = OP_RUNNING_POLL;
|
||||
|
||||
|
@ -823,15 +821,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* mark MCI offline: */
|
||||
mci->op_state = OP_OFFLINE;
|
||||
|
||||
if (!del_mc_from_global_list(mci))
|
||||
edac_mc_owner = NULL;
|
||||
|
||||
mutex_unlock(&mem_ctls_mutex);
|
||||
|
||||
/* flush workq processes */
|
||||
edac_mc_workq_teardown(mci);
|
||||
|
||||
/* marking MCI offline */
|
||||
mci->op_state = OP_OFFLINE;
|
||||
if (mci->edac_check)
|
||||
edac_mc_workq_teardown(mci);
|
||||
|
||||
/* remove from sysfs */
|
||||
edac_remove_sysfs_mci_device(mci);
|
||||
|
|
|
@ -241,8 +241,6 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
|
|||
{
|
||||
edac_dbg(0, "\n");
|
||||
|
||||
pci->op_state = OP_OFFLINE;
|
||||
|
||||
edac_stop_work(&pci->work);
|
||||
}
|
||||
|
||||
|
@ -289,7 +287,7 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx)
|
|||
goto fail1;
|
||||
}
|
||||
|
||||
if (pci->edac_check != NULL) {
|
||||
if (pci->edac_check) {
|
||||
pci->op_state = OP_RUNNING_POLL;
|
||||
|
||||
edac_pci_workq_setup(pci, 1000);
|
||||
|
@ -350,8 +348,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)
|
|||
|
||||
mutex_unlock(&edac_pci_ctls_mutex);
|
||||
|
||||
/* stop the workq timer */
|
||||
edac_pci_workq_teardown(pci);
|
||||
if (pci->edac_check)
|
||||
edac_pci_workq_teardown(pci);
|
||||
|
||||
edac_printk(KERN_INFO, EDAC_PCI,
|
||||
"Removed device %d for %s %s: DEV %s\n",
|
||||
|
|
Loading…
Reference in New Issue