aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>2018-09-18 09:10:48 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-09-18 10:08:38 -0400
commitebe4582281d6e90972f057318a6edea14810ea48 (patch)
tree4da6cbfc9082c78cb4df7a6a8dcfa040d9770cbf
parent8801922cd94c918e4dc3a108ecaa500c4d40583f (diff)
intel_th: Fix resource handling for ACPI glue layer
The core of the driver expects the resource array from the glue layer to be indexed by even numbers, as is the case for 64-bit PCI resources. This doesn't hold true for others, ACPI in this instance, which leads to an out-of-bounds access and an ioremap() on whatever address that access fetches. This patch fixes the problem by reading resource array differently based on whether the 64-bit flag is set, which would indicate PCI glue layer. Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com> Fixes: ebc57e399b8e ("intel_th: Add ACPI glue layer") CC: stable@vger.kernel.org # v4.17+ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/hwtracing/intel_th/core.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index 4e70ecee2103..fc6b7f8b62fb 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -488,7 +488,7 @@ static const struct intel_th_subdevice {
488 .flags = IORESOURCE_MEM, 488 .flags = IORESOURCE_MEM,
489 }, 489 },
490 { 490 {
491 .start = TH_MMIO_SW, 491 .start = 1, /* use resource[1] */
492 .end = 0, 492 .end = 0,
493 .flags = IORESOURCE_MEM, 493 .flags = IORESOURCE_MEM,
494 }, 494 },
@@ -581,6 +581,7 @@ intel_th_subdevice_alloc(struct intel_th *th,
581 struct intel_th_device *thdev; 581 struct intel_th_device *thdev;
582 struct resource res[3]; 582 struct resource res[3];
583 unsigned int req = 0; 583 unsigned int req = 0;
584 bool is64bit = false;
584 int r, err; 585 int r, err;
585 586
586 thdev = intel_th_device_alloc(th, subdev->type, subdev->name, 587 thdev = intel_th_device_alloc(th, subdev->type, subdev->name,
@@ -590,12 +591,18 @@ intel_th_subdevice_alloc(struct intel_th *th,
590 591
591 thdev->drvdata = th->drvdata; 592 thdev->drvdata = th->drvdata;
592 593
594 for (r = 0; r < th->num_resources; r++)
595 if (th->resource[r].flags & IORESOURCE_MEM_64) {
596 is64bit = true;
597 break;
598 }
599
593 memcpy(res, subdev->res, 600 memcpy(res, subdev->res,
594 sizeof(struct resource) * subdev->nres); 601 sizeof(struct resource) * subdev->nres);
595 602
596 for (r = 0; r < subdev->nres; r++) { 603 for (r = 0; r < subdev->nres; r++) {
597 struct resource *devres = th->resource; 604 struct resource *devres = th->resource;
598 int bar = TH_MMIO_CONFIG; 605 int bar = 0; /* cut subdevices' MMIO from resource[0] */
599 606
600 /* 607 /*
601 * Take .end == 0 to mean 'take the whole bar', 608 * Take .end == 0 to mean 'take the whole bar',
@@ -604,6 +611,8 @@ intel_th_subdevice_alloc(struct intel_th *th,
604 */ 611 */
605 if (!res[r].end && res[r].flags == IORESOURCE_MEM) { 612 if (!res[r].end && res[r].flags == IORESOURCE_MEM) {
606 bar = res[r].start; 613 bar = res[r].start;
614 if (is64bit)
615 bar *= 2;
607 res[r].start = 0; 616 res[r].start = 0;
608 res[r].end = resource_size(&devres[bar]) - 1; 617 res[r].end = resource_size(&devres[bar]) - 1;
609 } 618 }