我正在使用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/

10-11 09:03