欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報激活碼778899分享:網(wǎng)絡(luò) 網(wǎng)卡驅(qū)動架構(gòu)以及源碼分析

柚子快報激活碼778899分享:網(wǎng)絡(luò) 網(wǎng)卡驅(qū)動架構(gòu)以及源碼分析

http://yzkb.51969.com/

由于工作很忙,一直沒有時間靜下心來好好整理文檔。文檔的功夫不僅反映了一個人對相關(guān)知識的掌握,也可以發(fā)現(xiàn)不足之處,從而提高自己,增加自己的內(nèi)功。希望從這篇開始,日積月累,成為一個優(yōu)秀的程序員。

本文的stmmac驅(qū)動以linux內(nèi)核5.15為參考。

stmmac驅(qū)動用于支持?synopsys ip的系列網(wǎng)卡芯片,包括xgmac,以及gmac。xgmac對應(yīng)的是10G網(wǎng)卡芯片,gmac對應(yīng)的則是千兆網(wǎng)卡芯片。我將從三個方面進行網(wǎng)卡驅(qū)動的分析,分別是網(wǎng)卡驅(qū)動架構(gòu),link方式,以及收發(fā)包流程。

1.網(wǎng)卡驅(qū)動架構(gòu)

xgmac 網(wǎng)卡主要有兩種應(yīng)用場景,分別是Local xgmac和PCIe xgmac 應(yīng)用場景。Local xgmac方式下,cpu通過內(nèi)部高速總線訪問xgmac,而PCIe xgmac則通過PCIe總線與host主機相連。stmmac目錄中,dwmac-intel-plat對應(yīng)著Local xgmac方式,而dwmac-intel.c,stmmac_pci.c則對應(yīng)這PCIe xgmac的方式。stmmac_main.c包括對xgamc硬件進行操作,調(diào)用dwxgmac_core.c,dwxgamc_desc.c,dwxgmac_dma.c,以及提供各種網(wǎng)卡接口feature,包括mmc軟硬件計數(shù),ethtool,ptp,以及xdp等。

本文主要以PCIe方式即以stmmac_pci.c進行說明。

static struct pci_driver stmmac_pci_driver = {

.name = STMMAC_RESOURCE_NAME,

.id_table = stmmac_id_table,

.probe = stmmac_pci_probe,

.remove = stmmac_pci_remove,

.driver = {

.pm = &stmmac_pm_ops,

},

};

利用stmmac_id_table的device_id以及vendor_id進行driver和devcie的匹配,匹配成功后調(diào)用stmmac_pci_probe函數(shù)。stmmac_pci_probe函數(shù)流程為

1.分配plat、plat->mdio_bus_data、plat->dma_cfg結(jié)構(gòu)體,plat結(jié)構(gòu)體提供硬件以及ndev的一些基本參數(shù),mdio_bus_data主要與mdio相關(guān),dma_cfg配置xgmac dma 通路,比如rxpbl,txpbl等等。

plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);

plat->mdio_bus_data = devm_kzalloc(&pdev->dev,sizeof(*plat->mdio_bus_data), GFP_KERNEL);

plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg),GFP_KERNEL);

plat->safety_feat_cfg = devm_kzalloc(&pdev->dev,sizeof(*plat->safety_feat_cfg),GFP_KERNEL);

2.由于PCIe xgmac下,網(wǎng)卡是一個PCIe設(shè)備,既然是PCIe設(shè)備,則必須對網(wǎng)卡的bar空間進行初始化。包括使能pci設(shè)備,獲取網(wǎng)卡設(shè)備的bar空間機制,并對bar空間進行映射。

pcim_enable_device(pdev);

for(i=0; i<6; i++)

ret = pcim_iomap_regions(pdev, BIT(i), pci_name(pdev));

pci_set_master(pdev);

3.賦值一些必要信息,中斷初始化(msi或者msix),處理完畢后進入stmmac_dvr_probe函數(shù)。

4.進入stmmac_dvr_probe函數(shù)后,就是申請網(wǎng)卡設(shè)備net_device和私有數(shù)據(jù)stmmac_priv,網(wǎng)卡設(shè)備和私有數(shù)據(jù)緊緊挨在一起:網(wǎng)卡設(shè)備+私有數(shù)據(jù)結(jié)構(gòu),通過netdev_pri獲取私有數(shù)據(jù)結(jié)構(gòu)。

5.dwxgmac2_core.c,dwxgmac2_dma.c,dwxgmac2_desc.c實現(xiàn)了xgmac 的操作接口,那么如何將xgmac的操作接口與netdev或者priv強綁定呢,stmmac的做法是根據(jù)網(wǎng)卡芯片的型號(xgmac以及gmac芯片的型號都不一樣),去綁定不同的操作接口的回調(diào)函數(shù)。hwif.c中的stmmac_hw數(shù)組來進行注冊管理。

// dwxgmac210_ops mac相關(guān)操作接口注冊如下

const struct stmmac_ops dwxgmac210_ops = {

.core_init = dwxgmac2_core_init,

.set_mac = dwxgmac2_set_mac,

.rx_ipc = dwxgmac2_rx_ipc,

.rx_queue_enable = dwxgmac2_rx_queue_enable,

.rx_queue_prio = dwxgmac2_rx_queue_prio,

.tx_queue_prio = dwxgmac2_tx_queue_prio,

......

}

// dwxgmac210_ops dma 相關(guān)操作接口注冊如下

const struct stmmac_dma_ops dwxgmac210_dma_ops = {

.start_tx = dwxgmac2_dma_start_tx,

.stop_tx = dwxgmac2_dma_stop_tx,

.start_rx = dwxgmac2_dma_start_rx,

.stop_rx = dwxgmac2_dma_stop_rx,

......

}

const struct stmmac_desc_ops ndesc_ops = {

.tx_status = ndesc_get_tx_status,

.rx_status = ndesc_get_rx_status,

.get_tx_len = ndesc_get_tx_len,

.init_rx_desc = ndesc_init_rx_desc,

.init_tx_desc = ndesc_init_tx_desc,

.get_tx_owner = ndesc_get_tx_owner,

......

}

static const struct stmmac_hwif_entry {

bool gmac;

bool gmac4;

bool xgmac;

......

const void *desc;

const void *dma;

const void *mac;

const void *hwtimestamp;

const void *mode;

const void *tc;

const void *mmc;

int (*setup)(struct stmmac_priv *priv);

int (*quirks)(struct stmmac_priv *priv);

} stmmac_hw[] = {

{

.gmac = false,

.gmac4 = false,

.xgmac = true,

......

.desc = &dwxgmac210_desc_ops,

.dma = &dwxgmac210_dma_ops,

.mac = &dwxgmac210_ops,

.hwtimestamp = &stmmac_ptp,

.mode = NULL,

.tc = &dwmac510_tc_ops,

.mmc = &dwxgmac_mmc_ops,

.setup = dwxgmac2_setup,

.quirks = NULL,

},

..... // .gmac = true,

}

6.stmmac_dvr_probe函數(shù)主要作用是申請netdev結(jié)構(gòu)體和priv結(jié)構(gòu)體,并對結(jié)構(gòu)體進行賦值,包括將各個接口的回調(diào)函數(shù)賦給priv結(jié)構(gòu)體。而stmmac_open 函數(shù)則對應(yīng)著上層的命令(ifconfig eth up),通過調(diào)用stmmac_open函數(shù),網(wǎng)卡真正能工作起來,即可以開始收發(fā)包。

stmmac_open

|--- stmmac_hw_setup(dev, true)

|---stmmac_init_dma_engine(priv) /* DMA initialization and SW reset */

|---stmmac_core_init(priv, priv->hw, dev) /* Initialize the MAC Core */

|---stmmac_mtl_configuration(priv) /* Initialize MTL*/

|---stmmac_mac_set(priv, priv->ioaddr, true) /* Enable the MAC Rx/Tx */

|---stmmac_set_rings_length(priv) /* set TX and RX rings length */

|---stmmac_start_all_dma(priv) /* Start the ball rolling... */

|---stmmac_start_rx_dma(priv, chan)

|---stmmac_start_rx(priv, priv->ioaddr, chan)

|---stmmac_start_tx_dma(priv, chan)

|---stmmac_start_tx(priv, priv->ioaddr, chan)

|---stmmac_do_void_callback(__priv, dma, start_tx, __args)

//#define stmmac_do_void_callback(__priv, __module, __cname, __arg0, __args...)

// (__priv)->hw->__module->__cname((__arg0), ##__args);

|--- __priv->hw->dam->start_tx((__arg0), ##__args);

|---dwxgmac2_dma_start_tx

2.link架構(gòu)

stmmac支持兩種形式的phy,一種是外置phy,phy單獨存在,通過mdio總線與xgmac相連,另一種是內(nèi)置phy,即pcs。xpcs作為xgmac的一部分,訪問時不再需要通過mdio訪問,而是將xpcs相關(guān)寄存器映射到一段bar空間上,直接通過讀寫寄存器的方式訪問。在5.15內(nèi)核,stmmac驅(qū)動的link架構(gòu)依賴于phylink模塊。phylink層是一個軟件層面的中間層,它沒有對應(yīng)的硬件,主要功能是連接phy_device和mac層以及phy層的狀態(tài)。

對于外置phy的方式,phylink工作方式如下:

當phy_device的狀態(tài)改變時,mac層能及時作出改變。phy_device層和phylink層均采用了定時器輪詢的方式,phy_device層通過phy_state_machine()函數(shù)獲取phy的狀態(tài),當狀態(tài)改變時,將信息通過phylink_phy_change()函數(shù)傳遞給phylink.phylink層也采用了輪詢的方式,利用phylink_resolve()函數(shù)將信息傳給mac層。

對于內(nèi)置phy即xpcs的方式,phylink的工作方式如下:

phylink層維護了1s鐘輪詢一次的定時器,通過該定時器,會定期去查看xpcs的link狀態(tài),如果xpcs是linkup的,則會配置xgmac的mac層,使其linkup。

phylink_resolve函數(shù)的核心邏輯如下

static void phylink_resolve(struct work_struct *w)

{

...

bool mac_config = false;

bool retrigger = false;

bool cur_link_state;

if (pl->netdev) //得到當前的link狀態(tài)

cur_link_state = netif_carrier_ok(ndev);

else

cur_link_state = pl->old_link_state;

if (pl->phylink_disable_state) { //判斷當前狀態(tài)phylink_disable_state和mac_link_dropped狀態(tài)

pl->mac_link_dropped = false;

link_state.link = false;

} else if (pl->mac_link_dropped) {

link_state.link = false;

retrigger = true;

} else { //其他情況

switch (pl->cur_link_an_mode) {

...

case MLO_AN_INBAND:

/*獲取當前的link_state*/

phylink_mac_pcs_get_state(pl, &link_state);

if (!link_state.link) {

if (cur_link_state)

retrigger = true;

else

phylink_mac_pcs_get_state(pl,&link_state);

}

phylink_apply_manual_flow(pl, &link_state);

break;

}

}

...

/*這里我的理解是如果link_state的link不等于當前狀態(tài)的link,

那么如果link=0,實際是link的,所以需要link up;

如果link=1,那么實際是沒link,所以需要link down.如果兩者都為0和1就不需要動作了*/

if (link_state.link != cur_link_state) {

pl->old_link_state = link_state.link;

if (!link_state.link)

phylink_link_down(pl);

else

phylink_link_up(pl, link_state);

}

if (!link_state.link && retrigger) { //如果link為0,并且需要馬上retrigger,那么就重新調(diào)度resolve函數(shù)

pl->mac_link_dropped = false;

queue_work(system_power_efficient_wq, &pl->resolve);

}

mutex_unlock(&pl->state_mutex);

}

對于外置phy,其與xgmac通信的總線為mdio。這里主要說明以下mdio總線的注冊流程。要用到mdio讀寫寄存器的方式對phy進行配置,一般讀寫方式有兩種,分別是c45和c22.

對于xpcs的方式,主要需要獲取xpcs的型號從而執(zhí)行不同的硬件操作函數(shù)。

pcs是物理編碼子層,位于協(xié)調(diào)子層(通過GMII)和物理介入接入層(PMA)子層之間。pcs子層完成將經(jīng)過完善定義的以太網(wǎng)MAC功能映射到現(xiàn)存的編碼和物理層信號系統(tǒng)的功能上去、pcs子層和上層MAC的接口由MII提供,與下層PMA接口使用PMA服務(wù)接口。而XPCS顧名思義,則是支持更高速率的pcs層。

不同廠家的xpcs不大相同,以stmmac源碼為參考,pcs_xpcs的初始化位置位于stmmac_main.c的stmmac_dvr_probe函數(shù)下的stmmac_xpcs_setup函數(shù)中,該函數(shù)流程為利用從0到32的phy地址進行循環(huán)遍歷的方式進行mdio設(shè)備以及xpcs的創(chuàng)建,如果phy地址不正確,那么xpcs則無法正確創(chuàng)建。若xpcs成功創(chuàng)建,將xpcs_create函數(shù)返回的xpcs結(jié)構(gòu)體給priv->hw->xpcs。

for (addr = 0; addr < PHY_MAX_ADDR; addr++) {

mdiodev = mdio_device_create(bus, addr);

if (IS_ERR(mdiodev))

continue;

xpcs = xpcs_create(mdiodev, mode);

if (IS_ERR_OR_NULL(xpcs)) {

mdio_device_free(mdiodev);

continue;

}

priv->hw->xpcs = xpcs;

break;}

與前面xgmac的硬件操作函數(shù)一致,xpcs也需要根據(jù)不同的型號來執(zhí)行不同操作函數(shù)。

//關(guān)鍵結(jié)構(gòu)體數(shù)組

xpc_id_list[] = {

{

.id = SYNOPSYS_XPCS_ID,

.mask = SYNOPSYS_XPCS_MASK,

.compat = synopsys_xpcs_compat,

}, {

.id = NXP_SJA1105_XPCS_ID,

.mask = SYNOPSYS_XPCS_MASK,

.compat = nxp_sja1105_xpcs_compat,

}, {

.id = NXP_SJA1110_XPCS_ID,

.mask = SYNOPSYS_XPCS_MASK,

.compat = nxp_sja1110_xpcs_compat,

},

};

//賦值后的xpcs結(jié)構(gòu)體

struct dw_xpcs {

struct mdio_device *mdiodev;

const struct xpcs_id *id;

struct phylink_pcs pcs;

}xpcs;

xpcs.mdiodev=mdiodev;

xpcs->id=&xpcs_id_list[i]; //根據(jù)id匹配得到

xpcs->pcs.ops =&xpcs_phylink_ops;

xpcs->pcs.poll = true;

3.收發(fā)包流程

Stmmac 以太網(wǎng)收發(fā)包驅(qū)動,核心是兩個函數(shù),一個是 stmmac_xmit, 用于將協(xié)議棧發(fā)送的數(shù)據(jù)包映射出DMA地址給硬讀?。?另一個是 stmmac_rx,用于將硬件寫入內(nèi)存的數(shù)據(jù),組織成 skb 并傳遞給協(xié)議層。

TX方向的流程如上圖所示:

網(wǎng)絡(luò)設(shè)備層_qdisc_run 函數(shù)調(diào)用 驅(qū)動注冊的 stmmac_xmit 函數(shù)進行發(fā)送數(shù)據(jù)包 Stmmac_xmit 對skb->data進行dma_map_single流式映射,獲取dma物理地址,供網(wǎng)卡芯片 DMA 獲取數(shù)據(jù)報文 stammac_xmit 將 skb映射后的dma 物理地址 更新到 TX Ring 的描述符中,然后更新描述符隊列的 cur_tx stammac_xmit 將當前生產(chǎn)的數(shù)據(jù)包位置 寫入 XGMAC 的doorbell寄存器,同時flush 描述符,并開啟軟件定時器,進行tx方向的中斷聚合 硬件DMA 讀取數(shù)據(jù)報文,傳遞給 MAC 層之后,根據(jù)描述符的IC值判斷是否發(fā)送硬中斷給CPU CPU 執(zhí)行硬中斷處理函數(shù) stmmac_msi_intr_tx 硬中斷處理函數(shù) 調(diào)用 napi_schedule(tx_napi) Linux 內(nèi)核對應(yīng)當前CPU 核心的軟中斷線程 Ksoftirqd/N 通過net_rx_action, 調(diào)用驅(qū)動注冊軟中斷處理函數(shù)stmmac_napi_poll_tx Poll tx 調(diào)用 stmmac_tx_clean 清理 tx 描述符,tx skb buffer,tx dma mpping 等

RX方向的流程如上圖所示:

網(wǎng)卡收到數(shù)據(jù)后,產(chǎn)生rx中斷,并發(fā)送給CPU; CPU執(zhí)行硬中斷處理函數(shù)stmmac_msi_intr_rx 硬中斷處理函數(shù)調(diào)用napi_schedule(rx_napi) 執(zhí)行netif_napi_add中綁定的stmmac_napi_poll_rx函數(shù) 進入驅(qū)動層的stmmac_rx; 調(diào)用dma_sync_single_for_cpu,確保在讀取rx buffer數(shù)據(jù)之前,dma操作已經(jīng)完成,申請skb,將rx buffer的數(shù)據(jù)copy到skb中,并更新描述符 cur_rx。 將skb通過napi_gro_receive 上送到協(xié)議棧。

柚子快報激活碼778899分享:網(wǎng)絡(luò) 網(wǎng)卡驅(qū)動架構(gòu)以及源碼分析

http://yzkb.51969.com/

推薦文章

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19490829.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機訪問

文章目錄