diff options
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 105 |
1 files changed, 92 insertions, 13 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 981b397cb46b..5b25311ba885 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1845,7 +1845,8 @@ static void ata_dev_config_ncq(struct ata_device *dev, int ata_dev_configure(struct ata_device *dev) { struct ata_port *ap = dev->ap; - int print_info = ap->eh_context.i.flags & ATA_EHI_PRINTINFO; + struct ata_eh_context *ehc = &ap->eh_context; + int print_info = ehc->i.flags & ATA_EHI_PRINTINFO; const u16 *id = dev->id; unsigned int xfer_mask; char revbuf[7]; /* XYZ-99\0 */ @@ -1862,15 +1863,10 @@ int ata_dev_configure(struct ata_device *dev) if (ata_msg_probe(ap)) ata_dev_printk(dev, KERN_DEBUG, "%s: ENTER\n", __FUNCTION__); - /* set _SDD */ - rc = ata_acpi_push_id(dev); - if (rc) { - ata_dev_printk(dev, KERN_WARNING, "failed to set _SDD(%d)\n", - rc); - } - - /* retrieve and execute the ATA task file of _GTF */ - ata_acpi_exec_tfs(ap); + /* let ACPI work its magic */ + rc = ata_acpi_on_devcfg(dev); + if (rc) + return rc; /* print device capabilities */ if (ata_msg_probe(ap)) @@ -3359,7 +3355,7 @@ int ata_std_prereset(struct ata_port *ap, unsigned long deadline) return 0; /* if SATA, resume phy */ - if (ap->cbl == ATA_CBL_SATA) { + if (ap->flags & ATA_FLAG_SATA) { rc = sata_phy_resume(ap, timing, deadline); /* whine about phy resume failure but proceed */ if (rc && rc != -EOPNOTSUPP) @@ -4107,6 +4103,68 @@ static void ata_fill_sg(struct ata_queued_cmd *qc) } /** + * ata_fill_sg_dumb - Fill PCI IDE PRD table + * @qc: Metadata associated with taskfile to be transferred + * + * Fill PCI IDE PRD (scatter-gather) table with segments + * associated with the current disk command. Perform the fill + * so that we avoid writing any length 64K records for + * controllers that don't follow the spec. + * + * LOCKING: + * spin_lock_irqsave(host lock) + * + */ +static void ata_fill_sg_dumb(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct scatterlist *sg; + unsigned int idx; + + WARN_ON(qc->__sg == NULL); + WARN_ON(qc->n_elem == 0 && qc->pad_len == 0); + + idx = 0; + ata_for_each_sg(sg, qc) { + u32 addr, offset; + u32 sg_len, len, blen; + + /* determine if physical DMA addr spans 64K boundary. + * Note h/w doesn't support 64-bit, so we unconditionally + * truncate dma_addr_t to u32. + */ + addr = (u32) sg_dma_address(sg); + sg_len = sg_dma_len(sg); + + while (sg_len) { + offset = addr & 0xffff; + len = sg_len; + if ((offset + sg_len) > 0x10000) + len = 0x10000 - offset; + + blen = len & 0xffff; + ap->prd[idx].addr = cpu_to_le32(addr); + if (blen == 0) { + /* Some PATA chipsets like the CS5530 can't + cope with 0x0000 meaning 64K as the spec says */ + ap->prd[idx].flags_len = cpu_to_le32(0x8000); + blen = 0x8000; + ap->prd[++idx].addr = cpu_to_le32(addr + 0x8000); + } + ap->prd[idx].flags_len = cpu_to_le32(blen); + VPRINTK("PRD[%u] = (0x%X, 0x%X)\n", idx, addr, len); + + idx++; + sg_len -= len; + addr += len; + } + } + + if (idx) + ap->prd[idx - 1].flags_len |= cpu_to_le32(ATA_PRD_EOT); +} + +/** * ata_check_atapi_dma - Check whether ATAPI DMA can be supported * @qc: Metadata associated with taskfile to check * @@ -4153,6 +4211,23 @@ void ata_qc_prep(struct ata_queued_cmd *qc) ata_fill_sg(qc); } +/** + * ata_dumb_qc_prep - Prepare taskfile for submission + * @qc: Metadata associated with taskfile to be prepared + * + * Prepare ATA taskfile for submission. + * + * LOCKING: + * spin_lock_irqsave(host lock) + */ +void ata_dumb_qc_prep(struct ata_queued_cmd *qc) +{ + if (!(qc->flags & ATA_QCFLAG_DMAMAP)) + return; + + ata_fill_sg_dumb(qc); +} + void ata_noop_qc_prep(struct ata_queued_cmd *qc) { } /** @@ -5660,7 +5735,7 @@ irqreturn_t ata_interrupt (int irq, void *dev_instance) */ int sata_scr_valid(struct ata_port *ap) { - return ap->cbl == ATA_CBL_SATA && ap->ops->scr_read; + return (ap->flags & ATA_FLAG_SATA) && ap->ops->scr_read; } /** @@ -6293,6 +6368,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) if (rc) return rc; + /* associate with ACPI nodes */ + ata_acpi_associate(host); + /* set cable, sata_spd_limit and report */ for (i = 0; i < host->n_ports; i++) { struct ata_port *ap = host->ports[i]; @@ -6324,7 +6402,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) if (!ata_port_is_dummy(ap)) ata_port_printk(ap, KERN_INFO, "%cATA max %s cmd 0x%p " "ctl 0x%p bmdma 0x%p irq %d\n", - ap->cbl == ATA_CBL_SATA ? 'S' : 'P', + (ap->flags & ATA_FLAG_SATA) ? 'S' : 'P', ata_mode_string(xfer_mask), ap->ioaddr.cmd_addr, ap->ioaddr.ctl_addr, @@ -6822,6 +6900,7 @@ EXPORT_SYMBOL_GPL(ata_do_set_mode); EXPORT_SYMBOL_GPL(ata_data_xfer); EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); EXPORT_SYMBOL_GPL(ata_qc_prep); +EXPORT_SYMBOL_GPL(ata_dumb_qc_prep); EXPORT_SYMBOL_GPL(ata_noop_qc_prep); EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_start); |