我正在使用Linux3.3,SMSC911X的以太网驱动程序。我想将NAPI轮询函数移到WorkQueue。
我的问题是:
一。如何将napi poll函数参数传递给work结构?
2.如何从work结构中获取napi poll函数参数?(与上述问题1有关)
三。如何将npackets值返回到原始napi poll函数调用方?
以下是一些解释:
当前的napi poll函数直接读取recvie fifo,我想更改它来使用dma控制器。对于这个dma,我触发dma,在wait-up事件可中断的情况下睡眠,然后在wake-up事件可中断的情况下被dma的isr唤醒。如您所知,napi poll函数位于中断上下文(softirq)中,因此我无法在那里睡眠以完成dma。我想将napi poll函数(读取rx fifo)移动到waitqueue(进程上下文)usnig a work结构。
问题是,napi poll函数是由内核用两个参数调用的:struct napi_struct*napi和int budget。
我想将这些参数传递给work结构并将work结构排队到work queue(使用queue-work函数)。
工作结构如下所示。(包括/linux/workqueue.h)
struct work_struct {
atomic_long_t data;
struct list_head entry;
work_func_t func;
#ifdef CONFIG_LOCKDEP
struct lockdep_map lockdep_map;
#endif
};
我认为原子长数据是用来将参数传递给工作结构的。如何将参数传递给工作结构?
我试过了(我在设备驱动程序结构smsc911x_data的结构中添加了一个成员结构work_struct rx_work以传递工作):
struct work_arg { // a new struct for pass the arguments
struct napi_struct *napi;
int budget;
};
/* NAPI poll function */
static int smsc911x_poll(struct napi_struct *napi, int budget) {
struct smsc911x_data *pdata =
container_of(napi, struct smsc911x_data, napi);
struct net_device *dev = pdata->dev;
int npackets = 0;
if (enable_rx_use_dma == 1) { // when using DMA for FIFO read
prom_printf("moving it to workqueue\n");
struct work_arg *p;
p = kzalloc(sizeof(struct work_arg), GFP_KERNEL);
p->napi = napi;
p->budget = budget;
pdata->rx_work.data = (atomic_long_t) p; // <== THIS LINE
prom_printf("queue work, with napi = %x, budget = %d\n", napi, budget);
queue_work(rx_work_workqueue, &pdata->rx_work); // smsc911x_poll_work } else {
-- original NAP poll function, reads FIFO until it's empty and enables the RX interrupt and
-- keeps the number of processed packets to npackets.
return npackets;
}
对于上面的“这一行”,我在编译过程中遇到错误。
with pdata->rx_work.data = p; , I get error: incompatible types when assigning to type 'atomic_long_t' from type 'struct work_arg *'
with pdata->rx_work.data = (atomic_long_t) p; , I get error: conversion to non-scalar type requested.
另外,在新的工作函数中,如何提取原始参数?我在下面试过了,结果出错了。
/* New work function called by the default worker thread */ static int smsc911x_poll_work(struct work_struct *work) {
struct smsc911x_data *pdata =
container_of(work, struct smsc911x_data, rx_work);
struct net_device *dev = pdata->dev;
int npackets = 0;
struct napi_struct *napi = (struct work_struct *)work->data.napi; // <== THIS LINE
int budget = (struct work_struct *)work->data.budget; // <== THIS LINE ..
}
从上面的“这条线”,我得到下面的错误。
错误:“atomic_long_t”没有名为“napi”的成员
错误:“atomic_long_t”没有名为“budget”的成员
我不知道如何将返回值传递给原始的napi poll functino调用方。
我不确定这种转换(从napi poll到workqueue)是否可行。
很抱歉问了这么长的问题,如果有任何帮助,我们将不胜感激。
附加:由于struct smsc911x_data同时具有struct napi napi;和struct work_struct rx_work;作为成员,我可以通过以下方法轻松地从work_struct*work(work函数的参数)获取struct napi*napi:
结构SMSC911X U数据*数据=
容器(work,struct smsc911x_data,rx_work);struct napi_struct*napi=&pdata.napi;
所以也许我可以通过structsm911x_数据中的一个新成员值来传递int预算。我想知道这个案子的正确做法。
最佳答案
如何将napi poll函数参数传递给work结构?
只需创建新结构,嵌入work_struct
并将参数添加到其中:
struct my_work {
struct work_struct base_work;// Embedded work_struct
struct napi_struct *napi; // Your arguments
int budget;
};
static int smsc911x_poll(struct napi_struct *napi, int budget) {
struct my_work* p = kmalloc(sizeof(*p), GFP_ATOMIC /* Flag usable for interrupt context */);
INIT_WORK(&p->base_work, smsc911x_poll_work); // Initialize underliying structure.
p->budget = budget; // Initialize your members
p->napi = napi;
...
}
如何从work结构中获取napi poll函数参数?(与上述问题1有关)
使用
container_of
:static int smsc911x_poll_work(struct work_struct *work) {
struct my_work* p = container_of(work, struct my_work, base_work);
...
}
如何将npackets值返回到原始napi poll函数调用方?
据我从描述中了解(参见,例如http://www.linuxfoundation.org/collaborate/workgroups/networking/napi),此函数应处理准备就绪的数据包。这种处理应该在函数本身内完成,而不应延迟到
workqueue
或类似的值。关于c - 如何将NAPI轮询功能卸载到工作队列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30704408/