diff options
author | Borislav Petkov <bp@suse.de> | 2016-02-02 04:59:53 -0500 |
---|---|---|
committer | Borislav Petkov <bp@suse.de> | 2016-02-02 05:04:29 -0500 |
commit | 096676061987c613bdacddbae838cb63a815db94 (patch) | |
tree | 9a73f90b19376faf2e9c5a55a038000d6ac25594 | |
parent | f5793c970888e48542de4ae152d16308873f29e4 (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>
-rw-r--r-- | drivers/edac/edac_mc.c | 15 | ||||
-rw-r--r-- | drivers/edac/edac_pci.c | 8 |
2 files changed, 10 insertions, 13 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) | |||
583 | */ | 583 | */ |
584 | static void edac_mc_workq_teardown(struct mem_ctl_info *mci) | 584 | static void edac_mc_workq_teardown(struct mem_ctl_info *mci) |
585 | { | 585 | { |
586 | mci->op_state = OP_OFFLINE; | ||
587 | |||
588 | edac_stop_work(&mci->work); | 586 | edac_stop_work(&mci->work); |
589 | } | 587 | } |
590 | 588 | ||
@@ -772,7 +770,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci, | |||
772 | } | 770 | } |
773 | 771 | ||
774 | /* If there IS a check routine, then we are running POLLED */ | 772 | /* If there IS a check routine, then we are running POLLED */ |
775 | if (mci->edac_check != NULL) { | 773 | if (mci->edac_check) { |
776 | /* This instance is NOW RUNNING */ | 774 | /* This instance is NOW RUNNING */ |
777 | mci->op_state = OP_RUNNING_POLL; | 775 | mci->op_state = OP_RUNNING_POLL; |
778 | 776 | ||
@@ -823,15 +821,16 @@ struct mem_ctl_info *edac_mc_del_mc(struct device *dev) | |||
823 | return NULL; | 821 | return NULL; |
824 | } | 822 | } |
825 | 823 | ||
824 | /* mark MCI offline: */ | ||
825 | mci->op_state = OP_OFFLINE; | ||
826 | |||
826 | if (!del_mc_from_global_list(mci)) | 827 | if (!del_mc_from_global_list(mci)) |
827 | edac_mc_owner = NULL; | 828 | edac_mc_owner = NULL; |
828 | mutex_unlock(&mem_ctls_mutex); | ||
829 | 829 | ||
830 | /* flush workq processes */ | 830 | mutex_unlock(&mem_ctls_mutex); |
831 | edac_mc_workq_teardown(mci); | ||
832 | 831 | ||
833 | /* marking MCI offline */ | 832 | if (mci->edac_check) |
834 | mci->op_state = OP_OFFLINE; | 833 | edac_mc_workq_teardown(mci); |
835 | 834 | ||
836 | /* remove from sysfs */ | 835 | /* remove from sysfs */ |
837 | edac_remove_sysfs_mci_device(mci); | 836 | edac_remove_sysfs_mci_device(mci); |
diff --git a/drivers/edac/edac_pci.c b/drivers/edac/edac_pci.c index 99685388d3fb..f0e8c3d01ed5 100644 --- a/drivers/edac/edac_pci.c +++ b/drivers/edac/edac_pci.c | |||
@@ -241,8 +241,6 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci) | |||
241 | { | 241 | { |
242 | edac_dbg(0, "\n"); | 242 | edac_dbg(0, "\n"); |
243 | 243 | ||
244 | pci->op_state = OP_OFFLINE; | ||
245 | |||
246 | edac_stop_work(&pci->work); | 244 | edac_stop_work(&pci->work); |
247 | } | 245 | } |
248 | 246 | ||
@@ -289,7 +287,7 @@ int edac_pci_add_device(struct edac_pci_ctl_info *pci, int edac_idx) | |||
289 | goto fail1; | 287 | goto fail1; |
290 | } | 288 | } |
291 | 289 | ||
292 | if (pci->edac_check != NULL) { | 290 | if (pci->edac_check) { |
293 | pci->op_state = OP_RUNNING_POLL; | 291 | pci->op_state = OP_RUNNING_POLL; |
294 | 292 | ||
295 | edac_pci_workq_setup(pci, 1000); | 293 | edac_pci_workq_setup(pci, 1000); |
@@ -350,8 +348,8 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev) | |||
350 | 348 | ||
351 | mutex_unlock(&edac_pci_ctls_mutex); | 349 | mutex_unlock(&edac_pci_ctls_mutex); |
352 | 350 | ||
353 | /* stop the workq timer */ | 351 | if (pci->edac_check) |
354 | edac_pci_workq_teardown(pci); | 352 | edac_pci_workq_teardown(pci); |
355 | 353 | ||
356 | edac_printk(KERN_INFO, EDAC_PCI, | 354 | edac_printk(KERN_INFO, EDAC_PCI, |
357 | "Removed device %d for %s %s: DEV %s\n", | 355 | "Removed device %d for %s %s: DEV %s\n", |