从旧的init_timer适应新的timer_setup [英] Adaptation from old init_timer to new timer_setup

查看:4404
本文介绍了从旧的init_timer适应新的timer_setup的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试将驱动程序从2.6移植到4.n,而没有原始板制造商的支持(并且Linux经验非常有限).

I have been trying to port a driver from 2.6 to 4.n without support from the original board manufacturer (and very limited Linux experience).

原始驱动程序使用init_timer()并传入指向timer_list结构的指针.该timer_list结构的data元素设置为指向另一个内存结构的指针,而'function'元素设置为该回调.在回调函数中,data元素用于访问其他内容.

The original driver uses init_timer() and passes in a pointer to the timer_list structure. That timer_list structure's data element was set to a pointer to another memory structure and the 'function' element set to the callback. Inside the callback function the data element was used to access other bits of stuff.

当前的计时器init方法使用

The current timer init method uses

timer_setup( timer_list *, callback, (unsigned int) flags);

并且timer_list结构已更改,以消除data字段.

and the timer_list structure has changed to eliminate the data field.

我不确定通知等效的data元素的回调函数的最佳/正确方法是什么.谁能提供一些指导?

I'm not sure what is the best/proper way to inform the callback function of the equivalent data element. Can anyone provide some guidance?

这是旧驱动程序的摘要:

Here is a snippet of the old driver:

myDevice * dev;

dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);    
init_timer(dev->getIntrTimer);

dev->getIntrTimer->data = (unsigned long) dev;
dev->getIntrTimer->function = GetIntrTimerCallback;

这样的回调函数开始:

void GetIntrTimerCallback(unsigned long devAddr)
{
    myDevice *dev = (myDevice *) devAddr;
    dev->blahBlah++; // etc.

因此,旧代码将指针传递给myDevice,以便在回调内部可以访问该结构.

So the old code gets passed the pointer to myDevice so inside the callback that structure can be accessed.

但是使用新的timer方法时,只能使用一个4字节的int,但一个指针是8(或任何其他值).

But with the new timer method only has available an int that is 4 bytes but a pointer is 8 (or whatever).

我想做的是这样

dev->getIntrTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
timer_setup(dev->getIntrTimer, GetIntrTimerCallback, dev);

但是当然会产生编译错误,因为dev是一个类型为myDevice的指针,该指针不适合int.

but of course that generates compile errors because dev is a pointer to type myDevice, which does not fit in an int.

推荐答案

从4.14 Linux内核开始存在带有三个args的timer_setup()(仅供参考,在稍早的版本中就有setup_timer()).如果您维护一些与最新内核相关的代码,则每次API更改时都必须以适当的方式对其进行更改.现在,您可以基于 container_of() .

The timer_setup() with three args is present since 4.14 Linux kernel (FYI there was setup_timer() in slightly earlier versions). If you maintain some code which should be relevant up to recent kernels - you have to change it in appropriate way every time the API changes. Now you can access your data through the special function from_timer() based on container_of().

timer_list通常不用作struct内部的指针,因此该示例暗示正常用法,并且可能类似于:

timer_list is normally used not as pointer inside struct, so the example implies normal usage and could be something like:

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
    init_timer(&dev->getIntrTimer);
    dev->getIntrTimer.data = (unsigned long) dev;
    dev->getIntrTimer.function = GetIntrTimerCallback;
    /* ... */
    add_timer(&dev->getIntrTimer);
#else
    timer_setup(&dev->getIntrTimer, GetIntrTimerCallback, 0);
    /* the third argument may include TIMER_* flags */
    /* ... */
#endif


回调函数:


The callback function:

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0)
void GetIntrTimerCallback(unsigned long devAddr)
{
    myDevice *dev = (myDevice *) devAddr;
#else
void GetIntrTimerCallback(struct timer_list *t)
{
    myDevice *dev = from_timer(dev, t, getIntrTimer);
#endif
    /* Do something with "dev" */

另请参阅:

  • Linux kernel timers new API
  • Example
  • Linux kernel versions

这篇关于从旧的init_timer适应新的timer_setup的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆