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)