|
|
Log in / Subscribe / Register

2.5.24 IDE 95

I have Martin's permission to push some ide-clean patches, so here we go.

I'm running fine SMP kernel with spinlocks debugging enabled on UP.
Note that this patch brokes ide-cd/tape/floppy/scsi locking...

This patch is mainly for developers to have something to sync with... ;-)

still TODO:
- remove ide_wait commands from interrupt paths
- move locking/completion upwards from ide_do_drive_cmd()
- fix ide device setup/tear down locking
- locking of ioctls
- tape->spinlock is probably obsolete now


Thu Jun 27 13:32:35 CEST 2002 ide-clean-95

It is a merge of patches by Alexander Atanasov and Zwane Mwaikambo
(big thanks guys!) plus some corrections by me...

- Remove locking from IRQ handlers (*_intr etc.) and ata_ops->do_reqeuest(),
  ata_ops->end_request().

- Add non-locking __blk_get_request() and __blk_attempt_remege() helpers
  to block layer (ll_rw_blk.c).

- Move locking up to the entry points.

- Move ata_expiry_t functions to the ide_startstop_t interface
  (need to call ata_error, and its return is idestartstop_t, not wait time).

- Kill ata_end_request() and restart_request() (they were locking variants).

- Disable some ide__sti() for now.

- Misc fixes.


diff -X dontdiff -ur linux-2.5.24/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- linux-2.5.24/drivers/block/ll_rw_blk.c	Mon Jun 24 22:20:53 2002
+++ linux/drivers/block/ll_rw_blk.c	Wed Jun 26 19:56:53 2002
@@ -1203,6 +1203,26 @@
 	return rq;
 }
 
+/*
+ * Non-locking blk_get_request variant, for special requests from drivers.
+ */
+struct request *__blk_get_request(request_queue_t *q, int rw)
+{
+	struct request *rq;
+
+	BUG_ON(rw != READ && rw != WRITE);
+
+	rq = get_request(q, rw);
+
+	if (rq) {
+		rq->flags = 0;
+		rq->buffer = NULL;
+		rq->bio = rq->biotail = NULL;
+		rq->waiting = NULL;
+	}
+	return rq;
+}
+
 void blk_put_request(struct request *rq)
 {
 	blkdev_release_request(rq);
@@ -1384,6 +1404,14 @@
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 
+/*
+ * Non-locking blk_attempt_remerge variant.
+ */
+void __blk_attempt_remerge(request_queue_t *q, struct request *rq)
+{
+	attempt_back_merge(q, rq);
+}
+
 static int __make_request(request_queue_t *q, struct bio *bio)
 {
 	struct request *req, *freereq = NULL;
@@ -2042,6 +2070,7 @@
 EXPORT_SYMBOL(blk_plug_device);
 EXPORT_SYMBOL(blk_remove_plug);
 EXPORT_SYMBOL(blk_attempt_remerge);
+EXPORT_SYMBOL(__blk_attempt_remerge);
 EXPORT_SYMBOL(blk_max_low_pfn);
 EXPORT_SYMBOL(blk_max_pfn);
 EXPORT_SYMBOL(blk_queue_max_sectors);
@@ -2058,6 +2087,7 @@
 EXPORT_SYMBOL(blk_phys_contig_segment);
 EXPORT_SYMBOL(blk_hw_contig_segment);
 EXPORT_SYMBOL(blk_get_request);
+EXPORT_SYMBOL(__blk_get_request);
 EXPORT_SYMBOL(blk_put_request);
 
 EXPORT_SYMBOL(blk_queue_prep_rq);
diff -X dontdiff -ur linux-2.5.24/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- linux-2.5.24/drivers/ide/ide-cd.c	Tue Jun 18 00:29:02 2002
+++ linux/drivers/ide/ide-cd.c	Thu Jun 27 01:36:08 2002
@@ -556,7 +556,7 @@
 	if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
 		uptodate = 1;
 
-	ata_end_request(drive, rq, uptodate);
+	__ata_end_request(drive, rq, uptodate, 0);
 }
 
 
@@ -692,10 +692,8 @@
 	return 1;
 }
 
-static int cdrom_timer_expiry(struct ata_device *drive, struct request *rq)
+static ide_startstop_t cdrom_timer_expiry(struct ata_device *drive, struct request *rq, unsigned long *wait)
 {
-	unsigned long wait = 0;
-
 	/*
 	 * Some commands are *slow* and normally take a long time to
 	 * complete. Usually we can use the ATAPI "disconnect" to bypass
@@ -706,14 +704,14 @@
 		case GPCMD_BLANK:
 		case GPCMD_FORMAT_UNIT:
 		case GPCMD_RESERVE_RZONE_TRACK:
-			wait = WAIT_CMD;
-			break;
+			*wait = WAIT_CMD;
+			return ide_started;
 		default:
-			wait = 0;
+			*wait = 0;
 			break;
 	}
 
-	return wait;
+	return ide_stopped;
 }
 
 /* Set up the device registers for transferring a packet command on DEV,
@@ -728,13 +726,10 @@
 						  int xferlen,
 						  ata_handler_t handler)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	ide_startstop_t startstop;
 	struct cdrom_info *info = drive->driver_data;
 	int ret;
 
-	spin_lock_irqsave(ch->lock, flags);
 	/* Wait for the controller to be idle. */
 	if (ata_status_poll(drive, 0, BUSY_STAT, WAIT_READY, rq, &startstop))
 		ret = startstop;
@@ -764,15 +759,9 @@
 		} else {
 			OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG); /* packet command */
 
-			/* FIXME: Oj kurwa! We have to ungrab the lock before
-			 * the IRQ handler gets called.
-			 */
-			spin_unlock_irqrestore(ch->lock, flags);
 			ret = handler(drive, rq);
-			spin_lock_irqsave(ch->lock, flags);
 		}
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -787,8 +776,6 @@
 		unsigned char *cmd, unsigned long timeout,
 		ata_handler_t handler)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	ide_startstop_t startstop;
 
 	if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) {
@@ -800,24 +787,15 @@
 		if (cdrom_decode_status(&startstop, drive, rq, DRQ_STAT, &stat_dum))
 			return startstop;
 	} else {
-		/* FIXME: make this locking go away */
-		spin_lock_irqsave(ch->lock, flags);
 		/* Otherwise, we must wait for DRQ to get set. */
 		if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
-					WAIT_READY, rq, &startstop)) {
-			spin_unlock_irqrestore(ch->lock, flags);
-
+					WAIT_READY, rq, &startstop))
 			return startstop;
-		}
-		spin_unlock_irqrestore(ch->lock, flags);
 	}
 
 	/* Arm the interrupt handler and send the command to the device. */
-	/* FIXME: make this locking go away */
-	spin_lock_irqsave(ch->lock, flags);
 	ata_set_handler(drive, handler, timeout, cdrom_timer_expiry);
 	atapi_write(drive, cmd, CDROM_PACKET_SIZE);
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_started;
 }
@@ -917,8 +895,6 @@
  */
 static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	int stat;
 	int ireason, len, sectors_to_transfer, nskip;
 	struct cdrom_info *info = drive->driver_data;
@@ -937,13 +913,7 @@
 
 	if (dma) {
 		if (!dma_error) {
-			/* FIXME: this locking should encompass the above register
-			 * file access too.
-			 */
-
-			spin_lock_irqsave(ch->lock, flags);
 			__ata_end_request(drive, rq, 1, rq->nr_sectors);
-			spin_unlock_irqrestore(ch->lock, flags);
 
 			return ide_stopped;
 		} else
@@ -1040,9 +1010,7 @@
 	}
 
 	/* Done moving data! Wait for another interrupt. */
-	spin_lock_irqsave(ch->lock, flags);
 	ata_set_handler(drive, cdrom_read_intr, WAIT_CMD, NULL);
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_started;
 }
@@ -1245,7 +1213,7 @@
 	if (cdrom_read_from_buffer(drive, rq))
 		return ide_stopped;
 
-	blk_attempt_remerge(&drive->queue, rq);
+	__blk_attempt_remerge(&drive->queue, rq);
 
 	/* Clear the local sector buffer. */
 	info->nsectors_buffered = 0;
@@ -1269,8 +1237,6 @@
 /* Interrupt routine for packet command completion. */
 static ide_startstop_t cdrom_pc_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	int ireason, len, stat, thislen;
 
 	/* FIXME --mdcki */
@@ -1363,9 +1329,7 @@
 	}
 
 	/* Now we wait for another interrupt. */
-	spin_lock_irqsave(ch->lock, flags);
 	ata_set_handler(drive, cdrom_pc_intr, WAIT_CMD, cdrom_timer_expiry);
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_started;
 }
@@ -1508,8 +1472,6 @@
 
 static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	int stat, ireason, len, sectors_to_transfer, uptodate;
 	struct cdrom_info *info = drive->driver_data;
 	int dma_error = 0, dma = info->dma;
@@ -1536,13 +1498,7 @@
 		if (dma_error)
 			return ata_error(drive, rq, "dma error");
 
-		/* FIXME: this locking should encompass the above register
-		 * file access too.
-		 */
-
-		spin_lock_irqsave(ch->lock, flags);
 		__ata_end_request(drive, rq, 1, rq->nr_sectors);
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return ide_stopped;
 	}
@@ -1607,9 +1563,7 @@
 	}
 
 	/* re-arm handler */
-	spin_lock_irqsave(ch->lock, flags);
 	ata_set_handler(drive, cdrom_write_intr, 5 * WAIT_CMD, NULL);
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_started;
 }
@@ -1637,7 +1591,7 @@
 	 * remerge requests, often the plugging will not have had time
 	 * to do this properly
 	 */
-	blk_attempt_remerge(&drive->queue, rq);
+	__blk_attempt_remerge(&drive->queue, rq);
 
 	info->nsectors_buffered = 0;
 
@@ -1658,7 +1612,6 @@
 static ide_startstop_t
 ide_cdrom_do_request(struct ata_device *drive, struct request *rq, sector_t block)
 {
-	struct ata_channel *ch = drive->channel;
 	int ret;
 	struct cdrom_info *info = drive->driver_data;
 
@@ -1675,8 +1628,6 @@
 			}
 			CDROM_CONFIG_FLAGS(drive)->seeking = 0;
 		}
-		/* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
 		if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) {
 			ret = cdrom_start_seek(drive, rq, block);
 		} else {
@@ -1686,13 +1637,9 @@
 				ret = cdrom_start_write(drive, rq);
 		}
 		info->last_block = block;
-		spin_lock_irq(ch->lock);
 		return ret;
 	} else if (rq->flags & (REQ_PC | REQ_SENSE)) {
-		/* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
 		ret = cdrom_do_packet_command(drive, rq);
-		spin_lock_irq(ch->lock);
 
 		return ret;
 	} else if (rq->flags & REQ_SPECIAL) {
@@ -1703,10 +1650,7 @@
 		 * right now this can only be a reset...
 		 */
 
-	        /* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
 		cdrom_end_request(drive, rq, 1);
-		spin_lock_irq(ch->lock);
 
 		return ide_stopped;
 	} else if (rq->flags & REQ_BLOCK_PC) {
@@ -1720,10 +1664,7 @@
 		/* FIXME --mdcki */
 		rq->special = (char *) &pc;
 
-		/* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
 		startstop = cdrom_do_packet_command(drive, rq);
-		spin_lock_irq(ch->lock);
 
 		if (pc.stat)
 			++rq->errors;
@@ -1732,10 +1673,8 @@
 	}
 
 	blk_dump_rq_flags(rq, "ide-cd bad flags");
-	/* FIXME: make this unlocking go away*/
-	spin_unlock_irq(ch->lock);
+
 	cdrom_end_request(drive, rq, 0);
-	spin_lock_irq(ch->lock);
 
 	return ide_stopped;
 }
diff -X dontdiff -ur linux-2.5.24/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- linux-2.5.24/drivers/ide/ide-disk.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/ide-disk.c	Wed Jun 26 22:17:11 2002
@@ -107,22 +107,20 @@
 }
 
 /*
+ * The following IRQ handlers (*_intr) should be called
+ * with the channel lock held and interrupts disabled.
+ */
+
+/*
  * Handler for command with PIO data-in phase.
  */
 static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	int ret;
 
-	spin_lock_irqsave(ch->lock, flags);
-
 	if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
-		if (drive->status & (ERR_STAT | DRQ_STAT)) {
-			spin_unlock_irqrestore(ch->lock, flags);
-
+		if (drive->status & (ERR_STAT | DRQ_STAT))
 			return ata_error(drive, rq, __FUNCTION__);
-		}
 
 		/* no data yet, so wait for another interrupt */
 		ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
@@ -149,7 +147,6 @@
 		if (rq->current_nr_sectors <= 0) {
 			if (!__ata_end_request(drive, rq, 1, 0)) {
 			//		printk("Request Ended stat: %02x\n", drive->status);
-				spin_unlock_irqrestore(ch->lock, flags);
 
 				return ide_stopped;
 			}
@@ -160,7 +157,6 @@
 
 		ret = ide_started;
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -170,16 +166,10 @@
  */
 static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	int ret;
 
-	spin_lock_irqsave(ch->lock, flags);
-	if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) {
-		spin_unlock_irqrestore(ch->lock, flags);
-
+	if (!ata_status(drive, DRIVE_READY, drive->bad_wstat))
 		return ata_error(drive, rq, __FUNCTION__);
-	}
 
 	if (!rq->current_nr_sectors && !__ata_end_request(drive, rq, 1, 0)) {
 		ret = ide_stopped;
@@ -200,7 +190,6 @@
 
 		ret = ide_started;
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -210,17 +199,11 @@
  */
 static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	int ret;
 
-	spin_lock_irqsave(ch->lock, flags);
 	if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
-		if (drive->status & (ERR_STAT | DRQ_STAT)) {
-			spin_unlock_irqrestore(ch->lock, flags);
-
+		if (drive->status & (ERR_STAT | DRQ_STAT))
 			return ata_error(drive, rq, __FUNCTION__);
-		}
 
 		/* no data yet, so wait for another interrupt */
 		ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
@@ -257,11 +240,8 @@
 
 			/* FIXME: this seems buggy */
 			if (rq->current_nr_sectors <= 0) {
-				if (!__ata_end_request(drive, rq, 1, 0)) {
-					spin_unlock_irqrestore(ch->lock, flags);
-
+				if (!__ata_end_request(drive, rq, 1, 0))
 					return ide_stopped;
-				}
 			}
 			msect -= nsect;
 		} while (msect);
@@ -271,20 +251,16 @@
 
 		ret = ide_started;
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
 
 static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
 	struct ata_channel *ch = drive->channel;
 	int ok;
 	int ret;
 
-	spin_lock_irqsave(ch->lock, flags);
-
 	/*
 	 * FIXME: the drive->status checks here seem to be messy.
 	 *
@@ -295,11 +271,8 @@
 	ok = ata_status(drive, DATA_READY, BAD_R_STAT);
 
 	if (!ok || !rq->nr_sectors) {
-		if (drive->status & (ERR_STAT | DRQ_STAT)) {
-			spin_unlock_irqrestore(ch->lock, flags);
-
+		if (drive->status & (ERR_STAT | DRQ_STAT))
 			return ata_error(drive, rq, __FUNCTION__);
-		}
 	}
 	if (!rq->nr_sectors) {
 		__ata_end_request(drive, rq, 1, rq->hard_nr_sectors);
@@ -307,6 +280,7 @@
 		ret = ide_stopped;
 	} else if (!ok) {
 		/* no data yet, so wait for another interrupt */
+		/* FIXME:  --bzolnier */
 		if (!ch->handler)
 			ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
 		ret = ide_started;
@@ -351,14 +325,14 @@
 
 		rq->errors = 0;
 
+		/* FIXME:  --bzolnier */
 		if (!ch->handler)
 			ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
 
 		ret = ide_started;
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
-	return ide_started;
+	return ret;
 }
 
 /*
@@ -508,8 +482,7 @@
 				} else if (drive->using_dma) {
 					cmd = WIN_READDMA;
 				} else if (drive->mult_count) {
-					/* FIXME : Shouldn't this be task_mulin_intr?! */
-					args.XXX_handler = task_in_intr;
+					args.XXX_handler = task_mulin_intr;
 					cmd = WIN_MULTREAD;
 				} else {
 					args.XXX_handler = task_in_intr;
@@ -579,7 +552,6 @@
 	/* FIXME: this is actually distingushing between PIO and DMA requests.
 	 */
 	if (ar->XXX_handler) {
-		struct ata_channel *ch = drive->channel;
 
 		ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL);
 		OUT_BYTE(cmd, IDE_COMMAND_REG);
@@ -628,7 +600,6 @@
 				return ide_started;
 			} else {
 				int i;
-				int ret;
 
 				/* Polling wait until the drive is ready.
 				 *
@@ -649,12 +620,8 @@
 					 */
 					printk(KERN_ERR "DISASTER WAITING TO HAPPEN!\n");
 				}
-				/* FIXME: make this unlocking go away*/
-				spin_unlock_irq(ch->lock);
-				ret =  ar->XXX_handler(drive, rq);
-				spin_lock_irq(ch->lock);
 
-				return ret;
+				return ar->XXX_handler(drive, rq);
 			}
 		}
 	} else {
diff -X dontdiff -ur linux-2.5.24/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c
--- linux-2.5.24/drivers/ide/ide-floppy.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/ide-floppy.c	Thu Jun 27 12:37:53 2002
@@ -365,7 +365,7 @@
 		return 0;
 
 	if (!(rq->flags & REQ_SPECIAL)) {
-		ata_end_request(drive, rq, uptodate);
+		__ata_end_request(drive, rq, uptodate, 0);
 		return 0;
 	}
 
@@ -554,8 +554,6 @@
  */
 static ide_startstop_t idefloppy_pc_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	idefloppy_floppy_t *floppy = drive->driver_data;
 	atapi_status_reg_t status;
 	atapi_bcount_reg_t bcount;
@@ -618,26 +616,20 @@
 		return ide_stopped;
 	}
 #endif
-	/* FIXME: this locking should encompass the above register
-	 * file access too.
-	 */
 
-	spin_lock_irqsave(ch->lock, flags);
 	bcount.b.high=IN_BYTE (IDE_BCOUNTH_REG);			/* Get the number of bytes to transfer */
 	bcount.b.low=IN_BYTE (IDE_BCOUNTL_REG);			/* on this interrupt */
 	ireason.all=IN_BYTE (IDE_IREASON_REG);
 
 	if (ireason.b.cod) {
-		spin_unlock_irqrestore(ch->lock, flags);
-
 		printk (KERN_ERR "ide-floppy: CoD != 0 in idefloppy_pc_intr\n");
+
 		return ide_stopped;
 	}
 	if (ireason.b.io == test_bit(PC_WRITING, &pc->flags)) {	/* Hopefully, we will never get here */
-		spin_unlock_irqrestore(ch->lock, flags);
-
 		printk (KERN_ERR "ide-floppy: We wanted to %s, ", ireason.b.io ? "Write":"Read");
 		printk (KERN_ERR "but the floppy wants us to %s !\n",ireason.b.io ? "Read":"Write");
+
 		return ide_stopped;
 	}
 	if (!test_bit(PC_WRITING, &pc->flags)) {			/* Reading - Check that we have enough space */
@@ -648,7 +640,6 @@
 
 				atapi_discard_data (drive,bcount.all);
 				ata_set_handler(drive, idefloppy_pc_intr,IDEFLOPPY_WAIT_CMD, NULL);
-				spin_unlock_irqrestore(ch->lock, flags);
 
 				return ide_started;
 			}
@@ -672,7 +663,6 @@
 	pc->current_position+=bcount.all;
 
 	ata_set_handler(drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);		/* And set the interrupt handler again */
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_started;
 }
@@ -684,16 +674,11 @@
  */
 static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	ide_startstop_t startstop;
 	idefloppy_floppy_t *floppy = drive->driver_data;
 	atapi_ireason_reg_t ireason;
 	int ret;
 
-	/* FIXME: Move this lock upwards.
-	 */
-	spin_lock_irqsave(ch->lock, flags);
 	if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
 				WAIT_READY, rq, &startstop)) {
 		printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
@@ -711,7 +696,6 @@
 			ret = ide_started;
 		}
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -729,18 +713,18 @@
  * packet, we schedule the packet transfer to occur about 2-3 ticks
  * later in transfer_pc2.
  */
-static int idefloppy_transfer_pc2(struct ata_device *drive, struct request *__rq)
+static ide_startstop_t idefloppy_transfer_pc2(struct ata_device *drive, struct request *__rq, unsigned long *wait)
 {
 	idefloppy_floppy_t *floppy = drive->driver_data;
 
 	atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */
-	return IDEFLOPPY_WAIT_CMD;		/* Timeout for the packet command */
+	*wait = IDEFLOPPY_WAIT_CMD;	/* Timeout for the packet command */
+
+	return ide_started;
 }
 
 static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	idefloppy_floppy_t *floppy = drive->driver_data;
 	ide_startstop_t startstop;
 	atapi_ireason_reg_t ireason;
@@ -753,11 +737,6 @@
 		return startstop;
 	}
 
-	/* FIXME: this locking should encompass the above register
-	 * file access too.
-	 */
-
-	spin_lock_irqsave(ch->lock, flags);
 	ireason.all=IN_BYTE(IDE_IREASON_REG);
 	if (!ireason.b.cod || ireason.b.io) {
 		printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
@@ -778,7 +757,6 @@
 				idefloppy_transfer_pc2);	/* fail == transfer_pc2 */
 		ret = ide_started;
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -859,17 +837,8 @@
 	}
 
 	if (test_bit(IDEFLOPPY_DRQ_INTERRUPT, &floppy->flags)) {
-		unsigned long flags;
-		struct ata_channel *ch = drive->channel;
-
-		/* FIXME: this locking should encompass the above register
-		 * file access too.
-		 */
-
-		spin_lock_irqsave(ch->lock, flags);
 		ata_set_handler(drive, pkt_xfer_routine, IDEFLOPPY_WAIT_CMD, NULL);
 		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		/* Issue the packet command */
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return ide_started;
 	} else {
@@ -1010,10 +979,8 @@
  */
 static ide_startstop_t idefloppy_do_request(struct ata_device *drive, struct request *rq, sector_t block)
 {
-	struct ata_channel *ch = drive->channel;
 	idefloppy_floppy_t *floppy = drive->driver_data;
 	struct atapi_packet_command *pc;
-	int ret;
 
 #if IDEFLOPPY_DEBUG_LOG
 	printk (KERN_INFO "rq_status: %d, rq_dev: %u, flags: %lx, errors: %d\n",rq->rq_status,(unsigned int) rq->rq_dev,rq->flags,rq->errors);
@@ -1027,20 +994,15 @@
 		else
 			printk (KERN_ERR "ide-floppy: %s: I/O error\n", drive->name);
 
-		/* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
 		idefloppy_end_request(drive, rq, 0);
-		spin_lock_irq(ch->lock);
 
 		return ide_stopped;
 	}
 	if (rq->flags & REQ_CMD) {
 		if (rq->sector % floppy->bs_factor || rq->nr_sectors % floppy->bs_factor) {
 			printk ("%s: unsupported r/w request size\n", drive->name);
-			/* FIXME: make this unlocking go away*/
-			spin_unlock_irq(ch->lock);
+
 			idefloppy_end_request(drive, rq, 0);
-			spin_lock_irq(ch->lock);
 
 			return ide_stopped;
 		}
@@ -1051,20 +1013,13 @@
 		pc = (struct atapi_packet_command *) rq->buffer;
 	} else {
 		blk_dump_rq_flags(rq, "ide-floppy: unsupported command in queue");
-		/* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
+
 		idefloppy_end_request(drive, rq, 0);
-		spin_lock_irq(ch->lock);
 
 		return ide_stopped;
 	}
 
-	/* FIXME: make this unlocking go away*/
-	spin_unlock_irq(ch->lock);
-	ret = idefloppy_issue_pc(drive, rq, pc);
-	spin_lock_irq(ch->lock);
-
-	return ret;
+	return idefloppy_issue_pc(drive, rq, pc);
 }
 
 /*
diff -X dontdiff -ur linux-2.5.24/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c
--- linux-2.5.24/drivers/ide/ide-tape.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/ide-tape.c	Wed Jun 26 17:54:11 2002
@@ -10,6 +10,10 @@
  */
 
 /*
+ * BIG FAT FIXME: clean tape->spinlock locking  --bzolnier
+ */
+
+/*
  * IDE ATAPI streaming tape driver.
  *
  * This driver is a part of the Linux ide driver and works in co-operation
@@ -1818,8 +1822,6 @@
  */
 static ide_startstop_t idetape_pc_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	idetape_tape_t *tape = drive->driver_data;
 	atapi_status_reg_t status;
 	atapi_bcount_reg_t bcount;
@@ -1915,17 +1917,11 @@
 		pc->callback(drive, rq);	/* Command finished - Call the callback function */
 		return ide_stopped;
 	}
-	/* FIXME: this locking should encompass the above register
-	 * file access too.
-	 */
-
-	spin_lock_irqsave(ch->lock, flags);
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (test_and_clear_bit (PC_DMA_IN_PROGRESS, &pc->flags)) {
 		printk (KERN_ERR "ide-tape: The tape wants to issue more interrupts in DMA mode\n");
 		printk (KERN_ERR "ide-tape: DMA disabled, reverting to PIO\n");
 		udma_enable(drive, 0, 1);
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return ide_stopped;
 	}
@@ -1936,16 +1932,14 @@
 	ireason.all   = IN_BYTE (IDE_IREASON_REG);
 
 	if (ireason.b.cod) {
-		spin_unlock_irqrestore(ch->lock, flags);
-
 		printk (KERN_ERR "ide-tape: CoD != 0 in idetape_pc_intr\n");
+
 		return ide_stopped;
 	}
 	if (ireason.b.io == test_bit (PC_WRITING, &pc->flags)) {	/* Hopefully, we will never get here */
-		spin_unlock_irqrestore(ch->lock, flags);
-
 		printk (KERN_ERR "ide-tape: We wanted to %s, ", ireason.b.io ? "Write":"Read");
 		printk (KERN_ERR "ide-tape: but the tape wants us to %s !\n",ireason.b.io ? "Read":"Write");
+
 		return ide_stopped;
 	}
 	if (!test_bit (PC_WRITING, &pc->flags)) {			/* Reading - Check that we have enough space */
@@ -1955,7 +1949,6 @@
 				printk (KERN_ERR "ide-tape: The tape wants to send us more data than expected - discarding data\n");
 				atapi_discard_data (drive, bcount.all);
 				ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);
-				spin_unlock_irqrestore(ch->lock, flags);
 
 				return ide_started;
 			}
@@ -1983,7 +1976,6 @@
 		printk(KERN_INFO "ide-tape: [cmd %x] transferred %d bytes on that interrupt\n", pc->c[0], bcount.all);
 #endif
 	ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL);	/* And set the interrupt handler again */
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_started;
 }
@@ -2032,8 +2024,6 @@
  */
 static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	idetape_tape_t *tape = drive->driver_data;
 	struct atapi_packet_command *pc = tape->pc;
 	atapi_ireason_reg_t ireason;
@@ -2041,9 +2031,6 @@
 	ide_startstop_t startstop;
 	int ret;
 
-	/* FIXME: Move this lock upwards.
-	 */
-	spin_lock_irqsave(ch->lock, flags);
 	if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
 				WAIT_READY, rq, &startstop)) {
 		printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
@@ -2071,7 +2058,6 @@
 			ret = ide_started;
 		}
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -2145,17 +2131,8 @@
 	}
 #endif
 	if (test_bit(IDETAPE_DRQ_INTERRUPT, &tape->flags)) {
-		unsigned long flags;
-		struct ata_channel *ch = drive->channel;
-
-		/* FIXME: this locking should encompass the above register
-		 * file access too.
-		 */
-
-		spin_lock_irqsave(ch->lock, flags);
 		ata_set_handler(drive, idetape_transfer_pc, IDETAPE_WAIT_CMD, NULL);
 		OUT_BYTE(WIN_PACKETCMD, IDE_COMMAND_REG);
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return ide_started;
 	} else {
@@ -2445,12 +2422,10 @@
  */
 static ide_startstop_t idetape_do_request(struct ata_device *drive, struct request *rq, sector_t block)
 {
-	struct ata_channel *ch = drive->channel;
 	idetape_tape_t *tape = drive->driver_data;
 	struct atapi_packet_command *pc;
 	struct request *postponed_rq = tape->postponed_rq;
 	atapi_status_reg_t status;
-	int ret;
 
 #if IDETAPE_DEBUG_LOG
 /*	if (tape->debug_level >= 5)
@@ -2472,23 +2447,15 @@
 	 *	Retry a failed packet command
 	 */
 	if (tape->failed_pc != NULL && tape->pc->c[0] == IDETAPE_REQUEST_SENSE_CMD) {
-		int ret;
 
-		/* FIXME: make this unlocking go away*/
-		spin_unlock_irq(ch->lock);
-		ret = idetape_issue_packet_command(drive, rq, tape->failed_pc);
-		spin_lock_irq(ch->lock);
-
-		return ret;
+		return idetape_issue_packet_command(drive, rq, tape->failed_pc);
 	}
 #if IDETAPE_DEBUG_BUGS
 	if (postponed_rq != NULL)
 		if (rq != postponed_rq) {
 			printk (KERN_ERR "ide-tape: ide-tape.c bug - Two DSC requests were queued\n");
-			/* FIXME: make this unlocking go away*/
-			spin_unlock_irq(ch->lock);
+
 			idetape_end_request(drive, rq, 0);
-			spin_lock_irq(ch->lock);
 
 			return ide_stopped;
 		}
@@ -2566,15 +2533,11 @@
 			tape->dsc_timeout = jiffies + IDETAPE_DSC_RW_TIMEOUT;
 		} else if ((signed long) (jiffies - tape->dsc_timeout) > 0) {
 			printk (KERN_ERR "ide-tape: %s: DSC timeout\n", tape->name);
-			if (rq->flags == IDETAPE_PC_RQ2) {
-				/* FIXME: make this unlocking go away*/
-				spin_unlock_irq(ch->lock);
+
+			if (rq->flags == IDETAPE_PC_RQ2)
 				idetape_media_access_finished(drive, rq);
-				spin_lock_irq(ch->lock);
-				return ide_stopped;
-			} else {
-				return ide_stopped;
-			}
+
+			return ide_stopped;
 		} else if (jiffies - tape->dsc_polling_start > IDETAPE_DSC_MA_THRESHOLD)
 			tape->dsc_polling_frequency = IDETAPE_DSC_MA_SLOW;
 		idetape_postpone_request(drive, rq);
@@ -2638,25 +2601,18 @@
 			rq->flags = IDETAPE_PC_RQ2;
 			break;
 		case IDETAPE_PC_RQ2:
-			/* FIXME: make this unlocking go away*/
-			spin_unlock_irq(ch->lock);
 			idetape_media_access_finished(drive, rq);
-			spin_lock_irq(ch->lock);
+
 			return ide_stopped;
 		default:
 			printk (KERN_ERR "ide-tape: bug in IDETAPE_RQ_CMD macro\n");
-			/* FIXME: make this unlocking go away*/
-			spin_unlock_irq(ch->lock);
+
 			idetape_end_request(drive, rq, 0);
-			spin_lock_irq(ch->lock);
+
 			return ide_stopped;
 	}
-	/* FIXME: make this unlocking go away*/
-	spin_unlock_irq(ch->lock);
-	ret = idetape_issue_packet_command(drive, rq, pc);
-	spin_lock_irq(ch->lock);
 
-	return ret;
+	return idetape_issue_packet_command(drive, rq, pc);
 }
 
 /*
diff -X dontdiff -ur linux-2.5.24/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.24/drivers/ide/ide-taskfile.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/ide-taskfile.c	Thu Jun 27 01:34:44 2002
@@ -242,16 +242,18 @@
 /*
  * Invoked on completion of a special REQ_SPECIAL command.
  */
+/*
+ * Channel lock should be held.
+ */
 static ide_startstop_t special_intr(struct ata_device *drive, struct
 		request *rq) {
 
 	struct ata_taskfile *ar = rq->special;
 	ide_startstop_t ret = ide_stopped;
-	unsigned long flags;
 
-	ide__sti();	/* local CPU only */
-
-	spin_lock_irqsave(drive->channel->lock, flags);
+	/* FIXME:  --bzolnier
+	ide__sti();
+	*/
 
 	if (rq->buffer && ar->taskfile.sector_number) {
 		if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) {
@@ -287,8 +289,6 @@
 	drive->rq = NULL;
 	end_that_request_last(rq);
 
-	spin_unlock_irqrestore(drive->channel->lock, flags);
-
 	return ret;
 }
 
diff -X dontdiff -ur linux-2.5.24/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.24/drivers/ide/ide.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/ide.c	Thu Jun 27 02:03:30 2002
@@ -148,22 +148,6 @@
 }
 
 /*
- * This is the default end request function as well
- */
-int ata_end_request(struct ata_device *drive, struct request *rq, int uptodate)
-{
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
-	int ret;
-
-	spin_lock_irqsave(ch->lock, flags);
-	ret = __ata_end_request(drive, rq, uptodate, 0);
-	spin_unlock_irqrestore(drive->channel->lock, flags);
-
-	return ret;
-}
-
-/*
  * This should get invoked any time we exit the driver to
  * wait for an interrupt response from a drive.  handler() points
  * at the appropriate code to handle the next interrupt, and a
@@ -347,7 +331,7 @@
 	}
 	ch->poll_timeout = 0;	/* done polling */
 
-	return ide_stopped;
+	return ret;
 }
 
 /*
@@ -374,6 +358,7 @@
 	unsigned long flags;
 	struct ata_channel *ch = drive->channel;
 
+	/* FIXME:  --bzolnier */
 	__save_flags(flags);	/* local CPU only */
 	__cli();		/* local CPU only */
 
@@ -467,6 +452,7 @@
 	unsigned long flags;
 	u8 err = 0;
 
+	/* FIXME:  --bzolnier */
 	__save_flags (flags);	/* local CPU only */
 	ide__sti();		/* local CPU only */
 
@@ -573,7 +559,7 @@
 /*
  * Take action based on the error returned by the drive.
  *
- * FIXME: Channel lock should be held.
+ * Channel lock should be held.
  */
 ide_startstop_t ata_error(struct ata_device *drive, struct request *rq,	const char *msg)
 {
@@ -617,7 +603,6 @@
 
 	if (rq->errors >= ERROR_MAX) {
 		printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name);
-		/* FIXME: make sure all end_request implementations are lock free */
 		if (ata_ops(drive) && ata_ops(drive)->end_request)
 			ata_ops(drive)->end_request(drive, rq, 0);
 		else
@@ -627,6 +612,7 @@
 		if ((rq->errors & ERROR_RESET) == ERROR_RESET)
 			return do_reset1(drive, 1);
 		if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
+			/* FIXME: tries to acquire the channel lock -Zwane */
 			return do_recalibrate(drive);
 	}
 
@@ -700,35 +686,14 @@
 	return ret;
 
 kill_rq:
-	if (ata_ops(drive)) {
-		if (ata_ops(drive)->end_request) {
-			spin_unlock_irq(ch->lock);
-			ata_ops(drive)->end_request(drive, rq, 0);
-			spin_lock_irq(ch->lock);
-		} else
-			__ata_end_request(drive, rq, 0, 0);
-	} else
+	if (ata_ops(drive) && ata_ops(drive)->end_request)
+		ata_ops(drive)->end_request(drive, rq, 0);
+	else
 		__ata_end_request(drive, rq, 0, 0);
 
 	return ide_stopped;
 }
 
-ide_startstop_t restart_request(struct ata_device *drive)
-{
-	struct ata_channel *ch = drive->channel;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(ch->lock, flags);
-
-	ch->handler = NULL;
-	del_timer(&ch->timer);
-	ret = start_request(drive, drive->rq);
-	spin_unlock_irqrestore(ch->lock, flags);
-
-	return ret;
-}
-
 /*
  * This is used by a drive to give excess bandwidth back by sleeping for
  * timeout jiffies.
@@ -993,10 +958,13 @@
 			unsigned long wait;
 
 			/* continue */
-			if ((wait = ch->expiry(drive, drive->rq)) != 0) {
+			ret = ch->expiry(drive, drive->rq, &wait);
+			if (ret == ide_started) {
 				/* reengage timer */
-				ch->timer.expires  = jiffies + wait;
-				add_timer(&ch->timer);
+				if (wait) {
+					ch->timer.expires  = jiffies + wait;
+					add_timer(&ch->timer);
+				}
 
 				spin_unlock_irqrestore(ch->lock, flags);
 
@@ -1012,7 +980,6 @@
 
 		handler = ch->handler;
 		ch->handler = NULL;
-		spin_unlock(ch->lock);
 
 		ch = drive->channel;
 #if DISABLE_IRQ_NOSYNC
@@ -1069,12 +1036,9 @@
 
 		enable_irq(ch->irq);
 
-		spin_lock_irq(ch->lock);
-
 		if (ret == ide_stopped)
 			clear_bit(IDE_BUSY, ch->active);
 
-
 		/* Reenter the request handling engine */
 		do_request(ch);
 	}
@@ -1202,14 +1166,14 @@
 	ch->handler = NULL;
 	del_timer(&ch->timer);
 
-	spin_unlock(ch->lock);
-
-	if (ch->unmask)
-		ide__sti();	/* local CPU only */
+	if (ch->unmask) {
+		/* FIXME: perhaps disable_irq(irq); __sti(); ? -Zwane
+		ide__sti();
+		*/
+	}
 
 	/* service this interrupt, may set handler for next interrupt */
 	startstop = handler(drive, drive->rq);
-	spin_lock_irq(ch->lock);
 
 	/*
 	 * Note that handler() may have set things up for another
@@ -1376,9 +1340,6 @@
 EXPORT_SYMBOL(ata_dump);
 EXPORT_SYMBOL(ata_error);
 
-/* FIXME: this is a trully bad name */
-EXPORT_SYMBOL(restart_request);
-EXPORT_SYMBOL(ata_end_request);
 EXPORT_SYMBOL(__ata_end_request);
 EXPORT_SYMBOL(ide_stall_queue);
 
diff -X dontdiff -ur linux-2.5.24/drivers/ide/pcidma.c linux/drivers/ide/pcidma.c
--- linux-2.5.24/drivers/ide/pcidma.c	Tue Jun 25 22:46:36 2002
+++ linux/drivers/ide/pcidma.c	Wed Jun 26 17:46:50 2002
@@ -36,6 +36,8 @@
 
 /*
  * This is the handler for disk read/write DMA interrupts.
+ *
+ * Channel lock should be held.
  */
 ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
 {
@@ -44,16 +46,7 @@
 
 	if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
 		if (!dma_stat) {
-			unsigned long flags;
-			struct ata_channel *ch = drive->channel;
-
-			/* FIXME: this locking should encompass the above register
-			 * file access too.
-			 */
-
-			spin_lock_irqsave(ch->lock, flags);
 			__ata_end_request(drive, rq, 1, rq->nr_sectors);
-			spin_unlock_irqrestore(ch->lock, flags);
 
 			return ide_stopped;
 		}
@@ -128,7 +121,7 @@
 /*
  * 1 dma-ing, 2 error, 4 intr
  */
-static int dma_timer_expiry(struct ata_device *drive, struct request *rq)
+static ide_startstop_t dma_timer_expiry(struct ata_device *drive, struct request *rq, unsigned long *wait)
 {
 	/* FIXME: What's that? */
 	u8 dma_stat = inb(drive->channel->dma_base + 2);
@@ -140,15 +133,17 @@
 #if 0
 	drive->expiry = NULL;	/* one free ride for now */
 #endif
-
+	*wait = 0;
 	if (dma_stat & 2) {	/* ERROR */
 		ata_status(drive, 0, 0);
 		return ata_error(drive, rq, __FUNCTION__);
 	}
-	if (dma_stat & 1)	/* DMAing */
-		return WAIT_CMD;
+	if (dma_stat & 1) {	/* DMAing */
+		*wait = WAIT_CMD;
+		return ide_started;
+	}
 
-	return 0;
+	return ide_stopped;
 }
 
 int ata_start_dma(struct ata_device *drive, struct request *rq)
diff -X dontdiff -ur linux-2.5.24/drivers/ide/pdc4030.c linux/drivers/ide/pdc4030.c
--- linux-2.5.24/drivers/ide/pdc4030.c	Tue Jun 18 00:29:02 2002
+++ linux/drivers/ide/pdc4030.c	Wed Jun 26 16:34:52 2002
@@ -414,10 +414,8 @@
 	rq->errors = 0;
 	rq->nr_sectors -= nsect;
 	total_remaining = rq->nr_sectors;
-	if ((rq->current_nr_sectors -= nsect) <= 0) {
-		/* FIXME: no queue locking above! */
-		ata_end_request(drive, rq, 1);
-	}
+	if ((rq->current_nr_sectors -= nsect) <= 0)
+		__ata_end_request(drive, rq, 1, 0);
 
 	/*
 	 * Now the data has been read in, do the following:
@@ -437,16 +435,7 @@
 		if (drive->status & DRQ_STAT)
 			goto read_again;
 		if (drive->status & BUSY_STAT) {
-			unsigned long flags;
-			struct ata_channel *ch = drive->channel;
-
-			/* FIXME: this locking should encompass the above register
-			 * file access too.
-			 */
-
-			spin_lock_irqsave(ch->lock, flags);
 			ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL);
-			spin_unlock_irqrestore(ch->lock, flags);
 #ifdef DEBUG_READ
 			printk(KERN_DEBUG "%s: promise_read: waiting for"
 			       "interrupt\n", drive->name);
@@ -470,18 +459,11 @@
  */
 static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
 	struct ata_channel *ch = drive->channel;
 
 	if (!ata_status(drive, 0, BUSY_STAT)) {
 		if (time_before(jiffies, ch->poll_timeout)) {
-			/* FIXME: this locking should encompass the above
-			 * register file access too.
-			 */
-
-			spin_lock_irqsave(ch->lock, flags);
 			ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
-			spin_unlock_irqrestore(ch->lock, flags);
 
 			return ide_started; /* continue polling... */
 		}
@@ -495,13 +477,7 @@
 #ifdef DEBUG_WRITE
 	printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
 #endif
-	/* FIXME: this locking should encompass the above
-	 * register file access too.
-	 */
-
-	spin_lock_irqsave(ch->lock, flags);
 	__ata_end_request(drive, rq, 1, rq->nr_sectors);
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ide_stopped;
 }
@@ -563,21 +539,17 @@
  */
 static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
 	struct ata_channel *ch = drive->channel;
 
-	spin_lock_irqsave(ch->lock, flags);
 	if (inb(IDE_NSECTOR_REG) != 0) {
 		if (time_before(jiffies, ch->poll_timeout)) {
 			ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
-			spin_unlock_irqrestore(ch->lock, flags);
 
 			return ide_started; /* continue polling... */
 		}
 		ch->poll_timeout = 0;
 		printk(KERN_ERR "%s: write timed out!\n", drive->name);
 		ata_status(drive, 0, 0);
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return ata_error(drive, rq, "write timeout");
 	}
@@ -592,7 +564,7 @@
 	printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
 		drive->name, drive->status);
 #endif
-	spin_unlock_irqrestore(ch->lock, flags);
+
 	return ide_started;
 }
 
@@ -605,7 +577,6 @@
  */
 static ide_startstop_t promise_do_write(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
 	struct ata_channel *ch = drive->channel;
 
 #ifdef DEBUG_WRITE
@@ -613,23 +584,17 @@
 	       "buffer=%p\n", drive->name, rq->sector,
 	       rq->sector + rq->nr_sectors - 1, rq->buffer);
 #endif
-	/* FIXME: this locking should encompass the above register
-	 * file access too.
-	 */
-
-	spin_lock_irqsave(ch->lock, flags);
 	/*
 	 * If there are more than 4 sectors to transfer, do n-4 then go into
 	 * the polling strategy as defined above.
 	 */
 	if (rq->nr_sectors > 4) {
 		if (promise_multwrite(drive, rq, rq->nr_sectors - 4)) {
-			spin_unlock_irqrestore(ch->lock, flags);
+
 			return ide_stopped;
 		}
 		ch->poll_timeout = jiffies + WAIT_WORSTCASE;
 		ata_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return ide_started;
 	} else {
@@ -637,13 +602,11 @@
 	 * There are 4 or fewer sectors to transfer, do them all in one go
 	 * and wait for NOT BUSY.
 	 */
-		if (promise_multwrite(drive, rq, rq->nr_sectors)) {
-			spin_unlock_irqrestore(ch->lock, flags);
+		if (promise_multwrite(drive, rq, rq->nr_sectors))
 			return ide_stopped;
-		}
+
 		ch->poll_timeout = jiffies + WAIT_WORSTCASE;
 		ata_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
-		spin_unlock_irqrestore(ch->lock, flags);
 
 #ifdef DEBUG_WRITE
 		printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
@@ -666,7 +629,7 @@
 	/* Check that it's a regular command. If not, bomb out early. */
 	if (!(rq->flags & REQ_CMD)) {
 		blk_dump_rq_flags(rq, "pdc4030 bad flags");
-		ata_end_request(drive, rq, 0);
+		__ata_end_request(drive, rq, 0, 0);
 
 		return ide_stopped;
 	}
@@ -701,20 +664,11 @@
 				return promise_read_intr(drive, rq);
 			}
 			if (inb(IDE_SELECT_REG) & 0x01) {
-				unsigned long flags;
-				struct ata_channel *ch = drive->channel;
-
-				/* FIXME: this locking should encompass the above register
-				 * file access too.
-				 */
-
-				spin_lock_irqsave(ch->lock, flags);
 #ifdef DEBUG_READ
 				printk(KERN_DEBUG "%s: read: waiting for "
 				                  "interrupt\n", drive->name);
 #endif
 				ata_set_handler(drive, promise_read_intr, WAIT_CMD, NULL);
-				spin_unlock_irqrestore(ch->lock, flags);
 
 				return ide_started;
 			}
@@ -727,8 +681,6 @@
 
 	case WRITE: {
 		ide_startstop_t startstop;
-		unsigned long flags;
-		struct ata_channel *ch = drive->channel;
 
 		/*
 		 * Strategy on write is: look for the DRQ that should have been
@@ -740,28 +692,23 @@
 		 * completion must be polled
 		 */
 
-		/* FIXME: Move this lock upwards.
-		 */
-		spin_lock_irqsave(ch->lock, flags);
 		if (ata_status_poll(drive, DATA_READY, drive->bad_wstat,
 					WAIT_DRQ, rq, &startstop )) {
 			printk(KERN_ERR "%s: no DRQ after issuing "
 			       "PROMISE_WRITE\n", drive->name);
-			spin_unlock_irqrestore(ch->lock, flags);
 
 			return startstop;
 		}
 		if (!drive->channel->unmask)
 			__cli();	/* local CPU only */
-		spin_unlock_irqrestore(ch->lock, flags);
 
 		return promise_do_write(drive, rq);
 	}
 
 	default:
 		printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
-		/* FIXME: This should already run under the lock. */
-		ata_end_request(drive, rq, 0);
+
+		__ata_end_request(drive, rq, 0, 0);
 		return ide_stopped;
 	}
 }
diff -X dontdiff -ur linux-2.5.24/drivers/ide/tcq.c linux/drivers/ide/tcq.c
--- linux-2.5.24/drivers/ide/tcq.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/tcq.c	Wed Jun 26 19:53:14 2002
@@ -58,18 +58,15 @@
 static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq)
 {
 	struct ata_taskfile *args = rq->special;
-	unsigned long flags;
 
+	/* FIXME:  --bzolnier
 	ide__sti();
-
-	spin_lock_irqsave(drive->channel->lock, flags);
+	*/
 
 	blkdev_dequeue_request(rq);
 	drive->rq = NULL;
 	end_that_request_last(rq);
 
-	spin_unlock_irqrestore(drive->channel->lock, flags);
-
 	kfree(args);
 
 	return ide_stopped;
@@ -86,12 +83,9 @@
 	request_queue_t *q = &drive->queue;
 	struct ata_taskfile *ar;
 	struct request *rq;
-	unsigned long flags;
 
 	printk(KERN_INFO "ATA: %s: invalidating pending queue (%d)\n", drive->name, ata_pending_commands(drive));
 
-	spin_lock_irqsave(ch->lock, flags);
-
 	del_timer(&ch->timer);
 
 	if (test_bit(IDE_DMA, ch->active))
@@ -116,9 +110,9 @@
 		goto out;
 	}
 
-	rq = blk_get_request(&drive->queue, READ, GFP_ATOMIC);
+	rq = __blk_get_request(&drive->queue, READ);
 	if (!rq)
-		rq = blk_get_request(&drive->queue, WRITE, GFP_ATOMIC);
+		rq = __blk_get_request(&drive->queue, WRITE);
 
 	/*
 	 * blk_queue_invalidate_tags() just added back at least one command
@@ -143,7 +137,7 @@
 	 * start doing stuff again
 	 */
 	q->request_fn(q);
-	spin_unlock_irqrestore(ch->lock, flags);
+
 	printk(KERN_DEBUG "ATA: tcq_invalidate_queue: done\n");
 }
 
@@ -162,17 +156,20 @@
 	if (!ch->handler)
 		printk(KERN_ERR "ATA: %s: missing ISR!\n", __FUNCTION__);
 
-	spin_unlock_irqrestore(ch->lock, flags);
-
 	/*
 	 * if pending commands, try service before giving up
 	 */
 	if (ata_pending_commands(drive) && !ata_status(drive, 0, SERVICE_STAT))
-		if (service(drive, drive->rq) == ide_started)
+		if (service(drive, drive->rq) == ide_started) {
+			spin_unlock_irqrestore(ch->lock, flags);
+
 			return;
+		}
 
 	if (drive)
 		tcq_invalidate_queue(drive);
+
+	spin_unlock_irqrestore(ch->lock, flags);
 }
 
 static void __set_irq(struct ata_channel *ch, ata_handler_t *handler)
@@ -191,16 +188,6 @@
 	ch->handler = handler;
 }
 
-static void set_irq(struct ata_device *drive, ata_handler_t *handler)
-{
-	struct ata_channel *ch = drive->channel;
-	unsigned long flags;
-
-	spin_lock_irqsave(ch->lock, flags);
-	__set_irq(ch, handler);
-	spin_unlock_irqrestore(ch->lock, flags);
-}
-
 /*
  * wait 400ns, then poll for busy_mask to clear from alt status
  */
@@ -233,9 +220,6 @@
  */
 static ide_startstop_t service(struct ata_device *drive, struct request *rq)
 {
-	struct ata_channel *ch = drive->channel;
-	ide_startstop_t ret;
-	unsigned long flags;
 	u8 feat, stat;
 	int tag;
 
@@ -296,12 +280,10 @@
 
 	TCQ_PRINTK("%s: stat %x, feat %x\n", __FUNCTION__, stat, feat);
 
-	spin_lock_irqsave(ch->lock, flags);
-
 	rq = blk_queue_find_tag(&drive->queue, tag);
 	if (!rq) {
 		printk(KERN_ERR"%s: missing request for tag %d\n", __FUNCTION__, tag);
-		spin_unlock_irqrestore(ch->lock, flags);
+
 		return ide_stopped;
 	}
 
@@ -313,9 +295,7 @@
 	 */
 	TCQ_PRINTK("%s: starting command %x\n", __FUNCTION__, stat);
 
-	ret = udma_tcq_start(drive, rq);
-	spin_unlock_irqrestore(ch->lock, flags);
-	return ret;
+	return udma_tcq_start(drive, rq);
 }
 
 static ide_startstop_t check_service(struct ata_device *drive, struct request *rq)
@@ -331,15 +311,13 @@
 	/*
 	 * we have pending commands, wait for interrupt
 	 */
-	set_irq(drive, ide_dmaq_intr);
+	__set_irq(drive, ide_dmaq_intr);
 
 	return ide_started;
 }
 
 static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	u8 dma_stat;
 
 	/*
@@ -362,13 +340,7 @@
 
 	TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag);
 
-	/* FIXME: this locking should encompass the above register
-	 * file access too.
-	 */
-
-	spin_lock_irqsave(ch->lock, flags);
 	__ata_end_request(drive, rq, !dma_stat, rq->nr_sectors);
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	/*
 	 * we completed this command, check if we can service a new command
diff -X dontdiff -ur linux-2.5.24/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- linux-2.5.24/drivers/scsi/ide-scsi.c	Tue Jun 18 00:29:03 2002
+++ linux/drivers/scsi/ide-scsi.c	Thu Jun 27 02:18:19 2002
@@ -241,10 +241,9 @@
 	struct atapi_packet_command *pc = (struct atapi_packet_command *) rq->special;
 	int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
 	u8 *scsi_buf;
-	unsigned long flags;
 
 	if (!(rq->flags & REQ_PC)) {
-		ata_end_request(drive, rq, uptodate);
+		__ata_end_request(drive, rq, uptodate, 0);
 		return 0;
 	}
 
@@ -273,9 +272,7 @@
 		}
 	}
 	host = pc->s.scsi_cmd->host;
-	spin_lock_irqsave(host->host_lock, flags);
 	pc->s.done(pc->s.scsi_cmd);
-	spin_unlock_irqrestore(host->host_lock, flags);
 	idescsi_free_bio(rq->bio);
 	kfree(pc); kfree(rq);
 	scsi->pc = NULL;
@@ -293,8 +290,6 @@
  */
 static ide_startstop_t idescsi_pc_intr(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	struct Scsi_Host *host = drive->driver_data;
 	idescsi_scsi_t *scsi = idescsi_private(host);
 	u8 ireason;
@@ -335,8 +330,6 @@
 		temp = pc->actually_transferred + bcount;
 		if ( temp > pc->request_transfer) {
 			if (temp > pc->buffer_size) {
-				unsigned long flags;
-				struct ata_channel *ch = drive->channel;
 				printk (KERN_ERR "ide-scsi: The scsi wants to send us more data than expected - discarding data\n");
 				temp = pc->buffer_size - pc->actually_transferred;
 				if (temp) {
@@ -350,13 +343,8 @@
 				pc->actually_transferred += temp;
 				pc->current_position += temp;
 				atapi_discard_data(drive,bcount - temp);
-				/* FIXME: this locking should encompass the above register
-				 * file access too.
-				 */
 
-				spin_lock_irqsave(ch->lock, flags);
 				ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL);
-				spin_unlock_irqrestore(ch->lock, flags);
 
 				return ide_started;
 			}
@@ -381,21 +369,14 @@
 	pc->actually_transferred+=bcount;				/* Update the current position */
 	pc->current_position+=bcount;
 
-	/* FIXME: this locking should encompass the above register
-	 * file access too.
-	 */
-
-	spin_lock_irqsave(ch->lock, flags);
-	ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL);	/* And set the interrupt handler again */
-	spin_unlock_irqrestore(ch->lock, flags);
+	/* And set the interrupt handler again */
+	ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL);
 
 	return ide_started;
 }
 
 static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct request *rq)
 {
-	unsigned long flags;
-	struct ata_channel *ch = drive->channel;
 	struct Scsi_Host *host = drive->driver_data;
 	idescsi_scsi_t *scsi = idescsi_private(host);
 	struct atapi_packet_command *pc = scsi->pc;
@@ -403,9 +384,6 @@
 	ide_startstop_t startstop;
 	int ret;
 
-	/* FIXME: Move this lock upwards.
-	 */
-	spin_lock_irqsave(ch->lock, flags);
 	if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
 				WAIT_READY, rq, &startstop)) {
 		printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n");
@@ -422,7 +400,6 @@
 			ret = ide_started;
 		}
 	}
-	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -457,18 +434,9 @@
 		udma_start(drive, rq);
 	}
 	if (test_bit(IDESCSI_DRQ_INTERRUPT, &scsi->flags)) {
-		unsigned long flags;
-		struct ata_channel *ch = drive->channel;
-
-		/* FIXME: this locking should encompass the above register
-		 * file access too.
-		 */
-
-		spin_lock_irqsave(ch->lock, flags);
 		ata_set_handler(drive, idescsi_transfer_pc, get_timeout(pc), NULL);
-		spin_unlock_irqrestore(ch->lock, flags);
 
-		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);		/* Issue the packet command */
+		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
 		return ide_started;
 	} else {
 		OUT_BYTE (WIN_PACKETCMD, IDE_COMMAND_REG);
@@ -481,7 +449,6 @@
  */
 static ide_startstop_t idescsi_do_request(struct ata_device *drive, struct request *rq, sector_t block)
 {
-	struct ata_channel *ch = drive->channel;
 	int ret;
 
 #ifdef DEBUG
@@ -496,8 +463,6 @@
 			rq->current_nr_sectors);
 #endif
 
-	/* FIXME: make this unlocking go away*/
-	spin_unlock_irq(ch->lock);
 	if (rq->flags & REQ_PC) {
 		ret = idescsi_issue_pc(drive, rq, (struct atapi_packet_command *) rq->special);
 	} else {
@@ -505,7 +470,6 @@
 	    idescsi_end_request(drive, rq, 0);
 	    ret = ide_stopped;
 	}
-	spin_lock_irq(ch->lock);
 
 	return ret;
 }
@@ -720,9 +684,7 @@
 	rq->flags = REQ_PC;
 	rq->special = (char *) pc;
 	rq->bio = idescsi_dma_bio (drive, pc);
-	spin_unlock_irq(cmd->host->host_lock);
-	ide_do_drive_cmd (drive, rq, ide_end);
-	spin_lock_irq(cmd->host->host_lock);
+	ide_do_drive_cmd(drive, rq, ide_end);
 
 	return 0;
 abort:
diff -X dontdiff -ur linux-2.5.24/include/linux/blkdev.h linux/include/linux/blkdev.h
--- linux-2.5.24/include/linux/blkdev.h	Mon Jun 24 22:20:54 2002
+++ linux/include/linux/blkdev.h	Wed Jun 26 17:21:41 2002
@@ -283,7 +283,9 @@
 extern inline request_queue_t *bdev_get_queue(struct block_device *bdev);
 extern void blkdev_release_request(struct request *);
 extern void blk_attempt_remerge(request_queue_t *, struct request *);
+extern void __blk_attempt_remerge(request_queue_t *, struct request *);
 extern struct request *blk_get_request(request_queue_t *, int, int);
+extern struct request *__blk_get_request(request_queue_t *, int);
 extern void blk_put_request(struct request *);
 extern void blk_plug_device(request_queue_t *);
 extern int blk_remove_plug(request_queue_t *);
diff -X dontdiff -ur linux-2.5.24/include/linux/ide.h linux/include/linux/ide.h
--- linux-2.5.24/include/linux/ide.h	Wed Jun 26 00:02:53 2002
+++ linux/include/linux/ide.h	Thu Jun 27 01:39:37 2002
@@ -381,7 +381,7 @@
  *  Interrupt and timeout handler type.
  */
 typedef ide_startstop_t (ata_handler_t)(struct ata_device *, struct request *);
-typedef int (ata_expiry_t)(struct ata_device *, struct request *);
+typedef ide_startstop_t (ata_expiry_t)(struct ata_device *, struct request *, unsigned long *);
 
 enum {
 	ATA_PRIMARY	= 0,
@@ -406,7 +406,7 @@
 
 	ide_startstop_t (*handler)(struct ata_device *, struct request *);	/* irq handler, if active */
 	struct timer_list timer;				/* failsafe timer */
-	int (*expiry)(struct ata_device *, struct request *);	/* irq handler, if active */
+	ide_startstop_t (*expiry)(struct ata_device *, struct request *, unsigned long *);	/* irq handler, if active */
 	unsigned long poll_timeout;				/* timeout value during polled operations */
 	struct ata_device *drive;				/* last serviced drive */
 
@@ -602,9 +602,7 @@
 #define DEVICE_NR(device)	(minor(device) >> PARTN_BITS)
 #include <linux/blk.h>
 
-/* Not locking and locking variant: */
 extern int __ata_end_request(struct ata_device *, struct request *, int, unsigned int);
-extern int ata_end_request(struct ata_device *drive, struct request *, int);
 
 extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
 		unsigned long timeout, ata_expiry_t expiry);
@@ -626,12 +624,6 @@
 struct ata_device *get_info_ptr(kdev_t i_rdev);
 
 /*
- * Re-Start an operation for an IDE interface.
- * The caller should return immediately after invoking this.
- */
-ide_startstop_t restart_request(struct ata_device *);
-
-/*
  * "action" parameter type for ide_do_drive_cmd() below.
  */
 typedef enum {

Copyright © 2002, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds