m68k: amiflop - Get rid of sleep_on calls
Apart from sleep_on() calls that could be easily converted to wait_event() and completion calls amiflop also used a flag in ms_delay() and ms_isr() as a custom mutex for ms_delay() without a need for explicit unlocking. I converted that to a standard mutex. The replacement for the unconditional sleep_on() in fd_motor_on() is a complete_all() together with a INIT_COMPLETION() before the mod_timer() call. It appears to me that fd_motor_on() might be called concurrently and fd_select() does not guarantee mutual exclusivity in the case the same drive gets selected again. Signed-off-by: Andreas Bombe <aeb@debian.org> Acked-by: Jörg Dorchain <joerg@dorchain.net> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
This commit is contained in:
Родитель
dc8ee69c76
Коммит
6d0be946e1
|
@ -156,7 +156,7 @@ static volatile int fdc_busy = -1;
|
||||||
static volatile int fdc_nested;
|
static volatile int fdc_nested;
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
|
static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
|
||||||
|
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(motor_wait);
|
static DECLARE_COMPLETION(motor_on_completion);
|
||||||
|
|
||||||
static volatile int selected = -1; /* currently selected drive */
|
static volatile int selected = -1; /* currently selected drive */
|
||||||
|
|
||||||
|
@ -184,8 +184,7 @@ static unsigned char mfmencode[16]={
|
||||||
static unsigned char mfmdecode[128];
|
static unsigned char mfmdecode[128];
|
||||||
|
|
||||||
/* floppy internal millisecond timer stuff */
|
/* floppy internal millisecond timer stuff */
|
||||||
static volatile int ms_busy = -1;
|
static DECLARE_COMPLETION(ms_wait_completion);
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(ms_wait);
|
|
||||||
#define MS_TICKS ((amiga_eclock+50)/1000)
|
#define MS_TICKS ((amiga_eclock+50)/1000)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -211,8 +210,7 @@ static int fd_device[4] = { 0, 0, 0, 0 };
|
||||||
|
|
||||||
static irqreturn_t ms_isr(int irq, void *dummy)
|
static irqreturn_t ms_isr(int irq, void *dummy)
|
||||||
{
|
{
|
||||||
ms_busy = -1;
|
complete(&ms_wait_completion);
|
||||||
wake_up(&ms_wait);
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,19 +218,17 @@ static irqreturn_t ms_isr(int irq, void *dummy)
|
||||||
A more generic routine would do a schedule a la timer.device */
|
A more generic routine would do a schedule a la timer.device */
|
||||||
static void ms_delay(int ms)
|
static void ms_delay(int ms)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
int ticks;
|
int ticks;
|
||||||
|
static DEFINE_MUTEX(mutex);
|
||||||
|
|
||||||
if (ms > 0) {
|
if (ms > 0) {
|
||||||
local_irq_save(flags);
|
mutex_lock(&mutex);
|
||||||
while (ms_busy == 0)
|
|
||||||
sleep_on(&ms_wait);
|
|
||||||
ms_busy = 0;
|
|
||||||
local_irq_restore(flags);
|
|
||||||
ticks = MS_TICKS*ms-1;
|
ticks = MS_TICKS*ms-1;
|
||||||
ciaa.tblo=ticks%256;
|
ciaa.tblo=ticks%256;
|
||||||
ciaa.tbhi=ticks/256;
|
ciaa.tbhi=ticks/256;
|
||||||
ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
|
ciaa.crb=0x19; /*count eclock, force load, one-shoot, start */
|
||||||
sleep_on(&ms_wait);
|
wait_for_completion(&ms_wait_completion);
|
||||||
|
mutex_unlock(&mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,8 +250,7 @@ static void get_fdc(int drive)
|
||||||
printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
|
printk("get_fdc: drive %d fdc_busy %d fdc_nested %d\n",drive,fdc_busy,fdc_nested);
|
||||||
#endif
|
#endif
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
while (!try_fdc(drive))
|
wait_event(fdc_wait, try_fdc(drive));
|
||||||
sleep_on(&fdc_wait);
|
|
||||||
fdc_busy = drive;
|
fdc_busy = drive;
|
||||||
fdc_nested++;
|
fdc_nested++;
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
@ -330,7 +325,7 @@ static void fd_deselect (int drive)
|
||||||
static void motor_on_callback(unsigned long nr)
|
static void motor_on_callback(unsigned long nr)
|
||||||
{
|
{
|
||||||
if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
|
if (!(ciaa.pra & DSKRDY) || --on_attempts == 0) {
|
||||||
wake_up (&motor_wait);
|
complete_all(&motor_on_completion);
|
||||||
} else {
|
} else {
|
||||||
motor_on_timer.expires = jiffies + HZ/10;
|
motor_on_timer.expires = jiffies + HZ/10;
|
||||||
add_timer(&motor_on_timer);
|
add_timer(&motor_on_timer);
|
||||||
|
@ -347,11 +342,12 @@ static int fd_motor_on(int nr)
|
||||||
unit[nr].motor = 1;
|
unit[nr].motor = 1;
|
||||||
fd_select(nr);
|
fd_select(nr);
|
||||||
|
|
||||||
|
INIT_COMPLETION(motor_on_completion);
|
||||||
motor_on_timer.data = nr;
|
motor_on_timer.data = nr;
|
||||||
mod_timer(&motor_on_timer, jiffies + HZ/2);
|
mod_timer(&motor_on_timer, jiffies + HZ/2);
|
||||||
|
|
||||||
on_attempts = 10;
|
on_attempts = 10;
|
||||||
sleep_on (&motor_wait);
|
wait_for_completion(&motor_on_completion);
|
||||||
fd_deselect(nr);
|
fd_deselect(nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,8 +578,7 @@ static void raw_read(int drive)
|
||||||
{
|
{
|
||||||
drive&=3;
|
drive&=3;
|
||||||
get_fdc(drive);
|
get_fdc(drive);
|
||||||
while (block_flag)
|
wait_event(wait_fd_block, !block_flag);
|
||||||
sleep_on(&wait_fd_block);
|
|
||||||
fd_select(drive);
|
fd_select(drive);
|
||||||
/* setup adkcon bits correctly */
|
/* setup adkcon bits correctly */
|
||||||
custom.adkcon = ADK_MSBSYNC;
|
custom.adkcon = ADK_MSBSYNC;
|
||||||
|
@ -598,8 +593,7 @@ static void raw_read(int drive)
|
||||||
|
|
||||||
block_flag = 1;
|
block_flag = 1;
|
||||||
|
|
||||||
while (block_flag)
|
wait_event(wait_fd_block, !block_flag);
|
||||||
sleep_on (&wait_fd_block);
|
|
||||||
|
|
||||||
custom.dsklen = 0;
|
custom.dsklen = 0;
|
||||||
fd_deselect(drive);
|
fd_deselect(drive);
|
||||||
|
@ -616,8 +610,7 @@ static int raw_write(int drive)
|
||||||
rel_fdc();
|
rel_fdc();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (block_flag)
|
wait_event(wait_fd_block, !block_flag);
|
||||||
sleep_on(&wait_fd_block);
|
|
||||||
fd_select(drive);
|
fd_select(drive);
|
||||||
/* clear adkcon bits */
|
/* clear adkcon bits */
|
||||||
custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
|
custom.adkcon = ADK_PRECOMP1|ADK_PRECOMP0|ADK_WORDSYNC|ADK_MSBSYNC;
|
||||||
|
@ -1294,8 +1287,7 @@ static int non_int_flush_track (unsigned long nr)
|
||||||
writepending = 0;
|
writepending = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
while (block_flag == 2)
|
wait_event(wait_fd_block, block_flag != 2);
|
||||||
sleep_on (&wait_fd_block);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
local_irq_restore(flags);
|
local_irq_restore(flags);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче