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

Commit 3bd354ab authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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 79040cad ("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
parents cbc25256 cb6ef42e
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -559,7 +559,8 @@ 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)
static void edac_mc_workq_setup(struct mem_ctl_info *mci, unsigned msec,
				bool init)
{
	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)
		return;

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

	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
 *	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 list_head *item;
@@ -611,7 +614,7 @@ void edac_mc_reset_delay_period(int value)
	list_for_each(item, &mc_devices) {
		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);
@@ -782,7 +785,7 @@ int edac_mc_add_mc(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());
		edac_mc_workq_setup(mci, edac_mc_get_poll_msec(), true);
	} else {
		mci->op_state = OP_RUNNING_INTERRUPT;
	}
+6 −4
Original line number Diff line number Diff line
@@ -52,18 +52,20 @@ int edac_mc_get_poll_msec(void)

static int edac_set_poll_msec(const char *val, struct kernel_param *kp)
{
	long l;
	unsigned long l;
	int ret;

	if (!val)
		return -EINVAL;

	ret = kstrtol(val, 0, &l);
	ret = kstrtoul(val, 0, &l);
	if (ret)
		return ret;
	if (!l || ((int)l != l))

	if (l < 1000)
		return -EINVAL;
	*((int *)kp->arg) = l;

	*((unsigned long *)kp->arg) = l;

	/* notify edac_mc engine to reset the poll period */
	edac_mc_reset_delay_period(l);
+1 −1
Original line number Diff line number Diff line
@@ -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_reset_delay_period(struct edac_device_ctl_info
					   *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);