ACPI: PCI: IRQ: Fix INTx GSIs signedness

In ACPI Global System Interrupts (GSIs) are described using a 32-bit
value.

ACPI/PCI legacy interrupts (INTx) parsing code treats GSIs as 'int',
which poses issues if the GSI interrupt value is a 32-bit value with the
MSB set (as required in some interrupt configurations - eg ARM64 GICv5
systems) because acpi_pci_link_allocate_irq() treats a negative gsi
return value as a failed GSI allocation (and acpi_irq_get_penalty()
would trigger an out-of-bounds array dereference if the 'irq' param is
a negative value).

Fix ACPI/PCI legacy INTx parsing by converting variables representing
GSIs from 'int' to 'u32' bringing the code in line with the ACPI
specification and fixing the current parsing issue.

Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
Link: https://patch.msgid.link/20260105101705.36703-1-lpieralisi@kernel.org
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by Lorenzo Pieralisi and committed by Rafael J. Wysocki 1ca8677d 9ace4753

Changed files
+44 -29
drivers
include
+11 -8
drivers/acpi/pci_irq.c
··· 188 188 * the IRQ value, which is hardwired to specific interrupt inputs on 189 189 * the interrupt controller. 190 190 */ 191 - pr_debug("%04x:%02x:%02x[%c] -> %s[%d]\n", 191 + pr_debug("%04x:%02x:%02x[%c] -> %s[%u]\n", 192 192 entry->id.segment, entry->id.bus, entry->id.device, 193 193 pin_name(entry->pin), prt->source, entry->index); 194 194 ··· 384 384 int acpi_pci_irq_enable(struct pci_dev *dev) 385 385 { 386 386 struct acpi_prt_entry *entry; 387 - int gsi; 387 + u32 gsi; 388 388 u8 pin; 389 389 int triggering = ACPI_LEVEL_SENSITIVE; 390 390 /* ··· 422 422 return 0; 423 423 } 424 424 425 + rc = -ENODEV; 426 + 425 427 if (entry) { 426 428 if (entry->link) 427 - gsi = acpi_pci_link_allocate_irq(entry->link, 429 + rc = acpi_pci_link_allocate_irq(entry->link, 428 430 entry->index, 429 431 &triggering, &polarity, 430 - &link); 431 - else 432 + &link, &gsi); 433 + else { 432 434 gsi = entry->index; 433 - } else 434 - gsi = -1; 435 + rc = 0; 436 + } 437 + } 435 438 436 - if (gsi < 0) { 439 + if (rc < 0) { 437 440 /* 438 441 * No IRQ known to the ACPI subsystem - maybe the BIOS / 439 442 * driver reported one, then use it. Exit in any case.
+25 -14
drivers/acpi/pci_link.c
··· 448 448 /* >IRQ15 */ 449 449 }; 450 450 451 - static int acpi_irq_pci_sharing_penalty(int irq) 451 + static int acpi_irq_pci_sharing_penalty(u32 irq) 452 452 { 453 453 struct acpi_pci_link *link; 454 454 int penalty = 0; ··· 474 474 return penalty; 475 475 } 476 476 477 - static int acpi_irq_get_penalty(int irq) 477 + static int acpi_irq_get_penalty(u32 irq) 478 478 { 479 479 int penalty = 0; 480 480 ··· 528 528 static int acpi_pci_link_allocate(struct acpi_pci_link *link) 529 529 { 530 530 acpi_handle handle = link->device->handle; 531 - int irq; 531 + u32 irq; 532 532 int i; 533 533 534 534 if (link->irq.initialized) { ··· 598 598 return 0; 599 599 } 600 600 601 - /* 602 - * acpi_pci_link_allocate_irq 603 - * success: return IRQ >= 0 604 - * failure: return -1 601 + /** 602 + * acpi_pci_link_allocate_irq(): Retrieve a link device GSI 603 + * 604 + * @handle: Handle for the link device 605 + * @index: GSI index 606 + * @triggering: pointer to store the GSI trigger 607 + * @polarity: pointer to store GSI polarity 608 + * @name: pointer to store link device name 609 + * @gsi: pointer to store GSI number 610 + * 611 + * Returns: 612 + * 0 on success with @triggering, @polarity, @name, @gsi initialized. 613 + * -ENODEV on failure 605 614 */ 606 615 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, 607 - int *polarity, char **name) 616 + int *polarity, char **name, u32 *gsi) 608 617 { 609 618 struct acpi_device *device = acpi_fetch_acpi_dev(handle); 610 619 struct acpi_pci_link *link; 611 620 612 621 if (!device) { 613 622 acpi_handle_err(handle, "Invalid link device\n"); 614 - return -1; 623 + return -ENODEV; 615 624 } 616 625 617 626 link = acpi_driver_data(device); 618 627 if (!link) { 619 628 acpi_handle_err(handle, "Invalid link context\n"); 620 - return -1; 629 + return -ENODEV; 621 630 } 622 631 623 632 /* TBD: Support multiple index (IRQ) entries per Link Device */ 624 633 if (index) { 625 634 acpi_handle_err(handle, "Invalid index %d\n", index); 626 - return -1; 635 + return -ENODEV; 627 636 } 628 637 629 638 mutex_lock(&acpi_link_lock); 630 639 if (acpi_pci_link_allocate(link)) { 631 640 mutex_unlock(&acpi_link_lock); 632 - return -1; 641 + return -ENODEV; 633 642 } 634 643 635 644 if (!link->irq.active) { 636 645 mutex_unlock(&acpi_link_lock); 637 646 acpi_handle_err(handle, "Link active IRQ is 0!\n"); 638 - return -1; 647 + return -ENODEV; 639 648 } 640 649 link->refcnt++; 641 650 mutex_unlock(&acpi_link_lock); ··· 656 647 if (name) 657 648 *name = acpi_device_bid(link->device); 658 649 acpi_handle_debug(handle, "Link is referenced\n"); 659 - return link->irq.active; 650 + *gsi = link->irq.active; 651 + 652 + return 0; 660 653 } 661 654 662 655 /*
+7 -6
drivers/xen/acpi.c
··· 89 89 int *trigger_out, 90 90 int *polarity_out) 91 91 { 92 - int gsi; 92 + u32 gsi; 93 93 u8 pin; 94 94 struct acpi_prt_entry *entry; 95 95 int trigger = ACPI_LEVEL_SENSITIVE; 96 - int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? 96 + int ret, polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ? 97 97 ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW; 98 98 99 99 if (!dev || !gsi_out || !trigger_out || !polarity_out) ··· 105 105 106 106 entry = acpi_pci_irq_lookup(dev, pin); 107 107 if (entry) { 108 + ret = 0; 108 109 if (entry->link) 109 - gsi = acpi_pci_link_allocate_irq(entry->link, 110 + ret = acpi_pci_link_allocate_irq(entry->link, 110 111 entry->index, 111 112 &trigger, &polarity, 112 - NULL); 113 + NULL, &gsi); 113 114 else 114 115 gsi = entry->index; 115 116 } else 116 - gsi = -1; 117 + ret = -ENODEV; 117 118 118 - if (gsi < 0) 119 + if (ret < 0) 119 120 return -EINVAL; 120 121 121 122 *gsi_out = gsi;
+1 -1
include/acpi/acpi_drivers.h
··· 51 51 52 52 int acpi_irq_penalty_init(void); 53 53 int acpi_pci_link_allocate_irq(acpi_handle handle, int index, int *triggering, 54 - int *polarity, char **name); 54 + int *polarity, char **name, u32 *gsi); 55 55 int acpi_pci_link_free_irq(acpi_handle handle); 56 56 57 57 /* ACPI PCI Device Binding */