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

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

EDAC: Rework workqueue handling



Hide the EDAC workqueue pointer in a separate compilation unit and add
accessors for the workqueue manipulations needed.

Remove edac_pci_reset_delay_period() which wasn't used by anything. It
seems it got added without a user with

  91b99041 ("drivers/edac: updated PCI monitoring")

Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
parent e136fa01
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ obj-$(CONFIG_EDAC) := edac_stub.o
obj-$(CONFIG_EDAC_MM_EDAC)		+= edac_core.o

edac_core-y	:= edac_mc.o edac_device.o edac_mc_sysfs.o
edac_core-y	+= edac_module.o edac_device_sysfs.o
edac_core-y	+= edac_module.o edac_device_sysfs.o wq.o

edac_core-$(CONFIG_EDAC_DEBUG)		+= debugfs.o

+11 −17
Original line number Diff line number Diff line
@@ -390,11 +390,9 @@ static void edac_device_workq_function(struct work_struct *work_req)
	 * between integral seconds
	 */
	if (edac_dev->poll_msec == 1000)
		queue_delayed_work(edac_workqueue, &edac_dev->work,
				round_jiffies_relative(edac_dev->delay));
		edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
	else
		queue_delayed_work(edac_workqueue, &edac_dev->work,
				edac_dev->delay);
		edac_queue_work(&edac_dev->work, edac_dev->delay);
}

/*
@@ -422,11 +420,9 @@ static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
	 * to fire together on the 1 second exactly
	 */
	if (edac_dev->poll_msec == 1000)
		queue_delayed_work(edac_workqueue, &edac_dev->work,
				round_jiffies_relative(edac_dev->delay));
		edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
	else
		queue_delayed_work(edac_workqueue, &edac_dev->work,
				edac_dev->delay);
		edac_queue_work(&edac_dev->work, edac_dev->delay);
}

/*
@@ -440,8 +436,7 @@ static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)

	edac_dev->op_state = OP_OFFLINE;

	cancel_delayed_work_sync(&edac_dev->work);
	flush_workqueue(edac_workqueue);
	edac_stop_work(&edac_dev->work);
}

/*
@@ -454,16 +449,15 @@ static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
					unsigned long value)
{
	/* cancel the current workq request, without the mutex lock */
	edac_device_workq_teardown(edac_dev);
	unsigned long jiffs = msecs_to_jiffies(value);

	/* acquire the mutex before doing the workq setup */
	mutex_lock(&device_ctls_mutex);
	if (value == 1000)
		jiffs = round_jiffies_relative(value);

	/* restart the workq request, with new delay value */
	edac_device_workq_setup(edac_dev, value);
	edac_dev->poll_msec = value;
	edac_dev->delay	    = jiffs;

	mutex_unlock(&device_ctls_mutex);
	edac_mod_work(&edac_dev->work, jiffs);
}

/*
+7 −12
Original line number Diff line number Diff line
@@ -548,8 +548,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
	mutex_unlock(&mem_ctls_mutex);

	/* Reschedule */
	queue_delayed_work(edac_workqueue, &mci->work,
			msecs_to_jiffies(edac_mc_get_poll_msec()));
	edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
}

/*
@@ -561,8 +560,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
 *
 *		called with the mem_ctls_mutex held
 */
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
				bool init)
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
{
	edac_dbg(0, "\n");

@@ -570,10 +568,9 @@ static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
	if (mci->op_state != OP_RUNNING_POLL)
		return;

	if (init)
	INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);

	mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
	edac_queue_work(&mci->work, msecs_to_jiffies(msec));
}

/*
@@ -588,8 +585,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
{
	mci->op_state = OP_OFFLINE;

	cancel_delayed_work_sync(&mci->work);
	flush_workqueue(edac_workqueue);
	edac_stop_work(&mci->work);
}

/*
@@ -608,9 +604,8 @@ void edac_mc_reset_delay_period(unsigned long value)
	list_for_each(item, &mc_devices) {
		mci = list_entry(item, struct mem_ctl_info, link);

		edac_mc_workq_setup(mci, value, false);
		edac_mod_work(&mci->work, value);
	}

	mutex_unlock(&mem_ctls_mutex);
}

@@ -781,7 +776,7 @@ int edac_mc_add_mc_with_groups(struct mem_ctl_info *mci,
		/* This instance is NOW RUNNING */
		mci->op_state = OP_RUNNING_POLL;

		edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
		edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
	} else {
		mci->op_state = OP_RUNNING_INTERRUPT;
	}
+0 −29
Original line number Diff line number Diff line
@@ -43,9 +43,6 @@ module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
#endif

/* scope is to module level only */
struct workqueue_struct *edac_workqueue;

/*
 * edac_op_state_to_string()
 */
@@ -65,32 +62,6 @@ char *edac_op_state_to_string(int opstate)
	return "UNKNOWN";
}

/*
 * edac_workqueue_setup
 *	initialize the edac work queue for polling operations
 */
static int edac_workqueue_setup(void)
{
	edac_workqueue = create_singlethread_workqueue("edac-poller");
	if (edac_workqueue == NULL)
		return -ENODEV;
	else
		return 0;
}

/*
 * edac_workqueue_teardown
 *	teardown the edac workqueue
 */
static void edac_workqueue_teardown(void)
{
	if (edac_workqueue) {
		flush_workqueue(edac_workqueue);
		destroy_workqueue(edac_workqueue);
		edac_workqueue = NULL;
	}
}

/*
 * sysfs object: /sys/devices/system/edac
 *	need to export to other files
+6 −1
Original line number Diff line number Diff line
@@ -47,7 +47,12 @@ extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);

/* edac core workqueue: single CPU mode */
extern struct workqueue_struct *edac_workqueue;
int edac_workqueue_setup(void);
void edac_workqueue_teardown(void);
bool edac_queue_work(struct delayed_work *work, unsigned long delay);
bool edac_stop_work(struct delayed_work *work);
bool edac_mod_work(struct delayed_work *work, unsigned long delay);

extern void edac_device_reset_delay_period(struct edac_device_ctl_info
					   *edac_dev, unsigned long value);
extern void edac_mc_reset_delay_period(unsigned long value);
Loading