PCIe Port 總線驅動


2.1 關於本指南

本指南介紹了PCI Express Port Bus驅動程序的基礎知識,並提供了如何使服務驅動程序向PCI Express Port Bus driver注冊/注銷的信息。

2.2 什么是PCIe端口總線驅動程序 

PCI Express Port是一種邏輯PCI-PCI橋接結構。有兩種類型的PCI Express端口:Root Port 和 Switch Port。Root Port從PCI Express根Complex生成PCI Express鏈接,而Switch Port將PCI Express鏈接連接到內部邏輯PCI總線。switch端口,它的副總線代表了switch的內部路由邏輯,被稱為swicth的上行端口。switch的下行端口從switch的內部路由總線橋接到PCI Express switch下行PCI Express鏈路的總線。

根據端口類型的不同,PCI Express Port最多可以提供四種不同的功能,在本文檔中稱為服務。PCI Express Port的服務包括本地熱插拔支持(HP)、電源管理事件支持(PME)、高級錯誤報告支持(AER)和虛擬通道支持(VC)。這些服務可以由單個復雜的驅動程序處理,也可以由相應的服務驅動程序單獨分發和處理。

2.3 為什么使用PCI Express端口總線驅動程序?

在現有的Linux內核中,Linux設備驅動程序模型只允許單個驅動程序處理物理設備。PCI Express Port是具有多種不同服務的PCI-PCI橋接設備。為了維護一個干凈和簡單的解決方案,每個服務可能都有自己的軟件服務驅動程序。在這種情況下,多個服務驅動程序將競爭單個PCI-PCI橋設備。例如,如果首先加載PCI Express根端口熱插拔服務驅動程序,那么它將聲明一個PCI-PCI橋根端口。因此,內核不會為該根端口加載其他服務驅動程序。換句話說,不可能使用當前驅動程序模型在PCI-PCI Bridge設備上同時加載和運行多個服務驅動程序。

要啟用多個服務驅動程序同時運行,需要有一個PCI Express Port Bus驅動程序,該驅動程序管理所有填充的PCI Express Ports,並根據需要將所有提供的服務請求分發給相應的服務驅動程序。使用PCI Express Port Bus驅動程序的一些關鍵優勢如下:

  • 允許多個服務驅動程序在PCI-PCI橋端口設備上同時運行。
  • 允許以獨立的分階段方法實現的服務驅動程序。
  • 允許一個服務驅動程序在多個PCI-PCI橋端口設備上運行。
  • 管理和分配PCI-PCI橋端口設備的資源到請求的服務驅動程序。

2.4 配置PCI Express端口總線驅動程序與服務驅動程序

2.4.1 將PCI Express Port 總線驅動支持包含到內核中 

是否包含PCI Express端口總線驅動程序取決於內核配置中是否包含PCI Express支持。當在內核中啟用PCI Express支持時,內核將自動包含PCI Express Port Bus驅動作為內核驅動程序。

2.4.2 啟用service驅動支持

基於Linux設備驅動程序模型實現了PCI設備驅動程序。所有服務驅動程序都是PCI設備驅動程序。如上所述,一旦內核加載了PCI Express端口總線驅動程序,就不可能加載任何服務驅動程序。要滿足PCI Express端口總線驅動程序模型,需要對現有服務驅動程序進行一些最小的更改,而這些更改不會影響現有服務驅動程序的功能。

服務驅動程序需要使用下面所示的兩個api來將其服務注冊到PCI Express Port Bus驅動程序。重要的是,服務驅動程序在調用這些api之前初始化頭文件/include/linux/pcieport_if.h中包含的pcie_port_service_driver數據結構。如果不這樣做,將導致標識不匹配,從而阻止PCI Express Port Bus驅動程序加載服務驅動程序。

2.4.2.1 pcie_port_service_register

int pcie_port_service_register(struct pcie_port_service_driver *new)

這個API替換了Linux驅動模型的pci_register_driver API。服務驅動程序應該總是在模塊init上調用pcie_port_service_register。注意,在加載服務驅動程序之后,像pci_enable_device(dev)和pci_set_master(dev)這樣的調用就不再需要了,因為這些調用是由PCI Port Bus驅動程序執行的。

2.4.2.2 pcie_port_service_unregister

void pcie_port_service_unregister(struct pcie_port_service_driver *new)

pcie_port_service_unregister替換Linux驅動模型的pci_unregister_driver。它總是在模塊退出時被服務驅動程序調用。

2.4.2.3 Sample Code

下面是初始化port service driver數據結構的示例代碼。

static struct pcie_port_service_id service_id[] = { {
  .vendor
= PCI_ANY_ID,   .device = PCI_ANY_ID,   .port_type = PCIE_RC_PORT,
  .service_type
= PCIE_PORT_SERVICE_AER, }, { /* end: all zeroes */ } }; static struct pcie_port_service_driver root_aerdrv = { .name = (char *)device_name, .id_table = &service_id[0], .probe = aerdrv_load, .remove = aerdrv_unload, .suspend = aerdrv_suspend, .resume = aerdrv_resume, };

下面是注冊/注銷服務驅動程序的示例代碼。

static int __init aerdrv_service_init(void)
{
    int retval = 0;

    retval = pcie_port_service_register(&root_aerdrv);
    if (!retval) {
      /*
      * FIX ME
      */
    }
    return retval;
}

static void __exit aerdrv_service_exit(void)
{
    pcie_port_service_unregister(&root_aerdrv);
}

module_init(aerdrv_service_init);
module_exit(aerdrv_service_exit);

 

2.5 可能的資源沖突

由於PCI-PCI Bridge Port設備的所有服務驅動程序都允許同時運行,下面列出了一些與建議的解決方案可能發生的資源沖突。

2.5.1  MSI 和 MSI-X Vector Resource

一旦MSI或MSI- x中斷在設備上被啟用,它將保持在該模式,直到它們再次被禁用。由於相同PCI-PCI Bridge端口的服務驅動共享相同的物理設備,如果單個服務驅動啟用或禁用MSI/MSI- x模式,可能會導致不可預知的行為。

為了避免這種情況,所有的服務驅動程序都不允許在其設備上切換中斷模式。PCI Express Port Bus驅動程序負責確定中斷模式,這對服務驅動程序是透明的。服務驅動只需要知道分配給結構體pcie_device的字段IRQ的矢量IRQ,當PCI Express Port Bus驅動探測每個服務驅動時,傳入這個字段。服務驅動應該使用(struct pcie_device*)dev->irq來調用request_irq/free_irq。此外,中斷模式存儲在struct pcie_device的interrupt_mode字段中。

2.5.2 PCI Memory/IO 映射區域

PCI Express端口上用於訪問PCI配置空間的PME、AER、HP和VC服務驅動程序。在所有情況下,被訪問的寄存器都是相互獨立的。這個補丁假定所有的服務驅動程序都是良好的,並且不會覆蓋其他服務驅動程序的配置設置。

2.5.3 PCI配置寄存器

除了PCI Express結構外,每個服務驅動程序都在自己的這個補丁假定所有的服務驅動程序都是良好的,並且不會覆蓋其他服務驅動程序的配置設置。這個補丁假定所有的服務驅動程序都是良好的,並且不會覆蓋其他服務驅動程序的配置設置。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM