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:
Andreas Bombe 2008-12-10 02:02:19 +01:00 коммит произвёл Geert Uytterhoeven
Родитель dc8ee69c76
Коммит 6d0be946e1
1 изменённых файлов: 16 добавлений и 24 удалений

Просмотреть файл

@ -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);