| From dbdda4277cf0422a9ccb7ea98d0263c3cdbecdf6 Mon Sep 17 00:00:00 2001 |
| From: Mark Salter <msalter@redhat.com> |
| Date: Tue, 8 May 2018 21:54:39 -0400 |
| Subject: [PATCH] ACPI / irq: Workaround firmware issue on X-Gene based |
| m400 |
| |
| The ACPI firmware on the xgene-based m400 platorms erroneously |
| describes its UART interrupt as ACPI_PRODUCER rather than |
| ACPI_CONSUMER. This leads to the UART driver being unable to |
| find its interrupt and the kernel unable find a console. |
| Work around this by avoiding the producer/consumer check |
| for X-Gene UARTs. |
| |
| Signed-off-by: Mark Salter <msalter@redhat.com> |
| |
| drivers/acpi/irq.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c |
| index 7c352cba0528..028c1a564cff 100644 |
| |
| |
| @@ -129,6 +129,7 @@ struct acpi_irq_parse_one_ctx { |
| unsigned int index; |
| unsigned long *res_flags; |
| struct irq_fwspec *fwspec; |
| + bool skip_producer_check; |
| }; |
| |
| /** |
| @@ -200,7 +201,8 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares, |
| return AE_CTRL_TERMINATE; |
| case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: |
| eirq = &ares->data.extended_irq; |
| - if (eirq->producer_consumer == ACPI_PRODUCER) |
| + if (!ctx->skip_producer_check && |
| + eirq->producer_consumer == ACPI_PRODUCER) |
| return AE_OK; |
| if (ctx->index >= eirq->interrupt_count) { |
| ctx->index -= eirq->interrupt_count; |
| @@ -235,8 +237,19 @@ static acpi_status acpi_irq_parse_one_cb(struct acpi_resource *ares, |
| static int acpi_irq_parse_one(acpi_handle handle, unsigned int index, |
| struct irq_fwspec *fwspec, unsigned long *flags) |
| { |
| - struct acpi_irq_parse_one_ctx ctx = { -EINVAL, index, flags, fwspec }; |
| + struct acpi_irq_parse_one_ctx ctx = { -EINVAL, index, flags, fwspec, false }; |
| |
| + /* |
| + * Firmware on arm64-based HPE m400 platform incorrectly marks |
| + * its UART interrupt as ACPI_PRODUCER rather than ACPI_CONSUMER. |
| + * Don't do the producer/consumer check for that device. |
| + */ |
| + if (IS_ENABLED(CONFIG_ARM64)) { |
| + struct acpi_device *adev = acpi_bus_get_acpi_device(handle); |
| + |
| + if (adev && !strcmp(acpi_device_hid(adev), "APMC0D08")) |
| + ctx.skip_producer_check = true; |
| + } |
| acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_irq_parse_one_cb, &ctx); |
| return ctx.rc; |
| } |
| -- |
| 2.17.0 |
| |