aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2012-01-12 00:10:32 -0500
committerLen Brown <len.brown@intel.com>2012-01-17 03:38:50 -0500
commitf654c0fefa8c16d439185b61442710fadc167e78 (patch)
treef6a375f7404e6a76f6eb24cc7d639f32b6789c7d /drivers
parentecafe6faa294697305453b5a6af7760b94622787 (diff)
ACPICA: Add support for region address conflict checking
Allows drivers to determine if any memory or I/O addresses will conflict with addresses used by ACPI operation regions. Introduces a new interface, acpi_check_address_range. http://marc.info/?t=132251388700002&r=1&w=2 Reported-and-tested-by: Luca Tettamanti <kronos.it@gmail.com> Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/acpica/Makefile1
-rw-r--r--drivers/acpi/acpica/acconfig.h4
-rw-r--r--drivers/acpi/acpica/acglobal.h2
-rw-r--r--drivers/acpi/acpica/aclocal.h9
-rw-r--r--drivers/acpi/acpica/acutils.h18
-rw-r--r--drivers/acpi/acpica/dsargs.c30
-rw-r--r--drivers/acpi/acpica/utaddress.c294
-rw-r--r--drivers/acpi/acpica/utdelete.c13
-rw-r--r--drivers/acpi/acpica/utglobal.c6
-rw-r--r--drivers/acpi/acpica/utinit.c1
-rw-r--r--drivers/acpi/acpica/utxface.c38
-rw-r--r--drivers/acpi/osl.c202
12 files changed, 403 insertions, 215 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 5f7d0cd1100..0ca208b6dcf 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -135,6 +135,7 @@ acpi-y += \
135 tbxfroot.o 135 tbxfroot.o
136 136
137acpi-y += \ 137acpi-y += \
138 utaddress.o \
138 utalloc.o \ 139 utalloc.o \
139 utcopy.o \ 140 utcopy.o \
140 utdebug.o \ 141 utdebug.o \
diff --git a/drivers/acpi/acpica/acconfig.h b/drivers/acpi/acpica/acconfig.h
index f467d49c1ac..4925aa5817f 100644
--- a/drivers/acpi/acpica/acconfig.h
+++ b/drivers/acpi/acpica/acconfig.h
@@ -123,6 +123,10 @@
123 123
124#define ACPI_MAX_SLEEP 2000 /* Two seconds */ 124#define ACPI_MAX_SLEEP 2000 /* Two seconds */
125 125
126/* Address Range lists are per-space_id (Memory and I/O only) */
127
128#define ACPI_ADDRESS_RANGE_MAX 2
129
126/****************************************************************************** 130/******************************************************************************
127 * 131 *
128 * ACPI Specification constants (Do not change unless the specification changes) 132 * ACPI Specification constants (Do not change unless the specification changes)
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 25912a93dea..dd5a3e34121 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -306,6 +306,8 @@ ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present;
306ACPI_EXTERN u8 acpi_gbl_events_initialized; 306ACPI_EXTERN u8 acpi_gbl_events_initialized;
307ACPI_EXTERN u8 acpi_gbl_osi_data; 307ACPI_EXTERN u8 acpi_gbl_osi_data;
308ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces; 308ACPI_EXTERN struct acpi_interface_info *acpi_gbl_supported_interfaces;
309ACPI_EXTERN struct acpi_address_range
310 *acpi_gbl_address_range_list[ACPI_ADDRESS_RANGE_MAX];
309 311
310#ifndef DEFINE_ACPI_GLOBALS 312#ifndef DEFINE_ACPI_GLOBALS
311 313
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h
index 2ddd61d07a0..d3b6f29cc41 100644
--- a/drivers/acpi/acpica/aclocal.h
+++ b/drivers/acpi/acpica/aclocal.h
@@ -630,6 +630,15 @@ union acpi_generic_state {
630 630
631typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state); 631typedef acpi_status(*ACPI_EXECUTE_OP) (struct acpi_walk_state * walk_state);
632 632
633/* Address Range info block */
634
635struct acpi_address_range {
636 struct acpi_address_range *next;
637 struct acpi_namespace_node *region_node;
638 acpi_physical_address start_address;
639 acpi_physical_address end_address;
640};
641
633/***************************************************************************** 642/*****************************************************************************
634 * 643 *
635 * Parser typedefs and structs 644 * Parser typedefs and structs
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index ab95d452f87..57df29360b9 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -580,6 +580,24 @@ acpi_ut_create_list(char *list_name,
580#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ 580#endif /* ACPI_DBG_TRACK_ALLOCATIONS */
581 581
582/* 582/*
583 * utaddress - address range check
584 */
585acpi_status
586acpi_ut_add_address_range(acpi_adr_space_type space_id,
587 acpi_physical_address address,
588 u32 length, struct acpi_namespace_node *region_node);
589
590void
591acpi_ut_remove_address_range(acpi_adr_space_type space_id,
592 struct acpi_namespace_node *region_node);
593
594u32
595acpi_ut_check_address_range(acpi_adr_space_type space_id,
596 acpi_physical_address address, u32 length, u8 warn);
597
598void acpi_ut_delete_address_lists(void);
599
600/*
583 * utxferror - various error/warning output functions 601 * utxferror - various error/warning output functions
584 */ 602 */
585void ACPI_INTERNAL_VAR_XFACE 603void ACPI_INTERNAL_VAR_XFACE
diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c
index d69e4a53175..19c2be941e7 100644
--- a/drivers/acpi/acpica/dsargs.c
+++ b/drivers/acpi/acpica/dsargs.c
@@ -250,6 +250,13 @@ acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
250 status = acpi_ds_execute_arguments(node, node->parent, 250 status = acpi_ds_execute_arguments(node, node->parent,
251 extra_desc->extra.aml_length, 251 extra_desc->extra.aml_length,
252 extra_desc->extra.aml_start); 252 extra_desc->extra.aml_start);
253 if (ACPI_FAILURE(status)) {
254 return_ACPI_STATUS(status);
255 }
256
257 status = acpi_ut_add_address_range(obj_desc->region.space_id,
258 obj_desc->region.address,
259 obj_desc->region.length, node);
253 return_ACPI_STATUS(status); 260 return_ACPI_STATUS(status);
254} 261}
255 262
@@ -391,25 +398,8 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
391 return_ACPI_STATUS(status); 398 return_ACPI_STATUS(status);
392 } 399 }
393 400
394 /* Validate the region address/length via the host OS */ 401 status = acpi_ut_add_address_range(obj_desc->region.space_id,
395 402 obj_desc->region.address,
396 status = acpi_os_validate_address(obj_desc->region.space_id, 403 obj_desc->region.length, node);
397 obj_desc->region.address,
398 (acpi_size) obj_desc->region.length,
399 acpi_ut_get_node_name(node));
400
401 if (ACPI_FAILURE(status)) {
402 /*
403 * Invalid address/length. We will emit an error message and mark
404 * the region as invalid, so that it will cause an additional error if
405 * it is ever used. Then return AE_OK.
406 */
407 ACPI_EXCEPTION((AE_INFO, status,
408 "During address validation of OpRegion [%4.4s]",
409 node->name.ascii));
410 obj_desc->common.flags |= AOPOBJ_INVALID;
411 status = AE_OK;
412 }
413
414 return_ACPI_STATUS(status); 404 return_ACPI_STATUS(status);
415} 405}
diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c
new file mode 100644
index 00000000000..67932aebe6d
--- /dev/null
+++ b/drivers/acpi/acpica/utaddress.c
@@ -0,0 +1,294 @@
1/******************************************************************************
2 *
3 * Module Name: utaddress - op_region address range check
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2012, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46#include "acnamesp.h"
47
48#define _COMPONENT ACPI_UTILITIES
49ACPI_MODULE_NAME("utaddress")
50
51/*******************************************************************************
52 *
53 * FUNCTION: acpi_ut_add_address_range
54 *
55 * PARAMETERS: space_id - Address space ID
56 * Address - op_region start address
57 * Length - op_region length
58 * region_node - op_region namespace node
59 *
60 * RETURN: Status
61 *
62 * DESCRIPTION: Add the Operation Region address range to the global list.
63 * The only supported Space IDs are Memory and I/O. Called when
64 * the op_region address/length operands are fully evaluated.
65 *
66 * MUTEX: Locks the namespace
67 *
68 * NOTE: Because this interface is only called when an op_region argument
69 * list is evaluated, there cannot be any duplicate region_nodes.
70 * Duplicate Address/Length values are allowed, however, so that multiple
71 * address conflicts can be detected.
72 *
73 ******************************************************************************/
74acpi_status
75acpi_ut_add_address_range(acpi_adr_space_type space_id,
76 acpi_physical_address address,
77 u32 length, struct acpi_namespace_node *region_node)
78{
79 struct acpi_address_range *range_info;
80 acpi_status status;
81
82 ACPI_FUNCTION_TRACE(ut_add_address_range);
83
84 if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
85 (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
86 return_ACPI_STATUS(AE_OK);
87 }
88
89 /* Allocate/init a new info block, add it to the appropriate list */
90
91 range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));
92 if (!range_info) {
93 return_ACPI_STATUS(AE_NO_MEMORY);
94 }
95
96 range_info->start_address = address;
97 range_info->end_address = (address + length - 1);
98 range_info->region_node = region_node;
99
100 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
101 if (ACPI_FAILURE(status)) {
102 ACPI_FREE(range_info);
103 return_ACPI_STATUS(status);
104 }
105
106 range_info->next = acpi_gbl_address_range_list[space_id];
107 acpi_gbl_address_range_list[space_id] = range_info;
108
109 ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
110 "\nAdded [%4.4s] address range: 0x%p-0x%p\n",
111 acpi_ut_get_node_name(range_info->region_node),
112 ACPI_CAST_PTR(void, address),
113 ACPI_CAST_PTR(void, range_info->end_address)));
114
115 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
116 return_ACPI_STATUS(AE_OK);
117}
118
119/*******************************************************************************
120 *
121 * FUNCTION: acpi_ut_remove_address_range
122 *
123 * PARAMETERS: space_id - Address space ID
124 * region_node - op_region namespace node
125 *
126 * RETURN: None
127 *
128 * DESCRIPTION: Remove the Operation Region from the global list. The only
129 * supported Space IDs are Memory and I/O. Called when an
130 * op_region is deleted.
131 *
132 * MUTEX: Assumes the namespace is locked
133 *
134 ******************************************************************************/
135
136void
137acpi_ut_remove_address_range(acpi_adr_space_type space_id,
138 struct acpi_namespace_node *region_node)
139{
140 struct acpi_address_range *range_info;
141 struct acpi_address_range *prev;
142
143 ACPI_FUNCTION_TRACE(ut_remove_address_range);
144
145 if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
146 (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
147 return_VOID;
148 }
149
150 /* Get the appropriate list head and check the list */
151
152 range_info = prev = acpi_gbl_address_range_list[space_id];
153 while (range_info) {
154 if (range_info->region_node == region_node) {
155 if (range_info == prev) { /* Found at list head */
156 acpi_gbl_address_range_list[space_id] =
157 range_info->next;
158 } else {
159 prev->next = range_info->next;
160 }
161
162 ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
163 "\nRemoved [%4.4s] address range: 0x%p-0x%p\n",
164 acpi_ut_get_node_name(range_info->
165 region_node),
166 ACPI_CAST_PTR(void,
167 range_info->
168 start_address),
169 ACPI_CAST_PTR(void,
170 range_info->
171 end_address)));
172
173 ACPI_FREE(range_info);
174 return_VOID;
175 }
176
177 prev = range_info;
178 range_info = range_info->next;
179 }
180
181 return_VOID;
182}
183
184/*******************************************************************************
185 *
186 * FUNCTION: acpi_ut_check_address_range
187 *
188 * PARAMETERS: space_id - Address space ID
189 * Address - Start address
190 * Length - Length of address range
191 * Warn - TRUE if warning on overlap desired
192 *
193 * RETURN: Count of the number of conflicts detected. Zero is always
194 * returned for Space IDs other than Memory or I/O.
195 *
196 * DESCRIPTION: Check if the input address range overlaps any of the
197 * ASL operation region address ranges. The only supported
198 * Space IDs are Memory and I/O.
199 *
200 * MUTEX: Assumes the namespace is locked.
201 *
202 ******************************************************************************/
203
204u32
205acpi_ut_check_address_range(acpi_adr_space_type space_id,
206 acpi_physical_address address, u32 length, u8 warn)
207{
208 struct acpi_address_range *range_info;
209 acpi_physical_address end_address;
210 char *pathname;
211 u32 overlap_count = 0;
212
213 ACPI_FUNCTION_TRACE(ut_check_address_range);
214
215 if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
216 (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
217 return_UINT32(0);
218 }
219
220 range_info = acpi_gbl_address_range_list[space_id];
221 end_address = address + length - 1;
222
223 /* Check entire list for all possible conflicts */
224
225 while (range_info) {
226 /*
227 * Check if the requested Address/Length overlaps this address_range.
228 * Four cases to consider:
229 *
230 * 1) Input address/length is contained completely in the address range
231 * 2) Input address/length overlaps range at the range start
232 * 3) Input address/length overlaps range at the range end
233 * 4) Input address/length completely encompasses the range
234 */
235 if ((address <= range_info->end_address) &&
236 (end_address >= range_info->start_address)) {
237
238 /* Found an address range overlap */
239
240 overlap_count++;
241 if (warn) { /* Optional warning message */
242 pathname =
243 acpi_ns_get_external_pathname(range_info->
244 region_node);
245
246 ACPI_WARNING((AE_INFO,
247 "0x%p-0x%p %s conflicts with Region %s %d",
248 ACPI_CAST_PTR(void, address),
249 ACPI_CAST_PTR(void, end_address),
250 acpi_ut_get_region_name(space_id),
251 pathname, overlap_count));
252 ACPI_FREE(pathname);
253 }
254 }
255
256 range_info = range_info->next;
257 }
258
259 return_UINT32(overlap_count);
260}
261
262/*******************************************************************************
263 *
264 * FUNCTION: acpi_ut_delete_address_lists
265 *
266 * PARAMETERS: None
267 *
268 * RETURN: None
269 *
270 * DESCRIPTION: Delete all global address range lists (called during
271 * subsystem shutdown).
272 *
273 ******************************************************************************/
274
275void acpi_ut_delete_address_lists(void)
276{
277 struct acpi_address_range *next;
278 struct acpi_address_range *range_info;
279 int i;
280
281 /* Delete all elements in all address range lists */
282
283 for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
284 next = acpi_gbl_address_range_list[i];
285
286 while (next) {
287 range_info = next;
288 next = range_info->next;
289 ACPI_FREE(range_info);
290 }
291
292 acpi_gbl_address_range_list[i] = NULL;
293 }
294}
diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c
index 31f5a7832ef..93ec06b0fe2 100644
--- a/drivers/acpi/acpica/utdelete.c
+++ b/drivers/acpi/acpica/utdelete.c
@@ -215,11 +215,14 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
215 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 215 ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
216 "***** Region %p\n", object)); 216 "***** Region %p\n", object));
217 217
218 /* Invalidate the region address/length via the host OS */ 218 /*
219 219 * Update address_range list. However, only permanent regions
220 acpi_os_invalidate_address(object->region.space_id, 220 * are installed in this list. (Not created within a method)
221 object->region.address, 221 */
222 (acpi_size) object->region.length); 222 if (!(object->region.node->flags & ANOBJ_TEMPORARY)) {
223 acpi_ut_remove_address_range(object->region.space_id,
224 object->region.node);
225 }
223 226
224 second_desc = acpi_ns_get_secondary_object(object); 227 second_desc = acpi_ns_get_secondary_object(object);
225 if (second_desc) { 228 if (second_desc) {
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index ffba0a39c3e..3cf758bab24 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -264,6 +264,12 @@ acpi_status acpi_ut_init_globals(void)
264 return_ACPI_STATUS(status); 264 return_ACPI_STATUS(status);
265 } 265 }
266 266
267 /* Address Range lists */
268
269 for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
270 acpi_gbl_address_range_list[i] = NULL;
271 }
272
267 /* Mutex locked flags */ 273 /* Mutex locked flags */
268 274
269 for (i = 0; i < ACPI_NUM_MUTEX; i++) { 275 for (i = 0; i < ACPI_NUM_MUTEX; i++) {
diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c
index 191b6828cce..cab61a05d21 100644
--- a/drivers/acpi/acpica/utinit.c
+++ b/drivers/acpi/acpica/utinit.c
@@ -92,6 +92,7 @@ static void acpi_ut_terminate(void)
92 gpe_xrupt_info = next_gpe_xrupt_info; 92 gpe_xrupt_info = next_gpe_xrupt_info;
93 } 93 }
94 94
95 acpi_ut_delete_address_lists();
95 return_VOID; 96 return_VOID;
96} 97}
97 98
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 420ebfe08c7..15cbddebb6b 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -48,6 +48,7 @@
48#include "acnamesp.h" 48#include "acnamesp.h"
49#include "acdebug.h" 49#include "acdebug.h"
50#include "actables.h" 50#include "actables.h"
51#include "acinterp.h"
51 52
52#define _COMPONENT ACPI_UTILITIES 53#define _COMPONENT ACPI_UTILITIES
53ACPI_MODULE_NAME("utxface") 54ACPI_MODULE_NAME("utxface")
@@ -640,4 +641,41 @@ acpi_status acpi_install_interface_handler(acpi_interface_handler handler)
640} 641}
641 642
642ACPI_EXPORT_SYMBOL(acpi_install_interface_handler) 643ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)
644
645/*****************************************************************************
646 *
647 * FUNCTION: acpi_check_address_range
648 *
649 * PARAMETERS: space_id - Address space ID
650 * Address - Start address
651 * Length - Length
652 * Warn - TRUE if warning on overlap desired
653 *
654 * RETURN: Count of the number of conflicts detected.
655 *
656 * DESCRIPTION: Check if the input address range overlaps any of the
657 * ASL operation region address ranges.
658 *
659 ****************************************************************************/
660u32
661acpi_check_address_range(acpi_adr_space_type space_id,
662 acpi_physical_address address,
663 acpi_size length, u8 warn)
664{
665 u32 overlaps;
666 acpi_status status;
667
668 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
669 if (ACPI_FAILURE(status)) {
670 return (0);
671 }
672
673 overlaps = acpi_ut_check_address_range(space_id, address,
674 (u32)length, warn);
675
676 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
677 return (overlaps);
678}
679
680ACPI_EXPORT_SYMBOL(acpi_check_address_range)
643#endif /* !ACPI_ASL_COMPILER */ 681#endif /* !ACPI_ASL_COMPILER */
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index f31c5c5f1b7..3e57fbdf50a 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -83,19 +83,6 @@ static struct workqueue_struct *kacpi_notify_wq;
83struct workqueue_struct *kacpi_hotplug_wq; 83struct workqueue_struct *kacpi_hotplug_wq;
84EXPORT_SYMBOL(kacpi_hotplug_wq); 84EXPORT_SYMBOL(kacpi_hotplug_wq);
85 85
86struct acpi_res_list {
87 resource_size_t start;
88 resource_size_t end;
89 acpi_adr_space_type resource_type; /* IO port, System memory, ...*/
90 char name[5]; /* only can have a length of 4 chars, make use of this
91 one instead of res->name, no need to kalloc then */
92 struct list_head resource_list;
93 int count;
94};
95
96static LIST_HEAD(resource_list_head);
97static DEFINE_SPINLOCK(acpi_res_lock);
98
99/* 86/*
100 * This list of permanent mappings is for memory that may be accessed from 87 * This list of permanent mappings is for memory that may be accessed from
101 * interrupt context, where we can't do the ioremap(). 88 * interrupt context, where we can't do the ioremap().
@@ -1278,44 +1265,28 @@ __setup("acpi_enforce_resources=", acpi_enforce_resources_setup);
1278 * drivers */ 1265 * drivers */
1279int acpi_check_resource_conflict(const struct resource *res) 1266int acpi_check_resource_conflict(const struct resource *res)
1280{ 1267{
1281 struct acpi_res_list *res_list_elem; 1268 acpi_adr_space_type space_id;
1282 int ioport = 0, clash = 0; 1269 acpi_size length;
1270 u8 warn = 0;
1271 int clash = 0;
1283 1272
1284 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) 1273 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1285 return 0; 1274 return 0;
1286 if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM)) 1275 if (!(res->flags & IORESOURCE_IO) && !(res->flags & IORESOURCE_MEM))
1287 return 0; 1276 return 0;
1288 1277
1289 ioport = res->flags & IORESOURCE_IO; 1278 if (res->flags & IORESOURCE_IO)
1290 1279 space_id = ACPI_ADR_SPACE_SYSTEM_IO;
1291 spin_lock(&acpi_res_lock); 1280 else
1292 list_for_each_entry(res_list_elem, &resource_list_head, 1281 space_id = ACPI_ADR_SPACE_SYSTEM_MEMORY;
1293 resource_list) {
1294 if (ioport && (res_list_elem->resource_type
1295 != ACPI_ADR_SPACE_SYSTEM_IO))
1296 continue;
1297 if (!ioport && (res_list_elem->resource_type
1298 != ACPI_ADR_SPACE_SYSTEM_MEMORY))
1299 continue;
1300 1282
1301 if (res->end < res_list_elem->start 1283 length = res->end - res->start + 1;
1302 || res_list_elem->end < res->start) 1284 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO)
1303 continue; 1285 warn = 1;
1304 clash = 1; 1286 clash = acpi_check_address_range(space_id, res->start, length, warn);
1305 break;
1306 }
1307 spin_unlock(&acpi_res_lock);
1308 1287
1309 if (clash) { 1288 if (clash) {
1310 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) { 1289 if (acpi_enforce_resources != ENFORCE_RESOURCES_NO) {
1311 printk(KERN_WARNING "ACPI: resource %s %pR"
1312 " conflicts with ACPI region %s "
1313 "[%s 0x%zx-0x%zx]\n",
1314 res->name, res, res_list_elem->name,
1315 (res_list_elem->resource_type ==
1316 ACPI_ADR_SPACE_SYSTEM_IO) ? "io" : "mem",
1317 (size_t) res_list_elem->start,
1318 (size_t) res_list_elem->end);
1319 if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX) 1290 if (acpi_enforce_resources == ENFORCE_RESOURCES_LAX)
1320 printk(KERN_NOTICE "ACPI: This conflict may" 1291 printk(KERN_NOTICE "ACPI: This conflict may"
1321 " cause random problems and system" 1292 " cause random problems and system"
@@ -1467,155 +1438,6 @@ acpi_status acpi_os_release_object(acpi_cache_t * cache, void *object)
1467 kmem_cache_free(cache, object); 1438 kmem_cache_free(cache, object);
1468 return (AE_OK); 1439 return (AE_OK);
1469} 1440}
1470
1471static inline int acpi_res_list_add(struct acpi_res_list *res)
1472{
1473 struct acpi_res_list *res_list_elem;
1474
1475 list_for_each_entry(res_list_elem, &resource_list_head,
1476 resource_list) {
1477
1478 if (res->resource_type == res_list_elem->resource_type &&
1479 res->start == res_list_elem->start &&
1480 res->end == res_list_elem->end) {
1481
1482 /*
1483 * The Region(addr,len) already exist in the list,
1484 * just increase the count
1485 */
1486
1487 res_list_elem->count++;
1488 return 0;
1489 }
1490 }
1491
1492 res->count = 1;
1493 list_add(&res->resource_list, &resource_list_head);
1494 return 1;
1495}
1496
1497static inline void acpi_res_list_del(struct acpi_res_list *res)
1498{
1499 struct acpi_res_list *res_list_elem;
1500
1501 list_for_each_entry(res_list_elem, &resource_list_head,
1502 resource_list) {
1503
1504 if (res->resource_type == res_list_elem->resource_type &&
1505 res->start == res_list_elem->start &&
1506 res->end == res_list_elem->end) {
1507
1508 /*
1509 * If the res count is decreased to 0,
1510 * remove and free it
1511 */
1512
1513 if (--res_list_elem->count == 0) {
1514 list_del(&res_list_elem->resource_list);
1515 kfree(res_list_elem);
1516 }
1517 return;
1518 }
1519 }
1520}
1521
1522acpi_status
1523acpi_os_invalidate_address(
1524 u8 space_id,
1525 acpi_physical_address address,
1526 acpi_size length)
1527{
1528 struct acpi_res_list res;
1529
1530 switch (space_id) {
1531 case ACPI_ADR_SPACE_SYSTEM_IO:
1532 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1533 /* Only interference checks against SystemIO and SystemMemory
1534 are needed */
1535 res.start = address;
1536 res.end = address + length - 1;
1537 res.resource_type = space_id;
1538 spin_lock(&acpi_res_lock);
1539 acpi_res_list_del(&res);
1540 spin_unlock(&acpi_res_lock);
1541 break;
1542 case ACPI_ADR_SPACE_PCI_CONFIG:
1543 case ACPI_ADR_SPACE_EC:
1544 case ACPI_ADR_SPACE_SMBUS:
1545 case ACPI_ADR_SPACE_CMOS:
1546 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1547 case ACPI_ADR_SPACE_DATA_TABLE:
1548 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1549 break;
1550 }
1551 return AE_OK;
1552}
1553
1554/******************************************************************************
1555 *
1556 * FUNCTION: acpi_os_validate_address
1557 *
1558 * PARAMETERS: space_id - ACPI space ID
1559 * address - Physical address
1560 * length - Address length
1561 *
1562 * RETURN: AE_OK if address/length is valid for the space_id. Otherwise,
1563 * should return AE_AML_ILLEGAL_ADDRESS.
1564 *
1565 * DESCRIPTION: Validate a system address via the host OS. Used to validate
1566 * the addresses accessed by AML operation regions.
1567 *
1568 *****************************************************************************/
1569
1570acpi_status
1571acpi_os_validate_address (
1572 u8 space_id,
1573 acpi_physical_address address,
1574 acpi_size length,
1575 char *name)
1576{
1577 struct acpi_res_list *res;
1578 int added;
1579 if (acpi_enforce_resources == ENFORCE_RESOURCES_NO)
1580 return AE_OK;
1581
1582 switch (space_id) {
1583 case ACPI_ADR_SPACE_SYSTEM_IO:
1584 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1585 /* Only interference checks against SystemIO and SystemMemory
1586 are needed */
1587 res = kzalloc(sizeof(struct acpi_res_list), GFP_KERNEL);
1588 if (!res)
1589 return AE_OK;
1590 /* ACPI names are fixed to 4 bytes, still better use strlcpy */
1591 strlcpy(res->name, name, 5);
1592 res->start = address;
1593 res->end = address + length - 1;
1594 res->resource_type = space_id;
1595 spin_lock(&acpi_res_lock);
1596 added = acpi_res_list_add(res);
1597 spin_unlock(&acpi_res_lock);
1598 pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, "
1599 "name: %s\n", added ? "Added" : "Already exist",
1600 (space_id == ACPI_ADR_SPACE_SYSTEM_IO)
1601 ? "SystemIO" : "System Memory",
1602 (unsigned long long)res->start,
1603 (unsigned long long)res->end,
1604 res->name);
1605 if (!added)
1606 kfree(res);
1607 break;
1608 case ACPI_ADR_SPACE_PCI_CONFIG:
1609 case ACPI_ADR_SPACE_EC:
1610 case ACPI_ADR_SPACE_SMBUS:
1611 case ACPI_ADR_SPACE_CMOS:
1612 case ACPI_ADR_SPACE_PCI_BAR_TARGET:
1613 case ACPI_ADR_SPACE_DATA_TABLE:
1614 case ACPI_ADR_SPACE_FIXED_HARDWARE:
1615 break;
1616 }
1617 return AE_OK;
1618}
1619#endif 1441#endif
1620 1442
1621acpi_status __init acpi_os_initialize(void) 1443acpi_status __init acpi_os_initialize(void)