bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 1/1 libacpica] acpi_init: Get pci root port handle \_SB.PC


From: Samuel Thibault
Subject: Re: [PATCH v2 1/1 libacpica] acpi_init: Get pci root port handle \_SB.PCI0 directly
Date: Sun, 29 Dec 2024 01:52:35 +0100

Applied, thanks!

Damien Zammit via Bug reports for the GNU Hurd, le sam. 28 déc. 2024 02:36:06 
+0000, a ecrit:
> This mostly fixes the numbering of IRQs when requested.
> This now works on an old AMD board with broken _CRS.
> It requests the possible irqs from _PRS and generates
> a valid _SRS request to set the one from the end of the list.
> 
> v2: It also no longer errors on a valid _CRS.
> 
> ---
>  debian/patches/acpi-init-files.diff | 327 +++++++++++++++++++---------
>  1 file changed, 221 insertions(+), 106 deletions(-)
> 
> diff --git a/debian/patches/acpi-init-files.diff 
> b/debian/patches/acpi-init-files.diff
> index eb7482c..f45cec9 100644
> --- a/debian/patches/acpi-init-files.diff
> +++ b/debian/patches/acpi-init-files.diff
> @@ -1,6 +1,6 @@
>  --- /dev/null
>  +++ b/acpi_init.c
> -@@ -0,0 +1,597 @@
> +@@ -0,0 +1,712 @@
>  +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
>  +#include <acpi/acpi.h>
>  +
> @@ -32,6 +32,9 @@
>  +#define PCI_CFG1_START 0xcf8
>  +#define PCI_CFG1_END   0xcff
>  +
> ++#define LEGACY_ISA_IRQS 8
> ++#define PCI_IRQ_START 16
> ++
>  +extern acpi_status acpi_hw_legacy_sleep(u8 sleep_state);
>  +
>  +// Lets keep the ACPI tables in this module
> @@ -361,162 +364,165 @@
>  +  acpi_hw_legacy_sleep (sleep_state);
>  +}
>  +
> ++
>  +static acpi_status
> -+register_slot(acpi_handle handle, u32 lev, void *context, void **rv)
> ++acpi_pci_link_count_all(struct acpi_resource *resource, void *context)
>  +{
> -+  if (!context)
> -+    return AE_ERROR;
> ++  int *count = (int *)context;
>  +
> -+  u64 addr, addr_bus;
> -+  acpi_status err;
> ++  (*count)++;
>  +
> -+  struct slots *s = (void *)malloc(sizeof (struct slots));
> -+  if (!s)
> -+    return -1;
> -+
> -+  {
> -+    struct acpi_buffer buffer = { 0, NULL };
> -+    union acpi_object element;
> -+    buffer.length = sizeof(union acpi_object);
> -+    buffer.pointer = &element;
> -+    err = acpi_evaluate_object(handle, METHOD_NAME__BBN, NULL, &buffer);
> -+    if (ACPI_SUCCESS(err) && element.type == ACPI_TYPE_INTEGER)
> -+      addr_bus = element.integer.value;
> -+    else if (err == AE_NOT_FOUND)
> -+      addr_bus = 0;
> -+    else
> -+      {
> -+        free(s);
> -+        return AE_ERROR;
> -+      }
> -+  }
> -+
> -+  s->bus = addr_bus & 0xff;
> -+
> -+  {
> -+    struct acpi_buffer buffer = { 0, NULL };
> -+    union acpi_object element;
> -+    buffer.length = sizeof(union acpi_object);
> -+    buffer.pointer = &element;
> -+
> -+    err = acpi_evaluate_object(handle, METHOD_NAME__ADR, NULL, &buffer);
> -+    if (ACPI_SUCCESS(err) && element.type == ACPI_TYPE_INTEGER)
> -+      addr = element.integer.value;
> -+    else if (err == AE_NOT_FOUND)
> -+      {
> -+        free(s);
> -+        return AE_OK;
> -+      }
> -+    else
> -+      {
> -+        free(s);
> -+        return AE_ERROR;
> -+      }
> -+  }
> -+
> -+  s->dev = (addr >> 16) & 0xffff;
> -+  s->func = addr & 0xffff;
> -+  s->handle = handle;
> -+  s->next = NULL;
> -+
> -+  struct slots **slot_ptr_ptr = (struct slots **)(context);
> -+  if (!(*slot_ptr_ptr))
> -+    *slot_ptr_ptr = s;
> -+  else
> ++  return AE_OK;
> ++}
> ++
> ++static acpi_status
> ++acpi_pci_link_count_irq(struct acpi_resource *resource, void *context)
> ++{
> ++  int *count = (int *)context;
> ++
> ++  if (!resource->length)
> ++    return AE_OK;
> ++
> ++  switch (resource->type)
>  +    {
> -+      struct slots *slot_ptr = *slot_ptr_ptr;
> -+      while(slot_ptr->next)
> -+        slot_ptr = slot_ptr->next;
> -+      slot_ptr->next = s;
> ++      case ACPI_RESOURCE_TYPE_IRQ:
> ++        {
> ++          struct acpi_resource_irq *irq_resource = &resource->data.irq;
> ++          if (!irq_resource || !irq_resource->interrupt_count || 
> !irq_resource->interrupts[0])
> ++            return AE_OK;
> ++          (*count)++;
> ++        }
> ++        break;
> ++      case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
> ++        {
> ++          struct acpi_resource_extended_irq *irq_resource = 
> &resource->data.extended_irq;
> ++          if (!irq_resource || !irq_resource->interrupt_count || 
> !irq_resource->interrupts[0])
> ++            return AE_OK;
> ++          (*count)++;
> ++        }
> ++        break;
> ++      default:
> ++        break;
> ++    }
> ++
> ++  return AE_OK;
> ++}
> ++
> ++static acpi_status
> ++acpi_pci_link_subset_last_irq(struct acpi_resource *resource, void *context)
> ++{
> ++  struct acpi_resource *res = (struct acpi_resource *)context;
> ++
> ++  switch (resource->type)
> ++    {
> ++      case ACPI_RESOURCE_TYPE_IRQ:
> ++        {
> ++          struct acpi_resource_irq *irq_resource = &resource->data.irq;
> ++          if (!irq_resource || !irq_resource->interrupt_count || 
> !irq_resource->interrupts[0])
> ++            return AE_OK;
> ++          *res = *resource;
> ++          return AE_OK;
> ++        }
> ++        break;
> ++      case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
> ++        {
> ++          struct acpi_resource_extended_irq *irq_resource = 
> &resource->data.extended_irq;
> ++          if (!irq_resource || !irq_resource->interrupt_count || 
> !irq_resource->interrupts[0])
> ++            return AE_OK;
> ++          *res = *resource;
> ++          return AE_OK;
> ++        }
> ++        break;
> ++      default:
> ++        break;
>  +    }
> ++
>  +  return AE_OK;
>  +}
>  +
>  +static acpi_status
> -+acpi_pci_link_check(struct acpi_resource *resource, void *context)
> ++acpi_pci_link_get_last_valid_irq(struct acpi_resource *resource, void 
> *context)
>  +{
>  +  int *irq = (int *)context;
>  +
> ++  if (!resource->length)
> ++    {
> ++      acpi_os_printf("Empty resource\n");
> ++      return AE_OK;
> ++    }
> ++
>  +  switch (resource->type)
>  +    {
>  +      case ACPI_RESOURCE_TYPE_IRQ:
>  +        {
>  +          struct acpi_resource_irq *irq_resource = &resource->data.irq;
> -+          if (!irq_resource || !irq_resource->interrupt_count)
> ++          if (!irq_resource || !irq_resource->interrupt_count || 
> !irq_resource->interrupts[0])
>  +            {
>  +              // no IRQ# bits set generally w/ _STA disabled
>  +              acpi_os_printf("Empty _CRS IRQ resource\n");
>  +              return AE_OK;
>  +            }
>  +          *irq = irq_resource->interrupts[0];
> -+          break;
>  +        }
> ++        break;
>  +      case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
>  +        {
>  +          struct acpi_resource_extended_irq *irq_resource = 
> &resource->data.extended_irq;
> -+          if (!irq_resource || !irq_resource->interrupt_count)
> ++          if (!irq_resource || !irq_resource->interrupt_count || 
> !irq_resource->interrupts[0])
>  +            {
>  +              // extended IRQ descriptors should return at least 1 IRQ
>  +              acpi_os_printf("Empty _CRS EXT IRQ resource\n");
>  +              return AE_OK;
>  +            }
>  +          *irq = irq_resource->interrupts[0];
> -+          break;
>  +        }
> ++        break;
> ++      case ACPI_RESOURCE_TYPE_END_TAG:
> ++        return AE_OK;
> ++        break;
>  +      default:
> ++        acpi_os_printf("Not IRQ resource\n");
>  +        return AE_OK;
>  +    }
>  +
> -+  return AE_CTRL_TERMINATE;
> ++  acpi_os_printf("Found IRQ resource %d\n", *irq);
> ++  return AE_OK;
>  +}
>  +
>  +int
>  +acpi_get_irq_number(uint16_t bus, uint16_t dev, uint16_t func)
>  +{
>  +  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;
> ++
>  +  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;
> -+  struct slots *pcislots = NULL, *iter;
> -+  int nslots = 0;
>  +
> -+  err = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, INT_MAX, 
> register_slot, NULL, (struct slots **)&pcislots, NULL);
> ++  err = acpi_get_handle(handle, "\\_SB.PCI0", &parent_handle);
>  +  if (ACPI_FAILURE(err))
>  +    return -EIO;
>  +
> -+  for (iter = pcislots; iter; iter = iter->next)
> -+    {
> -+      if ((iter->bus == bus) && (iter->dev == dev) && (iter->func == func))
> -+        {
> -+      handle = iter->handle;
> -+          break;
> -+        }
> -+      nslots++;
> -+    }
> ++  err = acpi_get_handle(parent_handle, METHOD_NAME__PRT, &prt);
> ++  if (ACPI_FAILURE(err))
> ++    return -EIO;
>  +
> -+  err = acpi_get_parent(handle, &parent_handle);
> ++  err = acpi_evaluate_object(prt, NULL, NULL, &buffer);
>  +  if (ACPI_FAILURE(err))
>  +    return -EIO;
>  +
>  +  err = acpi_get_irq_routing_table(parent_handle, &buffer);
>  +  if (ACPI_FAILURE(err))
> -+    {
> -+      free(buffer.pointer);
> -+      // free pcislots allocated in register_slot function
> -+      struct slots *current_pcislot = pcislots;
> -+      while (current_pcislot)
> -+        {
> -+          free(current_pcislot);
> -+          pcislots = pcislots->next;
> -+          current_pcislot = pcislots;
> -+        }
> -+      return -EIO;
> -+    }
> ++    return -EIO;
>  +
> -+  entry = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer.pointer);
> ++  entry = ACPI_CAST_PTR(struct acpi_pci_routing_table, ACPI_CAST_PTR(u8, 
> buffer.pointer));
>  +  while (entry && (entry->length > 0))
>  +    {
>  +      /* Already applies to the bus of the device */
> @@ -525,28 +531,137 @@
>  +      if ((prt_dev == dev) && (prt_func == 0xffff))
>  +        {
>  +          if (entry->source[0])
> -+        {
> ++            {
> ++              int crs_count = 0;
> ++              int prs_count_irq = 0;
> ++              int prs_count_all = 0;
> ++              int irq = -1;
> ++
>  +              /* Dynamic:
>  +               * - source field specifies PCI interrupt LNK
>  +               * - source_index specifies which resource descriptor in
>  +               *   resource template of LNK to allocate this interrupt
>  +               */
> -+              err = acpi_get_handle(handle, entry->source, &lnk);
> ++              err = acpi_get_handle(ACPI_ROOT_OBJECT, entry->source, &lnk);
>  +              if (ACPI_FAILURE(err))
>  +                return -EIO;
>  +
>  +              if (!lnk)
> -+                acpi_os_printf("error invalid lnk");
> -+
> -+              int irq = -1;
> -+              err = acpi_walk_resources(lnk, METHOD_NAME__CRS, 
> acpi_pci_link_check, &irq);
> ++                {
> ++                  acpi_os_printf("Error invalid lnk\n");
> ++                  return -EIO;
> ++                }
> ++
> ++              err = acpi_walk_resources(lnk, "_CRS", 
> acpi_pci_link_count_irq, &crs_count);
> ++              if (ACPI_FAILURE(err) || !crs_count)
> ++                acpi_os_printf("Warning: missing _CRS\n");
> ++              acpi_walk_resources(lnk, "_PRS", acpi_pci_link_count_all, 
> &prs_count_all);
> ++              err = acpi_walk_resources(lnk, "_PRS", 
> acpi_pci_link_count_irq, &prs_count_irq);
>  +              if (ACPI_FAILURE(err))
> -+                return -EIO;
> -+              return irq;
> -+              // FIXME check the LNK irq _CRS and then set it with _SRS
> ++                {
> ++                  if (crs_count == 0)
> ++                    {
> ++                      acpi_os_printf("Error: missing _PRS when needed\n");
> ++                      return -EIO;
> ++                    }
> ++                }
> ++              if (crs_count > 0)
> ++                {
> ++                  irq = 0;
> ++                  err = acpi_walk_resources(lnk, "_CRS", 
> acpi_pci_link_get_last_valid_irq, &irq);
> ++                  if (ACPI_FAILURE(err) || !irq)
> ++                    {
> ++                      acpi_os_printf("Error walk_resources _CRS\n");
> ++                      return -EIO;
> ++                    }
> ++
> ++                  err = acpi_get_current_resources(lnk, &srs_buffer);
> ++                  if (ACPI_FAILURE(err))
> ++                    {
> ++                      acpi_os_printf("Error getting _CRS\n");
> ++                      return -EIO;
> ++                    }
> ++
> ++                  err = acpi_set_current_resources(lnk, &srs_buffer);
> ++                  if (ACPI_FAILURE(err))
> ++                    {
> ++                      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;
> ++                }
> ++              else if (prs_count_irq > 0)
> ++                {
> ++                  irq = 0;
> ++                  err = acpi_walk_resources(lnk, "_PRS", 
> acpi_pci_link_get_last_valid_irq, &irq);
> ++                  if (ACPI_FAILURE(err) || !irq)
> ++                    {
> ++                      acpi_os_printf("Error walk_resources _PRS\n");
> ++                      return -EIO;
> ++                    }
> ++
> ++                  if (irq > 16)
> ++                    {
> ++                      acpi_os_printf("Error IRQ > 16, not implemented\n");
> ++                      return -EIO;
> ++                    }
> ++
> ++                  /* Found a possible irq, but need to call _SRS to set it 
> */
> ++
> ++                  /* IRQ resource + end tagged resource */
> ++                  srs_count = 2;
> ++
> ++                  res = (struct acpi_resource *)calloc(1, srs_count * 
> sizeof(struct acpi_resource));
> ++
> ++                  err = acpi_walk_resources(lnk, "_PRS", 
> acpi_pci_link_subset_last_irq, res);
> ++                  if (err)
> ++                    {
> ++                      acpi_os_printf("Error _PRS cannot be read\n");
> ++                      free(res);
> ++                      return -EIO;
> ++                    }
> ++
> ++                  /* Patch the _PRS to use for _SRS */
> ++                  srs_buffer.length = sizeof(struct acpi_resource) + 1;
> ++                  srs_buffer.pointer = res;
> ++
> ++                  switch (res->type)
> ++                    {
> ++                      case ACPI_RESOURCE_TYPE_IRQ:
> ++                        res->data.irq.interrupt_count = 1;
> ++                        res->data.irq.interrupts[0] = irq;
> ++                        break;
> ++                      case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
> ++                        res->data.extended_irq.interrupt_count = 1;
> ++                        res->data.extended_irq.interrupts[0] = irq;
> ++                        break;
> ++                    }
> ++
> ++                  res[1].type = ACPI_RESOURCE_TYPE_END_TAG;
> ++                  res[1].length = sizeof(struct acpi_resource);
> ++
> ++                  err = acpi_set_current_resources(lnk, &srs_buffer);
> ++                  if (ACPI_FAILURE(err))
> ++                    {
> ++                      acpi_os_printf("Error setting _SRS\n");
> ++                      free(res);
> ++                      return -EIO;
> ++                    }
> ++                  free(res);
> ++                  irq += (irq > LEGACY_ISA_IRQS) ? 0 : PCI_IRQ_START;
> ++                  acpi_os_printf("Final irq %d\n", irq);
> ++                  return irq;
> ++                }
> ++              else
> ++                {
> ++                  acpi_os_printf("Error: _CRS has empty IRQ resources\n");
> ++                  return -EIO;
> ++                }
>  +            }
> -+      else
> -+        {
> ++          else
> ++            {
>  +              /* Static:
>  +               * - source field is zero
>  +               * - source_index specifies IRQ value hardwired to
> -- 
> 2.45.2
> 
> 
> 

-- 
Samuel
 RR> Ce que je cherche à démontrer, c'est qu'il est injuste de faire
 RR> l'amalgame entre du bulk mail et du courrier non-solicité très ciblé
 un suppositoire non reclamé, meme tres bien ciblé, reste un suppositoire.
 -+-OS in : Guide du Neuneu d'Usenet - Plein le cul de la pub à neuneu -+-



reply via email to

[Prev in Thread] Current Thread [Next in Thread]