Freut mich, dass das Problem jetzt wohl behoben ist!
Zur technischen erläuterung:
sowohl das LCD als auch die CF/IDE-Umschaltung hängen an einem GPIO port. Im kernel findet sich folgendes:
|
Source code
|
1
2
3
4
5
6
7
8
9
10
11
12
|
static inline void gpio_set(int dev, unsigned int mask, int value)
{
if (value)
SETREG_REGMM32(GPIOA_DATA, GETREG_REGMM32(GPIOA_DATA) | mask);
else
SETREG_REGMM32(GPIOA_DATA, GETREG_REGMM32(GPIOA_DATA) & ~mask);
}
static inline void dreambox_set_ide_bus(int bus)
{
gpio_set(GPIO_CF_ACC, !bus);
}
|
Im LCD treiber gibts dann grob gesehen
|
Source code
|
1
2
3
4
5
6
7
|
static inline void setCLK(int clk)
{
if (value)
SETREG_REGMM32(GPIOA_DATA, GETREG_REGMM32(GPIOA_DATA) | LCD_CLK);
else
SETREG_REGMM32(GPIOA_DATA, GETREG_REGMM32(GPIOA_DATA) & ~LCD_CLK);
}
|
dreambox_set_ide_bus wird durchaus im Interrupt aufgerufen (nämlich wenn z.b. der letzte festplatten-Transfer fertig ist, und der nächste Transfer zur CF-Karte geht).
Der LCD-Treiber wird ausnahmslos aus dem Userspace aufgerufen (der write-Handler vom LCD-Device).
setCLK liest den alten register-wert, ORt bzw. ANDed das CLK-bit rein/raus, und schreibt es dann zurück. Nun kann unter (wohl nicht allzu seltenen umständen) es passieren, dass das register gelesen wird, das bit geändert wird - und dann aber ein CF-interrupt passiert, wo der bus umgeschaltet wird. Dort wird also das register (welches ja noch nicht im LCD-Treiber geschrieben wurde) gelesen, das CF-bit verändert, geschrieben, und dann aus dem interrupt zurückgekehrt, wo der lcd treiber seine arbeit fortsetzt, und den vorher berechneten register-inhalt schreibt - tja, leider geht dann die änderung aus dem IDE-treiber verloren.
Ein paar dringend benötigte spinlocks (bzw. interrupt-sperren, mehr bleibt auf UP davon ja nicht übrig) haben das problem behoben.