diff mbox series

[2/2] riscv: virt: Fix interrupt mapping

Message ID 1542754831-25567-2-git-send-email-linux@roeck-us.net (mailing list archive)
State New, archived
Headers show
Series [1/2] riscv: virt: Fix pcie memory ranges | expand

Commit Message

Guenter Roeck Nov. 20, 2018, 11 p.m. UTC
- Interrupt map width is 6, not 7
	address (3), pci interrupt (1), controller phandle (1), irq (1)
- Since the interrupt map is the default pci interrupt map, we can not
  omit devfn from the mapping function.
- It is not necessary to specify "interrupt-parent" and "interrupts"
  since both are part of interrupt-map.

Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
 hw/riscv/virt.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

Comments

Alistair Francis Nov. 21, 2018, 12:49 a.m. UTC | #1
On Tue, Nov 20, 2018 at 3:01 PM Guenter Roeck <linux@roeck-us.net> wrote:
>
> - Interrupt map width is 6, not 7
>         address (3), pci interrupt (1), controller phandle (1), irq (1)
> - Since the interrupt map is the default pci interrupt map, we can not
>   omit devfn from the mapping function.
> - It is not necessary to specify "interrupt-parent" and "interrupts"
>   since both are part of interrupt-map.
>
> Signed-off-by: Guenter Roeck <linux@roeck-us.net>

Hey Gunter,

Thanks again for the patch!

Also unfortunately Logan Gunthorpe had already sent me fixes for the
interrupt mappings as well. You can see his tree here:
https://github.com/lsgunth/qemu/commits/riscv_pci

If you have comments on that implementation just let me know.
Hopefully I will be able to send out a new version tomorrow.

I really appreciate your help! It's always good to have multiple
people working and looking over everything.

Alistair

> ---
>  hw/riscv/virt.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 675899d..fb3a492 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -65,35 +65,37 @@ static const struct MemmapEntry {
>      [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
>  };
>
> -#define INTERREUPT_MAP_WIDTH 7
> +#define INTERRUPT_MAP_WIDTH 6
>
>  static void create_pcie_irq_map(void *fdt, char *nodename,
>                                  uint32_t plic_phandle)
>  {
> -    int pin;
> -    uint32_t full_irq_map[GPEX_NUM_IRQS * INTERREUPT_MAP_WIDTH] = { 0 };
> +    int devfn, pin;
> +    uint32_t full_irq_map[GPEX_NUM_IRQS * 4 * INTERRUPT_MAP_WIDTH] = { 0 };
>      uint32_t *irq_map = full_irq_map;
>
> +    for (devfn = 0; devfn <= 0x18; devfn += 0x8) {
>          for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
> -            int irq_nr = PCIE_IRQ + (pin % PCI_NUM_PINS);
> +            int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
>              int i;
>
> -            uint32_t map[] = {
> -                0, 0, 0,
> -                pin + 1, plic_phandle, 0, irq_nr};
> +            uint32_t map[INTERRUPT_MAP_WIDTH] = {
> +                devfn << 8, 0, 0,
> +                pin + 1, plic_phandle, irq_nr};
>
>              /* Convert map to big endian */
> -            for (i = 0; i < INTERREUPT_MAP_WIDTH; i++) {
> +            for (i = 0; i < INTERRUPT_MAP_WIDTH; i++) {
>                  irq_map[i] = cpu_to_be32(map[i]);
>              }
> -            irq_map += INTERREUPT_MAP_WIDTH;
> +            irq_map += INTERRUPT_MAP_WIDTH;
>          }
> +    }
>
>      qemu_fdt_setprop(fdt, nodename, "interrupt-map",
>                       full_irq_map, sizeof(full_irq_map));
>
>      qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
> -                           0, 0, 0, 0x7);
> +                           0x1800, 0, 0, 0x7);
>  }
>
>  static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
> @@ -261,8 +263,6 @@ static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
>                                   2, memmap[VIRT_PCIE_MMIO_HIGH].base,
>                                   2, memmap[VIRT_PCIE_MMIO_HIGH].size);
>
> -    qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
> -    qemu_fdt_setprop_cells(fdt, nodename, "interrupts", PCIE_IRQ);
>      create_pcie_irq_map(fdt, nodename, plic_phandle);
>
>      nodename = g_strdup_printf("/test@%lx",
> --
> 2.7.4
>
>
diff mbox series

Patch

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 675899d..fb3a492 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -65,35 +65,37 @@  static const struct MemmapEntry {
     [VIRT_PCIE_ECAM] = { 0x30000000, 0x10000000 },
 };
 
-#define INTERREUPT_MAP_WIDTH 7
+#define INTERRUPT_MAP_WIDTH 6
 
 static void create_pcie_irq_map(void *fdt, char *nodename,
                                 uint32_t plic_phandle)
 {
-    int pin;
-    uint32_t full_irq_map[GPEX_NUM_IRQS * INTERREUPT_MAP_WIDTH] = { 0 };
+    int devfn, pin;
+    uint32_t full_irq_map[GPEX_NUM_IRQS * 4 * INTERRUPT_MAP_WIDTH] = { 0 };
     uint32_t *irq_map = full_irq_map;
 
+    for (devfn = 0; devfn <= 0x18; devfn += 0x8) {
         for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
-            int irq_nr = PCIE_IRQ + (pin % PCI_NUM_PINS);
+            int irq_nr = PCIE_IRQ + ((pin + PCI_SLOT(devfn)) % PCI_NUM_PINS);
             int i;
 
-            uint32_t map[] = {
-                0, 0, 0,
-                pin + 1, plic_phandle, 0, irq_nr};
+            uint32_t map[INTERRUPT_MAP_WIDTH] = {
+                devfn << 8, 0, 0,
+                pin + 1, plic_phandle, irq_nr};
 
             /* Convert map to big endian */
-            for (i = 0; i < INTERREUPT_MAP_WIDTH; i++) {
+            for (i = 0; i < INTERRUPT_MAP_WIDTH; i++) {
                 irq_map[i] = cpu_to_be32(map[i]);
             }
-            irq_map += INTERREUPT_MAP_WIDTH;
+            irq_map += INTERRUPT_MAP_WIDTH;
         }
+    }
 
     qemu_fdt_setprop(fdt, nodename, "interrupt-map",
                      full_irq_map, sizeof(full_irq_map));
 
     qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask",
-                           0, 0, 0, 0x7);
+                           0x1800, 0, 0, 0x7);
 }
 
 static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
@@ -261,8 +263,6 @@  static void *create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
                                  2, memmap[VIRT_PCIE_MMIO_HIGH].base,
                                  2, memmap[VIRT_PCIE_MMIO_HIGH].size);
 
-    qemu_fdt_setprop_cells(fdt, nodename, "interrupt-parent", plic_phandle);
-    qemu_fdt_setprop_cells(fdt, nodename, "interrupts", PCIE_IRQ);
     create_pcie_irq_map(fdt, nodename, plic_phandle);
 
     nodename = g_strdup_printf("/test@%lx",