diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-02-24 07:55:38 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2016-02-24 07:55:38 -0500 |
commit | e249714571db26cdb1ae8df7ed39971bafa041a7 (patch) | |
tree | 85c8bdee96e4ac222bab6dd6f16ee2d2d13f2c7a /drivers/acpi | |
parent | 5ec5d10682745d3280a37e8ffee1ddcd37ecfa94 (diff) |
Revert "ACPI, PCI, irq: remove interrupt count restriction"
Revert commit b5bd02695471 (ACPI, PCI, irq: remove interrupt count
restriction) that introduced a boot regression on some systems
where it caused kmalloc() to be used too early.
Link: http://marc.info/?l=linux-acpi&m=145580159209240&w=2
Reported-by: Nalla, Ravikanth <ravikanth.nalla@hpe.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/pci_link.c | 136 |
1 files changed, 34 insertions, 102 deletions
diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 5114d8007aa0..ededa909df2f 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> | 4 | * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> |
5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> | 5 | * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> |
6 | * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> | 6 | * Copyright (C) 2002 Dominik Brodowski <devel@brodo.de> |
7 | * Copyright (c) 2015, The Linux Foundation. All rights reserved. | ||
8 | * | 7 | * |
9 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
10 | * | 9 | * |
@@ -438,6 +437,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) | |||
438 | * enabled system. | 437 | * enabled system. |
439 | */ | 438 | */ |
440 | 439 | ||
440 | #define ACPI_MAX_IRQS 256 | ||
441 | #define ACPI_MAX_ISA_IRQ 16 | 441 | #define ACPI_MAX_ISA_IRQ 16 |
442 | 442 | ||
443 | #define PIRQ_PENALTY_PCI_AVAILABLE (0) | 443 | #define PIRQ_PENALTY_PCI_AVAILABLE (0) |
@@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) | |||
447 | #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) | 447 | #define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) |
448 | #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) | 448 | #define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) |
449 | 449 | ||
450 | static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = { | 450 | static int acpi_irq_penalty[ACPI_MAX_IRQS] = { |
451 | PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ | 451 | PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ |
452 | PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ | 452 | PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ |
453 | PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ | 453 | PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ |
@@ -464,68 +464,9 @@ static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = { | |||
464 | PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ | 464 | PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ |
465 | PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ | 465 | PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ |
466 | PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ | 466 | PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ |
467 | /* >IRQ15 */ | ||
467 | }; | 468 | }; |
468 | 469 | ||
469 | struct irq_penalty_info { | ||
470 | int irq; | ||
471 | int penalty; | ||
472 | struct list_head node; | ||
473 | }; | ||
474 | |||
475 | static LIST_HEAD(acpi_irq_penalty_list); | ||
476 | |||
477 | static int acpi_irq_get_penalty(int irq) | ||
478 | { | ||
479 | struct irq_penalty_info *irq_info; | ||
480 | |||
481 | if (irq < ACPI_MAX_ISA_IRQ) | ||
482 | return acpi_irq_isa_penalty[irq]; | ||
483 | |||
484 | list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) { | ||
485 | if (irq_info->irq == irq) | ||
486 | return irq_info->penalty; | ||
487 | } | ||
488 | |||
489 | return 0; | ||
490 | } | ||
491 | |||
492 | static int acpi_irq_set_penalty(int irq, int new_penalty) | ||
493 | { | ||
494 | struct irq_penalty_info *irq_info; | ||
495 | |||
496 | /* see if this is a ISA IRQ */ | ||
497 | if (irq < ACPI_MAX_ISA_IRQ) { | ||
498 | acpi_irq_isa_penalty[irq] = new_penalty; | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /* next, try to locate from the dynamic list */ | ||
503 | list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) { | ||
504 | if (irq_info->irq == irq) { | ||
505 | irq_info->penalty = new_penalty; | ||
506 | return 0; | ||
507 | } | ||
508 | } | ||
509 | |||
510 | /* nope, let's allocate a slot for this IRQ */ | ||
511 | irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL); | ||
512 | if (!irq_info) | ||
513 | return -ENOMEM; | ||
514 | |||
515 | irq_info->irq = irq; | ||
516 | irq_info->penalty = new_penalty; | ||
517 | list_add_tail(&irq_info->node, &acpi_irq_penalty_list); | ||
518 | |||
519 | return 0; | ||
520 | } | ||
521 | |||
522 | static void acpi_irq_add_penalty(int irq, int penalty) | ||
523 | { | ||
524 | int curpen = acpi_irq_get_penalty(irq); | ||
525 | |||
526 | acpi_irq_set_penalty(irq, curpen + penalty); | ||
527 | } | ||
528 | |||
529 | int __init acpi_irq_penalty_init(void) | 470 | int __init acpi_irq_penalty_init(void) |
530 | { | 471 | { |
531 | struct acpi_pci_link *link; | 472 | struct acpi_pci_link *link; |
@@ -546,16 +487,15 @@ int __init acpi_irq_penalty_init(void) | |||
546 | link->irq.possible_count; | 487 | link->irq.possible_count; |
547 | 488 | ||
548 | for (i = 0; i < link->irq.possible_count; i++) { | 489 | for (i = 0; i < link->irq.possible_count; i++) { |
549 | if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) { | 490 | if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) |
550 | int irqpos = link->irq.possible[i]; | 491 | acpi_irq_penalty[link->irq. |
551 | 492 | possible[i]] += | |
552 | acpi_irq_add_penalty(irqpos, penalty); | 493 | penalty; |
553 | } | ||
554 | } | 494 | } |
555 | 495 | ||
556 | } else if (link->irq.active) { | 496 | } else if (link->irq.active) { |
557 | acpi_irq_add_penalty(link->irq.active, | 497 | acpi_irq_penalty[link->irq.active] += |
558 | PIRQ_PENALTY_PCI_POSSIBLE); | 498 | PIRQ_PENALTY_PCI_POSSIBLE; |
559 | } | 499 | } |
560 | } | 500 | } |
561 | 501 | ||
@@ -607,12 +547,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
607 | * the use of IRQs 9, 10, 11, and >15. | 547 | * the use of IRQs 9, 10, 11, and >15. |
608 | */ | 548 | */ |
609 | for (i = (link->irq.possible_count - 1); i >= 0; i--) { | 549 | for (i = (link->irq.possible_count - 1); i >= 0; i--) { |
610 | if (acpi_irq_get_penalty(irq) > | 550 | if (acpi_irq_penalty[irq] > |
611 | acpi_irq_get_penalty(link->irq.possible[i])) | 551 | acpi_irq_penalty[link->irq.possible[i]]) |
612 | irq = link->irq.possible[i]; | 552 | irq = link->irq.possible[i]; |
613 | } | 553 | } |
614 | } | 554 | } |
615 | if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) { | 555 | if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) { |
616 | printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " | 556 | printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. " |
617 | "Try pci=noacpi or acpi=off\n", | 557 | "Try pci=noacpi or acpi=off\n", |
618 | acpi_device_name(link->device), | 558 | acpi_device_name(link->device), |
@@ -628,8 +568,7 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) | |||
628 | acpi_device_bid(link->device)); | 568 | acpi_device_bid(link->device)); |
629 | return -ENODEV; | 569 | return -ENODEV; |
630 | } else { | 570 | } else { |
631 | acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING); | 571 | acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; |
632 | |||
633 | printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", | 572 | printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n", |
634 | acpi_device_name(link->device), | 573 | acpi_device_name(link->device), |
635 | acpi_device_bid(link->device), link->irq.active); | 574 | acpi_device_bid(link->device), link->irq.active); |
@@ -839,7 +778,7 @@ static void acpi_pci_link_remove(struct acpi_device *device) | |||
839 | } | 778 | } |
840 | 779 | ||
841 | /* | 780 | /* |
842 | * modify penalty from cmdline | 781 | * modify acpi_irq_penalty[] from cmdline |
843 | */ | 782 | */ |
844 | static int __init acpi_irq_penalty_update(char *str, int used) | 783 | static int __init acpi_irq_penalty_update(char *str, int used) |
845 | { | 784 | { |
@@ -857,10 +796,13 @@ static int __init acpi_irq_penalty_update(char *str, int used) | |||
857 | if (irq < 0) | 796 | if (irq < 0) |
858 | continue; | 797 | continue; |
859 | 798 | ||
799 | if (irq >= ARRAY_SIZE(acpi_irq_penalty)) | ||
800 | continue; | ||
801 | |||
860 | if (used) | 802 | if (used) |
861 | acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED); | 803 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; |
862 | else | 804 | else |
863 | acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE); | 805 | acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; |
864 | 806 | ||
865 | if (retval != 2) /* no next number */ | 807 | if (retval != 2) /* no next number */ |
866 | break; | 808 | break; |
@@ -877,23 +819,18 @@ static int __init acpi_irq_penalty_update(char *str, int used) | |||
877 | */ | 819 | */ |
878 | void acpi_penalize_isa_irq(int irq, int active) | 820 | void acpi_penalize_isa_irq(int irq, int active) |
879 | { | 821 | { |
880 | int penalty; | 822 | if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { |
881 | 823 | if (active) | |
882 | if (irq < 0) | 824 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; |
883 | return; | 825 | else |
884 | 826 | acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; | |
885 | if (active) | 827 | } |
886 | penalty = PIRQ_PENALTY_ISA_USED; | ||
887 | else | ||
888 | penalty = PIRQ_PENALTY_PCI_USING; | ||
889 | |||
890 | acpi_irq_add_penalty(irq, penalty); | ||
891 | } | 828 | } |
892 | 829 | ||
893 | bool acpi_isa_irq_available(int irq) | 830 | bool acpi_isa_irq_available(int irq) |
894 | { | 831 | { |
895 | return irq >= 0 && | 832 | return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) || |
896 | (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS); | 833 | acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS); |
897 | } | 834 | } |
898 | 835 | ||
899 | /* | 836 | /* |
@@ -903,18 +840,13 @@ bool acpi_isa_irq_available(int irq) | |||
903 | */ | 840 | */ |
904 | void acpi_penalize_sci_irq(int irq, int trigger, int polarity) | 841 | void acpi_penalize_sci_irq(int irq, int trigger, int polarity) |
905 | { | 842 | { |
906 | int penalty; | 843 | if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) { |
907 | 844 | if (trigger != ACPI_MADT_TRIGGER_LEVEL || | |
908 | if (irq < 0) | 845 | polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) |
909 | return; | 846 | acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS; |
910 | 847 | else | |
911 | if (trigger != ACPI_MADT_TRIGGER_LEVEL || | 848 | acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING; |
912 | polarity != ACPI_MADT_POLARITY_ACTIVE_LOW) | 849 | } |
913 | penalty = PIRQ_PENALTY_ISA_ALWAYS; | ||
914 | else | ||
915 | penalty = PIRQ_PENALTY_PCI_USING; | ||
916 | |||
917 | acpi_irq_add_penalty(irq, penalty); | ||
918 | } | 850 | } |
919 | 851 | ||
920 | /* | 852 | /* |