Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at e88ba436e5615f5bb94deecbbb924227b15bbebb 173 lines 4.8 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * wakeup.c - support wakeup devices 4 * Copyright (C) 2004 Li Shaohua <shaohua.li@intel.com> 5 */ 6 7#include <linux/init.h> 8#include <linux/acpi.h> 9#include <linux/kernel.h> 10#include <linux/types.h> 11 12#include "internal.h" 13#include "sleep.h" 14 15struct acpi_wakeup_handler { 16 struct list_head list_node; 17 bool (*wakeup)(void *context); 18 void *context; 19}; 20 21static LIST_HEAD(acpi_wakeup_handler_head); 22static DEFINE_MUTEX(acpi_wakeup_handler_mutex); 23 24/* 25 * We didn't lock acpi_device_lock in the file, because it invokes oops in 26 * suspend/resume and isn't really required as this is called in S-state. At 27 * that time, there is no device hotplug 28 **/ 29#define _COMPONENT ACPI_SYSTEM_COMPONENT 30ACPI_MODULE_NAME("wakeup_devices") 31 32/** 33 * acpi_enable_wakeup_devices - Enable wake-up device GPEs. 34 * @sleep_state: ACPI system sleep state. 35 * 36 * Enable wakeup device power of devices with the state.enable flag set and set 37 * the wakeup enable mask bits in the GPE registers that correspond to wakeup 38 * devices. 39 */ 40void acpi_enable_wakeup_devices(u8 sleep_state) 41{ 42 struct acpi_device *dev, *tmp; 43 44 list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, 45 wakeup_list) { 46 if (!dev->wakeup.flags.valid 47 || sleep_state > (u32) dev->wakeup.sleep_state 48 || !(device_may_wakeup(&dev->dev) 49 || dev->wakeup.prepare_count)) 50 continue; 51 52 if (device_may_wakeup(&dev->dev)) 53 acpi_enable_wakeup_device_power(dev, sleep_state); 54 55 /* The wake-up power should have been enabled already. */ 56 acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, 57 ACPI_GPE_ENABLE); 58 } 59} 60 61/** 62 * acpi_disable_wakeup_devices - Disable devices' wakeup capability. 63 * @sleep_state: ACPI system sleep state. 64 */ 65void acpi_disable_wakeup_devices(u8 sleep_state) 66{ 67 struct acpi_device *dev, *tmp; 68 69 list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, 70 wakeup_list) { 71 if (!dev->wakeup.flags.valid 72 || sleep_state > (u32) dev->wakeup.sleep_state 73 || !(device_may_wakeup(&dev->dev) 74 || dev->wakeup.prepare_count)) 75 continue; 76 77 acpi_set_gpe_wake_mask(dev->wakeup.gpe_device, dev->wakeup.gpe_number, 78 ACPI_GPE_DISABLE); 79 80 if (device_may_wakeup(&dev->dev)) 81 acpi_disable_wakeup_device_power(dev); 82 } 83} 84 85int __init acpi_wakeup_device_init(void) 86{ 87 struct acpi_device *dev, *tmp; 88 89 mutex_lock(&acpi_device_lock); 90 list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list, 91 wakeup_list) { 92 if (device_can_wakeup(&dev->dev)) { 93 /* Button GPEs are supposed to be always enabled. */ 94 acpi_enable_gpe(dev->wakeup.gpe_device, 95 dev->wakeup.gpe_number); 96 device_set_wakeup_enable(&dev->dev, true); 97 } 98 } 99 mutex_unlock(&acpi_device_lock); 100 return 0; 101} 102 103/** 104 * acpi_register_wakeup_handler - Register wakeup handler 105 * @wake_irq: The IRQ through which the device may receive wakeups 106 * @wakeup: Wakeup-handler to call when the SCI has triggered a wakeup 107 * @context: Context to pass to the handler when calling it 108 * 109 * Drivers which may share an IRQ with the SCI can use this to register 110 * a handler which returns true when the device they are managing wants 111 * to trigger a wakeup. 112 */ 113int acpi_register_wakeup_handler(int wake_irq, bool (*wakeup)(void *context), 114 void *context) 115{ 116 struct acpi_wakeup_handler *handler; 117 118 /* 119 * If the device is not sharing its IRQ with the SCI, there is no 120 * need to register the handler. 121 */ 122 if (!acpi_sci_irq_valid() || wake_irq != acpi_sci_irq) 123 return 0; 124 125 handler = kmalloc(sizeof(*handler), GFP_KERNEL); 126 if (!handler) 127 return -ENOMEM; 128 129 handler->wakeup = wakeup; 130 handler->context = context; 131 132 mutex_lock(&acpi_wakeup_handler_mutex); 133 list_add(&handler->list_node, &acpi_wakeup_handler_head); 134 mutex_unlock(&acpi_wakeup_handler_mutex); 135 136 return 0; 137} 138EXPORT_SYMBOL_GPL(acpi_register_wakeup_handler); 139 140/** 141 * acpi_unregister_wakeup_handler - Unregister wakeup handler 142 * @wakeup: Wakeup-handler passed to acpi_register_wakeup_handler() 143 * @context: Context passed to acpi_register_wakeup_handler() 144 */ 145void acpi_unregister_wakeup_handler(bool (*wakeup)(void *context), 146 void *context) 147{ 148 struct acpi_wakeup_handler *handler; 149 150 mutex_lock(&acpi_wakeup_handler_mutex); 151 list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { 152 if (handler->wakeup == wakeup && handler->context == context) { 153 list_del(&handler->list_node); 154 kfree(handler); 155 break; 156 } 157 } 158 mutex_unlock(&acpi_wakeup_handler_mutex); 159} 160EXPORT_SYMBOL_GPL(acpi_unregister_wakeup_handler); 161 162bool acpi_check_wakeup_handlers(void) 163{ 164 struct acpi_wakeup_handler *handler; 165 166 /* No need to lock, nothing else is running when we're called. */ 167 list_for_each_entry(handler, &acpi_wakeup_handler_head, list_node) { 168 if (handler->wakeup(handler->context)) 169 return true; 170 } 171 172 return false; 173}