diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-10 10:05:16 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-02-10 10:05:16 -0500 |
commit | 8fbcf5ecb336eb6da560f08d60e95b51d318795c (patch) | |
tree | 77a1b947838d60edd0e81d37327985de2e842b68 /drivers/acpi/resource.c | |
parent | d23209680291dad6c79f1a6f187697c3884d554d (diff) | |
parent | 5c493df25a0d9e0c3bda742250ecfc5953bf4ccd (diff) |
Merge branch 'acpi-resources'
* acpi-resources: (23 commits)
Merge branch 'pci/host-generic' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci into acpi-resources
x86/irq, ACPI: Implement ACPI driver to support IOAPIC hotplug
ACPI: Add interfaces to parse IOAPIC ID for IOAPIC hotplug
x86/PCI: Refine the way to release PCI IRQ resources
x86/PCI/ACPI: Use common ACPI resource interfaces to simplify implementation
x86/PCI: Fix the range check for IO resources
PCI: Use common resource list management code instead of private implementation
resources: Move struct resource_list_entry from ACPI into resource core
ACPI: Introduce helper function acpi_dev_filter_resource_type()
ACPI: Add field offset to struct resource_list_entry
ACPI: Translate resource into master side address for bridge window resources
ACPI: Return translation offset when parsing ACPI address space resources
ACPI: Enforce stricter checks for address space descriptors
ACPI: Set flag IORESOURCE_UNSET for unassigned resources
ACPI: Normalize return value of resource parser functions
ACPI: Fix a bug in parsing ACPI Memory24 resource
ACPI: Add prefetch decoding to the address space parser
ACPI: Move the window flag logic to the combined parser
ACPI: Unify the parsing of address_space and ext_address_space
ACPI: Let the parser return false for disabled resources
...
Diffstat (limited to 'drivers/acpi/resource.c')
-rw-r--r-- | drivers/acpi/resource.c | 353 |
1 files changed, 217 insertions, 136 deletions
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index d0a4d90c6bcc..4752b9939987 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c | |||
@@ -34,21 +34,34 @@ | |||
34 | #define valid_IRQ(i) (true) | 34 | #define valid_IRQ(i) (true) |
35 | #endif | 35 | #endif |
36 | 36 | ||
37 | static unsigned long acpi_dev_memresource_flags(u64 len, u8 write_protect, | 37 | static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io) |
38 | bool window) | ||
39 | { | 38 | { |
40 | unsigned long flags = IORESOURCE_MEM; | 39 | u64 reslen = end - start + 1; |
41 | 40 | ||
42 | if (len == 0) | 41 | /* |
43 | flags |= IORESOURCE_DISABLED; | 42 | * CHECKME: len might be required to check versus a minimum |
43 | * length as well. 1 for io is fine, but for memory it does | ||
44 | * not make any sense at all. | ||
45 | */ | ||
46 | if (len && reslen && reslen == len && start <= end) | ||
47 | return true; | ||
44 | 48 | ||
45 | if (write_protect == ACPI_READ_WRITE_MEMORY) | 49 | pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n", |
46 | flags |= IORESOURCE_MEM_WRITEABLE; | 50 | io ? "io" : "mem", start, end, len); |
51 | |||
52 | return false; | ||
53 | } | ||
54 | |||
55 | static void acpi_dev_memresource_flags(struct resource *res, u64 len, | ||
56 | u8 write_protect) | ||
57 | { | ||
58 | res->flags = IORESOURCE_MEM; | ||
47 | 59 | ||
48 | if (window) | 60 | if (!acpi_dev_resource_len_valid(res->start, res->end, len, false)) |
49 | flags |= IORESOURCE_WINDOW; | 61 | res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; |
50 | 62 | ||
51 | return flags; | 63 | if (write_protect == ACPI_READ_WRITE_MEMORY) |
64 | res->flags |= IORESOURCE_MEM_WRITEABLE; | ||
52 | } | 65 | } |
53 | 66 | ||
54 | static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, | 67 | static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, |
@@ -56,7 +69,7 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, | |||
56 | { | 69 | { |
57 | res->start = start; | 70 | res->start = start; |
58 | res->end = start + len - 1; | 71 | res->end = start + len - 1; |
59 | res->flags = acpi_dev_memresource_flags(len, write_protect, false); | 72 | acpi_dev_memresource_flags(res, len, write_protect); |
60 | } | 73 | } |
61 | 74 | ||
62 | /** | 75 | /** |
@@ -67,6 +80,11 @@ static void acpi_dev_get_memresource(struct resource *res, u64 start, u64 len, | |||
67 | * Check if the given ACPI resource object represents a memory resource and | 80 | * Check if the given ACPI resource object represents a memory resource and |
68 | * if that's the case, use the information in it to populate the generic | 81 | * if that's the case, use the information in it to populate the generic |
69 | * resource object pointed to by @res. | 82 | * resource object pointed to by @res. |
83 | * | ||
84 | * Return: | ||
85 | * 1) false with res->flags setting to zero: not the expected resource type | ||
86 | * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource | ||
87 | * 3) true: valid assigned resource | ||
70 | */ | 88 | */ |
71 | bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | 89 | bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) |
72 | { | 90 | { |
@@ -77,60 +95,52 @@ bool acpi_dev_resource_memory(struct acpi_resource *ares, struct resource *res) | |||
77 | switch (ares->type) { | 95 | switch (ares->type) { |
78 | case ACPI_RESOURCE_TYPE_MEMORY24: | 96 | case ACPI_RESOURCE_TYPE_MEMORY24: |
79 | memory24 = &ares->data.memory24; | 97 | memory24 = &ares->data.memory24; |
80 | if (!memory24->minimum && !memory24->address_length) | 98 | acpi_dev_get_memresource(res, memory24->minimum << 8, |
81 | return false; | 99 | memory24->address_length << 8, |
82 | acpi_dev_get_memresource(res, memory24->minimum, | ||
83 | memory24->address_length, | ||
84 | memory24->write_protect); | 100 | memory24->write_protect); |
85 | break; | 101 | break; |
86 | case ACPI_RESOURCE_TYPE_MEMORY32: | 102 | case ACPI_RESOURCE_TYPE_MEMORY32: |
87 | memory32 = &ares->data.memory32; | 103 | memory32 = &ares->data.memory32; |
88 | if (!memory32->minimum && !memory32->address_length) | ||
89 | return false; | ||
90 | acpi_dev_get_memresource(res, memory32->minimum, | 104 | acpi_dev_get_memresource(res, memory32->minimum, |
91 | memory32->address_length, | 105 | memory32->address_length, |
92 | memory32->write_protect); | 106 | memory32->write_protect); |
93 | break; | 107 | break; |
94 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | 108 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: |
95 | fixed_memory32 = &ares->data.fixed_memory32; | 109 | fixed_memory32 = &ares->data.fixed_memory32; |
96 | if (!fixed_memory32->address && !fixed_memory32->address_length) | ||
97 | return false; | ||
98 | acpi_dev_get_memresource(res, fixed_memory32->address, | 110 | acpi_dev_get_memresource(res, fixed_memory32->address, |
99 | fixed_memory32->address_length, | 111 | fixed_memory32->address_length, |
100 | fixed_memory32->write_protect); | 112 | fixed_memory32->write_protect); |
101 | break; | 113 | break; |
102 | default: | 114 | default: |
115 | res->flags = 0; | ||
103 | return false; | 116 | return false; |
104 | } | 117 | } |
105 | return true; | 118 | |
119 | return !(res->flags & IORESOURCE_DISABLED); | ||
106 | } | 120 | } |
107 | EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); | 121 | EXPORT_SYMBOL_GPL(acpi_dev_resource_memory); |
108 | 122 | ||
109 | static unsigned int acpi_dev_ioresource_flags(u64 start, u64 end, u8 io_decode, | 123 | static void acpi_dev_ioresource_flags(struct resource *res, u64 len, |
110 | bool window) | 124 | u8 io_decode) |
111 | { | 125 | { |
112 | int flags = IORESOURCE_IO; | 126 | res->flags = IORESOURCE_IO; |
113 | 127 | ||
114 | if (io_decode == ACPI_DECODE_16) | 128 | if (!acpi_dev_resource_len_valid(res->start, res->end, len, true)) |
115 | flags |= IORESOURCE_IO_16BIT_ADDR; | 129 | res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; |
116 | 130 | ||
117 | if (start > end || end >= 0x10003) | 131 | if (res->end >= 0x10003) |
118 | flags |= IORESOURCE_DISABLED; | 132 | res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET; |
119 | 133 | ||
120 | if (window) | 134 | if (io_decode == ACPI_DECODE_16) |
121 | flags |= IORESOURCE_WINDOW; | 135 | res->flags |= IORESOURCE_IO_16BIT_ADDR; |
122 | |||
123 | return flags; | ||
124 | } | 136 | } |
125 | 137 | ||
126 | static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, | 138 | static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, |
127 | u8 io_decode) | 139 | u8 io_decode) |
128 | { | 140 | { |
129 | u64 end = start + len - 1; | ||
130 | |||
131 | res->start = start; | 141 | res->start = start; |
132 | res->end = end; | 142 | res->end = start + len - 1; |
133 | res->flags = acpi_dev_ioresource_flags(start, end, io_decode, false); | 143 | acpi_dev_ioresource_flags(res, len, io_decode); |
134 | } | 144 | } |
135 | 145 | ||
136 | /** | 146 | /** |
@@ -141,6 +151,11 @@ static void acpi_dev_get_ioresource(struct resource *res, u64 start, u64 len, | |||
141 | * Check if the given ACPI resource object represents an I/O resource and | 151 | * Check if the given ACPI resource object represents an I/O resource and |
142 | * if that's the case, use the information in it to populate the generic | 152 | * if that's the case, use the information in it to populate the generic |
143 | * resource object pointed to by @res. | 153 | * resource object pointed to by @res. |
154 | * | ||
155 | * Return: | ||
156 | * 1) false with res->flags setting to zero: not the expected resource type | ||
157 | * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource | ||
158 | * 3) true: valid assigned resource | ||
144 | */ | 159 | */ |
145 | bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | 160 | bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) |
146 | { | 161 | { |
@@ -150,135 +165,143 @@ bool acpi_dev_resource_io(struct acpi_resource *ares, struct resource *res) | |||
150 | switch (ares->type) { | 165 | switch (ares->type) { |
151 | case ACPI_RESOURCE_TYPE_IO: | 166 | case ACPI_RESOURCE_TYPE_IO: |
152 | io = &ares->data.io; | 167 | io = &ares->data.io; |
153 | if (!io->minimum && !io->address_length) | ||
154 | return false; | ||
155 | acpi_dev_get_ioresource(res, io->minimum, | 168 | acpi_dev_get_ioresource(res, io->minimum, |
156 | io->address_length, | 169 | io->address_length, |
157 | io->io_decode); | 170 | io->io_decode); |
158 | break; | 171 | break; |
159 | case ACPI_RESOURCE_TYPE_FIXED_IO: | 172 | case ACPI_RESOURCE_TYPE_FIXED_IO: |
160 | fixed_io = &ares->data.fixed_io; | 173 | fixed_io = &ares->data.fixed_io; |
161 | if (!fixed_io->address && !fixed_io->address_length) | ||
162 | return false; | ||
163 | acpi_dev_get_ioresource(res, fixed_io->address, | 174 | acpi_dev_get_ioresource(res, fixed_io->address, |
164 | fixed_io->address_length, | 175 | fixed_io->address_length, |
165 | ACPI_DECODE_10); | 176 | ACPI_DECODE_10); |
166 | break; | 177 | break; |
167 | default: | 178 | default: |
179 | res->flags = 0; | ||
168 | return false; | 180 | return false; |
169 | } | 181 | } |
170 | return true; | 182 | |
183 | return !(res->flags & IORESOURCE_DISABLED); | ||
171 | } | 184 | } |
172 | EXPORT_SYMBOL_GPL(acpi_dev_resource_io); | 185 | EXPORT_SYMBOL_GPL(acpi_dev_resource_io); |
173 | 186 | ||
174 | /** | 187 | static bool acpi_decode_space(struct resource_win *win, |
175 | * acpi_dev_resource_address_space - Extract ACPI address space information. | 188 | struct acpi_resource_address *addr, |
176 | * @ares: Input ACPI resource object. | 189 | struct acpi_address64_attribute *attr) |
177 | * @res: Output generic resource object. | ||
178 | * | ||
179 | * Check if the given ACPI resource object represents an address space resource | ||
180 | * and if that's the case, use the information in it to populate the generic | ||
181 | * resource object pointed to by @res. | ||
182 | */ | ||
183 | bool acpi_dev_resource_address_space(struct acpi_resource *ares, | ||
184 | struct resource *res) | ||
185 | { | 190 | { |
186 | acpi_status status; | 191 | u8 iodec = attr->granularity == 0xfff ? ACPI_DECODE_10 : ACPI_DECODE_16; |
187 | struct acpi_resource_address64 addr; | 192 | bool wp = addr->info.mem.write_protect; |
188 | bool window; | 193 | u64 len = attr->address_length; |
189 | u64 len; | 194 | struct resource *res = &win->res; |
190 | u8 io_decode; | ||
191 | 195 | ||
192 | switch (ares->type) { | 196 | /* |
193 | case ACPI_RESOURCE_TYPE_ADDRESS16: | 197 | * Filter out invalid descriptor according to ACPI Spec 5.0, section |
194 | case ACPI_RESOURCE_TYPE_ADDRESS32: | 198 | * 6.4.3.5 Address Space Resource Descriptors. |
195 | case ACPI_RESOURCE_TYPE_ADDRESS64: | 199 | */ |
196 | break; | 200 | if ((addr->min_address_fixed != addr->max_address_fixed && len) || |
197 | default: | 201 | (addr->min_address_fixed && addr->max_address_fixed && !len)) |
198 | return false; | 202 | pr_debug("ACPI: Invalid address space min_addr_fix %d, max_addr_fix %d, len %llx\n", |
199 | } | 203 | addr->min_address_fixed, addr->max_address_fixed, len); |
200 | 204 | ||
201 | status = acpi_resource_to_address64(ares, &addr); | 205 | res->start = attr->minimum; |
202 | if (ACPI_FAILURE(status)) | 206 | res->end = attr->maximum; |
203 | return false; | ||
204 | 207 | ||
205 | res->start = addr.address.minimum; | 208 | /* |
206 | res->end = addr.address.maximum; | 209 | * For bridges that translate addresses across the bridge, |
207 | window = addr.producer_consumer == ACPI_PRODUCER; | 210 | * translation_offset is the offset that must be added to the |
211 | * address on the secondary side to obtain the address on the | ||
212 | * primary side. Non-bridge devices must list 0 for all Address | ||
213 | * Translation offset bits. | ||
214 | */ | ||
215 | if (addr->producer_consumer == ACPI_PRODUCER) { | ||
216 | res->start += attr->translation_offset; | ||
217 | res->end += attr->translation_offset; | ||
218 | } else if (attr->translation_offset) { | ||
219 | pr_debug("ACPI: translation_offset(%lld) is invalid for non-bridge device.\n", | ||
220 | attr->translation_offset); | ||
221 | } | ||
208 | 222 | ||
209 | switch(addr.resource_type) { | 223 | switch (addr->resource_type) { |
210 | case ACPI_MEMORY_RANGE: | 224 | case ACPI_MEMORY_RANGE: |
211 | len = addr.address.maximum - addr.address.minimum + 1; | 225 | acpi_dev_memresource_flags(res, len, wp); |
212 | res->flags = acpi_dev_memresource_flags(len, | ||
213 | addr.info.mem.write_protect, | ||
214 | window); | ||
215 | break; | 226 | break; |
216 | case ACPI_IO_RANGE: | 227 | case ACPI_IO_RANGE: |
217 | io_decode = addr.address.granularity == 0xfff ? | 228 | acpi_dev_ioresource_flags(res, len, iodec); |
218 | ACPI_DECODE_10 : ACPI_DECODE_16; | ||
219 | res->flags = acpi_dev_ioresource_flags(addr.address.minimum, | ||
220 | addr.address.maximum, | ||
221 | io_decode, window); | ||
222 | break; | 229 | break; |
223 | case ACPI_BUS_NUMBER_RANGE: | 230 | case ACPI_BUS_NUMBER_RANGE: |
224 | res->flags = IORESOURCE_BUS; | 231 | res->flags = IORESOURCE_BUS; |
225 | break; | 232 | break; |
226 | default: | 233 | default: |
227 | res->flags = 0; | 234 | return false; |
228 | } | 235 | } |
229 | 236 | ||
230 | return true; | 237 | win->offset = attr->translation_offset; |
238 | |||
239 | if (addr->producer_consumer == ACPI_PRODUCER) | ||
240 | res->flags |= IORESOURCE_WINDOW; | ||
241 | |||
242 | if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY) | ||
243 | res->flags |= IORESOURCE_PREFETCH; | ||
244 | |||
245 | return !(res->flags & IORESOURCE_DISABLED); | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * acpi_dev_resource_address_space - Extract ACPI address space information. | ||
250 | * @ares: Input ACPI resource object. | ||
251 | * @win: Output generic resource object. | ||
252 | * | ||
253 | * Check if the given ACPI resource object represents an address space resource | ||
254 | * and if that's the case, use the information in it to populate the generic | ||
255 | * resource object pointed to by @win. | ||
256 | * | ||
257 | * Return: | ||
258 | * 1) false with win->res.flags setting to zero: not the expected resource type | ||
259 | * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned | ||
260 | * resource | ||
261 | * 3) true: valid assigned resource | ||
262 | */ | ||
263 | bool acpi_dev_resource_address_space(struct acpi_resource *ares, | ||
264 | struct resource_win *win) | ||
265 | { | ||
266 | struct acpi_resource_address64 addr; | ||
267 | |||
268 | win->res.flags = 0; | ||
269 | if (ACPI_FAILURE(acpi_resource_to_address64(ares, &addr))) | ||
270 | return false; | ||
271 | |||
272 | return acpi_decode_space(win, (struct acpi_resource_address *)&addr, | ||
273 | &addr.address); | ||
231 | } | 274 | } |
232 | EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); | 275 | EXPORT_SYMBOL_GPL(acpi_dev_resource_address_space); |
233 | 276 | ||
234 | /** | 277 | /** |
235 | * acpi_dev_resource_ext_address_space - Extract ACPI address space information. | 278 | * acpi_dev_resource_ext_address_space - Extract ACPI address space information. |
236 | * @ares: Input ACPI resource object. | 279 | * @ares: Input ACPI resource object. |
237 | * @res: Output generic resource object. | 280 | * @win: Output generic resource object. |
238 | * | 281 | * |
239 | * Check if the given ACPI resource object represents an extended address space | 282 | * Check if the given ACPI resource object represents an extended address space |
240 | * resource and if that's the case, use the information in it to populate the | 283 | * resource and if that's the case, use the information in it to populate the |
241 | * generic resource object pointed to by @res. | 284 | * generic resource object pointed to by @win. |
285 | * | ||
286 | * Return: | ||
287 | * 1) false with win->res.flags setting to zero: not the expected resource type | ||
288 | * 2) false with IORESOURCE_DISABLED in win->res.flags: valid unassigned | ||
289 | * resource | ||
290 | * 3) true: valid assigned resource | ||
242 | */ | 291 | */ |
243 | bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, | 292 | bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares, |
244 | struct resource *res) | 293 | struct resource_win *win) |
245 | { | 294 | { |
246 | struct acpi_resource_extended_address64 *ext_addr; | 295 | struct acpi_resource_extended_address64 *ext_addr; |
247 | bool window; | ||
248 | u64 len; | ||
249 | u8 io_decode; | ||
250 | 296 | ||
297 | win->res.flags = 0; | ||
251 | if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) | 298 | if (ares->type != ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64) |
252 | return false; | 299 | return false; |
253 | 300 | ||
254 | ext_addr = &ares->data.ext_address64; | 301 | ext_addr = &ares->data.ext_address64; |
255 | 302 | ||
256 | res->start = ext_addr->address.minimum; | 303 | return acpi_decode_space(win, (struct acpi_resource_address *)ext_addr, |
257 | res->end = ext_addr->address.maximum; | 304 | &ext_addr->address); |
258 | window = ext_addr->producer_consumer == ACPI_PRODUCER; | ||
259 | |||
260 | switch(ext_addr->resource_type) { | ||
261 | case ACPI_MEMORY_RANGE: | ||
262 | len = ext_addr->address.maximum - ext_addr->address.minimum + 1; | ||
263 | res->flags = acpi_dev_memresource_flags(len, | ||
264 | ext_addr->info.mem.write_protect, | ||
265 | window); | ||
266 | break; | ||
267 | case ACPI_IO_RANGE: | ||
268 | io_decode = ext_addr->address.granularity == 0xfff ? | ||
269 | ACPI_DECODE_10 : ACPI_DECODE_16; | ||
270 | res->flags = acpi_dev_ioresource_flags(ext_addr->address.minimum, | ||
271 | ext_addr->address.maximum, | ||
272 | io_decode, window); | ||
273 | break; | ||
274 | case ACPI_BUS_NUMBER_RANGE: | ||
275 | res->flags = IORESOURCE_BUS; | ||
276 | break; | ||
277 | default: | ||
278 | res->flags = 0; | ||
279 | } | ||
280 | |||
281 | return true; | ||
282 | } | 305 | } |
283 | EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); | 306 | EXPORT_SYMBOL_GPL(acpi_dev_resource_ext_address_space); |
284 | 307 | ||
@@ -310,7 +333,7 @@ static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi) | |||
310 | { | 333 | { |
311 | res->start = gsi; | 334 | res->start = gsi; |
312 | res->end = gsi; | 335 | res->end = gsi; |
313 | res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED; | 336 | res->flags = IORESOURCE_IRQ | IORESOURCE_DISABLED | IORESOURCE_UNSET; |
314 | } | 337 | } |
315 | 338 | ||
316 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | 339 | static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, |
@@ -369,6 +392,11 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, | |||
369 | * represented by the resource and populate the generic resource object pointed | 392 | * represented by the resource and populate the generic resource object pointed |
370 | * to by @res accordingly. If the registration of the GSI is not successful, | 393 | * to by @res accordingly. If the registration of the GSI is not successful, |
371 | * IORESOURCE_DISABLED will be set it that object's flags. | 394 | * IORESOURCE_DISABLED will be set it that object's flags. |
395 | * | ||
396 | * Return: | ||
397 | * 1) false with res->flags setting to zero: not the expected resource type | ||
398 | * 2) false with IORESOURCE_DISABLED in res->flags: valid unassigned resource | ||
399 | * 3) true: valid assigned resource | ||
372 | */ | 400 | */ |
373 | bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | 401 | bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, |
374 | struct resource *res) | 402 | struct resource *res) |
@@ -402,6 +430,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, | |||
402 | ext_irq->sharable, false); | 430 | ext_irq->sharable, false); |
403 | break; | 431 | break; |
404 | default: | 432 | default: |
433 | res->flags = 0; | ||
405 | return false; | 434 | return false; |
406 | } | 435 | } |
407 | 436 | ||
@@ -415,12 +444,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_resource_interrupt); | |||
415 | */ | 444 | */ |
416 | void acpi_dev_free_resource_list(struct list_head *list) | 445 | void acpi_dev_free_resource_list(struct list_head *list) |
417 | { | 446 | { |
418 | struct resource_list_entry *rentry, *re; | 447 | resource_list_free(list); |
419 | |||
420 | list_for_each_entry_safe(rentry, re, list, node) { | ||
421 | list_del(&rentry->node); | ||
422 | kfree(rentry); | ||
423 | } | ||
424 | } | 448 | } |
425 | EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list); | 449 | EXPORT_SYMBOL_GPL(acpi_dev_free_resource_list); |
426 | 450 | ||
@@ -432,18 +456,19 @@ struct res_proc_context { | |||
432 | int error; | 456 | int error; |
433 | }; | 457 | }; |
434 | 458 | ||
435 | static acpi_status acpi_dev_new_resource_entry(struct resource *r, | 459 | static acpi_status acpi_dev_new_resource_entry(struct resource_win *win, |
436 | struct res_proc_context *c) | 460 | struct res_proc_context *c) |
437 | { | 461 | { |
438 | struct resource_list_entry *rentry; | 462 | struct resource_entry *rentry; |
439 | 463 | ||
440 | rentry = kmalloc(sizeof(*rentry), GFP_KERNEL); | 464 | rentry = resource_list_create_entry(NULL, 0); |
441 | if (!rentry) { | 465 | if (!rentry) { |
442 | c->error = -ENOMEM; | 466 | c->error = -ENOMEM; |
443 | return AE_NO_MEMORY; | 467 | return AE_NO_MEMORY; |
444 | } | 468 | } |
445 | rentry->res = *r; | 469 | *rentry->res = win->res; |
446 | list_add_tail(&rentry->node, c->list); | 470 | rentry->offset = win->offset; |
471 | resource_list_add_tail(rentry, c->list); | ||
447 | c->count++; | 472 | c->count++; |
448 | return AE_OK; | 473 | return AE_OK; |
449 | } | 474 | } |
@@ -452,7 +477,8 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, | |||
452 | void *context) | 477 | void *context) |
453 | { | 478 | { |
454 | struct res_proc_context *c = context; | 479 | struct res_proc_context *c = context; |
455 | struct resource r; | 480 | struct resource_win win; |
481 | struct resource *res = &win.res; | ||
456 | int i; | 482 | int i; |
457 | 483 | ||
458 | if (c->preproc) { | 484 | if (c->preproc) { |
@@ -467,18 +493,18 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, | |||
467 | } | 493 | } |
468 | } | 494 | } |
469 | 495 | ||
470 | memset(&r, 0, sizeof(r)); | 496 | memset(&win, 0, sizeof(win)); |
471 | 497 | ||
472 | if (acpi_dev_resource_memory(ares, &r) | 498 | if (acpi_dev_resource_memory(ares, res) |
473 | || acpi_dev_resource_io(ares, &r) | 499 | || acpi_dev_resource_io(ares, res) |
474 | || acpi_dev_resource_address_space(ares, &r) | 500 | || acpi_dev_resource_address_space(ares, &win) |
475 | || acpi_dev_resource_ext_address_space(ares, &r)) | 501 | || acpi_dev_resource_ext_address_space(ares, &win)) |
476 | return acpi_dev_new_resource_entry(&r, c); | 502 | return acpi_dev_new_resource_entry(&win, c); |
477 | 503 | ||
478 | for (i = 0; acpi_dev_resource_interrupt(ares, i, &r); i++) { | 504 | for (i = 0; acpi_dev_resource_interrupt(ares, i, res); i++) { |
479 | acpi_status status; | 505 | acpi_status status; |
480 | 506 | ||
481 | status = acpi_dev_new_resource_entry(&r, c); | 507 | status = acpi_dev_new_resource_entry(&win, c); |
482 | if (ACPI_FAILURE(status)) | 508 | if (ACPI_FAILURE(status)) |
483 | return status; | 509 | return status; |
484 | } | 510 | } |
@@ -503,7 +529,7 @@ static acpi_status acpi_dev_process_resource(struct acpi_resource *ares, | |||
503 | * returned as the final error code. | 529 | * returned as the final error code. |
504 | * | 530 | * |
505 | * The resultant struct resource objects are put on the list pointed to by | 531 | * The resultant struct resource objects are put on the list pointed to by |
506 | * @list, that must be empty initially, as members of struct resource_list_entry | 532 | * @list, that must be empty initially, as members of struct resource_entry |
507 | * objects. Callers of this routine should use %acpi_dev_free_resource_list() to | 533 | * objects. Callers of this routine should use %acpi_dev_free_resource_list() to |
508 | * free that list. | 534 | * free that list. |
509 | * | 535 | * |
@@ -538,3 +564,58 @@ int acpi_dev_get_resources(struct acpi_device *adev, struct list_head *list, | |||
538 | return c.count; | 564 | return c.count; |
539 | } | 565 | } |
540 | EXPORT_SYMBOL_GPL(acpi_dev_get_resources); | 566 | EXPORT_SYMBOL_GPL(acpi_dev_get_resources); |
567 | |||
568 | /** | ||
569 | * acpi_dev_filter_resource_type - Filter ACPI resource according to resource | ||
570 | * types | ||
571 | * @ares: Input ACPI resource object. | ||
572 | * @types: Valid resource types of IORESOURCE_XXX | ||
573 | * | ||
574 | * This is a hepler function to support acpi_dev_get_resources(), which filters | ||
575 | * ACPI resource objects according to resource types. | ||
576 | */ | ||
577 | int acpi_dev_filter_resource_type(struct acpi_resource *ares, | ||
578 | unsigned long types) | ||
579 | { | ||
580 | unsigned long type = 0; | ||
581 | |||
582 | switch (ares->type) { | ||
583 | case ACPI_RESOURCE_TYPE_MEMORY24: | ||
584 | case ACPI_RESOURCE_TYPE_MEMORY32: | ||
585 | case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: | ||
586 | type = IORESOURCE_MEM; | ||
587 | break; | ||
588 | case ACPI_RESOURCE_TYPE_IO: | ||
589 | case ACPI_RESOURCE_TYPE_FIXED_IO: | ||
590 | type = IORESOURCE_IO; | ||
591 | break; | ||
592 | case ACPI_RESOURCE_TYPE_IRQ: | ||
593 | case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: | ||
594 | type = IORESOURCE_IRQ; | ||
595 | break; | ||
596 | case ACPI_RESOURCE_TYPE_DMA: | ||
597 | case ACPI_RESOURCE_TYPE_FIXED_DMA: | ||
598 | type = IORESOURCE_DMA; | ||
599 | break; | ||
600 | case ACPI_RESOURCE_TYPE_GENERIC_REGISTER: | ||
601 | type = IORESOURCE_REG; | ||
602 | break; | ||
603 | case ACPI_RESOURCE_TYPE_ADDRESS16: | ||
604 | case ACPI_RESOURCE_TYPE_ADDRESS32: | ||
605 | case ACPI_RESOURCE_TYPE_ADDRESS64: | ||
606 | case ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64: | ||
607 | if (ares->data.address.resource_type == ACPI_MEMORY_RANGE) | ||
608 | type = IORESOURCE_MEM; | ||
609 | else if (ares->data.address.resource_type == ACPI_IO_RANGE) | ||
610 | type = IORESOURCE_IO; | ||
611 | else if (ares->data.address.resource_type == | ||
612 | ACPI_BUS_NUMBER_RANGE) | ||
613 | type = IORESOURCE_BUS; | ||
614 | break; | ||
615 | default: | ||
616 | break; | ||
617 | } | ||
618 | |||
619 | return (type & types) ? 0 : 1; | ||
620 | } | ||
621 | EXPORT_SYMBOL_GPL(acpi_dev_filter_resource_type); | ||