To: linux-m68k@lists.linux-m68k.org
Subject: L68K: Race condition in ataflop.c (again)
X-Yow: If elected, Zippy pledges to each and every American
 a 55-year-old houseboy...
From: Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
Date: 19 Jan 1998 10:53:50 +0100
Sender: owner-linux-m68k@phil.uni-sb.de

Here is another attempt to fix the race condition in the Atari floppy
driver, but i think this time i got it right.  But then, you won't know
for sure until it happens again. :-(

Andreas.

--- linux-2.1.79/drivers/block/ataflop.c.~2~	Thu Jan 15 00:50:17 1998
+++ linux-2.1.79/drivers/block/ataflop.c	Sun Jan 18 10:34:20 1998
@@ -395,6 +395,7 @@
 static void fd_rwsec( void );
 static void fd_readtrack_check( unsigned long dummy );
 static void fd_rwsec_done( int status );
+static void fd_rwsec_done1(int status);
 static void fd_writetrack( void );
 static void fd_writetrack_done( int status );
 static void fd_times_out( unsigned long dummy );
@@ -1002,7 +1003,6 @@
 
 	del_timer( &readtrack_timer );
 
-#if 0
 	if (!MultReadInProgress) {
 		/* This prevents a race condition that could arise if the
 		 * interrupt is triggered while the calling of this timer
@@ -1013,7 +1013,6 @@
 		restore_flags(flags);
 		return;
 	}
-#endif
 
 	/* get the current DMA address */
 	/* ++ f.a. read twice to avoid being fooled by switcher */
@@ -1036,6 +1035,7 @@
 		 * the read operation
 		 */
 		SET_IRQ_HANDLER( NULL );
+		MultReadInProgress = 0;
 		restore_flags(flags);
 		DPRINT(("fd_readtrack_check(): done\n"));
 		FDC_WRITE( FDCREG_CMD, FDCCMD_FORCI );
@@ -1044,7 +1044,7 @@
 		/* No error until now -- the FDC would have interrupted
 		 * otherwise!
 		 */
-		fd_rwsec_done( 0 );
+		fd_rwsec_done1(0);
 	}
 	else {
 		/* not yet finished, wait another tenth rotation */
@@ -1058,16 +1058,20 @@
 
 static void fd_rwsec_done( int status )
 {
-	unsigned int track;
-
 	DPRINT(("fd_rwsec_done()\n"));
 
 	if (read_track) {
+		del_timer(&readtrack_timer);
 		if (!MultReadInProgress)
 			return;
-		del_timer( &readtrack_timer );
 		MultReadInProgress = 0;
 	}
+	fd_rwsec_done1(status);
+}
+
+static void fd_rwsec_done1(int status)
+{
+	unsigned int track;
 
 	STOP_TIMEOUT();
 	
