Sat Nov 10 11:46:31 2018 UTC ()
Implement pic_get_affinity/pic_set_affinity for LPIs via ITS


(jmcneill)
diff -r1.6 -r1.7 src/sys/arch/arm/cortex/gicv3.c
diff -r1.3 -r1.4 src/sys/arch/arm/cortex/gicv3.h
diff -r1.1 -r1.2 src/sys/arch/arm/cortex/gicv3_its.c
diff -r1.1 -r1.2 src/sys/arch/arm/cortex/gicv3_its.h

cvs diff -r1.6 -r1.7 src/sys/arch/arm/cortex/gicv3.c (expand / switch to unified diff)

--- src/sys/arch/arm/cortex/gicv3.c 2018/11/10 01:56:28 1.6
+++ src/sys/arch/arm/cortex/gicv3.c 2018/11/10 11:46:31 1.7
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gicv3.c,v 1.6 2018/11/10 01:56:28 jmcneill Exp $ */ 1/* $NetBSD: gicv3.c,v 1.7 2018/11/10 11:46:31 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -21,27 +21,27 @@ @@ -21,27 +21,27 @@
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include "opt_multiprocessor.h" 29#include "opt_multiprocessor.h"
30 30
31#define _INTR_PRIVATE 31#define _INTR_PRIVATE
32 32
33#include <sys/cdefs.h> 33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.6 2018/11/10 01:56:28 jmcneill Exp $"); 34__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.7 2018/11/10 11:46:31 jmcneill Exp $");
35 35
36#include <sys/param.h> 36#include <sys/param.h>
37#include <sys/kernel.h> 37#include <sys/kernel.h>
38#include <sys/bus.h> 38#include <sys/bus.h>
39#include <sys/device.h> 39#include <sys/device.h>
40#include <sys/intr.h> 40#include <sys/intr.h>
41#include <sys/systm.h> 41#include <sys/systm.h>
42#include <sys/cpu.h> 42#include <sys/cpu.h>
43 43
44#include <arm/locore.h> 44#include <arm/locore.h>
45#include <arm/armreg.h> 45#include <arm/armreg.h>
46 46
47#include <arm/cortex/gicv3.h> 47#include <arm/cortex/gicv3.h>
@@ -546,27 +546,27 @@ static void @@ -546,27 +546,27 @@ static void
546gicv3_lpi_establish_irq(struct pic_softc *pic, struct intrsource *is) 546gicv3_lpi_establish_irq(struct pic_softc *pic, struct intrsource *is)
547{ 547{
548 struct gicv3_softc * const sc = LPITOSOFTC(pic); 548 struct gicv3_softc * const sc = LPITOSOFTC(pic);
549 549
550 sc->sc_lpiconf.base[is->is_irq] = IPL_TO_PRIORITY(is->is_ipl) | GIC_LPICONF_Res1; 550 sc->sc_lpiconf.base[is->is_irq] = IPL_TO_PRIORITY(is->is_ipl) | GIC_LPICONF_Res1;
551 551
552 bus_dmamap_sync(sc->sc_dmat, sc->sc_lpiconf.map, is->is_irq, 1, BUS_DMASYNC_PREWRITE); 552 bus_dmamap_sync(sc->sc_dmat, sc->sc_lpiconf.map, is->is_irq, 1, BUS_DMASYNC_PREWRITE);
553} 553}
554 554
555static void 555static void
556gicv3_lpi_cpu_init(struct pic_softc *pic, struct cpu_info *ci) 556gicv3_lpi_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
557{ 557{
558 struct gicv3_softc * const sc = LPITOSOFTC(pic); 558 struct gicv3_softc * const sc = LPITOSOFTC(pic);
559 struct gicv3_cpu_init *cpu_init; 559 struct gicv3_lpi_callback *cb;
560 uint32_t ctlr; 560 uint32_t ctlr;
561 561
562 /* If physical LPIs are not supported on this redistributor, just return. */ 562 /* If physical LPIs are not supported on this redistributor, just return. */
563 const uint64_t typer = gicr_read_8(sc, ci->ci_gic_redist, GICR_TYPER); 563 const uint64_t typer = gicr_read_8(sc, ci->ci_gic_redist, GICR_TYPER);
564 if ((typer & GICR_TYPER_PLPIS) == 0) 564 if ((typer & GICR_TYPER_PLPIS) == 0)
565 return; 565 return;
566 566
567 /* Interrupt target address for this CPU, used by ITS when GITS_TYPER.PTA == 0 */ 567 /* Interrupt target address for this CPU, used by ITS when GITS_TYPER.PTA == 0 */
568 sc->sc_processor_id[cpu_index(ci)] = __SHIFTOUT(typer, GICR_TYPER_Processor_Number); 568 sc->sc_processor_id[cpu_index(ci)] = __SHIFTOUT(typer, GICR_TYPER_Processor_Number);
569 569
570 /* Disable LPIs before making changes */ 570 /* Disable LPIs before making changes */
571 ctlr = gicr_read_4(sc, ci->ci_gic_redist, GICR_CTLR); 571 ctlr = gicr_read_4(sc, ci->ci_gic_redist, GICR_CTLR);
572 ctlr &= ~GICR_CTLR_Enable_LPIs; 572 ctlr &= ~GICR_CTLR_Enable_LPIs;
@@ -584,36 +584,66 @@ gicv3_lpi_cpu_init(struct pic_softc *pic @@ -584,36 +584,66 @@ gicv3_lpi_cpu_init(struct pic_softc *pic
584 const uint64_t pendbase = sc->sc_lpipend[cpu_index(ci)].segs[0].ds_addr | 584 const uint64_t pendbase = sc->sc_lpipend[cpu_index(ci)].segs[0].ds_addr |
585 __SHIFTIN(GICR_Shareability_NS, GICR_PENDBASER_Shareability) | 585 __SHIFTIN(GICR_Shareability_NS, GICR_PENDBASER_Shareability) |
586 __SHIFTIN(GICR_Cache_NORMAL_NC, GICR_PENDBASER_InnerCache) | 586 __SHIFTIN(GICR_Cache_NORMAL_NC, GICR_PENDBASER_InnerCache) |
587 GICR_PENDBASER_PTZ; 587 GICR_PENDBASER_PTZ;
588 gicr_write_8(sc, ci->ci_gic_redist, GICR_PENDBASER, pendbase); 588 gicr_write_8(sc, ci->ci_gic_redist, GICR_PENDBASER, pendbase);
589 589
590 /* Enable LPIs */ 590 /* Enable LPIs */
591 ctlr = gicr_read_4(sc, ci->ci_gic_redist, GICR_CTLR); 591 ctlr = gicr_read_4(sc, ci->ci_gic_redist, GICR_CTLR);
592 ctlr |= GICR_CTLR_Enable_LPIs; 592 ctlr |= GICR_CTLR_Enable_LPIs;
593 gicr_write_4(sc, ci->ci_gic_redist, GICR_CTLR, ctlr); 593 gicr_write_4(sc, ci->ci_gic_redist, GICR_CTLR, ctlr);
594 arm_dsb(); 594 arm_dsb();
595 595
596 /* Setup ITS if present */ 596 /* Setup ITS if present */
597 LIST_FOREACH(cpu_init, &sc->sc_cpu_init, list) 597 LIST_FOREACH(cb, &sc->sc_lpi_callbacks, list)
598 cpu_init->func(cpu_init->arg, ci); 598 cb->cpu_init(cb->priv, ci);
599} 599}
600 600
 601#ifdef MULTIPROCESSOR
 602static void
 603gicv3_lpi_get_affinity(struct pic_softc *pic, size_t irq, kcpuset_t *affinity)
 604{
 605 struct gicv3_softc * const sc = LPITOSOFTC(pic);
 606 struct gicv3_lpi_callback *cb;
 607
 608 LIST_FOREACH(cb, &sc->sc_lpi_callbacks, list)
 609 cb->get_affinity(cb->priv, irq, affinity);
 610}
 611
 612static int
 613gicv3_lpi_set_affinity(struct pic_softc *pic, size_t irq, const kcpuset_t *affinity)
 614{
 615 struct gicv3_softc * const sc = LPITOSOFTC(pic);
 616 struct gicv3_lpi_callback *cb;
 617 int error = EINVAL;
 618
 619 LIST_FOREACH(cb, &sc->sc_lpi_callbacks, list) {
 620 error = cb->set_affinity(cb->priv, irq, affinity);
 621 if (error)
 622 return error;
 623 }
 624
 625 return error;
 626}
 627#endif
 628
601static const struct pic_ops gicv3_lpiops = { 629static const struct pic_ops gicv3_lpiops = {
602 .pic_unblock_irqs = gicv3_lpi_unblock_irqs, 630 .pic_unblock_irqs = gicv3_lpi_unblock_irqs,
603 .pic_block_irqs = gicv3_lpi_block_irqs, 631 .pic_block_irqs = gicv3_lpi_block_irqs,
604 .pic_establish_irq = gicv3_lpi_establish_irq, 632 .pic_establish_irq = gicv3_lpi_establish_irq,
605#ifdef MULTIPROCESSOR 633#ifdef MULTIPROCESSOR
606 .pic_cpu_init = gicv3_lpi_cpu_init, 634 .pic_cpu_init = gicv3_lpi_cpu_init,
 635 .pic_get_affinity = gicv3_lpi_get_affinity,
 636 .pic_set_affinity = gicv3_lpi_set_affinity,
607#endif 637#endif
608}; 638};
609 639
610void 640void
611gicv3_dma_alloc(struct gicv3_softc *sc, struct gicv3_dma *dma, bus_size_t len, bus_size_t align) 641gicv3_dma_alloc(struct gicv3_softc *sc, struct gicv3_dma *dma, bus_size_t len, bus_size_t align)
612{ 642{
613 int nsegs, error; 643 int nsegs, error;
614 644
615 dma->len = len; 645 dma->len = len;
616 error = bus_dmamem_alloc(sc->sc_dmat, dma->len, align, 0, dma->segs, 1, &nsegs, BUS_DMA_WAITOK); 646 error = bus_dmamem_alloc(sc->sc_dmat, dma->len, align, 0, dma->segs, 1, &nsegs, BUS_DMA_WAITOK);
617 if (error) 647 if (error)
618 panic("bus_dmamem_alloc failed: %d", error); 648 panic("bus_dmamem_alloc failed: %d", error);
619 error = bus_dmamem_map(sc->sc_dmat, dma->segs, nsegs, len, (void **)&dma->base, BUS_DMA_WAITOK); 649 error = bus_dmamem_map(sc->sc_dmat, dma->segs, nsegs, len, (void **)&dma->base, BUS_DMA_WAITOK);
@@ -685,27 +715,27 @@ gicv3_irq_handler(void *frame) @@ -685,27 +715,27 @@ gicv3_irq_handler(void *frame)
685 715
686 if (ci->ci_cpl != oldipl) 716 if (ci->ci_cpl != oldipl)
687 pic_set_priority(ci, oldipl); 717 pic_set_priority(ci, oldipl);
688} 718}
689 719
690int 720int
691gicv3_init(struct gicv3_softc *sc) 721gicv3_init(struct gicv3_softc *sc)
692{ 722{
693 const uint32_t gicd_typer = gicd_read_4(sc, GICD_TYPER); 723 const uint32_t gicd_typer = gicd_read_4(sc, GICD_TYPER);
694 int n; 724 int n;
695 725
696 KASSERT(CPU_IS_PRIMARY(curcpu())); 726 KASSERT(CPU_IS_PRIMARY(curcpu()));
697 727
698 LIST_INIT(&sc->sc_cpu_init); 728 LIST_INIT(&sc->sc_lpi_callbacks);
699 729
700 for (n = 0; n < MAXCPUS; n++) 730 for (n = 0; n < MAXCPUS; n++)
701 sc->sc_irouter[n] = UINT64_MAX; 731 sc->sc_irouter[n] = UINT64_MAX;
702 732
703 sc->sc_pic.pic_ops = &gicv3_picops; 733 sc->sc_pic.pic_ops = &gicv3_picops;
704 sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(gicd_typer); 734 sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(gicd_typer);
705 snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "gicv3"); 735 snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "gicv3");
706#ifdef MULTIPROCESSOR 736#ifdef MULTIPROCESSOR
707 sc->sc_pic.pic_cpus = kcpuset_running; 737 sc->sc_pic.pic_cpus = kcpuset_running;
708#endif 738#endif
709 pic_add(&sc->sc_pic, 0); 739 pic_add(&sc->sc_pic, 0);
710 740
711 if ((gicd_typer & GICD_TYPER_LPIS) != 0) { 741 if ((gicd_typer & GICD_TYPER_LPIS) != 0) {

cvs diff -r1.3 -r1.4 src/sys/arch/arm/cortex/gicv3.h (expand / switch to unified diff)

--- src/sys/arch/arm/cortex/gicv3.h 2018/11/10 01:56:28 1.3
+++ src/sys/arch/arm/cortex/gicv3.h 2018/11/10 11:46:31 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gicv3.h,v 1.3 2018/11/10 01:56:28 jmcneill Exp $ */ 1/* $NetBSD: gicv3.h,v 1.4 2018/11/10 11:46:31 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca> 4 * Copyright (c) 2018 Jared McNeill <jmcneill@invisible.ca>
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -28,53 +28,56 @@ @@ -28,53 +28,56 @@
28 28
29#ifndef _ARM_CORTEX_GICV3_H 29#ifndef _ARM_CORTEX_GICV3_H
30#define _ARM_CORTEX_GICV3_H 30#define _ARM_CORTEX_GICV3_H
31 31
32#include <sys/intr.h> 32#include <sys/intr.h>
33 33
34struct gicv3_dma { 34struct gicv3_dma {
35 bus_dma_segment_t segs[1]; 35 bus_dma_segment_t segs[1];
36 bus_dmamap_t map; 36 bus_dmamap_t map;
37 uint8_t *base; 37 uint8_t *base;
38 bus_size_t len; 38 bus_size_t len;
39}; 39};
40 40
41struct gicv3_cpu_init { 41struct gicv3_lpi_callback {
42 void (*func)(void *, struct cpu_info *ci); 42 void (*cpu_init)(void *, struct cpu_info *);
43 void *arg; 43 void (*get_affinity)(void *, size_t, kcpuset_t *);
 44 int (*set_affinity)(void *, size_t, const kcpuset_t *);
44 45
45 LIST_ENTRY(gicv3_cpu_init) list; 46 void *priv;
 47
 48 LIST_ENTRY(gicv3_lpi_callback) list;
46}; 49};
47 50
48struct gicv3_softc { 51struct gicv3_softc {
49 struct pic_softc sc_pic; /* SGI/PPI/SGIs */ 52 struct pic_softc sc_pic; /* SGI/PPI/SGIs */
50 struct pic_softc sc_lpi; /* LPIs */ 53 struct pic_softc sc_lpi; /* LPIs */
51 device_t sc_dev; 54 device_t sc_dev;
52 55
53 bus_space_tag_t sc_bst; 56 bus_space_tag_t sc_bst;
54 bus_dma_tag_t sc_dmat; 57 bus_dma_tag_t sc_dmat;
55 58
56 bus_space_handle_t sc_bsh_d; /* GICD */ 59 bus_space_handle_t sc_bsh_d; /* GICD */
57 bus_space_handle_t *sc_bsh_r; /* GICR */ 60 bus_space_handle_t *sc_bsh_r; /* GICR */
58 u_int sc_bsh_r_count; 61 u_int sc_bsh_r_count;
59 62
60 uint32_t sc_enabled_sgippi; 63 uint32_t sc_enabled_sgippi;
61 uint64_t sc_irouter[MAXCPUS]; 64 uint64_t sc_irouter[MAXCPUS];
62 65
63 /* LPI configuration table */ 66 /* LPI configuration table */
64 struct gicv3_dma sc_lpiconf; 67 struct gicv3_dma sc_lpiconf;
65 68
66 /* LPI pending tables */ 69 /* LPI pending tables */
67 struct gicv3_dma sc_lpipend[MAXCPUS]; 70 struct gicv3_dma sc_lpipend[MAXCPUS];
68 71
69 /* Unique identifier for PEs */ 72 /* Unique identifier for PEs */
70 u_int sc_processor_id[MAXCPUS]; 73 u_int sc_processor_id[MAXCPUS];
71 74
72 /* CPU init callbacks */ 75 /* Callbacks */
73 LIST_HEAD(, gicv3_cpu_init) sc_cpu_init; 76 LIST_HEAD(, gicv3_lpi_callback) sc_lpi_callbacks;
74}; 77};
75 78
76int gicv3_init(struct gicv3_softc *); 79int gicv3_init(struct gicv3_softc *);
77void gicv3_dma_alloc(struct gicv3_softc *, struct gicv3_dma *, bus_size_t, bus_size_t); 80void gicv3_dma_alloc(struct gicv3_softc *, struct gicv3_dma *, bus_size_t, bus_size_t);
78void gicv3_irq_handler(void *); 81void gicv3_irq_handler(void *);
79 82
80#endif /* _ARM_CORTEX_GICV3_H */ 83#endif /* _ARM_CORTEX_GICV3_H */

cvs diff -r1.1 -r1.2 src/sys/arch/arm/cortex/gicv3_its.c (expand / switch to unified diff)

--- src/sys/arch/arm/cortex/gicv3_its.c 2018/11/09 23:36:24 1.1
+++ src/sys/arch/arm/cortex/gicv3_its.c 2018/11/10 11:46:31 1.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gicv3_its.c,v 1.1 2018/11/09 23:36:24 jmcneill Exp $ */ 1/* $NetBSD: gicv3_its.c,v 1.2 2018/11/10 11:46:31 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc. 4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jared McNeill <jmcneill@invisible.ca>. 8 * by Jared McNeill <jmcneill@invisible.ca>.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -22,27 +22,27 @@ @@ -22,27 +22,27 @@
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#define _INTR_PRIVATE 32#define _INTR_PRIVATE
33 33
34#include <sys/cdefs.h> 34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.1 2018/11/09 23:36:24 jmcneill Exp $"); 35__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.2 2018/11/10 11:46:31 jmcneill Exp $");
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/kmem.h> 38#include <sys/kmem.h>
39#include <sys/bus.h> 39#include <sys/bus.h>
40#include <sys/cpu.h> 40#include <sys/cpu.h>
41 41
42#include <uvm/uvm.h> 42#include <uvm/uvm.h>
43 43
44#include <dev/pci/pcireg.h> 44#include <dev/pci/pcireg.h>
45#include <dev/pci/pcivar.h> 45#include <dev/pci/pcivar.h>
46 46
47#include <arm/pic/picvar.h> 47#include <arm/pic/picvar.h>
48#include <arm/cortex/gicv3_its.h> 48#include <arm/cortex/gicv3_its.h>
@@ -146,26 +146,43 @@ gits_command_mapi(struct gicv3_its *its, @@ -146,26 +146,43 @@ gits_command_mapi(struct gicv3_its *its,
146 146
147 /* 147 /*
148 * Map the event defined by EventID and DeviceID into an ITT entry with ICID and pINTID = EventID 148 * Map the event defined by EventID and DeviceID into an ITT entry with ICID and pINTID = EventID
149 */ 149 */
150 memset(&cmd, 0, sizeof(cmd)); 150 memset(&cmd, 0, sizeof(cmd));
151 cmd.dw[0] = GITS_CMD_MAPI | ((uint64_t)deviceid << 32); 151 cmd.dw[0] = GITS_CMD_MAPI | ((uint64_t)deviceid << 32);
152 cmd.dw[1] = eventid; 152 cmd.dw[1] = eventid;
153 cmd.dw[2] = icid; 153 cmd.dw[2] = icid;
154 154
155 gits_command(its, &cmd); 155 gits_command(its, &cmd);
156} 156}
157 157
158static inline void 158static inline void
 159gits_command_movi(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid, uint16_t icid)
 160{
 161 struct gicv3_its_command cmd;
 162
 163 /*
 164 * Update the ICID field in the ITT entry for the event defined by DeviceID and
 165 * EventID.
 166 */
 167 memset(&cmd, 0, sizeof(cmd));
 168 cmd.dw[0] = GITS_CMD_MOVI | ((uint64_t)deviceid << 32);
 169 cmd.dw[1] = eventid;
 170 cmd.dw[2] = icid;
 171
 172 gits_command(its, &cmd);
 173}
 174
 175static inline void
159gits_command_inv(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid) 176gits_command_inv(struct gicv3_its *its, uint32_t deviceid, uint32_t eventid)
160{ 177{
161 struct gicv3_its_command cmd; 178 struct gicv3_its_command cmd;
162 179
163 /* 180 /*
164 * Ensure any caching in the redistributors associated with the specified 181 * Ensure any caching in the redistributors associated with the specified
165 * EventID is consistent with the LPI configuration tables. 182 * EventID is consistent with the LPI configuration tables.
166 */ 183 */
167 memset(&cmd, 0, sizeof(cmd)); 184 memset(&cmd, 0, sizeof(cmd));
168 cmd.dw[0] = GITS_CMD_INV | ((uint64_t)deviceid << 32); 185 cmd.dw[0] = GITS_CMD_INV | ((uint64_t)deviceid << 32);
169 cmd.dw[1] = eventid; 186 cmd.dw[1] = eventid;
170 187
171 gits_command(its, &cmd); 188 gits_command(its, &cmd);
@@ -369,28 +386,28 @@ gicv3_its_msix_disable(struct gicv3_its  @@ -369,28 +386,28 @@ gicv3_its_msix_disable(struct gicv3_its
369 if (!pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, NULL)) 386 if (!pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, NULL))
370 panic("gicv3_its_msix_disable: device is not MSI-X-capable"); 387 panic("gicv3_its_msix_disable: device is not MSI-X-capable");
371 388
372 ctl = pci_conf_read(pc, tag, off + PCI_MSIX_CTL); 389 ctl = pci_conf_read(pc, tag, off + PCI_MSIX_CTL);
373 ctl &= ~PCI_MSIX_CTL_ENABLE; 390 ctl &= ~PCI_MSIX_CTL_ENABLE;
374 pci_conf_write(pc, tag, off + PCI_MSIX_CTL, ctl); 391 pci_conf_write(pc, tag, off + PCI_MSIX_CTL, ctl);
375} 392}
376 393
377static pci_intr_handle_t * 394static pci_intr_handle_t *
378gicv3_its_msi_alloc(struct arm_pci_msi *msi, int *count, 395gicv3_its_msi_alloc(struct arm_pci_msi *msi, int *count,
379 const struct pci_attach_args *pa, bool exact) 396 const struct pci_attach_args *pa, bool exact)
380{ 397{
381 struct gicv3_its * const its = msi->msi_priv; 398 struct gicv3_its * const its = msi->msi_priv;
 399 struct cpu_info * const ci = cpu_lookup(0);
382 struct gicv3_its_device *dev; 400 struct gicv3_its_device *dev;
383 struct cpu_info *ci = curcpu(); /* XXX */ 
384 pci_intr_handle_t *vectors; 401 pci_intr_handle_t *vectors;
385 int n, off; 402 int n, off;
386 403
387 if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &off, NULL)) 404 if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &off, NULL))
388 return NULL; 405 return NULL;
389 406
390 const uint64_t typer = gits_read_8(its, GITS_TYPER); 407 const uint64_t typer = gits_read_8(its, GITS_TYPER);
391 const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; 408 const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1;
392 if (*count == 0 || *count > (1 << id_bits)) 409 if (*count == 0 || *count > (1 << id_bits))
393 return NULL; 410 return NULL;
394 411
395 const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); 412 const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag);
396 413
@@ -402,43 +419,48 @@ gicv3_its_msi_alloc(struct arm_pci_msi * @@ -402,43 +419,48 @@ gicv3_its_msi_alloc(struct arm_pci_msi *
402 gits_wait(its); 419 gits_wait(its);
403 420
404 vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); 421 vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP);
405 for (n = 0; n < *count; n++) { 422 for (n = 0; n < *count; n++) {
406 const int lpi = gicv3_its_msi_alloc_lpi(its, pa); 423 const int lpi = gicv3_its_msi_alloc_lpi(its, pa);
407 vectors[n] = ARM_PCI_INTR_MSI | 424 vectors[n] = ARM_PCI_INTR_MSI |
408 __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | 425 __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) |
409 __SHIFTIN(n, ARM_PCI_INTR_MSI_VEC) | 426 __SHIFTIN(n, ARM_PCI_INTR_MSI_VEC) |
410 __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME); 427 __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME);
411 428
412 gicv3_its_msi_enable(its, lpi); 429 gicv3_its_msi_enable(its, lpi);
413 430
414 /* 431 /*
 432 * Record target PE
 433 */
 434 its->its_targets[lpi - its->its_pic->pic_irqbase] = ci;
 435
 436 /*
415 * Map event 437 * Map event
416 */ 438 */
417 gits_command_mapi(its, devid, lpi, cpu_index(ci)); 439 gits_command_mapi(its, devid, lpi, cpu_index(ci));
418 gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); 440 gits_command_sync(its, its->its_rdbase[cpu_index(ci)]);
419 } 441 }
420 gits_wait(its); 442 gits_wait(its);
421 443
422 return vectors; 444 return vectors;
423} 445}
424 446
425static pci_intr_handle_t * 447static pci_intr_handle_t *
426gicv3_its_msix_alloc(struct arm_pci_msi *msi, u_int *table_indexes, int *count, 448gicv3_its_msix_alloc(struct arm_pci_msi *msi, u_int *table_indexes, int *count,
427 const struct pci_attach_args *pa, bool exact) 449 const struct pci_attach_args *pa, bool exact)
428{ 450{
429 struct gicv3_its * const its = msi->msi_priv; 451 struct gicv3_its * const its = msi->msi_priv;
 452 struct cpu_info *ci = cpu_lookup(0);
430 struct gicv3_its_device *dev; 453 struct gicv3_its_device *dev;
431 struct cpu_info *ci = curcpu(); /* XXX */ 
432 pci_intr_handle_t *vectors; 454 pci_intr_handle_t *vectors;
433 bus_space_tag_t bst; 455 bus_space_tag_t bst;
434 bus_space_handle_t bsh; 456 bus_space_handle_t bsh;
435 bus_size_t bsz; 457 bus_size_t bsz;
436 uint32_t table_offset, table_size; 458 uint32_t table_offset, table_size;
437 int n, off, bar, error; 459 int n, off, bar, error;
438 pcireg_t tbl; 460 pcireg_t tbl;
439 461
440 if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSIX, &off, NULL)) 462 if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSIX, &off, NULL))
441 return NULL; 463 return NULL;
442 464
443 const uint64_t typer = gits_read_8(its, GITS_TYPER); 465 const uint64_t typer = gits_read_8(its, GITS_TYPER);
444 const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; 466 const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1;
@@ -469,26 +491,31 @@ gicv3_its_msix_alloc(struct arm_pci_msi  @@ -469,26 +491,31 @@ gicv3_its_msix_alloc(struct arm_pci_msi
469 491
470 vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); 492 vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP);
471 for (n = 0; n < *count; n++) { 493 for (n = 0; n < *count; n++) {
472 const int lpi = gicv3_its_msi_alloc_lpi(its, pa); 494 const int lpi = gicv3_its_msi_alloc_lpi(its, pa);
473 const int msix_vec = table_indexes ? table_indexes[n] : n; 495 const int msix_vec = table_indexes ? table_indexes[n] : n;
474 vectors[msix_vec] = ARM_PCI_INTR_MSIX | 496 vectors[msix_vec] = ARM_PCI_INTR_MSIX |
475 __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) | 497 __SHIFTIN(lpi, ARM_PCI_INTR_IRQ) |
476 __SHIFTIN(msix_vec, ARM_PCI_INTR_MSI_VEC) | 498 __SHIFTIN(msix_vec, ARM_PCI_INTR_MSI_VEC) |
477 __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME); 499 __SHIFTIN(msi->msi_id, ARM_PCI_INTR_FRAME);
478 500
479 gicv3_its_msix_enable(its, lpi, msix_vec, bst, bsh); 501 gicv3_its_msix_enable(its, lpi, msix_vec, bst, bsh);
480 502
481 /* 503 /*
 504 * Record target PE
 505 */
 506 its->its_targets[lpi - its->its_pic->pic_irqbase] = ci;
 507
 508 /*
482 * Map event 509 * Map event
483 */ 510 */
484 gits_command_mapi(its, devid, lpi, cpu_index(ci)); 511 gits_command_mapi(its, devid, lpi, cpu_index(ci));
485 gits_command_sync(its, its->its_rdbase[cpu_index(ci)]); 512 gits_command_sync(its, its->its_rdbase[cpu_index(ci)]);
486 } 513 }
487 gits_wait(its); 514 gits_wait(its);
488 515
489 bus_space_unmap(bst, bsh, bsz); 516 bus_space_unmap(bst, bsh, bsz);
490 517
491 return vectors; 518 return vectors;
492} 519}
493 520
494static void * 521static void *
@@ -521,26 +548,27 @@ gicv3_its_msi_intr_release(struct arm_pc @@ -521,26 +548,27 @@ gicv3_its_msi_intr_release(struct arm_pc
521 int count) 548 int count)
522{ 549{
523 struct gicv3_its * const its = msi->msi_priv; 550 struct gicv3_its * const its = msi->msi_priv;
524 int n; 551 int n;
525 552
526 for (n = 0; n < count; n++) { 553 for (n = 0; n < count; n++) {
527 const int lpi = __SHIFTOUT(pih[n], ARM_PCI_INTR_IRQ); 554 const int lpi = __SHIFTOUT(pih[n], ARM_PCI_INTR_IRQ);
528 KASSERT(lpi >= its->its_pic->pic_irqbase); 555 KASSERT(lpi >= its->its_pic->pic_irqbase);
529 if (pih[n] & ARM_PCI_INTR_MSIX) 556 if (pih[n] & ARM_PCI_INTR_MSIX)
530 gicv3_its_msix_disable(its, lpi); 557 gicv3_its_msix_disable(its, lpi);
531 if (pih[n] & ARM_PCI_INTR_MSI) 558 if (pih[n] & ARM_PCI_INTR_MSI)
532 gicv3_its_msi_disable(its, lpi); 559 gicv3_its_msi_disable(its, lpi);
533 gicv3_its_msi_free_lpi(its, lpi); 560 gicv3_its_msi_free_lpi(its, lpi);
 561 its->its_targets[lpi - its->its_pic->pic_irqbase] = NULL;
534 struct intrsource * const is = 562 struct intrsource * const is =
535 its->its_pic->pic_sources[lpi - its->its_pic->pic_irqbase]; 563 its->its_pic->pic_sources[lpi - its->its_pic->pic_irqbase];
536 if (is != NULL) 564 if (is != NULL)
537 pic_disestablish_source(is); 565 pic_disestablish_source(is);
538 } 566 }
539} 567}
540 568
541static void 569static void
542gicv3_its_command_init(struct gicv3_softc *sc, struct gicv3_its *its) 570gicv3_its_command_init(struct gicv3_softc *sc, struct gicv3_its *its)
543{ 571{
544 uint64_t cbaser; 572 uint64_t cbaser;
545 573
546 gicv3_dma_alloc(sc, &its->its_cmd, GITS_COMMANDS_SIZE, GITS_COMMANDS_ALIGN); 574 gicv3_dma_alloc(sc, &its->its_cmd, GITS_COMMANDS_SIZE, GITS_COMMANDS_ALIGN);
@@ -648,51 +676,92 @@ gicv3_its_cpu_init(void *priv, struct cp @@ -648,51 +676,92 @@ gicv3_its_cpu_init(void *priv, struct cp
648 } else { 676 } else {
649 rdbase = (uint64_t)sc->sc_processor_id[cpu_index(ci)] << 16; 677 rdbase = (uint64_t)sc->sc_processor_id[cpu_index(ci)] << 16;
650 } 678 }
651 its->its_rdbase[cpu_index(ci)] = rdbase; 679 its->its_rdbase[cpu_index(ci)] = rdbase;
652 680
653 /* 681 /*
654 * Map collection ID of this CPU's index to this CPU's redistributor. 682 * Map collection ID of this CPU's index to this CPU's redistributor.
655 */ 683 */
656 gits_command_mapc(its, cpu_index(ci), rdbase, true); 684 gits_command_mapc(its, cpu_index(ci), rdbase, true);
657 gits_command_invall(its, cpu_index(ci)); 685 gits_command_invall(its, cpu_index(ci));
658 gits_wait(its); 686 gits_wait(its);
659} 687}
660 688
 689static void
 690gicv3_its_get_affinity(void *priv, size_t irq, kcpuset_t *affinity)
 691{
 692 struct gicv3_its * const its = priv;
 693 struct cpu_info *ci;
 694
 695 kcpuset_zero(affinity);
 696 ci = its->its_targets[irq - its->its_pic->pic_irqbase];
 697 if (ci)
 698 kcpuset_set(affinity, cpu_index(ci));
 699}
 700
 701static int
 702gicv3_its_set_affinity(void *priv, size_t irq, const kcpuset_t *affinity)
 703{
 704 struct gicv3_its * const its = priv;
 705 const struct pci_attach_args *pa;
 706 struct cpu_info *ci;
 707
 708 const int set = kcpuset_countset(affinity);
 709 if (set != 1)
 710 return EINVAL;
 711
 712 pa = its->its_pa[irq - its->its_pic->pic_irqbase];
 713 if (pa == NULL)
 714 return EINVAL;
 715
 716 ci = cpu_lookup(kcpuset_ffs(affinity));
 717
 718 const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag);
 719 gits_command_movi(its, devid, devid, cpu_index(ci));
 720 gits_command_sync(its, its->its_rdbase[cpu_index(ci)]);
 721
 722 its->its_targets[irq - its->its_pic->pic_irqbase] = ci;
 723
 724 return 0;
 725}
 726
661int 727int
662gicv3_its_init(struct gicv3_softc *sc, bus_space_handle_t bsh, 728gicv3_its_init(struct gicv3_softc *sc, bus_space_handle_t bsh,
663 uint64_t its_base, uint32_t its_id) 729 uint64_t its_base, uint32_t its_id)
664{ 730{
665 struct gicv3_its *its; 731 struct gicv3_its *its;
666 struct arm_pci_msi *msi; 732 struct arm_pci_msi *msi;
667 733
668 const uint64_t typer = bus_space_read_8(sc->sc_bst, bsh, GITS_TYPER); 734 const uint64_t typer = bus_space_read_8(sc->sc_bst, bsh, GITS_TYPER);
669 if ((typer & GITS_TYPER_Physical) == 0) 735 if ((typer & GITS_TYPER_Physical) == 0)
670 return ENXIO; 736 return ENXIO;
671 737
672 its = kmem_alloc(sizeof(*its), KM_SLEEP); 738 its = kmem_alloc(sizeof(*its), KM_SLEEP);
673 its->its_id = its_id; 739 its->its_id = its_id;
674 its->its_bst = sc->sc_bst; 740 its->its_bst = sc->sc_bst;
675 its->its_bsh = bsh; 741 its->its_bsh = bsh;
676 its->its_dmat = sc->sc_dmat; 742 its->its_dmat = sc->sc_dmat;
677 its->its_base = its_base; 743 its->its_base = its_base;
678 its->its_pic = &sc->sc_lpi; 744 its->its_pic = &sc->sc_lpi;
679 KASSERT(its->its_pic->pic_maxsources > 0); 745 KASSERT(its->its_pic->pic_maxsources > 0);
680 its->its_pa = kmem_zalloc(sizeof(struct pci_attach_args *) * its->its_pic->pic_maxsources, KM_SLEEP); 746 its->its_pa = kmem_zalloc(sizeof(struct pci_attach_args *) * its->its_pic->pic_maxsources, KM_SLEEP);
 747 its->its_targets = kmem_zalloc(sizeof(struct cpu_info *) * its->its_pic->pic_maxsources, KM_SLEEP);
681 its->its_gic = sc; 748 its->its_gic = sc;
682 its->its_init.func = gicv3_its_cpu_init; 749 its->its_cb.cpu_init = gicv3_its_cpu_init;
683 its->its_init.arg = its; 750 its->its_cb.get_affinity = gicv3_its_get_affinity;
 751 its->its_cb.set_affinity = gicv3_its_set_affinity;
 752 its->its_cb.priv = its;
684 LIST_INIT(&its->its_devices); 753 LIST_INIT(&its->its_devices);
685 LIST_INSERT_HEAD(&sc->sc_cpu_init, &its->its_init, list); 754 LIST_INSERT_HEAD(&sc->sc_lpi_callbacks, &its->its_cb, list);
686 755
687 gicv3_its_command_init(sc, its); 756 gicv3_its_command_init(sc, its);
688 gicv3_its_table_init(sc, its); 757 gicv3_its_table_init(sc, its);
689 758
690 gicv3_its_enable(sc, its); 759 gicv3_its_enable(sc, its);
691 760
692 gicv3_its_cpu_init(its, curcpu()); 761 gicv3_its_cpu_init(its, curcpu());
693 762
694 msi = &its->its_msi; 763 msi = &its->its_msi;
695 msi->msi_dev = sc->sc_dev; 764 msi->msi_dev = sc->sc_dev;
696 msi->msi_priv = its; 765 msi->msi_priv = its;
697 msi->msi_alloc = gicv3_its_msi_alloc; 766 msi->msi_alloc = gicv3_its_msi_alloc;
698 msi->msix_alloc = gicv3_its_msix_alloc; 767 msi->msix_alloc = gicv3_its_msix_alloc;

cvs diff -r1.1 -r1.2 src/sys/arch/arm/cortex/gicv3_its.h (expand / switch to unified diff)

--- src/sys/arch/arm/cortex/gicv3_its.h 2018/11/09 23:36:24 1.1
+++ src/sys/arch/arm/cortex/gicv3_its.h 2018/11/10 11:46:31 1.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: gicv3_its.h,v 1.1 2018/11/09 23:36:24 jmcneill Exp $ */ 1/* $NetBSD: gicv3_its.h,v 1.2 2018/11/10 11:46:31 jmcneill Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc. 4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jared McNeill <jmcneill@invisible.ca>. 8 * by Jared McNeill <jmcneill@invisible.ca>.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -42,29 +42,30 @@ struct gicv3_its_device { @@ -42,29 +42,30 @@ struct gicv3_its_device {
42 42
43 LIST_ENTRY(gicv3_its_device) dev_list; 43 LIST_ENTRY(gicv3_its_device) dev_list;
44}; 44};
45 45
46struct gicv3_its { 46struct gicv3_its {
47 bus_space_tag_t its_bst; 47 bus_space_tag_t its_bst;
48 bus_space_handle_t its_bsh; 48 bus_space_handle_t its_bsh;
49 bus_dma_tag_t its_dmat; 49 bus_dma_tag_t its_dmat;
50 uint32_t its_id; 50 uint32_t its_id;
51 uint64_t its_base; 51 uint64_t its_base;
52 uint64_t its_rdbase[MAXCPUS]; 52 uint64_t its_rdbase[MAXCPUS];
53 53
54 struct gicv3_softc *its_gic; 54 struct gicv3_softc *its_gic;
55 struct gicv3_cpu_init its_init; 55 struct gicv3_lpi_callback its_cb;
56 56
57 struct pic_softc *its_pic; 57 struct pic_softc *its_pic;
58 const struct pci_attach_args **its_pa; 58 const struct pci_attach_args **its_pa;
 59 struct cpu_info **its_targets;
59 60
60 LIST_HEAD(, gicv3_its_device) its_devices; 61 LIST_HEAD(, gicv3_its_device) its_devices;
61 62
62 struct gicv3_dma its_cmd; /* Command queue */ 63 struct gicv3_dma its_cmd; /* Command queue */
63 struct gicv3_dma its_tab[8]; /* ITS tables */ 64 struct gicv3_dma its_tab[8]; /* ITS tables */
64 65
65 struct arm_pci_msi its_msi; 66 struct arm_pci_msi its_msi;
66}; 67};
67 68
68int gicv3_its_init(struct gicv3_softc *, bus_space_handle_t, uint64_t, uint32_t); 69int gicv3_its_init(struct gicv3_softc *, bus_space_handle_t, uint64_t, uint32_t);
69 70
70#endif /* !_ARM_CORTEX_GICV3_ITS_H */ 71#endif /* !_ARM_CORTEX_GICV3_ITS_H */