kernel_optimize_test/drivers/base
Grygorii Strashko 0bf0ee8ef9 PM / wakeirq: Fix spurious wake-up events for dedicated wakeirqs
Dedicated wakeirq is a one time event to wake-up the system from
low-power state and then call pm_runtime_resume() on the device wired
with the dedicated wakeirq.

Sometimes dedicated wakeirqs can get deferred if they trigger after we
call disable_irq_nosync() in dev_pm_disable_wake_irq(). This can happen
if pm_runtime_get() is called around the same time a wakeirq fires.

If an interrupt fires after disable_irq_nosync(), by default it will get
tagged with IRQS_PENDING and will run later on when the interrupt is
enabled again.

Deferred wakeirqs usually just produce pointless wake-up events. But they
can also cause suspend to fail if the deferred wakeirq fires during
dpm_suspend_noirq() for example. So we really don't want to see the
deferred wakeirqs triggering after the device has resumed.

Let's fix the issue by setting IRQ_DISABLE_UNLAZY flag for the dedicated
wakeirqs. The other option would be to implement irq_disable() in the
dedicated wakeirq controller, but that's not a generic solution.

For reference below is what happens with a IRQ_TYPE_EDGE_BOTH IRQ
type wakeirq:

- resume by dedicated IRQ (EDGE_FALLING)
 - suspend_enter()
  ....
 - arch_suspend_enable_irqs()
   |- dedicated IRQ armed and fired
   |- irq_pm_check_wakeup()
      |- disarm, disable IRQ and mark as IRQS_PENDING
  ....
 - dpm_resume_noirq()
   |- resume_device_irqs()
      |- __enable_irq()
         |- check_irq_resend()
            |- handle_threaded_wake_irq()
 	       |- dedicated IRQ processed
   |- device_wakeup_disarm_wake_irqs()
      |- disable_irq_wake()
  ....
 !-> dedicated IRQ (EDGE_RISING)
     -| handle_edge_irq()
        |- IRQ disabled: mask_ack_irq and mark as IRQS_PENDING
  ....
- subsequent suspend
  ....
  |- dpm_suspend_noirq()
     |- device_wakeup_arm_wake_irqs()
        |- __enable_irq()
           |- check_irq_resend()
(a)           |- handle_threaded_wake_irq()
                 |- pm_wakeup_event() --> abort suspend
  ....
     |- suspend_device_irqs()
        |- suspend_device_irq()
           |-  dedicated IRQ armed
  ....
(b)  |- resend_irqs
        |- irq_pm_check_wakeup()
           |- IRQ armed -> abort suspend

because of pending IRQ System suspend can be aborted at points
(a)-not armed or (b)-armed.

Fixes: 4990d4fe32 (PM / Wakeirq: Add automated device wake IRQ handling)
Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
[ tony@atomide.com: added a comment, updated the description ]
Tested-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-02-13 22:29:30 +01:00
..
power PM / wakeirq: Fix spurious wake-up events for dedicated wakeirqs 2017-02-13 22:29:30 +01:00
regmap regmap: cache: Remove unused 'blksize' variable 2016-11-25 13:01:36 +00:00
test driver core: test_async: fix up typo found by 0-day 2016-11-29 22:06:42 +01:00
attribute_container.c attribute_container: Fix typo 2016-08-31 15:13:56 +02:00
base.h Revert "driver core: Add deferred_probe attribute to devices in sysfs" 2017-01-14 14:09:03 +01:00
bus.c driver core: bus: use to_subsys_private and to_device_private_bus 2016-02-09 17:25:27 -08:00
cacheinfo.c Merge branch 'x86-cache-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip 2016-12-22 09:25:45 -08:00
class.c driver core: class: add class_groups support 2016-11-29 21:12:12 +01:00
component.c Merge 4.5-rc4 into driver-core-next 2016-02-14 14:29:55 -08:00
container.c
core.c Revert "driver core: Add deferred_probe attribute to devices in sysfs" 2017-01-14 14:09:03 +01:00
cpu.c cpu: clean up register_cpu func 2016-08-31 15:19:55 +02:00
dd.c Revert "driver core: Add deferred_probe attribute to devices in sysfs" 2017-01-14 14:09:03 +01:00
devcoredump.c driver core: devcoredump: convert to use class_groups 2016-11-29 21:12:12 +01:00
devres.c devres: add devm_alloc_percpu() 2016-11-15 22:34:25 -05:00
devtmpfs.c wrappers for ->i_mutex access 2016-01-22 18:04:28 -05:00
dma-coherent.c drivers: dma-coherent: Move spinlock in dma_alloc_from_coherent() 2016-09-28 17:53:16 +02:00
dma-contiguous.c
dma-mapping.c drivers: base: dma-mapping: Fix typo in dmam_alloc_non_coherent comments 2016-11-30 13:04:53 +01:00
driver.c
firmware_class.c firmware: fix NULL pointer dereference in __fw_load_abort() 2017-01-27 09:19:48 +01:00
firmware.c
hypervisor.c
init.c
isa.c isa: Call isa_bus_init before dependent ISA bus drivers register 2016-06-17 20:47:11 -07:00
Kconfig Driver core patches for 4.10-rc1 2016-12-13 11:42:18 -08:00
Makefile driver-core: add test module for asynchronous probing 2016-11-10 17:28:16 +01:00
map.c
memory.c base/memory, hotplug: fix a kernel oops in show_valid_zones() 2017-02-03 14:13:19 -08:00
module.c base: make module_create_drivers_dir race-free 2016-06-15 19:21:31 -07:00
node.c treewide: replace obsolete _refok by __ref 2016-08-02 17:31:41 -04:00
pinctrl.c driver: base: pinctrl: return error from pinctrl_bind_pins() 2016-09-13 23:02:59 +02:00
platform-msi.c genirq/msi: Add cpumask allocation to alloc_msi_entry 2016-09-14 22:11:08 +02:00
platform.c driver-core: platform: Catch errors from calls to irq_get_irq_data 2016-09-27 12:30:37 +02:00
property.c device property: Add function to search for named child of device 2016-06-26 12:39:03 +01:00
soc.c base: soc: Check for NULL SoC device attributes 2016-11-10 10:10:33 +01:00
syscore.c
topology.c drivers base/topology: Convert to hotplug state machine 2016-11-09 23:45:29 +01:00
transport_class.c