多队列queues网卡DMA收包方式Word下载.docx
《多队列queues网卡DMA收包方式Word下载.docx》由会员分享,可在线阅读,更多相关《多队列queues网卡DMA收包方式Word下载.docx(5页珍藏版)》请在冰豆网上搜索。
u32
bufPtr;
/*BufferPointer
通常DMA指向skb->
data*/
};
Rx_buffer:
skb
structrx_buffer{
structsk_buff*skb;
………
Queueringdescriptor:
ring->
desc包含count个structrxbd_desc和structrx_buffer
Structring{
void*desc;
/*descriptorringmemory*/
structrx_buffer
*rx_buffer_info;
/*skbdata*/
u16count;
/*amountof
descriptors
*/
unsignedintsize;
/*lengthinbytes(of
descriptors)*/
dma_addr_tdma;
/*phys.addressofdescriptorring*/
next_to_clean;
next_to_use;
……..
}
二.主要寄存器:
每个queue都有下列一组寄存器,n表示queue编号
ReceiveDescriptorBaseAddress(RDBA[n]):
存放ring->
desc的dma地址
ReceiveDescriptorLength(RDLEN[n]):
存放该ring的描述符长度(ring->
count*sizeof(structrxdb_desc))
3.
ReceiveDescriptorControl(RXDCTL[n]):
queue使能控制器
三.程序分析
在驱动probe函数中为每个queue分配一个ring:
staticintalloc_rx_queues(structixgbe_adapter*adapter)
{
intrx=0,nid=adapter->
node;
for(;
rx<
adapter->
num_rx_queues;
rx++){
structring*ring;
ring=kzalloc_node(sizeof(*ring),GFP_KERNEL,nid);
if(!
ring)
ring=kzalloc(sizeof(*ring),GFP_KERNEL);
gotoerr_allocation;
ring->
count=adapter->
rx_ring_count;
queue_index=rx;
reg_idx=ring->
queue_index;
/*用于I/O寄存器编号绑定
通常顺序绑定
可自定义*/
…….
adapter->
rx_ring[rx]=ring;
return0;
err_allocation:
while(rx)
kfree(adapter->
rx_ring[--rx]);
return-ENOMEM;
在open函数中为ring分配资源:
包括count个structrx_buffer和structrxbd_desc
intsetup_rx_resources(structring*rx_ring)
intsize;
size=sizeof(structrx_buffer)*rx_ring->
count;
rx_ring->
rx_buffer_info=vzalloc_node(size,rx_ring->
numa_node);
rx_buffer_info)
rx_buffer_info=vzalloc(size);
gotoerr;
/*Rounduptonearest4K*/
size=rx_ring->
count*sizeof(structrxbd_desc);
size=ALIGN(rx_ring->
size,4096);
desc=dma_alloc_coherent(dev,rx_ring->
size,
&
dma,GFP_KERNEL);
/*dma_alloc_coherent
分配rx_ring->
size
大小的dma内存,虚拟地址给描述符desc,物理地址给rx_ring->
dma,rx_ring->
dma值将被填入RDBA寄存器
desc)
next_to_clean=0;
next_to_use=0;
err:
vfree(rx_ring->
rx_buffer_info);
rx_buffer_info=NULL;
在open函数中为将ring与receivedescribtor
寄存器相绑定:
voidconfigure_rx_ring(structadapter*adapter,
structring*ring)
structhw*hw=&
hw;
u64rdba=ring->
dma;
u32rxdctl;
u8reg_idx=ring->
reg_idx;
/*ring
与寄存器组对应的编号,表示为该编号的I/Oqueue*/
/*disablequeuetoavoidissueswhileupdatingstate*/
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->
为
dma*/
IXGBE_WRITE_REG(hw,RDLEN(reg_idx),
count*sizeof(struct_rxdb_desc));
/*设置RDLEN[ring->
为count*desc_len*/
/*enablereceivedescriptorring*/
rxdctl|=IXGBE_RXDCTL_ENABLE;
IXGBE_WRITE_REG(hw,RXDCTL(reg_idx),rxdctl);
4.
在open函数中为ring的count个desc->
bufPtr分配空间,进行DMA绑定skb->
data:
alloc_rx_buffers(structring*rx_ring,u16cleaned_count);
structrxdb_desc*rx_desc;
structrx_buffer*bi;
u16i=rx_ring->
next_to_use;
while(cleaned_count--){
rx_desc=&
(structrxdb_desc*)((rx_ring)->
desc))[i])
/*取第i个描述符*/
bi=&
rx_buffer_info[i];
/*取第i个buffer*/
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_buf_len,DMA_FROM_DEVICE);
(注:
可编辑下载,若有不当之处,请指正,谢谢!
)