@@ -552,6 +552,132 @@ static void remove_bridge(acpi_handle handle)
552
552
}
553
553
}
554
554
555
+ static struct pci_dev * get_apic_pci_info (acpi_handle handle )
556
+ {
557
+ struct acpi_pci_id id ;
558
+ struct pci_bus * bus ;
559
+ struct pci_dev * dev ;
560
+
561
+ if (ACPI_FAILURE (acpi_get_pci_id (handle , & id )))
562
+ return NULL ;
563
+
564
+ bus = pci_find_bus (id .segment , id .bus );
565
+ if (!bus )
566
+ return NULL ;
567
+
568
+ dev = pci_get_slot (bus , PCI_DEVFN (id .device , id .function ));
569
+ if (!dev )
570
+ return NULL ;
571
+
572
+ if ((dev -> class != PCI_CLASS_SYSTEM_PIC_IOAPIC ) &&
573
+ (dev -> class != PCI_CLASS_SYSTEM_PIC_IOXAPIC ))
574
+ {
575
+ pci_dev_put (dev );
576
+ return NULL ;
577
+ }
578
+
579
+ return dev ;
580
+ }
581
+
582
+ static int get_gsi_base (acpi_handle handle , u32 * gsi_base )
583
+ {
584
+ acpi_status status ;
585
+ int result = -1 ;
586
+ unsigned long gsb ;
587
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER , NULL };
588
+ union acpi_object * obj ;
589
+ void * table ;
590
+
591
+ status = acpi_evaluate_integer (handle , "_GSB" , NULL , & gsb );
592
+ if (ACPI_SUCCESS (status )) {
593
+ * gsi_base = (u32 )gsb ;
594
+ return 0 ;
595
+ }
596
+
597
+ status = acpi_evaluate_object (handle , "_MAT" , NULL , & buffer );
598
+ if (ACPI_FAILURE (status ) || !buffer .length || !buffer .pointer )
599
+ return -1 ;
600
+
601
+ obj = buffer .pointer ;
602
+ if (obj -> type != ACPI_TYPE_BUFFER )
603
+ goto out ;
604
+
605
+ table = obj -> buffer .pointer ;
606
+ switch (((acpi_table_entry_header * )table )-> type ) {
607
+ case ACPI_MADT_IOSAPIC :
608
+ * gsi_base = ((struct acpi_table_iosapic * )table )-> global_irq_base ;
609
+ result = 0 ;
610
+ break ;
611
+ case ACPI_MADT_IOAPIC :
612
+ * gsi_base = ((struct acpi_table_ioapic * )table )-> global_irq_base ;
613
+ result = 0 ;
614
+ break ;
615
+ default :
616
+ break ;
617
+ }
618
+ out :
619
+ acpi_os_free (buffer .pointer );
620
+ return result ;
621
+ }
622
+
623
+ static acpi_status
624
+ ioapic_add (acpi_handle handle , u32 lvl , void * context , void * * rv )
625
+ {
626
+ acpi_status status ;
627
+ unsigned long sta ;
628
+ acpi_handle tmp ;
629
+ struct pci_dev * pdev ;
630
+ u32 gsi_base ;
631
+ u64 phys_addr ;
632
+
633
+ /* Evaluate _STA if present */
634
+ status = acpi_evaluate_integer (handle , "_STA" , NULL , & sta );
635
+ if (ACPI_SUCCESS (status ) && sta != ACPI_STA_ALL )
636
+ return AE_CTRL_DEPTH ;
637
+
638
+ /* Scan only PCI bus scope */
639
+ status = acpi_get_handle (handle , "_HID" , & tmp );
640
+ if (ACPI_SUCCESS (status ))
641
+ return AE_CTRL_DEPTH ;
642
+
643
+ if (get_gsi_base (handle , & gsi_base ))
644
+ return AE_OK ;
645
+
646
+ pdev = get_apic_pci_info (handle );
647
+ if (!pdev )
648
+ return AE_OK ;
649
+
650
+ if (pci_enable_device (pdev )) {
651
+ pci_dev_put (pdev );
652
+ return AE_OK ;
653
+ }
654
+
655
+ pci_set_master (pdev );
656
+
657
+ if (pci_request_region (pdev , 0 , "I/O APIC(acpiphp)" )) {
658
+ pci_disable_device (pdev );
659
+ pci_dev_put (pdev );
660
+ return AE_OK ;
661
+ }
662
+
663
+ phys_addr = pci_resource_start (pdev , 0 );
664
+ if (acpi_register_ioapic (handle , phys_addr , gsi_base )) {
665
+ pci_release_region (pdev , 0 );
666
+ pci_disable_device (pdev );
667
+ pci_dev_put (pdev );
668
+ return AE_OK ;
669
+ }
670
+
671
+ return AE_OK ;
672
+ }
673
+
674
+ static int acpiphp_configure_ioapics (acpi_handle handle )
675
+ {
676
+ acpi_walk_namespace (ACPI_TYPE_DEVICE , handle ,
677
+ ACPI_UINT32_MAX , ioapic_add , NULL , NULL );
678
+ return 0 ;
679
+ }
680
+
555
681
static int power_on_slot (struct acpiphp_slot * slot )
556
682
{
557
683
acpi_status status ;
@@ -942,6 +1068,7 @@ static int acpiphp_configure_bridge (acpi_handle handle)
942
1068
acpiphp_sanitize_bus (bus );
943
1069
acpiphp_set_hpp_values (handle , bus );
944
1070
pci_enable_bridges (bus );
1071
+ acpiphp_configure_ioapics (handle );
945
1072
return 0 ;
946
1073
}
947
1074
0 commit comments