Ho un driver che richiede ritardi al microsecondo. Per creare questo ritardo, il mio driver sta usando la funzione udelay del kernel. Nello specifico, c'è una chiamata a udelay (90):Kernel Linux: udelay() restituisce troppo presto?
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
Abbiamo riscontrato problemi di affidabilità con il dispositivo. Dopo un sacco di debug, abbiamo rintracciato il problema alla ripresa del driver prima che sia passato 90 secondi. (Vedere "prova" di seguito.)
Sto eseguendo la versione del kernel 2.6.38-11 SMP generico (Kubuntu 11.04, x86_64) su un Intel Pentium Dual Core (E5700).
Per quanto ne so, la documentazione afferma che udelay ritarderà l'esecuzione di almeno il ritardo specificato ed è ininterrotta. C'è un bug in questa versione del kernel o ho frainteso qualcosa sull'uso di udelay?
Per convincerci che il problema è stato causato da udelay ritorno troppo presto, abbiamo alimentato un orologio 100kHz a una delle porte di I/O e implementato il nostro ritardo come segue:
// 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;
}
}
}
}
... e l'autista ora funziona perfettamente.
Come nota finale, ho trovato a discussion che indica che l'adattamento della frequenza potrebbe essere la causa della famiglia * ritardo() di funzioni a comportarsi male, ma questo era su un braccio mailing list - ho ammesso questi problemi sarebbe non- esistente su un PC Linux x86.
Lo proverò e tornerò da te. Solo così ho capito bene, ogni core ha il suo TSC, quindi se il processo che il mio driver sta servendo è stato ripianificato su un'altra CPU, il TSC potrebbe non essere lo stesso? Inoltre, ho capito correttamente che X86_FEATURE_CONSTANT_TSC significa che il TSC della CPU è stabile indipendentemente dal ridimensionamento della frequenza e X86_FEATURE_NONSTOP_TSC significa che il TSC non smetterà mai di contare? Se è così, quando si fermerebbe una CPU è TSC? –
Il TSC può arrestarsi durante alcuni [Stati C] (http://en.wikipedia.org/wiki/Advanced_Configuration_and_Power_Interface#Processor_states). –
Il [codice di ritardo basato su TSC] (http://lxr.linux.no/#linux+v2.6.38/arch/x86/lib/delay.c#L51) rappresenta correttamente lo spostamento tra le CPU durante il ritardo. L'interruzione del TSC durante il ritardo non farebbe che ritardare * più a lungo *, non * più corto *, quindi neanche questo è il problema. – caf