Can you try this patch?
If it fixes the oops, I'll forward upstream ASAP.
Jeff
===== drivers/scsi/ahci.c 1.14 vs edited ===== --- 1.14/drivers/scsi/ahci.c 2005-02-13 19:58:01 -05:00 +++ edited/drivers/scsi/ahci.c 2005-02-22 21:46:25 -05:00 @@ -179,6 +179,7 @@ static void ahci_host_stop(struct ata_host_set *host_set); static void ahci_qc_prep(struct ata_queued_cmd *qc); static u8 ahci_check_status(struct ata_port *ap); +static u8 ahci_check_err(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static Scsi_Host_Template ahci_sht = { @@ -204,6 +205,8 @@ .port_disable = ata_port_disable, .check_status = ahci_check_status, + .check_altstatus = ahci_check_status, + .check_err = ahci_check_err, .dev_select = ata_noop_dev_select, .phy_reset = ahci_phy_reset, @@ -450,6 +453,13 @@ void *mmio = (void *) ap->ioaddr.cmd_addr; return readl(mmio + PORT_TFDATA) & 0xFF; +} + +static u8 ahci_check_err(struct ata_port *ap) +{ + void *mmio = (void *) ap->ioaddr.cmd_addr; + + return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF; } static void ahci_fill_sg(struct ata_queued_cmd *qc) ===== drivers/scsi/libata-core.c 1.120 vs edited ===== --- 1.120/drivers/scsi/libata-core.c 2005-02-22 21:19:40 -05:00 +++ edited/drivers/scsi/libata-core.c 2005-02-22 21:45:16 -05:00 @@ -377,7 +377,7 @@ } /** - * ata_check_status - Read device status reg & clear interrupt + * ata_check_status_pio - Read device status reg & clear interrupt * @ap: port where the device is * * Reads ATA taskfile status register for currently-selected device @@ -415,6 +415,27 @@ return ata_check_status_pio(ap); } +u8 ata_altstatus(struct ata_port *ap) +{ + if (ap->ops->check_altstatus) + return ap->ops->check_altstatus(ap); + + if (ap->flags & ATA_FLAG_MMIO) + return readb((void __iomem *)ap->ioaddr.altstatus_addr); + return inb(ap->ioaddr.altstatus_addr); +} + +u8 ata_chk_err(struct ata_port *ap) +{ + if (ap->ops->check_err) + return ap->ops->check_err(ap); + + if (ap->flags & ATA_FLAG_MMIO) { + return readb((void __iomem *) ap->ioaddr.error_addr); + } + return inb(ap->ioaddr.error_addr); +} + /** * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * @tf: Taskfile to convert @@ -1161,7 +1182,6 @@ printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", ap->id, device); err_out: - ata_irq_on(ap); /* re-enable interrupts */ dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ DPRINTK("EXIT, err\n"); } @@ -1669,7 +1689,8 @@ ata_dev_try_classify(ap, 1); /* re-enable interrupts */ - ata_irq_on(ap); + if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */ + ata_irq_on(ap); /* is double-select really necessary? */ if (ap->device[1].class != ATA_DEV_NONE) @@ -3972,6 +3993,8 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_check_status); +EXPORT_SYMBOL_GPL(ata_altstatus); +EXPORT_SYMBOL_GPL(ata_chk_err); EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_stop); ===== include/linux/libata.h 1.64 vs edited ===== --- 1.64/include/linux/libata.h 2005-02-17 19:29:16 -05:00 +++ edited/include/linux/libata.h 2005-02-22 21:37:02 -05:00 @@ -334,6 +334,8 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); u8 (*check_status)(struct ata_port *ap); + u8 (*check_altstatus)(struct ata_port *ap); + u8 (*check_err)(struct ata_port *ap); void (*dev_select)(struct ata_port *ap, unsigned int device); void (*phy_reset) (struct ata_port *ap); @@ -403,6 +405,8 @@ extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device); extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); extern u8 ata_check_status(struct ata_port *ap); +extern u8 ata_altstatus(struct ata_port *ap); +extern u8 ata_chk_err(struct ata_port *ap); extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); extern int ata_port_start (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap); @@ -457,24 +461,9 @@ (dev->class == ATA_DEV_ATAPI)); } -static inline u8 ata_chk_err(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) { - return readb((void __iomem *) ap->ioaddr.error_addr); - } - return inb(ap->ioaddr.error_addr); -} - static inline u8 ata_chk_status(struct ata_port *ap) { return ap->ops->check_status(ap); -} - -static inline u8 ata_altstatus(struct ata_port *ap) -{ - if (ap->flags & ATA_FLAG_MMIO) - return readb((void __iomem *)ap->ioaddr.altstatus_addr); - return inb(ap->ioaddr.altstatus_addr); } static inline void ata_pause(struct ata_port *ap)