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    [W:0.033 / U:187.832 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site