[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 30 acpi_irq_penalty_init(); 31 31 pcibios_scanned++; 32 32 pcibios_enable_irq = acpi_pci_irq_enable; 33 + pcibios_disable_irq = acpi_pci_irq_disable; 33 34 34 35 if (pci_routeirq) { 35 36 /*
+6
arch/i386/pci/common.c
··· 249 249 250 250 return pcibios_enable_irq(dev); 251 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 56 }; 57 57 58 58 int (*pcibios_enable_irq)(struct pci_dev *dev) = NULL; 59 + void (*pcibios_disable_irq)(struct pci_dev *dev) = NULL; 59 60 60 61 /* 61 62 * Search 0xf0000 -- 0xfffff for the PCI IRQ Routing Table.
+1
arch/i386/pci/pci.h
··· 72 72 extern spinlock_t pci_config_lock; 73 73 74 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 269 /* -------------------------------------------------------------------------- 270 270 PCI Interrupt Routing Support 271 271 -------------------------------------------------------------------------- */ 272 + typedef int (*irq_lookup_func)(struct acpi_prt_entry *, int *, int *, char **); 272 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 + } 273 317 /* 274 318 * acpi_pci_irq_lookup 275 319 * success: return IRQ >= 0 ··· 326 282 int pin, 327 283 int *edge_level, 328 284 int *active_high_low, 329 - char **link) 285 + char **link, 286 + irq_lookup_func func) 330 287 { 331 288 struct acpi_prt_entry *entry = NULL; 332 289 int segment = pci_domain_nr(bus); 333 290 int bus_nr = bus->number; 334 - int irq; 291 + int ret; 335 292 336 293 ACPI_FUNCTION_TRACE("acpi_pci_irq_lookup"); 337 294 ··· 346 301 return_VALUE(-1); 347 302 } 348 303 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); 304 + ret = func(entry, edge_level, active_high_low, link); 305 + return_VALUE(ret); 365 306 } 366 307 367 308 /* ··· 361 330 int pin, 362 331 int *edge_level, 363 332 int *active_high_low, 364 - char **link) 333 + char **link, 334 + irq_lookup_func func) 365 335 { 366 336 struct pci_dev *bridge = dev; 367 337 int irq = -1; ··· 395 363 } 396 364 397 365 irq = acpi_pci_irq_lookup(bridge->bus, PCI_SLOT(bridge->devfn), 398 - pin, edge_level, active_high_low, link); 366 + pin, edge_level, active_high_low, link, func); 399 367 } 400 368 401 369 if (irq < 0) { ··· 447 415 * values override any BIOS-assigned IRQs set during boot. 448 416 */ 449 417 irq = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, 450 - &edge_level, &active_high_low, &link); 418 + &edge_level, &active_high_low, &link, acpi_pci_allocate_irq); 451 419 452 420 /* 453 421 * If no PRT entry was found, we'll try to derive an IRQ from the ··· 455 423 */ 456 424 if (irq < 0) 457 425 irq = acpi_pci_irq_derive(dev, pin, &edge_level, 458 - &active_high_low, &link); 426 + &active_high_low, &link, acpi_pci_allocate_irq); 459 427 460 428 /* 461 429 * No IRQ known to the ACPI subsystem - maybe the BIOS / ··· 493 461 EXPORT_SYMBOL(acpi_pci_irq_enable); 494 462 495 463 496 - #ifdef CONFIG_ACPI_DEALLOCATE_IRQ 464 + /* FIXME: implement x86/x86_64 version */ 465 + void __attribute__((weak)) acpi_unregister_gsi(u32 i) {} 466 + 497 467 void 498 468 acpi_pci_irq_disable ( 499 469 struct pci_dev *dev) ··· 522 488 * First we check the PCI IRQ routing table (PRT) for an IRQ. 523 489 */ 524 490 gsi = acpi_pci_irq_lookup(dev->bus, PCI_SLOT(dev->devfn), pin, 525 - &edge_level, &active_high_low, NULL); 491 + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); 526 492 /* 527 493 * If no PRT entry was found, we'll try to derive an IRQ from the 528 494 * device's parent bridge. 529 495 */ 530 496 if (gsi < 0) 531 497 gsi = acpi_pci_irq_derive(dev, pin, 532 - &edge_level, &active_high_low, NULL); 498 + &edge_level, &active_high_low, NULL, acpi_pci_free_irq); 533 499 if (gsi < 0) 534 500 return_VOID; 535 501 ··· 545 511 546 512 return_VOID; 547 513 } 548 - #endif /* CONFIG_ACPI_DEALLOCATE_IRQ */
+87 -16
drivers/acpi/pci_link.c
··· 68 68 }, 69 69 }; 70 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 + */ 71 75 struct acpi_pci_link_irq { 72 76 u8 active; /* Current IRQ */ 73 77 u8 edge_level; /* All IRQs */ ··· 80 76 u8 possible_count; 81 77 u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE]; 82 78 u8 initialized:1; 83 - u8 suspend_resume:1; 84 - u8 reserved:6; 79 + u8 reserved:7; 85 80 }; 86 81 87 82 struct acpi_pci_link { ··· 88 85 struct acpi_device *device; 89 86 acpi_handle handle; 90 87 struct acpi_pci_link_irq irq; 88 + int refcnt; 91 89 }; 92 90 93 91 static struct { 94 92 int count; 95 93 struct list_head entries; 96 94 } acpi_link; 95 + DECLARE_MUTEX(acpi_link_lock); 97 96 98 97 99 98 /* -------------------------------------------------------------------------- ··· 537 532 538 533 ACPI_FUNCTION_TRACE("acpi_pci_link_allocate"); 539 534 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) 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); 545 539 return_VALUE(0); 540 + } 546 541 547 542 /* 548 543 * search for active IRQ in list of possible IRQs. ··· 601 596 } 602 597 603 598 /* 604 - * acpi_pci_link_get_irq 599 + * acpi_pci_link_allocate_irq 605 600 * success: return IRQ >= 0 606 601 * failure: return -1 607 602 */ 608 603 609 604 int 610 - acpi_pci_link_get_irq ( 605 + acpi_pci_link_allocate_irq ( 611 606 acpi_handle handle, 612 607 int index, 613 608 int *edge_level, ··· 618 613 struct acpi_device *device = NULL; 619 614 struct acpi_pci_link *link = NULL; 620 615 621 - ACPI_FUNCTION_TRACE("acpi_pci_link_get_irq"); 616 + ACPI_FUNCTION_TRACE("acpi_pci_link_allocate_irq"); 622 617 623 618 result = acpi_bus_get_device(handle, &device); 624 619 if (result) { ··· 638 633 return_VALUE(-1); 639 634 } 640 635 641 - if (acpi_pci_link_allocate(link)) 636 + down(&acpi_link_lock); 637 + if (acpi_pci_link_allocate(link)) { 638 + up(&acpi_link_lock); 642 639 return_VALUE(-1); 640 + } 643 641 644 642 if (!link->irq.active) { 643 + up(&acpi_link_lock); 645 644 ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Link active IRQ is 0!\n")); 646 645 return_VALUE(-1); 647 646 } 647 + link->refcnt ++; 648 + up(&acpi_link_lock); 648 649 649 650 if (edge_level) *edge_level = link->irq.edge_level; 650 651 if (active_high_low) *active_high_low = link->irq.active_high_low; 651 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))); 652 655 return_VALUE(link->irq.active); 653 656 } 654 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; 655 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 + } 656 700 /* -------------------------------------------------------------------------- 657 701 Driver Interface 658 702 -------------------------------------------------------------------------- */ ··· 731 677 strcpy(acpi_device_class(device), ACPI_PCI_LINK_CLASS); 732 678 acpi_driver_data(device) = link; 733 679 680 + down(&acpi_link_lock); 734 681 result = acpi_pci_link_get_possible(link); 735 682 if (result) 736 683 goto end; ··· 767 712 end: 768 713 /* disable all links -- to be activated on use */ 769 714 acpi_ut_evaluate_object(link->handle, "_DIS", 0, NULL); 715 + up(&acpi_link_lock); 770 716 771 717 if (result) 772 718 kfree(link); ··· 782 726 { 783 727 struct list_head *node = NULL; 784 728 struct acpi_pci_link *link = NULL; 729 + int ret = 0; 785 730 786 731 ACPI_FUNCTION_TRACE("irqrouter_suspend"); 787 732 788 733 list_for_each(node, &acpi_link.entries) { 789 734 link = list_entry(node, struct acpi_pci_link, node); 790 735 if (!link) { 791 - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid link context\n")); 736 + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, 737 + "Invalid link context\n")); 792 738 continue; 793 739 } 794 - if (link->irq.active && link->irq.initialized) 795 - link->irq.suspend_resume = 1; 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 + } 796 753 } 797 - return_VALUE(0); 754 + return_VALUE(ret); 798 755 } 799 756 800 757 ··· 825 756 826 757 link = (struct acpi_pci_link *) acpi_driver_data(device); 827 758 828 - /* TBD: Acquire/release lock */ 759 + down(&acpi_link_lock); 829 760 list_del(&link->node); 761 + up(&acpi_link_lock); 830 762 831 763 kfree(link); 832 764 ··· 919 849 __setup("acpi_irq_balance", acpi_irq_balance_set); 920 850 921 851 852 + /* FIXME: we will remove this interface after all drivers call pci_disable_device */ 922 853 static struct sysdev_class irqrouter_sysdev_class = { 923 854 set_kset_name("irqrouter"), 924 855 .suspend = irqrouter_suspend,
+2 -1
include/acpi/acpi_drivers.h
··· 56 56 /* ACPI PCI Interrupt Link (pci_link.c) */ 57 57 58 58 int acpi_irq_penalty_init (void); 59 - int acpi_pci_link_get_irq (acpi_handle handle, int index, int *edge_level, 59 + int acpi_pci_link_allocate_irq (acpi_handle handle, int index, int *edge_level, 60 60 int *active_high_low, char **name); 61 + int acpi_pci_link_free_irq(acpi_handle handle); 61 62 62 63 /* ACPI PCI Interrupt Routing (pci_irq.c) */ 63 64
-4
include/linux/acpi.h
··· 440 440 * If this matches the last registration, any IRQ resources for gsi 441 441 * are freed. 442 442 */ 443 - #ifdef CONFIG_ACPI_DEALLOCATE_IRQ 444 443 void acpi_unregister_gsi (u32 gsi); 445 - #endif 446 444 447 445 #ifdef CONFIG_ACPI_PCI 448 446 ··· 465 467 int acpi_pci_irq_enable (struct pci_dev *dev); 466 468 void acpi_penalize_isa_irq(int irq, int active); 467 469 468 - #ifdef CONFIG_ACPI_DEALLOCATE_IRQ 469 470 void acpi_pci_irq_disable (struct pci_dev *dev); 470 - #endif 471 471 472 472 struct acpi_pci_driver { 473 473 struct acpi_pci_driver *next;