aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2016-02-02 04:59:53 -0500
committerBorislav Petkov <bp@suse.de>2016-02-02 05:04:29 -0500
commit096676061987c613bdacddbae838cb63a815db94 (patch)
tree9a73f90b19376faf2e9c5a55a038000d6ac25594
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>
-rw-r--r--drivers/edac/edac_mc.c15
-rw-r--r--drivers/edac/edac_pci.c8
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 */
584static void edac_mc_workq_teardown(struct mem_ctl_info *mci) 584static 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",