aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evxfevnt.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-02-17 17:41:07 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-02-22 19:20:45 -0500
commit9630bdd9b15d2f489c646d8bc04b60e53eb5ec78 (patch)
treeed99f729cb9142492e0cdf2f7d19f2f33069a3f4 /drivers/acpi/acpica/evxfevnt.c
parentc39fae1416d59fd565606793f090cebe3720d50d (diff)
ACPI: Use GPE reference counting to support shared GPEs
ACPI GPEs may map to multiple devices. The current GPE interface only provides a mechanism for enabling and disabling GPEs, making it difficult to change the state of GPEs at runtime without extensive cooperation between devices. Add an API to allow devices to indicate whether or not they want their device's GPE to be enabled for both runtime and wakeup events. Remove the old GPE type handling entirely, which gets rid of various quirks, like the implicit disabling with GPE type setting. This requires a small amount of rework in order to ensure that non-wake GPEs are enabled by default to preserve existing behaviour. Based on patches from Matthew Garrett <mjg@redhat.com>. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/acpi/acpica/evxfevnt.c')
-rw-r--r--drivers/acpi/acpica/evxfevnt.c90
1 files changed, 65 insertions, 25 deletions
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c
index eed7a38d25f2..1aea1a734159 100644
--- a/drivers/acpi/acpica/evxfevnt.c
+++ b/drivers/acpi/acpica/evxfevnt.c
@@ -201,23 +201,27 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event)
201 201
202/******************************************************************************* 202/*******************************************************************************
203 * 203 *
204 * FUNCTION: acpi_set_gpe_type 204 * FUNCTION: acpi_set_gpe
205 * 205 *
206 * PARAMETERS: gpe_device - Parent GPE Device 206 * PARAMETERS: gpe_device - Parent GPE Device
207 * gpe_number - GPE level within the GPE block 207 * gpe_number - GPE level within the GPE block
208 * Type - New GPE type 208 * action - Enable or disable
209 * Called from ISR or not
209 * 210 *
210 * RETURN: Status 211 * RETURN: Status
211 * 212 *
212 * DESCRIPTION: Set the type of an individual GPE 213 * DESCRIPTION: Enable or disable an ACPI event (general purpose)
213 * 214 *
214 ******************************************************************************/ 215 ******************************************************************************/
215acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type) 216acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
216{ 217{
217 acpi_status status = AE_OK; 218 acpi_status status = AE_OK;
219 acpi_cpu_flags flags;
218 struct acpi_gpe_event_info *gpe_event_info; 220 struct acpi_gpe_event_info *gpe_event_info;
219 221
220 ACPI_FUNCTION_TRACE(acpi_set_gpe_type); 222 ACPI_FUNCTION_TRACE(acpi_set_gpe);
223
224 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
221 225
222 /* Ensure that we have a valid GPE number */ 226 /* Ensure that we have a valid GPE number */
223 227
@@ -227,19 +231,29 @@ acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
227 goto unlock_and_exit; 231 goto unlock_and_exit;
228 } 232 }
229 233
230 if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) { 234 /* Perform the action */
231 return_ACPI_STATUS(AE_OK); 235
232 } 236 switch (action) {
237 case ACPI_GPE_ENABLE:
238 status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
239 break;
233 240
234 /* Set the new type (will disable GPE if currently enabled) */ 241 case ACPI_GPE_DISABLE:
242 status = acpi_ev_disable_gpe(gpe_event_info);
243 break;
235 244
236 status = acpi_ev_set_gpe_type(gpe_event_info, type); 245 default:
246 ACPI_ERROR((AE_INFO, "Invalid action\n"));
247 status = AE_BAD_PARAMETER;
248 break;
249 }
237 250
238 unlock_and_exit: 251 unlock_and_exit:
252 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
239 return_ACPI_STATUS(status); 253 return_ACPI_STATUS(status);
240} 254}
241 255
242ACPI_EXPORT_SYMBOL(acpi_set_gpe_type) 256ACPI_EXPORT_SYMBOL(acpi_set_gpe)
243 257
244/******************************************************************************* 258/*******************************************************************************
245 * 259 *
@@ -247,15 +261,14 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
247 * 261 *
248 * PARAMETERS: gpe_device - Parent GPE Device 262 * PARAMETERS: gpe_device - Parent GPE Device
249 * gpe_number - GPE level within the GPE block 263 * gpe_number - GPE level within the GPE block
250 * Flags - Just enable, or also wake enable? 264 * type - Purpose the GPE will be used for
251 * Called from ISR or not
252 * 265 *
253 * RETURN: Status 266 * RETURN: Status
254 * 267 *
255 * DESCRIPTION: Enable an ACPI event (general purpose) 268 * DESCRIPTION: Take a reference to a GPE and enable it if necessary
256 * 269 *
257 ******************************************************************************/ 270 ******************************************************************************/
258acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number) 271acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
259{ 272{
260 acpi_status status = AE_OK; 273 acpi_status status = AE_OK;
261 acpi_cpu_flags flags; 274 acpi_cpu_flags flags;
@@ -273,15 +286,32 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
273 goto unlock_and_exit; 286 goto unlock_and_exit;
274 } 287 }
275 288
276 /* Perform the enable */ 289 if (type & ACPI_GPE_TYPE_RUNTIME) {
290 if (++gpe_event_info->runtime_count == 1)
291 status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
277 292
278 status = acpi_ev_enable_gpe(gpe_event_info, TRUE); 293 if (ACPI_FAILURE(status))
294 gpe_event_info->runtime_count--;
295 }
279 296
280 unlock_and_exit: 297 if (type & ACPI_GPE_TYPE_WAKE) {
298 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
299 status = AE_BAD_PARAMETER;
300 goto unlock_and_exit;
301 }
302
303 /*
304 * Wake-up GPEs are only enabled right prior to putting the
305 * system into a sleep state.
306 */
307 if (++gpe_event_info->wakeup_count == 1)
308 acpi_ev_update_gpe_enable_masks(gpe_event_info);
309 }
310
311unlock_and_exit:
281 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 312 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
282 return_ACPI_STATUS(status); 313 return_ACPI_STATUS(status);
283} 314}
284
285ACPI_EXPORT_SYMBOL(acpi_enable_gpe) 315ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
286 316
287/******************************************************************************* 317/*******************************************************************************
@@ -290,15 +320,14 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
290 * 320 *
291 * PARAMETERS: gpe_device - Parent GPE Device 321 * PARAMETERS: gpe_device - Parent GPE Device
292 * gpe_number - GPE level within the GPE block 322 * gpe_number - GPE level within the GPE block
293 * Flags - Just disable, or also wake disable? 323 * type - Purpose the GPE won't be used for any more
294 * Called from ISR or not
295 * 324 *
296 * RETURN: Status 325 * RETURN: Status
297 * 326 *
298 * DESCRIPTION: Disable an ACPI event (general purpose) 327 * DESCRIPTION: Release a reference to a GPE and disable it if necessary
299 * 328 *
300 ******************************************************************************/ 329 ******************************************************************************/
301acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number) 330acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type)
302{ 331{
303 acpi_status status = AE_OK; 332 acpi_status status = AE_OK;
304 acpi_cpu_flags flags; 333 acpi_cpu_flags flags;
@@ -315,13 +344,24 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
315 goto unlock_and_exit; 344 goto unlock_and_exit;
316 } 345 }
317 346
318 status = acpi_ev_disable_gpe(gpe_event_info); 347 if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->runtime_count) {
348 if (--gpe_event_info->runtime_count == 0)
349 acpi_ev_disable_gpe(gpe_event_info);
350 }
351
352 if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->wakeup_count) {
353 /*
354 * Wake-up GPEs are not enabled after leaving system sleep
355 * states, so we don't need to disable them here.
356 */
357 if (--gpe_event_info->wakeup_count == 0)
358 acpi_ev_update_gpe_enable_masks(gpe_event_info);
359 }
319 360
320unlock_and_exit: 361unlock_and_exit:
321 acpi_os_release_lock(acpi_gbl_gpe_lock, flags); 362 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
322 return_ACPI_STATUS(status); 363 return_ACPI_STATUS(status);
323} 364}
324
325ACPI_EXPORT_SYMBOL(acpi_disable_gpe) 365ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
326 366
327/******************************************************************************* 367/*******************************************************************************