|
|
Log in / Subscribe / Register

2.5.24 IDE 96

Ok, this should fix some pending issues...

Tue Jul  2 21:27:44 CEST 2002 ide-clean-96

- revert to previous (2.4.x + channel->lock) locking scheme

- bring back ide__sti() calls

- fix bug introduced in IDE 63 in ide_do_drive_cmd(), if action is ide_end
  request should be added to end of queue not next to current request,
  fortunately it is used only by ide-tape which is broken anyway

- fix bug introduced in IDE 94 in idedisk_do_request(), removal of
  rq->special = ar; probably needed by PMAC and TCQ

- fix bug introduced in IDE 94 in do_request(), always setting IDE_BUSY
  bit could lead to deadlock

- in check_crc_errors() do strict checking for UDMA modes

- clean double setting handler/timer hack

- remove CAP_SYS_ADMIN check from HDIO_GET* ioctls


diff -ur -Xdontdiff linux-2.5.24/drivers/ide/device.c linux/drivers/ide/device.c
--- linux-2.5.24/drivers/ide/device.c	Tue Jun 18 00:29:02 2002
+++ linux/drivers/ide/device.c	Tue Jul  2 17:30:20 2002
@@ -86,14 +86,21 @@
  */
 int ata_busy_poll(struct ata_device *drive, unsigned long timeout)
 {
+	unsigned long flags;
+
 	/* spec allows drive 400ns to assert "BUSY" */
 	udelay(1);
 	if (!ata_status(drive, 0, BUSY_STAT)) {
+		__save_flags(flags);
+		ide__sti();
 		timeout += jiffies;
 		while (!ata_status(drive, 0, BUSY_STAT)) {
-			if (time_after(jiffies, timeout))
+			if (time_after(jiffies, timeout)) {
+				__restore_flags(flags);
 				return 1;
+			}
 		}
+		__restore_flags(flags);
 	}
 
 	return 0;
@@ -101,8 +108,6 @@
 
 /*
  * Check the state of the status register.
- *
- * FIXME: Channel lock should be held.
  */
 int ata_status(struct ata_device *drive, u8 good, u8 bad)
 {
@@ -125,8 +130,6 @@
  * That could be done by busy-waiting for the first jiffy or two, and then
  * setting a timer to wake up at half second intervals thereafter, until
  * timeout is achieved, before timing out.
- *
- * Channel lock should be held.
  */
 int ata_status_poll(struct ata_device *drive, u8 good, u8 bad,
 		unsigned long timeout,
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- linux-2.5.24/drivers/ide/ide-cd.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/ide-cd.c	Tue Jul  2 16:53:55 2002
@@ -1213,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;
@@ -1591,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;
 
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- linux-2.5.24/drivers/ide/ide-disk.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/ide-disk.c	Tue Jul  2 17:37:11 2002
@@ -107,11 +107,6 @@
 }
 
 /*
- * 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)
@@ -257,7 +252,6 @@
 
 static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq)
 {
-	struct ata_channel *ch = drive->channel;
 	int ok;
 	int ret;
 
@@ -279,14 +273,16 @@
 		rq->bio = NULL;
 		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);
+		/* not ready yet, so wait for next IRQ */
+		ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
+
 		ret = ide_started;
 	} else {
 		int mcount = drive->mult_count;
 
+		/* prepare for next IRQ */
+		ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
+
 		do {
 			char *buf;
 			int nsect = rq->current_nr_sectors;
@@ -314,6 +310,7 @@
 					rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
 				}
 			}
+			rq->errors = 0; /* FIXME: why?  --bzolnier */
 
 			/*
 			 * Ok, we're all setup for the interrupt re-entering us on the
@@ -323,12 +320,6 @@
 			bio_kunmap_irq(buf, &flags);
 		} while (mcount);
 
-		rq->errors = 0;
-
-		/* FIXME:  --bzolnier */
-		if (!ch->handler)
-			ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
-
 		ret = ide_started;
 	}
 
@@ -339,8 +330,6 @@
  * Issue a READ or WRITE command to a disk, using LBA if supported, or CHS
  * otherwise, to address sectors.  It also takes care of issuing special
  * DRIVE_CMDs.
- *
- * Channel lock should be held.
  */
 static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct request *rq, sector_t block)
 {
@@ -526,10 +515,7 @@
 		printk("buffer=%p\n", rq->buffer);
 #endif
 	}
-
-	/*
-	 * Channel lock should be held on entry.
-	 */
+	rq->special = ar;
 
 	/* (ks/hs): Moved to start, do not use for multiple out commands.
 	 * FIXME: why not?! */
@@ -552,28 +538,25 @@
 	/* FIXME: this is actually distingushing between PIO and DMA requests.
 	 */
 	if (ar->XXX_handler) {
+		if (ar->command_type == IDE_DRIVE_TASK_IN ||
+		    ar->command_type == IDE_DRIVE_TASK_NO_DATA) {
+
+			ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL);
+			OUT_BYTE(cmd, IDE_COMMAND_REG);
 
-		ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL);
-		OUT_BYTE(cmd, IDE_COMMAND_REG);
+			return ide_started;
+		}
 
 		/* FIXME: Warning check for race between handler and prehandler
 		 * for writing first block of data.  however since we are well
 		 * inside the boundaries of the seek, we should be okay.
-		 *
-		 * FIXME: Replace the switch by using a proper command_type.
+		 * FIXME: should be fixed  --bzolnier
 		 */
-
-		if (cmd == CFA_WRITE_SECT_WO_ERASE ||
-		    cmd == WIN_WRITE ||
-		    cmd == WIN_WRITE_EXT ||
-		    cmd == WIN_WRITE_VERIFY ||
-		    cmd == WIN_WRITE_BUFFER ||
-		    cmd == WIN_DOWNLOAD_MICROCODE ||
-		    cmd == CFA_WRITE_MULTI_WO_ERASE ||
-		    cmd == WIN_MULTWRITE ||
-		    cmd == WIN_MULTWRITE_EXT) {
+		if (ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) {
 			ide_startstop_t startstop;
 
+			OUT_BYTE(cmd, IDE_COMMAND_REG);
+
 			if (ata_status_poll(drive, DATA_READY, drive->bad_wstat,
 						WAIT_DRQ, rq, &startstop)) {
 				printk(KERN_ERR "%s: no DRQ after issuing %s\n",
@@ -591,7 +574,10 @@
 				unsigned long flags;
 				char *buf = ide_map_rq(rq, &flags);
 
+				ata_set_handler(drive, ar->XXX_handler, WAIT_CMD, NULL);
+
 				/* For Write_sectors we need to stuff the first sector */
+				/* FIXME: what if !rq->current_nr_sectors  --bzolnier */
 				ata_write(drive, buf, SECTOR_WORDS);
 
 				rq->current_nr_sectors--;
@@ -621,6 +607,7 @@
 					printk(KERN_ERR "DISASTER WAITING TO HAPPEN!\n");
 				}
 
+				/* will set handler for us */
 				return ar->XXX_handler(drive, rq);
 			}
 		}
@@ -632,6 +619,7 @@
 		 * FIXME: Handle the alternateives by a command type.
 		 */
 
+		/* FIXME: ide_started?  --bzolnier */
 		if (!drive->using_dma)
 			return ide_started;
 
@@ -656,6 +644,7 @@
 		}
 	}
 
+	/* not reached */
 	return ide_started;
 }
 
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c
--- linux-2.5.24/drivers/ide/ide-floppy.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/ide-floppy.c	Tue Jul  2 17:41:31 2002
@@ -346,6 +346,8 @@
  */
 static int idefloppy_end_request(struct ata_device *drive, struct request *rq, int uptodate)
 {
+	unsigned long flags;
+	struct ata_channel *ch = drive->channel;
 	idefloppy_floppy_t *floppy = drive->driver_data;
 	int error;
 
@@ -369,11 +371,15 @@
 		return 0;
 	}
 
+	spin_lock_irqsave(ch->lock, flags);
+
 	rq->errors = error;
 	blkdev_dequeue_request(rq);
 	drive->rq = NULL;
 	end_that_request_last(rq);
 
+	spin_unlock_irqrestore(ch->lock, flags);
+
 	return 0;
 }
 
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c
--- linux-2.5.24/drivers/ide/ide-tape.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/ide-tape.c	Tue Jul  2 17:39:57 2002
@@ -1622,7 +1622,7 @@
 static int idetape_end_request(struct ata_device *drive, struct request *rq, int uptodate)
 {
 	idetape_tape_t *tape = drive->driver_data;
-	unsigned long flags;
+	unsigned long flags, flags2;
 	int error;
 	int remove_stage = 0;
 #if ONSTREAM_DEBUG
@@ -1709,10 +1709,15 @@
 		}
 	}
 
+	/* FIXME: replace tape->spinlock with channel->spinlock  --bzolnier */
+	spin_lock_irqsave(drive->channel->lock, flags2);
+
 	blkdev_dequeue_request(rq);
 	drive->rq = NULL;
 	end_that_request_last(rq);
 
+	spin_unlock_irqrestore(drive->channel->lock, flags2);
+
 	if (remove_stage)
 		idetape_remove_stage_head(drive);
 	if (tape->active_data_request == NULL)
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.24/drivers/ide/ide-taskfile.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/ide-taskfile.c	Tue Jul  2 17:35:47 2002
@@ -197,13 +197,14 @@
 int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t action)
 {
 	unsigned long flags;
-	unsigned int major = drive->channel->major;
+	struct ata_channel *ch = drive->channel;
+	unsigned int major = ch->major;
 	request_queue_t *q = &drive->queue;
 	struct list_head *queue_head = &q->queue_head;
 	DECLARE_COMPLETION(wait);
 
 #ifdef CONFIG_BLK_DEV_PDC4030
-	if (drive->channel->chipset == ide_pdc4030 && rq->buffer != NULL)
+	if (ch->chipset == ide_pdc4030 && rq->buffer)
 		return -ENOSYS;  /* special drive cmds not supported */
 #endif
 	rq->errors = 0;
@@ -212,22 +213,18 @@
 	if (action == ide_wait)
 		rq->waiting = &wait;
 
-	spin_lock_irqsave(drive->channel->lock, flags);
+	spin_lock_irqsave(ch->lock, flags);
+
+	if (action == ide_preempt)
+		drive->rq = NULL;
+	else if (!blk_queue_empty(&drive->queue))
+		queue_head = queue_head->prev;	/* ide_end and ide_wait */
 
-	if (blk_queue_empty(&drive->queue) || action == ide_preempt) {
-		if (action == ide_preempt)
-			drive->rq = NULL;
-	} else {
-		if (action == ide_wait)
-			queue_head = queue_head->prev;
-		else
-			queue_head = queue_head->next;
-	}
 	q->elevator.elevator_add_req_fn(q, rq, queue_head);
 
 	do_ide_request(q);
 
-	spin_unlock_irqrestore(drive->channel->lock, flags);
+	spin_unlock_irqrestore(ch->lock, flags);
 
 	if (action == ide_wait) {
 		wait_for_completion(&wait);	/* wait for it to be serviced */
@@ -235,25 +232,20 @@
 	}
 
 	return 0;
-
 }
 
 
 /*
  * 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) {
-
+	unsigned long flags;
+	struct ata_channel *ch =drive->channel;
 	struct ata_taskfile *ar = rq->special;
 	ide_startstop_t ret = ide_stopped;
 
-	/* FIXME:  --bzolnier
 	ide__sti();
-	*/
 
 	if (rq->buffer && ar->taskfile.sector_number) {
 		if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) {
@@ -285,10 +277,14 @@
 		ata_in_regfile(drive, &ar->hobfile);
 	}
 
+	spin_lock_irqsave(ch->lock, flags);
+
 	blkdev_dequeue_request(rq);
 	drive->rq = NULL;
 	end_that_request_last(rq);
 
+	spin_unlock_irqrestore(ch->lock, flags);
+
 	return ret;
 }
 
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.24/drivers/ide/ide.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/ide.c	Tue Jul  2 17:36:23 2002
@@ -106,15 +106,14 @@
 	return 0;
 }
 
-/*
- * Not locking variabt of the end_request method.
- *
- * Channel lock should be held.
- */
 int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs)
 {
+	unsigned long flags;
+	struct ata_channel *ch = drive->channel;
 	int ret = 1;
 
+	spin_lock_irqsave(ch->lock, flags);
+
 	BUG_ON(!(rq->flags & REQ_STARTED));
 
 	/* FIXME: Make this "small" hack to eliminate locking from
@@ -143,6 +142,7 @@
 		ret = 0;
 	}
 
+	spin_unlock_irqrestore(ch->lock, flags);
 
 	return ret;
 }
@@ -153,14 +153,16 @@
  * at the appropriate code to handle the next interrupt, and a
  * timer is started to prevent us from waiting forever in case
  * something goes wrong (see the ide_timer_expiry() handler later on).
- *
- * Channel lock should be held.
  */
 void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
 		      unsigned long timeout, ata_expiry_t expiry)
 {
+	unsigned long flags;
 	struct ata_channel *ch = drive->channel;
 
+	spin_lock_irqsave(ch->lock, flags);
+
+	/* FIXME: change it later to BUG_ON(ch->handler)  --bzolnier */
 	if (ch->handler)
 		printk("%s: %s: handler not null; old=%p, new=%p, from %p\n",
 			drive->name, __FUNCTION__, ch->handler, handler, __builtin_return_address(0));
@@ -172,48 +174,35 @@
 
 	add_timer(&ch->timer);
 
+	spin_unlock_irqrestore(ch->lock, flags);
 }
 
 static void check_crc_errors(struct ata_device *drive)
 {
 	if (!drive->using_dma)
-	    return;
+		return;
 
 	/* check the DMA crc count */
 	if (drive->crc_count) {
 		udma_enable(drive, 0, 0);
 		if (drive->channel->speedproc) {
-			u8 pio = XFER_PIO_4;
+			u8 mode = drive->current_speed;
 			drive->crc_count = 0;
 
-			switch (drive->current_speed) {
-			case XFER_UDMA_7: pio = XFER_UDMA_6;
-				break;
-			case XFER_UDMA_6: pio = XFER_UDMA_5;
-				break;
-			case XFER_UDMA_5: pio = XFER_UDMA_4;
-				break;
-			case XFER_UDMA_4: pio = XFER_UDMA_3;
-				break;
-			case XFER_UDMA_3: pio = XFER_UDMA_2;
-				break;
-			case XFER_UDMA_2: pio = XFER_UDMA_1;
-				break;
-			case XFER_UDMA_1: pio = XFER_UDMA_0;
-				break;
+			if (mode > XFER_UDMA_0)
+				mode--;
+			else
 			/*
 			 * OOPS we do not goto non Ultra DMA modes
 			 * without iCRC's available we force
 			 * the system to PIO and make the user
 			 * invoke the ATA-1 ATA-2 DMA modes.
 			 */
-			case XFER_UDMA_0:
-			default:
-				pio = XFER_PIO_4;
-			}
-		        drive->channel->speedproc(drive, pio);
+				mode = XFER_PIO_4;
+
+			drive->channel->speedproc(drive, mode);
 		}
-		if (drive->current_speed >= XFER_SW_DMA_0)
+		if (drive->current_speed >= XFER_UDMA_0)
 			udma_enable(drive, 1, 1);
 	} else
 		udma_enable(drive, 0, 1);
@@ -246,8 +235,6 @@
  * Poll the interface for completion every 50ms during an ATAPI drive reset
  * operation. If the drive has not yet responded, and we have not yet hit our
  * maximum waiting time, then the timer is restarted for another 50ms.
- *
- * Channel lock should be held.
  */
 static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
 {
@@ -279,8 +266,6 @@
  * Poll the interface for completion every 50ms during an ata reset operation.
  * If the drives have not yet responded, and we have not yet hit our maximum
  * waiting time, then the timer is restarted for another 50ms.
- *
- * Channel lock should be held.
  */
 static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
 {
@@ -348,10 +333,7 @@
  * Equally poor, though, is the fact that this may a very long time to
  * complete, (up to 30 seconds worst case).  So, instead of busy-waiting here
  * for it, we set a timer to poll at 50ms intervals.
- *
- * Channel lock should be held.
  */
-
 static ide_startstop_t do_reset1(struct ata_device *drive, int try_atapi)
 {
 	unsigned int unit;
@@ -558,8 +540,6 @@
 
 /*
  * Take action based on the error returned by the drive.
- *
- * Channel lock should be held.
  */
 ide_startstop_t ata_error(struct ata_device *drive, struct request *rq,	const char *msg)
 {
@@ -812,6 +792,7 @@
 		struct ata_channel *ch;
 		struct ata_device *drive;
 		struct request *rq = NULL;
+		ide_startstop_t startstop;
 		int i;
 
 		/* this will clear IDE_BUSY, if appropriate */
@@ -901,12 +882,16 @@
 
 			drive->rq = rq;
 
+			spin_unlock(ch->lock);
 			ide__sti();	/* allow other IRQs while we start this request */
+			startstop = start_request(drive, rq);
+			spin_lock_irq(ch->lock);
+
 			/* command started, we are busy */
-		} while (ide_started != start_request(drive, rq));
+		} while (startstop != ide_started);
 		/* make sure the BUSY bit is set */
 		/* FIXME: perhaps there is some place where we miss to set it? */
-		set_bit(IDE_BUSY, ch->active);
+//		set_bit(IDE_BUSY, ch->active);
 	}
 }
 
@@ -1166,15 +1151,16 @@
 	ch->handler = NULL;
 	del_timer(&ch->timer);
 
-	if (ch->unmask) {
-		/* FIXME: perhaps disable_irq(irq); __sti(); ? -Zwane
+	spin_unlock(ch->lock);
+
+	if (ch->unmask)
 		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
 	 * interrupt to occur soon, but it cannot happen until
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/ioctl.c linux/drivers/ide/ioctl.c
--- linux-2.5.24/drivers/ide/ioctl.c	Wed Jun 26 00:02:53 2002
+++ linux/drivers/ide/ioctl.c	Sun Jun 30 22:16:50 2002
@@ -122,9 +122,6 @@
 		case HDIO_GET_32BIT: {
 			unsigned long val = drive->channel->io_32bit;
 
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-
 			if (put_user(val, (unsigned long *) arg))
 				return -EFAULT;
 			return 0;
@@ -172,9 +169,6 @@
 		case HDIO_GET_UNMASKINTR: {
 			unsigned long val = drive->channel->unmask;
 
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-
 			if (put_user(val, (unsigned long *) arg))
 				return -EFAULT;
 
@@ -202,9 +196,6 @@
 		case HDIO_GET_DMA: {
 			unsigned long val = drive->using_dma;
 
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-
 			if (put_user(val, (unsigned long *) arg))
 				return -EFAULT;
 
@@ -236,9 +227,6 @@
 			struct hd_geometry *loc = (struct hd_geometry *) arg;
 			unsigned short bios_cyl = drive->bios_cyl; /* truncate */
 
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-
 			if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
 				return -EINVAL;
 
@@ -261,9 +249,6 @@
 		case HDIO_GETGEO_BIG_RAW: {
 			struct hd_big_geometry *loc = (struct hd_big_geometry *) arg;
 
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
-
 			if (!loc || (drive->type != ATA_DISK && drive->type != ATA_FLOPPY))
 				return -EINVAL;
 
@@ -284,8 +269,6 @@
 		}
 
 		case HDIO_GET_IDENTITY:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
 
 			if (minor(inode->i_rdev) & PARTN_MASK)
 				return -EINVAL;
@@ -299,8 +282,6 @@
 			return 0;
 
 		case HDIO_GET_NICE:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
 
 			return put_user(drive->dsc_overlap << IDE_NICE_DSC_OVERLAP |
 					drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP,
@@ -323,8 +304,6 @@
 			return 0;
 
 		case HDIO_GET_BUSSTATE:
-			if (!capable(CAP_SYS_ADMIN))
-				return -EACCES;
 
 			if (put_user(drive->channel->bus_state, (long *)arg))
 				return -EFAULT;
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/pcidma.c linux/drivers/ide/pcidma.c
--- linux-2.5.24/drivers/ide/pcidma.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/pcidma.c	Tue Jul  2 17:28:02 2002
@@ -36,8 +36,6 @@
 
 /*
  * 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)
 {
@@ -394,8 +392,6 @@
 
 /*
  * Teardown mappings after DMA has completed.
- *
- * Channel lock should be held.
  */
 void udma_destroy_table(struct ata_channel *ch)
 {
@@ -406,8 +402,6 @@
  * Prepare the channel for a DMA startfer. Please note that only the broken
  * Pacific Digital host chip needs the reques to be passed there to decide
  * about addressing modes.
- *
- * Channel lock should be held.
  */
 void udma_pci_start(struct ata_device *drive, struct request *rq)
 {
@@ -421,9 +415,6 @@
 	outb(inb(dma_base) | 1, dma_base);	/* start DMA */
 }
 
-/*
- * Channel lock should be held.
- */
 int udma_pci_stop(struct ata_device *drive)
 {
 	struct ata_channel *ch = drive->channel;
@@ -440,8 +431,6 @@
 
 /*
  * FIXME: This should be attached to a channel as we can see now!
- *
- * Channel lock should be held.
  */
 int udma_pci_irq_status(struct ata_device *drive)
 {
@@ -528,8 +517,6 @@
  *
  * It's exported only for host chips which use it for fallback or (too) late
  * capability checking.
- *
- * Channel lock should be held.
  */
 int udma_pci_init(struct ata_device *drive, struct request *rq)
 {
diff -ur -Xdontdiff linux-2.5.24/drivers/ide/tcq.c linux/drivers/ide/tcq.c
--- linux-2.5.24/drivers/ide/tcq.c	Thu Jun 27 13:34:42 2002
+++ linux/drivers/ide/tcq.c	Tue Jul  2 18:13:51 2002
@@ -57,16 +57,19 @@
 
 static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request *rq)
 {
+	unsigned long flags;
 	struct ata_taskfile *args = rq->special;
 
-	/* FIXME:  --bzolnier
 	ide__sti();
-	*/
+
+	spin_lock_irqsave(ch->lock, flags);
 
 	blkdev_dequeue_request(rq);
 	drive->rq = NULL;
 	end_that_request_last(rq);
 
+	spin_unlock_irqrestore(ch->lock, flags);
+
 	kfree(args);
 
 	return ide_stopped;
@@ -83,9 +86,12 @@
 	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))
@@ -137,7 +143,7 @@
 	 * start doing stuff again
 	 */
 	q->request_fn(q);
-
+	spin_unlock_irqrestore(ch->lock, flags);
 	printk(KERN_DEBUG "ATA: tcq_invalidate_queue: done\n");
 }
 
@@ -156,20 +162,17 @@
 	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) {
-			spin_unlock_irqrestore(ch->lock, flags);
-
+		if (service(drive, drive->rq) == ide_started)
 			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)
@@ -188,6 +191,16 @@
 	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
  */
@@ -215,11 +228,12 @@
  * and it must have reported a need for service (status has SERVICE_STAT set)
  *
  * Also, nIEN must be set as not to need protection against ide_dmaq_intr
- *
- * Channel lock should be held.
  */
 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;
 
@@ -280,15 +294,18 @@
 
 	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;
 	}
 
 	drive->rq = rq;
 
+	spin_unlock_irqrestore(ch->lock, flags);
 	/*
 	 * we'll start a dma read or write, device will trigger
 	 * interrupt to indicate end of transfer, release is not allowed
@@ -311,7 +328,7 @@
 	/*
 	 * we have pending commands, wait for interrupt
 	 */
-	__set_irq(drive, ide_dmaq_intr);
+	set_irq(drive, ide_dmaq_intr);
 
 	return ide_started;
 }
@@ -504,8 +521,6 @@
 /*
  * Invoked from a SERVICE interrupt, command etc already known.  Just need to
  * start the dma engine for this tag.
- *
- * Channel lock should be held.
  */
 static ide_startstop_t udma_tcq_start(struct ata_device *drive, struct request *rq)
 {
@@ -521,7 +536,7 @@
 	if (ata_start_dma(drive, rq))
 		return ide_stopped;
 
-	__set_irq(ch, ide_dmaq_intr);
+	set_irq(ch, ide_dmaq_intr);
 	udma_start(drive, rq);
 
 	return ide_started;
@@ -529,8 +544,6 @@
 
 /*
  * Start a queued command from scratch.
- *
- * Channel lock should be held.
  */
 ide_startstop_t udma_tcq_init(struct ata_device *drive, struct request *rq)
 {
@@ -573,7 +586,7 @@
 	if ((feat = GET_FEAT()) & NSEC_REL) {
 		drive->immed_rel++;
 		drive->rq = NULL;
-		__set_irq(drive->channel, ide_dmaq_intr);
+		set_irq(drive->channel, ide_dmaq_intr);
 
 		TCQ_PRINTK("REL in queued_start\n");
 
diff -ur -Xdontdiff linux-2.5.24/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- linux-2.5.24/drivers/scsi/ide-scsi.c	Fri Jun 28 00:03:06 2002
+++ linux/drivers/scsi/ide-scsi.c	Tue Jul  2 17:32:47 2002
@@ -236,6 +236,7 @@
 
 static int idescsi_end_request(struct ata_device *drive, struct request *rq, int uptodate)
 {
+	unsigned long flags;
 	struct Scsi_Host *host = drive->driver_data;
 	idescsi_scsi_t *scsi = idescsi_private(host);
 	struct atapi_packet_command *pc = (struct atapi_packet_command *) rq->special;
@@ -247,10 +248,14 @@
 		return 0;
 	}
 
+	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);
+
 	if (rq->errors >= ERROR_MAX) {
 		pc->s.scsi_cmd->result = DID_ERROR << 16;
 		if (log)

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