diff mbox

[v2,24/74] acpi: extend aml_interrupt() to support multiple irqs

Message ID 1449747273-22915-1-git-send-email-imammedo@redhat.com
State New
Headers show

Commit Message

Igor Mammedov Dec. 10, 2015, 11:34 a.m. UTC
ASL Interrupt() macro translates to Extended Interrupt Descriptor
which supports variable number of IRQs. It will be used for
conversion of ASL code for pc/q35 machines that use it for
returning several IRQs in _PSR object.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v2:
 - fix incorrect irq number calculation in ARM:acpi_dsdt_add_virtio()
     Reported-by: Shannon Zhao <zhaoshenglong@huawei.com>
---
 hw/acpi/aml-build.c         | 22 +++++++++++++---------
 hw/arm/virt-acpi-build.c    | 23 ++++++++++++-----------
 include/hw/acpi/aml-build.h |  2 +-
 3 files changed, 26 insertions(+), 21 deletions(-)

Comments

Shannon Zhao Dec. 11, 2015, 1:51 a.m. UTC | #1
On 2015/12/10 19:34, Igor Mammedov wrote:
> ASL Interrupt() macro translates to Extended Interrupt Descriptor
> which supports variable number of IRQs. It will be used for
> conversion of ASL code for pc/q35 machines that use it for
> returning several IRQs in _PSR object.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org>

Also, I'll include this patch in my patch set[1] as you suggested.

[1] Add system_powerdown support on ARM for ACPI and DT
> ---
> v2:
>  - fix incorrect irq number calculation in ARM:acpi_dsdt_add_virtio()
>      Reported-by: Shannon Zhao <zhaoshenglong@huawei.com>
> ---
>  hw/acpi/aml-build.c         | 22 +++++++++++++---------
>  hw/arm/virt-acpi-build.c    | 23 ++++++++++++-----------
>  include/hw/acpi/aml-build.h |  2 +-
>  3 files changed, 26 insertions(+), 21 deletions(-)
> 
> diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
> index 2ca9207..ee64d12 100644
> --- a/hw/acpi/aml-build.c
> +++ b/hw/acpi/aml-build.c
> @@ -667,23 +667,27 @@ Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
>  Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
>                     AmlLevelAndEdge level_and_edge,
>                     AmlActiveHighAndLow high_and_low, AmlShared shared,
> -                   uint32_t irq)
> +                   uint32_t *irq_list, uint8_t irq_count)
>  {
> +    int i;
>      Aml *var = aml_alloc();
>      uint8_t irq_flags = con_and_pro | (level_and_edge << 1)
>                          | (high_and_low << 2) | (shared << 3);
> +    const int header_bytes_in_len = 2;
> +    uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t);
> +
> +    assert(irq_count > 0);
>  
>      build_append_byte(var->buf, 0x89); /* Extended irq descriptor */
> -    build_append_byte(var->buf, 6); /* Length, bits[7:0] minimum value = 6 */
> -    build_append_byte(var->buf, 0); /* Length, bits[15:8] minimum value = 0 */
> +    build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */
> +    build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */
>      build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */
> -    build_append_byte(var->buf, 0x01);      /* Interrupt table length = 1 */
> +    build_append_byte(var->buf, irq_count);   /* Interrupt table length */
>  
> -    /* Interrupt Number */
> -    build_append_byte(var->buf, extract32(irq, 0, 8));  /* bits[7:0] */
> -    build_append_byte(var->buf, extract32(irq, 8, 8));  /* bits[15:8] */
> -    build_append_byte(var->buf, extract32(irq, 16, 8)); /* bits[23:16] */
> -    build_append_byte(var->buf, extract32(irq, 24, 8)); /* bits[31:24] */
> +    /* Interrupt Number List */
> +    for (i = 0; i < irq_count; i++) {
> +        build_append_int_noprefix(var->buf, irq_list[i], 4);
> +    }
>      return var;
>  }
>  
> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
> index 698b5f2..b0c1c4e 100644
> --- a/hw/arm/virt-acpi-build.c
> +++ b/hw/arm/virt-acpi-build.c
> @@ -71,7 +71,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
>  }
>  
>  static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
> -                                           int uart_irq)
> +                                           uint32_t uart_irq)
>  {
>      Aml *dev = aml_device("COM0");
>      aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011")));
> @@ -82,7 +82,7 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
>                                         uart_memmap->size, AML_READ_WRITE));
>      aml_append(crs,
>                 aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> -                             AML_EXCLUSIVE, uart_irq));
> +                             AML_EXCLUSIVE, &uart_irq, 1));
>      aml_append(dev, aml_name_decl("_CRS", crs));
>  
>      /* The _ADR entry is used to link this device to the UART described
> @@ -94,7 +94,7 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
>  }
>  
>  static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
> -                                          int rtc_irq)
> +                                          uint32_t rtc_irq)
>  {
>      Aml *dev = aml_device("RTC0");
>      aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013")));
> @@ -105,7 +105,7 @@ static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
>                                         rtc_memmap->size, AML_READ_WRITE));
>      aml_append(crs,
>                 aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> -                             AML_EXCLUSIVE, rtc_irq));
> +                             AML_EXCLUSIVE, &rtc_irq, 1));
>      aml_append(dev, aml_name_decl("_CRS", crs));
>      aml_append(scope, dev);
>  }
> @@ -136,14 +136,14 @@ static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap)
>  
>  static void acpi_dsdt_add_virtio(Aml *scope,
>                                   const MemMapEntry *virtio_mmio_memmap,
> -                                 int mmio_irq, int num)
> +                                 uint32_t mmio_irq, int num)
>  {
>      hwaddr base = virtio_mmio_memmap->base;
>      hwaddr size = virtio_mmio_memmap->size;
> -    int irq = mmio_irq;
>      int i;
>  
>      for (i = 0; i < num; i++) {
> +        uint32_t irq = mmio_irq + i;
>          Aml *dev = aml_device("VR%02u", i);
>          aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005")));
>          aml_append(dev, aml_name_decl("_UID", aml_int(i)));
> @@ -152,15 +152,15 @@ static void acpi_dsdt_add_virtio(Aml *scope,
>          aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE));
>          aml_append(crs,
>                     aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> -                                 AML_EXCLUSIVE, irq + i));
> +                                 AML_EXCLUSIVE, &irq, 1));
>          aml_append(dev, aml_name_decl("_CRS", crs));
>          aml_append(scope, dev);
>          base += size;
>      }
>  }
>  
> -static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
> -                              bool use_highmem)
> +static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
> +                              uint32_t irq, bool use_highmem)
>  {
>      Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
>      int i, bus_no;
> @@ -199,18 +199,19 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
>  
>      /* Create GSI link device */
>      for (i = 0; i < PCI_NUM_PINS; i++) {
> +        uint32_t irqs =  irq + i;
>          Aml *dev_gsi = aml_device("GSI%d", i);
>          aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F")));
>          aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0)));
>          crs = aml_resource_template();
>          aml_append(crs,
>                     aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> -                                 AML_EXCLUSIVE, irq + i));
> +                                 AML_EXCLUSIVE, &irqs, 1));
>          aml_append(dev_gsi, aml_name_decl("_PRS", crs));
>          crs = aml_resource_template();
>          aml_append(crs,
>                     aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
> -                                 AML_EXCLUSIVE, irq + i));
> +                                 AML_EXCLUSIVE, &irqs, 1));
>          aml_append(dev_gsi, aml_name_decl("_CRS", crs));
>          method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
>          aml_append(dev_gsi, method);
> diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
> index ca365c9..a3a058f 100644
> --- a/include/hw/acpi/aml-build.h
> +++ b/include/hw/acpi/aml-build.h
> @@ -253,7 +253,7 @@ Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
>  Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
>                     AmlLevelAndEdge level_and_edge,
>                     AmlActiveHighAndLow high_and_low, AmlShared shared,
> -                   uint32_t irq);
> +                   uint32_t *irq_list, uint8_t irq_count);
>  Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
>              uint8_t aln, uint8_t len);
>  Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
>
diff mbox

Patch

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 2ca9207..ee64d12 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -667,23 +667,27 @@  Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
 Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
                    AmlLevelAndEdge level_and_edge,
                    AmlActiveHighAndLow high_and_low, AmlShared shared,
-                   uint32_t irq)
+                   uint32_t *irq_list, uint8_t irq_count)
 {
+    int i;
     Aml *var = aml_alloc();
     uint8_t irq_flags = con_and_pro | (level_and_edge << 1)
                         | (high_and_low << 2) | (shared << 3);
+    const int header_bytes_in_len = 2;
+    uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t);
+
+    assert(irq_count > 0);
 
     build_append_byte(var->buf, 0x89); /* Extended irq descriptor */
-    build_append_byte(var->buf, 6); /* Length, bits[7:0] minimum value = 6 */
-    build_append_byte(var->buf, 0); /* Length, bits[15:8] minimum value = 0 */
+    build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */
+    build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */
     build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */
-    build_append_byte(var->buf, 0x01);      /* Interrupt table length = 1 */
+    build_append_byte(var->buf, irq_count);   /* Interrupt table length */
 
-    /* Interrupt Number */
-    build_append_byte(var->buf, extract32(irq, 0, 8));  /* bits[7:0] */
-    build_append_byte(var->buf, extract32(irq, 8, 8));  /* bits[15:8] */
-    build_append_byte(var->buf, extract32(irq, 16, 8)); /* bits[23:16] */
-    build_append_byte(var->buf, extract32(irq, 24, 8)); /* bits[31:24] */
+    /* Interrupt Number List */
+    for (i = 0; i < irq_count; i++) {
+        build_append_int_noprefix(var->buf, irq_list[i], 4);
+    }
     return var;
 }
 
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 698b5f2..b0c1c4e 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -71,7 +71,7 @@  static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
 }
 
 static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
-                                           int uart_irq)
+                                           uint32_t uart_irq)
 {
     Aml *dev = aml_device("COM0");
     aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011")));
@@ -82,7 +82,7 @@  static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
                                        uart_memmap->size, AML_READ_WRITE));
     aml_append(crs,
                aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
-                             AML_EXCLUSIVE, uart_irq));
+                             AML_EXCLUSIVE, &uart_irq, 1));
     aml_append(dev, aml_name_decl("_CRS", crs));
 
     /* The _ADR entry is used to link this device to the UART described
@@ -94,7 +94,7 @@  static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
 }
 
 static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
-                                          int rtc_irq)
+                                          uint32_t rtc_irq)
 {
     Aml *dev = aml_device("RTC0");
     aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013")));
@@ -105,7 +105,7 @@  static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
                                        rtc_memmap->size, AML_READ_WRITE));
     aml_append(crs,
                aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
-                             AML_EXCLUSIVE, rtc_irq));
+                             AML_EXCLUSIVE, &rtc_irq, 1));
     aml_append(dev, aml_name_decl("_CRS", crs));
     aml_append(scope, dev);
 }
@@ -136,14 +136,14 @@  static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap)
 
 static void acpi_dsdt_add_virtio(Aml *scope,
                                  const MemMapEntry *virtio_mmio_memmap,
-                                 int mmio_irq, int num)
+                                 uint32_t mmio_irq, int num)
 {
     hwaddr base = virtio_mmio_memmap->base;
     hwaddr size = virtio_mmio_memmap->size;
-    int irq = mmio_irq;
     int i;
 
     for (i = 0; i < num; i++) {
+        uint32_t irq = mmio_irq + i;
         Aml *dev = aml_device("VR%02u", i);
         aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005")));
         aml_append(dev, aml_name_decl("_UID", aml_int(i)));
@@ -152,15 +152,15 @@  static void acpi_dsdt_add_virtio(Aml *scope,
         aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE));
         aml_append(crs,
                    aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
-                                 AML_EXCLUSIVE, irq + i));
+                                 AML_EXCLUSIVE, &irq, 1));
         aml_append(dev, aml_name_decl("_CRS", crs));
         aml_append(scope, dev);
         base += size;
     }
 }
 
-static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
-                              bool use_highmem)
+static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
+                              uint32_t irq, bool use_highmem)
 {
     Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
     int i, bus_no;
@@ -199,18 +199,19 @@  static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
 
     /* Create GSI link device */
     for (i = 0; i < PCI_NUM_PINS; i++) {
+        uint32_t irqs =  irq + i;
         Aml *dev_gsi = aml_device("GSI%d", i);
         aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F")));
         aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0)));
         crs = aml_resource_template();
         aml_append(crs,
                    aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
-                                 AML_EXCLUSIVE, irq + i));
+                                 AML_EXCLUSIVE, &irqs, 1));
         aml_append(dev_gsi, aml_name_decl("_PRS", crs));
         crs = aml_resource_template();
         aml_append(crs,
                    aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
-                                 AML_EXCLUSIVE, irq + i));
+                                 AML_EXCLUSIVE, &irqs, 1));
         aml_append(dev_gsi, aml_name_decl("_CRS", crs));
         method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
         aml_append(dev_gsi, method);
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
index ca365c9..a3a058f 100644
--- a/include/hw/acpi/aml-build.h
+++ b/include/hw/acpi/aml-build.h
@@ -253,7 +253,7 @@  Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
 Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
                    AmlLevelAndEdge level_and_edge,
                    AmlActiveHighAndLow high_and_low, AmlShared shared,
-                   uint32_t irq);
+                   uint32_t *irq_list, uint8_t irq_count);
 Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
             uint8_t aln, uint8_t len);
 Aml *aml_operation_region(const char *name, AmlRegionSpace rs,