[ACPI] suspend/resume ACPI PCI Interrupt Links

Add reference count and disable ACPI PCI Interrupt Link
when no device still uses it.

Warn when drivers have not released Link at suspend time.

http://bugzilla.kernel.org/show_bug.cgi?id=3469

Signed-off-by: David Shaohua Li <shaohua.li@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>

authored by David Shaohua Li and committed by Len Brown 87bec66b 68ac7676

+157 -47
+1
arch/i386/pci/acpi.c
··· 30 acpi_irq_penalty_init(); 31 pcibios_scanned++; 32 pcibios_enable_irq = acpi_pci_irq_enable; 33 34 if (pci_routeirq) { 35 /*
··· 30 acpi_irq_penalty_init(); 31 pcibios_scanned++; 32 pcibios_enable_irq = acpi_pci_irq_enable; 33 + pcibios_disable_irq = acpi_pci_irq_disable; 34 35 if (pci_routeirq) { 36 /*
+6
arch/i386/pci/common.c
··· 249 250 return pcibios_enable_irq(dev); 251 }
··· 249 250 return pcibios_enable_irq(dev); 251 } 252 + 253 + void pcibios_disable_device (struct pci_dev *dev) 254 + { 255 + if (pcibios_disable_irq) 256 + pcibios_disable_irq(dev); 257 + }
+1
arch/i386/pci/irq.c
··· 56 }; 57 58 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 59 60 /* 61 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
··· 56 }; 57 58 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 59 + void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; 60 61 /* 62 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
+1
arch/i386/pci/pci.h
··· 72 extern spinlock_t pci_config_lock; 73 74 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
··· 72 extern spinlock_t pci_config_lock; 73 74 extern int (*pcibios_enable_irq)(struct pci_dev *dev); 75 + extern void (*pcibios_disable_irq)(struct pci_dev *dev);
+59 -26
drivers/acpi/pci_irq.c
··· 269 /* -------------------------------------------------------------------------- 270 PCI Interrupt Routing Support 271 -------------------------------------------------------------------------- */ 272 273 /* 274 * acpi_pci_irq_lookup 275 * success: return IRQ >= 0 ··· 326 int pin, 327 int *edge_level, 328 int *active_high_low, 329 - char **link) 330 { 331 struct acpi_prt_entry *entry = NULL; 332 int segment = pci_domain_nr(bus); 333 int bus_nr = bus->number; 334 - int irq; 335 336 ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); 337 ··· 346 return_VALUE(-1); 347 } 348 349 - if (entry->link.handle) { 350 - irq = acpi_pci_link_get_irq(entry->link.handle, 351 - entry->link.index, edge_level, active_high_low, link); 352 - if (irq < 0) { 353 - ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); 354 - return_VALUE(-1); 355 - } 356 - } else { 357 - irq = entry->link.index; 358 - *edge_level = ACPI_LEVEL_SENSITIVE; 359 - *active_high_low = ACPI_ACTIVE_LOW; 360 - } 361 - 362 - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); 363 - 364 - return_VALUE(irq); 365 } 366 367 /* ··· 361 int pin, 362 int *edge_level, 363 int *active_high_low, 364 - char **link) 365 { 366 struct pci_dev *bridge = dev; 367 int irq = -1; ··· 395 } 396 397 irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), 398 - pin, edge_level, active_high_low, link); 399 } 400 401 if (irq < 0) { ··· 447 * values override any BIOS-assigned IRQs set during boot. 448 */ 449 irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, 450 - &edge_level, &active_high_low, &link); 451 452 /* 453 * If no PRT entry was found, we'll try to derive an IRQ from the ··· 455 */ 456 if (irq < 0) 457 irq = acpi_pci_irq_derive(dev, pin, &edge_level, 458 - &active_high_low, &link); 459 460 /* 461 * No IRQ known to the ACPI subsystem - maybe the BIOS / ··· 493 EXPORT_SYMBOL(acpi_pci_irq_enable); 494 495 496 - #ifdef CONFIG_ACPI_DEALLOCATE_IRQ 497 void 498 acpi_pci_irq_disable ( 499 struct pci_dev *dev) ··· 522 * First we check the PCI IRQ routing table (PRT) for an IRQ. 523 */ 524 gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, 525 - &edge_level, &active_high_low, NULL); 526 /* 527 * If no PRT entry was found, we'll try to derive an IRQ from the 528 * device's parent bridge. 529 */ 530 if (gsi < 0) 531 gsi = acpi_pci_irq_derive(dev, pin, 532 - &edge_level, &active_high_low, NULL); 533 if (gsi < 0) 534 return_VOID; 535 ··· 545 546 return_VOID; 547 } 548 - #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
··· 269 /* -------------------------------------------------------------------------- 270 PCI Interrupt Routing Support 271 -------------------------------------------------------------------------- */ 272 + typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **); 273 274 + static int 275 + acpi_pci_allocate_irq(struct acpi_prt_entry *entry, 276 + int *edge_level, 277 + int *active_high_low, 278 + char **link) 279 + { 280 + int irq; 281 + 282 + ACPI_FUNCTION_TRACE("acpi_pci_allocate_irq"); 283 + 284 + if (entry->link.handle) { 285 + irq = acpi_pci_link_allocate_irq(entry->link.handle, 286 + entry->link.index, edge_level, active_high_low, link); 287 + if (irq < 0) { 288 + ACPI_DEBUG_PRINT((ACPI_DB_WARN, "Invalid IRQ link routing entry\n")); 289 + return_VALUE(-1); 290 + } 291 + } else { 292 + irq = entry->link.index; 293 + *edge_level = ACPI_LEVEL_SENSITIVE; 294 + *active_high_low = ACPI_ACTIVE_LOW; 295 + } 296 + 297 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found IRQ %d\n", irq)); 298 + return_VALUE(irq); 299 + } 300 + 301 + static int 302 + acpi_pci_free_irq(struct acpi_prt_entry *entry, 303 + int *edge_level, 304 + int *active_high_low, 305 + char **link) 306 + { 307 + int irq; 308 + 309 + ACPI_FUNCTION_TRACE("acpi_pci_free_irq"); 310 + if (entry->link.handle) { 311 + irq = acpi_pci_link_free_irq(entry->link.handle); 312 + } else { 313 + irq = entry->link.index; 314 + } 315 + return_VALUE(irq); 316 + } 317 /* 318 * acpi_pci_irq_lookup 319 * success: return IRQ >= 0 ··· 282 int pin, 283 int *edge_level, 284 int *active_high_low, 285 + char **link, 286 + irq_lookup_func func) 287 { 288 struct acpi_prt_entry *entry = NULL; 289 int segment = pci_domain_nr(bus); 290 int bus_nr = bus->number; 291 + int ret; 292 293 ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); 294 ··· 301 return_VALUE(-1); 302 } 303 304 + ret = func(entry, edge_level, active_high_low, link); 305 + return_VALUE(ret); 306 } 307 308 /* ··· 330 int pin, 331 int *edge_level, 332 int *active_high_low, 333 + char **link, 334 + irq_lookup_func func) 335 { 336 struct pci_dev *bridge = dev; 337 int irq = -1; ··· 363 } 364 365 irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), 366 + pin, edge_level, active_high_low, link, func); 367 } 368 369 if (irq < 0) { ··· 415 * values override any BIOS-assigned IRQs set during boot. 416 */ 417 irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, 418 + &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); 419 420 /* 421 * If no PRT entry was found, we'll try to derive an IRQ from the ··· 423 */ 424 if (irq < 0) 425 irq = acpi_pci_irq_derive(dev, pin, &edge_level, 426 + &active_high_low, &link, acpi_pci_allocate_irq); 427 428 /* 429 * No IRQ known to the ACPI subsystem - maybe the BIOS / ··· 461 EXPORT_SYMBOL(acpi_pci_irq_enable); 462 463 464 + /* FIXME: implement x86/x86_64 version */ 465 + void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} 466 + 467 void 468 acpi_pci_irq_disable ( 469 struct pci_dev *dev) ··· 488 * First we check the PCI IRQ routing table (PRT) for an IRQ. 489 */ 490 gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, 491 + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); 492 /* 493 * If no PRT entry was found, we'll try to derive an IRQ from the 494 * device's parent bridge. 495 */ 496 if (gsi < 0) 497 gsi = acpi_pci_irq_derive(dev, pin, 498 + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); 499 if (gsi < 0) 500 return_VOID; 501 ··· 511 512 return_VOID; 513 }
+87 -16
drivers/acpi/pci_link.c
··· 68 }, 69 }; 70 71 struct acpi_pci_link_irq { 72 u8 active; /* Current IRQ */ 73 u8 edge_level; /* All IRQs */ ··· 80 u8 possible_count; 81 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; 82 u8 initialized:1; 83 - u8 suspend_resume:1; 84 - u8 reserved:6; 85 }; 86 87 struct acpi_pci_link { ··· 88 struct acpi_device *device; 89 acpi_handle handle; 90 struct acpi_pci_link_irq irq; 91 }; 92 93 static struct { 94 int count; 95 struct list_head entries; 96 } acpi_link; 97 98 99 /* -------------------------------------------------------------------------- ··· 537 538 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); 539 540 - if (link->irq.suspend_resume) { 541 - acpi_pci_link_set(link, link->irq.active); 542 - link->irq.suspend_resume = 0; 543 - } 544 - if (link->irq.initialized) 545 return_VALUE(0); 546 547 /* 548 * search for active IRQ in list of possible IRQs. ··· 601 } 602 603 /* 604 - * acpi_pci_link_get_irq 605 * success: return IRQ >= 0 606 * failure: return -1 607 */ 608 609 int 610 - acpi_pci_link_get_irq ( 611 acpi_handle handle, 612 int index, 613 int *edge_level, ··· 618 struct acpi_device *device = NULL; 619 struct acpi_pci_link *link = NULL; 620 621 - ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); 622 623 result = acpi_bus_get_device(handle, &device); 624 if (result) { ··· 638 return_VALUE(-1); 639 } 640 641 - if (acpi_pci_link_allocate(link)) 642 return_VALUE(-1); 643 644 if (!link->irq.active) { 645 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); 646 return_VALUE(-1); 647 } 648 649 if (edge_level) *edge_level = link->irq.edge_level; 650 if (active_high_low) *active_high_low = link->irq.active_high_low; 651 if (name) *name = acpi_device_bid(link->device); 652 return_VALUE(link->irq.active); 653 } 654 655 656 /* -------------------------------------------------------------------------- 657 Driver Interface 658 -------------------------------------------------------------------------- */ ··· 731 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); 732 acpi_driver_data(device) = link; 733 734 result = acpi_pci_link_get_possible(link); 735 if (result) 736 goto end; ··· 767 end: 768 /* disable all links -- to be activated on use */ 769 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); 770 771 if (result) 772 kfree(link); ··· 782 { 783 struct list_head *node = NULL; 784 struct acpi_pci_link *link = NULL; 785 786 ACPI_FUNCTION_TRACE("irqrouter_suspend"); 787 788 list_for_each(node, &acpi_link.entries) { 789 link = list_entry(node, struct acpi_pci_link, node); 790 if (!link) { 791 - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); 792 continue; 793 } 794 - if (link->irq.active && link->irq.initialized) 795 - link->irq.suspend_resume = 1; 796 } 797 - return_VALUE(0); 798 } 799 800 ··· 825 826 link = (struct acpi_pci_link *) acpi_driver_data(device); 827 828 - /* TBD: Acquire/release lock */ 829 list_del(&link->node); 830 831 kfree(link); 832 ··· 919 __setup("acpi_irq_balance", acpi_irq_balance_set); 920 921 922 static struct sysdev_class irqrouter_sysdev_class = { 923 set_kset_name("irqrouter"), 924 .suspend = irqrouter_suspend,
··· 68 }, 69 }; 70 71 + /* 72 + * If a link is initialized, we never change its active and initialized 73 + * later even the link is disable. Instead, we just repick the active irq 74 + */ 75 struct acpi_pci_link_irq { 76 u8 active; /* Current IRQ */ 77 u8 edge_level; /* All IRQs */ ··· 76 u8 possible_count; 77 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; 78 u8 initialized:1; 79 + u8 reserved:7; 80 }; 81 82 struct acpi_pci_link { ··· 85 struct acpi_device *device; 86 acpi_handle handle; 87 struct acpi_pci_link_irq irq; 88 + int refcnt; 89 }; 90 91 static struct { 92 int count; 93 struct list_head entries; 94 } acpi_link; 95 + DECLARE_MUTEX(acpi_link_lock); 96 97 98 /* -------------------------------------------------------------------------- ··· 532 533 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); 534 535 + if (link->irq.initialized) { 536 + if (link->refcnt == 0) 537 + /* This means the link is disabled but initialized */ 538 + acpi_pci_link_set(link, link->irq.active); 539 return_VALUE(0); 540 + } 541 542 /* 543 * search for active IRQ in list of possible IRQs. ··· 596 } 597 598 /* 599 + * acpi_pci_link_allocate_irq 600 * success: return IRQ >= 0 601 * failure: return -1 602 */ 603 604 int 605 + acpi_pci_link_allocate_irq ( 606 acpi_handle handle, 607 int index, 608 int *edge_level, ··· 613 struct acpi_device *device = NULL; 614 struct acpi_pci_link *link = NULL; 615 616 + ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq"); 617 618 result = acpi_bus_get_device(handle, &device); 619 if (result) { ··· 633 return_VALUE(-1); 634 } 635 636 + down(&acpi_link_lock); 637 + if (acpi_pci_link_allocate(link)) { 638 + up(&acpi_link_lock); 639 return_VALUE(-1); 640 + } 641 642 if (!link->irq.active) { 643 + up(&acpi_link_lock); 644 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); 645 return_VALUE(-1); 646 } 647 + link->refcnt ++; 648 + up(&acpi_link_lock); 649 650 if (edge_level) *edge_level = link->irq.edge_level; 651 if (active_high_low) *active_high_low = link->irq.active_high_low; 652 if (name) *name = acpi_device_bid(link->device); 653 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 654 + "Link %s is referenced\n", acpi_device_bid(link->device))); 655 return_VALUE(link->irq.active); 656 } 657 658 + /* 659 + * We don't change link's irq information here. After it is reenabled, we 660 + * continue use the info 661 + */ 662 + int 663 + acpi_pci_link_free_irq(acpi_handle handle) 664 + { 665 + struct acpi_device *device = NULL; 666 + struct acpi_pci_link *link = NULL; 667 + acpi_status result; 668 669 + ACPI_FUNCTION_TRACE("acpi_pci_link_free_irq"); 670 + 671 + result = acpi_bus_get_device(handle, &device); 672 + if (result) { 673 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link device\n")); 674 + return_VALUE(-1); 675 + } 676 + 677 + link = (struct acpi_pci_link *) acpi_driver_data(device); 678 + if (!link) { 679 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); 680 + return_VALUE(-1); 681 + } 682 + 683 + down(&acpi_link_lock); 684 + if (!link->irq.initialized) { 685 + up(&acpi_link_lock); 686 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link isn't initialized\n")); 687 + return_VALUE(-1); 688 + } 689 + 690 + link->refcnt --; 691 + ACPI_DEBUG_PRINT((ACPI_DB_INFO, 692 + "Link %s is dereferenced\n", acpi_device_bid(link->device))); 693 + 694 + if (link->refcnt == 0) { 695 + acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); 696 + } 697 + up(&acpi_link_lock); 698 + return_VALUE(link->irq.active); 699 + } 700 /* -------------------------------------------------------------------------- 701 Driver Interface 702 -------------------------------------------------------------------------- */ ··· 677 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); 678 acpi_driver_data(device) = link; 679 680 + down(&acpi_link_lock); 681 result = acpi_pci_link_get_possible(link); 682 if (result) 683 goto end; ··· 712 end: 713 /* disable all links -- to be activated on use */ 714 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); 715 + up(&acpi_link_lock); 716 717 if (result) 718 kfree(link); ··· 726 { 727 struct list_head *node = NULL; 728 struct acpi_pci_link *link = NULL; 729 + int ret = 0; 730 731 ACPI_FUNCTION_TRACE("irqrouter_suspend"); 732 733 list_for_each(node, &acpi_link.entries) { 734 link = list_entry(node, struct acpi_pci_link, node); 735 if (!link) { 736 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 737 + "Invalid link context\n")); 738 continue; 739 } 740 + if (link->irq.initialized && link->refcnt != 0 741 + /* We ignore legacy IDE device irq */ 742 + && link->irq.active != 14 && link->irq.active !=15) { 743 + printk(KERN_WARNING PREFIX 744 + "%d drivers with interrupt %d neglected to call" 745 + " pci_disable_device at .suspend\n", 746 + link->refcnt, 747 + link->irq.active); 748 + printk(KERN_WARNING PREFIX 749 + "Fix the driver, or rmmod before suspend\n"); 750 + link->refcnt = 0; 751 + ret = -EINVAL; 752 + } 753 } 754 + return_VALUE(ret); 755 } 756 757 ··· 756 757 link = (struct acpi_pci_link *) acpi_driver_data(device); 758 759 + down(&acpi_link_lock); 760 list_del(&link->node); 761 + up(&acpi_link_lock); 762 763 kfree(link); 764 ··· 849 __setup("acpi_irq_balance", acpi_irq_balance_set); 850 851 852 + /* FIXME: we will remove this interface after all drivers call pci_disable_device */ 853 static struct sysdev_class irqrouter_sysdev_class = { 854 set_kset_name("irqrouter"), 855 .suspend = irqrouter_suspend,
+2 -1
include/acpi/acpi_drivers.h
··· 56 /* ACPI PCI Interrupt Link (pci_link.c) */ 57 58 int acpi_irq_penalty_init (void); 59 - int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level, 60 int *active_high_low, char **name); 61 62 /* ACPI PCI Interrupt Routing (pci_irq.c) */ 63
··· 56 /* ACPI PCI Interrupt Link (pci_link.c) */ 57 58 int acpi_irq_penalty_init (void); 59 + int acpi_pci_link_allocate_irq (acpi_handle handle, int index, int *edge_level, 60 int *active_high_low, char **name); 61 + int acpi_pci_link_free_irq(acpi_handle handle); 62 63 /* ACPI PCI Interrupt Routing (pci_irq.c) */ 64
-4
include/linux/acpi.h
··· 440 * If this matches the last registration, any IRQ resources for gsi 441 * are freed. 442 */ 443 - #ifdef CONFIG_ACPI_DEALLOCATE_IRQ 444 void acpi_unregister_gsi (u32 gsi); 445 - #endif 446 447 #ifdef CONFIG_ACPI_PCI 448 ··· 465 int acpi_pci_irq_enable (struct pci_dev *dev); 466 void acpi_penalize_isa_irq(int irq, int active); 467 468 - #ifdef CONFIG_ACPI_DEALLOCATE_IRQ 469 void acpi_pci_irq_disable (struct pci_dev *dev); 470 - #endif 471 472 struct acpi_pci_driver { 473 struct acpi_pci_driver *next;
··· 440 * If this matches the last registration, any IRQ resources for gsi 441 * are freed. 442 */ 443 void acpi_unregister_gsi (u32 gsi); 444 445 #ifdef CONFIG_ACPI_PCI 446 ··· 467 int acpi_pci_irq_enable (struct pci_dev *dev); 468 void acpi_penalize_isa_irq(int irq, int active); 469 470 void acpi_pci_irq_disable (struct pci_dev *dev); 471 472 struct acpi_pci_driver { 473 struct acpi_pci_driver *next;