Realtek 8126驅動分析第四篇——multi queue相關

Realtek 8126是 5G 網卡,因為和 8125 較為接近,第四篇從這里開始也無不可。本篇主要是講 multi queue 相關,其他的一些內容在之前就已經提過,不加贅述。

1 初始化

1.1?rtl8126_init_one

從第一篇我們可以知道每個 PCI 驅動都注冊了一個 probe() 方法,為設備尋找驅動就是調用其 probe() 方法,即?rtl8126_init_one。這里我們重點講 multi queue 相關的內容。

1.1.1 rtl8126_init_board

/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev_mq(sizeof (*tp), R8126_MAX_QUEUES);

分配并設置以太網設備,這里的?R8126_MAX_QUEUES 指 TX 和 RX 都有這么多個 queue。

1.1.2?rtl8126_try_msi

該函數里主要是先確定了支援的 irq vector number,最關鍵的是?rtl8126_enable_msix 函數。這樣內核就根據硬件能力分配了實際的 vector 即中斷號。

static int rtl8126_enable_msix(struct rtl8126_private *tp)
{int i, nvecs = 0;struct msix_entry msix_ent[R8126_MAX_MSIX_VEC];/** 這里的entry表示設備支持的MSI-X表項索引(即設備硬件層面的中斷條目編號)。* 例如,設備支持16個MSI-X中斷,entry可以是0-15* 而vector表示系統范圍內唯一的中斷向量號(Interrupt Vector Number)。* 該向量號是CPU中斷描述符表(IDT)的索引,用于在硬件觸發中斷時,CPU查找對應的中斷處理函數*/for (i = 0; i < R8126_MAX_MSIX_VEC; i++) {msix_ent[i].entry = i;msix_ent[i].vector = 0;}/* 調用pci_enable_msix_range(),內核根據硬件能力和系統資源分配實際的vector,* 并回填到msix_entry.vector*/nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent,tp->min_irq_nvecs, tp->max_irq_nvecs);if (nvecs < 0)goto out;for (i = 0; i < nvecs; i++) {struct r8126_irq *irq = &tp->irq_tbl[i];irq->vector = msix_ent[i].vector;}out:return nvecs;
}

1.1.3?rtl8126_init_software_variable

這個函數主要是初始化一些變量,諸如 HwSuppNumTxQueues 和?HwSuppNumRxQueues。

這里要注意以下代碼,這里調用內核限制設置了 rss queue 的數量上限。

/* 此例程應設置多隊列設備默認使用的 RSS 隊列數量的上限。*/
u8 rss_queue_num = netif_get_num_default_rss_queues();
tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)?rss_queue_num : tp->HwSuppNumRxQueues;

然后根據之前設置的變量的值,在?rtl8126_setup_mqs_reg 函數中,設置不同的 ring 對應的硬件寄存器的值,這里比較重要的就是如果支援 multi queue,那么每個 queue 對應的 descriptor start address 都要設置。另外對于 RX 還要額外設置 ISR 和 IMR。

在函數?rtl8126_set_ring_size 中,設置每個 ring 的 ring size 即 descriptor number。

最關鍵的就是函數rtl8126_init_rss。

void rtl8126_init_rss(struct rtl8126_private *tp)
{int i;/* 0~HwSuppIndirTblEntries對queue numbers取余,得到hash indirection table*/for (i = 0; i < rtl8126_rss_indir_tbl_entries(tp); i++)tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings);/* 該函數依賴內核的強隨機數生成器,生成 RSS 哈希密鑰*/netdev_rss_key_fill(tp->rss_key, RTL8126_RSS_KEY_SIZE);
}

1.1.4?rtl8126_init_napi

這個函數主要是為每一個 irq vector 注冊napi的poll方法。在中斷線程被觸發后,內核會執行中斷處理函數 ISR,進而進入軟中斷收包環節。而進入軟中斷,就會調用到這里注冊的 poll 函數。

1.1.5?rtl8126_set_real_num_queue

通過合理設置實際隊列數,可最大化利用多核CPU和硬件加速特性(如RSS),同時避免因配置不當導致的性能瓶頸或穩定性問題。

1.2?rtl8126_open

ndo_open 在 8126 驅動中就是 rtl8126_open,當網絡設備轉換為啟動狀態時,將調用此函數。

1.2.1 alloc desc

這兩個函數初始化DMA描述符環形緩沖區,用于網卡收發包。

1.2.2?rtl8126_init_ring

int
rtl8126_init_ring(struct net_device *dev)
{struct rtl8126_private *tp = netdev_priv(dev);int i;/* 初始化ring的一些變量 */rtl8126_init_ring_indexes(tp);/* 初始化trx desc ring,并為tx ring設置 end of ring */rtl8126_tx_desc_init(tp);rtl8126_rx_desc_init(tp);for (i = 0; i < tp->num_tx_rings; i++) {struct rtl8126_tx_ring *ring = &tp->tx_ring[i];memset(ring->tx_skb, 0x0, sizeof(ring->tx_skb));}for (i = 0; i < tp->num_rx_rings; i++) {struct rtl8126_rx_ring *ring = &tp->rx_ring[i];
#ifdef ENABLE_PAGE_REUSEring->rx_offset = R8126_RX_ALIGN;
#elsememset(ring->Rx_skbuff, 0x0, sizeof(ring->Rx_skbuff));
#endif //ENABLE_PAGE_REUSEif (rtl8126_rx_fill(tp, ring, dev, 0, ring->num_rx_desc, 0) != ring->num_rx_desc)goto err_out;rtl8126_mark_as_last_descriptor(tp, rtl8126_get_rxdesc(tp, ring->RxDescArray, ring->num_rx_desc - 1));}return 0;err_out:rtl8126_rx_clear(tp);return -ENOMEM;
}

1.2.3?rtl8126_alloc_irq

該函數主要是為每個 irq 設置 中斷處理函數 iSR rtl8126_interrupt_msix,并利用 request_irq 注冊中斷。

1.2.4?rtl8126_hw_config

void rtl8126_config_rss(struct rtl8126_private *tp)
{if (!tp->EnableRss) {rtl8126_disable_rss(tp);return;}_rtl8126_config_rss(tp);
}

著重就是講這個函數。

void _rtl8126_config_rss(struct rtl8126_private *tp)
{/* 設置寄存器?RSS_CTRL_8125 的值 */_rtl8126_set_rss_hash_opt(tp);/* 把之前得到的 redirection table 寫進寄存器里 */rtl8126_store_reta(tp);/* 將之前內核生成的 rss key 寫進寄存器里 */rtl8126_store_rss_key(tp);
}

rtl8126_set_rx_q_num 和?rtl8126_set_tx_q_num 要向寄存器里寫入 TRX queue 的數目。

到此為止,關于 multi queue 的所有初始化就已經完成了。

2 收發包

2.1 收包

如果有數據包過來,并且觸發了硬件中斷,那么就會調用?rtl8126_interrupt_msix 函數,首先判斷是否是 link change,這顯然不是,然后就會 disable hw interrupt,隨后要轉入軟中斷。

進而就會調用對應的 poll 函數,這里我們不去區分 mapping 方式,最終 RX 都會調用到函數?rtl8126_rx_interrupt。這里其他的我們不用去管,只要看一個函數?rtl8126_rx_hash。

以?rtl8126_rx_hash_v3 為例,關于 hash 的信息保存在 descriptor 中,提取出 hash 值后,賦給 skb->hash,至此工作完成。

2.2 發包

發包的部分更為簡單,發包函數?rtl8126_start_xmit 會通過?skb_get_queue_mapping 來選擇用哪個 queue,得出?queue_mapping 用作 queue number 即可。這里的 skb->queue_mapping 是上層計算出的結果。

到此為止,主要的 multi queue 相關的就已經完成了,但是在 linux driver 中,還有通過 ethtool 來修改 rss 相關的 code 需要介紹。

3 ethtool

.get_rxnfc =>?rtl8126_get_rxnfc 該函數用于返回 rx ring number 以及 返回 rss hash option。

.set_rxnfc >= rtl8126_set_rxnfc 該函數用于設置 rss hash option,這里要注意,UDP RSS 是需要通過這個函數來開啟的,default 不支持。

.get_rxfh_indir_size >= rtl8126_rss_indir_size 該函數用于返回?indirection table 的 size。

.get_rxfh_key_size >= rtl8126_get_rxfh_key_size 該函數返回 rss_key 的 size。

.get_rxfh >= rtl8126_get_rxfh 該函數用于獲得 indirection table 和 rss_key。

.set_rxfh >= rtl8126_set_rxfh 該函數用于將 ethtool 給的 indirection table 和 rss_key 寫入寄存器,采用它們。

如果覺得這篇文章有用的話,可以點贊、評論或者收藏,萬分感謝,goodbye~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82893.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82893.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82893.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用PHP對接日本股票市場數據

本文將介紹如何通過StockTV提供的API接口&#xff0c;使用PHP語言來獲取并處理日本股票市場的數據。我們將以查詢公司信息、查看漲跌排行榜和實時接收數據為例&#xff0c;展示具體的操作流程。 準備工作 首先&#xff0c;請確保您已經從StockTV獲得了API密鑰&#xff0c;并且…

爬蟲工具與編程語言選擇指南

有人問爬蟲如何選擇工具和編程語言。根據我多年的經驗來說&#xff0c;是我肯定得先分析不同場景下適合的工具和語言。 如果大家不知道其他語言&#xff0c;比如JavaScript&#xff08;Node.js&#xff09;或者Go&#xff0c;這些在特定情況下可能更合適。比如&#xff0c;如果…

C語言while循環的用法(非常詳細,附帶實例)

while 是 C 語言中的一種循環控制結構&#xff0c;用于在特定條件為真時重復執行一段代碼。 while 循環的語法如下&#xff1a; while (條件表達式) { // 循環體&#xff1a;條件為真時執行的代碼 } 條件表達式&#xff1a;返回真&#xff08;非 0&#xff09;或假&#x…

1.短信登錄

1.0 問題記錄 1.0.1 redis 重復 token 問題 每次用戶登錄時&#xff0c;后端會創建一個新的 token 并存入 Redis&#xff0c;但之前登錄的 token 還沒有過期。這可能會導致以下問題&#xff1a; 1. Redis 中存在大量未過期但實際已不使用的 token2. 同一用戶可能有多個有效 …

需求與技術實現不匹配,如何協調

協調需求與技術實現不匹配問題&#xff0c;需要加強技術參與需求階段、推動架構與需求同步設計、建立跨職能溝通機制&#xff0c;其中加強技術參與需求階段是最關鍵的一步。 需求如果脫離技術實際&#xff0c;就容易導致實現困難、資源浪費甚至項目失敗。根據麥肯錫的一項研究&…

java每日精進 5.11【WebSocket】

1.純Websocket實現消息發送 1.1一對一發送 前端 用戶在輸入框輸入消息內容(sendText) 選擇特定接收用戶(sendUserId) 點擊發送按鈕觸發handlerSend方法 構造消息內容JSON: {text: "Hello", // 消息內容toUserId: 123 // 目標用戶ID } 包裝為WebSocket標準格式…

【NextPilot日志移植】params.c解析

params.c 參數說明 params.c 文件的主要作用是定義與 SD卡日志記錄 相關的參數。這些參數用于配置日志記錄的行為&#xff0c;包括日志記錄的時間、內容、存儲管理以及加密設置等。 1. UTC 偏移量 (SDLOG_UTC_OFFSET) PARAM_DEFINE_INT32(SDLOG_UTC_OFFSET, 0);用途&#xf…

jFinal 使用 SolonMCP 開發 MCP(擁抱新潮流)

MCP 官方的 java-sdk 目前只支持 java17。直接基于 mcp-java-sdk 也比較復雜。使用 SolonMCP&#xff0c;可以基于 java8 開發&#xff08;像 MVC 的開發風格&#xff09;&#xff0c;且比較簡單。 1、SolonMCP 簡介 SolonMCP&#xff08;全稱&#xff1a;solon-ai-mcp&#…

“端 - 邊 - 云”三級智能協同平臺的理論建構與技術實現

摘要 隨著低空經濟與智能制造的深度融合&#xff0c;傳統集中式云計算架構在實時性、隱私保護和資源效率上的瓶頸日益凸顯。本文提出“端 - 邊 - 云”三級智能協同平臺架構&#xff0c;以“時空 - 資源 - 服務”三維協同理論為核心&#xff0c;構建覆蓋終端感知、邊緣計算、云端…

【如何搭建開發環境】

了解java程序 JAVA體系結構 跨平臺原理與編譯和反編譯 如何學習java語言&#xff0c;如何搭建環境 設置JAVA_HOME&#xff0c;指向jdk的安裝目錄這一級即可。比如我的JDK安裝在C:\java\jdk1.8.0_25&#xff0c;那JAVA_HOME的值就是C:\java\jdk1.8.0_25設置Path變量 在Path值后…

LegoGPT,卡內基梅隆大學推出的樂高積木設計模型

LegoGPT 是由卡內基梅隆大學開發的一款創新性樂高積木設計模型&#xff0c;能夠根據用戶的文本提示生成結構穩固、可組裝的樂高模型。該模型基于自回歸語言模型和大規模樂高設計數據集進行訓練&#xff0c;用戶只需輸入簡單的文字描述&#xff0c;LegoGPT 就能逐步構建出物理穩…

深入理解 NumPy:Python 科學計算的基石

在數據科學、人工智能和科學計算的世界里&#xff0c;NumPy 是一塊繞不過去的基石。它是 Python 語言中用于高性能科學計算的基礎包&#xff0c;幾乎所有的數據分析與機器學習框架&#xff08;如 Pandas、TensorFlow、Scikit-learn&#xff09;都離不開它的支持。 一、什么是 …

Java基礎(IO)

所有操作都在內存&#xff0c;不能長時間保存&#xff0c;IO主要在硬盤&#xff0c;可以長時間保存。 一、File類 File類被定義為文件和目錄路徑名的抽象表示形式&#xff0c;這是因為 File 類既可以表示文件也可以表示目錄&#xff0c;他們都通過對應的路徑來描述。 提供構…

仿正點原子驅動BMP280氣壓傳感器實例

文章目錄 前言 一、寄存器頭文件定義 二、設備樹文件中添加節點 三、驅動文件編寫 四、編寫驅動測試文件并編譯測試 總結 前言 本文驅動開發仿照正點原子的iic驅動實現&#xff0c;同時附上bmp280的數據手冊&#xff0c;可訪問下面的鏈接&#xff1a; BMP280_Bosch(博世…

論壇系統(中-1)

軟件開發 編寫公共代碼 定義狀態碼 對執?業務處理邏輯過程中可能出現的成功與失敗狀態做針對性描述(根據需求分析階段可以遇見的問題提前做出定義)&#xff0c;?枚舉定義狀態碼&#xff0c;先定義?部分&#xff0c;業務中遇到新的問題再添加 定義狀態碼如下 狀態碼類型描…

E+H流量計通過Profibus DP主站轉Modbus TCP網關與上位機輕松通訊

EH流量計通過Profibus DP主站轉Modbus TCP網關與上位機輕松通訊 在現代工業自動化的廣闊舞臺上&#xff0c;Profibus DP與Modbus TCP這兩種通信協議各領風騷&#xff0c;它們在不同的應用場景中發揮著舉足輕重的作用。但工業生產的復雜性往往要求不同設備、系統之間能夠順暢溝…

服務器中存儲空間不足該怎么辦?

服務器作為存儲數據信息的重要網絡設備&#xff0c;隨著企業業務的不斷拓展&#xff0c;所需要存儲的數據信息也在不斷增加&#xff0c;最終會導致服務器中存儲空間不足&#xff0c;這不僅會影響到服務器系統性能&#xff0c;還會造成業務無法正常執行&#xff0c;那么&#xf…

C++23 views::chunk_by (P2443R1) 詳解

文章目錄 引言C23 范圍庫概述范圍視圖&#xff08;Range Views&#xff09;范圍算法&#xff08;Range Algorithms&#xff09;范圍適配器&#xff08;Range Adapters&#xff09; std::views::chunk_by 介紹基本概念特性使用場景 示例代碼簡單示例自定義謂詞示例 總結 引言 在…

零碳園區能源系統-多能互補體系

構建以可再生能源為核心的零碳園區能源系統&#xff0c;需整合光儲直柔、光伏發電、微電網、氫能與儲能技術&#xff0c;通過多能協同與智能調控實現能源生產、存儲、消費全鏈條優化。以下是系統性實施方案&#xff1a; 一、系統架構設計 1. 多能互補體系 &#xff08;圖示&a…

elastic search學習

首先在自己電腦上安裝elastic search。安裝成功后&#xff0c;查看ES是否啟動成功。 安裝過程參考&#xff1a;ElasticSearch入門1: mac 安裝 - 霜井 - 博客園 安裝完成后&#xff0c;直接執行bin目錄中的elastic search命令后&#xff0c;就可以啟動成功&#xff01; 在網頁…