ixgbevf驱动

  1. ixgbevf主要数据结构

        1)struct ixgbevf_adapter

             描述一个vf设备对象,主要包括qvetor、tx_ring、rx_ring以及记录io地址空间、netdev等信息;

struct ixgbevf_adapter {
	
    struct ixgbevf_q_vector *q_vector[MAX_MSIX_Q_VECTORS];//中断关联信息
	/* TX */
	int num_tx_queues;  //发送队列个数
	struct ixgbevf_ring *tx_ring[MAX_TX_QUEUES]; /* One per active queue */

	/* RX */
	int num_rx_queues; //接收队列个数
	struct ixgbevf_ring *rx_ring[MAX_TX_QUEUES]; /* One per active queue */

	struct msix_entry *msix_entries;//msix中断信息

	/* OS defined structs */
	struct net_device *netdev;
	struct pci_dev *pdev;

	/* structs defined in ixgbe_vf.h */
	struct ixgbe_hw hw;//硬件设备

	struct ixgbevf_hw_stats stats;

	u8 __iomem *io_addr; /* Mainly for iounmap use */ //io地址空间

	u32 rss_key[IXGBEVF_VFRSSRK_REGS];
	u8 rss_indir_tbl[IXGBEVF_X550_VFRETA_SIZE];
};

        2)struct ixgbevf_q_vector

        vf的每个中断都会申请一个q_vector对象,q_vector主要记录与其关联的tx、rx队列(在ixgbevf_map_rings_to_vectors里会做队列与q_vector的映射关系,可能存在一个q_vector对应多个队列的情况),另外比较重要的napi信息,当ixgbevf收包进入中断处理函数时,会通过改napi完成轮询批量收包,避免每个包处理都有中断;

struct ixgbevf_q_vector {
	struct ixgbevf_adapter *adapter;
	/* index of q_vector within array, also used for finding the bit in
	 * EICR and friends that represents the vector for this ring
	 */
	u16 v_idx;
	u16 itr; /* Interrupt throttle rate written to EITR */
	struct napi_struct napi;
	struct ixgbevf_ring_container rx, tx;
	char name[IFNAMSIZ + 9];
#ifdef CONFIG_NET_RX_BUSY_POLL
	unsigned int state;
#define IXGBEVF_QV_STATE_IDLE		0
#define IXGBEVF_QV_STATE_NAPI		1    /* NAPI owns this QV */
#define IXGBEVF_QV_STATE_POLL		2    /* poll owns this QV */
#define IXGBEVF_QV_STATE_DISABLED	4    /* QV is disabled */
#define IXGBEVF_QV_OWNED	(IXGBEVF_QV_STATE_NAPI | IXGBEVF_QV_STATE_POLL)
#define IXGBEVF_QV_LOCKED	(IXGBEVF_QV_OWNED | IXGBEVF_QV_STATE_DISABLED)
#define IXGBEVF_QV_STATE_NAPI_YIELD	8    /* NAPI yielded this QV */
#define IXGBEVF_QV_STATE_POLL_YIELD	16   /* poll yielded this QV */
#define IXGBEVF_QV_YIELD	(IXGBEVF_QV_STATE_NAPI_YIELD | \
				 IXGBEVF_QV_STATE_POLL_YIELD)
#define IXGBEVF_QV_USER_PEND	(IXGBEVF_QV_STATE_POLL | \
				 IXGBEVF_QV_STATE_POLL_YIELD)
	spinlock_t lock;
#endif /* CONFIG_NET_RX_BUSY_POLL */
};

        3)struct ixgbevf_ring

        用于描述一个ring对象,ring数据结构处理描述符desc、dma起始地址、长度外,还有两个比较重要的数据结构tx_buffer_info、rx_buffer_info,其中tx_buffer_info是在ixgbevf发送数据包是会使用到,ixgbevf每发送一个数据包,都会将数据包对应的dma信息记录到tx_buffer_info里,并且tx_buffer_info的next_to_watch设置改发送数据包所使用的描述符对象;然后在ixgbevf的中断处理函数ixgbevf_poll里会根据判断硬件是否已使用tx_buffer_info里缓存的描述符,如果已使用,则回收描述符(将对应的dma信息unmap);同理也会在ixgbevf_clean_rx_irq回收硬件已使用的描述符,将描述符的dma信息重新分配后设置给硬件下次继续使用;

        

struct ixgbevf_ring {
	struct ixgbevf_ring *next;
	struct net_device *netdev;
	struct device *dev;
	void *desc;			/* descriptor ring memory */
	dma_addr_t dma;			/* phys. address of descriptor ring */
	unsigned int size;		/* length in bytes */
	u16 count;			/* amount of descriptors */
	u16 next_to_use;
	u16 next_to_clean;
	u16 next_to_alloc;

	union {
		struct ixgbevf_tx_buffer *tx_buffer_info;   //缓存tx_ring的描述符信息
		struct ixgbevf_rx_buffer *rx_buffer_info;   //缓存rx_ring的描述符信息
	};
	unsigned long state;
	struct ixgbevf_stats stats;
	struct u64_stats_sync syncp;
	union {
		struct ixgbevf_tx_queue_stats tx_stats;
		struct ixgbevf_rx_queue_stats rx_stats;
	};

	u64 hw_csum_rx_error;
	u8 __iomem *tail;
	struct sk_buff *skb;

	/* holds the special value that gets the hardware register offset
	 * associated with this ring, which is different for DCB and RSS modes
	 */
	u16 reg_idx;
	int queue_index; /* needed for multiqueue queue management */
};

 

  2、设备初始化流程

1)、设备probe阶段

   ixgbevf_probe
    ixgbevf_init_interrupt_scheme
        ixgbevf_set_interrupt_capability
            ixgbevf_acquire_msix_vectors
                pci_enable_msix_range    
                    __pci_enable_msix_range(msi.c)
                        __pci_enable_msix
                            msix_capability_init
                                msix_setup_entries(分配msi_desc信息,并根据msix_entry信息填充msi_desc,完成后将msi_desc添加到                                                                     dev->msi_list)
                                arch_setup_msi_irqs
                                    arch_setup_msi_irqs(x86_init.c)
                                         native_setup_msi_irqs(从dev->msi_list获取msi_desc信息,通过irq_alloc_hwirq为每个msi_desc分配                                                                                  中断号,分配完成后通过setup_msi_irq-->irq_set_msi_desc_off将中断号信息                                                                                  填充到msi_desc->irq里)
                                msix_program_entries(遍历dev->msi_list的每个msi_desc,将其中保存的irq保存到msix_entry->vector                                                                               里)
        ixgbevf_alloc_q_vectors(分配qvector,为每个qvector分配一个napi,设置ixgbevf_poll)
        ixgbevf_alloc_queues(分配tx、rx ring)

2)ixgbevf_open阶段

ixgbevf_open
    ixgbevf_setup_all_tx_resources
    ixgbevf_setup_all_rx_resources
    ixgbevf_configure(将描述符信息通告给硬件)
        ixgbevf_configure_tx
        ixgbevf_configure_rx
            ixgbevf_configure_rx_ring
                ixgbevf_alloc_rx_buffers(为每个描述符预先分配好DMA内存信息供硬件使用)
    ixgbevf_map_rings_to_vectors(将ring与qvector关联, 一个qvector可以匹配多个ring)
    ixgbevf_request_irq
        ixgbevf_request_msix_irqs(根据ixbevf_probe阶段分配的msix_entry->vector中断号信息,通过request_irq注册中断处理                                                           函数ixgbevf_msix_clean_rings)                                
    ixgbevf_up_complete(enable irq,enable tx、rq queue)

 

3、收包流程:

1)、驱动在ixgbevf_setup_all_rx_resources里为每个vring分配描述符信息以及rx_buffer_info信息;
2)、ixgbevf_configure_rx里将每个ring的描述符信息通知给硬件使用;
3)、ixgbevf_alloc_rx_buffers为每个ring的描述符信息分配内存信息(硬件使用);
4)、硬件收到报文后,通过DMA控制器,将实际报文填充到ring的描述符里指定的dma地址;
5)、硬件触发中断;
6)、ixgbevf驱动进入中断处理流程ixgbevf_msix_clean_rings;
7)、中断处理函数里将qvector的napi添加到softnet_data的pool_list里;然后触发软中断;
8)、在软中断处理函数net_rx_action里进入napi的pool函数ixgbevf_poll轮询收取报文;
9)、ixgbevf_poll里进入ixgbevf_clean_rx_irq,根据rx_ring->next_to_clean获得下一个待清理的描述符;清理前首先判断该描             述符硬件是否已经使用过;硬件如果使用了描述符,会将描述符标志置位IXGBE_RXD_STAT_DD状态;如果硬件确实已             经使用了改描述符,则通过ixgbevf_fetch_rx_buffer获取描述符里的buffer信息,并填充到skb中;
10)、rx描述符的报文取出后,判断描述指定的page信息是否可重复使用;如果可以,则将该描述符指定的DMA内存信息分配             给rx_ring->next_to_alloc标识的下一个待分配的描述符中;
11)、通过ixgbevf_rx_skb将收到的skb信息加到softnet_data的input_pkt_queue队列中;并将softnet_data的napi                               (sd->backlog)加到softnet_data的poll_list里,再次触发软中断;
12)、软中断处理函数net_rx_action里进入napi的pool函数process_backlog;
13)、process_backlog里获取softnet_data的input_pkt_queue队列的数据包;并通过__netif_receive_skb送到dev设备;

4、发包流程:

1)、在ixgbevf_setup_all_tx_resources里为每个ring分配tx描述符信息;
2)、协议栈有报文发送时,最终会调用到ixgbevf_xmit_frame;
3)、ixgbevf_xmit_frame获取上层协议栈选定的tx_ring信息,然后根据tx_ring->next_to_use标识获取下一个待使用tx_desc(假           设为tx_desc0)以及tx_buffer_info信息;
4)、进入ixgbevf_tx_map,首先将skb->data包数据内容做DMA映射,并将返回的DMA内存地址及长度信息先保存在                           tx_buffer_info中;
5)、将数据包的DMA地址信息、长度填充到tx_desc中(当skb存在flag信息时,可能会需要使用多个描述符信息,假设最好使             用的是tx_desc_i);
6)、将tx_buffer_info的next_to_watch指定为本次填充的第一个描述符tx_desc0;
7)、更新tx_ring->next_to_use下一个待使用的描述符;
8)、将tx_ring->tail更新为tx_desc_i,并通知硬件(硬件需要将缓存的数据包发送,直到第i个描述符为止);
9)、硬件通过DMA控制器,将内存信息取走后,通过中断通知驱动,当驱动收到中断时,进入ixgbevf_poll;
10)、在ixgbevf_poll里通过ixgbevf_clean_tx_irq清理tx队列;
11)、首先根据tx_ring->next_to_clean获取待清理的tx_buffer,以及需要清理的下一个描述符tx_desc;然后根据                                 tx_buffer->next_to_watch获取本次待清理的最后一个tx描述符eop_desc(因为在发送的时候,skb有flag时,每次可能会               使用多个tx描述符);
12)、判断tx_desc描述符状态是否为IXGBE_TXD_STAT_DD(如果硬件已经将报文取走发送出去,则会将描述符置位DD状               态);如果是,则循环获取描述符释放对应的DMA内存释放,直到tx_desc描述符等于本次需要清理的最后一个描述符                 eop_desc为止,将tx_buffer->next_to_watch置空,表示该tx_buffer没有需要清理的描述符了;

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值