summaryrefslogtreecommitdiff
path: root/drivers/edac/edac_mc.c
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2016-02-02 10:59:53 +0100
committerBorislav Petkov <bp@suse.de>2016-02-02 11:04:29 +0100
commit096676061987c613bdacddbae838cb63a815db94 (patch)
tree9a73f90b19376faf2e9c5a55a038000d6ac25594 /drivers/edac/edac_mc.c
parentf5793c970888e48542de4ae152d16308873f29e4 (diff)
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>
Diffstat (limited to 'drivers/edac/edac_mc.c')
-rw-r--r--drivers/edac/edac_mc.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 8adfc167c2e3..50802c154915 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -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);
+ mutex_unlock(&mem_ctls_mutex);
- /* 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);