<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > Linux 2.6.10內(nèi)核下PCI Express Native熱插拔框架的實現(xiàn)機制

          Linux 2.6.10內(nèi)核下PCI Express Native熱插拔框架的實現(xiàn)機制

          作者: 時間:2008-07-22 來源:網(wǎng)絡(luò) 收藏
          熱插拔技術(shù),可以有效避免由更換外設(shè)引起的服務(wù)器系統(tǒng)停機,對于提高服務(wù)器系統(tǒng)可用性和可擴展性意義重大。本文討論了 熱插拔所涉及的軟件因素,并基于此,剖析了 插槽熱插拔子系統(tǒng)的關(guān)鍵

          一 相關(guān)技術(shù)與研究

          1997年,PCI SIG制定了第一個PCI熱插拔規(guī)范,其中定義了支持熱插拔所必需的平臺、板卡和軟件元素。PCI SIG推出了標(biāo)準(zhǔn)熱插拔控制器規(guī)范(SHPC SPEC),其中明確了熱插拔的標(biāo)準(zhǔn)使用模式和嚴(yán)格的寄存器組要求,并且允許操作系統(tǒng)提供商在平臺特定的軟件之外提供熱插拔支持,逐步完成了熱插拔標(biāo)準(zhǔn)制定工作,進(jìn)入技術(shù)的全面推廣階段。 2002年以后,Intel把熱插拔作為一種天然屬性賦予新推出的PCI 規(guī)范,PCI Express熱插拔總結(jié)了五年來工業(yè)標(biāo)準(zhǔn)的經(jīng)驗,具有如下特點:

          • 基于SHPC模式并對其進(jìn)行了功能擴展;
          • PCI Express從設(shè)計上就把熱插拔寄存器集成進(jìn)入了其標(biāo)準(zhǔn)的性能寄存器組(而在SHPC 1.0中,熱插拔寄存器是附加的);
          • 提供給操作系統(tǒng)一個統(tǒng)一的熱插拔硬件寄存器接口,賦予了操作系統(tǒng)進(jìn)行原生熱插拔(繞過了傳統(tǒng)基于BIOS的熱插拔方法)的能力;
          • 通過在基本的體系機構(gòu)層次定義熱插拔必須的硬件要求,完善了一種標(biāo)準(zhǔn)的使用模式;
          • 提供了規(guī)格參數(shù)來保證OEM產(chǎn)品的低成本而高平臺可靠性。

          具有完整功能的PCI Express熱插拔系統(tǒng)在平臺硬件和固件支持之外,還必須有操作系統(tǒng)以及設(shè)備驅(qū)動程序的支持。

          在各大芯片廠商紛紛推出支持PCI熱插拔的產(chǎn)品的同時,Microsoft,Novell,SCO等公司在他們相關(guān)的操作系統(tǒng)中也都包括了支持熱插拔的技術(shù), Novell NetWare 4.115和SCO UnixWare 7以及更新版本支持完整PCI熱插拔(熱替換和熱添加)。Microsoft Windows NT 4.0利用Compaq 服務(wù)器支持盤(SSD) for NT 4.0,提供了PCI熱替換支持,進(jìn)入2000年后,Microsoft Windows 2000也內(nèi)建了對PCI熱插拔技術(shù)的全面軟件支持。對于GNU/,從2001年1月份的2.4版本開始,PCI 熱插拔開始成為其標(biāo)準(zhǔn)特性之一,到2.6 版本,熱插拔功能已經(jīng)被整合進(jìn)入核心設(shè)備模型?,F(xiàn)在,幾乎所有的發(fā)行版本,包括RedHat, Debian和 United Linux,都對PCI 熱插拔提供了良好支持,并分別有所擴展。BSD分支在這方面起步較晚,OpenBSD在2004年三月份的3.6版本中才出現(xiàn)了不含設(shè)備驅(qū)動的設(shè)備熱插拔參考,而FreeBSD 到5.3版本為止,尚未提供對PCI 熱插拔的支持。

          作為2002年出現(xiàn)的規(guī)范,各個通用操作系統(tǒng)對PCI Express的支持才剛剛起步。在微軟公司的 Windows 2000, Windows XP, and Windows Server 2003中,PCI Express設(shè)備被當(dāng)作PCI設(shè)備進(jìn)行熱插拔,其他PCI Express的高級功能可以由固件激活。在Windows Longhorn中,才提供對PCI Express高級特性的原生支持。GNU/Linux在版本2.6.9中開始專門提供對于PCI Express 熱插拔的支持,中間歷經(jīng)軟件架構(gòu)的改動,逐漸發(fā)展為以內(nèi)核版本以及內(nèi)核版本2.6.12下兩種不同的PCI Express熱插拔驅(qū)動架構(gòu)。本文主要討論所采用的PCI Express熱插拔驅(qū)動架構(gòu),并在最后給出2.6.12的新特性。

          三 PCI Express 熱插拔的軟件支持

          根據(jù)規(guī)范,一個完整的 PCI Express 熱插拔系統(tǒng)需要幾方面的相互配合,分別為硬件元素、固件元素和軟件元素。硬件元素是指主板總線系統(tǒng)的電氣特性方面的支持,包括熱插拔控制器(Hot-Plug Controller)、卡槽電源切換邏輯(Card Slot Power Switching Logic)、板卡重置邏輯(Card Reset Logic)、電源指示燈(Power Indicator)、提示按鈕(Attention Button)和板卡存在檢測引腳(Card Present Detect Pins)等等;固件元素是指主板BIOS必須對熱插拔提供的支持,要 PCI Express熱插拔,固件必須提供OSHP方法或ACPI _OSC方法之一;軟件元素是指操作系統(tǒng)操綜合使用PCI Express 熱插拔所必須提供的功能組件。

          軟件元素

          為了操縱平臺的硬件元素,提供PCI Express熱插拔服務(wù),我們必須表1所示的主要熱插拔軟件元素。



          PCI Express服務(wù)模型

          PCIE熱插拔(PCIEHP)子系統(tǒng)中的標(biāo)準(zhǔn)熱插拔系統(tǒng)驅(qū)動程序通過檢查PCI Express性能數(shù)據(jù)結(jié)構(gòu)中的插槽性能寄存器(Slot Capabilities register),來獲取硬件的熱插拔部件信息。這些寄存器所能反映的信息如下:

          1. 插槽是否支持熱插拔
          2. 設(shè)備是否支持不通知軟件的突然拔出操作
          3. 提示燈、控制器等硬件元素是否存在

          一旦軟件完成了PCI Express設(shè)備熱插拔功能的開啟和配置工作,熱插拔行為(例如移出或插入請求,電源故障)就可以向系統(tǒng)熱插拔處理提交系統(tǒng)中斷和電源管理事件。這種熱插拔處理由操作系統(tǒng)獨立提供,圖1展示了PCI Express 熱插拔的服務(wù)模型,并展示了它與傳統(tǒng)的基于ACPI的模型之間的區(qū)別。


          圖1 PCI Express熱插拔服務(wù)模型比較
          圖1 PCI Express熱插拔服務(wù)模型比較

          四Linux 2.6.10 PCIE 熱插拔子系統(tǒng)代碼分析

          熱插拔

          為了提供PCI Express熱插拔服務(wù),Linux 2.6.10 PCIE熱插拔(PCIEHP)子系統(tǒng)必須實現(xiàn)用戶操作界面、熱插拔服務(wù)程序和標(biāo)準(zhǔn)熱插拔系統(tǒng)驅(qū)動等熱插拔軟件元素,并使軟件的行為符合熱插拔標(biāo)準(zhǔn)使用模式[4]。另外,一些特定的熱插拔功能必須與支持熱插拔的設(shè)備驅(qū)動結(jié)合在一起發(fā)揮作用。

          PCIEHP核內(nèi)部分的主體是一個核心線程,其控制邏輯以模塊的方式加載入內(nèi)核,負(fù)責(zé)監(jiān)控PCI Express總線上的熱插拔事件,并做相關(guān)處理;核外部分是一個用戶空間的腳本,從內(nèi)核中調(diào)用,并根據(jù)內(nèi)核傳回的信息執(zhí)行后續(xù)處理過程。

          1 熱插拔驅(qū)動程序生命周期

          從PCIEHP子系統(tǒng)啟動,到子系統(tǒng)被卸載期間,PCIEHP完全接管系統(tǒng)中PCI Express插槽熱插拔事件。

          PCIEHP子系統(tǒng)啟動時,首先要開啟用戶態(tài)守護(hù)進(jìn)程。然后初始化通知機制,開啟PCI Express熱插拔事件處理核心線程,為操作系統(tǒng)中各總線數(shù)據(jù)結(jié)構(gòu)分別預(yù)初始化一個熱插拔插槽列表。接著,根據(jù)內(nèi)核編譯時是否指定ACPI式資源管理,初始化設(shè)備資源管理方式。最后,根據(jù)設(shè)備標(biāo)識,在系統(tǒng)中注冊PCI Express熱插拔驅(qū)動程序,并將其綁定到總線上所有可能掛載熱插拔插槽的PCIE橋接設(shè)備,然后初始化對應(yīng)的熱插拔控制器,分配資源,開啟定時的中斷輪詢機制。

          卸載PCIEHP子系統(tǒng),首先釋放熱插拔控制器全局列表中每個控制器所占用的資源,釋放熱插拔插槽全局列表中每個插槽所占用的資源,終止通知機制的運行,結(jié)束PCI Express熱插拔事件處理核心線程;接著,根據(jù)內(nèi)核編譯時是否指定ACPI式資源管理,釋放相關(guān)設(shè)備占用的系統(tǒng)資源;然后,注銷PCI Express熱插拔驅(qū)動程序;在處理完當(dāng)前熱插拔事件后,終止核外守護(hù)進(jìn)程。

          在PCIEHP加載后,為了在熱插拔執(zhí)行過程中追蹤其狀態(tài)變化,我們把熱插拔插槽的狀態(tài)抽象如下:

          • 靜態(tài) (STATIC STATE ),
            正常工作或者空閑的時段,
          • 開啟前閃爍提示態(tài)(BLINKINGON STATE)
            發(fā)出開啟請求到確認(rèn)之前的時段
          • 關(guān)閉前閃爍提示態(tài) (BLINKINGOFF STATE)
            發(fā)出關(guān)閉請求到確認(rèn)之前的時段
          • 開啟態(tài) (POWERON STATE)
            執(zhí)行開啟操作的時段
          • 關(guān)閉態(tài)(POWEROFF STATE)
            執(zhí)行關(guān)閉操作的時段

          各個插槽狀態(tài)之間的轉(zhuǎn)換關(guān)系如圖2所示:


          圖2 插槽狀態(tài)轉(zhuǎn)換圖
          圖2 插槽狀態(tài)轉(zhuǎn)換圖

          2 用戶控制腳本/sbin/hotplug和核內(nèi)外通信機制

          在內(nèi)核熱插拔處理完畢后,它會在核內(nèi)調(diào)用一個用戶態(tài)腳本hotplug,這個腳本將根據(jù)內(nèi)核提供的信息進(jìn)行后續(xù)處理工作。它是設(shè)備熱插拔通告的用戶空間部分,它接收內(nèi)核傳出的熱插拔操作類型和環(huán)境變量,處理設(shè)備掛載和卸載操作。通常,hotplug會根據(jù)設(shè)備類型調(diào)用一個策略腳本,針對設(shè)備和系統(tǒng)當(dāng)前參數(shù)進(jìn)行后續(xù)的配置工作。例如,對于網(wǎng)卡,可能會調(diào)用腳本指定IP地址,網(wǎng)關(guān)和域名服務(wù)器等等,對于存儲設(shè)備,可能會調(diào)用mount命令來加載它到文件系統(tǒng)內(nèi)。

          內(nèi)核傳送給hotplug的信息包含熱插拔操作類型(例如PCI),并且在一個環(huán)境變量中提供本次操作相關(guān)信息:

          • 行為種類:添加或刪除
          • 對象設(shè)備所屬PCI 類、子類和編程接口
          • 對象制造商標(biāo)志和設(shè)備標(biāo)志
          • 對象總線地址、插槽地址和功能函數(shù)編號

          核外的后續(xù)配置工作涉及如下文件:

          /etc/hotplug/pci.rc/ect/hotplug/pci.Agent/etc/rc.d/init.d/hotplug

          在內(nèi)核中,由kernel/kmod.c中的函數(shù)

          int call_usermodehelper (char *path, char **argv, char **envp, int wait)來開啟用戶態(tài)腳本/sbin/hotplug。在參數(shù)表中,path表示了所啟動的核外應(yīng)用程序的路徑,argv是應(yīng)用程序的參數(shù)表,envp是環(huán)境變量列表,wait則指出了是否同步等待應(yīng)用程序執(zhí)行完畢再返回執(zhí)行結(jié)果的狀態(tài)。

          3 PCIE 熱插拔模塊構(gòu)成

          為了使用PCI Express Native Hotplug,我們必須在編譯的時候開啟對應(yīng)的功能模塊。

          在內(nèi)核配置中,PCIE Hotplug對應(yīng)的開關(guān)為HOTPLUG_PCI_PCIE,它依賴于HOTPLUG_PCI。如果你的主板支持PCI Express Native Hotplug,可以選擇Y;如果你只是想把這個驅(qū)動作為模塊來編譯,那么選擇M,此模塊叫做pciehp,在源代碼dirverpcihotplugKconfig文件中,你可以看到:

          config HOTPLUG_PCI_PCIEtristate "PCI Express Hotplug driver"depends on HOTPLUG_PCI

          完整的pciehp模塊功能涉及到如下幾個文件pci_hotplug_core.c, pciehp_core.c,pciehp_ctrl.c,pciehp_pci.c pciehp_hpc.c,另外根據(jù)是否開啟了ACPI,包含pciehprm_acpi.c 或者pciehprm_nonacpi.c,在源代碼dirverpcihotplugMakefile文件中,你可以看到:

          pci_hotplug-objs	:=	pci_hotplug_core.opciehp-objs		:=	pciehp_core.o	pciehp_ctrl.o	pciehp_pci.o	pciehp_hpc.oifdef CONFIG_ACPI_BUSpciehp-objs += pciehprm_acpi.oelsepciehp-objs += pciehprm_nonacpi.oendif

          代碼的主要任務(wù)就是在所有支持熱插拔的PCIE橋上加載熱插拔驅(qū)動程序,監(jiān)控?zé)岵灏问录?,并根?jù)類型,如是熱插入事件、熱拔出事件還是電源故障等分別予以處理。

          熱插拔驅(qū)動的加載

          熱插拔驅(qū)動程序的加載所進(jìn)行的主要工作是開啟并初始化PCIE熱插拔的內(nèi)核線程,這部分代碼位于/driver/pci/hotplug/pciehp_core.c中。入口函數(shù)為:

          static int __init pcied_init(void)

          #ifdef CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODEpciehp_poll_mode = 1;#endifretval = pcie_start_thread();if (retval)goto error_hpc_init;retval = pciehprm_init(PCI);if (!retval) {retval = pci_register_driver(pcie_driver);dbg("pci_register_driver = %d", retval);info(DRIVER_DESC " version: " DRIVER_VERSION "");}

          pcied_init中所涉及的關(guān)鍵函數(shù)分析如下:

          retval = pcie_start_thread();

          初始化并開啟通知機制:

          pciehp_event_start_thread()啟動事件監(jiān)控處理線程
          然后初始化slot列表,系統(tǒng)中每個bus給一個slot列表。
          struct pci_func *pciehp_slot_list[256]; 都設(shè)為NULL

          retval = pciehprm_init(PCI);

          原型:int pciehprm_init(enum php_ctlr_type ctlr_type)

          初始化資源(區(qū)別兩種情況:acpi和非acpi的)在非acpi的初始化方式下,調(diào)用空函數(shù)legacy_pciehprm_init_pci();在pcihprm_nonacpi.h中,定義了irq_info,irq_routing_table兩個結(jié)構(gòu)。在acpi初始化方式下,通過pciehprm_acpi_scan_pci()在acpi樹下遍歷搜尋PCI設(shè)備。不論acpi和非acpi的,都要求php_ctlr_type為PCI。

          retval = pci_register_driver(pcie_driver);

          注冊并初始化PCI橋熱插拔驅(qū)動程序模塊。

          把設(shè)備驅(qū)動加入已注冊設(shè)備驅(qū)動列表,即使在期間沒有相應(yīng)設(shè)備出現(xiàn)驅(qū)動程序仍然保持有效。

          	int count = 0;/* initialize common driver fields */

          用來泛化之,可以把drv->driver看作為drv的基類信息

          	drv->driver.name = drv->name;drv->driver.bus = pci_bus_type;drv->driver.probe = pci_device_probe;drv->driver.remove = pci_device_remove;drv->driver.kobj.ktype = pci_driver_kobj_type;pci_init_dynids(drv->dynids);count = driver_register(drv->driver);

          注意:這里是如何從基類drv->driver一般設(shè)備的驅(qū)動向子類drv這個pci設(shè)備的驅(qū)動逆向關(guān)聯(lián)的--使用CONTAINER宏

          pcie_driver為PCIE驅(qū)動程序?qū)ο螅x在 pciehp_core.c中

          	static struct pci_driver pcie_driver = {//驅(qū)動名稱定義為"pciehp".name=	PCIE_MODULE_NAME, // id_table指定探測函數(shù)probe所應(yīng)用的范圍,這里在表中指定為所有的PCI橋設(shè)備.id_table	=	pcied_pci_tbl, //probe為指定的設(shè)備探測函數(shù).probe	=	pcie_probe, };static struct pci_device_id pcied_pci_tbl[] = {{//此處選擇所有PCI橋.class =        ((PCI_CLASS_BRIDGE_PCI  8) | 0x00),.class_mask =	~0,.vendor =       PCI_ANY_ID,.device =       PCI_ANY_ID,.subvendor =    PCI_ANY_ID,.subdevice =    PCI_ANY_ID,},

          設(shè)備探測pcie_probe:

          static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *ent)in pcie-core.c

          已經(jīng)確定了pdev就是pcie_driver 所匹配的PCI橋設(shè)備,而且它在pcie_driver中所對應(yīng)的設(shè)備特征號是*ent,就可以對其進(jìn)行進(jìn)一步的初始化和探測。

          具體行為如下:

          • 綁定熱插拔插槽
          • 設(shè)置了控制器及其狀態(tài)
          • 注冊中斷處理函數(shù)
          • 讀寫配置頭,然后分配資源,最后對插槽檢測,掛接

          熱插拔事件的監(jiān)控處理線程

          熱插拔驅(qū)動程序?qū)τ跓岵灏问录妮喸兒屯ㄖ捎卯惒綑C制,對熱插拔功能部件的操縱是通過讀寫相關(guān)寄存器組進(jìn)行的。主要功能函數(shù)關(guān)系請參見圖3:


          圖3 插槽熱插拔事件處理函數(shù)關(guān)系
          圖3 插槽熱插拔事件處理函數(shù)關(guān)系

          圖3中主要函數(shù)的功能介紹如下:

          A插槽事件監(jiān)控線程

          作為熱插拔活動最直接的信息,插槽事件由硬件操作并置位相關(guān)寄存器組,系統(tǒng)軟件可以通過定時輪詢或者中斷方式獲取事件信息,執(zhí)行對應(yīng)的事件預(yù)處理函數(shù)。插槽事件如下:

          • 熱插拔命令到達(dá)
          • 插槽鎖狀態(tài)改變
          • 適配卡存在狀態(tài)改變
          • 電源出現(xiàn)故障

          php_ctlr->int_poll_timer.function = int_poll_timeout 其中php_ctlr是熱插拔控制器狀態(tài)php_ctlr_state_s類型,它定義于pciehp_hpc.h中,記錄當(dāng)前熱插拔控制器重要狀態(tài),被用作HPC(controller)的控制器句柄;熱插拔控制器controller位于文件pciehp.h中,描述了PCIE熱插拔控制器的特征;

          定時輪詢函數(shù)原型如下:

          static void int_poll_timeout(unsigned long lphp_ctlr)
          其中調(diào)用pcie_isr( 0, (void *)php_ctlr, NULL );
          當(dāng)最后一個參數(shù)是NULL時,采用polling機制。
          static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs);
          輪詢機制通過定期(2second,使用一個計時器)讀取ctrller對應(yīng)的狀態(tài)寄存器,來獲取事件,然后調(diào)用ctrl狀態(tài)參量對應(yīng)的事件處理函數(shù)。也就是按鈕、電源、MRL等等事件處理函數(shù),并分別調(diào)用event_semaphore來激活event_thread.

          B事件預(yù)處理函數(shù)

          在插槽事件監(jiān)控線程截獲插槽事件后,它根據(jù)事件類型調(diào)用這組處理函數(shù),執(zhí)行完畢后,填寫對應(yīng)控制器上所掛接的事件隊列,并激活睡眠等待的處理線程??梢约せ钏咧械奶幚砭€程的函數(shù)包括如下幾個:

          pciehp_handle_attention_button :處理按鈕事件
          pciehp_handle_switch_change:處理開關(guān)狀態(tài)改變事件
          pciehp_handle_presence_change:處理存在性狀態(tài)變化事件
          pciehp_handle_power_fault:處理電源故障事件
          pushbutton_helper_thread:按鈕動作處理線程

          C熱插拔事件處理核心線程event_thread

          event_thread的處理過程如下:
          在一個無限循環(huán)中,阻塞等待插槽事件發(fā)生
          當(dāng)線程被某一事件喚醒后,
          如果 熱插拔請求已通過延時確認(rèn)
          進(jìn)入熱插拔請求處理函數(shù)
          否則
          輪詢熱插拔控制器隊列:
          把控制器作為參數(shù)傳給插槽事件處理函數(shù)
          其中

          if (pushbutton_pending)pciehp_pushbutton_thread(pushbutton_pending);else if (surprise_rm_pending)pciehp_surprise_rm_thread(surprise_rm_pending);

          前一個處理按鈕事件,后一個處理突然拔出事件。

          參數(shù)pushbutton_pending是由如下函數(shù)提供的:

          static void pushbutton_helper_thread(unsigned long data){pushbutton_pending = data;up(event_semaphore);

          而這個函數(shù)又被作為定時task事件的行動部分,賦值給

          static void interrupt_event_handler(struct controller *ctrl)中的
          p_slot->task_event.function:
          函數(shù):
          p_slot->task_event.function
          = (void (*)(unsigned long)) pushbutton_helper_thread;
          參數(shù):
          p_slot->task_event.data
          = (unsigned long) p_slot;

          D插槽事件處理函數(shù)interrupt_event_handler

          根據(jù)控制器信息,獲取控制器對應(yīng)插槽事件
          尚有事件等待處理,則執(zhí)行以下內(nèi)容:

          逐一查看控制器所掛接事件隊列的每個成員(根據(jù)事件類型):

          1. 請求取消
          取消前五秒內(nèi)觸發(fā)的一次熱插拔請求

          2. 請求觸發(fā)
          觸發(fā)一次熱插拔操作:導(dǎo)致一個五秒鐘的延時,如果五秒內(nèi)請求沒有被拒絕,則確認(rèn)前一個熱插拔請求

          3. 電源故障
          彈出提示信息

          4. 其他
          讀取插槽的功能寄存器,更新狀態(tài)信息。

          E熱插拔請求處理函數(shù)pciehp_pushbutton_thread

          一個定期運行的程序,處理當(dāng)前插槽上阻塞的請求,根據(jù)請求類型:對插槽中的設(shè)備進(jìn)行熱移出(F)或者熱添加操作(G)。

          F插槽熱拔出設(shè)備pciehp_disable_slot

          保證所除去的不是視頻控制器
          卸載所除去的適配卡占用的系統(tǒng)資源,更新總線結(jié)構(gòu),關(guān)閉電源
          通知用戶態(tài)守護(hù)進(jìn)程
          更新插槽狀態(tài)

          G插槽熱添加設(shè)備pciehp_enable_slot

          1. 執(zhí)行適配卡添加的一系列相關(guān)操作: 失敗恢復(fù)預(yù)處理,存在性檢驗、打開電源,檢查link training狀態(tài),獲取設(shè)備基本信息,配置設(shè)備,為設(shè)備建立相關(guān)數(shù)據(jù)結(jié)構(gòu),掛接到上級總線等。

          2. 為新添加的設(shè)備查找并掛接驅(qū)動程序。

          3. 特別地,對于橋接設(shè)備,把它掛接到上級總線后,還要繼續(xù)對其下級總線進(jìn)行掃描和掛接。

          4. 通知用戶態(tài)守護(hù)進(jìn)程。

          5. 更新插槽狀態(tài)。

          五 PCIE板卡熱插拔的標(biāo)準(zhǔn)過程

          熱插拔PCI板卡可以使用提示按鈕或用戶界面來進(jìn)行,下面我們介紹使用用戶界面來啟動熱插入和熱拔出的操作過程,以及Fedora C4T2下所采用的方式。

          設(shè)備的熱插入

          1. 操作員安裝卡,閉合插槽保護(hù)鎖,保護(hù)鎖感應(yīng)器通知熱插拔控制器把連接信號接通到插槽。

          2. 然后,操作員通知熱插拔服務(wù)程序:卡已經(jīng)被安裝并可以激活。軟件提示用戶對此進(jìn)行確認(rèn)。

          3. 在操作員請求連接后,熱插拔服務(wù)程序向控制著熱插拔控制器的熱插拔系統(tǒng)驅(qū)動程序下達(dá)命令,閃爍插槽的電源指示燈,提示操作員此時不可以拔動適配卡。

          4. 在熱插拔軟件對此請求進(jìn)行確認(rèn)期間內(nèi),電源指示燈繼續(xù)閃爍。注意此時軟件可能會拒絕這個安裝請求(例如,安全策略此刻禁止插槽被激活)。另外,如果請求沒有生效,軟件拒絕請求并對熱插拔控制器發(fā)出命令關(guān)閉電源指示燈。規(guī)范建議軟件通過一條消息通知操作員請求被拒絕的原因。

          5. 如果請求被確認(rèn),熱插拔服務(wù)程序?qū)岵灏蜗到y(tǒng)驅(qū)動發(fā)出請求,為插槽加電。

          6. 加電后,軟件發(fā)出命令完全打開電源指示燈。

          7. 當(dāng)link training完成后,操作系統(tǒng)指示平臺配置程序賦予適配卡必需的資源,來配置適配卡的功能。

          8. 操作系統(tǒng)為PCI Express設(shè)備中的功能尋找恰當(dāng)?shù)尿?qū)動程序,并加載之。

          9. 接著系統(tǒng)調(diào)用驅(qū)動程序的初始化入口,并執(zhí)行驅(qū)動的初始化代碼。這些代碼完成設(shè)備的設(shè)置,并填寫設(shè)備的PCI 配置命令寄存器的相關(guān)標(biāo)志位來激活設(shè)備。

          熱移出設(shè)備

          1. 操作員通過指定適配卡所在物理插槽號碼來初始化移出請求。

          2. 軟件彈出窗口要求操作員確認(rèn)請求。注意,此時電源指示燈保持開啟狀態(tài)。

          3. 操作員確認(rèn)請求后,熱插拔服務(wù)程序向熱插拔系統(tǒng)驅(qū)動發(fā)出請求,要求熱插拔控制器閃爍電源指示燈。注意此時軟件可能會拒絕這個移出請求(例如,適配卡目前正被關(guān)鍵系統(tǒng)功能所使用)。另外,如果請求沒有被確認(rèn),軟件將拒絕請求并對熱插拔控制器發(fā)出命令,重新開啟電源指示燈。規(guī)范建議軟件通過一條消息通知操作員請求被拒絕的原因。

          4. 如果請求被確認(rèn),熱插拔服務(wù)程序?qū)⒚钸m配卡的設(shè)備驅(qū)動保持靜默,也就是說驅(qū)動一方面必須停止向適配卡發(fā)出請求,另一方面必須完成或者終止所有已經(jīng)發(fā)出的請求,并禁止適配卡產(chǎn)生新的事務(wù)(包括中斷)。

          5. 軟件發(fā)出命令,通過在插槽所連接的根端口或交換端口中的鏈接控制寄存器禁掉適配卡的鏈接。這使得鏈接兩側(cè)的端口均被禁止。

          6. 軟件指示熱插拔控制器禁掉插槽。

          7. 成功切斷電源后,軟件發(fā)出關(guān)閉電源指示燈命令。指示燈熄滅后,操作員可以開始安全地從插槽移出適配卡。打開插槽安全鎖,熱插拔控制器從插槽上撤除所有的信號(例如SMBus 和Vaux),此時卡可以被移出。

          8. 操作系統(tǒng)釋放內(nèi)存空間,I/O空間,中斷線等曾經(jīng)屬于該設(shè)備的系統(tǒng)資源。

          Fedora下所采用熱插拔實現(xiàn)的方式

          如果在最近一次編譯中選擇了PCI Express 熱插拔功能,而且驅(qū)動是以模塊方式存在,那么,可以在命令行下鍵入以下內(nèi)容:

          modprobe pciehp

          如果驅(qū)動成功,則可以在/sys/bus/pci/slots/下面發(fā)現(xiàn)以可熱插拔插槽編號命名的目錄,進(jìn)入相關(guān)目錄,可以進(jìn)行下一步操作。

          echo 1 >power開啟某個插槽上的電源 ,進(jìn)行熱插入

          echo 0 >power關(guān)閉某個插槽上的電源,執(zhí)行熱拔出

          若不能加載pciehp驅(qū)動,一般是由于硬件不支持或者固件缺少OSHP方法或ACPI _OSC方法之一。

          六 linux2.6.12中PCIE驅(qū)動模型的變化

          在linux2.6.10中,Linux驅(qū)動程序模型要求物理設(shè)備被單獨的驅(qū)動程序獨占訪問。 PCI Express端口是一個擁有許多獨立功能的PCI-PCI橋設(shè)備,作為一個簡潔的方案,每個功能要分別實現(xiàn)其自己的驅(qū)動程序,但是這樣造成了多個驅(qū)動程序在唯一的PCI-PCI橋設(shè)備中出現(xiàn)競爭的狀況。也就是說,雖然PCI Express提供了如Power Management (PME)、 Advanced Error Reporting (AER)、 Hot-Plug (HP) 和Virtual Channel (VC) access等多種功能,但是如果某個PCI Express端口的native hotplug 驅(qū)動程序加載后,它就會獨占這個PCI-PCI橋的端口,內(nèi)核就不能再于其上加載其他功能的驅(qū)動程序了。為解決這個問題,在Linux內(nèi)核版本2.6.12中,PCI Express的熱插拔又有所改變,提出了PCI Express 端口總線驅(qū)動程序(PCI Express Port Bus Driver)的概念。

          在實現(xiàn)上,PCI Express 端口總線驅(qū)動程序管理主板上的所有PCI Express 端口,并且把所有提供的服務(wù)請求發(fā)送到對應(yīng)的服務(wù)驅(qū)動程序上。其優(yōu)點概括如下:

          • 允許多個服務(wù)驅(qū)動程序在一個PCI-PCI橋端口設(shè)備上同步運行。
          • 允許各個服務(wù)驅(qū)動程序相互不受干擾地獨立實現(xiàn)。
          • 允許一個服務(wù)驅(qū)動程序在多個PCI-PCI橋端口設(shè)備上運行。
          • 管理PCI-PCI橋端口設(shè)備資源并分發(fā)它們到發(fā)出請求的服務(wù)驅(qū)動程序。

          例如,在注冊熱插拔驅(qū)動程序時,不再使用pci_register_driver直接向系統(tǒng)注冊,而是使用int pcie_port_service_register(struct pcie_port_service_driver *new) 向端口總線驅(qū)動程序注冊;在注銷熱插拔驅(qū)動程序時,不再使用pci_unregister_driver直接向系統(tǒng)注銷,而是使用void pcie_port_service_unregister(struct pcie_port_service_driver *new)來向端口總線驅(qū)動程序注銷;而端口總線驅(qū)動程序是直接注冊注銷到系統(tǒng)的。

          目前,PCI Express 端口總線驅(qū)動程序模型還在發(fā)展演變中。

          七 評估與總結(jié)

          根據(jù)可用性理論,系統(tǒng)的可用度可以使用下列公式來計算:



          在高負(fù)荷運轉(zhuǎn)的服務(wù)器上,商用可靠性的元件的故障更換并非小概率事件,對于更換故障元件和升級配件這樣的事件,沒有熱插拔支持的系統(tǒng)必須停機斷電進(jìn)行處理,而具備熱插拔支持的系統(tǒng)則僅僅需要很少的軟件切換和拔插時間開銷。從上面的公式我們可以看出,MTTR值越小,系統(tǒng)的可用性就越高。我們定義了一個比例因子V,V= MTTRnoHP/MTTRHP,根據(jù)業(yè)界經(jīng)驗,V的取值一般在10-100之間。描述可用性的一種常用的方法是使用"9"。如三個 9 表示 99.9% 的可用性,它表示一年大約有 8.5 小時的服務(wù)中斷期。四個 9 (99.99%) 是更高一級的可用性,表示一年大約有 1 小時的服務(wù)中斷期。根據(jù)可用度公式計算,在單個元件可靠度不變的情況下,Linux操作系統(tǒng)對PCI Express熱插拔的支持,可以使服務(wù)器系統(tǒng)的外設(shè)相關(guān)可用性躍升一個等級(1個9),同時,PCI Express熱插拔技術(shù)使得在線更換和升級PCI Express外設(shè)板卡成為可能,這使系統(tǒng)獲得了良好的可擴展性。

          綜上所述,本文討論了PCI Express熱插拔所涉及的軟件因素,分析了linux2.6.10的PCI Express插槽熱插拔功能PCIEHP子系統(tǒng),并對熱插拔支持在提高服務(wù)器系統(tǒng)外設(shè)相關(guān)可用性的作用進(jìn)行了定量的分析。為了繼續(xù)提高操作系統(tǒng)可用性和可擴展性支持能力,Linux PCI Express hotplug以下方面還有待發(fā)展:繼續(xù)完善熱插拔架構(gòu)的開放性,以提供完整統(tǒng)一的接口供驅(qū)動開發(fā)人員編寫其他設(shè)備的熱插拔支持模塊;在插槽熱插拔之外,提供對Server IO Module(SIOM)熱插拔的支持;完善熱替換和熱升級技術(shù)。這些問題都是非常具有挑戰(zhàn)性的。

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

          linux相關(guān)文章:linux教程




          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();