首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将NAPI轮询函数卸载到工作队列

如何将NAPI轮询函数卸载到工作队列
EN

Stack Overflow用户
提问于 2015-06-08 08:30:46
回答 2查看 1.1K关注 0票数 1

我正在使用Linux3.3,这是smsc911x的以太网驱动程序。我想把NAPI投票函数移到工作队列中。

我的问题是:

  1. 如何将NAPI民意测验函数参数传递给work_struct?
  2. 如何从work_struct中获取NAPI民意测验函数参数?(与上文Q.1有关)
  3. 如何将npackets值返回到原始NAPI轮询函数调用方?

以下是一些解释:

当前的NAPI轮询功能直接读取recevie,这是我想要改变的,用DMA控制器来完成。对于这个DMA,我触发DMA,使用wait_event_interruptible睡觉,然后被DMA的ISR与wake_up_interruptible唤醒。如您所知,NAPI轮询功能处于中断上下文(softirq)中,因此我无法在那里睡觉以完成DMA。我希望将NAPI轮询函数(读取RX )移动到使用work_struct的等待队列(进程上下文)。

问题是,NAPI轮询函数是由内核使用两个参数调用的: struct napi_struct *napi和int预算。我希望将这些参数传递给work_struct,并将work_struct排队到工作队列(使用queue_work函数)。

work_struct看起来如下所示。(包括/linux/workQuee.h)

代码语言:javascript
复制
struct work_struct { 
        atomic_long_t data;
        struct list_head entry; 
        work_func_t func;
#ifdef CONFIG_LOCKDEP
        struct lockdep_map lockdep_map;
#endif
};

我认为atomic_long_t数据是用来将参数传递给work_struct的。如何将参数传递给work_struct?我尝试过这样做(我在用于设备驱动程序struct smsc911x_data的结构中添加了用于传递工作的成员struct work_struct rx_work ):

代码语言:javascript
复制
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;
}

对于上面的“此行”,我在编译过程中会出错。

代码语言:javascript
复制
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.

此外,在新的工作函数中,如何提取原始论证?我在下面试了一下,这会给我带来错误。

代码语言:javascript
复制
/* 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”没有名为“预算”的成员

我不知道如何将返回值传递给原始的NAPI投票函数调用者。

我不确定这种转换(从NAPI投票到工作队列)是否可行。很抱歉有这么长的问题,但是如果有任何帮助,我们将不胜感激。

添加:因为struct smsc911x_data同时具有struct work_struct rx_work和struct work_struct rx_work;作为成员,我可以通过以下方法轻松地从work_struct *work (工作函数的参数)中获得struct *rx_work:

struct smsc911x_data *pdata = container_of(work,struct smsc911x_data,rx_work);struct napi_struct *pdata= &pdata.napi;

所以,也许我可以在struct smsc911x_data中通过一个新的成员值来传递int预算。我很想知道这个案子的正确做法。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-06-08 09:18:06

  1. 如何将NAPI民意测验函数参数传递给work_struct?

只需创建新结构,该结构嵌入work_struct并将参数添加到其中:

代码语言:javascript
复制
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;
    ...
}

  1. 如何从work_struct中获取NAPI民意测验函数参数?(与上文Q.1有关)

使用container_of

代码语言:javascript
复制
static int smsc911x_poll_work(struct work_struct *work) {
    struct my_work* p = container_of(work, struct my_work, base_work);
    ...
}

  1. 如何将npackets值返回到原始NAPI轮询函数调用方?

正如我从描述(例如,http://www.linuxfoundation.org/collaborate/workgroups/networking/napi)中了解到的那样,这个函数应该处理已准备好的数据包。这个处理应该在函数本身内完成,而不是推迟到workqueue或类似的。

票数 1
EN

Stack Overflow用户

发布于 2018-10-23 11:36:08

这种方法看起来非常无效,因为您需要两次中断,一次是在接收数据包时,另一次是在DMA tansfer完成时。

我认为这是DMA网络接口的工作方式:当数据包到达时,套接字缓冲区已经被分配并映射到DMA内存缓冲区中,DMA被启动。

  1. 数据包通过DMA从网卡传送到套接字缓冲区。
  2. NIC会引发硬件中断(当DMA传输完成时)。
  3. 硬件中断处理程序调度数据包接收软件中断(SOFTIRQ)
  4. SOFTIRQ为进一步处理进行NAPI轮询()。
  5. NAPI轮询()处理DMA缓冲区中的数据包,并将其作为sk_buff传递到上层,并初始化新的DMA缓冲区。如果处理了所有数据包(配额),则启用IRQ,并通知NAPI停止轮询。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30704408

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档