Linux Audio

Check our new training course

Loading...
v5.9
  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 - 2020, Intel Corp.
  7 *
  8 *****************************************************************************/
  9
 10#include <acpi/acpi.h>
 11#include "accommon.h"
 12#include "acnamesp.h"
 13
 14#define _COMPONENT          ACPI_UTILITIES
 15ACPI_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 ******************************************************************************/
 40acpi_status
 41acpi_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
 94void
 95acpi_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
160u32
161acpi_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
237void 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}
v5.14.15
  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 - 2021, Intel Corp.
  7 *
  8 *****************************************************************************/
  9
 10#include <acpi/acpi.h>
 11#include "accommon.h"
 12#include "acnamesp.h"
 13
 14#define _COMPONENT          ACPI_UTILITIES
 15ACPI_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 ******************************************************************************/
 40acpi_status
 41acpi_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
 94void
 95acpi_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
160u32
161acpi_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
237void 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}