mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-12 16:19:53 +00:00
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 91b99041c1d5 ("drivers/edac: updated PCI monitoring") Signed-off-by: Borislav Petkov <bp@suse.de>
This commit is contained in:
parent
e136fa016f
commit
c4cf3b454e
@ -10,7 +10,7 @@ obj-$(CONFIG_EDAC) := edac_stub.o
|
|||||||
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.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_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
|
edac_core-$(CONFIG_EDAC_DEBUG) += debugfs.o
|
||||||
|
|
||||||
|
@ -390,11 +390,9 @@ static void edac_device_workq_function(struct work_struct *work_req)
|
|||||||
* between integral seconds
|
* between integral seconds
|
||||||
*/
|
*/
|
||||||
if (edac_dev->poll_msec == 1000)
|
if (edac_dev->poll_msec == 1000)
|
||||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||||
round_jiffies_relative(edac_dev->delay));
|
|
||||||
else
|
else
|
||||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
||||||
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
|
* to fire together on the 1 second exactly
|
||||||
*/
|
*/
|
||||||
if (edac_dev->poll_msec == 1000)
|
if (edac_dev->poll_msec == 1000)
|
||||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
|
||||||
round_jiffies_relative(edac_dev->delay));
|
|
||||||
else
|
else
|
||||||
queue_delayed_work(edac_workqueue, &edac_dev->work,
|
edac_queue_work(&edac_dev->work, edac_dev->delay);
|
||||||
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;
|
edac_dev->op_state = OP_OFFLINE;
|
||||||
|
|
||||||
cancel_delayed_work_sync(&edac_dev->work);
|
edac_stop_work(&edac_dev->work);
|
||||||
flush_workqueue(edac_workqueue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -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,
|
void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
|
||||||
unsigned long value)
|
unsigned long value)
|
||||||
{
|
{
|
||||||
/* cancel the current workq request, without the mutex lock */
|
unsigned long jiffs = msecs_to_jiffies(value);
|
||||||
edac_device_workq_teardown(edac_dev);
|
|
||||||
|
|
||||||
/* acquire the mutex before doing the workq setup */
|
if (value == 1000)
|
||||||
mutex_lock(&device_ctls_mutex);
|
jiffs = round_jiffies_relative(value);
|
||||||
|
|
||||||
/* restart the workq request, with new delay value */
|
edac_dev->poll_msec = value;
|
||||||
edac_device_workq_setup(edac_dev, value);
|
edac_dev->delay = jiffs;
|
||||||
|
|
||||||
mutex_unlock(&device_ctls_mutex);
|
edac_mod_work(&edac_dev->work, jiffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -548,8 +548,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
|
|||||||
mutex_unlock(&mem_ctls_mutex);
|
mutex_unlock(&mem_ctls_mutex);
|
||||||
|
|
||||||
/* Reschedule */
|
/* Reschedule */
|
||||||
queue_delayed_work(edac_workqueue, &mci->work,
|
edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
|
||||||
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
|
* called with the mem_ctls_mutex held
|
||||||
*/
|
*/
|
||||||
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
|
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
|
||||||
bool init)
|
|
||||||
{
|
{
|
||||||
edac_dbg(0, "\n");
|
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)
|
if (mci->op_state != OP_RUNNING_POLL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (init)
|
INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
|
||||||
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;
|
mci->op_state = OP_OFFLINE;
|
||||||
|
|
||||||
cancel_delayed_work_sync(&mci->work);
|
edac_stop_work(&mci->work);
|
||||||
flush_workqueue(edac_workqueue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -608,9 +604,8 @@ void edac_mc_reset_delay_period(unsigned long value)
|
|||||||
list_for_each(item, &mc_devices) {
|
list_for_each(item, &mc_devices) {
|
||||||
mci = list_entry(item, struct mem_ctl_info, link);
|
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);
|
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 */
|
/* This instance is NOW RUNNING */
|
||||||
mci->op_state = OP_RUNNING_POLL;
|
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 {
|
} else {
|
||||||
mci->op_state = OP_RUNNING_INTERRUPT;
|
mci->op_state = OP_RUNNING_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
@ -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");
|
MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* scope is to module level only */
|
|
||||||
struct workqueue_struct *edac_workqueue;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* edac_op_state_to_string()
|
* edac_op_state_to_string()
|
||||||
*/
|
*/
|
||||||
@ -65,32 +62,6 @@ char *edac_op_state_to_string(int opstate)
|
|||||||
return "UNKNOWN";
|
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
|
* sysfs object: /sys/devices/system/edac
|
||||||
* need to export to other files
|
* need to export to other files
|
||||||
|
@ -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);
|
extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
|
||||||
|
|
||||||
/* edac core workqueue: single CPU mode */
|
/* 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
|
extern void edac_device_reset_delay_period(struct edac_device_ctl_info
|
||||||
*edac_dev, unsigned long value);
|
*edac_dev, unsigned long value);
|
||||||
extern void edac_mc_reset_delay_period(unsigned long value);
|
extern void edac_mc_reset_delay_period(unsigned long value);
|
||||||
|
@ -209,7 +209,7 @@ static void edac_pci_workq_function(struct work_struct *work_req)
|
|||||||
delay = msecs_to_jiffies(msec);
|
delay = msecs_to_jiffies(msec);
|
||||||
|
|
||||||
/* Reschedule only if we are in POLL mode */
|
/* Reschedule only if we are in POLL mode */
|
||||||
queue_delayed_work(edac_workqueue, &pci->work, delay);
|
edac_queue_work(&pci->work, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&edac_pci_ctls_mutex);
|
mutex_unlock(&edac_pci_ctls_mutex);
|
||||||
@ -229,8 +229,8 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
|
|||||||
edac_dbg(0, "\n");
|
edac_dbg(0, "\n");
|
||||||
|
|
||||||
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
|
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
|
||||||
queue_delayed_work(edac_workqueue, &pci->work,
|
|
||||||
msecs_to_jiffies(edac_pci_get_poll_msec()));
|
edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -243,33 +243,9 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
|
|||||||
|
|
||||||
pci->op_state = OP_OFFLINE;
|
pci->op_state = OP_OFFLINE;
|
||||||
|
|
||||||
cancel_delayed_work_sync(&pci->work);
|
edac_stop_work(&pci->work);
|
||||||
flush_workqueue(edac_workqueue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* edac_pci_reset_delay_period
|
|
||||||
*
|
|
||||||
* called with a new period value for the workq period
|
|
||||||
* a) stop current workq timer
|
|
||||||
* b) restart workq timer with new value
|
|
||||||
*/
|
|
||||||
void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
|
|
||||||
unsigned long value)
|
|
||||||
{
|
|
||||||
edac_dbg(0, "\n");
|
|
||||||
|
|
||||||
edac_pci_workq_teardown(pci);
|
|
||||||
|
|
||||||
/* need to lock for the setup */
|
|
||||||
mutex_lock(&edac_pci_ctls_mutex);
|
|
||||||
|
|
||||||
edac_pci_workq_setup(pci, value);
|
|
||||||
|
|
||||||
mutex_unlock(&edac_pci_ctls_mutex);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* edac_pci_alloc_index: Allocate a unique PCI index number
|
* edac_pci_alloc_index: Allocate a unique PCI index number
|
||||||
*
|
*
|
||||||
|
42
drivers/edac/wq.c
Normal file
42
drivers/edac/wq.c
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "edac_module.h"
|
||||||
|
|
||||||
|
static struct workqueue_struct *wq;
|
||||||
|
|
||||||
|
bool edac_queue_work(struct delayed_work *work, unsigned long delay)
|
||||||
|
{
|
||||||
|
return queue_delayed_work(wq, work, delay);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(edac_queue_work);
|
||||||
|
|
||||||
|
bool edac_mod_work(struct delayed_work *work, unsigned long delay)
|
||||||
|
{
|
||||||
|
return mod_delayed_work(wq, work, delay);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(edac_mod_work);
|
||||||
|
|
||||||
|
bool edac_stop_work(struct delayed_work *work)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
ret = cancel_delayed_work_sync(work);
|
||||||
|
flush_workqueue(wq);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(edac_stop_work);
|
||||||
|
|
||||||
|
int edac_workqueue_setup(void)
|
||||||
|
{
|
||||||
|
wq = create_singlethread_workqueue("edac-poller");
|
||||||
|
if (!wq)
|
||||||
|
return -ENODEV;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void edac_workqueue_teardown(void)
|
||||||
|
{
|
||||||
|
flush_workqueue(wq);
|
||||||
|
destroy_workqueue(wq);
|
||||||
|
wq = NULL;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user