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)