Author: jchandra
Date: Mon Nov 19 03:02:47 2018
New Revision: 340598
URL: https://svnweb.freebsd.org/changeset/base/340598

Log:
  acpica: rework INTRNG interrupts
  
  On arm64 (where INTRNG is enabled), the interrupts have to be mapped
  with ACPI_BUS_MAP_INTR() before adding them as resources to devices.
  
  The earlier code did the mapping before calling acpi_set_resource(),
  which bypassed code that checked for PCI link interrupts.
  
  To fix this, move the call to map interrupts into acpi_set_resource()
  and that requires additional work to lookup interrupt properties.
  The changes here are to:
   * extend acpi_lookup_irq_handler() to lookup an irq in the ACPI
     resources
   * create a helper function acpi_map_intr() which uses the updated
     acpi_lookup_irq_handler() to look up an irq, and then map it
     with ACPI_BUS_MAP_INTR()
   * use acpi_map_intr() in acpi_pcib_route_interrupt() to map
     pci link interrupts.
  
  With these changes, we can drop the ifdefs in acpi_resource.c, and
  we can also drop the call for mapping interrupts in generic_timer.c
  
  Reviewed by:  andrew
  Differential Revision:        https://reviews.freebsd.org/D17790

Modified:
  head/sys/arm/arm/generic_timer.c
  head/sys/dev/acpica/acpi.c
  head/sys/dev/acpica/acpi_pcib.c
  head/sys/dev/acpica/acpi_resource.c
  head/sys/dev/acpica/acpivar.h

Modified: head/sys/arm/arm/generic_timer.c
==============================================================================
--- head/sys/arm/arm/generic_timer.c    Mon Nov 19 02:55:18 2018        
(r340597)
+++ head/sys/arm/arm/generic_timer.c    Mon Nov 19 03:02:47 2018        
(r340598)
@@ -72,7 +72,6 @@ __FBSDID("$FreeBSD$");
 #ifdef DEV_ACPI
 #include <contrib/dev/acpica/include/acpi.h>
 #include <dev/acpica/acpivar.h>
-#include "acpi_bus_if.h"
 #endif
 
 #define        GT_CTRL_ENABLE          (1 << 0)
@@ -340,8 +339,6 @@ static void
 arm_tmr_acpi_add_irq(device_t parent, device_t dev, int rid, u_int irq)
 {
 
-       irq = ACPI_BUS_MAP_INTR(parent, dev, irq,
-               INTR_TRIGGER_LEVEL, INTR_POLARITY_HIGH);
        BUS_SET_RESOURCE(parent, dev, SYS_RES_IRQ, rid, irq, 1);
 }
 

Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c  Mon Nov 19 02:55:18 2018        (r340597)
+++ head/sys/dev/acpica/acpi.c  Mon Nov 19 03:02:47 2018        (r340598)
@@ -1319,6 +1319,13 @@ acpi_set_resource(device_t dev, device_t child, int ty
     }
 #endif
 
+#ifdef INTRNG
+    /* map with default for now */
+    if (type == SYS_RES_IRQ)
+       start = (rman_res_t)acpi_map_intr(child, (u_int)start,
+                       acpi_get_handle(child));
+#endif
+
     /* If the resource is already allocated, fail. */
     if (resource_list_busy(rl, type, rid))
        return (EBUSY);

Modified: head/sys/dev/acpica/acpi_pcib.c
==============================================================================
--- head/sys/dev/acpica/acpi_pcib.c     Mon Nov 19 02:55:18 2018        
(r340597)
+++ head/sys/dev/acpica/acpi_pcib.c     Mon Nov 19 03:02:47 2018        
(r340598)
@@ -188,6 +188,7 @@ acpi_pcib_route_interrupt(device_t pcib, device_t dev,
 
     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 
+    lnkdev = NULL;
     interrupt = PCI_INVALID_IRQ;
 
     /* ACPI numbers pins 0-3, not 1-4 like the BIOS. */
@@ -252,7 +253,12 @@ acpi_pcib_route_interrupt(device_t pcib, device_t dev,
 
 out:
     ACPI_SERIAL_END(pcib);
-
+#ifdef INTRNG
+    if (PCI_INTERRUPT_VALID(interrupt)) {
+       interrupt  = acpi_map_intr(dev, interrupt, lnkdev);
+       KASSERT(PCI_INTERRUPT_VALID(interrupt), ("mapping fail"));
+    }
+#endif
     return_VALUE(interrupt);
 }
 

Modified: head/sys/dev/acpica/acpi_resource.c
==============================================================================
--- head/sys/dev/acpica/acpi_resource.c Mon Nov 19 02:55:18 2018        
(r340597)
+++ head/sys/dev/acpica/acpi_resource.c Mon Nov 19 03:02:47 2018        
(r340598)
@@ -55,10 +55,13 @@ ACPI_MODULE_NAME("RESOURCE")
 
 struct lookup_irq_request {
     ACPI_RESOURCE *acpi_res;
-    struct resource *res;
+    u_int      irq;
     int                counter;
     int                rid;
     int                found;
+    int                checkrid;
+    int                trig;
+    int                pol;
 };
 
 static ACPI_STATUS
@@ -66,18 +69,22 @@ acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *cont
 {
     struct lookup_irq_request *req;
     size_t len;
-    u_int irqnum, irq;
+    u_int irqnum, irq, trig, pol;
 
     switch (res->Type) {
     case ACPI_RESOURCE_TYPE_IRQ:
        irqnum = res->Data.Irq.InterruptCount;
        irq = res->Data.Irq.Interrupts[0];
        len = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
+       trig = res->Data.Irq.Triggering;
+       pol = res->Data.Irq.Polarity;
        break;
     case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
        irqnum = res->Data.ExtendedIrq.InterruptCount;
        irq = res->Data.ExtendedIrq.Interrupts[0];
        len = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
+       trig = res->Data.ExtendedIrq.Triggering;
+       pol = res->Data.ExtendedIrq.Polarity;
        break;
     default:
        return (AE_OK);
@@ -85,14 +92,21 @@ acpi_lookup_irq_handler(ACPI_RESOURCE *res, void *cont
     if (irqnum != 1)
        return (AE_OK);
     req = (struct lookup_irq_request *)context;
-    if (req->counter != req->rid) {
-       req->counter++;
-       return (AE_OK);
+    if (req->checkrid) {
+       if (req->counter != req->rid) {
+           req->counter++;
+           return (AE_OK);
+       }
+       KASSERT(irq == req->irq, ("IRQ resources do not match"));
+    } else {
+       if (req->irq != irq)
+           return (AE_OK);
     }
     req->found = 1;
-    KASSERT(irq == rman_get_start(req->res),
-       ("IRQ resources do not match"));
-    bcopy(res, req->acpi_res, len);
+    req->pol = pol;
+    req->trig = trig;
+    if (req->acpi_res != NULL)
+       bcopy(res, req->acpi_res, len);
     return (AE_CTRL_TERMINATE);
 }
 
@@ -104,10 +118,11 @@ acpi_lookup_irq_resource(device_t dev, int rid, struct
     ACPI_STATUS status;
 
     req.acpi_res = acpi_res;
-    req.res = res;
+    req.irq = rman_get_start(res);
     req.counter = 0;
     req.rid = rid;
     req.found = 0;
+    req.checkrid = 1;
     status = AcpiWalkResources(acpi_get_handle(dev), "_CRS",
        acpi_lookup_irq_handler, &req);
     if (ACPI_SUCCESS(status) && req.found == 0)
@@ -155,6 +170,34 @@ acpi_config_intr(device_t dev, ACPI_RESOURCE *res)
        INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
 }
 
+#ifdef INTRNG
+int
+acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle)
+{
+    struct lookup_irq_request req;
+    int trig, pol;
+
+    trig = ACPI_LEVEL_SENSITIVE;
+    pol = ACPI_ACTIVE_HIGH;
+    if (handle != NULL) {
+       req.found = 0;
+       req.acpi_res = NULL;
+       req.irq = irq;
+       req.counter = 0;
+       req.rid = 0;
+       req.checkrid = 0;
+       AcpiWalkResources(handle, "_CRS", acpi_lookup_irq_handler, &req);
+       if (req.found != 0) {
+           trig = req.trig;
+           pol = req.pol;
+       }
+    }
+    return ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, irq,
+       (trig == ACPI_EDGE_SENSITIVE) ?  INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
+       (pol == ACPI_ACTIVE_HIGH) ?  INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
+}
+#endif
+
 struct acpi_resource_context {
     struct acpi_parse_resource_set *set;
     device_t   dev;
@@ -591,13 +634,7 @@ acpi_res_set_irq(device_t dev, void *context, uint8_t 
     if (count != 1)
        return;
 
-#ifdef INTRNG
-    intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
-       (trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
-       (pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
-#else
     intr = *irq;
-#endif
     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
 }
 
@@ -615,13 +652,7 @@ acpi_res_set_ext_irq(device_t dev, void *context, uint
     if (count != 1)
        return;
 
-#ifdef INTRNG
-    intr = ACPI_BUS_MAP_INTR(device_get_parent(dev), dev, *irq,
-       (trig == ACPI_EDGE_SENSITIVE) ? INTR_TRIGGER_EDGE : INTR_TRIGGER_LEVEL,
-       (pol == ACPI_ACTIVE_HIGH) ? INTR_POLARITY_HIGH : INTR_POLARITY_LOW);
-#else
     intr = *irq;
-#endif
     bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, intr, 1);
 }
 

Modified: head/sys/dev/acpica/acpivar.h
==============================================================================
--- head/sys/dev/acpica/acpivar.h       Mon Nov 19 02:55:18 2018        
(r340597)
+++ head/sys/dev/acpica/acpivar.h       Mon Nov 19 03:02:47 2018        
(r340598)
@@ -403,6 +403,9 @@ extern struct       acpi_parse_resource_set acpi_res_parse_s
 
 int            acpi_identify(void);
 void           acpi_config_intr(device_t dev, ACPI_RESOURCE *res);
+#ifdef INTRNG
+int            acpi_map_intr(device_t dev, u_int irq, ACPI_HANDLE handle);
+#endif
 ACPI_STATUS    acpi_lookup_irq_resource(device_t dev, int rid,
                    struct resource *res, ACPI_RESOURCE *acpi_res);
 ACPI_STATUS    acpi_parse_resources(device_t dev, ACPI_HANDLE handle,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to