lkml.org 
[lkml]   [2002]   [Jul]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: ata_special_intr, ide_do_drive_cmd deadlock

On Sun, 7 Jul 2002, Zwane Mwaikambo wrote:

> On Sun, 7 Jul 2002, Zwane Mwaikambo wrote:
>
> > > If it was IDE 95, or IDE 95 on atapi device it is known, noted in 95's
> > > changelog and fixed in 96...
> >
> > On ATA disk, with 2.5.25 stock and the deadlock is still there (visual
> > inspection) in IDE 97
>
> Sorry perhaps let me elaborate, i was doing a dd if=/dev/hdX of=file then
> the drive dropped down to PIO, thats when i reckon i hit do_recalibrate.
> This was on 2.5.25.

do_recalibrate is called under lock and it tries to acquire lock, so
deadlock, you was the first to notice it and you have even added FIXME
to the code... ;-)

Do you realise that 2.5.25 have IDE 93 and it should be fixed in IDE 96.

BTW: know problem with 96 is broken ide_timer_expiry().
Attached IDE 98 (or not) prepatch should fix it.

--
Bartlomiej

>
> Thanks,
> Zwane Mwaikambo
>
> --
> function.linuxpower.ca
>
>
>
diff -ur -X/home/dontdiff linux-2.5.24/drivers/ide/alim15x3.c linux/drivers/ide/alim15x3.c
--- linux-2.5.24/drivers/ide/alim15x3.c Tue Jul 2 23:54:16 2002
+++ linux/drivers/ide/alim15x3.c Thu Jul 4 19:53:06 2002
@@ -362,8 +362,10 @@

static void __init ali15x3_init_dma(struct ata_channel *ch, unsigned long dmabase)
{
- if ((dmabase) && (m5229_revision < 0x20))
+ if (dmabase && (m5229_revision < 0x20)) {
+ ch->autodma = 0;
return;
+ }

ata_init_dma(ch, dmabase);
}
diff -ur -X/home/dontdiff linux-2.5.24/drivers/ide/ide-pci.c linux/drivers/ide/ide-pci.c
--- linux-2.5.24/drivers/ide/ide-pci.c Tue Jul 2 23:54:16 2002
+++ linux/drivers/ide/ide-pci.c Fri Jul 5 00:47:28 2002
@@ -313,13 +313,14 @@
* already enabled by the primary channel run.
*/
pci_set_master(dev);
+
+ if (autodma)
+ ch->autodma = 1;
+
if (d->init_dma)
d->init_dma(ch, dma_base);
else
ata_init_dma(ch, dma_base);
-
- if (ch->dma_base && autodma)
- ch->autodma = 1;
#endif

no_dma:
diff -ur -X/home/dontdiff linux-2.5.24/drivers/ide/ide-taskfile.c linux/drivers/ide/ide-taskfile.c
--- linux-2.5.24/drivers/ide/ide-taskfile.c Tue Jul 2 17:35:47 2002
+++ linux/drivers/ide/ide-taskfile.c Fri Jul 5 01:30:41 2002
@@ -220,7 +220,7 @@
else if (!blk_queue_empty(&drive->queue))
queue_head = queue_head->prev; /* ide_end and ide_wait */

- q->elevator.elevator_add_req_fn(q, rq, queue_head);
+ __elv_add_request(q, rq, queue_head);

do_ide_request(q);

diff -ur -X/home/dontdiff linux-2.5.24/drivers/ide/ide.c linux/drivers/ide/ide.c
--- linux-2.5.24/drivers/ide/ide.c Tue Jul 2 17:36:23 2002
+++ linux/drivers/ide/ide.c Fri Jul 5 01:21:30 2002
@@ -277,6 +277,7 @@
ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
ret = ide_started; /* continue polling */
} else {
+ ch->poll_timeout = 0; /* done polling */
printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status);
++drive->failures;
ret = ide_stopped;
@@ -284,6 +285,7 @@
} else {
u8 stat;

+ ch->poll_timeout = 0; /* done polling */
printk("%s: reset: ", ch->name);
if ((stat = GET_ERR()) == 1) {
printk("success\n");
@@ -314,7 +316,6 @@

ret = ide_stopped;
}
- ch->poll_timeout = 0; /* done polling */

return ret;
}
@@ -337,25 +338,17 @@
static ide_startstop_t do_reset1(struct ata_device *drive, int try_atapi)
{
unsigned int unit;
- unsigned long flags;
struct ata_channel *ch = drive->channel;

- /* FIXME: --bzolnier */
- __save_flags(flags); /* local CPU only */
- __cli(); /* local CPU only */
-
/* For an ATAPI device, first try an ATAPI SRST. */
- if (try_atapi) {
- if (drive->type != ATA_DISK) {
- check_crc_errors(drive);
- ata_select(drive, 20);
- OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
- ch->poll_timeout = jiffies + WAIT_WORSTCASE;
- ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
- __restore_flags(flags); /* local CPU only */
+ if (try_atapi && drive->type != ATA_DISK) {
+ check_crc_errors(drive);
+ ata_select(drive, 20);
+ OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
+ ch->poll_timeout = jiffies + WAIT_WORSTCASE;
+ ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);

- return ide_started;
- }
+ return ide_started;
}

/*
@@ -365,8 +358,7 @@
for (unit = 0; unit < MAX_DRIVES; ++unit)
check_crc_errors(&ch->drives[unit]);

- __restore_flags(flags); /* local CPU only */
-
+ /* FIXME: and then we should reset it --bzolnier */
return ide_started;
}

@@ -547,6 +539,8 @@
u8 stat = drive->status;

err = ata_dump(drive, rq, msg);
+
+ /* FIXME: at least !drive check is bogus --bzolnier */
if (!drive || !rq)
return ide_stopped;

@@ -703,7 +697,7 @@
/* This device is sleeping and waiting to be serviced
* later than any other device we checked thus far.
*/
- if (drive->sleep && (!sleep || time_after(sleep, drive->sleep)))
+ if (drive->sleep && (!sleep || time_after(drive->sleep, sleep)))
sleep = drive->sleep;
}

@@ -729,7 +723,7 @@

/* There are no request pending for this device.
*/
- if (list_empty(&drive->queue.queue_head))
+ if (blk_queue_empty(&drive->queue))
continue;

/* This device still wants to remain idle.
@@ -916,7 +910,7 @@
del_timer(&ch->timer);

if (!ch->drive) {
- printk(KERN_ERR "%s: IRQ handler was NULL\n", __FUNCTION__);
+ printk(KERN_ERR "%s: channel->drive was NULL\n", __FUNCTION__);
ch->handler = NULL;
} else if (!ch->handler) {

@@ -936,7 +930,7 @@

/* paranoia */
if (!test_and_set_bit(IDE_BUSY, ch->active))
- printk(KERN_ERR "%s: %s: IRQ handler was not busy?!\n",
+ printk(KERN_ERR "%s: %s: channel was not busy?!\n",
drive->name, __FUNCTION__);

if (ch->expiry) {
@@ -966,12 +960,13 @@
handler = ch->handler;
ch->handler = NULL;

- ch = drive->channel;
+ spin_unlock(ch->lock);
#if DISABLE_IRQ_NOSYNC
disable_irq_nosync(ch->irq);
#else
disable_irq(ch->irq); /* disable_irq_nosync ?? */
#endif
+ /* FIXME: IRQs are already disabled by spin_lock_irqsave() --bzolnier */
__cli(); /* local CPU only, as if we were handling an interrupt */
if (ch->poll_timeout) {
ret = handler(drive, drive->rq);
@@ -1020,6 +1015,7 @@
ret = ata_error(drive, drive->rq, "irq timeout");

enable_irq(ch->irq);
+ spin_lock_irq(ch->lock);

if (ret == ide_stopped)
clear_bit(IDE_BUSY, ch->active);
diff -ur -X/home/dontdiff linux-2.5.24/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- linux-2.5.24/drivers/ide/pdc202xx.c Tue Jul 2 23:54:16 2002
+++ linux/drivers/ide/pdc202xx.c Fri Jul 5 00:51:02 2002
@@ -165,9 +165,6 @@
u8 DP;
#endif

- if (drive->dn > 3) /* FIXME: remove this --bkz */
- return -1;
-
drive_pci = 0x60 + (drive->dn << 2);

if ((drive->type != ATA_DISK) && (speed < XFER_SW_DMA_0))
diff -ur -X/home/dontdiff linux-2.5.24/drivers/ide/sis5513.c linux/drivers/ide/sis5513.c
--- linux-2.5.24/drivers/ide/sis5513.c Tue Jul 2 23:54:16 2002
+++ linux/drivers/ide/sis5513.c Fri Jul 5 00:50:30 2002
@@ -273,9 +273,6 @@
drive->dn, pio, timing);
#endif

- if (drive->dn > 3) /* FIXME: remove this --bkz */
- return 1;
-
drive_pci = 0x40 + (drive->dn << 1);

/* register layout changed with newer ATA100 chips */
\
 
 \ /
  Last update: 2005-03-22 13:27    [from the cache]
©2003-2011 Jasper Spaans