Applied, thanks!

Mike Kelly, le dim. 26 oct. 2025 16:11:09 +0000, a ecrit:
> General support for applying ACPI data to subordinate buses:
> Parse ACPI tables to find PCI-PCI bridges, their bus numbers and _PRT tables.
> Use the parsed data to apply appropriate _PRT table per GSI lookup.
> Translate PCI pin numbers whilst iterating the bus hierarchy.
> ---
>  debian/patches/acpi-init-files.diff | 269 +++++++++++++++++++++++++---
>  1 file changed, 242 insertions(+), 27 deletions(-)
> 
> diff --git a/debian/patches/acpi-init-files.diff 
> b/debian/patches/acpi-init-files.diff
> index 8f2080b..5ee59dd 100644
> --- a/debian/patches/acpi-init-files.diff
> +++ b/debian/patches/acpi-init-files.diff
> @@ -1,6 +1,8 @@
> ---- /dev/null
> -+++ b/acpi_init.c
> -@@ -0,0 +1,830 @@
> +Index: libacpica/acpi_init.c
> +===================================================================
> +--- /dev/null        1970-01-01 00:00:00.000000000 +0000
> ++++ libacpica/acpi_init.c    2025-10-26 13:07:39.753578190 +0000
> +@@ -0,0 +1,1041 @@
>  +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
>  +#include <acpi/acpi.h>
>  +
> @@ -33,12 +35,16 @@
>  +#define PCI_CFG1_START 0xcf8
>  +#define PCI_CFG1_END   0xcff
>  +
> -+#define LEGACY_ISA_IRQS 8
> -+#define PCI_IRQ_START 16
> -+
>  +#define PCI_INTERRUPT_PIN 0x3d
>  +#define BAD_PIC_MODE(m) ((m) < ACPI_PICMODE_PIC || (m) > ACPI_PICMODE_SAPIC)
>  +
> ++#define PCI_HDR_TYPE_REG        0x0e
> ++#define PCI_HDR_TYPE_PPB        1
> ++#define PCI_PPB_SECBUS_REG      0x19
> ++#define PCI_MAX_DEV_ID          0x1f
> ++#define PCI_MAX_FUNC_ID         0x7
> ++#define PCI_MULTI_FUNC_MASK     0x80
> ++
>  +extern acpi_status acpi_hw_legacy_sleep(u8 sleep_state);
>  +
>  +// Lets keep the ACPI tables in this module
> @@ -48,6 +54,16 @@
>  +static int numdevs = -1;
>  +static int pic_mode = -1;
>  +
> ++typedef struct acpi_pci_bridge
> ++{
> ++  acpi_handle handle;
> ++  uint8_t up_bus;
> ++  uint8_t down_bus;
> ++  struct acpi_pci_bridge* next;
> ++} acpi_pci_bridge_t;
> ++
> ++static acpi_pci_bridge_t* acpi_pci_bridges;
> ++
>  +struct slots {
>  +  uint8_t bus;
>  +  uint16_t dev;
> @@ -111,6 +127,17 @@
>  +    return NULL;
>  +}
>  +
> ++static void
> ++acpi_unload_pci_bridges(void)
> ++{
> ++  while (acpi_pci_bridges != NULL)
> ++    {
> ++      acpi_pci_bridge_t* bridge = acpi_pci_bridges;
> ++      acpi_pci_bridges = bridge->next;
> ++      free(bridge);
> ++    }
> ++}
> ++
>  +void
>  +acpi_ds_dump_method_stack(acpi_status status, ...)
>  +//    struct acpi_walk_state *walk_state, union acpi_parse_object *op)
> @@ -331,6 +358,7 @@
>  +acpi_os_terminate(void)
>  +{
>  +  free(pci_devices);
> ++  acpi_unload_pci_bridges();
>  +  acpi_os_printf("Bye!\n");
>  +  return AE_OK;
>  +}
> @@ -508,29 +536,22 @@
>  +      : (int)pci_pin);
>  +}
>  +
> -+int
> -+acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func)
> ++static int
> ++acpi_get_irq_from_handle(acpi_handle handle,
> ++                     uint16_t dev, uint16_t func, int pci_pin)
>  +{
>  +  struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>  +  struct acpi_buffer srs_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
>  +  struct acpi_pci_routing_table *entry;
>  +  struct acpi_resource *res;
> -+  uint8_t *buf;
>  +  int srs_count;
> -+  int pci_pin;
>  +
> -+  acpi_handle handle = ACPI_ROOT_OBJECT;
> -+  acpi_handle parent_handle = NULL;
>  +  acpi_handle prt = NULL;
>  +  acpi_handle lnk = NULL;
>  +  acpi_status err = AE_OK;
>  +  u16 prt_dev, prt_func;
>  +
> -+  err = acpi_get_handle(handle, "\\_SB.PCI0", &parent_handle);
> -+  if (ACPI_FAILURE(err))
> -+    return -EIO;
> -+
> -+  err = acpi_get_handle(parent_handle, METHOD_NAME__PRT, &prt);
> ++  err = acpi_get_handle(handle, METHOD_NAME__PRT, &prt);
>  +  if (ACPI_FAILURE(err))
>  +    return -EIO;
>  +
> @@ -538,7 +559,7 @@
>  +  if (ACPI_FAILURE(err))
>  +    return -EIO;
>  +
> -+  err = acpi_get_irq_routing_table(parent_handle, &buffer);
> ++  err = acpi_get_irq_routing_table(handle, &buffer);
>  +  if (ACPI_FAILURE(err))
>  +    return -EIO;
>  +
> @@ -546,11 +567,6 @@
>  +  if (BAD_PIC_MODE(pic_mode))
>  +    return -EIO;
>  +
> -+  pci_pin = acpi_pci_get_device_pin(bus, dev, func);
> -+  /* Fail if the device pin used is unknown (0) */
> -+  if (pci_pin <= 0)
> -+    return -EIO;
> -+
>  +  entry = ACPI_CAST_PTR(struct acpi_pci_routing_table, ACPI_CAST_PTR(u8, 
> buffer.pointer));
>  +  while (entry && (entry->length > 0))
>  +    {
> @@ -619,7 +635,6 @@
>  +                      acpi_os_printf("Error setting _SRS\n");
>  +                      return -EIO;
>  +                    }
> -+                  irq += (irq > LEGACY_ISA_IRQS) ? 0 : PCI_IRQ_START;
>  +                  acpi_os_printf("Final irq %d\n", irq);
>  +                  return irq;
>  +                }
> @@ -681,7 +696,6 @@
>  +                      return -EIO;
>  +                    }
>  +                  free(res);
> -+                  irq += (irq > LEGACY_ISA_IRQS) ? 0 : PCI_IRQ_START;
>  +                  acpi_os_printf("Final irq %d\n", irq);
>  +                  return irq;
>  +                }
> @@ -708,6 +722,55 @@
>  +  return -EIO;
>  +}
>  +
> ++static acpi_pci_bridge_t*
> ++acpi_find_pci_bridge(int bus)
> ++{
> ++  if (bus == 0)
> ++    return NULL;
> ++
> ++  acpi_pci_bridge_t* bridge = acpi_pci_bridges;
> ++
> ++  while (bridge != NULL)
> ++    {
> ++      if (bridge->down_bus == bus)
> ++    return bridge;
> ++
> ++      bridge = bridge->next;
> ++    }
> ++
> ++  return NULL;
> ++}
> ++
> ++int
> ++acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func)
> ++{
> ++  int pci_pin = acpi_pci_get_device_pin(bus, dev, func);
> ++  /* Fail if the device pin used is unknown (0) */
> ++  if (pci_pin <= 0)
> ++    return -EIO;
> ++
> ++  acpi_pci_bridge_t* bridge = acpi_find_pci_bridge(bus);
> ++
> ++  while (bridge != NULL)
> ++    {
> ++      int irq = acpi_get_irq_from_handle(bridge->handle, dev, func, 
> pci_pin);
> ++      if (irq >= 0)
> ++    return irq;
> ++
> ++      /* Translate the downstream INTx to the upstream one */
> ++      pci_pin = ((pci_pin + dev) % 4);
> ++      bus = bridge->up_bus;
> ++      bridge = acpi_find_pci_bridge(bus);
> ++    }
> ++
> ++  acpi_handle handle;
> ++  acpi_status err = acpi_get_handle(ACPI_ROOT_OBJECT, "\\_SB.PCI0", 
> &handle);
> ++  if (ACPI_FAILURE(err))
> ++    return -EIO;
> ++
> ++  return acpi_get_irq_from_handle(handle, dev, func, pci_pin);
> ++}
> ++
>  +/* Fetch the active interrupt mode from GNU mach */
>  +static error_t
>  +acpi_required_pic_mode (void)
> @@ -792,6 +855,152 @@
>  +  return err;
>  +}
>  +
> ++static acpi_status
> ++acpi_pci_bridge_add(acpi_handle handle, uint8_t up_bus, uint8_t down_bus)
> ++{
> ++  acpi_pci_bridge_t* bridge =
> ++    (acpi_pci_bridge_t*)malloc(sizeof(acpi_pci_bridge_t));
> ++
> ++  if (bridge == NULL)
> ++    return AE_NO_MEMORY;
> ++
> ++  bridge->handle = handle;
> ++  bridge->up_bus = up_bus;
> ++  bridge->down_bus = down_bus;
> ++  bridge->next = acpi_pci_bridges;
> ++  acpi_pci_bridges = bridge;
> ++
> ++  return AE_OK;
> ++}
> ++
> ++struct acpi_find_bus_context
> ++{
> ++  int     is_bridge; /* Is this level a bridge or not */
> ++  uint8_t down_bus;  /* The downstream bus num if a bridge */
> ++  struct  acpi_find_bus_context* parent;
> ++};
> ++
> ++static acpi_status
> ++acpi_find_busses_down(acpi_handle handle, uint32_t level,
> ++                  void *context_arg, void **status)
> ++{
> ++  struct acpi_find_bus_context** context =
> ++    (struct acpi_find_bus_context**)context_arg;
> ++
> ++  struct acpi_device_info *devinfo;
> ++  acpi_status rv = acpi_get_object_info(handle, &devinfo);
> ++
> ++  if (ACPI_FAILURE(rv))
> ++    return rv;
> ++
> ++  struct acpi_find_bus_context* device_context =
> ++    (struct acpi_find_bus_context*)malloc(sizeof(struct 
> acpi_find_bus_context));
> ++
> ++  if (device_context == NULL)
> ++    return AE_NO_MEMORY;
> ++
> ++  device_context->is_bridge = 0;
> ++  device_context->down_bus = 0;
> ++  device_context->parent = *context;
> ++  *context = device_context;
> ++
> ++  if (devinfo->flags & ACPI_PCI_ROOT_BRIDGE)
> ++    {
> ++      device_context->is_bridge = 1;
> ++    }
> ++  else if (device_context->parent->is_bridge && (devinfo->valid & 
> ACPI_VALID_ADR))
> ++    {
> ++      uint8_t bus = device_context->parent->down_bus;
> ++      uint32_t devfunc = ACPI_LODWORD(devinfo->address);
> ++      uint16_t dev = ACPI_HIWORD(devfunc);
> ++      uint16_t func = ACPI_LOWORD(devfunc);
> ++
> ++      if (func <= PCI_MAX_FUNC_ID && dev <= PCI_MAX_DEV_ID)
> ++    {
> ++      struct acpi_pci_id pci_id =
> ++        {
> ++          .segment = 0, .bus = bus, .device = dev, .function = func
> ++        };
> ++      u64 val;
> ++
> ++      /* Ignore ACPI entries that refer to absent devices. */
> ++      if (acpi_os_read_pci_configuration(&pci_id, PCI_HDR_TYPE_REG, &val, 
> 8))
> ++        goto exit;
> ++
> ++      {
> ++        /* Only 8 bits was read from the PCI configuration so cast OK. */
> ++        uint8_t hdrType = (uint8_t)val;
> ++        uint8_t mask = PCI_MULTI_FUNC_MASK;
> ++
> ++        if ((hdrType & ~mask) != PCI_HDR_TYPE_PPB)
> ++          goto exit;
> ++      }
> ++
> ++      if (acpi_os_read_pci_configuration(&pci_id, PCI_PPB_SECBUS_REG, &val, 
> 8))
> ++        {
> ++          acpi_os_printf("Failed to find secondary bus for: %x:%x:%x\n",
> ++                         bus, dev, func);
> ++          rv = AE_IO_ERROR;
> ++          goto exit;
> ++        }
> ++
> ++      /* Only 8 bits was read from the PCI configuration so cast OK. */
> ++      device_context->down_bus = (uint8_t)val;
> ++      device_context->is_bridge = 1;
> ++
> ++      rv = acpi_pci_bridge_add(handle, bus, device_context->down_bus);
> ++    }
> ++    }
> ++
> ++ exit:
> ++  ACPI_FREE(devinfo);
> ++
> ++  return rv;
> ++}
> ++
> ++static acpi_status
> ++acpi_find_busses_up(acpi_handle handle, uint32_t level,
> ++                void *context_arg, void **status)
> ++{
> ++  struct acpi_find_bus_context** context =
> ++    (struct acpi_find_bus_context**)context_arg;
> ++
> ++  struct acpi_find_bus_context* entry = *context;
> ++  *context = entry->parent;
> ++
> ++  free(entry);
> ++
> ++  return AE_OK;
> ++}
> ++
> ++static acpi_status
> ++acpi_load_pci_bridges(void)
> ++{
> ++  struct acpi_find_bus_context head_context =
> ++  {
> ++    .is_bridge = 0,
> ++    .down_bus = 0,
> ++    .parent = NULL
> ++  };
> ++
> ++  struct acpi_find_bus_context* context = &head_context;
> ++
> ++  acpi_status rv = acpi_walk_namespace
> ++    (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, UINT_MAX,
> ++     acpi_find_busses_down, acpi_find_busses_up, &context, NULL);
> ++
> ++  /* There should only be anything to free here in error cases */
> ++  while (context != &head_context)
> ++    {
> ++      struct acpi_find_bus_context* entry = context;
> ++      context = context->parent;
> ++
> ++      free(entry);
> ++    }
> ++
> ++  return rv;
> ++}
> ++
>  +void acpi_init(void)
>  +{
>  +  acpi_status err;
> @@ -815,6 +1024,10 @@
>  +  if (ACPI_FAILURE (err))
>  +    goto die;
>  +
> ++  err = acpi_load_pci_bridges();
> ++  if (ACPI_FAILURE (err))
> ++    goto die;
> ++
>  +  /* Ignore return value for old gnumach without irq status */
>  +  acpi_configure_pic_mode();
>  +
> @@ -831,8 +1044,10 @@
>  +die:
>  +  acpi_os_printf("OUCH!\n");
>  +}
> ---- /dev/null
> -+++ b/include/acpi/acpi_init.h
> +Index: libacpica/include/acpi/acpi_init.h
> +===================================================================
> +--- /dev/null        1970-01-01 00:00:00.000000000 +0000
> ++++ libacpica/include/acpi/acpi_init.h       2025-10-26 13:07:13.161934280 
> +0000
>  @@ -0,0 +1,11 @@
>  +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
>  +#ifndef ACPI_INIT_H_
> -- 
> 2.39.5
> 
> 

-- 
Samuel
Now, it we had this sort of thing:
  yield -a     for yield to all traffic
  yield -t     for yield to trucks
  yield -f     for yield to people walking (yield foot)
  yield -d t*  for yield on days starting with t
...you'd have a lot of dead people at intersections, and traffic jams you
wouldn't believe...
(Discussion in comp.os.linux.misc on the intuitiveness of commands.)

Reply via email to