环境
BCM6756驱动程序。
驱动初始化
源码路径:
bcmdrivers/opensource/net/enet/impl7/
以下为BCM网卡驱动初始化的概要。初始化工作主要在bcm_enet_init_post函数中,该驱动适配了支持设备树和不支持设备树两种,不支持设备树的情况下,bcm_enet_init直接调用bcm_enet_init_post完成网卡驱动的初始化。
bcm_enet_init();
/* 注册网卡设备(设备树),在prob函数中调用bcm_enet_init_post */
register_enet_platform_device();
bcm_enet_init_post();
phy_drivers_init(); /* PHY 驱动初始化 */
sw_init(); /* switch 初始化,BCM这里把BCM6756自带的网卡也初始化为switch */
enet_create_netdevice(); /* 创建网络设备 */
port_init(); /* port 初始化 */
enetxapi_queues_init();
init_waitqueue_head (&chan->rxq_wqh); /* 初始化接收事件chan->rxq_wqh */
kthread_run(chan_thread_handler, chan, "bcmsw_rx"); /* 创建内核线程(接收数据) */
cpu_queues_init(); /*初始化队列,并创建数据包回收线程bcmsw_recycle */
archer_enet_host_bind(); /* 注册硬件驱动相关内容,如:中断回调 */
网卡驱动接收函数调用关系
下图主要展现了chan_thread_handler函数调用关系图。硬件驱动接收程序不可见,回调由archer_driver_host_bind函数注册。
- chan_thread_handler是一个内核线程,由硬件中断程序驱动。在enetx_rx_isr中会唤醒等待队列。
- mux_port_rx是一个回调函数,指向驱动程序mux_index.c文件的mux_get_rx_index函数。
- 加速失败后rx_skb会通过skb_header_alloc分配sk_buff结构,将fkb转化成skb接收,用于后续处理。
- fkb是BCM中驱动数据缓存器,是一块DMA内存,用于底层驱动和加速使用。
static inline int rx_pkt(enetx_channel *chan, int budget)
{
int i, rc , count;
/* Receive up to budget packets while Iterating over queues in channel by priority */
for (count = 0, i = 0; i < chan->rx_q_count && count < budget; i++)
{
rc = rx_pkt_from_q(chan->rx_q[i], budget - count);
count += rc;
/*do not continue process an empty queue*/
if(rc == 0)
continue;
}
return count;
}
- chan->rx_q_count表示接收队列大小,chan->rx_q[]表示接收队列。该参数enetxapi_queues_init函数中初始化。chan->rx_q_count为NUM_RX_QUEUES(2),一个高速队列一个低速队列。先处理高速队列。这里使用NAPI,因为线程是有时间片的,处理过程会超时,这里可以理解为中断下半部。