Skip to content

Commit c4cf3b4

Browse files
committed
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 91b9904 ("drivers/edac: updated PCI monitoring") Signed-off-by: Borislav Petkov <[email protected]>
1 parent e136fa0 commit c4cf3b4

File tree

7 files changed

+71
-88
lines changed

7 files changed

+71
-88
lines changed

drivers/edac/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ obj-$(CONFIG_EDAC) := edac_stub.o
1010
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
1111

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

1515
edac_core-$(CONFIG_EDAC_DEBUG) += debugfs.o
1616

drivers/edac/edac_device.c

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -390,11 +390,9 @@ static void edac_device_workq_function(struct work_struct *work_req)
390390
* between integral seconds
391391
*/
392392
if (edac_dev->poll_msec == 1000)
393-
queue_delayed_work(edac_workqueue, &edac_dev->work,
394-
round_jiffies_relative(edac_dev->delay));
393+
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
395394
else
396-
queue_delayed_work(edac_workqueue, &edac_dev->work,
397-
edac_dev->delay);
395+
edac_queue_work(&edac_dev->work, edac_dev->delay);
398396
}
399397

400398
/*
@@ -422,11 +420,9 @@ static void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
422420
* to fire together on the 1 second exactly
423421
*/
424422
if (edac_dev->poll_msec == 1000)
425-
queue_delayed_work(edac_workqueue, &edac_dev->work,
426-
round_jiffies_relative(edac_dev->delay));
423+
edac_queue_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
427424
else
428-
queue_delayed_work(edac_workqueue, &edac_dev->work,
429-
edac_dev->delay);
425+
edac_queue_work(&edac_dev->work, edac_dev->delay);
430426
}
431427

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

441437
edac_dev->op_state = OP_OFFLINE;
442438

443-
cancel_delayed_work_sync(&edac_dev->work);
444-
flush_workqueue(edac_workqueue);
439+
edac_stop_work(&edac_dev->work);
445440
}
446441

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

460-
/* acquire the mutex before doing the workq setup */
461-
mutex_lock(&device_ctls_mutex);
454+
if (value == 1000)
455+
jiffs = round_jiffies_relative(value);
462456

463-
/* restart the workq request, with new delay value */
464-
edac_device_workq_setup(edac_dev, value);
457+
edac_dev->poll_msec = value;
458+
edac_dev->delay = jiffs;
465459

466-
mutex_unlock(&device_ctls_mutex);
460+
edac_mod_work(&edac_dev->work, jiffs);
467461
}
468462

469463
/*

drivers/edac/edac_mc.c

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -548,8 +548,7 @@ static void edac_mc_workq_function(struct work_struct *work_req)
548548
mutex_unlock(&mem_ctls_mutex);
549549

550550
/* Reschedule */
551-
queue_delayed_work(edac_workqueue, &mci->work,
552-
msecs_to_jiffies(edac_mc_get_poll_msec()));
551+
edac_queue_work(&mci->work, msecs_to_jiffies(edac_mc_get_poll_msec()));
553552
}
554553

555554
/*
@@ -561,19 +560,17 @@ static void edac_mc_workq_function(struct work_struct *work_req)
561560
*
562561
* called with the mem_ctls_mutex held
563562
*/
564-
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
565-
bool init)
563+
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec)
566564
{
567565
edac_dbg(0, "\n");
568566

569567
/* if this instance is not in the POLL state, then simply return */
570568
if (mci->op_state != OP_RUNNING_POLL)
571569
return;
572570

573-
if (init)
574-
INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
571+
INIT_DELAYED_WORK(&mci->work, edac_mc_workq_function);
575572

576-
mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
573+
edac_queue_work(&mci->work, msecs_to_jiffies(msec));
577574
}
578575

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

591-
cancel_delayed_work_sync(&mci->work);
592-
flush_workqueue(edac_workqueue);
588+
edac_stop_work(&mci->work);
593589
}
594590

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

611-
edac_mc_workq_setup(mci, value, false);
607+
edac_mod_work(&mci->work, value);
612608
}
613-
614609
mutex_unlock(&mem_ctls_mutex);
615610
}
616611

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

784-
edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
779+
edac_mc_workq_setup(mci, edac_mc_get_poll_msec());
785780
} else {
786781
mci->op_state = OP_RUNNING_INTERRUPT;
787782
}

drivers/edac/edac_module.c

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,6 @@ module_param_call(edac_debug_level, edac_set_debug_level, param_get_int,
4343
MODULE_PARM_DESC(edac_debug_level, "EDAC debug level: [0-4], default: 2");
4444
#endif
4545

46-
/* scope is to module level only */
47-
struct workqueue_struct *edac_workqueue;
48-
4946
/*
5047
* edac_op_state_to_string()
5148
*/
@@ -65,32 +62,6 @@ char *edac_op_state_to_string(int opstate)
6562
return "UNKNOWN";
6663
}
6764

68-
/*
69-
* edac_workqueue_setup
70-
* initialize the edac work queue for polling operations
71-
*/
72-
static int edac_workqueue_setup(void)
73-
{
74-
edac_workqueue = create_singlethread_workqueue("edac-poller");
75-
if (edac_workqueue == NULL)
76-
return -ENODEV;
77-
else
78-
return 0;
79-
}
80-
81-
/*
82-
* edac_workqueue_teardown
83-
* teardown the edac workqueue
84-
*/
85-
static void edac_workqueue_teardown(void)
86-
{
87-
if (edac_workqueue) {
88-
flush_workqueue(edac_workqueue);
89-
destroy_workqueue(edac_workqueue);
90-
edac_workqueue = NULL;
91-
}
92-
}
93-
9465
/*
9566
* sysfs object: /sys/devices/system/edac
9667
* need to export to other files

drivers/edac/edac_module.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,12 @@ extern int edac_device_create_sysfs(struct edac_device_ctl_info *edac_dev);
4747
extern void edac_device_remove_sysfs(struct edac_device_ctl_info *edac_dev);
4848

4949
/* edac core workqueue: single CPU mode */
50-
extern struct workqueue_struct *edac_workqueue;
50+
int edac_workqueue_setup(void);
51+
void edac_workqueue_teardown(void);
52+
bool edac_queue_work(struct delayed_work *work, unsigned long delay);
53+
bool edac_stop_work(struct delayed_work *work);
54+
bool edac_mod_work(struct delayed_work *work, unsigned long delay);
55+
5156
extern void edac_device_reset_delay_period(struct edac_device_ctl_info
5257
*edac_dev, unsigned long value);
5358
extern void edac_mc_reset_delay_period(unsigned long value);

drivers/edac/edac_pci.c

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ static void edac_pci_workq_function(struct work_struct *work_req)
209209
delay = msecs_to_jiffies(msec);
210210

211211
/* Reschedule only if we are in POLL mode */
212-
queue_delayed_work(edac_workqueue, &pci->work, delay);
212+
edac_queue_work(&pci->work, delay);
213213
}
214214

215215
mutex_unlock(&edac_pci_ctls_mutex);
@@ -229,8 +229,8 @@ static void edac_pci_workq_setup(struct edac_pci_ctl_info *pci,
229229
edac_dbg(0, "\n");
230230

231231
INIT_DELAYED_WORK(&pci->work, edac_pci_workq_function);
232-
queue_delayed_work(edac_workqueue, &pci->work,
233-
msecs_to_jiffies(edac_pci_get_poll_msec()));
232+
233+
edac_queue_work(&pci->work, msecs_to_jiffies(edac_pci_get_poll_msec()));
234234
}
235235

236236
/*
@@ -243,32 +243,8 @@ static void edac_pci_workq_teardown(struct edac_pci_ctl_info *pci)
243243

244244
pci->op_state = OP_OFFLINE;
245245

246-
cancel_delayed_work_sync(&pci->work);
247-
flush_workqueue(edac_workqueue);
248-
}
249-
250-
/*
251-
* edac_pci_reset_delay_period
252-
*
253-
* called with a new period value for the workq period
254-
* a) stop current workq timer
255-
* b) restart workq timer with new value
256-
*/
257-
void edac_pci_reset_delay_period(struct edac_pci_ctl_info *pci,
258-
unsigned long value)
259-
{
260-
edac_dbg(0, "\n");
261-
262-
edac_pci_workq_teardown(pci);
263-
264-
/* need to lock for the setup */
265-
mutex_lock(&edac_pci_ctls_mutex);
266-
267-
edac_pci_workq_setup(pci, value);
268-
269-
mutex_unlock(&edac_pci_ctls_mutex);
246+
edac_stop_work(&pci->work);
270247
}
271-
EXPORT_SYMBOL_GPL(edac_pci_reset_delay_period);
272248

273249
/*
274250
* edac_pci_alloc_index: Allocate a unique PCI index number

drivers/edac/wq.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#include "edac_module.h"
2+
3+
static struct workqueue_struct *wq;
4+
5+
bool edac_queue_work(struct delayed_work *work, unsigned long delay)
6+
{
7+
return queue_delayed_work(wq, work, delay);
8+
}
9+
EXPORT_SYMBOL_GPL(edac_queue_work);
10+
11+
bool edac_mod_work(struct delayed_work *work, unsigned long delay)
12+
{
13+
return mod_delayed_work(wq, work, delay);
14+
}
15+
EXPORT_SYMBOL_GPL(edac_mod_work);
16+
17+
bool edac_stop_work(struct delayed_work *work)
18+
{
19+
bool ret;
20+
21+
ret = cancel_delayed_work_sync(work);
22+
flush_workqueue(wq);
23+
24+
return ret;
25+
}
26+
EXPORT_SYMBOL_GPL(edac_stop_work);
27+
28+
int edac_workqueue_setup(void)
29+
{
30+
wq = create_singlethread_workqueue("edac-poller");
31+
if (!wq)
32+
return -ENODEV;
33+
else
34+
return 0;
35+
}
36+
37+
void edac_workqueue_teardown(void)
38+
{
39+
flush_workqueue(wq);
40+
destroy_workqueue(wq);
41+
wq = NULL;
42+
}

0 commit comments

Comments
 (0)