evgpeblk.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: evgpeblk - GPE block creation and initialization.
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #include "acevents.h"
  12. #include "acnamesp.h"
  13. #define _COMPONENT ACPI_EVENTS
  14. ACPI_MODULE_NAME("evgpeblk")
  15. #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
  16. /* Local prototypes */
  17. static acpi_status
  18. acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
  19. u32 interrupt_number);
  20. static acpi_status
  21. acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block);
  22. /*******************************************************************************
  23. *
  24. * FUNCTION: acpi_ev_install_gpe_block
  25. *
  26. * PARAMETERS: gpe_block - New GPE block
  27. * interrupt_number - Xrupt to be associated with this
  28. * GPE block
  29. *
  30. * RETURN: Status
  31. *
  32. * DESCRIPTION: Install new GPE block with mutex support
  33. *
  34. ******************************************************************************/
  35. static acpi_status
  36. acpi_ev_install_gpe_block(struct acpi_gpe_block_info *gpe_block,
  37. u32 interrupt_number)
  38. {
  39. struct acpi_gpe_block_info *next_gpe_block;
  40. struct acpi_gpe_xrupt_info *gpe_xrupt_block;
  41. acpi_status status;
  42. acpi_cpu_flags flags;
  43. ACPI_FUNCTION_TRACE(ev_install_gpe_block);
  44. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  45. if (ACPI_FAILURE(status)) {
  46. return_ACPI_STATUS(status);
  47. }
  48. status =
  49. acpi_ev_get_gpe_xrupt_block(interrupt_number, &gpe_xrupt_block);
  50. if (ACPI_FAILURE(status)) {
  51. goto unlock_and_exit;
  52. }
  53. /* Install the new block at the end of the list with lock */
  54. flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  55. if (gpe_xrupt_block->gpe_block_list_head) {
  56. next_gpe_block = gpe_xrupt_block->gpe_block_list_head;
  57. while (next_gpe_block->next) {
  58. next_gpe_block = next_gpe_block->next;
  59. }
  60. next_gpe_block->next = gpe_block;
  61. gpe_block->previous = next_gpe_block;
  62. } else {
  63. gpe_xrupt_block->gpe_block_list_head = gpe_block;
  64. }
  65. gpe_block->xrupt_block = gpe_xrupt_block;
  66. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  67. unlock_and_exit:
  68. (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  69. return_ACPI_STATUS(status);
  70. }
  71. /*******************************************************************************
  72. *
  73. * FUNCTION: acpi_ev_delete_gpe_block
  74. *
  75. * PARAMETERS: gpe_block - Existing GPE block
  76. *
  77. * RETURN: Status
  78. *
  79. * DESCRIPTION: Remove a GPE block
  80. *
  81. ******************************************************************************/
  82. acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block)
  83. {
  84. acpi_status status;
  85. acpi_cpu_flags flags;
  86. ACPI_FUNCTION_TRACE(ev_install_gpe_block);
  87. status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
  88. if (ACPI_FAILURE(status)) {
  89. return_ACPI_STATUS(status);
  90. }
  91. /* Disable all GPEs in this block */
  92. status =
  93. acpi_hw_disable_gpe_block(gpe_block->xrupt_block, gpe_block, NULL);
  94. if (ACPI_FAILURE(status)) {
  95. return_ACPI_STATUS(status);
  96. }
  97. if (!gpe_block->previous && !gpe_block->next) {
  98. /* This is the last gpe_block on this interrupt */
  99. status = acpi_ev_delete_gpe_xrupt(gpe_block->xrupt_block);
  100. if (ACPI_FAILURE(status)) {
  101. goto unlock_and_exit;
  102. }
  103. } else {
  104. /* Remove the block on this interrupt with lock */
  105. flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
  106. if (gpe_block->previous) {
  107. gpe_block->previous->next = gpe_block->next;
  108. } else {
  109. gpe_block->xrupt_block->gpe_block_list_head =
  110. gpe_block->next;
  111. }
  112. if (gpe_block->next) {
  113. gpe_block->next->previous = gpe_block->previous;
  114. }
  115. acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
  116. }
  117. acpi_current_gpe_count -= gpe_block->gpe_count;
  118. /* Free the gpe_block */
  119. ACPI_FREE(gpe_block->register_info);
  120. ACPI_FREE(gpe_block->event_info);
  121. ACPI_FREE(gpe_block);
  122. unlock_and_exit:
  123. status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
  124. return_ACPI_STATUS(status);
  125. }
  126. /*******************************************************************************
  127. *
  128. * FUNCTION: acpi_ev_create_gpe_info_blocks
  129. *
  130. * PARAMETERS: gpe_block - New GPE block
  131. *
  132. * RETURN: Status
  133. *
  134. * DESCRIPTION: Create the register_info and event_info blocks for this GPE block
  135. *
  136. ******************************************************************************/
  137. static acpi_status
  138. acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block)
  139. {
  140. struct acpi_gpe_register_info *gpe_register_info = NULL;
  141. struct acpi_gpe_event_info *gpe_event_info = NULL;
  142. struct acpi_gpe_event_info *this_event;
  143. struct acpi_gpe_register_info *this_register;
  144. u32 i;
  145. u32 j;
  146. acpi_status status;
  147. ACPI_FUNCTION_TRACE(ev_create_gpe_info_blocks);
  148. /* Allocate the GPE register information block */
  149. gpe_register_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->
  150. register_count *
  151. sizeof(struct
  152. acpi_gpe_register_info));
  153. if (!gpe_register_info) {
  154. ACPI_ERROR((AE_INFO,
  155. "Could not allocate the GpeRegisterInfo table"));
  156. return_ACPI_STATUS(AE_NO_MEMORY);
  157. }
  158. /*
  159. * Allocate the GPE event_info block. There are eight distinct GPEs
  160. * per register. Initialization to zeros is sufficient.
  161. */
  162. gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size)gpe_block->gpe_count *
  163. sizeof(struct
  164. acpi_gpe_event_info));
  165. if (!gpe_event_info) {
  166. ACPI_ERROR((AE_INFO,
  167. "Could not allocate the GpeEventInfo table"));
  168. status = AE_NO_MEMORY;
  169. goto error_exit;
  170. }
  171. /* Save the new Info arrays in the GPE block */
  172. gpe_block->register_info = gpe_register_info;
  173. gpe_block->event_info = gpe_event_info;
  174. /*
  175. * Initialize the GPE Register and Event structures. A goal of these
  176. * tables is to hide the fact that there are two separate GPE register
  177. * sets in a given GPE hardware block, the status registers occupy the
  178. * first half, and the enable registers occupy the second half.
  179. */
  180. this_register = gpe_register_info;
  181. this_event = gpe_event_info;
  182. for (i = 0; i < gpe_block->register_count; i++) {
  183. /* Init the register_info for this GPE register (8 GPEs) */
  184. this_register->base_gpe_number = (u16)
  185. (gpe_block->block_base_number +
  186. (i * ACPI_GPE_REGISTER_WIDTH));
  187. this_register->status_address.address = gpe_block->address + i;
  188. this_register->enable_address.address =
  189. gpe_block->address + i + gpe_block->register_count;
  190. this_register->status_address.space_id = gpe_block->space_id;
  191. this_register->enable_address.space_id = gpe_block->space_id;
  192. /* Init the event_info for each GPE within this register */
  193. for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
  194. this_event->gpe_number =
  195. (u8) (this_register->base_gpe_number + j);
  196. this_event->register_info = this_register;
  197. this_event++;
  198. }
  199. /* Disable all GPEs within this register */
  200. status = acpi_hw_gpe_write(0x00, &this_register->enable_address);
  201. if (ACPI_FAILURE(status)) {
  202. goto error_exit;
  203. }
  204. /* Clear any pending GPE events within this register */
  205. status = acpi_hw_gpe_write(0xFF, &this_register->status_address);
  206. if (ACPI_FAILURE(status)) {
  207. goto error_exit;
  208. }
  209. this_register++;
  210. }
  211. return_ACPI_STATUS(AE_OK);
  212. error_exit:
  213. if (gpe_register_info) {
  214. ACPI_FREE(gpe_register_info);
  215. }
  216. if (gpe_event_info) {
  217. ACPI_FREE(gpe_event_info);
  218. }
  219. return_ACPI_STATUS(status);
  220. }
  221. /*******************************************************************************
  222. *
  223. * FUNCTION: acpi_ev_create_gpe_block
  224. *
  225. * PARAMETERS: gpe_device - Handle to the parent GPE block
  226. * gpe_block_address - Address and space_ID
  227. * register_count - Number of GPE register pairs in the block
  228. * gpe_block_base_number - Starting GPE number for the block
  229. * interrupt_number - H/W interrupt for the block
  230. * return_gpe_block - Where the new block descriptor is returned
  231. *
  232. * RETURN: Status
  233. *
  234. * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within
  235. * the block are disabled at exit.
  236. * Note: Assumes namespace is locked.
  237. *
  238. ******************************************************************************/
  239. acpi_status
  240. acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
  241. u64 address,
  242. u8 space_id,
  243. u32 register_count,
  244. u16 gpe_block_base_number,
  245. u32 interrupt_number,
  246. struct acpi_gpe_block_info **return_gpe_block)
  247. {
  248. acpi_status status;
  249. struct acpi_gpe_block_info *gpe_block;
  250. struct acpi_gpe_walk_info walk_info;
  251. ACPI_FUNCTION_TRACE(ev_create_gpe_block);
  252. if (!register_count) {
  253. return_ACPI_STATUS(AE_OK);
  254. }
  255. /* Validate the space_ID */
  256. if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
  257. (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
  258. ACPI_ERROR((AE_INFO,
  259. "Unsupported address space: 0x%X", space_id));
  260. return_ACPI_STATUS(AE_SUPPORT);
  261. }
  262. if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
  263. status = acpi_hw_validate_io_block(address,
  264. ACPI_GPE_REGISTER_WIDTH,
  265. register_count);
  266. if (ACPI_FAILURE(status))
  267. return_ACPI_STATUS(status);
  268. }
  269. /* Allocate a new GPE block */
  270. gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
  271. if (!gpe_block) {
  272. return_ACPI_STATUS(AE_NO_MEMORY);
  273. }
  274. /* Initialize the new GPE block */
  275. gpe_block->address = address;
  276. gpe_block->space_id = space_id;
  277. gpe_block->node = gpe_device;
  278. gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH);
  279. gpe_block->initialized = FALSE;
  280. gpe_block->register_count = register_count;
  281. gpe_block->block_base_number = gpe_block_base_number;
  282. /*
  283. * Create the register_info and event_info sub-structures
  284. * Note: disables and clears all GPEs in the block
  285. */
  286. status = acpi_ev_create_gpe_info_blocks(gpe_block);
  287. if (ACPI_FAILURE(status)) {
  288. ACPI_FREE(gpe_block);
  289. return_ACPI_STATUS(status);
  290. }
  291. /* Install the new block in the global lists */
  292. status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
  293. if (ACPI_FAILURE(status)) {
  294. ACPI_FREE(gpe_block->register_info);
  295. ACPI_FREE(gpe_block->event_info);
  296. ACPI_FREE(gpe_block);
  297. return_ACPI_STATUS(status);
  298. }
  299. acpi_gbl_all_gpes_initialized = FALSE;
  300. /* Find all GPE methods (_Lxx or_Exx) for this block */
  301. walk_info.gpe_block = gpe_block;
  302. walk_info.gpe_device = gpe_device;
  303. walk_info.execute_by_owner_id = FALSE;
  304. (void)acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
  305. ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
  306. acpi_ev_match_gpe_method, NULL, &walk_info,
  307. NULL);
  308. /* Return the new block */
  309. if (return_gpe_block) {
  310. (*return_gpe_block) = gpe_block;
  311. }
  312. ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
  313. " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
  314. (u32)gpe_block->block_base_number,
  315. (u32)(gpe_block->block_base_number +
  316. (gpe_block->gpe_count - 1)),
  317. gpe_device->name.ascii, gpe_block->register_count,
  318. interrupt_number,
  319. interrupt_number ==
  320. acpi_gbl_FADT.sci_interrupt ? " (SCI)" : ""));
  321. /* Update global count of currently available GPEs */
  322. acpi_current_gpe_count += gpe_block->gpe_count;
  323. return_ACPI_STATUS(AE_OK);
  324. }
  325. /*******************************************************************************
  326. *
  327. * FUNCTION: acpi_ev_initialize_gpe_block
  328. *
  329. * PARAMETERS: acpi_gpe_callback
  330. *
  331. * RETURN: Status
  332. *
  333. * DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
  334. * associated methods.
  335. * Note: Assumes namespace is locked.
  336. *
  337. ******************************************************************************/
  338. acpi_status
  339. acpi_ev_initialize_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
  340. struct acpi_gpe_block_info *gpe_block,
  341. void *context)
  342. {
  343. acpi_status status;
  344. struct acpi_gpe_event_info *gpe_event_info;
  345. u32 gpe_enabled_count;
  346. u32 gpe_index;
  347. u32 i;
  348. u32 j;
  349. u8 *is_polling_needed = context;
  350. ACPI_ERROR_ONLY(u32 gpe_number);
  351. ACPI_FUNCTION_TRACE(ev_initialize_gpe_block);
  352. /*
  353. * Ignore a null GPE block (e.g., if no GPE block 1 exists), and
  354. * any GPE blocks that have been initialized already.
  355. */
  356. if (!gpe_block || gpe_block->initialized) {
  357. return_ACPI_STATUS(AE_OK);
  358. }
  359. /*
  360. * Enable all GPEs that have a corresponding method and have the
  361. * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
  362. * must be enabled via the acpi_enable_gpe() interface.
  363. */
  364. gpe_enabled_count = 0;
  365. for (i = 0; i < gpe_block->register_count; i++) {
  366. for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) {
  367. /* Get the info block for this particular GPE */
  368. gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j;
  369. gpe_event_info = &gpe_block->event_info[gpe_index];
  370. ACPI_ERROR_ONLY(gpe_number =
  371. gpe_block->block_base_number +
  372. gpe_index);
  373. gpe_event_info->flags |= ACPI_GPE_INITIALIZED;
  374. /*
  375. * Ignore GPEs that have no corresponding _Lxx/_Exx method
  376. * and GPEs that are used for wakeup
  377. */
  378. if ((ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
  379. ACPI_GPE_DISPATCH_METHOD)
  380. || (gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
  381. continue;
  382. }
  383. status = acpi_ev_add_gpe_reference(gpe_event_info, FALSE);
  384. if (ACPI_FAILURE(status)) {
  385. ACPI_EXCEPTION((AE_INFO, status,
  386. "Could not enable GPE 0x%02X",
  387. gpe_number));
  388. continue;
  389. }
  390. gpe_event_info->flags |= ACPI_GPE_AUTO_ENABLED;
  391. if (is_polling_needed &&
  392. ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
  393. *is_polling_needed = TRUE;
  394. }
  395. gpe_enabled_count++;
  396. }
  397. }
  398. if (gpe_enabled_count) {
  399. ACPI_INFO(("Enabled %u GPEs in block %02X to %02X",
  400. gpe_enabled_count, (u32)gpe_block->block_base_number,
  401. (u32)(gpe_block->block_base_number +
  402. (gpe_block->gpe_count - 1))));
  403. }
  404. gpe_block->initialized = TRUE;
  405. return_ACPI_STATUS(AE_OK);
  406. }
  407. #endif /* !ACPI_REDUCED_HARDWARE */