Linux Kernel: ¿udelay () regresa demasiado temprano?

Tengo un controlador que requiere retrasos de microsegundos. Para crear este retraso, mi controlador está utilizando la función udelay del núcleo. Específicamente, hay una llamada a 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

Tuvimos problemas de confiabilidad con el dispositivo. Después de mucha depuración, rastreamos el problema hasta que el controlador se reanudó antes de que 90us pasara. (Ver "prueba" a continuación).

Estoy ejecutando el kernel versión 2.6.38-11-SMP genérico (Kubuntu 11.04, x86_64) en un Intel Pentium Dual Core (E5700).

asta donde yo sé, la documentación indica que udelay retrasará la ejecución deal meno el retraso especificado, y es ininterrumpible. @ ¿Hay algún error en esta versión del kernel o no he entendido bien algo sobre el uso de udelay?

ara convencernos de que el problema fue causado por el udelay que regresó demasiado temprano, alimentamos un reloj de 100 kHz a uno de los puertos de E / S e implementamos nuestro propio retraso de la siguiente manera:

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

... y el controlador ahora funciona perfectamente.

omo nota final, encontréuna discusió indicando que el escalado de frecuencia puede estar causando que la familia de funciones * delay () se comporte mal, pero esto estaba en una lista de correo ARM - Supongo que tales problemas serían inexistentes en una PC con Linux x86.

Respuestas a la pregunta(4)

Su respuesta a la pregunta