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

Commit 09667606 authored by Borislav Petkov's avatar Borislav Petkov
Browse files

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: default avatarZhiqiang Hou <Zhiqiang.Hou@freescale.com>
Cc: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent f5793c97
Loading
Loading
Loading
Loading
+7 −8
Original line number Diff line number Diff line
@@ -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,16 +821,17 @@ 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 */
	if (mci->edac_check)
		edac_mc_workq_teardown(mci);

	/* marking MCI offline */
	mci->op_state = OP_OFFLINE;

	/* remove from sysfs */
	edac_remove_sysfs_mci_device(mci);

+3 −5
Original line number Diff line number Diff line
@@ -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,7 +348,7 @@ struct edac_pci_ctl_info *edac_pci_del_device(struct device *dev)

	mutex_unlock(&edac_pci_ctls_mutex);

	/* stop the workq timer */
	if (pci->edac_check)
		edac_pci_workq_teardown(pci);

	edac_printk(KERN_INFO, EDAC_PCI,