ACPICA: Validate GPE blocks at init time
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 4 Sep 2020 16:27:27 +0000 (18:27 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 4 Sep 2020 17:33:54 +0000 (19:33 +0200)
Some of the checks done by acpi_hw_read() and acpi_hw_write(),
which are used for accessing GPE registers, are redundant in the
specific case of GPE registers and the ones that are not redundant
can be done upfront at the initialization time so as to fail the
initialization if they are not passed instead of failing every
access to the affected GPE registers going forward (including
accesses from the SCI interrupt handler).

Modify the GPE blocks initialization code accordingly.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/achware.h
drivers/acpi/acpica/evgpeblk.c
drivers/acpi/acpica/hwvalid.c

index ebf6453d0e2143849cd5f98ced9f7677c0a912d6..f1f644b58b1532e2444974ea406226d656605e10 100644 (file)
@@ -73,6 +73,8 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width);
 
 acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width);
 
+acpi_status acpi_hw_validate_io_block(u64 address, u32 bit_width, u32 count);
+
 /*
  * hwgpe - GPE support
  */
index 132adff1e13161242b8a7421d0c6889e5f8e0627..eb5d98757fdcd8900cf5436c6d7bac85389b46a5 100644 (file)
@@ -317,6 +317,23 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
                return_ACPI_STATUS(AE_OK);
        }
 
+       /* Validate the space_ID */
+
+       if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
+           (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
+               ACPI_ERROR((AE_INFO,
+                           "Unsupported address space: 0x%X", space_id));
+               return_ACPI_STATUS(AE_SUPPORT);
+       }
+
+       if (space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
+               status = acpi_hw_validate_io_block(address,
+                                                  ACPI_GPE_REGISTER_WIDTH,
+                                                  register_count);
+               if (ACPI_FAILURE(status))
+                       return_ACPI_STATUS(status);
+       }
+
        /* Allocate a new GPE block */
 
        gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
index 4d94861e60934c9fd07327d27b8871bbede58500..b2ca7dfd3fc927daee6111d3918dbf9b38e096b8 100644 (file)
@@ -292,3 +292,33 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
 
        return (AE_OK);
 }
+
+/******************************************************************************
+ *
+ * FUNCTION:    acpi_hw_validate_io_block
+ *
+ * PARAMETERS:  Address             Address of I/O port/register blobk
+ *              bit_width           Number of bits (8,16,32) in each register
+ *              count               Number of registers in the block
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Validates a block of I/O ports/registers.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_hw_validate_io_block(u64 address, u32 bit_width, u32 count)
+{
+       acpi_status status;
+
+       while (count--) {
+               status = acpi_hw_validate_io_request((acpi_io_address)address,
+                                                    bit_width);
+               if (ACPI_FAILURE(status))
+                       return_ACPI_STATUS(status);
+
+               address += ACPI_DIV_8(bit_width);
+       }
+
+       return_ACPI_STATUS(AE_OK);
+}