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