Ядро 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

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

Я использую ядро версии 2.6.38-11 - общий SMP (Kubuntu 11.04, x86_64) на двухъядерном процессоре Intel Pentium (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.

Ответы на вопрос(2)

Ваш ответ на вопрос