Ядро Linux: udelay () возвращается слишком рано?

У меня есть драйвер, который требует микросекундных задержек. Чтобы создать эту задержку, мой драйвер использует функцию ядра udelay. В частности, там это один вызов 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

У нас были проблемы с надежностью устройства. После долгой отладки мы отследили проблему до возобновления работы драйвера до того, как прошло 90 мкс (см. «доказательство» ниже.)

Я использую ядро ​​версии 2.6.38-11-generic SMP (Kubuntu 11.04, x86_64) на Intel Pentium Dual Core (E5700).

Насколько мне известно, в документации указано, что udelay будет задерживать выполнение на по крайней мере на указанную задержку и является бесперебойным. Есть ли ошибка в этой версии ядра, или я неправильно понял использование udelay?


Чтобы убедить себя, что проблема вызвана слишком ранним возвратом udelay, мы подали частоту 100 кГц на один из порты ввода-вывода и реализовали нашу собственную задержку следующим образом:

// 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;
            }
        }
    }
}

... и драйвер теперь работает безупречно.


В качестве последнего примечания, я обнаружил обсуждение , указывающее на то, что масштабирование частоты могло приводить к неправильному функционированию семейства функций * delay (), но это было в списке рассылки ARM - я предполагал, что такие проблемы будут не существовать на ПК на базе Linux x86.

6
задан tan-ce 2 December 2011 в 07:00
поделиться