evxface.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983
  1. /******************************************************************************
  2. *
  3. * Module Name: evxface - External interfaces for ACPI events
  4. *
  5. *****************************************************************************/
  6. /*
  7. * Copyright (C) 2000 - 2013, Intel Corp.
  8. * All rights reserved.
  9. *
  10. * Redistribution and use in source and binary forms, with or without
  11. * modification, are permitted provided that the following conditions
  12. * are met:
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions, and the following disclaimer,
  15. * without modification.
  16. * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  17. * substantially similar to the "NO WARRANTY" disclaimer below
  18. * ("Disclaimer") and any redistribution must be conditioned upon
  19. * including a substantially similar Disclaimer requirement for further
  20. * binary redistribution.
  21. * 3. Neither the names of the above-listed copyright holders nor the names
  22. * of any contributors may be used to endorse or promote products derived
  23. * from this software without specific prior written permission.
  24. *
  25. * Alternatively, this software may be distributed under the terms of the
  26. * GNU General Public License ("GPL") version 2 as published by the Free
  27. * Software Foundation.
  28. *
  29. * NO WARRANTY
  30. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  31. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  32. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  33. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  34. * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  35. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  36. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  37. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  38. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  39. * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  40. * POSSIBILITY OF SUCH DAMAGES.
  41. */
  42. #define EXPORT_ACPI_INTERFACES
  43. #include <acpi/acpi.h>
  44. #include "accommon.h"
  45. #include "acnamesp.h"
  46. #include "acevents.h"
  47. #include "acinterp.h"
  48. #define _COMPONENT ACPI_EVENTS
  49. ACPI_MODULE_NAME("evxface")
  50. /*******************************************************************************
  51. *
  52. * FUNCTION: acpi_install_notify_handler
  53. *
  54. * PARAMETERS: device - The device for which notifies will be handled
  55. * handler_type - The type of handler:
  56. * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
  57. * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
  58. * ACPI_ALL_NOTIFY: Both System and Device
  59. * handler - Address of the handler
  60. * context - Value passed to the handler on each GPE
  61. *
  62. * RETURN: Status
  63. *
  64. * DESCRIPTION: Install a handler for notifications on an ACPI Device,
  65. * thermal_zone, or Processor object.
  66. *
  67. * NOTES: The Root namespace object may have only one handler for each
  68. * type of notify (System/Device). Device/Thermal/Processor objects
  69. * may have one device notify handler, and multiple system notify
  70. * handlers.
  71. *
  72. ******************************************************************************/
  73. acpi_status
  74. acpi_install_notify_handler(acpi_handle device,
  75. u32 handler_type,
  76. acpi_notify_handler handler, void *context)
  77. {
  78. struct acpi_namespace_node *node =
  79. ACPI_CAST_PTR(struct acpi_namespace_node, device);
  80. union acpi_operand_object *obj_desc;
  81. union acpi_operand_object *handler_obj;
  82. acpi_status status;
  83. u32 i;
  84. ACPI_FUNCTION_TRACE(acpi_install_notify_handler);
  85. /* Parameter validation */
  86. if ((!device) || (!handler) || (!handler_type) ||
  87. (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
  88. return_ACPI_STATUS(AE_BAD_PARAMETER);
  89. }
  90. status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  91. if (ACPI_FAILURE(status)) {
  92. return_ACPI_STATUS(status);
  93. }
  94. /*
  95. * Root Object:
  96. * Registering a notify handler on the root object indicates that the
  97. * caller wishes to receive notifications for all objects. Note that
  98. * only one global handler can be registered per notify type.
  99. * Ensure that a handler is not already installed.
  100. */
  101. if (device == ACPI_ROOT_OBJECT) {
  102. for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  103. if (handler_type & (i + 1)) {
  104. if (acpi_gbl_global_notify[i].handler) {
  105. status = AE_ALREADY_EXISTS;
  106. goto unlock_and_exit;
  107. }
  108. acpi_gbl_global_notify[i].handler = handler;
  109. acpi_gbl_global_notify[i].context = context;
  110. }
  111. }
  112. goto unlock_and_exit; /* Global notify handler installed, all done */
  113. }
  114. /*
  115. * All Other Objects:
  116. * Caller will only receive notifications specific to the target
  117. * object. Note that only certain object types are allowed to
  118. * receive notifications.
  119. */
  120. /* Are Notifies allowed on this object? */
  121. if (!acpi_ev_is_notify_object(node)) {
  122. status = AE_TYPE;
  123. goto unlock_and_exit;
  124. }
  125. /* Check for an existing internal object, might not exist */
  126. obj_desc = acpi_ns_get_attached_object(node);
  127. if (!obj_desc) {
  128. /* Create a new object */
  129. obj_desc = acpi_ut_create_internal_object(node->type);
  130. if (!obj_desc) {
  131. status = AE_NO_MEMORY;
  132. goto unlock_and_exit;
  133. }
  134. /* Attach new object to the Node, remove local reference */
  135. status = acpi_ns_attach_object(device, obj_desc, node->type);
  136. acpi_ut_remove_reference(obj_desc);
  137. if (ACPI_FAILURE(status)) {
  138. goto unlock_and_exit;
  139. }
  140. }
  141. /* Ensure that the handler is not already installed in the lists */
  142. for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  143. if (handler_type & (i + 1)) {
  144. handler_obj = obj_desc->common_notify.notify_list[i];
  145. while (handler_obj) {
  146. if (handler_obj->notify.handler == handler) {
  147. status = AE_ALREADY_EXISTS;
  148. goto unlock_and_exit;
  149. }
  150. handler_obj = handler_obj->notify.next[i];
  151. }
  152. }
  153. }
  154. /* Create and populate a new notify handler object */
  155. handler_obj = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_NOTIFY);
  156. if (!handler_obj) {
  157. status = AE_NO_MEMORY;
  158. goto unlock_and_exit;
  159. }
  160. handler_obj->notify.node = node;
  161. handler_obj->notify.handler_type = handler_type;
  162. handler_obj->notify.handler = handler;
  163. handler_obj->notify.context = context;
  164. /* Install the handler at the list head(s) */
  165. for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  166. if (handler_type & (i + 1)) {
  167. handler_obj->notify.next[i] =
  168. obj_desc->common_notify.notify_list[i];
  169. obj_desc->common_notify.notify_list[i] = handler_obj;
  170. }
  171. }
  172. /* Add an extra reference if handler was installed in both lists */
  173. if (handler_type == ACPI_ALL_NOTIFY) {
  174. acpi_ut_add_reference(handler_obj);
  175. }
  176. unlock_and_exit:
  177. (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  178. return_ACPI_STATUS(status);
  179. }
  180. ACPI_EXPORT_SYMBOL(acpi_install_notify_handler)
  181. /*******************************************************************************
  182. *
  183. * FUNCTION: acpi_remove_notify_handler
  184. *
  185. * PARAMETERS: device - The device for which the handler is installed
  186. * handler_type - The type of handler:
  187. * ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
  188. * ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
  189. * ACPI_ALL_NOTIFY: Both System and Device
  190. * handler - Address of the handler
  191. *
  192. * RETURN: Status
  193. *
  194. * DESCRIPTION: Remove a handler for notifies on an ACPI device
  195. *
  196. ******************************************************************************/
  197. acpi_status
  198. acpi_remove_notify_handler(acpi_handle device,
  199. u32 handler_type, acpi_notify_handler handler)
  200. {
  201. struct acpi_namespace_node *node =
  202. ACPI_CAST_PTR(struct acpi_namespace_node, device);
  203. union acpi_operand_object *obj_desc;
  204. union acpi_operand_object *handler_obj;
  205. union acpi_operand_object *previous_handler_obj;
  206. acpi_status status;
  207. u32 i;
  208. ACPI_FUNCTION_TRACE(acpi_remove_notify_handler);
  209. /* Parameter validation */
  210. if ((!device) || (!handler) || (!handler_type) ||
  211. (handler_type > ACPI_MAX_NOTIFY_HANDLER_TYPE)) {
  212. return_ACPI_STATUS(AE_BAD_PARAMETER);
  213. }
  214. /* Make sure all deferred notify tasks are completed */
  215. acpi_os_wait_events_complete();
  216. status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  217. if (ACPI_FAILURE(status)) {
  218. return_ACPI_STATUS(status);
  219. }
  220. /* Root Object. Global handlers are removed here */
  221. if (device == ACPI_ROOT_OBJECT) {
  222. for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  223. if (handler_type & (i + 1)) {
  224. if (!acpi_gbl_global_notify[i].handler ||
  225. (acpi_gbl_global_notify[i].handler !=
  226. handler)) {
  227. status = AE_NOT_EXIST;
  228. goto unlock_and_exit;
  229. }
  230. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  231. "Removing global notify handler\n"));
  232. acpi_gbl_global_notify[i].handler = NULL;
  233. acpi_gbl_global_notify[i].context = NULL;
  234. }
  235. }
  236. goto unlock_and_exit;
  237. }
  238. /* All other objects: Are Notifies allowed on this object? */
  239. if (!acpi_ev_is_notify_object(node)) {
  240. status = AE_TYPE;
  241. goto unlock_and_exit;
  242. }
  243. /* Must have an existing internal object */
  244. obj_desc = acpi_ns_get_attached_object(node);
  245. if (!obj_desc) {
  246. status = AE_NOT_EXIST;
  247. goto unlock_and_exit;
  248. }
  249. /* Internal object exists. Find the handler and remove it */
  250. for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) {
  251. if (handler_type & (i + 1)) {
  252. handler_obj = obj_desc->common_notify.notify_list[i];
  253. previous_handler_obj = NULL;
  254. /* Attempt to find the handler in the handler list */
  255. while (handler_obj &&
  256. (handler_obj->notify.handler != handler)) {
  257. previous_handler_obj = handler_obj;
  258. handler_obj = handler_obj->notify.next[i];
  259. }
  260. if (!handler_obj) {
  261. status = AE_NOT_EXIST;
  262. goto unlock_and_exit;
  263. }
  264. /* Remove the handler object from the list */
  265. if (previous_handler_obj) { /* Handler is not at the list head */
  266. previous_handler_obj->notify.next[i] =
  267. handler_obj->notify.next[i];
  268. } else { /* Handler is at the list head */
  269. obj_desc->common_notify.notify_list[i] =
  270. handler_obj->notify.next[i];
  271. }
  272. acpi_ut_remove_reference(handler_obj);
  273. }
  274. }
  275. unlock_and_exit:
  276. (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  277. return_ACPI_STATUS(status);
  278. }
  279. ACPI_EXPORT_SYMBOL(acpi_remove_notify_handler)
  280. /*******************************************************************************
  281. *
  282. * FUNCTION: acpi_install_exception_handler
  283. *
  284. * PARAMETERS: handler - Pointer to the handler function for the
  285. * event
  286. *
  287. * RETURN: Status
  288. *
  289. * DESCRIPTION: Saves the pointer to the handler function
  290. *
  291. ******************************************************************************/
  292. #ifdef ACPI_FUTURE_USAGE
  293. acpi_status acpi_install_exception_handler(acpi_exception_handler handler)
  294. {
  295. acpi_status status;
  296. ACPI_FUNCTION_TRACE(acpi_install_exception_handler);
  297. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  298. if (ACPI_FAILURE(status)) {
  299. return_ACPI_STATUS(status);
  300. }
  301. /* Don't allow two handlers. */
  302. if (acpi_gbl_exception_handler) {
  303. status = AE_ALREADY_EXISTS;
  304. goto cleanup;
  305. }
  306. /* Install the handler */
  307. acpi_gbl_exception_handler = handler;
  308. cleanup:
  309. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  310. return_ACPI_STATUS(status);
  311. }
  312. ACPI_EXPORT_SYMBOL(acpi_install_exception_handler)
  313. #endif /* ACPI_FUTURE_USAGE */
  314. #if (!ACPI_REDUCED_HARDWARE)
  315. /*******************************************************************************
  316. *
  317. * FUNCTION: acpi_install_sci_handler
  318. *
  319. * PARAMETERS: address - Address of the handler
  320. * context - Value passed to the handler on each SCI
  321. *
  322. * RETURN: Status
  323. *
  324. * DESCRIPTION: Install a handler for a System Control Interrupt.
  325. *
  326. ******************************************************************************/
  327. acpi_status acpi_install_sci_handler(acpi_sci_handler address, void *context)
  328. {
  329. struct acpi_sci_handler_info *new_sci_handler;
  330. struct acpi_sci_handler_info *sci_handler;
  331. acpi_cpu_flags flags;
  332. acpi_status status;
  333. ACPI_FUNCTION_TRACE(acpi_install_sci_handler);
  334. if (!address) {
  335. return_ACPI_STATUS(AE_BAD_PARAMETER);
  336. }
  337. /* Allocate and init a handler object */
  338. new_sci_handler = ACPI_ALLOCATE(sizeof(struct acpi_sci_handler_info));
  339. if (!new_sci_handler) {
  340. return_ACPI_STATUS(AE_NO_MEMORY);
  341. }
  342. new_sci_handler->address = address;
  343. new_sci_handler->context = context;
  344. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  345. if (ACPI_FAILURE(status)) {
  346. goto exit;
  347. }
  348. /* Lock list during installation */
  349. flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  350. sci_handler = acpi_gbl_sci_handler_list;
  351. /* Ensure handler does not already exist */
  352. while (sci_handler) {
  353. if (address == sci_handler->address) {
  354. status = AE_ALREADY_EXISTS;
  355. goto unlock_and_exit;
  356. }
  357. sci_handler = sci_handler->next;
  358. }
  359. /* Install the new handler into the global list (at head) */
  360. new_sci_handler->next = acpi_gbl_sci_handler_list;
  361. acpi_gbl_sci_handler_list = new_sci_handler;
  362. unlock_and_exit:
  363. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  364. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  365. exit:
  366. if (ACPI_FAILURE(status)) {
  367. ACPI_FREE(new_sci_handler);
  368. }
  369. return_ACPI_STATUS(status);
  370. }
  371. /*******************************************************************************
  372. *
  373. * FUNCTION: acpi_remove_sci_handler
  374. *
  375. * PARAMETERS: address - Address of the handler
  376. *
  377. * RETURN: Status
  378. *
  379. * DESCRIPTION: Remove a handler for a System Control Interrupt.
  380. *
  381. ******************************************************************************/
  382. acpi_status acpi_remove_sci_handler(acpi_sci_handler address)
  383. {
  384. struct acpi_sci_handler_info *prev_sci_handler;
  385. struct acpi_sci_handler_info *next_sci_handler;
  386. acpi_cpu_flags flags;
  387. acpi_status status;
  388. ACPI_FUNCTION_TRACE(acpi_remove_sci_handler);
  389. if (!address) {
  390. return_ACPI_STATUS(AE_BAD_PARAMETER);
  391. }
  392. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  393. if (ACPI_FAILURE(status)) {
  394. return_ACPI_STATUS(status);
  395. }
  396. /* Remove the SCI handler with lock */
  397. flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  398. prev_sci_handler = NULL;
  399. next_sci_handler = acpi_gbl_sci_handler_list;
  400. while (next_sci_handler) {
  401. if (next_sci_handler->address == address) {
  402. /* Unlink and free the SCI handler info block */
  403. if (prev_sci_handler) {
  404. prev_sci_handler->next = next_sci_handler->next;
  405. } else {
  406. acpi_gbl_sci_handler_list =
  407. next_sci_handler->next;
  408. }
  409. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  410. ACPI_FREE(next_sci_handler);
  411. goto unlock_and_exit;
  412. }
  413. prev_sci_handler = next_sci_handler;
  414. next_sci_handler = next_sci_handler->next;
  415. }
  416. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  417. status = AE_NOT_EXIST;
  418. unlock_and_exit:
  419. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  420. return_ACPI_STATUS(status);
  421. }
  422. /*******************************************************************************
  423. *
  424. * FUNCTION: acpi_install_global_event_handler
  425. *
  426. * PARAMETERS: handler - Pointer to the global event handler function
  427. * context - Value passed to the handler on each event
  428. *
  429. * RETURN: Status
  430. *
  431. * DESCRIPTION: Saves the pointer to the handler function. The global handler
  432. * is invoked upon each incoming GPE and Fixed Event. It is
  433. * invoked at interrupt level at the time of the event dispatch.
  434. * Can be used to update event counters, etc.
  435. *
  436. ******************************************************************************/
  437. acpi_status
  438. acpi_install_global_event_handler(acpi_gbl_event_handler handler, void *context)
  439. {
  440. acpi_status status;
  441. ACPI_FUNCTION_TRACE(acpi_install_global_event_handler);
  442. /* Parameter validation */
  443. if (!handler) {
  444. return_ACPI_STATUS(AE_BAD_PARAMETER);
  445. }
  446. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  447. if (ACPI_FAILURE(status)) {
  448. return_ACPI_STATUS(status);
  449. }
  450. /* Don't allow two handlers. */
  451. if (acpi_gbl_global_event_handler) {
  452. status = AE_ALREADY_EXISTS;
  453. goto cleanup;
  454. }
  455. acpi_gbl_global_event_handler = handler;
  456. acpi_gbl_global_event_handler_context = context;
  457. cleanup:
  458. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  459. return_ACPI_STATUS(status);
  460. }
  461. ACPI_EXPORT_SYMBOL(acpi_install_global_event_handler)
  462. /*******************************************************************************
  463. *
  464. * FUNCTION: acpi_install_fixed_event_handler
  465. *
  466. * PARAMETERS: event - Event type to enable.
  467. * handler - Pointer to the handler function for the
  468. * event
  469. * context - Value passed to the handler on each GPE
  470. *
  471. * RETURN: Status
  472. *
  473. * DESCRIPTION: Saves the pointer to the handler function and then enables the
  474. * event.
  475. *
  476. ******************************************************************************/
  477. acpi_status
  478. acpi_install_fixed_event_handler(u32 event,
  479. acpi_event_handler handler, void *context)
  480. {
  481. acpi_status status;
  482. ACPI_FUNCTION_TRACE(acpi_install_fixed_event_handler);
  483. /* Parameter validation */
  484. if (event > ACPI_EVENT_MAX) {
  485. return_ACPI_STATUS(AE_BAD_PARAMETER);
  486. }
  487. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  488. if (ACPI_FAILURE(status)) {
  489. return_ACPI_STATUS(status);
  490. }
  491. /* Do not allow multiple handlers */
  492. if (acpi_gbl_fixed_event_handlers[event].handler) {
  493. status = AE_ALREADY_EXISTS;
  494. goto cleanup;
  495. }
  496. /* Install the handler before enabling the event */
  497. acpi_gbl_fixed_event_handlers[event].handler = handler;
  498. acpi_gbl_fixed_event_handlers[event].context = context;
  499. status = acpi_clear_event(event);
  500. if (ACPI_SUCCESS(status))
  501. status = acpi_enable_event(event, 0);
  502. if (ACPI_FAILURE(status)) {
  503. ACPI_WARNING((AE_INFO,
  504. "Could not enable fixed event - %s (%u)",
  505. acpi_ut_get_event_name(event), event));
  506. /* Remove the handler */
  507. acpi_gbl_fixed_event_handlers[event].handler = NULL;
  508. acpi_gbl_fixed_event_handlers[event].context = NULL;
  509. } else {
  510. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  511. "Enabled fixed event %s (%X), Handler=%p\n",
  512. acpi_ut_get_event_name(event), event,
  513. handler));
  514. }
  515. cleanup:
  516. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  517. return_ACPI_STATUS(status);
  518. }
  519. ACPI_EXPORT_SYMBOL(acpi_install_fixed_event_handler)
  520. /*******************************************************************************
  521. *
  522. * FUNCTION: acpi_remove_fixed_event_handler
  523. *
  524. * PARAMETERS: event - Event type to disable.
  525. * handler - Address of the handler
  526. *
  527. * RETURN: Status
  528. *
  529. * DESCRIPTION: Disables the event and unregisters the event handler.
  530. *
  531. ******************************************************************************/
  532. acpi_status
  533. acpi_remove_fixed_event_handler(u32 event, acpi_event_handler handler)
  534. {
  535. acpi_status status = AE_OK;
  536. ACPI_FUNCTION_TRACE(acpi_remove_fixed_event_handler);
  537. /* Parameter validation */
  538. if (event > ACPI_EVENT_MAX) {
  539. return_ACPI_STATUS(AE_BAD_PARAMETER);
  540. }
  541. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  542. if (ACPI_FAILURE(status)) {
  543. return_ACPI_STATUS(status);
  544. }
  545. /* Disable the event before removing the handler */
  546. status = acpi_disable_event(event, 0);
  547. /* Always Remove the handler */
  548. acpi_gbl_fixed_event_handlers[event].handler = NULL;
  549. acpi_gbl_fixed_event_handlers[event].context = NULL;
  550. if (ACPI_FAILURE(status)) {
  551. ACPI_WARNING((AE_INFO,
  552. "Could not disable fixed event - %s (%u)",
  553. acpi_ut_get_event_name(event), event));
  554. } else {
  555. ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  556. "Disabled fixed event - %s (%X)\n",
  557. acpi_ut_get_event_name(event), event));
  558. }
  559. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  560. return_ACPI_STATUS(status);
  561. }
  562. ACPI_EXPORT_SYMBOL(acpi_remove_fixed_event_handler)
  563. /*******************************************************************************
  564. *
  565. * FUNCTION: acpi_install_gpe_handler
  566. *
  567. * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
  568. * defined GPEs)
  569. * gpe_number - The GPE number within the GPE block
  570. * type - Whether this GPE should be treated as an
  571. * edge- or level-triggered interrupt.
  572. * address - Address of the handler
  573. * context - Value passed to the handler on each GPE
  574. *
  575. * RETURN: Status
  576. *
  577. * DESCRIPTION: Install a handler for a General Purpose Event.
  578. *
  579. ******************************************************************************/
  580. acpi_status
  581. acpi_install_gpe_handler(acpi_handle gpe_device,
  582. u32 gpe_number,
  583. u32 type, acpi_gpe_handler address, void *context)
  584. {
  585. struct acpi_gpe_event_info *gpe_event_info;
  586. struct acpi_gpe_handler_info *handler;
  587. acpi_status status;
  588. acpi_cpu_flags flags;
  589. ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
  590. /* Parameter validation */
  591. if ((!address) || (type & ~ACPI_GPE_XRUPT_TYPE_MASK)) {
  592. return_ACPI_STATUS(AE_BAD_PARAMETER);
  593. }
  594. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  595. if (ACPI_FAILURE(status)) {
  596. return_ACPI_STATUS(status);
  597. }
  598. /* Allocate and init handler object (before lock) */
  599. handler = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_handler_info));
  600. if (!handler) {
  601. status = AE_NO_MEMORY;
  602. goto unlock_and_exit;
  603. }
  604. flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  605. /* Ensure that we have a valid GPE number */
  606. gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
  607. if (!gpe_event_info) {
  608. status = AE_BAD_PARAMETER;
  609. goto free_and_exit;
  610. }
  611. /* Make sure that there isn't a handler there already */
  612. if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
  613. ACPI_GPE_DISPATCH_HANDLER) {
  614. status = AE_ALREADY_EXISTS;
  615. goto free_and_exit;
  616. }
  617. handler->address = address;
  618. handler->context = context;
  619. handler->method_node = gpe_event_info->dispatch.method_node;
  620. handler->original_flags = (u8)(gpe_event_info->flags &
  621. (ACPI_GPE_XRUPT_TYPE_MASK |
  622. ACPI_GPE_DISPATCH_MASK));
  623. /*
  624. * If the GPE is associated with a method, it may have been enabled
  625. * automatically during initialization, in which case it has to be
  626. * disabled now to avoid spurious execution of the handler.
  627. */
  628. if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD)
  629. && gpe_event_info->runtime_count) {
  630. handler->originally_enabled = 1;
  631. (void)acpi_ev_remove_gpe_reference(gpe_event_info);
  632. }
  633. /* Install the handler */
  634. gpe_event_info->dispatch.handler = handler;
  635. /* Setup up dispatch flags to indicate handler (vs. method/notify) */
  636. gpe_event_info->flags &=
  637. ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
  638. gpe_event_info->flags |= (u8) (type | ACPI_GPE_DISPATCH_HANDLER);
  639. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  640. unlock_and_exit:
  641. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  642. return_ACPI_STATUS(status);
  643. free_and_exit:
  644. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  645. ACPI_FREE(handler);
  646. goto unlock_and_exit;
  647. }
  648. ACPI_EXPORT_SYMBOL(acpi_install_gpe_handler)
  649. /*******************************************************************************
  650. *
  651. * FUNCTION: acpi_remove_gpe_handler
  652. *
  653. * PARAMETERS: gpe_device - Namespace node for the GPE (NULL for FADT
  654. * defined GPEs)
  655. * gpe_number - The event to remove a handler
  656. * address - Address of the handler
  657. *
  658. * RETURN: Status
  659. *
  660. * DESCRIPTION: Remove a handler for a General Purpose acpi_event.
  661. *
  662. ******************************************************************************/
  663. acpi_status
  664. acpi_remove_gpe_handler(acpi_handle gpe_device,
  665. u32 gpe_number, acpi_gpe_handler address)
  666. {
  667. struct acpi_gpe_event_info *gpe_event_info;
  668. struct acpi_gpe_handler_info *handler;
  669. acpi_status status;
  670. acpi_cpu_flags flags;
  671. ACPI_FUNCTION_TRACE(acpi_remove_gpe_handler);
  672. /* Parameter validation */
  673. if (!address) {
  674. return_ACPI_STATUS(AE_BAD_PARAMETER);
  675. }
  676. /* Make sure all deferred GPE tasks are completed */
  677. acpi_os_wait_events_complete();
  678. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  679. if (ACPI_FAILURE(status)) {
  680. return_ACPI_STATUS(status);
  681. }
  682. flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  683. /* Ensure that we have a valid GPE number */
  684. gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
  685. if (!gpe_event_info) {
  686. status = AE_BAD_PARAMETER;
  687. goto unlock_and_exit;
  688. }
  689. /* Make sure that a handler is indeed installed */
  690. if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
  691. ACPI_GPE_DISPATCH_HANDLER) {
  692. status = AE_NOT_EXIST;
  693. goto unlock_and_exit;
  694. }
  695. /* Make sure that the installed handler is the same */
  696. if (gpe_event_info->dispatch.handler->address != address) {
  697. status = AE_BAD_PARAMETER;
  698. goto unlock_and_exit;
  699. }
  700. /* Remove the handler */
  701. handler = gpe_event_info->dispatch.handler;
  702. /* Restore Method node (if any), set dispatch flags */
  703. gpe_event_info->dispatch.method_node = handler->method_node;
  704. gpe_event_info->flags &=
  705. ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
  706. gpe_event_info->flags |= handler->original_flags;
  707. /*
  708. * If the GPE was previously associated with a method and it was
  709. * enabled, it should be enabled at this point to restore the
  710. * post-initialization configuration.
  711. */
  712. if ((handler->original_flags & ACPI_GPE_DISPATCH_METHOD) &&
  713. handler->originally_enabled) {
  714. (void)acpi_ev_add_gpe_reference(gpe_event_info);
  715. }
  716. /* Now we can free the handler object */
  717. ACPI_FREE(handler);
  718. unlock_and_exit:
  719. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  720. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  721. return_ACPI_STATUS(status);
  722. }
  723. ACPI_EXPORT_SYMBOL(acpi_remove_gpe_handler)
  724. /*******************************************************************************
  725. *
  726. * FUNCTION: acpi_acquire_global_lock
  727. *
  728. * PARAMETERS: timeout - How long the caller is willing to wait
  729. * handle - Where the handle to the lock is returned
  730. * (if acquired)
  731. *
  732. * RETURN: Status
  733. *
  734. * DESCRIPTION: Acquire the ACPI Global Lock
  735. *
  736. * Note: Allows callers with the same thread ID to acquire the global lock
  737. * multiple times. In other words, externally, the behavior of the global lock
  738. * is identical to an AML mutex. On the first acquire, a new handle is
  739. * returned. On any subsequent calls to acquire by the same thread, the same
  740. * handle is returned.
  741. *
  742. ******************************************************************************/
  743. acpi_status acpi_acquire_global_lock(u16 timeout, u32 * handle)
  744. {
  745. acpi_status status;
  746. if (!handle) {
  747. return (AE_BAD_PARAMETER);
  748. }
  749. /* Must lock interpreter to prevent race conditions */
  750. acpi_ex_enter_interpreter();
  751. status = acpi_ex_acquire_mutex_object(timeout,
  752. acpi_gbl_global_lock_mutex,
  753. acpi_os_get_thread_id());
  754. if (ACPI_SUCCESS(status)) {
  755. /* Return the global lock handle (updated in acpi_ev_acquire_global_lock) */
  756. *handle = acpi_gbl_global_lock_handle;
  757. }
  758. acpi_ex_exit_interpreter();
  759. return (status);
  760. }
  761. ACPI_EXPORT_SYMBOL(acpi_acquire_global_lock)
  762. /*******************************************************************************
  763. *
  764. * FUNCTION: acpi_release_global_lock
  765. *
  766. * PARAMETERS: handle - Returned from acpi_acquire_global_lock
  767. *
  768. * RETURN: Status
  769. *
  770. * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
  771. *
  772. ******************************************************************************/
  773. acpi_status acpi_release_global_lock(u32 handle)
  774. {
  775. acpi_status status;
  776. if (!handle || (handle != acpi_gbl_global_lock_handle)) {
  777. return (AE_NOT_ACQUIRED);
  778. }
  779. status = acpi_ex_release_mutex_object(acpi_gbl_global_lock_mutex);
  780. return (status);
  781. }
  782. ACPI_EXPORT_SYMBOL(acpi_release_global_lock)
  783. #endif /* !ACPI_REDUCED_HARDWARE */