轉:https://blog.csdn.net/walker0411/article/details/73332737?spm=1001.2101.3001.6650.2&utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-2.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-2.no_search_link&utm_relevant_index=5
高通AP10.4開發者指南——WLAN(2.5 代碼流程)
2.5 代碼流程(Code Flow)
這部分講解一些主要的配置通路、收發數據的通路。下面這些顏色,用於區分不同的模塊。
2.5.1配置通路(Configuration Path)
WLAN驅動的配置路徑主要包含:radio接口的初始化和去初始化(比如wifi network接口)、VAP的創建和刪除(比如說ath network接口)。
2.5.1.1 驅動線程(Driver Threads)
同一時間可能有多個線程被啟動。這些線程有:
- 傳輸線程(Transmit (OS context))
- 中斷線程(Interrupt)
- 延遲中斷處理線程(Deferred Interrupt Handler)
- Timer處理線程(Timers)
- Beacon處理線程(Beacon handling)
- ADDBA幀處理線(Addba exchange)
- 接收包亂序處理(Receive Reordering)
- MLME timer處理(鑒權/關聯)(MLME timers (authentication/association))
- 同步處理(Synchronization (Lock Macros: OS-specific abstraction))
2.5.1.2 Tx和Rx的初始化(Tx and Rx Initialization)
Tx和Rx初始化包含如下內容:
- 為transmit & receive分配Descriptor
- 針對不同OS,初始化過程會有一些不同:
- NDIS請求驅動來分配receive buffer
- Unix OS變量維護一個common的buffer pool
- 對於AR93xx設備,status會進入到環狀的packet buffer
2.5.1.3 設備attach過程(Device attach)
圖2-4解釋了radio interface通過PCI bus interface的初始化過程(通過其他bus interface的初始化過程不在本次討論之列)。WLAN driver load后,radio interface通過ath_pci_probe進行初始化。每個radio interface都會進行一次device attach。
圖 2-4 Radio Interface初始化(PCI Mode)
2.5.1.4 設備detach過程(Device detach)
driver unload的時候,會remove掉radio interface,使用ath_pci_remove函數來進行。這個函數是注冊在pci_driver結構體中的,作為remove動作時的例行函數。
2.5.1.5 VAP的創建(VAP create)
VAP network interface通過“wifi” radio network interface ioctl SIOC80211IFCREATE進行創建。
這個“wifi” interface是這個VAP interface的父設備。圖2-5說明了VAP創建的代碼流程。每個VAP都有與之對應的“ath” network interface。
Figure 2-5 VAP創建的代碼流程
2.5.1.6 VAP的刪除(VAP delete)
VAP的刪除,通過application調用VAP network接口ioctl SIOC80211IFDESTROY來完成。
Figure 2-6 VAP Delete代碼流程
2.5.1.7 VAP的啟動(VAP start)
VAP的啟動,是通過VAP創建時注冊的network device open callback函數來完成。
Figure 2-7 VAP Start代碼流程
2.5.1.8 VAP的停止(VAP stop)
VAP的停止,是通過VAP創建時注冊的network device stop callback函數來完成。
Figure 2-8 VAP Stop代碼流程
2.5.2 數據通路(Data Path)
2.5.2.1 傳輸流(Transmit flow)
傳輸流主要存在於兩種不同的執行路徑:WLAN驅動從network stack中獲取data packet,以及驅動處理過后,獲取存儲在software TID隊列,或發送到硬件的data packet(假定這里在硬件隊列中沒有pending的傳輸packet)。packet傳輸完成后,硬件產生傳輸完成interrupt,驅動啟動tx_tasklet任務來完成transmit流程。作為tx_tasklet的一部分,驅動釋放已完成傳輸的packet,並運行TID scheduler,將軟件TID queue中的packet,放到hardware queue中。
數據傳輸通路主要在OS shim層進行,並有如下特征:
- 調用wlan_vap_send (umac/txrx/ieee80211_output.c) 來啟動傳輸流程
- Win7/Vista處理802.11 packet,其他的處理802.3
- Node查找與鑒權
- UMAC調用ath_tx_send (umac/if_lmac/if_ath.c)傳遞packet,構建packet
- 封裝crypto headers, tid, crypto
- Packet傳遞到ath_tx_start_dma (lmac/ath_dev/ath_xmit.c)
- 完成Physical mapping to descriptor
- Descriptors分配與創建
- 若硬件queue中的閥值packet比較少,則操作單一packet入隊列,或者將packe放到“tid”隊列中處理
- 處理中斷時創建Aggregate
- 中斷對應queue
- tx中斷發生時,驅動掃描有packet發送的node
- 通過“round robin”算法從中選擇一個node
- 創建Aggregate並放到硬件隊列中
2.5.2.2 傳輸中斷的處理(Transmit Interrupt Handling)
傳輸中斷與queue一一對應。中斷發生時,ath_tx_edma_tasklet()將被調用。Rate信息可通過ath_rate_tx_complete_11n函數獲取。
- 對於single packet,如果軟件允許retry,則會有retry動作。
- 對於aggregate,ath_tx_complete_aggr_rifs() 函數用於處理block ack並return沒有完成的傳輸queue的head(node,tid)
- 如果retry次數達到最大,則將packet送至OS shim層完成處理
- 通過調用ath_txq_schedule() (ath_xmit_ht.c)函數,來調度下一次傳輸處理
- 根據發送的packet篩選node(round robin算法,即輪詢)
- 如果addba完成,則創建一個aggregate(之前failed的packet將做為新aggregate的一部分)
- 查找速率控制和選擇速率序列
- 用於hardware傳輸的Queue packet/aggregate
2.5.2.3 傳輸通路管理(Transmit Path Management)
ieee80211_send_mgmt (wlan/umac/mlme/ieee80211_mgmt.c) 函數主要作用有:
- probe request
- probe response
- beacon
- action frames
- null data packets
這里的packet跟data packet很像。速率強制設定為最小速率,voice queue用於所有的management packet。
傳輸路徑管理接口,通過ath_tx_mgt_send()函數提供給ath層。management task結束之后的代碼流程與data packet的相同。
2.5.2.4 中斷流程(Interrupt Path)
驅動初始化的過程中會注冊中斷. 流程如下:
- 入口 sc -> sc_ops -> isr() 映射到 ath_intr
- ath_intr (lmac/ath_dev/ath_main.c)調用HAL層(ah_isInterruptPending)來獲取pending狀態的中斷
- ah_isInterruptPending根據平台映射到不同函數——AR93xx平台HAL使用的是ar9300IsInterruptPending()
- HAL層將不同平台的中斷寄存器的每個bit的意義抽象出來,做一個common的映射:
HAL_INT_SWBA
HAL_INT_RX
HAL_INT_TX
… - ath_intr() 返回一個bool值來表明這個中斷是否為當前使用者所創建的
- ath_handle_intr()通過OS來調度。
OS適配層與下面的內容關聯:
- Windows平台中的DPC接口
- MacOS平台的handle_interrupt接口
- netBSD平台的緊急調用
- 調用指定的tasklet,來響應每個中斷
- 發送中斷的處理,在文件ath_edma_xmit.c的ath_tx_edma_tasklet()函數中結束。
- 接收中斷的處理,在文件ath_edma_recv.c的ath_rx_edma_tasklet()函數中結束。
- 其他的中斷也有類似處理。
- Beacon
- GPIO
- 錯誤處理,如overrun/underrun/fatal-chip-error
2.5.2.5 AR93xx的傳輸(AR93xx Transmit)
對於AR93xx的設備,有一個通用的循環鏈結構會上報傳輸的結束狀態。每個硬件descriptor指針都會指向4個物理內存塊。descriptor可以有多個鏈在一起。
- TX descriptor指針(TXDP) FIFO
- 長度為8個元素
- 每個隊列有一個FIFO
- 2 個(最多)
2.5.2.5.1 數據傳輸流程(Data Transmit flow)
圖 2-9 數據傳輸流程
2.5.2.6 數據傳輸完畢的處理流程(Data Transmit Completion Flow)
圖 2-10 說明了TX完成中斷的處理,以及tx是如何調度的,這些都是傳輸完畢的處理內容。
圖 2-10 數據傳輸完畢的代碼流程
2.5.2.7 接收流程(Receive flow)
硬件的接收幀通過HAL_INT_RX發送帶指定驅動。有一些接收處理是延遲敏感的(如UAPSD觸發),在這種情況下,處理在ISR上下文中處理。這些rx處理應該盡可能的保持到最小。其他主要的接收處理流程,在tasklet上下文中處理(ath_rx_tasklet)。rx幀的處理細節參看圖2-11。
圖 2-11 接收代碼流程
2.5.2.8 單包接收(Single Data Packet Receive)
在單包接收task中,由ieee80211_input_data()進行處理。並根據STA/HOSTAP/IBSS這些不同的mode來進行解析和排序,並使用不同的廣播。其他的event包括:
- Crypto DeCap和DeMic; 給軟件提供處理crypto和demic的機會。
- 按需進行AMSDU的處理(ieee80211_amsdu_input)
- 按需調用ieee80211_deliver_data 轉換成802.3
- 在HostAP mode下,如果目的節點已經associated,則包可以轉發到wifi mediumu或轉發到上面的橋接接口。
- 在STA mode下,包由棧處理。
2.5.2.9 聚合接收(Aggregate Receive)
在Aggregate接收中,包由AMPDU處理流程中的ath層進行處理。
ath_ampdu_input() (in lmac/ath_dev/ath_recv_ht.c)會獲取packet。
- 如果處理的內容是qos data,則tid會從中解析出來。
- tid相關的rxbaw結構會從node中被抽取出來。
- Seq#映射到baw中,所有流程中的幀,此時會交由上層 (umac)進行處理。
- 傳輸通道會維護一個timer,如果timer到了,則所有的包都處理結束,window向下一個遷移。
處理完畢的packet,會與上面提到的單包處理的流程一樣,繼續進行處理。
2.5.2.10 AR93xx的接收處理(AR93xx Receive Handling)
AR93xx芯片支持高低優先級的接收ring。高優先級的用於UAPSD。低優先級的是通常的TID traffic。
ath_rx_edma_init() (在wlan/lmac/ath_dev/ath_edma_recv.c中) 會初始化一個固定大小的receive buffer、FIFO軟件數據結構,並在ath_osdep.c調用OS-specific的函數來分配buffer。
接收准備就緒時,通過調用th_edma_startrecv() 來傳遞已分配的buffer、使能硬件上的的接收FIFO,設置MAC地址,並啟動DMA引擎。
2.5.2.11 接收中斷(Receive Interrupt)
當接收中斷觸發時,DPC函數會調用ath_rx_edma_tasklet(),來處理接收的高低優先級隊列。
這個函數有如下功能:
- 取出第一個“完成”位被置位的buffer
- 如果完成了,則檢查狀態,取出所有完整的packet,並處理
- 將損壞的packet放回到硬件隊列中以便重用
在閉環結構中處理完畢的packet,會傳遞到ath_rx_process (在the ath_recv.c文件中)。
針對不同硬件,這個函數是一個通用的函數。狀態位處理后,帶有狀態的packet會傳遞到ath_osdep文件中的ath_rx_indicate()函數。
2.5.2.12 MacOS萍提的ath_rx_indicate()(ath_rx_indicate() for MacOS)
在這個函數中,packet會通過調用入口函數sc_ieee_ops -> rx_indicate()來傳遞給上層(UMAC)。一個新的buffer分配后,會發送到硬件的ready隊列。
2.5.2.13 其他的接收event(Other Receive Events)
sc_ieee_ops -> rx_indicate()映射到if_ath.c文件(在umac/if_lmac路徑下)的ath_net80211_rx()函數。
包含如下功能:
- 能夠在監控mode的接口上打印packet內容
- 定位與這個packet associated的節點
- 針對ampdu節點,在ath層調用 sc_ops -> rx_proc_frame
- 對於單packet,會在ieee80211_input() (在umac/txrx/ieee80211_input.c文件中)函數中做進一步處理
- 數據packet會在ieee80211_input_data()函數中處理
- 管理packet會在ieee80211_recv_mgt()函數中處理
2.5.3 數據通路——局部卸載(Data Path — Partial Offload)
在新的一代802.11ac無線芯片中,比如QCA988x/989x和QCA999x/998x,多數的數據處理由主CPU轉移到芯片本身來處理(目標處理器),這樣可以降低主CPU負載,提高數據處理效率。AP SOC平台上的處理器,如AP135等,會運行一個小的host數據通路代碼。在AP平台上,“低延遲”的代碼路徑被啟用。host和target之間的通信,通過DMA來進行,這被稱作Copy Engine。“Copy Engine”有8個管道。每個管道都被配制成雙向通信。
所有的taget到host的通知,都是由一系列中斷產生,中斷的handler有如下功能:
1. 檢查中斷是否有錯誤
2. 關閉中斷
3. 調度延遲進程進行進一步處理。(比如Linux的tasklet)
在Partial Offload架構中,host和target的功能划分可以大體按照下面進行:
Host Tx
- 棧中的單個包或多個包所使用的buffer直接由DMA映射
- 建立基於target的擴展數據
- 建立copy engine來傳輸擴展數據或部分數據包
-
Tx閉環處理,包含兩個步驟:
- Tx descriptor下載完畢
- Tx packet處理t完畢
只有上面兩個部分都結束,packet才會被釋放。
Target Tx
- packet按照WMM訪問類別進行分類。
- 匯總每個TID,匯總setup & teardown。
- 查詢率。
- 通過HTT消息,表明packet結束。
Host Rx
- 通過DMA發送Rx buffer到MAC硬件。
- 丟棄、重排序或轉發packet到棧中(取決於HTT消息)。
Target Rx
- Block Ack窗口管理和發送Block Ack.
- 發送HTT Rx indication消息到host
header的封裝/解封,以及加密/解密(如果使能了安全機制),在MAC硬件中進行。
圖 2-13 列出了數據通路的相關模塊:
圖 2-13 TxRx 架構概述
2.5.3.1 Tx處理(Tx Processing)
對於Partial Offload的通路,Tx處理流程可以分為兩個部分:
- packet的傳輸
- packet的結束
- 標記完成傳輸的packet
WLAN驅動可以從棧中接收下面幾種類型的packet: (取決於配置):
- 普通Ethernet packet (包含或不包含一個VLAN header)
- 一個本地的Wi-Fi (802.11)packet(包含或不包含一個VLAN header)
- 一個裸802.11packet
下面是Tx處理的主要feature:
packet的傳輸
- packet通過OS適配層提供的主要節點進入驅動。DMA到buffer list的映射在此時完成。同時packet會下放到通用“Offload”(OL)層做進一步處理。
- OL層的入口是 ol_tx_ll()
-
ol_tx_ll()
- 分配OL層Tx descriptor
- 存儲packet中控制塊里的meta-data碎片 (linux中使用結構體struct cb {})
- 准備HTT descriptor,並嵌入到OL Tx descriptor
- 填充HTT descriptor中的分散-收集list
- 調用 ol_tx_send()
-
ol_tx_send() 將packet傳遞到HTT層。
- htt_tx_send_std() 添加HTT/HTC fragment到qdf_nbuf meta-data,設置每個fragment的endianness,分配並准備一個HTC (僅軟件內部) packet,並通知HTC層。
- HTCSendDataPkt() 檢查可用的HIF資源,如果沒有足夠的資源則將packet丟棄。這個函數會填充HTCdescriptor,並傳遞給HIF層。
- HIFSend_head() 添加fragment到qdf_nbuf _cb的meta-data (fragment由stack +HTT/HTC fragment組成),並放到Copy Engine (CE) send-list中和激活CE。
- CE_sendlist_send() 通過將copy engine環索引,寫入target上對應的CE register來傳遞buffer。CE slot的數量與包中的fragment數量(= DMA已映射的地址) 對等。如果linux從棧中一次發送一個packet,則每個packet所使用的CE slot數為2。
- CE 4 用於從host到target的 HTT + HTCdescriptor,以及數據packet的一部分。
NOTE
對於一個已知的packet,驅動會下載24byte的HTT/HTC header + 一部分固定的數據packet到target端。這個下載動作很有必要,即使這部分數據packet已經由MAC層h/w的host內存,放在了DMA中,也需要進行,這樣target端才能解析packet header,並按照packet類型分類。下載的長度包括 L2 headers + L3 headers的2 bytes(Ipv4 TOS / IPV6 Flow label) 長度的信息。下載從行度在驅動初始化的時候設置,使用下面的值:
Ethernet packet -> 28 bytes
Native 802.11 packet -> 44 bytes
Raw 802.11 packet -> 50 bytes
圖 2-14 傳輸流程
傳輸packet的完成
Tx完畢通知包含兩部分:
-
target端完成下載descriptor。
- 這個完畢通知只是一個從target到host的中斷,用來通知descriptor傳輸結束。
- 這個可以用於釋放Copy Engine索引,但不是實際的packet的meta-data。
- 為了CPU更有效率,用於CE 4的這個中斷已經被禁用了。替代的方案是,這個CE硬件索引會被輪詢,用於查找已完成的descriptor數。
-
真實packet的傳輸結束。
- 會產生一個從target到host的HTT消息。
- 會在CE 1上的每個Tx PPDU都產生中斷作為通知,主要用於從target到host的HTT消息。
- HTT消息攜帶所有完成的packet的ID。根據這些ID,所有實際的packet和所有的meta-data,比如HTC packet,OL Tx descriptor等等,都會被釋放。
- 釋放每個copy engine所處理的HTT消息buffer。這些buffer會在函數return之前,重新分配,並通過HTT消息handler傳遞回去。
圖 2-15 發送完成的處理流程
2.5.3.2 Rx處理(Rx Processing)
接收處理主要包含兩個部分:
- 處理由target發向host的HTT消息中的Rx通知。
- 分配並傳遞Rx buffer到MAC硬件,來處理實際的數據。
處理Rx標識
- 從target到host的Rx標識,是在每一個PPDU中斷中的。
- 從target到host的Rx標識通過HTT消息來傳遞,因此他使用target到host的專用copy engine 1。
- CEhandler從TID隊列中,獲取HTT消息buffer,並經由HIF、HTC、最終到達HTT。
- HTT消息handler(htt_t2h_message_handler())分解消息,並調用OL handler函數ol_rx_inidication_handler()。
- ol_rx_indication_handler()查找Rxdescriptor(實際的Rx buffer),並從MPDU抽取MSDU,並將每個MSDU入棧。
Rx buffer的分配和發送
Rx buffer在ol_rx_indication_handler()函數返回之前,會傳遞給硬件,
圖 2-16 Rx處理流程
2.5.3.3 數據通路和數據結構
下面的章節,列舉了一些offload層數據路徑的重要結構。
2.5.3.2.1 ol_txrx_pdev_t: 與TxRx物理設備對應
這個結構主要是,與WLAN驅動協作的物理設備,在offload mode下的收發特性。一個OL物理設備代表一個射頻接口(比如wifi0,wifi1等等)。這個結構體維護下面這些重要的信息:
- 非透明OS設備的handler
- 與更底層的物理設備的接口,比如HTT
- 針對特殊物理設備(Ethernet, native Wi-Fi, raw等等)的幀格式
- 與當前物理設備(PDEV)對應的虛擬設備(VDEV)列表
- Peer Id到Peer Object的映射數組
- 接收處理產生的信息;比如說Rx re-order數組
- 調用OS接口層注冊的Rx處理回調函數
- TxRx host統計計數TxRx host statistics
- Tx descriptor池
2.5.3.2.2 ol_txrx_vdev_t: 與TxRx虛擬設備對應
這個結構主要指,對於一個已知的VAP,offload mode下的虛擬設備與之對應的OL物理設備的收發特性。一個VDEV實體對應一個網絡接口(如 ath0, ath1等等)。多個VDEV實體可以映射到OS層中,可見的、單個OL物理設備(PDEV)。
- TxRx物理設備的handler(ol_txrx_vdev_t)
- VAP的MAC地址
- 當前vdev的虛擬設備ID
- 與當前VAP(vdev)連接的對端設備列表
- Tx和Rx處理函數的函數指針
- 速率控制信息(在host端完成的)
- VAP的可選mode
2.5.3.2.3 ol_tx_desc_t: 與Tx descriptor對應
這個結構體代表OL Tx descriptor。一個Tx descriptor池空間會在驅動初始化的時候申請。池的size等於1K,這與射頻接口的傳輸descriptor數量是一致的。對於每個有驅動傳輸的packet,都有一個對應的OL Tx descriptor會被分配出來與之對應。每個OL Tx descriptor都有自己的唯一ID。這個ID會在meta-data中攜帶給target。Target會將這個Tx descriptor的ID作為Tx傳輸結束message的一部分,依次返回給host,並由host釋放Tx包和OL Tx包。
2.5.3.2.4 ol_txrx_peer_t: 與peer node對應
這個結構體存儲了已連接的對端節點的重要狀態信息。這個數據結構主要用在Rx流程中。其包含的一些重要的信息如下:
- 對端已連接的VEDV的handler。
- 每個已連接的對端ID列表。這些對端ID主要用於獲取對應的節點結構體(利用對端ID到節點的映射機制)。
- 已連接對端,所對應的本地VAP的MAC地址。
- 每個TID的Rx重排序數組。這個數組會緩存Rx packet,直到當這個驅動從Target接收到一段連續的packet,或者從Target收到FLUSH消息。當收到FLUSH消息時,整個數組會被發送到網絡棧中,不管TID packet數組是否已存有連續的packet。
- 安全信息。
2.5.3.2.5 cvg_nbuf_cb: 聚會網絡buffer控制塊
這是一個非常重要的meta-data結構,存儲於inline或作為一個在OS專用data buffer結構中(比如linux的sk_buff,NetBSD的mbuf,Windows的NBLs)的指針。
這個meta-data結構,作為每個packet的一部分,維護了下面這些內容:
- 分散或集聚由OS下發到驅動的,物理地址&長度的碎片list。
- 由驅動添加的物理地址碎片和碎片的長度(在Tx通路中,target所需求的HTT/HTC meta-data)。
2.5.4 OL數據結構(OL Data Structures)
對於offload架構解決方案,OL(Off-Load)層是處於Unified MAC和其底層中間,比如target固件的WMI (無線管理接口) / WDI (無線數據接口)。參看圖 2-18
圖 2-18 Offload層架構
從圖2-18中可以很明顯的看出。大部分OSIF層和UMAC層數據結構沒有什么變化,並可以在offload模型中被重用。LMAC和其底層並沒有應用在offload模式下,而是使用OL和其底層,比如WMI和WDI來代替。OL層有一些新的數據結構,將會在下面的小節中說明。
2.5.4.1 ol_ath_softc_net80211: OL radio device結構
這個結構屬於OL層的“scn”模塊,主要抽象出了radio接口。在offload架構中,目標固件code實例和radio接口之間有一個1:1的映射。這個數據結構還會截取在指定radio接口上運行的code信息。它嵌套了UMAC層ieee80211結構體。
本結構體中的一些重要內容如下:
- UMAC通用設備結構體 (sc_ic)
- OS
- 設備handler
- OS層注冊的回調函數,會在目標遷移到service ready狀態時調用.
- 目標的狀態信息;如version/type/status
- 固件下載相關信息 (BMI information)
- 其他層的handler如WMI, HTT, HTC, HIF
- Channel和Tx功率信息
- 存儲TxRx統計計數的結構體
- 同步鎖
2.5.4.2 ol_ath_vap_net80211: OL network interface結構
ol_ath_vap_ieee80211是WLAN network接口在offload層的抽象。每個WLAN network接口在UMAC層通過“Virtual AP” (VAP)來表示,並與底層物理device/radio接口對應,比如“wifi0”, “wifi1”等等。一個VAP主要呈現出access point的操作模式,access point可以是一個host access point,一個IBSS或一個station。
存儲在這個結構圖中的重要信息如下:
- UMAC層VAP object (av_vap)
- OL層底層的物理設備 (OL層scn模塊)
- 每個VAP數據通路結構體的handler(av_txrx_handle)
- 用於beacon的相關信息(如offload mode, beacon buffer, probe templates etc.)
- Timer,主要用於cleanup。
- 同步鎖。
2.5.4.3 ol_ath_node_net80211: OL network interface結構
ol_ath_node_ieee80211是offload層在UMAC節點的抽象。一個UMAC節點代表了一個在HOST AP模式下已連接的station,或一個IBSS模式下的ad-hoc station,或一個infra-structure模式下的BSS。已連接的節點list,代表VAP的本地網絡。OL節點結構包含下面內容:
- UMAC層節點 (an_node)
-
VAP數據通路objecthandler (an_txrx_handle)
NOTE