注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

蒙奇D小豌豆的博客

蒙奇D小豌豆的学习记录

 
 
 

日志

 
 

多队列(queues)网卡DMA收包方式  

2011-12-19 20:52:35|  分类: network |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

本文档介绍了多队列(queues)网卡DMA接收数据包方式:

1.       Queues:增加驱动I/O能力,提供多个输入队列

2.       DMA:减少CPU负载处理

一. 主要数据结构

Receive descriptor node

struct rxbd_desc{

                u16         status;  /* Status Fields*/    /* optional */

                u16         length;  /* Buffer Length */ /* optional */

                u32         bufPtr;  /* Buffer Pointer 通常DMA指向skb->data*/ 

};

Rx_buffer:skb

struct rx_buffer {

                struct sk_buff *skb;

                ………

                };

Queue ring descriptor: ring->desc包含countstruct rxbd_descstruct rx_buffer

Struct ring {

                void *desc;                                         /* descriptor ring memory */

                struct rx_buffer *rx_buffer_info; /*skb data*/

                u16 count;                                           /* amount of descriptors */

                unsigned int size;                             /* length in bytes (of  descriptors) */

                dma_addr_t dma;                                           /* phys. address of descriptor ring */

                next_to_clean

                next_to_use

                ……..

}

二.主要寄存器:每个queue都有下列一组寄存器, n表示queue编号

1. Receive Descriptor Base Address(RDBA[n]):存放ring->descdma地址

2. Receive Descriptor LengthRDLEN[n]: 存放该ring的描述符长度(ring->count * sizeof(struct rxdb_desc)

3. Receive Descriptor ControlRXDCTL[n]queue使能控制器

.程序分析

1.       在驱动probe函数中为每个queue分配一个ring

static int alloc_rx_queues(struct ixgbe_adapter *adapter)

{

                int rx = 0, nid = adapter->node;

 

                for (; rx < adapter->num_rx_queues; rx++) {

                                struct ring *ring;

 

                                ring = kzalloc_node(sizeof(*ring), GFP_KERNEL, nid);

                                if (!ring)

                                                ring = kzalloc(sizeof(*ring), GFP_KERNEL);

                                if (!ring)

                                                goto err_allocation;

                                ring->count = adapter->rx_ring_count;

                                ring->queue_index = rx;

                                ring->reg_idx = ring->queue_index  /*用于I/O寄存器编号绑定 通常顺序绑定  可自定义*/

                                ……..

                                …….

                                adapter->rx_ring[rx] = ring;

                }

                                return 0;

err_allocation:

                while (rx)

                                kfree(adapter->rx_ring[--rx]);

                return -ENOMEM;

}

2.       open函数中为ring分配资源: 包括countstruct rx_bufferstruct rxbd_desc

int setup_rx_resources(struct ring *rx_ring)

{

                int size;

 

                size = sizeof(struct rx_buffer) * rx_ring->count;

                rx_ring->rx_buffer_info = vzalloc_node(size, rx_ring->numa_node);

                if (!rx_ring->rx_buffer_info)

                                rx_ring->rx_buffer_info = vzalloc(size);

                if (!rx_ring->rx_buffer_info)

                                goto err;

 

                /* Round up to nearest 4K */

                rx_ring->size = rx_ring->count * sizeof(struct rxbd_desc);

                rx_ring->size = ALIGN(rx_ring->size, 4096);

 

                rx_ring->desc = dma_alloc_coherent(dev, rx_ring->size,

                                                                                   &rx_ring->dma, GFP_KERNEL);

                /* dma_alloc_coherent  分配rx_ring->size 大小的dma内存,虚拟地址给描述符desc,物理地址给rx_ring->dmarx_ring->dma值将被填入RDBA寄存器 */

                if (!rx_ring->desc)

                                goto err;

 

                rx_ring->next_to_clean = 0;

                rx_ring->next_to_use = 0;

                return 0;

err:

                vfree(rx_ring->rx_buffer_info);

                rx_ring->rx_buffer_info = NULL;

                return -ENOMEM;

}

3.       open函数中为将ringreceive describtor 寄存器相绑定:

void configure_rx_ring(struct adapter *adapter,

                                                     struct ring *ring)

{

                struct hw *hw = &adapter->hw;

                u64 rdba = ring->dma;

                u32 rxdctl;

                u8 reg_idx = ring->reg_idx;/*ring 与寄存器组对应的编号,表示为该编号的I/Oqueue*/

                /* disable queue to avoid issues while updating state */

                rxdctl = IXGBE_READ_REG(hw, RXDCTL(reg_idx));

                ixgbe_disable_rx_queue(adapter, ring);

 /*设置RXDCTL[ring->reg_idx] 关闭queue使能*/

 

                IXGBE_WRITE_REG(hw, RDBA(reg_idx), rdba )

                /*设置RDBA [ring->reg_idx] ring->dma */

 

                IXGBE_WRITE_REG(hw, RDLEN(reg_idx),

                                                ring->count * sizeof(struct_rxdb_desc));

                /*设置RDLEN [ring->reg_idx] count*desc_len */

 

                /* enable receive descriptor ring */

                rxdctl |= IXGBE_RXDCTL_ENABLE;

                IXGBE_WRITE_REG(hw, RXDCTL(reg_idx), rxdctl);

}

4.       open函数中为ringcountdesc-> bufPtr分配空间,进行DMA绑定skb->data

alloc_rx_buffers(struct ring *rx_ring, u16 cleaned_count);

                {

                struct rxdb_desc *rx_desc;

                struct rx_buffer *bi;

                struct sk_buff *skb;

                u16 i = rx_ring->next_to_use;

                while (cleaned_count--) {

                                rx_desc = &(struct rxdb_desc *)(( rx_ring)->desc))[i]) /*取第i个描述符*/

                                bi = &rx_ring->rx_buffer_info[i]; /*取第ibuffer*/

                                skb = bi->skb;

                                /*分配skb*/

                                skb = netdev_alloc_skb_ip_align(rx_ring->netdev, rx_ring->rx_buf_len);

                                bi->skb = skb;

                                /*skb->data 映射给描述符bufPtr*/

                                rx_desc->bufPtr = dma_map_single(rx_ring->dev,skb->data,

                                 rx_ring->rx_buf_len, DMA_FROM_DEVICE);

                                }

}

  评论这张
 
阅读(2606)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018