Ядро Linux: udelay () возвращает слишком рано? - PullRequest
6 голосов
/ 02 декабря 2011

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

3 голосов
/ 05 декабря 2011

Я не знаю ни одной ошибки в этой версии ядра (но это не значит, что ее нет).

udelay() не является "бесперебойной" - она ​​делаетНе отключайте выгрузку, поэтому ваша задача может быть прервана заданием RT во время задержки.Однако то же самое относится и к вашей альтернативной реализации задержки, так что это вряд ли будет проблемой.

Может ли быть вашей реальной проблемой проблема с последовательностью DMA / упорядочением памяти?Ваша альтернативная реализация задержки обращается к шине, так что это может скрывать реальную проблему как побочный эффект.

2 голосов
/ 03 декабря 2011

E5700 имеет X86_FEATURE_CONSTANT_TSC, но не X86_FEATURE_NONSTOP_TSC. TSC является вероятным источником синхронизации для udelay. Если вы не привязаны к одному из ядер с маской сходства, ваша задача может быть прервана и перенесена на другой процессор во время udelay. Или TSC может быть нестабильным в режимах процессора с низким энергопотреблением.

Можете ли вы попробовать отключить прерывания или отключить прерывание во время udelay? Также попробуйте прочитать TSC до и после.

...