linux kernel 工程师
全部博文(99)
分类: LINUX
2014-02-10 11:33:54
当需要对本设备进行poll的时候,调用__napi_schedule 将设备的napi 的poll_list 挂在每cpu变量 softnet_data的poll_list下面。
在net_rx_action函数中, 会轮讯softnet_data的poll_list,即调用设备的napi->poll 函数。
/* Called with irq disabled */
static inline void ____napi_schedule(struct softnet_data *sd,
struct napi_struct *napi)
{
list_add_tail(&napi->poll_list, &sd->poll_list); /* napi 的poll_list 挂在 softnet_data的poll_list */
__raise_softirq_irqoff(NET_RX_SOFTIRQ); /* 触发softirq,rangsoftirq来执行poll 函数 */}
/**
* __napi_schedule - schedule for receive
* @n: entry to schedule
*
* The entry's receive function will be scheduled to run
*/
void __napi_schedule(struct napi_struct *n) /* 对____napi_schedule进行了一层封装,主要是关闭中断 */
{
unsigned long flags;
local_irq_save(flags);
____napi_schedule(&__get_cpu_var(softnet_data), n);
local_irq_restore(flags);
}
EXPORT_SYMBOL(__napi_schedule);
/**
* napi_schedule - schedule NAPI poll
* @n: napi context
*
* Schedule NAPI poll routine to be called if it is not already
* running.
*/
static inline void napi_schedule(struct napi_struct *n)
{
if (napi_schedule_prep(n)) /* 判断是否可以调度 */
__napi_schedule(n);
}
/**
* napi_schedule_prep - check if napi can be scheduled
* @n: napi context
*
* Test if NAPI routine is already running, and if not mark
* it as running. This is used as a condition variable
* insure only one NAPI poll instance runs. We also make
* sure there is no pending NAPI disable.
*/
static inline bool napi_schedule_prep(struct napi_struct *n)
{
return !napi_disable_pending(n) && /* 没有disable */
!test_and_set_bit(NAPI_STATE_SCHED, &n->state); /* not running */
}