aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pnp/pnpacpi/rsparser.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pnp/pnpacpi/rsparser.c')
-rw-r--r--drivers/pnp/pnpacpi/rsparser.c84
1 files changed, 61 insertions, 23 deletions
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
index 5702b2c8691f..35bb44af49b3 100644
--- a/drivers/pnp/pnpacpi/rsparser.c
+++ b/drivers/pnp/pnpacpi/rsparser.c
@@ -24,6 +24,7 @@
24#include <linux/acpi.h> 24#include <linux/acpi.h>
25#include <linux/pci.h> 25#include <linux/pci.h>
26#include <linux/pnp.h> 26#include <linux/pnp.h>
27#include <linux/slab.h>
27#include "../base.h" 28#include "../base.h"
28#include "pnpacpi.h" 29#include "pnpacpi.h"
29 30
@@ -177,7 +178,8 @@ static int dma_flags(struct pnp_dev *dev, int type, int bus_master,
177} 178}
178 179
179static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start, 180static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
180 u64 len, int io_decode) 181 u64 len, int io_decode,
182 int window)
181{ 183{
182 int flags = 0; 184 int flags = 0;
183 u64 end = start + len - 1; 185 u64 end = start + len - 1;
@@ -186,6 +188,8 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_dev *dev, u64 start,
186 flags |= IORESOURCE_IO_16BIT_ADDR; 188 flags |= IORESOURCE_IO_16BIT_ADDR;
187 if (len == 0 || end >= 0x10003) 189 if (len == 0 || end >= 0x10003)
188 flags |= IORESOURCE_DISABLED; 190 flags |= IORESOURCE_DISABLED;
191 if (window)
192 flags |= IORESOURCE_WINDOW;
189 193
190 pnp_add_io_resource(dev, start, end, flags); 194 pnp_add_io_resource(dev, start, end, flags);
191} 195}
@@ -247,7 +251,7 @@ static void pnpacpi_parse_allocated_vendor(struct pnp_dev *dev,
247 251
248static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev, 252static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
249 u64 start, u64 len, 253 u64 start, u64 len,
250 int write_protect) 254 int write_protect, int window)
251{ 255{
252 int flags = 0; 256 int flags = 0;
253 u64 end = start + len - 1; 257 u64 end = start + len - 1;
@@ -256,15 +260,47 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_dev *dev,
256 flags |= IORESOURCE_DISABLED; 260 flags |= IORESOURCE_DISABLED;
257 if (write_protect == ACPI_READ_WRITE_MEMORY) 261 if (write_protect == ACPI_READ_WRITE_MEMORY)
258 flags |= IORESOURCE_MEM_WRITEABLE; 262 flags |= IORESOURCE_MEM_WRITEABLE;
263 if (window)
264 flags |= IORESOURCE_WINDOW;
259 265
260 pnp_add_mem_resource(dev, start, end, flags); 266 pnp_add_mem_resource(dev, start, end, flags);
261} 267}
262 268
269static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev,
270 u64 start, u64 len)
271{
272 u64 end = start + len - 1;
273
274 pnp_add_bus_resource(dev, start, end);
275}
276
277static u64 addr_space_length(struct pnp_dev *dev, u64 min, u64 max, u64 len)
278{
279 u64 max_len;
280
281 max_len = max - min + 1;
282 if (len <= max_len)
283 return len;
284
285 /*
286 * Per 6.4.3.5, _LEN cannot exceed _MAX - _MIN + 1, but some BIOSes
287 * don't do this correctly, e.g.,
288 * https://bugzilla.kernel.org/show_bug.cgi?id=15480
289 */
290 dev_info(&dev->dev,
291 "resource length %#llx doesn't fit in %#llx-%#llx, trimming\n",
292 (unsigned long long) len, (unsigned long long) min,
293 (unsigned long long) max);
294 return max_len;
295}
296
263static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, 297static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
264 struct acpi_resource *res) 298 struct acpi_resource *res)
265{ 299{
266 struct acpi_resource_address64 addr, *p = &addr; 300 struct acpi_resource_address64 addr, *p = &addr;
267 acpi_status status; 301 acpi_status status;
302 int window;
303 u64 len;
268 304
269 status = acpi_resource_to_address64(res, p); 305 status = acpi_resource_to_address64(res, p);
270 if (!ACPI_SUCCESS(status)) { 306 if (!ACPI_SUCCESS(status)) {
@@ -273,37 +309,39 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev,
273 return; 309 return;
274 } 310 }
275 311
276 if (p->producer_consumer == ACPI_PRODUCER) 312 len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
277 return; 313 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
278 314
279 if (p->resource_type == ACPI_MEMORY_RANGE) 315 if (p->resource_type == ACPI_MEMORY_RANGE)
280 pnpacpi_parse_allocated_memresource(dev, 316 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
281 p->minimum, p->address_length, 317 p->info.mem.write_protect, window);
282 p->info.mem.write_protect);
283 else if (p->resource_type == ACPI_IO_RANGE) 318 else if (p->resource_type == ACPI_IO_RANGE)
284 pnpacpi_parse_allocated_ioresource(dev, 319 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
285 p->minimum, p->address_length,
286 p->granularity == 0xfff ? ACPI_DECODE_10 : 320 p->granularity == 0xfff ? ACPI_DECODE_10 :
287 ACPI_DECODE_16); 321 ACPI_DECODE_16, window);
322 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
323 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
288} 324}
289 325
290static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, 326static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev,
291 struct acpi_resource *res) 327 struct acpi_resource *res)
292{ 328{
293 struct acpi_resource_extended_address64 *p = &res->data.ext_address64; 329 struct acpi_resource_extended_address64 *p = &res->data.ext_address64;
330 int window;
331 u64 len;
294 332
295 if (p->producer_consumer == ACPI_PRODUCER) 333 len = addr_space_length(dev, p->minimum, p->maximum, p->address_length);
296 return; 334 window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0;
297 335
298 if (p->resource_type == ACPI_MEMORY_RANGE) 336 if (p->resource_type == ACPI_MEMORY_RANGE)
299 pnpacpi_parse_allocated_memresource(dev, 337 pnpacpi_parse_allocated_memresource(dev, p->minimum, len,
300 p->minimum, p->address_length, 338 p->info.mem.write_protect, window);
301 p->info.mem.write_protect);
302 else if (p->resource_type == ACPI_IO_RANGE) 339 else if (p->resource_type == ACPI_IO_RANGE)
303 pnpacpi_parse_allocated_ioresource(dev, 340 pnpacpi_parse_allocated_ioresource(dev, p->minimum, len,
304 p->minimum, p->address_length,
305 p->granularity == 0xfff ? ACPI_DECODE_10 : 341 p->granularity == 0xfff ? ACPI_DECODE_10 :
306 ACPI_DECODE_16); 342 ACPI_DECODE_16, window);
343 else if (p->resource_type == ACPI_BUS_NUMBER_RANGE)
344 pnpacpi_parse_allocated_busresource(dev, p->minimum, len);
307} 345}
308 346
309static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res, 347static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
@@ -368,7 +406,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
368 pnpacpi_parse_allocated_ioresource(dev, 406 pnpacpi_parse_allocated_ioresource(dev,
369 io->minimum, 407 io->minimum,
370 io->address_length, 408 io->address_length,
371 io->io_decode); 409 io->io_decode, 0);
372 break; 410 break;
373 411
374 case ACPI_RESOURCE_TYPE_START_DEPENDENT: 412 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
@@ -380,7 +418,7 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
380 pnpacpi_parse_allocated_ioresource(dev, 418 pnpacpi_parse_allocated_ioresource(dev,
381 fixed_io->address, 419 fixed_io->address,
382 fixed_io->address_length, 420 fixed_io->address_length,
383 ACPI_DECODE_10); 421 ACPI_DECODE_10, 0);
384 break; 422 break;
385 423
386 case ACPI_RESOURCE_TYPE_VENDOR: 424 case ACPI_RESOURCE_TYPE_VENDOR:
@@ -396,21 +434,21 @@ static acpi_status pnpacpi_allocated_resource(struct acpi_resource *res,
396 pnpacpi_parse_allocated_memresource(dev, 434 pnpacpi_parse_allocated_memresource(dev,
397 memory24->minimum, 435 memory24->minimum,
398 memory24->address_length, 436 memory24->address_length,
399 memory24->write_protect); 437 memory24->write_protect, 0);
400 break; 438 break;
401 case ACPI_RESOURCE_TYPE_MEMORY32: 439 case ACPI_RESOURCE_TYPE_MEMORY32:
402 memory32 = &res->data.memory32; 440 memory32 = &res->data.memory32;
403 pnpacpi_parse_allocated_memresource(dev, 441 pnpacpi_parse_allocated_memresource(dev,
404 memory32->minimum, 442 memory32->minimum,
405 memory32->address_length, 443 memory32->address_length,
406 memory32->write_protect); 444 memory32->write_protect, 0);
407 break; 445 break;
408 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 446 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32:
409 fixed_memory32 = &res->data.fixed_memory32; 447 fixed_memory32 = &res->data.fixed_memory32;
410 pnpacpi_parse_allocated_memresource(dev, 448 pnpacpi_parse_allocated_memresource(dev,
411 fixed_memory32->address, 449 fixed_memory32->address,
412 fixed_memory32->address_length, 450 fixed_memory32->address_length,
413 fixed_memory32->write_protect); 451 fixed_memory32->write_protect, 0);
414 break; 452 break;
415 case ACPI_RESOURCE_TYPE_ADDRESS16: 453 case ACPI_RESOURCE_TYPE_ADDRESS16:
416 case ACPI_RESOURCE_TYPE_ADDRESS32: 454 case ACPI_RESOURCE_TYPE_ADDRESS32: