Lines 99-105
Link Here
|
99 |
void *context) |
99 |
void *context) |
100 |
{ |
100 |
{ |
101 |
struct acpi_pci_link *link = (struct acpi_pci_link *) context; |
101 |
struct acpi_pci_link *link = (struct acpi_pci_link *) context; |
102 |
int i = 0; |
102 |
u32 i = 0; |
103 |
|
103 |
|
104 |
ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible"); |
104 |
ACPI_FUNCTION_TRACE("acpi_pci_link_check_possible"); |
105 |
|
105 |
|
Lines 294-300
Link Here
|
294 |
|
294 |
|
295 |
if (!link->irq.active) { |
295 |
if (!link->irq.active) { |
296 |
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n")); |
296 |
ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "No active IRQ resource found\n")); |
297 |
printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for device (%s [%s]).\n", irq, acpi_device_name(link->device), acpi_device_bid(link->device)); |
297 |
printk(KERN_WARNING "_CRS returns NULL! Using IRQ %d for" |
|
|
298 |
"device (%s [%s]).\n", irq, |
299 |
acpi_device_name(link->device), |
300 |
acpi_device_bid(link->device)); |
298 |
link->irq.active = irq; |
301 |
link->irq.active = irq; |
299 |
} |
302 |
} |
300 |
|
303 |
|
Lines 429-458
Link Here
|
429 |
PCI Link IRQ Management |
432 |
PCI Link IRQ Management |
430 |
-------------------------------------------------------------------------- */ |
433 |
-------------------------------------------------------------------------- */ |
431 |
|
434 |
|
432 |
#define ACPI_MAX_IRQS 256 |
|
|
433 |
#define ACPI_MAX_ISA_IRQ 16 |
434 |
|
435 |
/* |
435 |
/* |
436 |
* IRQ penalties are used to promote PCI IRQ balancing. We set each ISA- |
436 |
* Interrupt sharing can impact performance, so this code |
437 |
* possible IRQ (0-15) with a default penalty relative to its feasibility |
437 |
* spreads the PCI link devices across the available IRQs. |
438 |
* for PCI's use: |
438 |
* |
|
|
439 |
* A tables of penalties avoids directing PCI interrupts to well known |
440 |
* ISA IRQs. Boot params are available to over-ride the default table: |
439 |
* |
441 |
* |
440 |
* Never use: 0, 1, 2 (timer, keyboard, and cascade) |
442 |
* List interrupts that are free for PCI use. |
441 |
* Avoid using: 13, 14, and 15 (FP error and IDE) |
443 |
* acpi_irq_pci=n[,m] |
442 |
* Penalize: 3, 4, 6, 7, 12 (known ISA uses) |
|
|
443 |
* |
444 |
* |
444 |
* Thus we're left with IRQs 5, 9, 10, 11, and everything above 15 (IO[S]APIC) |
445 |
* List interrupts that should not be used for PCI: |
445 |
* as 'best bets' for PCI use. |
446 |
* acpi_irq_isa=n[,m] |
|
|
447 |
* |
448 |
* Note that PCI IRQ routers have a list of possible IRQs, |
449 |
* which may not include the IRQs this table says are available. |
450 |
* |
451 |
* Since this heuristic can't tell the difference between a link |
452 |
* that no device will attach to, vs. a link which may be shared |
453 |
* by multiple active devices -- it is not optimal. |
454 |
* |
455 |
* If interrupt performance is that important, get an IO-APIC system |
456 |
* with a pin dedicated to each device. Or for that matter, an MSI |
457 |
* enabled system. |
446 |
*/ |
458 |
*/ |
447 |
|
459 |
|
|
|
460 |
#define ACPI_MAX_IRQS 256 |
461 |
#define ACPI_MAX_ISA_IRQ 16 |
462 |
|
463 |
#define PIRQ_PENALTY_PCI_AVAILABLE (0) |
464 |
#define PIRQ_PENALTY_PCI_POSSIBLE (16*16) |
465 |
#define PIRQ_PENALTY_PCI_USING (16*16*16) |
466 |
#define PIRQ_PENALTY_ISA_TYPICAL (16*16*16*16) |
467 |
#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16) |
468 |
#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16) |
469 |
|
448 |
static int acpi_irq_penalty[ACPI_MAX_IRQS] = { |
470 |
static int acpi_irq_penalty[ACPI_MAX_IRQS] = { |
449 |
1000000, 1000000, 1000000, 10000, |
471 |
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */ |
450 |
10000, 0, 10000, 10000, |
472 |
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */ |
451 |
10000, 0, 0, 0, |
473 |
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */ |
452 |
10000, 100000, 100000, 100000, |
474 |
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ3 serial */ |
|
|
475 |
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ4 serial */ |
476 |
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ5 PCI */ |
477 |
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ6 */ |
478 |
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ7 parallel, spurious */ |
479 |
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ8 rtc, sometimes */ |
480 |
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ9 PCI, often acpi */ |
481 |
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ10 PCI */ |
482 |
PIRQ_PENALTY_PCI_AVAILABLE, /* IRQ11 PCI */ |
483 |
PIRQ_PENALTY_ISA_TYPICAL, /* IRQ12 mouse */ |
484 |
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */ |
485 |
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */ |
486 |
PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */ |
487 |
/* >IRQ15 */ |
453 |
}; |
488 |
}; |
454 |
|
489 |
|
455 |
|
|
|
456 |
int |
490 |
int |
457 |
acpi_pci_link_check (void) |
491 |
acpi_pci_link_check (void) |
458 |
{ |
492 |
{ |
Lines 473-492
Link Here
|
473 |
continue; |
507 |
continue; |
474 |
} |
508 |
} |
475 |
|
509 |
|
476 |
if (link->irq.active) |
510 |
/* |
477 |
acpi_irq_penalty[link->irq.active] += 100; |
511 |
* reflect the possible and active irqs in the penalty table -- |
478 |
else if (link->irq.possible_count) { |
512 |
* useful for breaking ties. |
479 |
int penalty = 100 / link->irq.possible_count; |
513 |
*/ |
480 |
for (i=0; i<link->irq.possible_count; i++) { |
514 |
if (link->irq.possible_count) { |
|
|
515 |
int penalty = PIRQ_PENALTY_PCI_POSSIBLE / link->irq.possible_count; |
516 |
|
517 |
for (i = 0; i < link->irq.possible_count; i++) { |
481 |
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) |
518 |
if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) |
482 |
acpi_irq_penalty[link->irq.possible[i]] += penalty; |
519 |
acpi_irq_penalty[link->irq.possible[i]] += penalty; |
483 |
} |
520 |
} |
|
|
521 |
|
522 |
} else if (link->irq.active) { |
523 |
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_POSSIBLE; |
484 |
} |
524 |
} |
485 |
} |
525 |
} |
486 |
|
|
|
487 |
return_VALUE(0); |
526 |
return_VALUE(0); |
488 |
} |
527 |
} |
489 |
|
528 |
|
|
|
529 |
static int acpi_irq_static; /* don't re-program active IRQs */ |
530 |
|
490 |
static int acpi_pci_link_allocate(struct acpi_pci_link* link) { |
531 |
static int acpi_pci_link_allocate(struct acpi_pci_link* link) { |
491 |
int irq; |
532 |
int irq; |
492 |
int i; |
533 |
int i; |
Lines 500-511
Link Here
|
500 |
irq = link->irq.active; |
541 |
irq = link->irq.active; |
501 |
} else { |
542 |
} else { |
502 |
irq = link->irq.possible[0]; |
543 |
irq = link->irq.possible[0]; |
|
|
544 |
} |
503 |
|
545 |
|
|
|
546 |
if (!(link->irq.active && acpi_irq_static)) { |
504 |
/* |
547 |
/* |
505 |
* Select the best IRQ. This is done in reverse to promote |
548 |
* Select the best IRQ. This is done in reverse to promote |
506 |
* the use of IRQs 9, 10, 11, and >15. |
549 |
* the use of IRQs 9, 10, 11, and >15. |
507 |
*/ |
550 |
*/ |
508 |
for (i=(link->irq.possible_count-1); i>0; i--) { |
551 |
for (i = (link->irq.possible_count - 1); i >= 0; i--) { |
509 |
if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) |
552 |
if (acpi_irq_penalty[irq] > acpi_irq_penalty[link->irq.possible[i]]) |
510 |
irq = link->irq.possible[i]; |
553 |
irq = link->irq.possible[i]; |
511 |
} |
554 |
} |
Lines 518-530
Link Here
|
518 |
acpi_device_bid(link->device)); |
561 |
acpi_device_bid(link->device)); |
519 |
return_VALUE(-ENODEV); |
562 |
return_VALUE(-ENODEV); |
520 |
} else { |
563 |
} else { |
521 |
acpi_irq_penalty[link->irq.active] += 100; |
564 |
acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING; |
522 |
printk(PREFIX "%s [%s] enabled at IRQ %d\n", |
565 |
printk(PREFIX "%s [%s] enabled at IRQ %d\n", |
523 |
acpi_device_name(link->device), |
566 |
acpi_device_name(link->device), |
524 |
acpi_device_bid(link->device), link->irq.active); |
567 |
acpi_device_bid(link->device), link->irq.active); |
525 |
} |
568 |
} |
526 |
|
569 |
|
527 |
link->irq.setonboot = 1; |
570 |
link->irq.setonboot = 1; |
|
|
571 |
|
528 |
return_VALUE(0); |
572 |
return_VALUE(0); |
529 |
} |
573 |
} |
530 |
|
574 |
|
Lines 607-615
Link Here
|
607 |
if (result) |
651 |
if (result) |
608 |
goto end; |
652 |
goto end; |
609 |
|
653 |
|
|
|
654 |
/* query and set link->irq.active */ |
610 |
acpi_pci_link_get_current(link); |
655 |
acpi_pci_link_get_current(link); |
611 |
|
656 |
|
612 |
printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), acpi_device_bid(device)); |
657 |
//#ifdef CONFIG_ACPI_DEBUG |
|
|
658 |
printk(PREFIX "%s [%s] (IRQs", acpi_device_name(device), |
659 |
acpi_device_bid(device)); |
613 |
for (i = 0; i < link->irq.possible_count; i++) { |
660 |
for (i = 0; i < link->irq.possible_count; i++) { |
614 |
if (link->irq.active == link->irq.possible[i]) { |
661 |
if (link->irq.active == link->irq.possible[i]) { |
615 |
printk(" *%d", link->irq.possible[i]); |
662 |
printk(" *%d", link->irq.possible[i]); |
Lines 619-624
Link Here
|
619 |
printk(" %d", link->irq.possible[i]); |
666 |
printk(" %d", link->irq.possible[i]); |
620 |
} |
667 |
} |
621 |
printk(")\n"); |
668 |
printk(")\n"); |
|
|
669 |
//#endif /* CONFIG_ACPI_DEBUG */ |
622 |
|
670 |
|
623 |
/* TBD: Acquire/release lock */ |
671 |
/* TBD: Acquire/release lock */ |
624 |
list_add_tail(&link->node, &acpi_link.entries); |
672 |
list_add_tail(&link->node, &acpi_link.entries); |
Lines 670-674
Link Here
|
670 |
|
718 |
|
671 |
return_VALUE(0); |
719 |
return_VALUE(0); |
672 |
} |
720 |
} |
|
|
721 |
|
722 |
/* |
723 |
* modify acpi_irq_penalty[] from cmdline |
724 |
*/ |
725 |
static int __init acpi_irq_penalty_update(char *str, int used) |
726 |
{ |
727 |
int i; |
728 |
|
729 |
for (i = 0; i < 16; i++) { |
730 |
int retval; |
731 |
int irq; |
732 |
|
733 |
retval = get_option(&str,&irq); |
734 |
|
735 |
if (!retval) |
736 |
break; /* no number found */ |
737 |
|
738 |
if (irq < 0) |
739 |
continue; |
740 |
|
741 |
if (irq >= ACPI_MAX_IRQS) |
742 |
continue; |
743 |
|
744 |
if (used) |
745 |
acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED; |
746 |
else |
747 |
acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE; |
748 |
|
749 |
if (retval != 2) /* no next number */ |
750 |
break; |
751 |
} |
752 |
return 1; |
753 |
} |
754 |
|
755 |
/* |
756 |
* Over-ride default table to reserve additional IRQs for use by ISA |
757 |
* e.g. acpi_irq_isa=5 |
758 |
* Useful for telling ACPI how not to interfere with your ISA sound card. |
759 |
*/ |
760 |
static int __init acpi_irq_isa(char *str) |
761 |
{ |
762 |
return(acpi_irq_penalty_update(str, 1)); |
763 |
} |
764 |
__setup("acpi_irq_isa=", acpi_irq_isa); |
765 |
|
766 |
|
767 |
/* |
768 |
* Over-ride default table to free additional IRQs for use by PCI |
769 |
* e.g. acpi_irq_pci=7,15 |
770 |
* Useful for freeing up IRQs to reduce PCI IRQ sharing. |
771 |
*/ |
772 |
static int __init acpi_irq_pci(char *str) |
773 |
{ |
774 |
return(acpi_irq_penalty_update(str, 0)); |
775 |
} |
776 |
__setup("acpi_irq_pci=", acpi_irq_pci); |
777 |
|
778 |
/* |
779 |
* Do not re-program active IRQs, |
780 |
* keep the static active settings left by the BIOS. |
781 |
* Useful for working around broken BIOS. |
782 |
*/ |
783 |
static int __init acpi_irq_static_set(char *str) |
784 |
{ |
785 |
acpi_irq_static = 1; |
786 |
return(1); |
787 |
} |
788 |
__setup("acpi_irq_static", acpi_irq_static_set); |
673 |
|
789 |
|
674 |
subsys_initcall(acpi_pci_link_init); |
790 |
subsys_initcall(acpi_pci_link_init); |