本文介绍了Linux内核:udelay()返回为时过早吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个要求微秒延迟的驱动程序.为了产生这种延迟,我的驱动程序正在使用内核的udelay函数.具体来说,有一个调用udelay(90):

I have a driver which requires microsecond delays. To create this delay, my driver is using the kernel's udelay function. Specifically, there is one call to udelay(90):

iowrite32(data, addr + DATA_OFFSET);
iowrite32(trig, addr + CONTROL_OFFSET);

udelay(30);

trig |= 1;
iowrite32(trig, addr + CONTROL_OFFSET);

udelay(90); // This is the problematic call

我们的设备存在可靠性问题.经过大量调试,我们将问题追溯到驱动程序在90us过去之前恢复. (请参见下面的证明".)

We had reliability issues with the device. After a lot of debugging, we traced the problem to the driver resuming before 90us has passed. (See "proof" below.)

我正在Intel Pentium Dual Core(E5700)上运行内核版本2.6.38-11-generic SMP(Kubuntu 11.04,x86_64).

I am running kernel version 2.6.38-11-generic SMP (Kubuntu 11.04, x86_64) on an Intel Pentium Dual Core (E5700).

据我所知,文档指出udelay将至少延迟 指定的延迟执行,并且是不间断的. 此版本的内核是否存在错误,还是我对udelay的使用有误解?

As far as I know, the documentation states that udelay will delay execution for at least the specified delay, and is uninterruptible. Is there a bug is this version of the kernel, or did I misunderstand something about the use of udelay?

为使自己确信问题是由于udelay返回时间过早而引起的,我们将100kHz时钟馈送到一个I/O端口,并实现了自己的延迟,如下所示:

To convince ourselves that the problem was caused by udelay returning too early, we fed a 100kHz clock to one of the I/O ports and implemented our own delay as follows:

// Wait until n number of falling edges
// are observed
void clk100_delay(void *addr, u32 n) {
    int i;

    for (i = 0; i < n; i++) {
        u32 prev_clk = ioread32(addr);
        while (1) {
            u32 clk = ioread32(addr);
            if (prev_clk && !clk) {
                break;
            } else {
                prev_clk = clk;
            }
        }
    }
}

...驱动程序现在可以正常工作.

...and the driver now works flawlessly.

作为最后的说明,我发现了讨论,表明频率缩放可能是导致* delay()系列功能出现异常,但这在ARM邮件列表中-我假设在基于Linux x86的PC上将不存在此类问题.

As a final note, I found a discussion indicating that frequency scaling could be causing the *delay() family of functions to misbehave, but this was on a ARM mailing list - I assuming such problems would be non-existent on a Linux x86 based PC.

推荐答案

我不知道该版本内核中的任何错误(但这并不意味着没有错误).

I don't know of any bug in that version of the kernel (but that doesn't mean that there isn't one).

udelay()不是不间断的"-它不会禁用抢占,因此RT任务可以在延迟期间抢占您的任务.但是,您的备用延迟实现也是如此,因此这不太可能成为问题.

udelay() isn't "uninterruptible" - it does not disable preemption, so your task can be preempted by a RT task during the delay. However the same is true of your alternate delay implementation, so that is unlikely to be the problem.

您的实际问题可能是DMA一致性/内存排序问题吗?您的备用延迟实现会访问总线,因此这可能会将真正的问题隐藏为副作用.

Could your actual problem be a DMA coherency / memory ordering issue? Your alternate delay implementation accesses the bus, so this might be hiding the real problem as a side-effect.

这篇关于Linux内核:udelay()返回为时过早吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-10 08:58