aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c105
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);