總攬

https://myfamily12345.pixnet.net/blog/post/404540683

 

 

在 System.map中,可以看到相當多相關於PCI的初始化動作,

ffffffff81eab7e0 T __initcall_start

............................................................
ffffffff81eaba20 t __initcall_pcibus_class_init2
ffffffff81eaba28 t __initcall_pci_driver_init2
ffffffff81eaba30 t __initcall_backlight_class_init2
............................................................
ffffffff81eabb28 t __initcall_pci_arch_init3

.....................................................................................................................................
ffffffff81eabae0 t __initcall_gigantic_pages_init3
ffffffff81eabae8 t __initcall_kcmp_cookies_init3
ffffffff81eabaf0 t __initcall_acpi_pci_init3
ffffffff81eabaf8 t __initcall_dma_bus_init3
......................................................................................................................................
ffffffff81eabb08 t __initcall_setup_vcpu_hotplug_event3
ffffffff81eabb10 t __initcall_register_xen_pci_notifier3
ffffffff81eabb18 t __initcall_xen_pcpu_init3
ffffffff81eabb20 t __initcall_dmi_id_init3
ffffffff81eabb28 t __initcall_pci_arch_init3
ffffffff81eabb30 T __initcall4_start
.....................................................
ffffffff81eabc70 t __initcall_pci_slot_init4
.........................................................
ffffffff81eabc80 t __initcall_acpi_init4

.....................................................................................
ffffffff81eabd60 t __initcall_pci_subsys_init4
...........................................................
ffffffff81eabf58 t __initcall_init_acpi_pm_clocksource5
ffffffff81eabf60 t __initcall_pcibios_assign_resources5
............................................................
ffffffff81eabf98 t __initcall_pci_apply_final_quirks5s
ffffffff81eabfa0 t __initcall_acpi_reserve_resources5s
ffffffff81eabfa8 t __initcall_populate_rootfsrootfs
ffffffff81eabfa8 T __initcallrootfs_start
ffffffff81eabfb0 t __initcall_pci_iommu_initrootfs
............................................................
ffffffff81eac360 t __initcall_phy_core_init6
ffffffff81eac368 t __initcall_pci_proc_init6
ffffffff81eac370 t __initcall_pcie_portdrv_init6
ffffffff81eac378 t __initcall_aer_service_init6
ffffffff81eac380 t __initcall_pcie_pme_service_init6
ffffffff81eac388 t __initcall_pci_hotplug_init6
ffffffff81eac390 t __initcall_pcied_init6
ffffffff81eac398 t __initcall_xenfb_init6
..........................................................
ffffffff81eac3f0 t __initcall_dw_pci_driver_init6
...........................................................
ffffffff81eac420 t __initcall_platform_pci_init6
..........................................................
ffffffff81eac448 t __initcall_serial8250_init6
ffffffff81eac450 t __initcall_serial_pci_driver_init6
ffffffff81eac458 t __initcall_lpss8250_pci_driver_init6
ffffffff81eac460 t __initcall_mid8250_pci_driver_init6
ffffffff81eac468 t __initcall_hpet_init6
................................................................
ffffffff81eac4e0 t __initcall_nvme_core_init6
ffffffff81eac4e8 t __initcall_nvme_init6
ffffffff81eac4f0 t __initcall_ahci_pci_driver_init6
ffffffff81eac4f8 t __initcall_net_olddevs_init6
ffffffff81eac500 t __initcall_ehci_hcd_init6
ffffffff81eac508 t __initcall_ehci_pci_init6
ffffffff81eac510 t __initcall_ohci_hcd_mod_init6
ffffffff81eac518 t __initcall_xhci_hcd_init6
ffffffff81eac520 t __initcall_xhci_pci_init6
ffffffff81eac528 t __initcall_i8042_init6
..............................................................
ffffffff81eac710 t __initcall_prandom_reseed7
ffffffff81eac718 t __initcall_pci_resource_alignment_sysfs_init7
ffffffff81eac720 t __initcall_pci_sysfs_init7
ffffffff81eac728 t __initcall_bert_init7
...................................................................
ffffffff81eac760 t __initcall_efi_shutdown_init7
ffffffff81eac768 t __initcall_pci_mmcfg_late_insert_resources7
ffffffff81eac770 t __initcall_register_sk_filter_ops7

 

(1) 在/sys/class目錄下,產生 pci_bus 的目錄:

/sys/class is exported by the kernel at run time, exposing the hierarchy of the hardware through sysfs.

'/sys/class' is used to group all devices that are similar (by class) so you'll find all memory stuff under '/sys/class/mem', sensor stuff under '/sys/class/thermal', network stuff under '/sys/class/net' and so on.

路徑 /drivers/pci/probe.c

static struct class pcibus_class = {
    .name        = "pci_bus",
    .dev_release    = &release_pcibus_dev,
    .dev_groups    = pcibus_groups,
};

static int __init pcibus_class_init(void)
{
    return class_register(&pcibus_class);
}

 

(2) 在/sys/bus下,建立 pci目錄,如果,有偵測到PCI devcie 將會在將會在 /sys/bus/pci/drivers 建立device使用的目錄

路徑  /drivers/pci/pci-driver.c

struct bus_type pci_bus_type = {
    .name        = "pci",
    .match        = pci_bus_match,
    .uevent        = pci_uevent,
    .probe        = pci_device_probe,
    .remove        = pci_device_remove,
    .shutdown    = pci_device_shutdown,
    .dev_groups    = pci_dev_groups,
    .bus_groups    = pci_bus_groups,
    .drv_groups    = pci_drv_groups,
    .pm        = PCI_PM_OPS_PTR,
};

static int __init pci_driver_init(void)
{
    return bus_register(&pci_bus_type);
}

 

(3)ACPI(Advanced  Configuration and Power Interface)負責x86處理器系統的資源,電源,熱插拔和中斷向量管理

  在程式中設定相關ACPI2的相關函式,同時顯示ACPI Hot Plug PCI Controller Driver 版本

路徑  /drivers/pci/pci-acpi.c

static int __init acpi_pci_init(void)
{
    int ret;

    if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_MSI) {
        pr_info("ACPI FADT declares the system doesn't support MSI, so disable it\n");
        pci_no_msi();
    }

    if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
        pr_info("ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
        pcie_no_aspm();
    }

    ret = register_acpi_bus_type(&acpi_pci_bus);
    if (ret)
        return 0;

    pci_set_platform_pm(&acpi_pci_platform_pm);
    acpi_pci_slot_init();
    acpiphp_init();

    return 0;
}

(4) 對PCI總線進行初始化,指定raw_pci_ops透過 0xCF8 0xCFC 兩個端口進行讀寫,指定pci_mmcfg到raw_pci_ext_ops,

CONFIG_PCI_BIOS => 透過BIOS對PCI總線init

CONFIG_PCI_DIRECT=> 透過BIOS對linux總線init

路徑  /arch/x86/pci/init.c

static __init int pci_arch_init(void)
{
#ifdef CONFIG_PCI_DIRECT
    int type = 0;

    type = pci_direct_probe();
#endif

    if (!(pci_probe & PCI_PROBE_NOEARLY))
        pci_mmcfg_early_init();

    if (x86_init.pci.arch_init && !x86_init.pci.arch_init())
        return 0;

#ifdef CONFIG_PCI_BIOS
    pci_pcbios_init();
#endif
    /*
     * don't check for raw_pci_ops here because we want pcbios as last
     * fallback, yet it's needed to run first to set pcibios_last_bus
     * in case legacy PCI probing is used. otherwise detecting peer busses
     * fails.
     */
#ifdef CONFIG_PCI_DIRECT
    pci_direct_init(type);
#endif
    if (!raw_pci_ops && !raw_pci_ext_ops)
        printk(KERN_ERR
        "PCI: Fatal: No config space access function found\n");

    dmi_check_pciprobe();

    dmi_check_skip_isa_align();

    return 0;
}

pci_arch_init

|--> pci_mmcfg_early_init

      |--> pci_mmcfg_check_hostbridge

      |--> pci_parse_mcfg

              |-->  free_all_mmcfg

              |--> acpi_mcfg_check_entry

              |-->pci_mmconfig_add

                     |--> pci_mmconfig_alloc

                     |--> list_add_sorted

      |-->   __pci_mmcfg_init  

              |--> pci_mmcfg_arch_init

                    |--> pci_mmcfg_arch_map

                    |--> mcfg_ioremap

 

(5)   在/sys/bus/pci/下建立一個slots目錄跟 kobject結構

static int pci_slot_init(void)
{
    struct kset *pci_bus_kset;

    pci_bus_kset = bus_get_kset(&pci_bus_type);
    pci_slots_kset = kset_create_and_add("slots", NULL,
                        &pci_bus_kset->kobj);
    if (!pci_slots_kset) {
        printk(KERN_ERR "PCI: Slot initialization failure\n");
        return -ENOMEM;
    }
    return 0;
}

 

(6) acpi 相關的init 動作


static int __init acpi_init(void)
{
    int result;

    if (acpi_disabled) {
        printk(KERN_INFO PREFIX "Interpreter disabled.\n");
        return -ENODEV;
    }

    acpi_kobj = kobject_create_and_add("acpi", firmware_kobj);
    if (!acpi_kobj) {
        printk(KERN_WARNING "%s: kset create error\n", __func__);
        acpi_kobj = NULL;
    }

    init_acpi_device_notify();
    result = acpi_bus_init();
    if (result) {
        disable_acpi();
        return result;
    }

    pci_mmcfg_late_init();
    acpi_iort_init();
    acpi_scan_init();
    acpi_ec_init();
    acpi_debugfs_init();
    acpi_sleep_proc_init();
    acpi_wakeup_device_init();
    acpi_debugger_init();
    acpi_setup_sb_notify_handler();
    acpi_set_processor_mapping();
    return 0;
}
 

acpi_init

   |-->  acpi_scan_init

                 |-->  acpi_pci_root_init

                 |-->  acpi_pci_link_init

 

 

(7) 建立 PCI Root Bridge,並配置相關 io mem resource

static struct acpi_scan_handler pci_root_handler = {
    .ids = root_device_ids,
    .attach = acpi_pci_root_add,
    .detach = acpi_pci_root_remove,
    .hotplug = {
        .enabled = true,
        .scan_dependent = acpi_pci_root_scan_dependent,
    },
};


void __init acpi_pci_root_init(void)
{
    acpi_hest_init();
    if (acpi_pci_disabled)
        return;

    pci_acpi_crs_quirks();
    acpi_scan_add_handler_with_hotplug(&pci_root_handler, "pci_root");
}
 

acpi_pci_root_init

|-->  pci_root_handler(acpi_pci_root_add)

         ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])

        |--> negotiate_os_control

        |--> pci_acpi_scan_root

                kzalloc_node(sizeof(*info), GFP_KERNEL, node);

                |--> acpi_pci_root_create

                        |--> pci_acpi_root_init_info

                                |--> setup_mcfg_map                 

                                        |--> pci_mmconfig_insert

                                                |-->  pci_mmconfig_lookup

                      |-->   acpi_pci_probe_root_resources

                      |-->  pci_acpi_root_add_resources                                                                                 

                      |-->  pci_add_resource

                      |-->  pci_create_root_bus

                              ||-->  pci_alloc_bus

                              ||-->   pci_find_bus(pci_domain_nr(b), bus)

                              ||-->  pcibios_root_bridge_prepare(bridge)

                                          kzalloc

                                          pci_bus 0000:00: root bus resource [io  0x0000-0x0cf7 window]
                                          pci_bus 0000:00: root bus resource [io  0x0d00-0xffff window]
                                          pci_bus 0000:00: root bus resource [mem 0x000a0000-0x000bffff  window]
                                          pci_bus 0000:00: root bus resource [mem 0x000c0000-0x000dffff  window]
                                          pci_bus 0000:00: root bus resource [mem 0x80000000-0xdfffffff   window]
                                          pci_bus 0000:00: root bus resource [mem 0x480000000-0x7fffffffff window]
                                          pci_bus 0000:00: root bus resource [mem 0xfe010000-0xfe010fff window]
                                          pci_bus 0000:00: root bus resource [mem 0xfa000000-0xfa0fffff  window]
                                          pci_bus 0000:00: root bus resource [mem 0xfb000000-0xfb7fffff window]
                                          pci_bus 0000:00: root bus resource [mem 0xfa100000-0xfa1007ff  window]

                              ||--> pci_bus_insert_busn_res

                                          pci_bus 0000:00: root bus resource [bus 00-ff]

                              ||--> pci_scan_child_bus

                                                                               |-->  for (devfn = 0; devfn < 0x100; devfn += 8)

                                                                                          pci_scan_slot

                                                                                            |-->pci_scan_single_device

                                                                                                      |--> pci_get_slot

                                                                                                      |--> pci_scan_device

                                                                                                              |--> pci_bus_read_dev_vendor_id

                                                                                                              |--> pci_alloc_dev

                                                                                                              |--> pci_set_of_node

                                                                                                              |--> pci_setup_device

                                                                                                                       0000:00:00.0  [domain:busnum:PCIslot.func]

                                                                                                      |--> pci_device_add

                                                                                                            |--> pci_configure_device

                                                                                                            |--> set_dev_node

                                                                                                            |--> pci_dma_configure

                                                                                                            |--> pci_fixup_device

                                                                                                            |--> pci_reassigndev_resource_alignment

                                                                                                            |--> pci_init_capabilities

                                                                                                            |--> pcibios_add_device

                                                                                                            |--> pci_set_msi_domain

                                                                                                            |-->device_add

                                   |--> pci_iov_bus_range 

                                   |--> pcibios_fixup_bus 

                                                                                        |-->pci_read_bridge_bases

                                                                                                pci 0000:00:17.0: PCI bridge to [bus 06-07]

                                                                                                 |-->pci_bus_add_resource

                                                                                        |-->pcibios_fixup_device_resources

                                    |--> list_for_each_entry(dev, &bus->devices, bus_list) 

                                                                                               pci_scan_bridge

                                                                                                      |--> pci_read_config_dword

                                                                                                      |--> pci_read_config_word

                                                                                                      |--> pci_write_config_word

                                                                                                      |--> pci_enable_crs

                                                                                                      |--> pci_find_bus

                                                                                                      |--> pci_add_new_bus

                                                                                                      |--> pci_scan_child_bus

                              ||--> pci_set_host_bridge_release

arrow
arrow
    文章標籤
    PCIe linux
    全站熱搜
    創作者介紹
    創作者 kingsman 的頭像
    kingsman

    Kingsman的部落格

    kingsman 發表在 痞客邦 留言(0) 人氣()