Author: andrew
Date: Fri Jan 31 11:33:11 2020
New Revision: 357330
URL: https://svnweb.freebsd.org/changeset/base/357330

Log:
  Call the MAPTI command earlier in the ITS driver
  
  The GICv3 Software Overview suggests when allocating a new MSI/MSI-X
  interrupt we need to call MAPD followed by MAPTI. Unfortunately the code
  would place a MOVI command between these. This is invalid as it needs
  values set by the MAPTI to be present.
  
  Re-order so we allocate a temporary CPU for the interrupt, then use the
  MAPTI command to assign the MSI to it.
  
  MFC after:    2 weeks
  Sponsored by: DARPA, AFRL

Modified:
  head/sys/arm64/arm64/gicv3_its.c

Modified: head/sys/arm64/arm64/gicv3_its.c
==============================================================================
--- head/sys/arm64/arm64/gicv3_its.c    Fri Jan 31 11:31:14 2020        
(r357329)
+++ head/sys/arm64/arm64/gicv3_its.c    Fri Jan 31 11:33:11 2020        
(r357330)
@@ -928,21 +928,29 @@ gicv3_its_post_filter(device_t dev, struct intr_irqsrc
 }
 
 static int
-gicv3_its_bind_intr(device_t dev, struct intr_irqsrc *isrc)
+gicv3_its_select_cpu(device_t dev, struct intr_irqsrc *isrc)
 {
-       struct gicv3_its_irqsrc *girq;
        struct gicv3_its_softc *sc;
 
        sc = device_get_softc(dev);
-       girq = (struct gicv3_its_irqsrc *)isrc;
        if (CPU_EMPTY(&isrc->isrc_cpu)) {
                sc->gic_irq_cpu = intr_irq_next_cpu(sc->gic_irq_cpu,
                    &sc->sc_cpus);
                CPU_SETOF(sc->gic_irq_cpu, &isrc->isrc_cpu);
        }
 
-       its_cmd_movi(dev, girq);
+       return (0);
+}
 
+static int
+gicv3_its_bind_intr(device_t dev, struct intr_irqsrc *isrc)
+{
+       struct gicv3_its_irqsrc *girq;
+
+       gicv3_its_select_cpu(dev, isrc);
+
+       girq = (struct gicv3_its_irqsrc *)isrc;
+       its_cmd_movi(dev, girq);
        return (0);
 }
 
@@ -1129,6 +1137,10 @@ gicv3_its_alloc_msi(device_t dev, device_t child, int 
                girq = &sc->sc_irqs[irq];
                girq->gi_its_dev = its_dev;
                srcs[i] = (struct intr_irqsrc *)girq;
+
+               /* Map the message to the given IRQ */
+               gicv3_its_select_cpu(dev, (struct intr_irqsrc *)girq);
+               its_cmd_mapti(dev, girq);
        }
        its_dev->lpis.lpi_busy += count;
        *pic = dev;
@@ -1189,6 +1201,10 @@ gicv3_its_alloc_msix(device_t dev, device_t child, dev
        girq = &sc->sc_irqs[irq];
        girq->gi_its_dev = its_dev;
 
+       /* Map the message to the given IRQ */
+       gicv3_its_select_cpu(dev, (struct intr_irqsrc *)girq);
+       its_cmd_mapti(dev, girq);
+
        *pic = dev;
        *isrcp = (struct intr_irqsrc *)girq;
 
@@ -1228,9 +1244,6 @@ gicv3_its_map_msi(device_t dev, device_t child, struct
 
        sc = device_get_softc(dev);
        girq = (struct gicv3_its_irqsrc *)isrc;
-
-       /* Map the message to the given IRQ */
-       its_cmd_mapti(dev, girq);
 
        *addr = vtophys(rman_get_virtual(sc->sc_its_res)) + GITS_TRANSLATER;
        *data = girq->gi_irq - girq->gi_its_dev->lpis.lpi_base;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to