lkml.org 
[lkml]   [1998]   [Apr]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    SubjectPending IDE update for SMP, bugfixes, ...
    Attached are the current accumulated IDE bug-fixes
    against 2.1.96. If the nice folks with SMP machines
    could try these out and pass on any feedback, it would
    be greatly appreciated.

    Thanks.
    --
    mlord@pobox.com
    The Linux IDE guy
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
    --- linux-2.1.96/arch/i386/kernel/smp.c Mon Apr 6 22:16:07 1998
    +++ linux/arch/i386/kernel/smp.c Wed Apr 15 22:17:50 1998
    @@ -52,8 +52,6 @@

    #include "irq.h"

    -spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
    -
    extern unsigned long start_kernel, _etext;
    extern void update_one_process( struct task_struct *p,
    unsigned long ticks, unsigned long user,
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ali14xx.c linux/drivers/block/ali14xx.c
    --- linux-2.1.96/drivers/block/ali14xx.c Mon Dec 29 12:25:29 1997
    +++ linux/drivers/block/ali14xx.c Wed Apr 15 22:17:50 1998
    @@ -134,15 +134,15 @@

    /* stuff timing parameters into controller registers */
    driveNum = (HWIF(drive)->index << 1) + drive->select.b.unit;
    - save_flags(flags);
    - cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    outb_p(regOn, basePort);
    outReg(param1, regTab[driveNum].reg1);
    outReg(param2, regTab[driveNum].reg2);
    outReg(param3, regTab[driveNum].reg3);
    outReg(param4, regTab[driveNum].reg4);
    outb_p(regOff, basePort);
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    }

    /*
    @@ -154,8 +154,8 @@
    byte t;
    unsigned long flags;

    - save_flags(flags);
    - cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    for (i = 0; i < ALI_NUM_PORTS; ++i) {
    basePort = ports[i];
    regOff = inb(basePort);
    @@ -166,7 +166,7 @@
    dataPort = basePort + 8;
    t = inReg(0) & 0xf0;
    outb_p(regOff, basePort);
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    if (t != 0x50)
    return 0;
    return 1; /* success */
    @@ -174,7 +174,7 @@
    }
    outb_p(regOff, basePort);
    }
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    return 0;
    }

    @@ -186,15 +186,15 @@
    byte t;
    unsigned long flags;

    - save_flags(flags);
    - cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    outb_p(regOn, basePort);
    for (p = initData; p->reg != 0; ++p)
    outReg(p->data, p->reg);
    outb_p(0x01, regPort);
    t = inb(regPort) & 0x01;
    outb_p(regOff, basePort);
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    return t;
    }

    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/dtc2278.c linux/drivers/block/dtc2278.c
    --- linux-2.1.96/drivers/block/dtc2278.c Mon Dec 29 12:25:29 1997
    +++ linux/drivers/block/dtc2278.c Wed Apr 15 22:17:50 1998
    @@ -74,14 +74,14 @@
    pio = ide_get_best_pio_mode(drive, pio, 4, NULL);

    if (pio >= 3) {
    - save_flags(flags);
    - cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    /*
    * This enables PIO mode4 (3?) on the first interface
    */
    sub22(1,0xc3);
    sub22(0,0xa0);
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    } else {
    /* we don't know how to set it back again.. */
    }
    @@ -97,8 +97,8 @@
    {
    unsigned long flags;

    - save_flags(flags);
    - cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    /*
    * This enables the second interface
    */
    @@ -114,7 +114,7 @@
    sub22(1,0xc3);
    sub22(0,0xa0);
    #endif
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */

    ide_hwifs[0].serialized = 1;
    ide_hwifs[1].serialized = 1;
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ht6560b.c linux/drivers/block/ht6560b.c
    --- linux-2.1.96/drivers/block/ht6560b.c Mon Dec 29 12:25:29 1997
    +++ linux/drivers/block/ht6560b.c Wed Apr 15 22:17:50 1998
    @@ -133,8 +133,8 @@
    if (select != current_select || timing != current_timing) {
    current_select = select;
    current_timing = timing;
    - save_flags (flags);
    - cli();
    + __save_flags (flags); /* local CPU only */
    + __cli(); /* local CPU only */
    (void) inb(HT_SELECT_PORT);
    (void) inb(HT_SELECT_PORT);
    (void) inb(HT_SELECT_PORT);
    @@ -150,7 +150,7 @@
    */
    outb (timing, IDE_SELECT_REG);
    (void) inb (IDE_STATUS_REG);
    - restore_flags (flags);
    + __restore_flags (flags); /* local CPU only */
    #ifdef DEBUG
    printk("ht6560b: %s: select=%#x timing=%#x\n", drive->name, t, timing);
    #endif
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
    --- linux-2.1.96/drivers/block/ide-cd.c Wed Apr 1 21:24:31 1998
    +++ linux/drivers/block/ide-cd.c Wed Apr 15 22:17:50 1998
    @@ -276,7 +276,7 @@
    #if VERBOSE_IDE_CD_ERRORS
    {
    int i;
    - char *s;
    + const char *s;
    char buf[80];

    printk ("ATAPI device %s:\n", drive->name);
    @@ -1020,7 +1020,7 @@

    #define IDECD_SEEK_THRESHOLD (1000) /* 1000 blocks */
    #define IDECD_SEEK_TIMER (2 * WAIT_MIN_SLEEP) /* 40 ms */
    -#define IDECD_SEEK_TIMEOUT (20 * IDECD_SEEK_TIMER) /* 0.8 sec */
    +#define IDECD_SEEK_TIMEOUT WAIT_CMD /* 10 sec */

    static void cdrom_seek_intr (ide_drive_t *drive)
    {
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h
    --- linux-2.1.96/drivers/block/ide-cd.h Wed Apr 1 21:24:31 1998
    +++ linux/drivers/block/ide-cd.h Wed Apr 15 22:17:50 1998
    @@ -415,7 +415,7 @@
    /* From Table 124 of the ATAPI 1.2 spec.
    Unchanged in Table 140 of the ATAPI 2.6 draft standard. */

    -char *sense_key_texts[16] = {
    +const char *sense_key_texts[16] = {
    "No sense data",
    "Recovered error",
    "Not ready",
    @@ -438,7 +438,7 @@
    /* From Table 37 of the ATAPI 2.6 draft standard. */
    struct {
    unsigned short packet_command;
    - char *text;
    + const char *text;
    } packet_command_texts[] = {
    { TEST_UNIT_READY, "Test Unit Ready" },
    { REQUEST_SENSE, "Request Sense" },
    @@ -473,7 +473,7 @@

    struct {
    unsigned short asc_ascq;
    - char *text;
    + const char *text;
    } sense_data_texts[] = {
    { 0x0000, "No additional sense information" },

    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-disk.c linux/drivers/block/ide-disk.c
    --- linux-2.1.96/drivers/block/ide-disk.c Wed Apr 15 22:08:27 1998
    +++ linux/drivers/block/ide-disk.c Wed Apr 15 22:38:28 1998
    @@ -185,9 +185,7 @@
    }
    } else
    error = 1;
    -
    out:
    -
    if (error)
    ide_error(drive, "write_intr", stat);
    }
    @@ -258,9 +256,7 @@
    }
    } else
    error = 1;
    -
    out:
    -
    if (error)
    ide_error(drive, "multwrite_intr", stat);
    }
    @@ -380,7 +376,7 @@
    return;
    }
    if (!drive->unmask)
    - __cli();
    + __cli(); /* local CPU only */
    if (drive->mult_count) {
    HWGROUP(drive)->wrq = *rq; /* scratchpad */
    ide_set_handler (drive, &multwrite_intr, WAIT_CMD);
    @@ -587,8 +583,13 @@

    static int set_nowerr(ide_drive_t *drive, int arg)
    {
    + unsigned long flags;
    +
    + if (ide_spin_wait_hwgroup("set_nowerr", drive, flags))
    + return -EBUSY;
    drive->nowerr = arg;
    drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
    + spin_unlock_irqrestore(&HWGROUP(drive)->spinlock, flags);
    return 0;
    }

    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-dma.c linux/drivers/block/ide-dma.c
    --- linux-2.1.96/drivers/block/ide-dma.c Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/ide-dma.c Wed Apr 15 22:18:01 1998
    @@ -84,7 +84,7 @@
    */
    const char *good_dma_drives[] = {"Micropolis 2112A",
    "CONNER CTMA 4000",
    - "ST34342A",
    + "ST34342A", /* for Sun Ultra */
    NULL};

    /*
    @@ -128,7 +128,7 @@
    }
    printk("%s: dma_intr: bad DMA status\n", drive->name);
    }
    - sti();
    + ide__sti(); /* local CPU only */
    ide_error(drive, "dma_intr", stat);
    }

    @@ -210,7 +210,7 @@
    struct hd_driveid *id = drive->id;
    ide_hwif_t *hwif = HWIF(drive);

    - if (id && (id->capability & 1) && !HWIF(drive)->no_autodma) {
    + if (id && (id->capability & 1) && !hwif->no_autodma) {
    /* Enable DMA on any drive that has UltraDMA (mode 0/1/2) enabled */
    if (id->field_valid & 4) /* UltraDMA */
    if ((id->dma_ultra & (id->dma_ultra >> 8) & 7))
    @@ -250,6 +250,7 @@
    ide_hwif_t *hwif = HWIF(drive);
    unsigned long dma_base = hwif->dma_base;
    unsigned int count, reading = 0;
    + byte dma_stat;

    switch (func) {
    case ide_dma_off:
    @@ -267,22 +268,29 @@
    return 1; /* try PIO instead of DMA */
    outl(virt_to_bus(hwif->dmatable), dma_base + 4); /* PRD table */
    outb(reading, dma_base); /* specify r/w */
    - outb(inb(dma_base+2)|0x06, dma_base+2); /* clear status bits */
    + outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
    + drive->waiting_for_dma = 1;
    if (drive->media != ide_disk)
    return 0;
    ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);/* issue cmd to drive */
    OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
    case ide_dma_begin:
    + /* Note that this is done *after* the cmd has
    + * been issued to the drive, as per the BM-IDE spec.
    + * The Promise Ultra33 doesn't work correctly when
    + * we do this part before issuing the drive cmd.
    + */
    outb(inb(dma_base)|1, dma_base); /* start DMA */
    return 0;
    case ide_dma_end: /* returns 1 on error, 0 otherwise */
    - {
    - byte dma_stat = inb(dma_base+2);
    - int rc = (dma_stat & 7) != 4;
    + drive->waiting_for_dma = 0;
    + dma_stat = inb(dma_base+2);
    outb(inb(dma_base)&~1, dma_base); /* stop DMA */
    outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
    - return rc; /* verify good DMA status */
    - }
    + return (dma_stat & 7) != 4; /* verify good DMA status */
    + case ide_dma_test_irq: /* returns 1 if dma irq issued, 0 otherwise */
    + dma_stat = inb(dma_base+2);
    + return (dma_stat & 4) == 4; /* return 1 if INTR asserted */
    default:
    printk("ide_dmaproc: unsupported func: %d\n", func);
    return 1;
    @@ -331,9 +339,10 @@
    /*
    * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space:
    */
    -__initfunc(unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name))
    +__initfunc(unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name))
    {
    - unsigned long new, dma_base = 0;
    + unsigned long new, dma_base = 0;
    + struct pci_dev *dev = hwif->pci_dev;

    if (hwif->mate && hwif->mate->dma_base) {
    dma_base = hwif->mate->dma_base - (hwif->channel ? 0 : 8);
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-floppy.c linux/drivers/block/ide-floppy.c
    --- linux-2.1.96/drivers/block/ide-floppy.c Wed Apr 1 21:24:31 1998
    +++ linux/drivers/block/ide-floppy.c Wed Apr 15 22:18:01 1998
    @@ -713,7 +713,7 @@
    #endif /* IDEFLOPPY_DEBUG_LOG */
    clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);

    - ide_sti();
    + ide__sti(); /* local CPU only */

    if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
    #if IDEFLOPPY_DEBUG_LOG
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-pci.c linux/drivers/block/ide-pci.c
    --- linux-2.1.96/drivers/block/ide-pci.c Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/ide-pci.c Wed Apr 15 22:37:58 1998
    @@ -43,6 +43,7 @@
    #define DEVID_NS87415 ((ide_pci_devid_t){PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87415})
    #define DEVID_HT6565 ((ide_pci_devid_t){PCI_VENDOR_ID_HOLTEK, PCI_DEVICE_ID_HOLTEK_6565})
    #define DEVID_AEC6210 ((ide_pci_devid_t){0x1191, 0x0005})
    +#define DEVID_W82C105 ((ide_pci_devid_t){PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105})

    #define IDE_IGNORE ((void *)-1)

    @@ -71,7 +72,14 @@
    extern void ide_init_cmd646(ide_hwif_t *);
    #define INIT_CMD646 &ide_init_cmd646
    #else
    -#define INIT_CMD646 IDE_IGNORE
    +#define INIT_CMD646 NULL
    +#endif
    +
    +#ifdef CONFIG_BLK_DEV_SL82C105
    +extern void ide_init_sl82c105(ide_hwif_t *);
    +#define INIT_W82C105 &ide_init_sl82c105
    +#else
    +#define INIT_W82C105 IDE_IGNORE
    #endif

    #ifdef CONFIG_BLK_DEV_RZ1000
    @@ -113,6 +121,7 @@
    {DEVID_TRM290, "TRM290", INIT_TRM290, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
    {DEVID_NS87415, "NS87415", INIT_NS87415, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
    {DEVID_AEC6210, "AEC6210", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} },
    + {DEVID_W82C105, "W82C105", INIT_W82C105, {{0x40,0x01,0x01}, {0x40,0x10,0x10}} },
    {IDE_PCI_DEVID_NULL, "PCI_IDE", NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}} }};

    /*
    @@ -300,7 +309,7 @@
    ide_pci_enablebit_t *e = &(d->enablebits[port]);
    if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
    continue; /* port not enabled */
    - ctl = dev->base_address[1+2*port] & PCI_BASE_ADDRESS_IO_MASK;
    + ctl = dev->base_address[(2*port)+1] & PCI_BASE_ADDRESS_IO_MASK;
    if (!ctl)
    ctl = port ? 0x374 : 0x3f4; /* use default value */
    base = dev->base_address[2*port] & ~7;
    @@ -330,7 +339,7 @@
    if (IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246) ||
    ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && (dev->class & 0x80))) {
    unsigned int extra = (!mate && IDE_PCI_DEVID_EQ(d->devid, DEVID_PDC20246)) ? 16 : 0;
    - unsigned long dma_base = ide_get_or_set_dma_base(dev, hwif, extra, d->name);
    + unsigned long dma_base = ide_get_or_set_dma_base(hwif, extra, d->name);
    if (dma_base && !(pcicmd & PCI_COMMAND_MASTER)) {
    /*
    * Set up BM-DMA capability (PnP BIOS should have done this)
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-probe.c linux/drivers/block/ide-probe.c
    --- linux-2.1.96/drivers/block/ide-probe.c Wed Apr 1 21:24:32 1998
    +++ linux/drivers/block/ide-probe.c Wed Apr 15 22:18:02 1998
    @@ -47,7 +47,7 @@

    id = drive->id = kmalloc (SECTOR_WORDS*4, GFP_KERNEL);
    ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
    - sti();
    + ide__sti(); /* local CPU only */
    ide_fix_driveid(id);

    #if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
    @@ -195,12 +195,12 @@
    delay_50ms(); /* wait for IRQ and DRQ_STAT */
    if (OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
    unsigned long flags;
    - save_flags(flags);
    - cli(); /* some systems need this */
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only; some systems need this */
    do_identify(drive, cmd); /* drive returned ID */
    rc = 0; /* drive responded with ID */
    (void) GET_STAT(); /* clear drive IRQ */
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    } else
    rc = 2; /* drive refused ID */
    if (!HWIF(drive)->irq) {
    @@ -398,8 +398,8 @@
    return;
    }

    - save_flags(flags);
    - sti(); /* needed for jiffies and irq probing */
    + __save_flags(flags); /* local CPU only */
    + __sti(); /* local CPU only; needed for jiffies and irq probing */
    /*
    * Second drive should only exist if first drive was found,
    * but a lot of cdrom drives are configured as single slaves.
    @@ -429,7 +429,7 @@
    } while ((stat & BUSY_STAT) && 0 < (signed long)(timeout - jiffies));

    }
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    for (unit = 0; unit < MAX_DRIVES; ++unit) {
    ide_drive_t *drive = &hwif->drives[unit];
    if (drive->present) {
    @@ -486,8 +486,8 @@
    ide_hwgroup_t *hwgroup;
    ide_hwif_t *match = NULL;

    - save_flags(flags);
    - cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */

    hwif->hwgroup = NULL;
    #if MAX_HWIFS > 1
    @@ -499,7 +499,9 @@
    if (h->hwgroup) { /* scan only initialized hwif's */
    if (hwif->irq == h->irq) {
    hwif->sharing_irq = h->sharing_irq = 1;
    - save_match(hwif, h, &match);
    + if (hwif->chipset != ide_pci || h->chipset != ide_pci) {
    + save_match(hwif, h, &match);
    + }
    }
    if (hwif->serialized) {
    if (hwif->mate && hwif->mate->irq == h->irq)
    @@ -520,10 +522,15 @@
    } else {
    hwgroup = kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL);
    memset(hwgroup, 0, sizeof(ide_hwgroup_t));
    - hwgroup->hwif = hwif->next = hwif;
    - hwgroup->rq = NULL;
    - hwgroup->handler = NULL;
    - hwgroup->drive = NULL;
    + hwgroup->hwif = hwif->next = hwif;
    + hwgroup->rq = NULL;
    + hwgroup->handler = NULL;
    + hwgroup->drive = NULL;
    + hwgroup->busy = 0;
    + hwgroup->spinlock = (spinlock_t)SPIN_LOCK_UNLOCKED;
    +#if (DEBUG_SPINLOCK > 0)
    + printk("hwgroup(%s) spinlock is %p\n", hwif->name, &hwgroup->spinlock); /* FIXME */
    +#endif
    init_timer(&hwgroup->timer);
    hwgroup->timer.function = &ide_timer_expiry;
    hwgroup->timer.data = (unsigned long) hwgroup;
    @@ -533,10 +540,11 @@
    * Allocate the irq, if not already obtained for another hwif
    */
    if (!match || match->irq != hwif->irq) {
    - if (ide_request_irq(hwif->irq, &ide_intr, SA_INTERRUPT, hwif->name, hwgroup)) {
    + int sa = (hwif->chipset == ide_pci) ? SA_INTERRUPT|SA_SHIRQ : SA_INTERRUPT;
    + if (ide_request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwgroup)) {
    if (!match)
    kfree(hwgroup);
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    return 1;
    }
    }
    @@ -558,7 +566,7 @@
    hwgroup->drive->next = drive;
    }
    hwgroup->hwif = HWIF(hwgroup->drive);
    - restore_flags(flags); /* safe now that hwif->hwgroup is set up */
    + restore_flags(flags); /* all CPUs; safe now that hwif->hwgroup is set up */

    #ifndef __mc68000__
    printk("%s at 0x%03x-0x%03x,0x%03x on irq %d", hwif->name,
    @@ -685,13 +693,17 @@
    read_ahead[hwif->major] = 8; /* (4kB) */
    hwif->present = 1; /* success */
    }
    +#if (DEBUG_SPINLOCK > 0)
    +{
    + static int done = 0;
    + if (!done++)
    + printk("io_request_lock is %p\n", &io_request_lock); /* FIXME */
    +}
    +#endif
    return hwif->present;
    }

    -
    -int ideprobe_init(void);
    -
    -
    +int ideprobe_init (void);
    static ide_module_t ideprobe_module = {
    IDE_PROBE_MODULE,
    ideprobe_init,
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-proc.c linux/drivers/block/ide-proc.c
    --- linux-2.1.96/drivers/block/ide-proc.c Thu Apr 9 16:18:48 1998
    +++ linux/drivers/block/ide-proc.c Wed Apr 15 22:18:02 1998
    @@ -124,7 +124,7 @@
    * Do one full pass to verify all parameters,
    * then do another to actually write the regs.
    */
    - save_flags(flags);
    + save_flags(flags); /* all CPUs */
    do {
    const char *p;
    if (for_real) {
    @@ -133,14 +133,15 @@
    ide_hwgroup_t *mategroup = NULL;
    if (hwif->mate && hwif->mate->hwgroup)
    mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
    - cli(); /* ensure all writes are done together */
    - while (mygroup->active || (mategroup && mategroup->active)) {
    - restore_flags(flags);
    + cli(); /* all CPUs; ensure all writes are done together */
    + while (mygroup->busy || (mategroup && mategroup->busy)) {
    + sti(); /* all CPUs */
    if (0 < (signed long)(jiffies - timeout)) {
    printk("/proc/ide/%s/config: channel(s) busy, cannot write\n", hwif->name);
    + restore_flags(flags); /* all CPUs */
    return -EBUSY;
    }
    - cli();
    + cli(); /* all CPUs */
    }
    }
    p = buffer;
    @@ -174,7 +175,7 @@
    msg = "bad/missing register number";
    goto parse_error;
    }
    - if (--n < 0 || *p++ != ':') {
    + if (n-- == 0 || *p++ != ':') {
    msg = "missing ':'";
    goto parse_error;
    }
    @@ -223,7 +224,7 @@
    break;
    }
    if (rc) {
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    printk("proc_ide_write_config: error writing %s at bus %02x dev %02x reg 0x%x value 0x%x\n",
    msg, dev->bus->number, dev->devfn, reg, val);
    printk("proc_ide_write_config: %s\n", pcibios_strerror(rc));
    @@ -243,10 +244,10 @@
    }
    }
    } while (!for_real++);
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    return count;
    parse_error:
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    printk("parse error\n");
    return xx_xx_parse_error(start, startn, msg);
    }
    @@ -259,27 +260,26 @@

    #ifdef CONFIG_BLK_DEV_IDEPCI
    ide_hwif_t *hwif = (ide_hwif_t *)data;
    - int reg = 0;
    + struct pci_dev *dev = hwif->pci_dev;
    + if (!IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL) && dev && dev->bus) {
    + int reg = 0;

    - struct pci_dev *dev = hwif->pci_dev;
    -
    - out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
    - dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
    - do {
    - byte val;
    - int rc = pci_read_config_byte(dev, reg, &val);
    - if (rc) {
    - printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n",
    - dev->bus->number, dev->devfn, reg);
    - printk("proc_ide_read_config: %s\n", pcibios_strerror(rc));
    - return -EIO;
    - out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
    - } else
    - out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n');
    - } while (reg < 0x100);
    -#else /* CONFIG_BLK_DEV_IDEPCI */
    - out += sprintf(out, "(none)\n");
    + out += sprintf(out, "pci bus %02x device %02x vid %04x did %04x channel %d\n",
    + dev->bus->number, dev->devfn, hwif->pci_devid.vid, hwif->pci_devid.did, hwif->channel);
    + do {
    + byte val;
    + int rc = pci_read_config_byte(dev, reg, &val);
    + if (rc) {
    + printk("proc_ide_read_config: error reading bus %02x dev %02x reg 0x%02x\n",
    + dev->bus->number, dev->devfn, reg);
    + printk("proc_ide_read_config: %s\n", pcibios_strerror(rc));
    + out += sprintf(out, "??%c", (++reg & 0xf) ? ' ' : '\n');
    + } else
    + out += sprintf(out, "%02x%c", val, (++reg & 0xf) ? ' ' : '\n');
    + } while (reg < 0x100);
    + } else
    #endif /* CONFIG_BLK_DEV_IDEPCI */
    + out += sprintf(out, "(none)\n");
    len = out - page;
    PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
    }
    @@ -425,10 +425,9 @@
    (struct file *file, const char *buffer, unsigned long count, void *data)
    {
    ide_drive_t *drive = (ide_drive_t *) data;
    - ide_hwif_t *hwif = HWIF(drive);
    char name[MAX_LEN + 1];
    int for_real = 0, len;
    - unsigned long n, flags;
    + unsigned long n;
    const char *start = NULL;
    ide_settings_t *setting;

    @@ -443,27 +442,10 @@
    }
    /*
    * Do one full pass to verify all parameters,
    - * then do another to actually write the pci regs.
    + * then do another to actually write the new settings.
    */
    - save_flags(flags);
    do {
    const char *p;
    - if (for_real) {
    - unsigned long timeout = jiffies + (3 * HZ);
    - ide_hwgroup_t *mygroup = (ide_hwgroup_t *)(hwif->hwgroup);
    - ide_hwgroup_t *mategroup = NULL;
    - if (hwif->mate && hwif->mate->hwgroup)
    - mategroup = (ide_hwgroup_t *)(hwif->mate->hwgroup);
    - cli(); /* ensure all writes are done together */
    - while (mygroup->active || (mategroup && mategroup->active)) {
    - restore_flags(flags);
    - if (0 < (signed long)(jiffies - timeout)) {
    - printk("/proc/ide/%s/settings: channel(s) busy, cannot write\n", drive->name);
    - return -EBUSY;
    - }
    - cli();
    - }
    - }
    p = buffer;
    n = count;
    while (n > 0) {
    @@ -508,10 +490,8 @@
    ide_write_setting(drive, setting, val * setting->div_factor / setting->mul_factor);
    }
    } while (!for_real++);
    - restore_flags(flags);
    return count;
    parse_error:
    - restore_flags(flags);
    printk("proc_ide_write_settings(): parse error\n");
    return -EINVAL;
    }
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide-tape.c linux/drivers/block/ide-tape.c
    --- linux-2.1.96/drivers/block/ide-tape.c Wed Apr 1 21:24:32 1998
    +++ linux/drivers/block/ide-tape.c Wed Apr 15 22:18:02 1998
    @@ -1432,8 +1432,8 @@
    #if IDETAPE_DEBUG_LOG
    printk (KERN_INFO "Reached idetape_add_stage_tail\n");
    #endif /* IDETAPE_DEBUG_LOG */
    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    stage->next=NULL;
    if (tape->last_stage != NULL)
    tape->last_stage->next=stage;
    @@ -1444,7 +1444,7 @@
    tape->next_stage=tape->last_stage;
    tape->nr_stages++;
    tape->nr_pending_stages++;
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */
    }

    /*
    @@ -1754,7 +1754,7 @@
    #endif /* IDETAPE_DEBUG_LOG */
    clear_bit (PC_DMA_IN_PROGRESS, &pc->flags);

    - ide_sti();
    + ide__sti(); /* local CPU only */

    if (status.b.check || test_bit (PC_DMA_ERROR, &pc->flags)) { /* Error detected */
    #if IDETAPE_DEBUG_LOG
    @@ -2398,11 +2398,11 @@
    */
    return (idetape_queue_rw_tail (drive, IDETAPE_READ_RQ, blocks, tape->merge_stage->bh));
    }
    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    if (tape->active_stage == tape->first_stage)
    idetape_wait_for_request (tape->active_data_request);
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */

    rq_ptr = &tape->first_stage->rq;
    bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors);
    @@ -2451,13 +2451,13 @@
    * Pay special attention to possible race conditions.
    */
    while ((new_stage = idetape_kmalloc_stage (tape)) == NULL) {
    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    if (idetape_pipeline_active (tape)) {
    idetape_wait_for_request (tape->active_data_request);
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */
    } else {
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */
    idetape_insert_pipeline_into_queue (drive);
    if (idetape_pipeline_active (tape))
    continue;
    @@ -2514,12 +2514,12 @@
    if (tape->first_stage == NULL)
    return;

    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    tape->next_stage = NULL;
    if (idetape_pipeline_active (tape))
    idetape_wait_for_request (tape->active_data_request);
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */

    while (tape->first_stage != NULL)
    idetape_remove_stage_head (drive);
    @@ -2539,8 +2539,8 @@
    if (!idetape_pipeline_active (tape))
    idetape_insert_pipeline_into_queue (drive);

    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    if (!idetape_pipeline_active (tape))
    goto abort;
    #if IDETAPE_DEBUG_BUGS
    @@ -2550,7 +2550,7 @@
    #endif /* IDETAPE_DEBUG_BUGS */
    idetape_wait_for_request (&tape->last_stage->rq);
    abort:
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */
    }

    static void idetape_pad_zeros (ide_drive_t *drive, int bcount)
    @@ -2795,11 +2795,11 @@
    * Wait until the first read-ahead request
    * is serviced.
    */
    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    if (tape->active_stage == tape->first_stage)
    idetape_wait_for_request (tape->active_data_request);
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */

    if (tape->first_stage->rq.errors == IDETAPE_ERROR_FILEMARK)
    count++;
    @@ -3620,14 +3620,14 @@
    int minor = tape->minor;
    unsigned long flags;

    - save_flags (flags);
    - cli ();
    + save_flags (flags); /* all CPUs (overkill?) */
    + cli(); /* all CPUs (overkill?) */
    if (test_bit (IDETAPE_BUSY, &tape->flags) || tape->first_stage != NULL || tape->merge_stage_size || drive->usage) {
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs (overkill?) */
    return 1;
    }
    idetape_chrdevs[minor].drive = NULL;
    - restore_flags (flags);
    + restore_flags (flags); /* all CPUs (overkill?) */
    DRIVER(drive)->busy = 0;
    (void) ide_unregister_subdriver (drive);
    drive->driver_data = NULL;
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide.c linux/drivers/block/ide.c
    --- linux-2.1.96/drivers/block/ide.c Wed Apr 15 22:08:27 1998
    +++ linux/drivers/block/ide.c Wed Apr 15 22:46:22 1998
    @@ -86,6 +86,9 @@
    * Version 6.12 integrate ioctl and proc interfaces
    * fix parsing of "idex=" command line parameter
    * Version 6.13 add support for ide4/ide5 courtesy rjones@orchestream.com
    + * Version 6.14 fixed IRQ sharing among PCI devices
    + * Version 6.15 added SMP awareness to IDE drivers
    + * Version 6.16 fixed various bugs; even more SMP friendly
    *
    * Some additional driver compile-time options are in ide.h
    *
    @@ -155,13 +158,13 @@
    unsigned long t, flags;
    int i;

    - __save_flags(flags);
    - __cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    t = jiffies * 11932;
    outb_p(0, 0x43);
    i = inb_p(0x40);
    i |= inb(0x40) << 8;
    - __restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    return (t - i);
    }
    #endif /* DISK_RECOVERY_TIME */
    @@ -178,15 +181,11 @@
    */
    static void init_hwif_data (unsigned int index)
    {
    - byte *p;
    unsigned int unit;
    ide_hwif_t *hwif = &ide_hwifs[index];

    /* bulk initialize hwif & drive info with zeros */
    - p = ((byte *) hwif) + sizeof(ide_hwif_t);
    - do {
    - *--p = 0;
    - } while (p > (byte *) hwif);
    + memset(hwif, 0, sizeof(ide_hwif_t));

    /* fill in any non-zero initial values */
    hwif->index = index;
    @@ -299,11 +298,11 @@
    #if SUPPORT_VLB_SYNC
    if (io_32bit & 2) {
    unsigned long flags;
    - __save_flags(flags);
    - __cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    do_vlb_sync(IDE_NSECTOR_REG);
    insl(IDE_DATA_REG, buffer, wcount);
    - __restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    } else
    #endif /* SUPPORT_VLB_SYNC */
    insl(IDE_DATA_REG, buffer, wcount);
    @@ -332,11 +331,11 @@
    #if SUPPORT_VLB_SYNC
    if (io_32bit & 2) {
    unsigned long flags;
    - __save_flags(flags);
    - __cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    do_vlb_sync(IDE_NSECTOR_REG);
    outsl(IDE_DATA_REG, buffer, wcount);
    - __restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    } else
    #endif /* SUPPORT_VLB_SYNC */
    outsl(IDE_DATA_REG, buffer, wcount);
    @@ -392,6 +391,85 @@
    }

    /*
    + * Needed for PCI irq sharing
    + */
    +static inline int drive_is_ready (ide_drive_t *drive)
    +{
    + if (drive->waiting_for_dma)
    + return HWIF(drive)->dmaproc(ide_dma_test_irq, drive);
    +#if 0
    + udelay(1); /* need to guarantee 400ns since last command was issued */
    +#endif
    + if (GET_STAT() & BUSY_STAT)
    + return 0; /* drive busy: definitely not interrupting */
    + return 1; /* drive ready: *might* be interrupting */
    +}
    +
    +#if !defined(__SMP__) && defined(DEBUG_SPINLOCKS) && (DEBUG_SPINLOCKS > 1)
    +
    +static const char *ide_lock_name(spinlock_t *spinlock)
    +{
    + int index;
    +
    + if (spinlock == &io_request_lock)
    + return "io_request_lock";
    + for (index = 0; index < MAX_HWIFS; index++) {
    + ide_hwif_t *hwif = &ide_hwifs[index];
    + ide_hwgroup_t *hwgroup = hwif->hwgroup;
    + if (spinlock == &hwgroup->spinlock)
    + return hwif->name;
    + }
    + return "?";
    +}
    +
    +#define IDE_SPIN_LOCK_IRQ(msg,spinlock) \
    +{ \
    + static int __babble = 20; \
    + __cli(); \
    + if ((spinlock)->lock && __babble) { \
    + __babble--; \
    + printk("ide_lock: %s: already locked (%s)\n", msg, ide_lock_name(spinlock)); \
    + } \
    + /* spin_lock_irq(spinlock); */ \
    + (spinlock)->lock = 1; \
    +}
    +
    +#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags) \
    +{ \
    + __save_flags(flags); \
    + IDE_SPIN_LOCK_IRQ(msg,spinlock); \
    +}
    +
    +#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) \
    +{ \
    + static int __babble = 20; \
    + __cli(); \
    + if (!((spinlock)->lock) && __babble) { \
    + __babble--; \
    + printk("ide_unlock: %s: not locked (%s)\n", msg, ide_lock_name(spinlock)); \
    + } \
    + /* spin_unlock_irqrestore(msg,spinlock,flags); */ \
    + (spinlock)->lock = 0; \
    + restore_flags(flags); \
    +}
    +
    +#define IDE_SPIN_UNLOCK(msg,spinlock) \
    +{ \
    + unsigned long __flags; \
    + __save_flags(__flags); \
    + IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,__flags); \
    +}
    +
    +#else /* DEBUG_SPINLOCKS */
    +
    +#define IDE_SPIN_LOCK_IRQ(msg,spinlock) spin_lock_irq(spinlock)
    +#define IDE_SPIN_LOCK_IRQSAVE(msg,spinlock,flags) spin_lock_irqsave(spinlock,flags)
    +#define IDE_SPIN_UNLOCK(msg,spinlock) spin_unlock(spinlock)
    +#define IDE_SPIN_UNLOCK_IRQRESTORE(msg,spinlock,flags) spin_unlock_irqrestore(spinlock,flags)
    +
    +#endif /* DEBUG_SPINLOCKS */
    +
    +/*
    * This should get invoked any time we exit the driver to
    * wait for an interrupt response from a drive. handler() points
    * at the appropriate code to handle the next interrupt, and a
    @@ -400,7 +478,10 @@
    */
    void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigned int timeout)
    {
    + unsigned long flags;
    ide_hwgroup_t *hwgroup = HWGROUP(drive);
    +
    + IDE_SPIN_LOCK_IRQSAVE("ide_set_handler", &hwgroup->spinlock, flags);
    #ifdef DEBUG
    if (hwgroup->handler != NULL) {
    printk("%s: ide_set_handler: handler not null; old=%p, new=%p\n",
    @@ -410,6 +491,7 @@
    hwgroup->handler = handler;
    hwgroup->timer.expires = jiffies + timeout;
    add_timer(&(hwgroup->timer));
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_set_handler", &hwgroup->spinlock, flags);
    }

    /*
    @@ -558,8 +640,8 @@
    ide_hwif_t *hwif = HWIF(drive);
    ide_hwgroup_t *hwgroup = HWGROUP(drive);

    - __save_flags(flags);
    - __cli(); /* Why ? */
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */

    /* For an ATAPI device, first try an ATAPI SRST. */
    if (drive->media != ide_disk && !do_not_try_atapi) {
    @@ -569,7 +651,7 @@
    OUT_BYTE (WIN_SRST, IDE_COMMAND_REG);
    hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
    ide_set_handler (drive, &atapi_reset_pollfunc, HZ/20);
    - __restore_flags (flags);
    + __restore_flags (flags); /* local CPU only */
    return;
    }

    @@ -597,7 +679,7 @@
    ide_set_handler (drive, &reset_pollfunc, HZ/20);
    #endif /* OK_TO_RESET_CONTROLLER */

    - __restore_flags (flags);
    + __restore_flags (flags); /* local CPU only */
    }

    /*
    @@ -625,15 +707,17 @@
    args[2] = IN_BYTE(IDE_NSECTOR_REG);
    }
    }
    - __save_flags(flags);
    - __cli();
    + IDE_SPIN_LOCK_IRQSAVE("ide_end_drive_cmd", &io_request_lock, flags);
    drive->queue = rq->next;
    blk_dev[MAJOR(rq->rq_dev)].current_request = NULL;
    HWGROUP(drive)->rq = NULL;
    rq->rq_status = RQ_INACTIVE;
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_end_drive_cmd", &io_request_lock, flags);
    + save_flags(flags); /* all CPUs; overkill? */
    + cli(); /* all CPUs; overkill? */
    if (rq->sem != NULL)
    - up(rq->sem);
    - __restore_flags(flags);
    + up(rq->sem); /* inform originator that rq has been serviced */
    + restore_flags(flags); /* all CPUs; overkill? */
    }

    /*
    @@ -644,8 +728,8 @@
    unsigned long flags;
    byte err = 0;

    - __save_flags (flags);
    - /* ide_sti(); HACK */
    + __save_flags (flags); /* local CPU only */
    + ide__sti(); /* local CPU only */
    printk("%s: %s: status=0x%02x", drive->name, msg, stat);
    #if FANCY_STATUS_DUMPS
    printk(" { ");
    @@ -698,7 +782,7 @@
    #endif /* FANCY_STATUS_DUMPS */
    printk("\n");
    }
    - __restore_flags (flags);
    + __restore_flags (flags); /* local CPU only */
    return err;
    }

    @@ -732,7 +816,7 @@
    byte err;

    err = ide_dump_status(drive, msg, stat);
    - if ((rq = HWGROUP(drive)->rq) == NULL || drive == NULL)
    + if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
    return;
    /* retry only "normal" I/O: */
    if (rq->cmd == IDE_DRIVE_CMD) {
    @@ -784,7 +868,7 @@
    void ide_cmd(ide_drive_t *drive, byte cmd, byte nsect, ide_handler_t *handler)
    {
    ide_set_handler (drive, handler, WAIT_CMD);
    - OUT_BYTE(drive->ctl,IDE_CONTROL_REG);
    + OUT_BYTE(drive->ctl,IDE_CONTROL_REG); /* clear nIEN */
    OUT_BYTE(nsect,IDE_NSECTOR_REG);
    OUT_BYTE(cmd,IDE_COMMAND_REG);
    }
    @@ -799,7 +883,7 @@
    byte stat = GET_STAT();
    int retries = 10;

    - /* ide_sti(); HACK */
    + ide__sti(); /* local CPU only */
    if ((stat & DRQ_STAT) && args && args[3]) {
    byte io_32bit = drive->io_32bit;
    drive->io_32bit = 0;
    @@ -857,17 +941,17 @@

    udelay(1); /* spec allows drive 400ns to assert "BUSY" */
    if ((stat = GET_STAT()) & BUSY_STAT) {
    - __save_flags(flags);
    - /* ide_sti(); HACK */
    + __save_flags(flags); /* local CPU only */
    + ide__sti(); /* local CPU only */
    timeout += jiffies;
    while ((stat = GET_STAT()) & BUSY_STAT) {
    if (0 < (signed long)(jiffies - timeout)) {
    - __restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    ide_error(drive, "status timeout", stat);
    return 1;
    }
    }
    - __restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    }
    udelay(1); /* allow status to settle, then read it again */
    if (OK_STAT((stat = GET_STAT()), good, bad))
    @@ -909,17 +993,18 @@
    }

    /*
    - * do_request() initiates handling of a new I/O request
    + * start_request() initiates handling of a new I/O request
    */
    -static inline void do_request (ide_hwgroup_t *hwgroup, ide_hwif_t *hwif, ide_drive_t *drive)
    +static inline void start_request (ide_drive_t *drive)
    {
    unsigned long block, blockend;
    struct request *rq = drive->queue;
    unsigned int minor = MINOR(rq->rq_dev), unit = minor >> PARTN_BITS;
    + ide_hwif_t *hwif = HWIF(drive);

    - /* ide_sti(); HACK */
    + ide__sti(); /* local CPU only */
    #ifdef DEBUG
    - printk("%s: do_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
    + printk("%s: start_request: current=0x%08lx\n", hwif->name, (unsigned long) rq);
    #endif
    if (unit >= MAX_DRIVES) {
    printk("%s: bad device number: %s\n", hwif->name, kdevname(rq->rq_dev));
    @@ -946,15 +1031,11 @@
    #if (DISK_RECOVERY_TIME > 0)
    while ((read_timer() - hwif->last_time) < DISK_RECOVERY_TIME);
    #endif
    -
    - hwgroup->hwif = hwif;
    - hwgroup->drive = drive;
    SELECT_DRIVE(hwif, drive);
    if (ide_wait_stat(drive, drive->ready_stat, BUSY_STAT|DRQ_STAT, WAIT_READY)) {
    printk("%s: drive not ready for command\n", drive->name);
    return;
    }
    -
    if (!drive->special.all) {
    if (rq->cmd == IDE_DRIVE_CMD) {
    execute_drive_cmd(drive, rq);
    @@ -973,7 +1054,7 @@
    if (drive->driver != NULL)
    DRIVER(drive)->end_request(0, HWGROUP(drive));
    else
    - ide_end_request(0, hwgroup);
    + ide_end_request(0, HWGROUP(drive));
    }

    /*
    @@ -1000,21 +1081,19 @@
    best = NULL;
    drive = hwgroup->drive;
    do {
    - if (!drive->queue)
    - continue;
    - if (drive->sleep && 0 < (signed long)(drive->sleep - jiffies))
    - continue;
    - if (!best) {
    - best = drive;
    - continue;
    + if (drive->queue && (!drive->sleep || 0 <= (signed long)(jiffies - drive->sleep))) {
    + if (!best
    + || (drive->sleep && (!best->sleep || 0 < (signed long)(best->sleep - drive->sleep)))
    + || (!best->sleep && 0 < (signed long)(WAKEUP(best) - WAKEUP(drive))))
    + {
    + struct blk_dev_struct *bdev = &blk_dev[HWIF(drive)->major];
    + if (bdev->current_request != &bdev->plug)
    + best = drive;
    + }
    }
    - if (drive->sleep && (!best->sleep || drive->sleep < best->sleep))
    - best = drive;
    - if (!best->sleep && WAKEUP(drive) < WAKEUP(best))
    - best = drive;
    } while ((drive = drive->next) != hwgroup->drive);
    - if (best != hwgroup->drive && best && best->service_time > WAIT_MIN_SLEEP && !best->sleep && best->nice1) {
    - long t = (signed) (WAKEUP(best) - jiffies); /* BUGGY? */
    + if (best && best->nice1 && !best->sleep && best != hwgroup->drive && best->service_time > WAIT_MIN_SLEEP) {
    + long t = (signed long)(WAKEUP(best) - jiffies);
    if (t >= WAIT_MIN_SLEEP) {
    /*
    * We *may* have some time to spare, but first let's see if
    @@ -1022,9 +1101,10 @@
    */
    drive = best->next;
    do {
    - if (drive->sleep) /* this drive tried to be nice to us */
    - continue;
    - if (WAKEUP(drive) > (jiffies - best->service_time) && WAKEUP(drive) < (jiffies + t)) { /* BUGGY? */
    + if (!drive->sleep
    + && 0 < (signed long)(WAKEUP(drive) - (jiffies - best->service_time))
    + && 0 < (signed long)((jiffies + t) - WAKEUP(drive)))
    + {
    ide_stall_queue(best, IDE_MIN(t, 10 * WAIT_MIN_SLEEP));
    goto repeat;
    }
    @@ -1034,33 +1114,6 @@
    return best;
    }

    -static inline void ide_leave_hwgroup (ide_hwgroup_t *hwgroup)
    -{
    - ide_drive_t *drive = hwgroup->drive;
    - unsigned long sleep = 0;
    -
    - hwgroup->rq = NULL;
    - do {
    - blk_dev[HWIF(drive)->major].current_request = NULL;
    - if (!drive->sleep)
    - continue;
    - if (!sleep) {
    - sleep = drive->sleep;
    - continue;
    - }
    - if (drive->sleep < sleep)
    - sleep = drive->sleep;
    - } while ((drive = drive->next) != hwgroup->drive);
    - if (sleep) {
    - if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
    - sleep = jiffies + WAIT_MIN_SLEEP;
    - hwgroup->timer.expires = sleep;
    - add_timer(&hwgroup->timer);
    - } else /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
    - ide_release_lock(&ide_lock);
    - hwgroup->active = 0;
    -}
    -
    /*
    * The driver enables interrupts as much as possible. In order to do this,
    * (a) the device-interrupt is always masked before entry, and
    @@ -1075,30 +1128,68 @@
    * tolerance for latency during I/O. For devices which don't suffer from
    * this problem (most don't), the unmask flag can be set using the "hdparm"
    * utility, to permit other interrupts during data/cmd transfers.
    + *
    + * Caller must have already acquired spinlock using *spinflags
    + *
    */
    -void ide_do_request (ide_hwgroup_t *hwgroup)
    +static void ide_do_request (ide_hwgroup_t *hwgroup, unsigned long *hwgroup_flags, int masked_irq)
    {
    - __cli(); /* paranoia */
    - if (hwgroup->handler != NULL) {
    - printk("%s: EEeekk!! handler not NULL in ide_do_request()\n", hwgroup->hwif->name);
    - return;
    - }
    - do {
    - ide_drive_t *drive = choose_drive(hwgroup);
    - if (drive != NULL) {
    - ide_hwif_t *hwif = HWIF(drive);
    - if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif)
    - OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
    - drive->sleep = 0;
    - blk_dev[hwif->major].current_request = hwgroup->rq = drive->queue;
    - drive->service_start = jiffies;
    - do_request(hwgroup, hwif, drive);
    - __cli();
    - } else {
    - ide_leave_hwgroup(hwgroup); /* no work left for this hwgroup */
    + struct blk_dev_struct *bdev;
    + ide_drive_t *drive;
    + ide_hwif_t *hwif;
    + unsigned long io_flags;
    +
    + hwgroup->busy = 1;
    + while (hwgroup->handler == NULL) {
    + IDE_SPIN_LOCK_IRQSAVE("ide_do_request1", &io_request_lock, io_flags);
    + drive = choose_drive(hwgroup);
    + if (drive == NULL) {
    + unsigned long sleep = 0;
    +
    + hwgroup->rq = NULL;
    + drive = hwgroup->drive;
    + do {
    + bdev = &blk_dev[HWIF(drive)->major];
    + if (bdev->current_request != &bdev->plug) /* FIXME: this will do for now */
    + bdev->current_request = NULL; /* (broken since patch-2.1.15) */
    + if (drive->sleep && (!sleep || 0 < (signed long)(sleep - drive->sleep)))
    + sleep = drive->sleep;
    + } while ((drive = drive->next) != hwgroup->drive);
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request2", &io_request_lock, io_flags);
    + if (sleep) {
    + if (0 < (signed long)(jiffies + WAIT_MIN_SLEEP - sleep))
    + sleep = jiffies + WAIT_MIN_SLEEP;
    + hwgroup->timer.expires = sleep;
    + add_timer(&hwgroup->timer);
    + } else {
    + /* Ugly, but how can we sleep for the lock otherwise? perhaps from tq_scheduler? */
    + ide_release_lock(&ide_lock); /* for atari only */
    + }
    + hwgroup->busy = 0;
    return;
    }
    - } while (hwgroup->handler == NULL);
    + hwif = HWIF(drive);
    + if (hwgroup->hwif->sharing_irq && hwif != hwgroup->hwif) /* set nIEN for previous hwif */
    + OUT_BYTE(hwgroup->drive->ctl|2, hwgroup->hwif->io_ports[IDE_CONTROL_OFFSET]);
    + hwgroup->hwif = hwif;
    + hwgroup->drive = drive;
    + drive->sleep = 0;
    + drive->service_start = jiffies;
    +
    + bdev = &blk_dev[hwif->major];
    + if (bdev->current_request == &bdev->plug) /* FIXME: paranoia */
    + printk("%s: Huh? nuking plugged queue\n", drive->name);
    + bdev->current_request = hwgroup->rq = drive->queue;
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request3", &io_request_lock, io_flags);
    +
    + if (hwif->irq != masked_irq)
    + disable_irq(hwif->irq);
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_request4", &hwgroup->spinlock, *hwgroup_flags);
    + start_request(drive);
    + IDE_SPIN_LOCK_IRQSAVE("ide_do_request5", &hwgroup->spinlock, *hwgroup_flags);
    + if (hwif->irq != masked_irq)
    + enable_irq(hwif->irq);
    + }
    }

    /*
    @@ -1106,110 +1197,136 @@
    */
    struct request **ide_get_queue (kdev_t dev)
    {
    - struct blk_dev_struct *bdev = blk_dev + MAJOR(dev);
    - ide_hwif_t *hwif = bdev->data;
    + ide_hwif_t *hwif = (ide_hwif_t *)blk_dev[MAJOR(dev)].data;

    return &hwif->drives[DEVICE_NR(dev) & 1].queue;
    }

    /*
    - * do_hwgroup_request() invokes ide_do_request() after first masking
    - * all possible interrupts for the current hwgroup. This prevents race
    - * conditions in the event that an unexpected interrupt occurs while
    - * we are in the driver.
    - *
    - * Note that when an interrupt is used to reenter the driver, the first level
    - * handler will already have masked the irq that triggered, but any other ones
    - * for the hwgroup will still be unmasked. The driver tries to be careful
    - * about such things.
    - */
    -static void do_hwgroup_request (ide_hwgroup_t *hwgroup)
    -{
    - if (hwgroup->handler == NULL) {
    - ide_hwif_t *hgif = hwgroup->hwif;
    - ide_hwif_t *hwif = hgif;
    -
    - del_timer(&hwgroup->timer);
    - ide_get_lock(&ide_lock, ide_intr, hwgroup);
    - hwgroup->active = 1;
    - do {
    - disable_irq(hwif->irq);
    - } while ((hwif = hwif->next) != hgif);
    - ide_do_request (hwgroup);
    - do {
    - enable_irq(hwif->irq);
    - } while ((hwif = hwif->next) != hgif);
    + * do_hwgroup_request() invokes ide_do_request() after claiming hwgroup->busy.
    + */
    +static void do_hwgroup_request (const char *msg, ide_hwgroup_t *hwgroup)
    +{
    + unsigned long flags;
    +
    + IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, flags);
    + if (hwgroup->busy) {
    + IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
    + return;
    }
    + del_timer(&hwgroup->timer);
    + ide_get_lock(&ide_lock, ide_intr, hwgroup); /* for atari only */
    + ide_do_request(hwgroup, &flags, 0);
    + IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, flags);
    +}
    +
    +/*
    + * As of linux-2.1.95, ll_rw_blk.c invokes our do_idex_request()
    + * functions with the io_request_spinlock already grabbed.
    + * Since we need to do our own spinlock's internally,
    + * on paths that don't necessarily originate through the
    + * do_idex_request() path.
    + *
    + * We have to undo the spinlock on entry, and restore it again on exit.
    + * Fortunately, this is mostly a nop for non-SMP kernels.
    + */
    +static inline void unlock_do_hwgroup_request (ide_hwgroup_t *hwgroup)
    +{
    + IDE_SPIN_UNLOCK("unlock_do_hwgroup_request", &io_request_lock);
    + do_hwgroup_request ("from unlock_do_hwgroup_request", hwgroup);
    + IDE_SPIN_LOCK_IRQ("unlock_do_hwgroup_request", &io_request_lock);
    }

    -void do_ide0_request (void) /* invoked with __cli() */
    +void do_ide0_request (void)
    {
    - do_hwgroup_request (ide_hwifs[0].hwgroup);
    + unlock_do_hwgroup_request (ide_hwifs[0].hwgroup);
    }

    #if MAX_HWIFS > 1
    -void do_ide1_request (void) /* invoked with __cli() */
    +void do_ide1_request (void)
    {
    - do_hwgroup_request (ide_hwifs[1].hwgroup);
    + unlock_do_hwgroup_request (ide_hwifs[1].hwgroup);
    }
    #endif /* MAX_HWIFS > 1 */

    #if MAX_HWIFS > 2
    -void do_ide2_request (void) /* invoked with __cli() */
    +void do_ide2_request (void)
    {
    - do_hwgroup_request (ide_hwifs[2].hwgroup);
    + unlock_do_hwgroup_request (ide_hwifs[2].hwgroup);
    }
    #endif /* MAX_HWIFS > 2 */

    #if MAX_HWIFS > 3
    -void do_ide3_request (void) /* invoked with __cli() */
    +void do_ide3_request (void)
    {
    - do_hwgroup_request (ide_hwifs[3].hwgroup);
    + unlock_do_hwgroup_request (ide_hwifs[3].hwgroup);
    }
    #endif /* MAX_HWIFS > 3 */

    #if MAX_HWIFS > 4
    -void do_ide4_request (void) /* invoked with cli() */
    +void do_ide4_request (void)
    {
    - do_hwgroup_request (ide_hwifs[4].hwgroup);
    + unlock_do_hwgroup_request (ide_hwifs[4].hwgroup);
    }
    #endif /* MAX_HWIFS > 4 */

    #if MAX_HWIFS > 5
    -void do_ide5_request (void) /* invoked with cli() */
    +void do_ide5_request (void)
    {
    - do_hwgroup_request (ide_hwifs[5].hwgroup);
    + unlock_do_hwgroup_request (ide_hwifs[5].hwgroup);
    }
    #endif /* MAX_HWIFS > 5 */

    +static void start_next_request (ide_hwgroup_t *hwgroup, int masked_irq)
    +{
    + unsigned long flags;
    + ide_drive_t *drive;
    +
    + IDE_SPIN_LOCK_IRQSAVE("start_next_request", &hwgroup->spinlock, flags);
    + if (hwgroup->handler != NULL) {
    + IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
    + return;
    + }
    + drive = hwgroup->drive;
    + set_recovery_timer(HWIF(drive));
    + drive->service_time = jiffies - drive->service_start;
    + ide_do_request(hwgroup, &flags, masked_irq);
    + IDE_SPIN_UNLOCK_IRQRESTORE("start_next_request", &hwgroup->spinlock, flags);
    +}
    +
    void ide_timer_expiry (unsigned long data)
    {
    ide_hwgroup_t *hwgroup = (ide_hwgroup_t *) data;
    - ide_drive_t *drive = hwgroup->drive;
    + ide_drive_t *drive;
    ide_handler_t *handler;
    unsigned long flags;

    - __save_flags(flags);
    - __cli();
    -
    - if ((handler = hwgroup->handler) != NULL) {
    - hwgroup->handler = NULL;
    - if (hwgroup->poll_timeout != 0) /* polling in progress? */
    - handler(drive);
    - else { /* abort the operation */
    - if (hwgroup->hwif->dmaproc)
    - (void) hwgroup->hwif->dmaproc (ide_dma_end, drive);
    - ide_error(drive, "irq timeout", GET_STAT());
    - }
    - __cli();
    - if (hwgroup->handler == NULL) {
    - set_recovery_timer(HWIF(drive));
    - drive->service_time = jiffies - drive->service_start;
    - do_hwgroup_request (hwgroup);
    - }
    - } else
    - do_hwgroup_request (hwgroup);
    - __restore_flags(flags);
    + IDE_SPIN_LOCK_IRQSAVE("ide_timer_expiry1", &hwgroup->spinlock, flags);
    + drive = hwgroup->drive;
    + if ((handler = hwgroup->handler) == NULL) {
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry2", &hwgroup->spinlock, flags);
    + do_hwgroup_request("timer do_hwgroup_request", hwgroup);
    + return;
    + }
    + hwgroup->busy = 1; /* should already be "1" */
    + hwgroup->handler = NULL;
    + if (hwgroup->poll_timeout != 0) { /* polling in progress? */
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry3", &hwgroup->spinlock, flags);
    + handler(drive);
    + } else if (drive_is_ready(drive)) {
    + printk("%s: lost interrupt\n", drive->name);
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry4", &hwgroup->spinlock, flags);
    + handler(drive);
    + } else {
    + if (drive->waiting_for_dma) {
    + (void) hwgroup->hwif->dmaproc(ide_dma_end, drive);
    + printk("%s: timeout waiting for DMA\n", drive->name);
    + }
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_timer_expiry5", &hwgroup->spinlock, flags);
    + ide_error(drive, "irq timeout", GET_STAT());
    + }
    + del_timer(&hwgroup->timer);
    + start_next_request(hwgroup, 0);
    }

    /*
    @@ -1248,83 +1365,78 @@
    stat = IN_BYTE(hwif->io_ports[IDE_STATUS_OFFSET]);
    if (!OK_STAT(stat, READY_STAT, BAD_STAT)) {
    /* Try to not flood the console with msgs */
    - static unsigned long last_msgtime = 0;
    + static unsigned long last_msgtime = 0, count = 0;
    + ++count;
    if (0 < (signed long)(jiffies - (last_msgtime + HZ))) {
    last_msgtime = jiffies;
    - printk("%s%s: unexpected interrupt, status=0x%02x\n",
    - hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat);
    + printk("%s%s: unexpected interrupt, status=0x%02x, count=%ld\n",
    + hwif->name, (hwif->next == hwgroup->hwif) ? "" : "(?)", stat, count);
    }
    }
    }
    } while ((hwif = hwif->next) != hwgroup->hwif);
    }
    -
    -#ifdef __sparc_v9__
    -#define IDE_IRQ_EQUAL(irq1, irq2) (1)
    -#else
    -#define IDE_IRQ_EQUAL(irq1, irq2) ((irq1) == (irq2))
    -#endif
    -
    -static void do_ide_intr (int irq, void *dev_id, struct pt_regs *regs)
    -{
    - ide_hwgroup_t *hwgroup = dev_id;
    - ide_hwif_t *hwif = hwgroup->hwif;
    - ide_handler_t *handler;
    -
    - if (!ide_ack_intr (hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]))
    - return;
    -
    - do {
    - if (!IDE_IRQ_EQUAL(irq, hwgroup->hwif->irq))
    - disable_irq(hwif->irq);
    - } while ((hwif = hwif->next) != hwgroup->hwif);
    - if (IDE_IRQ_EQUAL(irq, hwif->irq)
    - && (handler = hwgroup->handler) != NULL) {
    - ide_drive_t *drive = hwgroup->drive;
    -#if 1 /* temporary, remove later -- FIXME */
    - {
    - struct request *rq = hwgroup->rq;
    - if (rq != NULL
    - &&( MAJOR(rq->rq_dev) != HWIF(drive)->major
    - || (MINOR(rq->rq_dev) >> PARTN_BITS) != drive->select.b.unit))
    - {
    - printk("ide_intr: got IRQ from wrong device: email mlord@pobox.com!!\n");
    - return;
    - }
    - }
    -#endif /* temporary */
    - hwgroup->handler = NULL;
    - del_timer(&(hwgroup->timer));
    - /* if (drive->unmask)
    - ide_sti(); HACK */
    - handler(drive);
    - /* this is necessary, as next rq may be different irq */
    - if (hwgroup->handler == NULL) {
    - set_recovery_timer(HWIF(drive));
    - drive->service_time = jiffies - drive->service_start;
    - ide_do_request(hwgroup);
    - }
    - } else {
    - unexpected_intr(irq, hwgroup);
    - }
    - __cli();
    - hwif = hwgroup->hwif;
    - do {
    - if (!IDE_IRQ_EQUAL(hwif->irq, irq))
    - enable_irq(hwif->irq);
    - } while ((hwif = hwif->next) != hwgroup->hwif);
    -}
    -
    /*
    * entry point for all interrupts, caller does __cli() for us
    */
    void ide_intr (int irq, void *dev_id, struct pt_regs *regs)
    {
    unsigned long flags;
    + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)dev_id;
    + ide_hwif_t *hwif;
    + ide_drive_t *drive;
    + ide_handler_t *handler;

    - spin_lock_irqsave(&io_request_lock, flags);
    - do_ide_intr(irq, dev_id, regs);
    - spin_unlock_irqrestore(&io_request_lock, flags);
    + __cli(); /* local CPU only */
    + IDE_SPIN_LOCK_IRQSAVE("ide_intr1", &hwgroup->spinlock, flags);
    + hwif = hwgroup->hwif;
    + if ((handler = hwgroup->handler) == NULL || hwgroup->poll_timeout != 0) {
    + /*
    + * Not expecting an interrupt from this drive.
    + * That means this could be:
    + * (1) an interrupt from another PCI device
    + * sharing the same PCI INT# as us.
    + * or (2) a drive just entered sleep or standby mode,
    + * and is interrupting to let us know.
    + * or (3) a spurious interrupt of unknown origin.
    + *
    + * For PCI, we cannot tell the difference,
    + * so in that case we just ignore it and hope it goes away.
    + */
    +#ifdef CONFIG_BLK_DEV_IDEPCI
    + if (IDE_PCI_DEVID_EQ(hwif->pci_devid, IDE_PCI_DEVID_NULL))
    +#endif /* CONFIG_BLK_DEV_IDEPCI */
    + {
    + /*
    + * Probably not a shared PCI interrupt,
    + * so we can safely try to do something about it:
    + */
    + (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
    + unexpected_intr(irq, hwgroup);
    + }
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr2", &hwgroup->spinlock, flags);
    + return;
    + }
    + drive = hwgroup->drive;
    + if (!drive || !drive_is_ready(drive)) {
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr3", &hwgroup->spinlock, flags);
    + return;
    + }
    + hwgroup->handler = NULL;
    + (void)ide_ack_intr(hwif->io_ports[IDE_STATUS_OFFSET], hwif->io_ports[IDE_IRQ_OFFSET]);
    + del_timer(&(hwgroup->timer));
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_intr4", &hwgroup->spinlock, flags);
    + if (drive->unmask)
    + ide__sti(); /* local CPU only */
    + handler(drive); /* service this interrupt, may set handler for next interrupt */
    + /*
    + * Note that handler() may have set things up for another
    + * interrupt to occur soon, but it cannot happen until
    + * we exit from this routine, because it will be the
    + * same irq as is currently being serviced here,
    + * and Linux won't allow another (on any CPU) until we return.
    + */
    + start_next_request(hwgroup, hwif->irq);
    }

    /*
    @@ -1408,10 +1520,8 @@
    if (action == ide_wait)
    rq->sem = &sem;

    - __save_flags(flags);
    - __cli();
    + IDE_SPIN_LOCK_IRQSAVE("ide_do_drive_cmd", &io_request_lock, flags);
    cur_rq = drive->queue;
    -
    if (cur_rq == NULL || action == ide_preempt) {
    rq->next = cur_rq;
    drive->queue = rq;
    @@ -1425,13 +1535,13 @@
    rq->next = cur_rq->next;
    cur_rq->next = rq;
    }
    - if (!hwgroup->active) {
    - do_hwgroup_request(hwgroup);
    - __cli();
    - }
    - if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_do_drive_cmd", &io_request_lock, flags);
    + do_hwgroup_request("drive_cmd do_hwgroup_request", hwgroup);
    + save_flags(flags); /* all CPUs; overkill? */
    + cli(); /* all CPUs; overkill? */
    + if (action == ide_wait && rq->rq_status != RQ_INACTIVE)
    down(&sem); /* wait for it to be serviced */
    - __restore_flags(flags);
    + restore_flags(flags); /* all CPUs; overkill? */
    return rq->errors ? -EIO : 0; /* return -EIO if errors */
    }

    @@ -1446,6 +1556,7 @@
    int ide_revalidate_disk(kdev_t i_rdev)
    {
    ide_drive_t *drive;
    + ide_hwgroup_t *hwgroup;
    unsigned int p, major, minor;
    long flags;

    @@ -1453,15 +1564,15 @@
    return -ENODEV;
    major = MAJOR(i_rdev);
    minor = drive->select.b.unit << PARTN_BITS;
    - __save_flags(flags);
    - __cli();
    + hwgroup = HWGROUP(drive);
    + IDE_SPIN_LOCK_IRQSAVE("ide_revalidate_disk", &hwgroup->spinlock, flags);
    if (drive->busy || (drive->usage > 1)) {
    - __restore_flags(flags);
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);
    return -EBUSY;
    };
    drive->busy = 1;
    MOD_INC_USE_COUNT;
    - __restore_flags(flags);
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_revalidate_disk", &hwgroup->spinlock, flags);

    for (p = 0; p < (1<<PARTN_BITS); ++p) {
    if (drive->part[p].nr_sects > 0) {
    @@ -1607,8 +1718,8 @@

    if (index >= MAX_HWIFS)
    return;
    - __save_flags(flags);
    - __cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    hwif = &ide_hwifs[index];
    if (!hwif->present)
    goto abort;
    @@ -1698,7 +1809,7 @@
    }
    init_hwif_data (index); /* restore hwif data to pristine status */
    abort:
    - __restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    }

    int ide_register (int arg1, int arg2, int irq)
    @@ -1737,7 +1848,7 @@
    return hwif->present ? index : -1;
    }

    -void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
    +void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
    {
    ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;

    @@ -1816,25 +1927,50 @@

    int ide_read_setting(ide_drive_t *drive, ide_settings_t *setting)
    {
    - if (!(setting->rw & SETTING_READ))
    - return -EINVAL;
    - switch(setting->data_type) {
    - case TYPE_BYTE:
    - return *((u8 *) setting->data);
    - case TYPE_SHORT:
    - return *((u16 *) setting->data);
    - case TYPE_INT:
    - case TYPE_INTA:
    - return *((u32 *) setting->data);
    - default:
    - return -EINVAL;
    + int val = -EINVAL;
    + unsigned long flags;
    +
    + if ((setting->rw & SETTING_READ)) {
    + IDE_SPIN_LOCK_IRQSAVE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
    + switch(setting->data_type) {
    + case TYPE_BYTE:
    + val = *((u8 *) setting->data);
    + break;
    + case TYPE_SHORT:
    + val = *((u16 *) setting->data);
    + break;
    + case TYPE_INT:
    + case TYPE_INTA:
    + val = *((u32 *) setting->data);
    + break;
    + }
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_read_setting", &HWGROUP(drive)->spinlock, flags);
    + }
    + return val;
    +}
    +
    +int ide_spin_wait_hwgroup (const char *msg, ide_drive_t *drive, unsigned long *flags)
    +{
    + ide_hwgroup_t *hwgroup = HWGROUP(drive);
    + unsigned long timeout = jiffies + (3 * HZ);
    +
    + IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
    + while (hwgroup->busy) {
    + IDE_SPIN_UNLOCK_IRQRESTORE(msg, &hwgroup->spinlock, *flags);
    + __sti(); /* local CPU only; needed for jiffies */
    + if (0 < (signed long)(jiffies - timeout)) {
    + printk("%s: %s: channel busy\n", drive->name, msg);
    + return -EBUSY;
    + }
    + IDE_SPIN_LOCK_IRQSAVE(msg, &hwgroup->spinlock, *flags);
    }
    + return 0;
    }

    int ide_write_setting(ide_drive_t *drive, ide_settings_t *setting, int val)
    {
    unsigned long flags;
    - int i, rc = 0;
    + int i;
    u32 *p;

    if (!suser())
    @@ -1843,11 +1979,11 @@
    return -EPERM;
    if (val < setting->min || val > setting->max)
    return -EINVAL;
    - __save_flags(flags);
    - __cli();
    if (setting->set)
    - rc = setting->set(drive, val);
    - else switch (setting->data_type) {
    + return setting->set(drive, val);
    + if (ide_spin_wait_hwgroup("ide_write_settings", drive, &flags))
    + return -EBUSY;
    + switch (setting->data_type) {
    case TYPE_BYTE:
    *((u8 *) setting->data) = val;
    break;
    @@ -1863,8 +1999,8 @@
    *p = val;
    break;
    }
    - __restore_flags(flags);
    - return rc;
    + IDE_SPIN_UNLOCK_IRQRESTORE("ide_write_setting4", &HWGROUP(drive)->spinlock, flags);
    + return 0;
    }

    static int set_io_32bit(ide_drive_t *drive, int arg)
    @@ -1986,18 +2122,14 @@
    if (!suser()) return -EACCES;
    return ide_revalidate_disk(inode->i_rdev);

    + case HDIO_OBSOLETE_IDENTITY:
    case HDIO_GET_IDENTITY:
    if (MINOR(inode->i_rdev) & PARTN_MASK)
    return -EINVAL;
    if (drive->id == NULL)
    return -ENOMSG;
    -#if 0
    - if (copy_to_user((char *)arg, (char *)drive->id, sizeof(*drive->id)))
    + if (copy_to_user((char *)arg, (char *)drive->id, (cmd == HDIO_GET_IDENTITY) ? sizeof(*drive->id) : 142))
    return -EFAULT;
    -#else
    - if (copy_to_user((char *)arg, (char *)drive->id, 142))
    - return -EFAULT;
    -#endif
    return 0;

    case HDIO_GET_NICE:
    @@ -2329,7 +2461,7 @@
    goto bad_option; /* chipset already specified */
    if (i <= -7 && hw != 0)
    goto bad_hwif; /* chipset drivers are for "ide0=" only */
    - if (ide_hwifs[hw^1].chipset != ide_unknown)
    + if (i <= -7 && ide_hwifs[hw^1].chipset != ide_unknown)
    goto bad_option; /* chipset for 2nd port already specified */
    printk("\n");
    }
    @@ -2546,12 +2678,6 @@
    ide_probe_for_rz100x();
    }
    #endif /* CONFIG_BLK_DEV_RZ1000 */
    -#ifdef CONFIG_BLK_DEV_SL82C105
    - {
    - extern void ide_probe_for_sl82c105(void);
    - ide_probe_for_sl82c105();
    - }
    -#endif /* CONFIG_BLK_DEV_SL82C105 */
    #endif /* CONFIG_BLK_DEV_IDEPCI */
    }
    #endif /* CONFIG_PCI */
    @@ -2580,7 +2706,7 @@
    #ifdef CONFIG_BLK_DEV_IDE
    #ifdef __mc68000__
    if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
    - ide_get_lock(&ide_lock, NULL, NULL);
    + ide_get_lock(&ide_lock, NULL, NULL); /* for atari only */
    disable_irq(ide_hwifs[0].irq);
    }
    #endif /* __mc68000__ */
    @@ -2590,7 +2716,7 @@
    #ifdef __mc68000__
    if (ide_hwifs[0].io_ports[IDE_DATA_OFFSET]) {
    enable_irq(ide_hwifs[0].irq);
    - ide_release_lock(&ide_lock);
    + ide_release_lock(&ide_lock); /* for atari only */
    }
    #endif /* __mc68000__ */
    #endif /* CONFIG_BLK_DEV_IDE */
    @@ -2723,16 +2849,15 @@
    {
    unsigned long flags;

    - __save_flags(flags);
    - __cli();
    - if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL ||
    - drive->busy || drive->usage) {
    - __restore_flags(flags);
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    + if (version != IDE_SUBDRIVER_VERSION || !drive->present || drive->driver != NULL || drive->busy || drive->usage) {
    + restore_flags(flags); /* all CPUs */
    return 1;
    }
    drive->driver = driver;
    setup_driver_defaults(drive);
    - __restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    if (drive->autotune != 2) {
    if (driver->supports_dma && HWIF(drive)->dmaproc != NULL)
    (void) (HWIF(drive)->dmaproc(ide_dma_check, drive));
    @@ -2751,10 +2876,10 @@
    {
    unsigned long flags;

    - __save_flags(flags);
    - __cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    if (drive->usage || drive->busy || drive->driver == NULL || DRIVER(drive)->busy) {
    - __restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    return 1;
    }
    #ifdef CONFIG_PROC_FS
    @@ -2763,7 +2888,7 @@
    #endif
    auto_remove_settings(drive);
    drive->driver = NULL;
    - __restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    return 0;
    }

    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ide.h linux/drivers/block/ide.h
    --- linux-2.1.96/drivers/block/ide.h Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/ide.h Wed Apr 15 22:30:11 1998
    @@ -204,26 +204,27 @@
    unsigned long service_start; /* time we started last request */
    unsigned long service_time; /* service time of last request */
    special_t special; /* special action flags */
    + byte keep_settings; /* restore settings after drive reset */
    + byte using_dma; /* disk is using dma for read/write */
    + byte waiting_for_dma; /* dma currently in progress */
    + byte unmask; /* flag: okay to unmask other irqs */
    + byte slow; /* flag: slow data port */
    + byte bswap; /* flag: byte swap data */
    + byte dsc_overlap; /* flag: DSC overlap */
    + byte nice1; /* flag: give potential excess bandwidth */
    unsigned present : 1; /* drive is physically present */
    unsigned noprobe : 1; /* from: hdx=noprobe */
    - byte keep_settings; /* restore settings after drive reset */
    unsigned busy : 1; /* currently doing revalidate_disk() */
    unsigned removable : 1; /* 1 if need to do check_media_change */
    - byte using_dma; /* disk is using dma for read/write */
    unsigned forced_geom : 1; /* 1 if hdx=c,h,s was given at boot */
    - byte unmask; /* flag: okay to unmask other irqs */
    unsigned no_unmask : 1; /* disallow setting unmask bit */
    unsigned no_io_32bit : 1; /* disallow enabling 32bit I/O */
    unsigned nobios : 1; /* flag: do not probe bios for drive */
    - byte slow; /* flag: slow data port */
    - unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
    unsigned revalidate : 1; /* request revalidation */
    - byte bswap; /* flag: byte swap data */
    - byte dsc_overlap; /* flag: DSC overlap */
    unsigned atapi_overlap : 1; /* flag: ATAPI overlap (not supported) */
    unsigned nice0 : 1; /* flag: give obvious excess bandwidth */
    - byte nice1; /* flag: give potential excess bandwidth */
    unsigned nice2 : 1; /* flag: give a share in our own bandwidth */
    + unsigned autotune : 2; /* 1=autotune, 2=noautotune, 0=default */
    #if FAKE_FDISK_FOR_EZDRIVE
    unsigned remap_0_to_1 : 1; /* flag: partitioned with ezdrive */
    #endif /* FAKE_FDISK_FOR_EZDRIVE */
    @@ -270,7 +271,8 @@
    * should either try again later, or revert to PIO for the current request.
    */
    typedef enum { ide_dma_read, ide_dma_write, ide_dma_begin, ide_dma_end,
    - ide_dma_check, ide_dma_on, ide_dma_off, ide_dma_off_quietly
    + ide_dma_check, ide_dma_on, ide_dma_off, ide_dma_off_quietly,
    + ide_dma_test_irq
    } ide_dma_action_t;

    typedef int (ide_dmaproc_t)(ide_dma_action_t, ide_drive_t *);
    @@ -340,7 +342,7 @@
    unsigned reset : 1; /* reset after probe */
    unsigned no_autodma : 1; /* don't automatically enable DMA at boot */
    byte channel; /* for dual-port chips: 0=primary, 1=secondary */
    - struct pci_dev *pci_dev; /* for pci chipsets */
    + struct pci_dev *pci_dev; /* for pci chipsets */
    ide_pci_devid_t pci_devid; /* for pci chipsets: {VID,DID} */
    #if (DISK_RECOVERY_TIME > 0)
    unsigned long last_time; /* time when previous rq was done */
    @@ -353,14 +355,15 @@
    typedef void (ide_handler_t)(ide_drive_t *);

    typedef struct hwgroup_s {
    + spinlock_t spinlock; /* protects "busy" and "handler" */
    ide_handler_t *handler;/* irq handler, if active */
    + int busy; /* BOOL: protects all fields below */
    ide_drive_t *drive; /* current drive */
    ide_hwif_t *hwif; /* ptr to current hwif in linked-list */
    struct request *rq; /* current request */
    struct timer_list timer; /* failsafe timer */
    struct request wrq; /* local copy of current write rq */
    unsigned long poll_timeout; /* timeout value during long polls */
    - int active; /* set when servicing requests */
    } ide_hwgroup_t;

    /*
    @@ -393,7 +396,7 @@
    struct ide_settings_s *next;
    } ide_settings_t;

    -void ide_add_setting(ide_drive_t *drive, char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
    +void ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set);
    void ide_remove_setting(ide_drive_t *drive, char *name);
    ide_settings_t *ide_find_setting_by_name(ide_drive_t *drive, char *name);
    int ide_read_setting(ide_drive_t *t, ide_settings_t *setting);
    @@ -663,6 +666,7 @@
    */
    struct request **ide_get_queue (kdev_t dev);

    +int ide_spin_wait_hwgroup(const char *msg, ide_drive_t *drive, unsigned long *flags);
    void ide_timer_expiry (unsigned long data);
    void ide_intr (int irq, void *dev_id, struct pt_regs *regs);
    void ide_geninit (struct gendisk *gd);
    @@ -689,6 +693,9 @@
    #endif

    #ifdef _IDE_C
    +#ifdef CONFIG_BLK_DEV_IDE
    +int ideprobe_init (void);
    +#endif /* CONFIG_BLK_DEV_IDE */
    #ifdef CONFIG_BLK_DEV_IDEDISK
    int idedisk_init (void);
    #endif /* CONFIG_BLK_DEV_IDEDISK */
    @@ -722,12 +729,8 @@
    void ide_dma_intr (ide_drive_t *drive);
    int ide_dmaproc (ide_dma_action_t func, ide_drive_t *drive);
    void ide_setup_dma (ide_hwif_t *hwif, unsigned long dmabase, unsigned int num_ports) __init;
    -unsigned long ide_get_or_set_dma_base (struct pci_dev *dev, ide_hwif_t *hwif, int extra, const char *name) __init;
    +unsigned long ide_get_or_set_dma_base (ide_hwif_t *hwif, int extra, const char *name) __init;
    #endif
    -
    -#ifdef CONFIG_BLK_DEV_IDE
    -int ideprobe_init (void);
    -#endif /* CONFIG_BLK_DEV_IDE */

    #ifdef CONFIG_BLK_DEV_PDC4030
    #include "pdc4030.h"
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/ns87415.c linux/drivers/block/ns87415.c
    --- linux-2.1.96/drivers/block/ns87415.c Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/ns87415.c Wed Apr 15 22:18:02 1998
    @@ -35,7 +35,8 @@
    struct pci_dev *dev = hwif->pci_dev;
    unsigned long flags;

    - save_flags(flags); cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    new = *old;

    /* adjust IRQ enable bit */
    @@ -56,7 +57,7 @@
    *old = new;
    (void) pci_write_config_dword(dev, 0x40, new);
    }
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    }

    static void ns87415_selectproc (ide_drive_t *drive)
    @@ -66,33 +67,25 @@

    static int ns87415_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
    {
    - ide_hwif_t *hwif = HWIF(drive);
    + ide_hwif_t *hwif = HWIF(drive);
    + byte dma_stat;

    switch (func) {
    case ide_dma_end: /* returns 1 on error, 0 otherwise */
    - {
    - byte dma_stat = inb(hwif->dma_base+2);
    - int rc = (dma_stat & 7) != 4;
    - /* from errata: stop DMA, clear INTR & ERROR */
    - outb(7, hwif->dma_base);
    - /* clear the INTR & ERROR bits */
    - outb(dma_stat|6, hwif->dma_base+2);
    - /* verify good DMA status */
    - return rc;
    - }
    + drive->waiting_for_dma = 0;
    + dma_stat = inb(hwif->dma_base+2);
    + outb(7, hwif->dma_base); /* from errata: stop DMA, clear INTR & ERROR */
    + outb(dma_stat|6, hwif->dma_base+2); /* clear the INTR & ERROR bits */
    + return (dma_stat & 7) != 4; /* verify good DMA status */
    case ide_dma_write:
    case ide_dma_read:
    - /* select DMA xfer */
    - ns87415_prepare_drive(drive, 1);
    - /* use standard DMA stuff */
    - if (!ide_dmaproc(func, drive))
    + ns87415_prepare_drive(drive, 1); /* select DMA xfer */
    + if (!ide_dmaproc(func, drive)) /* use standard DMA stuff */
    return 0;
    - /* DMA failed: select PIO xfer */
    - ns87415_prepare_drive(drive, 0);
    + ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */
    return 1;
    default:
    - /* use standard DMA stuff */
    - return ide_dmaproc(func, drive);
    + return ide_dmaproc(func, drive); /* use standard DMA stuff */
    }
    }

    @@ -100,8 +93,7 @@
    {
    struct pci_dev *dev = hwif->pci_dev;
    unsigned int ctrl, using_inta;
    - byte progif, stat;
    - int timeout;
    + byte progif;

    /*
    * We cannot probe for IRQ: both ports share common IRQ on INTA.
    @@ -134,6 +126,9 @@
    pci_write_config_byte(dev, 0x55, 0xee);

    #ifdef __sparc_v9__
    +{
    + int timeout;
    + byte stat;
    /*
    * XXX: Reset the device, if we don't it will not respond
    * to SELECT_DRIVE() properly during first probe_hwif().
    @@ -148,6 +143,7 @@
    if (stat == 0xff)
    break;
    } while ((stat & BUSY_STAT) && --timeout);
    +}
    #endif
    }
    if (!using_inta)
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/opti621.c linux/drivers/block/opti621.c
    --- linux-2.1.96/drivers/block/opti621.c Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/opti621.c Wed Apr 15 22:18:02 1998
    @@ -242,8 +242,8 @@
    hwif->name, ax, second.data_time, second.recovery_time, drdy);
    #endif

    - save_flags(flags);
    - cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */

    reg_base = hwif->io_ports[IDE_DATA_OFFSET];
    outb(0xc0, reg_base+CNTRL_REG); /* allow Register-B */
    @@ -268,7 +268,7 @@
    write_reg(misc, MISC_REG); /* set address setup, DRDY timings, */
    /* and read prefetch for both drives */

    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    }

    /*
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/pdc4030.c linux/drivers/block/pdc4030.c
    --- linux-2.1.96/drivers/block/pdc4030.c Mon Dec 29 12:25:29 1997
    +++ linux/drivers/block/pdc4030.c Wed Apr 15 22:18:02 1998
    @@ -327,15 +327,9 @@
    do {
    stat=GET_STAT();
    if(stat & DRQ_STAT) {
    -/* unsigned long flags;
    - save_flags(flags);
    - cli();
    disable_irq(HWIF(drive)->irq);
    -*/
    ide_intr(HWIF(drive)->irq,HWGROUP(drive),NULL);
    -/* enable_irq(HWIF(drive)->irq);
    - restore_flags(flags);
    -*/
    + enable_irq(HWIF(drive)->irq);
    return;
    }
    if(IN_BYTE(IDE_SELECT_REG) & 0x01)
    @@ -353,7 +347,7 @@
    return;
    }
    if (!drive->unmask)
    - cli();
    + __cli(); /* local CPU only */
    HWGROUP(drive)->wrq = *rq; /* scratchpad */
    promise_write(drive);
    return;
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/qd6580.c linux/drivers/block/qd6580.c
    --- linux-2.1.96/drivers/block/qd6580.c Mon Dec 29 12:25:29 1997
    +++ linux/drivers/block/qd6580.c Wed Apr 15 22:18:02 1998
    @@ -49,13 +49,13 @@

    pio = ide_get_best_pio_mode(drive, pio, 3, NULL);

    - save_flags(flags);
    - cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    outb_p(0x8d,0xb0);
    outb_p(0x0 ,0xb2);
    outb_p(((pio+1)<<4)|0x0f,0xb3);
    inb(0x3f6);
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    }

    void init_qd6580 (void)
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/sl82c105.c linux/drivers/block/sl82c105.c
    --- linux-2.1.96/drivers/block/sl82c105.c Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/sl82c105.c Wed Apr 15 22:18:02 1998
    @@ -19,8 +19,9 @@
    ide_ioreg_t chrp_ide_regbase[MAX_HWIFS];
    ide_ioreg_t chrp_idedma_regbase;

    -void ide_init_sl82c105(struct pci_dev *dev) {
    -
    +void ide_init_sl82c105(ide_hwif_t *hwif)
    +{
    + struct pci_dev *dev = hwif->pci_dev;
    unsigned short t16;
    unsigned int t32;

    @@ -37,15 +38,7 @@
    pci_write_config_dword(dev, 0x40, 0x10ff08a1);
    }

    -
    -void ide_probe_for_sl82c105(void)
    -{
    - struct pci_dev *dev = NULL;
    -
    - while ((dev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, dev)))
    - ide_init_sl82c105(dev);
    -}
    -
    +#if 0 /* nobody ever calls these.. ?? */
    void chrp_ide_probe(void) {

    struct pci_dev *pdev = pci_find_device(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, NULL);
    @@ -75,4 +68,4 @@
    if (irq != NULL)
    *irq = chrp_ide_irq;
    }
    -
    +#endif
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/trm290.c linux/drivers/block/trm290.c
    --- linux-2.1.96/drivers/block/trm290.c Mon Apr 6 22:16:07 1998
    +++ linux/drivers/block/trm290.c Wed Apr 15 22:18:02 1998
    @@ -148,8 +148,8 @@
    /* select PIO or DMA */
    reg = use_dma ? (0x21 | 0x82) : (0x21 & ~0x82);

    - save_flags(flags);
    - cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */

    if (reg != hwif->select_data) {
    hwif->select_data = reg;
    @@ -164,7 +164,7 @@
    outw(reg, hwif->config_data+3);
    }

    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    }

    static void trm290_selectproc (ide_drive_t *drive)
    @@ -189,15 +189,20 @@
    break; /* try PIO instead of DMA */
    trm290_prepare_drive(drive, 1); /* select DMA xfer */
    outl(virt_to_bus(hwif->dmatable)|reading|writing, hwif->dma_base);
    + drive->waiting_for_dma = 1;
    outw((count * 2) - 1, hwif->dma_base+2); /* start DMA */
    if (drive->media != ide_disk)
    return 0;
    ide_set_handler(drive, &ide_dma_intr, WAIT_CMD);
    OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG);
    + return 0;
    case ide_dma_begin:
    return 0;
    case ide_dma_end:
    + drive->waiting_for_dma = 0;
    return (inw(hwif->dma_base+2) != 0x00ff);
    + case ide_dma_test_irq:
    + return (inw(hwif->dma_base+2) == 0x00ff);
    default:
    return ide_dmaproc(func, drive);
    }
    @@ -226,8 +231,8 @@
    printk("TRM290: using default config base at 0x%04lx\n", hwif->config_data);
    }

    - save_flags(flags);
    - cli();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    /* put config reg into first byte of hwif->select_data */
    outb(0x51|(hwif->channel<<3), hwif->config_data+1);
    hwif->select_data = 0x21; /* select PIO as default */
    @@ -235,13 +240,13 @@
    reg = inb(hwif->config_data+3); /* get IRQ info */
    reg = (reg & 0x10) | 0x03; /* mask IRQs for both ports */
    outb(reg, hwif->config_data+3);
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */

    if ((reg & 0x10))
    hwif->irq = hwif->channel ? 15 : 14; /* legacy mode */
    else if (!hwif->irq && hwif->mate && hwif->mate->irq)
    hwif->irq = hwif->mate->irq; /* sharing IRQ with mate */
    - ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 2);
    + ide_setup_dma(hwif, (hwif->config_data + 4) ^ (hwif->channel ? 0x0080 : 0x0000), 3);
    hwif->dmaproc = &trm290_dmaproc;
    hwif->selectproc = &trm290_selectproc;
    hwif->no_autodma = 1; /* play it safe for now */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/block/umc8672.c linux/drivers/block/umc8672.c
    --- linux-2.1.96/drivers/block/umc8672.c Mon Dec 29 12:25:30 1997
    +++ linux/drivers/block/umc8672.c Wed Apr 15 22:18:02 1998
    @@ -112,39 +112,39 @@

    pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
    printk("%s: setting umc8672 to PIO mode%d (speed %d)\n", drive->name, pio, pio_to_umc[pio]);
    - save_flags(flags);
    - cli();
    + save_flags(flags); /* all CPUs */
    + cli(); /* all CPUs */
    if (hwgroup && hwgroup->handler != NULL) {
    printk("umc8672: other interface is busy: exiting tune_umc()\n");
    } else {
    current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
    umc_set_speeds (current_speeds);
    }
    - restore_flags(flags);
    + restore_flags(flags); /* all CPUs */
    }

    void init_umc8672 (void) /* called from ide.c */
    {
    unsigned long flags;

    - save_flags(flags);
    - cli ();
    + __save_flags(flags); /* local CPU only */
    + __cli(); /* local CPU only */
    if (check_region(0x108, 2)) {
    - restore_flags(flags);
    + __restore_flags(flags);
    printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
    return;
    }
    outb_p (0x5A,0x108); /* enable umc */
    if (in_umc (0xd5) != 0xa0)
    {
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */
    printk ("umc8672: not found\n");
    return;
    }
    outb_p (0xa5,0x108); /* disable umc */

    umc_set_speeds (current_speeds);
    - restore_flags(flags);
    + __restore_flags(flags); /* local CPU only */

    request_region(0x108, 2, "umc8672");
    ide_hwifs[0].chipset = ide_umc8672;
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
    --- linux-2.1.96/drivers/scsi/ide-scsi.c Wed Apr 15 22:08:30 1998
    +++ linux/drivers/scsi/ide-scsi.c Wed Apr 15 22:25:38 1998
    @@ -326,7 +326,7 @@
    if ((status & DRQ_STAT) == 0) { /* No more interrupts */
    if (test_bit(IDESCSI_LOG_CMD, &scsi->log))
    printk (KERN_INFO "Packet command completed, %d bytes transferred\n", pc->actually_transferred);
    - ide_sti();
    + ide__sti();
    if (status & ERR_STAT)
    rq->errors++;
    idescsi_end_request (1, HWGROUP(drive));
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-alpha/ide.h linux/include/asm-alpha/ide.h
    --- linux-2.1.96/include/asm-alpha/ide.h Thu Mar 27 17:40:06 1997
    +++ linux/include/asm-alpha/ide.h Wed Apr 15 22:18:02 1998
    @@ -19,7 +19,7 @@
    #define MAX_HWIFS 4
    #endif

    -#define ide_sti() sti()
    +#define ide__sti() __sti()

    static __inline__ int ide_default_irq(ide_ioreg_t base)
    {
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-arm/ide.h linux/include/asm-arm/ide.h
    --- linux-2.1.96/include/asm-arm/ide.h Mon Jan 26 19:32:12 1998
    +++ linux/include/asm-arm/ide.h Wed Apr 15 22:18:02 1998
    @@ -19,7 +19,7 @@
    #define MAX_HWIFS 4
    #endif

    -#define ide_sti() sti()
    +#define ide__sti() __sti()

    #include <asm/arch/ide.h>

    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-i386/ide.h linux/include/asm-i386/ide.h
    --- linux-2.1.96/include/asm-i386/ide.h Wed Apr 1 21:24:41 1998
    +++ linux/include/asm-i386/ide.h Wed Apr 15 22:18:02 1998
    @@ -19,7 +19,7 @@
    #define MAX_HWIFS 6
    #endif

    -#define ide_sti() sti()
    +#define ide__sti() __sti()

    static __inline__ int ide_default_irq(ide_ioreg_t base)
    {
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h
    --- linux-2.1.96/include/asm-i386/spinlock.h Sun Jan 18 16:58:56 1998
    +++ linux/include/asm-i386/spinlock.h Wed Apr 15 22:18:02 1998
    @@ -3,6 +3,10 @@

    #ifndef __SMP__

    +#define DEBUG_SPINLOCKS 0 /* 0 == no debugging, 1 == maintain lock state, 2 == full debug */
    +
    +#if (DEBUG_SPINLOCKS < 1)
    +
    /*
    * Your basic spinlocks, allowing only a single CPU anywhere
    */
    @@ -11,7 +15,7 @@

    #define spin_lock_init(lock) do { } while(0)
    #define spin_lock(lock) do { } while(0)
    -#define spin_trylock(lock) do { } while(0)
    +#define spin_trylock(lock) (1)
    #define spin_unlock_wait(lock) do { } while(0)
    #define spin_unlock(lock) do { } while(0)
    #define spin_lock_irq(lock) cli()
    @@ -22,6 +26,52 @@
    #define spin_unlock_irqrestore(lock, flags) \
    restore_flags(flags)

    +#elif (DEBUG_SPINLOCKS < 2)
    +
    +typedef struct {
    + volatile unsigned int lock;
    +} spinlock_t;
    +#define SPIN_LOCK_UNLOCKED { 0 }
    +
    +#define spin_lock_init(x) do { (x)->lock = 0; } while (0)
    +#define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
    +
    +#define spin_lock(x) do { (x)->lock = 1; } while (0)
    +#define spin_unlock_wait(x) do { } while (0)
    +#define spin_unlock(x) do { (x)->lock = 0; } while (0)
    +#define spin_lock_irq(x) do { cli(); spin_lock(x); } while (0)
    +#define spin_unlock_irq(x) do { spin_unlock(x); sti(); } while (0)
    +
    +#define spin_lock_irqsave(x, flags) \
    + do { save_flags(flags); spin_lock_irq(x); } while (0)
    +#define spin_unlock_irqrestore(x, flags) \
    + do { spin_unlock(x); restore_flags(flags); } while (0)
    +
    +#else /* (DEBUG_SPINLOCKS >= 2) */
    +
    +typedef struct {
    + volatile unsigned int lock;
    + volatile unsigned int babble;
    + const char *module;
    +} spinlock_t;
    +#define SPIN_LOCK_UNLOCKED { 0, 25, __BASE_FILE__ }
    +
    +#include <linux/kernel.h>
    +
    +#define spin_lock_init(x) do { (x)->lock = 0; } while (0)
    +#define spin_trylock(lock) (!test_and_set_bit(0,(lock)))
    +
    +#define spin_lock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; restore_flags(__spinflags);} while (0)
    +#define spin_unlock_wait(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_unlock_wait(%s:%p) deadlock\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} restore_flags(__spinflags);} while (0)
    +#define spin_unlock(x) do {unsigned long __spinflags; save_flags(__spinflags); cli(); if (!(x)->lock&&(x)->babble) {printk("%s: spin_unlock(%s:%p) not locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(__spinflags);} while (0)
    +#define spin_lock_irq(x) do {cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock_irq(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
    +#define spin_unlock_irq(x) do {cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1; sti();} while (0)
    +
    +#define spin_lock_irqsave(x,flags) do {save_flags(flags); cli(); if ((x)->lock&&(x)->babble) {printk("%s: spin_lock_irqsave(%s:%p) already locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 1;} while (0)
    +#define spin_unlock_irqrestore(x,flags) do {cli(); if (!(x)->lock&&(x)->babble) {printk("%s: spin_unlock_irqrestore(%s:%p) not locked\n", __BASE_FILE__, (x)->module, (x));(x)->babble--;} (x)->lock = 0; restore_flags(flags);} while (0)
    +
    +#endif /* DEBUG_SPINLOCKS */
    +
    /*
    * Read-write spinlocks, allowing multiple readers
    * but only one writer.
    @@ -53,13 +103,10 @@
    #define write_unlock_irqrestore(lock, flags) \
    restore_flags(flags)

    -#else
    +#else /* __SMP__ */

    /*
    - * Simple spin lock operations. There are two variants, one clears IRQ's
    - * on the local processor, one does not.
    - *
    - * We make no fairness assumptions. They have a cost.
    + * Your basic spinlocks, allowing only a single CPU anywhere
    */

    typedef struct {
    @@ -69,6 +116,13 @@
    #define SPIN_LOCK_UNLOCKED { 0 }

    #define spin_lock_init(x) do { (x)->lock = 0; } while(0)
    +/*
    + * Simple spin lock operations. There are two variants, one clears IRQ's
    + * on the local processor, one does not.
    + *
    + * We make no fairness assumptions. They have a cost.
    + */
    +
    #define spin_unlock_wait(x) do { barrier(); } while(((volatile spinlock_t *)(x))->lock)

    typedef struct { unsigned long a[100]; } __dummy_lock_t;
    @@ -176,5 +230,5 @@
    #define write_unlock_irqrestore(lock, flags) \
    do { write_unlock(lock); __restore_flags(flags); } while (0)

    -#endif /* SMP */
    +#endif /* __SMP__ */
    #endif /* __ASM_SPINLOCK_H */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
    --- linux-2.1.96/include/asm-m68k/ide.h Thu Mar 26 22:30:30 1998
    +++ linux/include/asm-m68k/ide.h Wed Apr 15 22:18:02 1998
    @@ -424,17 +424,17 @@
    * works. (Roman)
    */
    #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA)
    -#define ide_sti() \
    +#define ide__sti() \
    do { \
    - if (!in_interrupt()) sti(); \
    + if (!in_interrupt()) __sti(); \
    } while(0)
    #elif defined(CONFIG_ATARI)
    -#define ide_sti() \
    +#define ide__sti() \
    do { \
    if (!MACH_IS_ATARI || !in_interrupt()) sti(); \
    } while(0)
    #else /* !defined(CONFIG_ATARI) */
    -#define ide_sti() sti()
    +#define ide__sti() __sti()
    #endif

    #endif /* __KERNEL__ */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-mips/ide.h linux/include/asm-mips/ide.h
    --- linux-2.1.96/include/asm-mips/ide.h Thu Jun 26 15:33:39 1997
    +++ linux/include/asm-mips/ide.h Wed Apr 15 22:18:02 1998
    @@ -19,7 +19,7 @@
    #define MAX_HWIFS 4
    #endif

    -#define ide_sti() sti()
    +#define ide__sti() __sti()

    static __inline__ int ide_default_irq(ide_ioreg_t base)
    {
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-ppc/ide.h linux/include/asm-ppc/ide.h
    --- linux-2.1.96/include/asm-ppc/ide.h Sun Jan 18 16:58:56 1998
    +++ linux/include/asm-ppc/ide.h Wed Apr 15 22:18:02 1998
    @@ -26,7 +26,7 @@
    #define SUPPORT_VLB_SYNC 0


    -#define ide_sti() sti()
    +#define ide__sti() __sti()

    typedef unsigned long ide_ioreg_t;
    void ide_init_hwif_ports(ide_ioreg_t *p, ide_ioreg_t base, int *irq);
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/asm-sparc64/ide.h linux/include/asm-sparc64/ide.h
    --- linux-2.1.96/include/asm-sparc64/ide.h Thu Sep 4 15:54:49 1997
    +++ linux/include/asm-sparc64/ide.h Wed Apr 15 22:18:02 1998
    @@ -21,7 +21,7 @@

    extern void sparc64_ide_probe(void);

    -#define ide_sti() sti()
    +#define ide__sti() __sti()

    static __inline__ int ide_default_irq(ide_ioreg_t base)
    {
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/linux/blk.h linux/include/linux/blk.h
    --- linux-2.1.96/include/linux/blk.h Wed Apr 1 21:24:42 1998
    +++ linux/include/linux/blk.h Wed Apr 15 22:29:47 1998
    @@ -411,14 +411,20 @@

    #ifdef IDE_DRIVER
    void ide_end_request(byte uptodate, ide_hwgroup_t *hwgroup) {
    - struct request *req = hwgroup->rq;
    + int nsect;
    + struct buffer_head *bh;
    + struct request *req;
    + unsigned long flags;
    +
    + spin_lock_irqsave(&io_request_lock,flags);
    + req = hwgroup->rq;
    #else
    static void end_request(int uptodate) {
    - struct request *req = CURRENT;
    -#endif /* IDE_DRIVER */
    - struct buffer_head * bh;
    int nsect;
    + struct buffer_head *bh;
    + struct request *req = CURRENT;

    +#endif /* IDE_DRIVER */
    req->errors = 0;
    if (!uptodate) {
    printk("end_request: I/O error, dev %s, sector %lu\n",
    @@ -443,6 +449,9 @@
    printk("end_request: buffer-list destroyed\n");
    }
    req->buffer = bh->b_data;
    +#ifdef IDE_DRIVER
    + spin_unlock_irqrestore(&io_request_lock,flags);
    +#endif /* IDE_DRIVER */
    return;
    }
    }
    @@ -461,6 +470,9 @@
    up(req->sem);
    req->rq_status = RQ_INACTIVE;
    wake_up(&wait_for_request);
    +#ifdef IDE_DRIVER
    + spin_unlock_irqrestore(&io_request_lock,flags);
    +#endif /* IDE_DRIVER */
    }
    #endif /* defined(IDE_DRIVER) && !defined(_IDE_C) */
    #endif /* ! SCSI_BLK_MAJOR(MAJOR_NR) */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/linux/hdreg.h linux/include/linux/hdreg.h
    --- linux-2.1.96/include/linux/hdreg.h Wed Feb 18 21:23:13 1998
    +++ linux/include/linux/hdreg.h Wed Apr 15 22:29:47 1998
    @@ -45,7 +45,7 @@
    #define WIN_VERIFY 0x40
    #define WIN_FORMAT 0x50
    #define WIN_INIT 0x60
    -#define WIN_SEEK 0x70
    +#define WIN_SEEK 0x70
    #define WIN_DIAGNOSE 0x90
    #define WIN_SPECIFY 0x91 /* set drive geometry translation */
    #define WIN_SETIDLE1 0xE3
    @@ -101,12 +101,13 @@
    #define HDIO_GETGEO 0x0301 /* get device geometry */
    #define HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */
    #define HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */
    -#define HDIO_GET_IDENTITY 0x0307 /* get IDE identification info */
    -#define HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */
    -#define HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */
    +#define HDIO_OBSOLETE_IDENTITY 0x0307 /* OBSOLETE, DO NOT USE: returns 142 bytes */
    +#define HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */
    +#define HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */
    #define HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */
    #define HDIO_GET_DMA 0x030b /* get use-dma flag */
    #define HDIO_GET_NICE 0x030c /* get nice flags */
    +#define HDIO_GET_IDENTITY 0x030d /* get IDE identification info */
    #define HDIO_DRIVE_CMD 0x031f /* execute a special drive command */

    /* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/include/linux/proc_fs.h linux/include/linux/proc_fs.h
    --- linux-2.1.96/include/linux/proc_fs.h Sat Apr 11 09:26:14 1998
    +++ linux/include/linux/proc_fs.h Wed Apr 15 22:29:47 1998
    @@ -363,7 +363,6 @@
    extern struct inode_operations proc_file_inode_operations;
    extern struct inode_operations proc_net_inode_operations;
    extern struct inode_operations proc_netdir_inode_operations;
    -extern struct inode_operations proc_scsi_inode_operations;
    extern struct inode_operations proc_openprom_inode_operations;
    extern struct inode_operations proc_mem_inode_operations;
    extern struct inode_operations proc_sys_inode_operations;
    @@ -380,8 +379,6 @@
    extern struct inode_operations proc_omirr_inode_operations;
    extern struct inode_operations proc_ppc_htab_inode_operations;

    -#endif
    -
    /*
    * generic.c
    */
    @@ -400,3 +397,5 @@
    * proc_devtree.c
    */
    extern void proc_device_tree_init(void);
    +
    +#endif /* _LINUX_PROC_FS_H */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/kernel/fork.c linux/kernel/fork.c
    --- linux-2.1.96/kernel/fork.c Wed Apr 15 22:08:33 1998
    +++ linux/kernel/fork.c Wed Apr 15 22:18:02 1998
    @@ -56,9 +56,7 @@
    int task_count;
    } *uidhash[UIDHASH_SZ];

    -#ifdef __SMP__
    -static spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;
    -#endif
    +spinlock_t uidhash_lock = SPIN_LOCK_UNLOCKED;

    kmem_cache_t *uid_cachep;

    @@ -154,10 +152,8 @@
    return -EAGAIN;
    }

    -#ifdef __SMP__
    /* Protects next_safe and last_pid. */
    -static spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;
    -#endif
    +spinlock_t lastpid_lock = SPIN_LOCK_UNLOCKED;

    static int get_pid(unsigned long flags)
    {
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/kernel/sched.c linux/kernel/sched.c
    --- linux-2.1.96/kernel/sched.c Wed Apr 1 21:24:43 1998
    +++ linux/kernel/sched.c Wed Apr 15 22:18:02 1998
    @@ -47,6 +47,8 @@
    * kernel variables
    */

    +spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
    +
    unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */

    long tick = (1000000 + HZ/2) / HZ; /* timer interrupt period */
    diff -u --recursive --new-file --exclude=.* linux-2.1.96/mm/page_alloc.c linux/mm/page_alloc.c
    --- linux-2.1.96/mm/page_alloc.c Mon Apr 6 22:16:18 1998
    +++ linux/mm/page_alloc.c Wed Apr 15 22:18:02 1998
    @@ -98,9 +98,7 @@
    *
    * Hint: -mask = 1+~mask
    */
    -#ifdef __SMP__
    -static spinlock_t page_alloc_lock;
    -#endif
    +static spinlock_t page_alloc_lock = SPIN_LOCK_UNLOCKED;

    /*
    * This routine is used by the kernel swap deamon to determine
    \
     
     \ /
      Last update: 2005-03-22 13:42    [W:0.205 / U:1.000 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site