日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

RK3288 GMAC整理

發布時間:2025/6/17 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RK3288 GMAC整理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、源文件

源碼路徑:\drivers\net\ethernet\rockchip\gmac

源碼閱讀順序:

? ? ?

二、重要探針函數stmmac_dvr_probe

1. alloc_etherdev

申請網卡設備和私有數據。

struct net_device *ndev = NULL;

struct stmmac_priv *priv;

ndev = alloc_etherdev(sizeof(struct stmmac_priv));

priv = netdev_priv(ndev);

網卡設備和私有數據緊緊的挨在一起:網卡設備+私用數據結構,通過netdev_priv獲取私有數據。網卡設備是通用數據結構,私有數據則為各個MAC控制器的數據結構。

2. stmmac_hw_init

初始化MAC設備。檢測要添加的設備(GMAC/MAC10-100),檢查HW能力并設置驅動程序的特性。

3. netif_napi_add

初始化一個NAPI上下文,輪詢接收數據包接口。

netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);

stmmac_poll是輪詢接口

該接口完成兩個事情:

1)當數據發送完成時產生中斷,進入該函數進行資源回收。

2)收到數據產生中斷,進入該函數進行數據接收和處理。

static int stmmac_poll(struct napi_struct *napi, int budget) {   ......   stmmac_tx_clean(priv); //傳輸完成后回收資源work_done = stmmac_rx(priv, budget); //數據包接收處理stmmac_enable_dma_irq(priv); //使能dma終端   ...... }

stmmac_rx函數解析

作用:再次填充并使用skb預先分配的緩存,由NAPI輪詢方法調用,可以獲得環內所有幀。

函數:static int stmmac_rx(struct stmmac_priv *priv, int limit)

函數內定義:

1priv->hw->desc->get_rx_owner(p)

判斷當前描述子的歸屬:描述子數據結構中OWN位,

  0: 當前描述子應該由CPU操作,

  1: 前描述子應該由GMAC操作。

對于接收,初始化dma描述子隊列時設置為1

GMAC根據寄存器配置,獲取可用接收描述子,然后從RxFIFO中讀取從PHY接收的Ethernet報文,如果報文符合接收條件,將該報文寫入接收描述子指向的數據緩沖區,并回寫接收描述子。這個回寫就會將OWN位設置為0。

2)next_entry = (++priv->cur_rx) % rxsize;

獲取下一幀描述符,

p_next =priv->dma_rx + next_entry;

priv->cur_rx:已經傳遞給協議層的index。

3)status =(priv->hw->desc->rx_status(&priv->dev->stats, &priv->xstats,p));

獲取收到幀狀態,如果是丟棄幀,則什么都不處理;否則上傳到上層網絡。

4frame_len = priv->hw->desc->get_rx_frame_len(p, coe); 獲取幀長度

5skb = priv->rx_skbuff[entry];

priv->rx_skbuff[entry] = NULL;

注意:skb將有上層網絡處理完后進行釋放。

6skb_put(skb, frame_len);

dma_unmap_single(priv->device,priv->rx_skbuff_dma[entry],priv->dma_buf_sz, DMA_FROM_DEVICE); ?設置skb數據長度和解除流式DMA映射

7)獲取skb的協議類型

skb->protocol = eth_type_trans(skb,priv->dev);

skb->dev = priv->dev;

8)napi_gro_receive(&priv->napi,skb);

skb通過NAPI接口上傳上層網絡協議處理。

9)stmmac_rx_refill(priv); 重新填充接收隊列

?

三、打開網卡設備接口stmmac_open

網卡剛起來時是關閉的,要用命令去打開,ifconfig eth0 up 時調用net_device_ops.ndo_open,這里為stmmac_open。

  • netdev_priv 獲得網絡設備私有數據
  • stmmac_check_ether_addr 檢測MAC地址是否有效,若無效,隨機產生一個
  • stmmac_mdio_register注冊MII總線
  • mdiobus_register()

    a.注冊總線設備device_register(&bus->dev);

    b.復位總線bus->reset(bus);

    c.掃描總線上的PHY設備,最大支持32

    4. stmmac_init_phy初始化PHY設備,并將PHYMAC綁定

    5. request_irq 申請中斷

    ret = request_irq(dev->irq,?stmmac_interrupt,

    ??IRQF_SHARED, dev->name, dev);

    注冊中斷請求線IRQ,中斷處理函數stmmac_interrupt用于接收DMA數據,配NAPI處理。

    static irqreturn_t stmmac_interrupt(int irq, void *dev_id) {....../* To handle DMA interrupts */stmmac_dma_interrupt(priv);   }static void stmmac_dma_interrupt(struct stmmac_priv *priv) {......status = priv->hw->dma->dma_interrupt(priv->ioaddr, &priv->xstats);if (likely((status & handle_rx)) || (status & handle_tx)) {if (likely(napi_schedule_prep(&priv->napi))) {stmmac_disable_dma_irq(priv);__napi_schedule(&priv->napi); //加入poll流程}}...... }

    ?

    四、發送數據接口stmmac_xmit

    該接口實現了Scatter/Gather I/O功能,通過skb_shinfo宏來判斷數據包是由一個數據片段組成,還是由大量數據片段組成。

    1、entry= priv->cur_tx % txsize;

    desc= priv->dma_tx + entry; 獲取可用發送描述子

    first= desc; 保存第一個數據片段

    2priv->tx_skbuff[entry]= skb;

    priv->tx_page[entry]= NULL; skb放到發送隊列

    3、unsignedint nopaged_len = skb_headlen(skb);

    desc->des2=dma_map_single(priv->device,skb->data,nopaged_len, DMA_TO_DEVICE);

    priv->hw->desc->prepare_tx_desc(desc,1, nopaged_len, csum_insertion);

    發送單個或第一個數據包,當只有一個數據片段時,skb->data將發送所有數據;當有多個數據片段時,skb->data則指向第一個數據片段,數據長度skb->len skb->data_len,其他數據存放在共享數據結構frags數組中。(skb->len:數據包中全部數據的長度,skb->data_len分隔存儲數據片段長度)

    4、

    for (i = 0; i < nfrags; i++) {const skb_frag_t *frag = &skb_shinfo(skb)->frags[i];int len = skb_frag_size(frag);entry = (++priv->cur_tx) % txsize;if (priv->extend_desc)desc = (struct dma_desc *)(priv->dma_etx + entry);elsedesc = priv->dma_tx + entry;TX_DBG("\t[entry %d] segment len: %d\n", entry, len);desc->des2 = skb_frag_dma_map(priv->device, frag, 0, len, DMA_TO_DEVICE);priv->tx_skbuff_dma[entry] = desc->des2;priv->tx_skbuff[entry] = NULL;priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion,priv->mode);wmb();priv->hw->desc->set_tx_owner(desc);wmb(); }

    發送剩余數據片段。

    對于多個數據片段時,還要進行數據片段的發送,采用頁處理。直接處理頁結構,而不是內核虛擬地址。

    5priv->hw->desc->set_tx_owner(first);

    priv->cur_tx ++;

    將第一個數據片段描述子交給GMAC,記錄當前發送index

    6、priv->hw->dma->enable_dma_transmission(priv->dma_ioaddr,

    ??????????????????????????priv->dma_channel);

    寫任何值喚醒處于掛起的RxDMA

    轉載于:https://www.cnblogs.com/debruyne/p/9133439.html

    總結

    以上是生活随笔為你收集整理的RK3288 GMAC整理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。