From 6a40da02be1e1d74eee653c6d181934d35cbca7d Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 24 Jan 2007 11:49:03 +0000 Subject: libata cmd64x: whack into a shape that looks like the documentation Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_cmd64x.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 15841a563694..449162cbf93e 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -197,7 +197,7 @@ static void cmd64x_set_piomode(struct ata_port *ap, struct ata_device *adev) static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) { static const u8 udma_data[] = { - 0x31, 0x21, 0x11, 0x25, 0x15, 0x05 + 0x30, 0x20, 0x10, 0x20, 0x10, 0x00 }; static const u8 mwdma_data[] = { 0x30, 0x20, 0x10 @@ -213,12 +213,21 @@ static void cmd64x_set_dmamode(struct ata_port *ap, struct ata_device *adev) pci_read_config_byte(pdev, pciD, ®D); pci_read_config_byte(pdev, pciU, ®U); - regD &= ~(0x20 << shift); - regU &= ~(0x35 << shift); + /* DMA bits off */ + regD &= ~(0x20 << adev->devno); + /* DMA control bits */ + regU &= ~(0x30 << shift); + /* DMA timing bits */ + regU &= ~(0x05 << adev->devno); - if (adev->dma_mode >= XFER_UDMA_0) + if (adev->dma_mode >= XFER_UDMA_0) { + /* Merge thge timing value */ regU |= udma_data[adev->dma_mode - XFER_UDMA_0] << shift; - else + /* Merge the control bits */ + regU |= 1 << adev->devno; /* UDMA on */ + if (adev->dma_mode > 2) /* 15nS timing */ + regU |= 4 << adev->devno; + } else regD |= mwdma_data[adev->dma_mode - XFER_MW_DMA_0] << shift; regD |= 0x20 << adev->devno; @@ -239,8 +248,8 @@ static void cmd648_bmdma_stop(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; struct pci_dev *pdev = to_pci_dev(ap->host->dev); u8 dma_intr; - int dma_reg = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; - int dma_mask = ap->port_no ? ARTTIM2 : CFR; + int dma_mask = ap->port_no ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; + int dma_reg = ap->port_no ? ARTTIM2 : CFR; ata_bmdma_stop(qc); -- cgit v1.2.3 From a52865c239b1bc4f62e387509b1ad3415e476ee5 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 24 Jan 2007 11:51:38 +0000 Subject: libata hpt3xn: Hopefully sort out the DPLL logic versus the vendor code Rather than ending up with two layers of negation jut rename the variable and lose one. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_hpt3x2n.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index f6817b4093a4..886fab9aa62c 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -25,7 +25,7 @@ #include #define DRV_NAME "pata_hpt3x2n" -#define DRV_VERSION "0.3" +#define DRV_VERSION "0.3.2" enum { HPT_PCI_FAST = (1 << 31), @@ -297,11 +297,11 @@ static int hpt3x2n_pair_idle(struct ata_port *ap) return 0; } -static int hpt3x2n_use_dpll(struct ata_port *ap, int reading) +static int hpt3x2n_use_dpll(struct ata_port *ap, int writing) { long flags = (long)ap->host->private_data; /* See if we should use the DPLL */ - if (reading == 0) + if (writing) return USE_DPLL; /* Needed for write */ if (flags & PCI66) return USE_DPLL; /* Needed at 66Mhz */ -- cgit v1.2.3 From b229a7b0aed808f2ef6a5e9dbf78b0f17cefb4d0 Mon Sep 17 00:00:00 2001 From: Alan Date: Wed, 24 Jan 2007 11:47:07 +0000 Subject: libata: set_mode, Fix the FIXME When set_mode() changed ->set_mode didn't adapt. This makes the needed changes and removes the relevant FIXME case. Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/ata_generic.c | 6 ++++-- drivers/ata/libata-core.c | 14 ++------------ drivers/ata/pata_it821x.c | 4 +++- drivers/ata/pata_ixp4xx_cf.c | 5 +++-- drivers/ata/pata_legacy.c | 4 +++- drivers/ata/pata_rz1000.c | 6 ++++-- include/linux/libata.h | 4 ++-- 7 files changed, 21 insertions(+), 22 deletions(-) diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index 908751d27e76..24af56081b5d 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -64,6 +64,7 @@ static void generic_error_handler(struct ata_port *ap) /** * generic_set_mode - mode setting * @ap: interface to set up + * @unused: returned device on error * * Use a non standard set_mode function. We don't want to be tuned. * The BIOS configured everything. Our job is not to fiddle. We @@ -71,7 +72,7 @@ static void generic_error_handler(struct ata_port *ap) * and respect them. */ -static void generic_set_mode(struct ata_port *ap) +static int generic_set_mode(struct ata_port *ap, struct ata_device **unused) { int dma_enabled = 0; int i; @@ -82,7 +83,7 @@ static void generic_set_mode(struct ata_port *ap) for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_enabled(dev)) { + if (ata_dev_ready(dev)) { /* We don't really care */ dev->pio_mode = XFER_PIO_0; dev->dma_mode = XFER_MW_DMA_0; @@ -99,6 +100,7 @@ static void generic_set_mode(struct ata_port *ap) } } } + return 0; } static struct scsi_host_template generic_sht = { diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 0d51d13b16bf..a388a8df0043 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2431,18 +2431,8 @@ int ata_set_mode(struct ata_port *ap, struct ata_device **r_failed_dev) int i, rc = 0, used_dma = 0, found = 0; /* has private set_mode? */ - if (ap->ops->set_mode) { - /* FIXME: make ->set_mode handle no device case and - * return error code and failing device on failure. - */ - for (i = 0; i < ATA_MAX_DEVICES; i++) { - if (ata_dev_ready(&ap->device[i])) { - ap->ops->set_mode(ap); - break; - } - } - return 0; - } + if (ap->ops->set_mode) + return ap->ops->set_mode(ap, r_failed_dev); /* step 1: calculate xfer_mask */ for (i = 0; i < ATA_MAX_DEVICES; i++) { diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 0b56ff3d1cfe..e8afd486434a 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -476,6 +476,7 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc) /** * it821x_smart_set_mode - mode setting * @ap: interface to set up + * @unused: device that failed (error only) * * Use a non standard set_mode function. We don't want to be tuned. * The BIOS configured everything. Our job is not to fiddle. We @@ -483,7 +484,7 @@ static unsigned int it821x_passthru_qc_issue_prot(struct ata_queued_cmd *qc) * and respect them. */ -static void it821x_smart_set_mode(struct ata_port *ap) +static int it821x_smart_set_mode(struct ata_port *ap, struct ata_device **unused) { int dma_enabled = 0; int i; @@ -512,6 +513,7 @@ static void it821x_smart_set_mode(struct ata_port *ap) } } } + return 0; } /** diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index cb8924109f59..23b8aab3ebd8 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -23,9 +23,9 @@ #include #define DRV_NAME "pata_ixp4xx_cf" -#define DRV_VERSION "0.1.1" +#define DRV_VERSION "0.1.1ac1" -static void ixp4xx_set_mode(struct ata_port *ap) +static int ixp4xx_set_mode(struct ata_port *ap, struct ata_device *adev) { int i; @@ -38,6 +38,7 @@ static void ixp4xx_set_mode(struct ata_port *ap) dev->flags |= ATA_DFLAG_PIO; } } + return 0; } static void ixp4xx_phy_reset(struct ata_port *ap) diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index e7bf9d89c8ee..581cb33c6f45 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -96,6 +96,7 @@ static int pio_mask = 0x1F; /* PIO range for autospeed devices */ /** * legacy_set_mode - mode setting * @ap: IDE interface + * @unused: Device that failed when error is returned * * Use a non standard set_mode function. We don't want to be tuned. * @@ -105,7 +106,7 @@ static int pio_mask = 0x1F; /* PIO range for autospeed devices */ * expand on this as per hdparm in the base kernel. */ -static void legacy_set_mode(struct ata_port *ap) +static int legacy_set_mode(struct ata_port *ap, struct ata_device **unused) { int i; @@ -118,6 +119,7 @@ static void legacy_set_mode(struct ata_port *ap) dev->flags |= ATA_DFLAG_PIO; } } + return 0; } static struct scsi_host_template legacy_sht = { diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index adf4cc134f25..cec0729225e1 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -52,19 +52,20 @@ static void rz1000_error_handler(struct ata_port *ap) /** * rz1000_set_mode - mode setting function * @ap: ATA interface + * @unused: returned device on set_mode failure * * Use a non standard set_mode function. We don't want to be tuned. We * would prefer to be BIOS generic but for the fact our hardware is * whacked out. */ -static void rz1000_set_mode(struct ata_port *ap) +static int rz1000_set_mode(struct ata_port *ap, struct ata_device **unused) { int i; for (i = 0; i < ATA_MAX_DEVICES; i++) { struct ata_device *dev = &ap->device[i]; - if (ata_dev_enabled(dev)) { + if (ata_dev_ready(dev)) { /* We don't really care */ dev->pio_mode = XFER_PIO_0; dev->xfer_mode = XFER_PIO_0; @@ -72,6 +73,7 @@ static void rz1000_set_mode(struct ata_port *ap) dev->flags |= ATA_DFLAG_PIO; } } + return 0; } diff --git a/include/linux/libata.h b/include/linux/libata.h index f7f268e38749..df76fc467816 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -612,11 +612,11 @@ struct ata_port_operations { void (*dev_select)(struct ata_port *ap, unsigned int device); void (*phy_reset) (struct ata_port *ap); /* obsolete */ - void (*set_mode) (struct ata_port *ap); + int (*set_mode) (struct ata_port *ap, struct ata_device **r_failed_dev); void (*post_set_mode) (struct ata_port *ap); - int (*check_atapi_dma) (struct ata_queued_cmd *qc); + int (*check_atapi_dma) (struct ata_queued_cmd *qc); void (*bmdma_setup) (struct ata_queued_cmd *qc); void (*bmdma_start) (struct ata_queued_cmd *qc); -- cgit v1.2.3 From 17234246eb82898cf98e3c29e81d941c738e0587 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 25 Jan 2007 20:46:59 +0900 Subject: sata_via: don't diddle with ATA_NIEN in ->freeze vt6420 completely loses its ability to raise IRQ for ATAPI devices if ATA_NIEN is diddled with in ->freeze. Further investigation is necessary to determine whether this problem is shared on other controllers but it doesn't seem to be at this point. Make vt6420's ->freeze only clear IRQ to fix this problem. This makes vt6420 relatively more prone to IRQ storms but the controller is way too braindamaged to worry about that anyway. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 88f0565c8883..55b01236a6f0 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -74,6 +74,7 @@ enum { static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent); static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); +static void svia_noop_freeze(struct ata_port *ap); static void vt6420_error_handler(struct ata_port *ap); static const struct pci_device_id svia_pci_tbl[] = { @@ -128,7 +129,7 @@ static const struct ata_port_operations vt6420_sata_ops = { .qc_issue = ata_qc_issue_prot, .data_xfer = ata_pio_data_xfer, - .freeze = ata_bmdma_freeze, + .freeze = svia_noop_freeze, .thaw = ata_bmdma_thaw, .error_handler = vt6420_error_handler, .post_internal_cmd = ata_bmdma_post_internal_cmd, @@ -204,6 +205,15 @@ static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val) outl(val, ap->ioaddr.scr_addr + (4 * sc_reg)); } +static void svia_noop_freeze(struct ata_port *ap) +{ + /* Some VIA controllers choke if ATA_NIEN is manipulated in + * certain way. Leave it alone and just clear pending IRQ. + */ + ata_chk_status(ap); + ap->ops->irq_clear(ap); +} + /** * vt6420_prereset - prereset for vt6420 * @ap: target ATA port -- cgit v1.2.3 From 0291f95fdb5fcd91cc077aafabea2c5b109fa8a8 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 25 Jan 2007 19:16:28 +0900 Subject: ahci: improve and limit spurious interrupt messages, take#3 We're still seeing a lot of issues with NCQ implementation in drive firmwares. Sprious FISes during NCQ command phase occur on many drives and some of them seem potentially dangerous (at least to me). Until we find the solution, spurious messages can give us more info. Improve and limit them such that more info can be reported while not disturbing users too much. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index e3c7b312287a..2fe5a58195de 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -75,6 +75,7 @@ enum { AHCI_CMD_CLR_BUSY = (1 << 10), RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */ + RX_FIS_SDB = 0x58, /* offset of SDB FIS data */ RX_FIS_UNK = 0x60, /* offset of Unknown FIS data */ board_ahci = 0, @@ -202,6 +203,10 @@ struct ahci_port_priv { dma_addr_t cmd_tbl_dma; void *rx_fis; dma_addr_t rx_fis_dma; + /* for NCQ spurious interrupt analysis */ + int ncq_saw_spurious_sdb_cnt; + unsigned int ncq_saw_d2h:1; + unsigned int ncq_saw_dmas:1; }; static u32 ahci_scr_read (struct ata_port *ap, unsigned int sc_reg); @@ -1109,8 +1114,9 @@ static void ahci_host_intr(struct ata_port *ap) void __iomem *mmio = ap->host->mmio_base; void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); struct ata_eh_info *ehi = &ap->eh_info; + struct ahci_port_priv *pp = ap->private_data; u32 status, qc_active; - int rc; + int rc, known_irq = 0; status = readl(port_mmio + PORT_IRQ_STAT); writel(status, port_mmio + PORT_IRQ_STAT); @@ -1137,17 +1143,52 @@ static void ahci_host_intr(struct ata_port *ap) /* hmmm... a spurious interupt */ - /* some devices send D2H reg with I bit set during NCQ command phase */ - if (ap->sactive && (status & PORT_IRQ_D2H_REG_FIS)) + /* if !NCQ, ignore. No modern ATA device has broken HSM + * implementation for non-NCQ commands. + */ + if (!ap->sactive) return; - /* ignore interim PIO setup fis interrupts */ - if (ata_tag_valid(ap->active_tag) && (status & PORT_IRQ_PIOS_FIS)) - return; + if (status & PORT_IRQ_D2H_REG_FIS) { + if (!pp->ncq_saw_d2h) + ata_port_printk(ap, KERN_INFO, + "D2H reg with I during NCQ, " + "this message won't be printed again\n"); + pp->ncq_saw_d2h = 1; + known_irq = 1; + } + + if (status & PORT_IRQ_DMAS_FIS) { + if (!pp->ncq_saw_dmas) + ata_port_printk(ap, KERN_INFO, + "DMAS FIS during NCQ, " + "this message won't be printed again\n"); + pp->ncq_saw_dmas = 1; + known_irq = 1; + } + + if (status & PORT_IRQ_SDB_FIS && + pp->ncq_saw_spurious_sdb_cnt < 10) { + /* SDB FIS containing spurious completions might be + * dangerous, we need to know more about them. Print + * more of it. + */ + const u32 *f = pp->rx_fis + RX_FIS_SDB; + + ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ " + "issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n", + readl(port_mmio + PORT_CMD_ISSUE), + readl(port_mmio + PORT_SCR_ACT), f[0], f[1], + pp->ncq_saw_spurious_sdb_cnt < 10 ? + "" : ", shutting up"); + + pp->ncq_saw_spurious_sdb_cnt++; + known_irq = 1; + } - if (ata_ratelimit()) + if (!known_irq) ata_port_printk(ap, KERN_INFO, "spurious interrupt " - "(irq_stat 0x%x active_tag %d sactive 0x%x)\n", + "(irq_stat 0x%x active_tag 0x%x sactive 0x%x)\n", status, ap->active_tag, ap->sactive); } -- cgit v1.2.3 From b2a8bbe67d73631c71492fd60b757fc50a87f182 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 25 Jan 2007 19:40:05 +0900 Subject: libata: implement ATA_FLAG_IGN_SIMPLEX and use it in sata_uli Some uli controllers have stuck SIMPLEX bit which can't be cleared with ata_pci_clear_simplex(), but the controller is capable of doing DMAs on both channels simultaneously. Implement ATA_FLAG_IGN_SIMPLEX which makes libata ignore the simplex bit and use it in sata_uli. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 12 ++++++++---- drivers/ata/sata_uli.c | 3 ++- include/linux/libata.h | 1 + 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 623cec914c9b..114fa81deb83 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -870,7 +870,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS; bmdma = pci_resource_start(pdev, 4); if (bmdma) { - if (inb(bmdma + 2) & 0x80) + if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) && + (inb(bmdma + 2) & 0x80)) probe_ent->_host_flags |= ATA_HOST_SIMPLEX; probe_ent->port[p].bmdma_addr = bmdma; } @@ -886,7 +887,8 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int bmdma = pci_resource_start(pdev, 4); if (bmdma) { bmdma += 8; - if(inb(bmdma + 2) & 0x80) + if ((!(port[p]->flags & ATA_FLAG_IGN_SIMPLEX)) && + (inb(bmdma + 2) & 0x80)) probe_ent->_host_flags |= ATA_HOST_SIMPLEX; probe_ent->port[p].bmdma_addr = bmdma; } @@ -920,7 +922,8 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL; if (bmdma) { probe_ent->port[0].bmdma_addr = bmdma; - if (inb(bmdma + 2) & 0x80) + if ((!(port[0]->flags & ATA_FLAG_IGN_SIMPLEX)) && + (inb(bmdma + 2) & 0x80)) probe_ent->_host_flags |= ATA_HOST_SIMPLEX; } ata_std_ports(&probe_ent->port[0]); @@ -937,7 +940,8 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL; if (bmdma) { probe_ent->port[1].bmdma_addr = bmdma + 8; - if (inb(bmdma + 10) & 0x80) + if ((!(port[1]->flags & ATA_FLAG_IGN_SIMPLEX)) && + (inb(bmdma + 10) & 0x80)) probe_ent->_host_flags |= ATA_HOST_SIMPLEX; } ata_std_ports(&probe_ent->port[1]); diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index 5c603ca3a50a..a43aec62d505 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -128,7 +128,8 @@ static const struct ata_port_operations uli_ops = { static struct ata_port_info uli_port_info = { .sht = &uli_sht, - .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, + .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | + ATA_FLAG_IGN_SIMPLEX, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = 0x7f, /* udma0-6 */ .port_ops = &uli_ops, diff --git a/include/linux/libata.h b/include/linux/libata.h index df76fc467816..22aa69e20905 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -177,6 +177,7 @@ enum { * Register FIS clearing BSY */ ATA_FLAG_DEBUGMSG = (1 << 13), ATA_FLAG_SETXFER_POLLING= (1 << 14), /* use polling for SETXFER */ + ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ /* The following flag belongs to ap->pflags but is kept in * ap->flags because it's referenced in many LLDs and will be -- cgit v1.2.3 From 61dd08c6c8d2b4ede530e43c01fa72f789ef65b1 Mon Sep 17 00:00:00 2001 From: Alan Date: Thu, 25 Jan 2007 15:09:05 +0000 Subject: libata-sff: Don't call bmdma_stop on non DMA capable controllers Fixes bogus accesses to ports 0-15 with a non DMA capable controller. This I think should go in for 2.6.20 Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 114fa81deb83..942aeba2940a 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -827,7 +827,8 @@ void ata_bmdma_error_handler(struct ata_port *ap) */ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) { - ata_bmdma_stop(qc); + if (qc->ap->ioaddr.bmdma_addr) + ata_bmdma_stop(qc); } #ifdef CONFIG_PCI -- cgit v1.2.3 From 6096b63e2584796341baf7e7735f98d387f489f2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 26 Jan 2007 14:47:38 +0900 Subject: ahci: fix endianness in spurious interrupt message Fix endianness in spurious interrupt message. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 2fe5a58195de..d8f0ce970d54 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1178,7 +1178,8 @@ static void ahci_host_intr(struct ata_port *ap) ata_port_printk(ap, KERN_INFO, "Spurious SDB FIS during NCQ " "issue=0x%x SAct=0x%x FIS=%08x:%08x%s\n", readl(port_mmio + PORT_CMD_ISSUE), - readl(port_mmio + PORT_SCR_ACT), f[0], f[1], + readl(port_mmio + PORT_SCR_ACT), + le32_to_cpu(f[0]), le32_to_cpu(f[1]), pp->ncq_saw_spurious_sdb_cnt < 10 ? "" : ", shutting up"); -- cgit v1.2.3 From d02598721706ab62a574823479b1f6c26c8980d2 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 26 Jan 2007 14:57:31 +0900 Subject: sata_via: style clean up, no indirect method call in LLD Call ata_bmdma_irq_clear() directly instead of through ap->ops->irq_clear() according to libata style guideline. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_via.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 55b01236a6f0..d3d5c0d57032 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -211,7 +211,7 @@ static void svia_noop_freeze(struct ata_port *ap) * certain way. Leave it alone and just clear pending IRQ. */ ata_chk_status(ap); - ap->ops->irq_clear(ap); + ata_bmdma_irq_clear(ap); } /** -- cgit v1.2.3 From dfd7a3db3898e299bdc25f0c77081a8632b3a73c Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 26 Jan 2007 15:37:20 +0900 Subject: ahci: use 0x80 as wait stat value instead of 0xff Before hardreset, ahci initialized stat part of received FIS area to 0xff to wait for the first D2H Reg FIS which would change the value to device ready state. This used to work but now libata considers status value of 0xff as device not present making this wait prone to failure. This patch makes ahci use 0x80 for the wait stat value instead of 0xff to fix the above problem. Signed-off-by: Tejun Heo drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index d8f0ce970d54..28a82e3403f1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -903,7 +903,7 @@ static int ahci_hardreset(struct ata_port *ap, unsigned int *class) /* clear D2H reception area to properly wait for D2H FIS */ ata_tf_init(ap->device, &tf); - tf.command = 0xff; + tf.command = 0x80; ata_tf_to_fis(&tf, d2h_fis, 0); rc = sata_std_hardreset(ap, class); -- cgit v1.2.3 From 8cdf92a98fa0f91068615443f2a8597b7f2c34ca Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Mon, 1 Jan 2007 19:31:15 +0000 Subject: Fix Maple PATA IRQ assignment. On the Maple board, the AMD8111 IDE is in legacy mode... except that it appears on IRQ 20 instead of IRQ 15. For drivers/ide this was handled by the architecture's "pci_get_legacy_ide_irq()" function, but in libata we just hard-code the numbers 14 and 15. This patch provides asm-powerpc/libata-portmap.h which maps the IRQ as appropriate, having added a pci_dev argument to the ATA_{PRIM,SECOND}ARY_IRQ macros. There's probably a better way to do this -- especially if we observe that the _only_ case in which this seemingly-generic "pci_get_legacy_ide_irq()" function returns anything other than 14 and 15 for primary and secondary respectively is the case of the AMD8111 on the Maple board -- couldn't we handle that with a special case in the pata_amd driver, or perhaps with a PCI quirk for Maple to switch it into native mode during early boot and assign resources properly? Signed-off-by: David Woodhouse Signed-off-by: Jeff Garzik --- arch/powerpc/Kconfig | 1 + drivers/ata/Kconfig | 4 ++++ drivers/ata/libata-sff.c | 6 +++--- include/asm-generic/libata-portmap.h | 4 ++-- include/asm-powerpc/libata-portmap.h | 12 ++++++++++++ 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 include/asm-powerpc/libata-portmap.h diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 0855d55c194d..b268c417c0bf 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -484,6 +484,7 @@ config PPC_MAPLE select PPC_970_NAP select PPC_NATIVE select PPC_RTAS + select ATA_NONSTANDARD if ATA default n help This option enables support for the Maple 970FX Evaluation Board. diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index da21552d2b1c..1c94b43d2c9b 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -19,6 +19,10 @@ config ATA if ATA +config ATA_NONSTANDARD + bool + default n + config SATA_AHCI tristate "AHCI SATA support" depends on PCI diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 942aeba2940a..12c88c588039 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -917,7 +917,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, probe_ent->irq_flags = IRQF_SHARED; if (port_mask & ATA_PORT_PRIMARY) { - probe_ent->irq = ATA_PRIMARY_IRQ; + probe_ent->irq = ATA_PRIMARY_IRQ(pdev); probe_ent->port[0].cmd_addr = ATA_PRIMARY_CMD; probe_ent->port[0].altstatus_addr = probe_ent->port[0].ctl_addr = ATA_PRIMARY_CTL; @@ -933,9 +933,9 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, if (port_mask & ATA_PORT_SECONDARY) { if (probe_ent->irq) - probe_ent->irq2 = ATA_SECONDARY_IRQ; + probe_ent->irq2 = ATA_SECONDARY_IRQ(pdev); else - probe_ent->irq = ATA_SECONDARY_IRQ; + probe_ent->irq = ATA_SECONDARY_IRQ(pdev); probe_ent->port[1].cmd_addr = ATA_SECONDARY_CMD; probe_ent->port[1].altstatus_addr = probe_ent->port[1].ctl_addr = ATA_SECONDARY_CTL; diff --git a/include/asm-generic/libata-portmap.h b/include/asm-generic/libata-portmap.h index 9202fd02d5be..62fb3618293d 100644 --- a/include/asm-generic/libata-portmap.h +++ b/include/asm-generic/libata-portmap.h @@ -3,10 +3,10 @@ #define ATA_PRIMARY_CMD 0x1F0 #define ATA_PRIMARY_CTL 0x3F6 -#define ATA_PRIMARY_IRQ 14 +#define ATA_PRIMARY_IRQ(dev) 14 #define ATA_SECONDARY_CMD 0x170 #define ATA_SECONDARY_CTL 0x376 -#define ATA_SECONDARY_IRQ 15 +#define ATA_SECONDARY_IRQ(dev) 15 #endif diff --git a/include/asm-powerpc/libata-portmap.h b/include/asm-powerpc/libata-portmap.h new file mode 100644 index 000000000000..4d8518049f4d --- /dev/null +++ b/include/asm-powerpc/libata-portmap.h @@ -0,0 +1,12 @@ +#ifndef __ASM_POWERPC_LIBATA_PORTMAP_H +#define __ASM_POWERPC_LIBATA_PORTMAP_H + +#define ATA_PRIMARY_CMD 0x1F0 +#define ATA_PRIMARY_CTL 0x3F6 +#define ATA_PRIMARY_IRQ(dev) pci_get_legacy_ide_irq(dev, 0) + +#define ATA_SECONDARY_CMD 0x170 +#define ATA_SECONDARY_CTL 0x376 +#define ATA_SECONDARY_IRQ(dev) pci_get_legacy_ide_irq(dev, 1) + +#endif -- cgit v1.2.3