patch-2.1.88 linux/drivers/block/ide-disk.c

Next file: linux/drivers/block/ide.c
Previous file: linux/drivers/block/ide-cd.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.87/linux/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
@@ -105,12 +105,15 @@
 	int i;
 	unsigned int msect, nsect;
 	struct request *rq;
+	unsigned long flags;
 
 	if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT)) {
 		ide_error(drive, "read_intr", stat);
 		return;
 	}
 	msect = drive->mult_count;
+	
+	spin_lock_irqsave(&io_request_lock,flags);
 read_next:
 	rq = HWGROUP(drive)->rq;
 	if (msect) {
@@ -119,6 +122,12 @@
 		msect -= nsect;
 	} else
 		nsect = 1;
+	/*
+	 * PIO input can take longish times, so we drop the spinlock.
+	 * On SMP, bad things might happen if syscall level code adds
+	 * a new request while we do this PIO, so we just freeze all
+	 * request queue handling while doing the PIO. FIXME
+	 */
 	idedisk_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
 #ifdef DEBUG
 	printk("%s:  read: sectors(%ld-%ld), buffer=0x%08lx, remaining=%ld\n",
@@ -136,6 +145,7 @@
 			goto read_next;
 		ide_set_handler (drive, &read_intr, WAIT_CMD);
 	}
+	spin_unlock_irqrestore(&io_request_lock,flags);
 }
 
 /*
@@ -147,7 +157,10 @@
 	int i;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	struct request *rq = hwgroup->rq;
+	unsigned long flags;
+	int error = 0;
 
+	spin_lock_irqsave(&io_request_lock,flags);
 	if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
 #ifdef DEBUG
 		printk("%s: write: sector %ld, buffer=0x%08lx, remaining=%ld\n",
@@ -166,10 +179,16 @@
 				idedisk_output_data (drive, rq->buffer, SECTOR_WORDS);
 				ide_set_handler (drive, &write_intr, WAIT_CMD);
 			}
-			return;
+			goto out;
 		}
-	}
-	ide_error(drive, "write_intr", stat);
+	} else
+		error = 1;
+
+out:
+	spin_unlock_irqrestore(&io_request_lock,flags);
+
+	if (error)
+		ide_error(drive, "write_intr", stat);
 }
 
 /*
@@ -217,13 +236,16 @@
 	int i;
 	ide_hwgroup_t *hwgroup = HWGROUP(drive);
 	struct request *rq = &hwgroup->wrq;
+	unsigned long flags;
+	int error = 0;
 
+	spin_lock_irqsave(&io_request_lock,flags);
 	if (OK_STAT(stat=GET_STAT(),DRIVE_READY,drive->bad_wstat)) {
 		if (stat & DRQ_STAT) {
 			if (rq->nr_sectors) {
 				ide_multwrite(drive, drive->mult_count);
 				ide_set_handler (drive, &multwrite_intr, WAIT_CMD);
-				return;
+				goto out;
 			}
 		} else {
 			if (!rq->nr_sectors) {	/* all done? */
@@ -232,11 +254,17 @@
 					i -= rq->current_nr_sectors;
 					ide_end_request(1, hwgroup);
 				}
-				return;
+				goto out;
 			}
 		}
-	}
-	ide_error(drive, "multwrite_intr", stat);
+	} else
+		error = 1;
+
+out:
+	spin_unlock_irqrestore(&io_request_lock,flags);
+
+	if (error)
+		ide_error(drive, "multwrite_intr", stat);
 }
 
 /*
@@ -354,7 +382,7 @@
 			return;
 		}
 		if (!drive->unmask)
-			cli();
+			__cli();
 		if (drive->mult_count) {
 			HWGROUP(drive)->wrq = *rq; /* scratchpad */
 			ide_set_handler (drive, &multwrite_intr, WAIT_CMD);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov