EDAC: Fix workqueues poll period resetting
authorNicholas Krause <xerofoify@gmail.com>
Thu, 19 May 2016 22:45:58 +0000 (18:45 -0400)
committerBorislav Petkov <bp@suse.de>
Fri, 3 Jun 2016 09:14:27 +0000 (11:14 +0200)
After the workqueue cleanup, we're registering workqueues based on
the presence of an ->edac_check function. When that is the case,
we're setting OP_RUNNING_POLL. But we forgot to check that in
edac_mc_reset_delay_period(), leading to:

  BUG: unable to handle kernel paging request at 0000000000015d10
  IP: [ .. ] queued_spin_lock_slowpath
  PGD 3ffcc8067 PUD 3ffc56067 PMD 0
  Oops: 0002 [#1] SMP
  Modules linked in: ...
  CPU: 1 PID: 2792 Comm: edactest Not tainted 4.6.0-dirty #1
  Hardware name: HP ProLiant MicroServer, BIOS O41     10/01/2013
  Stack:
  Call Trace:
    ? _raw_spin_lock_irqsave
    ? lock_timer_base.isra.34
    ? del_timer
    ? try_to_grab_pending
    ? mod_delayed_work_on
    ? edac_mc_reset_delay_period
    ? edac_set_poll_msec
    ? param_attr_store
    ? module_attr_store
    ? kernfs_fop_write
    ? __vfs_write
    ? __vfs_read
    ? __alloc_fd
    ? vfs_write
    ? SyS_write
    ? entry_SYSCALL_64_fastpath
  Code:
  RIP  [ .. ] queued_spin_lock_slowpath
   RSP <>
  CR2: 0000000000015d10
  ---[ end trace 3f286bc71cca15d1 ]---
  Kernel panic - not syncing: Fatal exception

Fix it.

Signed-off-by: Nicholas Krause <xerofoify@gmail.com>
Cc: <stable@vger.kernel.org> # 4.5
Cc: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Cc: linux-edac <linux-edac@vger.kernel.org>
Link: http://lkml.kernel.org/r/1463697958-13406-1-git-send-email-xerofoify@gmail.com
[ Rewrite commit message. ]
Signed-off-by: Borislav Petkov <bp@suse.de>
drivers/edac/edac_mc.c

index 6aa256b..c3ee3ad 100644 (file)
@@ -565,7 +565,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_mod_work(&mci->work, value);
+               if (mci->op_state == OP_RUNNING_POLL)
+                       edac_mod_work(&mci->work, value);
        }
        mutex_unlock(&mem_ctls_mutex);
 }