Fix polling timeout setting through sysfs.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.15 (GNU/Linux)
iQIcBAABAgAGBQJS/eolAAoJEBLB8Bhh3lVKuJgP/3Z+bT+NUt6rPia6q9aVtxD8
tnk+QdSiXWM+r1UFSbsmHsJNMEqHUAc37zYW5VBrgzOXbxnoNiPGWLqb8jwaj2nC
QV26aj7nhJI8Zi6VF17liG21qOsYCJJtyrMOKttXO1hxTtj2MCTMWPftNhOJ/atl
IA+LW3b8nUHFZSOdHNZl7blKPzUj8enhh0fm+iQ7UCtryjKIK/nB2Y98jEzLJ8BU
v9LYIUcXC+9L/Yzs2FesOLR9s7P9FaxBKrW2Nqu5lj9J0yxDaHkuAtyutz68unpF
8CRaUdcI+8lO/nIh99g7cO14W/VrJxhbceldvSls72a0yP66yq1jeTsU41LwcWOg
416hCJET6py1Jxvs038Qfu0g/hYFnnSkcBaChv3TM9WdilxTgb8kw8ek+0ojTmkJ
1XGNZ0za5ncRDePCpY/PbBmBWwF6+SvpyQsJdr9OCn0kIJIydiltw20MfzLwdTjg
ozZ0zEJ2E0AgwZCG6wkvtkQM8bDCSqW/W20/3YB/v4NLEftx/ftAO8dwQFkGwBqd
SI0FmXZyEBUraUUIWsgLJRHAZ/lEKLkTAWwCBJS0rbm0gaezqsiK6+f+4kSLeHXo
aPxYExz70fdcWXkksFTRr5AYgasNO1YzzXU+XsntsAgDpaFGUwaYESyrxmV3waMb
FGqhC/OGwHTlqH1xwxXj
=0lW4
-----END PGP SIGNATURE-----
Merge tag 'edac_for_3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
Pull EDAC fixes from Borislav Petkov:
"Fix polling timeout setting through sysfs.
You're surely wondering why the patches are not based on an rc. Well,
Andrew sent you 79040cad3f
("drivers/edac/edac_mc_sysfs.c: poll
timeout cannot be zero sent you") already (it got in in -rc2) but it
is not enough as a fix because for one, setting too low polling
intervals (< 1sec) don't make any sense and cause unnecessary polling
load on the system.
Then, even if we set some interval, we explode with
[ 4143.094342] WARNING: CPU: 1 PID: 0 at kernel/workqueue.c:1393 __queue_work+0x1d7/0x340()
because the workqueue setup path is used also for the timeout period
resetting and we're doing INIT_DELAYED_WORK() on an already active
workqueue. Which is total bollocks. So this is taken care of by the
second patch.
I've CCed stable for those two"
* tag 'edac_for_3.14' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
EDAC: Correct workqueue setup path
EDAC: Poll timeout cannot be zero, p2
This commit is contained in:
commit
3bd354abe1
|
@ -559,7 +559,8 @@ 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");
|
||||||
|
|
||||||
|
@ -567,7 +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));
|
mod_delayed_work(edac_workqueue, &mci->work, msecs_to_jiffies(msec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -601,7 +604,7 @@ static void edac_mc_workq_teardown(struct mem_ctl_info *mci)
|
||||||
* user space has updated our poll period value, need to
|
* user space has updated our poll period value, need to
|
||||||
* reset our workq delays
|
* reset our workq delays
|
||||||
*/
|
*/
|
||||||
void edac_mc_reset_delay_period(int value)
|
void edac_mc_reset_delay_period(unsigned long value)
|
||||||
{
|
{
|
||||||
struct mem_ctl_info *mci;
|
struct mem_ctl_info *mci;
|
||||||
struct list_head *item;
|
struct list_head *item;
|
||||||
|
@ -611,7 +614,7 @@ void edac_mc_reset_delay_period(int 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, (unsigned long) value);
|
edac_mc_workq_setup(mci, value, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&mem_ctls_mutex);
|
mutex_unlock(&mem_ctls_mutex);
|
||||||
|
@ -782,7 +785,7 @@ int edac_mc_add_mc(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());
|
edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
|
||||||
} else {
|
} else {
|
||||||
mci->op_state = OP_RUNNING_INTERRUPT;
|
mci->op_state = OP_RUNNING_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,18 +52,20 @@ int edac_mc_get_poll_msec(void)
|
||||||
|
|
||||||
static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
|
static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
long l;
|
unsigned long l;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!val)
|
if (!val)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ret = kstrtol(val, 0, &l);
|
ret = kstrtoul(val, 0, &l);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
if (!l || ((int)l != l))
|
|
||||||
|
if (l < 1000)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
*((int *)kp->arg) = l;
|
|
||||||
|
*((unsigned long *)kp->arg) = l;
|
||||||
|
|
||||||
/* notify edac_mc engine to reset the poll period */
|
/* notify edac_mc engine to reset the poll period */
|
||||||
edac_mc_reset_delay_period(l);
|
edac_mc_reset_delay_period(l);
|
||||||
|
|
|
@ -52,7 +52,7 @@ extern void edac_device_workq_setup(struct edac_device_ctl_info *edac_dev,
|
||||||
extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev);
|
extern void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev);
|
||||||
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(int value);
|
extern void edac_mc_reset_delay_period(unsigned long value);
|
||||||
|
|
||||||
extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
|
extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue