Re: ATA driver races with interrupts

From: Søren Schmidt <sos_at_DeepCore.dk>
Date: Tue, 03 Aug 2004 10:40:06 +0200
Ville-Pertti Keinonen wrote:
> Søren Schmidt wrote:
> 
>> If the controller doesn't have a bit saying if the interrupt is for 
>> us, then its impossible to close the race completely (without the 
>> above measures in place). However some devices use the DMA interrupt 
>> bits even in PIO mode (ie HPT does this) but I have no docs on the 
>> VIA's on that, but its worth a try at least...
> 
> The current situation seems to me like ata_generic_intr can't work for 
> *any* controller sharing interrupts, even with DMA on a controller that 
> sets ATA_BMSTAT_INTERRUPT correctly, since if an interrupt occurs before 
> ATA_DMA_ACTIVE is set, ATA_BMSTAT_PORT is never even checked.

Oh, I dont mean the ATA_BMSTAT* bits, I mean real interrupt status bits 
in the controller that you can poll on interrupt to see what exactly 
caused the event (check the Promise support fx).

> IMHO ch->running != NULL is an insufficient condition based on which to 
> assume that an interrupt is intended for a specific channel...

It was newer meant for that purpose really, but checking it was a nice 
way of sorting of some trouble.

> Something similar to my patch + disabling interrupts to avoid a race 
> between the interrupt and ATA_EXPECT_INTR being set should at least 
> improve the situation.  What races would that leave open?

We dont want to disable interrupts, ever.

I have one change in a tree here that you could try, but as long as the 
hardware doesn't support proper interrupt status its impossible to close 
the race window completely. Please remember that this is part of a 
bigger patchset, so I might have edited it too much, YMMV,,


-- 
-Søren


Index: ata-lowlevel.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/ata/ata-lowlevel.c,v
retrieving revision 1.40
diff -u -r1.40 ata-lowlevel.c
--- ata-lowlevel.c	24 Jul 2004 19:03:28 -0000	1.40
+++ ata-lowlevel.c	3 Aug 2004 10:25:19 -0000
_at__at_ -80,9 +80,6 _at__at_
 	return ATA_OP_FINISHED;
     }
 
-    /* record the request as running */
-    ch->running = request;
-
     ATA_DEBUG_RQ(request, "transaction");
 
     /* disable ATAPI DMA writes if HW doesn't support it */
_at__at_ -139,7 +136,8 _at__at_
 	    }
 	}
 	
-	/* return and wait for interrupt */
+	/* record the request as running and return for interrupt */
+	ch->running = request;
 	return ATA_OP_CONTINUES;
 
     /* ATA DMA data transfer commands */
_at__at_ -168,7 +166,8 _at__at_
 	    break;
 	}
 
-	/* return and wait for interrupt */
+	/* record the request as running and return for interrupt */
+	ch->running = request;
 	return ATA_OP_CONTINUES;
 
     /* ATAPI PIO commands */
_at__at_ -192,8 +191,10 _at__at_
 	}
 
 	/* command interrupt device ? just return and wait for interrupt */
-	if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR)
+	if ((request->device->param->config & ATA_DRQ_MASK) == ATA_DRQ_INTR) {
+	    ch->running = request;
 	    return ATA_OP_CONTINUES;
+	}
 
 	/* wait for ready to write ATAPI command block */
 	{
_at__at_ -224,7 +225,8 _at__at_
 			   (request->device->param->config & ATA_PROTO_MASK) ==
 			   ATA_PROTO_ATAPI_12 ? 6 : 8);
 
-	/* return and wait for interrupt */
+	/* record the request as running and return for interrupt */
+	ch->running = request;
 	return ATA_OP_CONTINUES;
 
     case ATA_R_ATAPI|ATA_R_DMA:
_at__at_ -289,14 +291,14 _at__at_
 	    break;
 	}
 
-	/* return and wait for interrupt */
+	/* record the request as running and return for interrupt */
+	ch->running = request;
 	return ATA_OP_CONTINUES;
     }
 
     /* request finish here */
     if (ch->dma->flags & ATA_DMA_ACTIVE)
 	ch->dma->unload(ch);
-    ch->running = NULL;
     return ATA_OP_FINISHED;
 }
 
Received on Tue Aug 03 2004 - 06:40:19 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:38:04 UTC