root/drivers/acpi/acpica/utaddress.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ACPI_MODULE_NAME
  2. acpi_ut_remove_address_range
  3. acpi_ut_check_address_range
  4. acpi_ut_delete_address_lists

   1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2 /******************************************************************************
   3  *
   4  * Module Name: utaddress - op_region address range check
   5  *
   6  * Copyright (C) 2000 - 2019, Intel Corp.
   7  *
   8  *****************************************************************************/
   9 
  10 #include <acpi/acpi.h>
  11 #include "accommon.h"
  12 #include "acnamesp.h"
  13 
  14 #define _COMPONENT          ACPI_UTILITIES
  15 ACPI_MODULE_NAME("utaddress")
  16 
  17 /*******************************************************************************
  18  *
  19  * FUNCTION:    acpi_ut_add_address_range
  20  *
  21  * PARAMETERS:  space_id            - Address space ID
  22  *              address             - op_region start address
  23  *              length              - op_region length
  24  *              region_node         - op_region namespace node
  25  *
  26  * RETURN:      Status
  27  *
  28  * DESCRIPTION: Add the Operation Region address range to the global list.
  29  *              The only supported Space IDs are Memory and I/O. Called when
  30  *              the op_region address/length operands are fully evaluated.
  31  *
  32  * MUTEX:       Locks the namespace
  33  *
  34  * NOTE: Because this interface is only called when an op_region argument
  35  * list is evaluated, there cannot be any duplicate region_nodes.
  36  * Duplicate Address/Length values are allowed, however, so that multiple
  37  * address conflicts can be detected.
  38  *
  39  ******************************************************************************/
  40 acpi_status
  41 acpi_ut_add_address_range(acpi_adr_space_type space_id,
  42                           acpi_physical_address address,
  43                           u32 length, struct acpi_namespace_node *region_node)
  44 {
  45         struct acpi_address_range *range_info;
  46 
  47         ACPI_FUNCTION_TRACE(ut_add_address_range);
  48 
  49         if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
  50             (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
  51                 return_ACPI_STATUS(AE_OK);
  52         }
  53 
  54         /* Allocate/init a new info block, add it to the appropriate list */
  55 
  56         range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));
  57         if (!range_info) {
  58                 return_ACPI_STATUS(AE_NO_MEMORY);
  59         }
  60 
  61         range_info->start_address = address;
  62         range_info->end_address = (address + length - 1);
  63         range_info->region_node = region_node;
  64 
  65         range_info->next = acpi_gbl_address_range_list[space_id];
  66         acpi_gbl_address_range_list[space_id] = range_info;
  67 
  68         ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
  69                           "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
  70                           acpi_ut_get_node_name(range_info->region_node),
  71                           ACPI_FORMAT_UINT64(address),
  72                           ACPI_FORMAT_UINT64(range_info->end_address)));
  73 
  74         return_ACPI_STATUS(AE_OK);
  75 }
  76 
  77 /*******************************************************************************
  78  *
  79  * FUNCTION:    acpi_ut_remove_address_range
  80  *
  81  * PARAMETERS:  space_id            - Address space ID
  82  *              region_node         - op_region namespace node
  83  *
  84  * RETURN:      None
  85  *
  86  * DESCRIPTION: Remove the Operation Region from the global list. The only
  87  *              supported Space IDs are Memory and I/O. Called when an
  88  *              op_region is deleted.
  89  *
  90  * MUTEX:       Assumes the namespace is locked
  91  *
  92  ******************************************************************************/
  93 
  94 void
  95 acpi_ut_remove_address_range(acpi_adr_space_type space_id,
  96                              struct acpi_namespace_node *region_node)
  97 {
  98         struct acpi_address_range *range_info;
  99         struct acpi_address_range *prev;
 100 
 101         ACPI_FUNCTION_TRACE(ut_remove_address_range);
 102 
 103         if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
 104             (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
 105                 return_VOID;
 106         }
 107 
 108         /* Get the appropriate list head and check the list */
 109 
 110         range_info = prev = acpi_gbl_address_range_list[space_id];
 111         while (range_info) {
 112                 if (range_info->region_node == region_node) {
 113                         if (range_info == prev) {       /* Found at list head */
 114                                 acpi_gbl_address_range_list[space_id] =
 115                                     range_info->next;
 116                         } else {
 117                                 prev->next = range_info->next;
 118                         }
 119 
 120                         ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
 121                                           "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
 122                                           acpi_ut_get_node_name(range_info->
 123                                                                 region_node),
 124                                           ACPI_FORMAT_UINT64(range_info->
 125                                                              start_address),
 126                                           ACPI_FORMAT_UINT64(range_info->
 127                                                              end_address)));
 128 
 129                         ACPI_FREE(range_info);
 130                         return_VOID;
 131                 }
 132 
 133                 prev = range_info;
 134                 range_info = range_info->next;
 135         }
 136 
 137         return_VOID;
 138 }
 139 
 140 /*******************************************************************************
 141  *
 142  * FUNCTION:    acpi_ut_check_address_range
 143  *
 144  * PARAMETERS:  space_id            - Address space ID
 145  *              address             - Start address
 146  *              length              - Length of address range
 147  *              warn                - TRUE if warning on overlap desired
 148  *
 149  * RETURN:      Count of the number of conflicts detected. Zero is always
 150  *              returned for Space IDs other than Memory or I/O.
 151  *
 152  * DESCRIPTION: Check if the input address range overlaps any of the
 153  *              ASL operation region address ranges. The only supported
 154  *              Space IDs are Memory and I/O.
 155  *
 156  * MUTEX:       Assumes the namespace is locked.
 157  *
 158  ******************************************************************************/
 159 
 160 u32
 161 acpi_ut_check_address_range(acpi_adr_space_type space_id,
 162                             acpi_physical_address address, u32 length, u8 warn)
 163 {
 164         struct acpi_address_range *range_info;
 165         acpi_physical_address end_address;
 166         char *pathname;
 167         u32 overlap_count = 0;
 168 
 169         ACPI_FUNCTION_TRACE(ut_check_address_range);
 170 
 171         if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
 172             (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
 173                 return_UINT32(0);
 174         }
 175 
 176         range_info = acpi_gbl_address_range_list[space_id];
 177         end_address = address + length - 1;
 178 
 179         /* Check entire list for all possible conflicts */
 180 
 181         while (range_info) {
 182                 /*
 183                  * Check if the requested address/length overlaps this
 184                  * address range. There are four cases to consider:
 185                  *
 186                  * 1) Input address/length is contained completely in the
 187                  *    address range
 188                  * 2) Input address/length overlaps range at the range start
 189                  * 3) Input address/length overlaps range at the range end
 190                  * 4) Input address/length completely encompasses the range
 191                  */
 192                 if ((address <= range_info->end_address) &&
 193                     (end_address >= range_info->start_address)) {
 194 
 195                         /* Found an address range overlap */
 196 
 197                         overlap_count++;
 198                         if (warn) {     /* Optional warning message */
 199                                 pathname =
 200                                     acpi_ns_get_normalized_pathname(range_info->
 201                                                                     region_node,
 202                                                                     TRUE);
 203 
 204                                 ACPI_WARNING((AE_INFO,
 205                                               "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)",
 206                                               acpi_ut_get_region_name(space_id),
 207                                               ACPI_FORMAT_UINT64(address),
 208                                               ACPI_FORMAT_UINT64(end_address),
 209                                               ACPI_FORMAT_UINT64(range_info->
 210                                                                  start_address),
 211                                               ACPI_FORMAT_UINT64(range_info->
 212                                                                  end_address),
 213                                               pathname));
 214                                 ACPI_FREE(pathname);
 215                         }
 216                 }
 217 
 218                 range_info = range_info->next;
 219         }
 220 
 221         return_UINT32(overlap_count);
 222 }
 223 
 224 /*******************************************************************************
 225  *
 226  * FUNCTION:    acpi_ut_delete_address_lists
 227  *
 228  * PARAMETERS:  None
 229  *
 230  * RETURN:      None
 231  *
 232  * DESCRIPTION: Delete all global address range lists (called during
 233  *              subsystem shutdown).
 234  *
 235  ******************************************************************************/
 236 
 237 void acpi_ut_delete_address_lists(void)
 238 {
 239         struct acpi_address_range *next;
 240         struct acpi_address_range *range_info;
 241         int i;
 242 
 243         /* Delete all elements in all address range lists */
 244 
 245         for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
 246                 next = acpi_gbl_address_range_list[i];
 247 
 248                 while (next) {
 249                         range_info = next;
 250                         next = range_info->next;
 251                         ACPI_FREE(range_info);
 252                 }
 253 
 254                 acpi_gbl_address_range_list[i] = NULL;
 255         }
 256 }

/* [<][>][^][v][top][bottom][index][help] */