[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 -+-