aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShaohua Li <shaohua.li@intel.com>2009-07-26 21:24:35 -0400
committerJeff Garzik <jgarzik@redhat.com>2009-09-01 19:47:19 -0400
commit388539f3ff0cf1de926b03f94e1eec112358f74d (patch)
tree6840b76ede7e27e27eb9aaf516f827beba16c5ad
parent2fc37adba0fb05760b8635c6706773af828ccf3c (diff)
[libata] add DMA setup FIS auto-activate feature
Hopefully results in fewer on-the-wire FIS's and no breakage. We'll see! Signed-off-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/ahci.c2
-rw-r--r--drivers/ata/libata-core.c36
-rw-r--r--include/linux/ata.h4
-rw-r--r--include/linux/libata.h2
4 files changed, 36 insertions, 8 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index fe3eba5d6b3e..7a3124a9abc6 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -2869,7 +2869,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
2869 2869
2870 /* prepare host */ 2870 /* prepare host */
2871 if (hpriv->cap & HOST_CAP_NCQ) 2871 if (hpriv->cap & HOST_CAP_NCQ)
2872 pi.flags |= ATA_FLAG_NCQ; 2872 pi.flags |= ATA_FLAG_NCQ | ATA_FLAG_FPDMA_AA;
2873 2873
2874 if (hpriv->cap & HOST_CAP_PMP) 2874 if (hpriv->cap & HOST_CAP_PMP)
2875 pi.flags |= ATA_FLAG_PMP; 2875 pi.flags |= ATA_FLAG_PMP;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 072ba5ea138f..98af50f16e0c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2299,29 +2299,49 @@ static inline u8 ata_dev_knobble(struct ata_device *dev)
2299 return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id))); 2299 return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(dev->id)));
2300} 2300}
2301 2301
2302static void ata_dev_config_ncq(struct ata_device *dev, 2302static int ata_dev_config_ncq(struct ata_device *dev,
2303 char *desc, size_t desc_sz) 2303 char *desc, size_t desc_sz)
2304{ 2304{
2305 struct ata_port *ap = dev->link->ap; 2305 struct ata_port *ap = dev->link->ap;
2306 int hdepth = 0, ddepth = ata_id_queue_depth(dev->id); 2306 int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
2307 unsigned int err_mask;
2308 char *aa_desc = "";
2307 2309
2308 if (!ata_id_has_ncq(dev->id)) { 2310 if (!ata_id_has_ncq(dev->id)) {
2309 desc[0] = '\0'; 2311 desc[0] = '\0';
2310 return; 2312 return 0;
2311 } 2313 }
2312 if (dev->horkage & ATA_HORKAGE_NONCQ) { 2314 if (dev->horkage & ATA_HORKAGE_NONCQ) {
2313 snprintf(desc, desc_sz, "NCQ (not used)"); 2315 snprintf(desc, desc_sz, "NCQ (not used)");
2314 return; 2316 return 0;
2315 } 2317 }
2316 if (ap->flags & ATA_FLAG_NCQ) { 2318 if (ap->flags & ATA_FLAG_NCQ) {
2317 hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1); 2319 hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
2318 dev->flags |= ATA_DFLAG_NCQ; 2320 dev->flags |= ATA_DFLAG_NCQ;
2319 } 2321 }
2320 2322
2323 if (!(dev->horkage & ATA_HORKAGE_BROKEN_FPDMA_AA) &&
2324 (ap->flags & ATA_FLAG_FPDMA_AA) &&
2325 ata_id_has_fpdma_aa(dev->id)) {
2326 err_mask = ata_dev_set_feature(dev, SETFEATURES_SATA_ENABLE,
2327 SATA_FPDMA_AA);
2328 if (err_mask) {
2329 ata_dev_printk(dev, KERN_ERR, "failed to enable AA"
2330 "(error_mask=0x%x)\n", err_mask);
2331 if (err_mask != AC_ERR_DEV) {
2332 dev->horkage |= ATA_HORKAGE_BROKEN_FPDMA_AA;
2333 return -EIO;
2334 }
2335 } else
2336 aa_desc = ", AA";
2337 }
2338
2321 if (hdepth >= ddepth) 2339 if (hdepth >= ddepth)
2322 snprintf(desc, desc_sz, "NCQ (depth %d)", ddepth); 2340 snprintf(desc, desc_sz, "NCQ (depth %d)%s", ddepth, aa_desc);
2323 else 2341 else
2324 snprintf(desc, desc_sz, "NCQ (depth %d/%d)", hdepth, ddepth); 2342 snprintf(desc, desc_sz, "NCQ (depth %d/%d)%s", hdepth,
2343 ddepth, aa_desc);
2344 return 0;
2325} 2345}
2326 2346
2327/** 2347/**
@@ -2461,7 +2481,7 @@ int ata_dev_configure(struct ata_device *dev)
2461 2481
2462 if (ata_id_has_lba(id)) { 2482 if (ata_id_has_lba(id)) {
2463 const char *lba_desc; 2483 const char *lba_desc;
2464 char ncq_desc[20]; 2484 char ncq_desc[24];
2465 2485
2466 lba_desc = "LBA"; 2486 lba_desc = "LBA";
2467 dev->flags |= ATA_DFLAG_LBA; 2487 dev->flags |= ATA_DFLAG_LBA;
@@ -2475,7 +2495,9 @@ int ata_dev_configure(struct ata_device *dev)
2475 } 2495 }
2476 2496
2477 /* config NCQ */ 2497 /* config NCQ */
2478 ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc)); 2498 rc = ata_dev_config_ncq(dev, ncq_desc, sizeof(ncq_desc));
2499 if (rc)
2500 return rc;
2479 2501
2480 /* print device info to dmesg */ 2502 /* print device info to dmesg */
2481 if (ata_msg_drv(ap) && print_info) { 2503 if (ata_msg_drv(ap) && print_info) {
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 9c75921f0c16..f5494050df83 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -306,6 +306,7 @@ enum {
306 /* SETFEATURE Sector counts for SATA features */ 306 /* SETFEATURE Sector counts for SATA features */
307 SATA_AN = 0x05, /* Asynchronous Notification */ 307 SATA_AN = 0x05, /* Asynchronous Notification */
308 SATA_DIPM = 0x03, /* Device Initiated Power Management */ 308 SATA_DIPM = 0x03, /* Device Initiated Power Management */
309 SATA_FPDMA_AA = 0x02, /* DMA Setup FIS Auto-Activate */
309 310
310 /* feature values for SET_MAX */ 311 /* feature values for SET_MAX */
311 ATA_SET_MAX_ADDR = 0x00, 312 ATA_SET_MAX_ADDR = 0x00,
@@ -525,6 +526,9 @@ static inline int ata_is_data(u8 prot)
525#define ata_id_has_atapi_AN(id) \ 526#define ata_id_has_atapi_AN(id) \
526 ( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \ 527 ( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
527 ((id)[78] & (1 << 5)) ) 528 ((id)[78] & (1 << 5)) )
529#define ata_id_has_fpdma_aa(id) \
530 ( (((id)[76] != 0x0000) && ((id)[76] != 0xffff)) && \
531 ((id)[78] & (1 << 2)) )
528#define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10)) 532#define ata_id_iordy_disable(id) ((id)[ATA_ID_CAPABILITY] & (1 << 10))
529#define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11)) 533#define ata_id_has_iordy(id) ((id)[ATA_ID_CAPABILITY] & (1 << 11))
530#define ata_id_u32(id,n) \ 534#define ata_id_u32(id,n) \
diff --git a/include/linux/libata.h b/include/linux/libata.h
index e5b6e33c6571..d3f7cab4873e 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -190,6 +190,7 @@ enum {
190 ATA_FLAG_NO_POWEROFF_SPINDOWN = (1 << 11), /* don't spindown before poweroff */ 190 ATA_FLAG_NO_POWEROFF_SPINDOWN = (1 << 11), /* don't spindown before poweroff */
191 ATA_FLAG_NO_HIBERNATE_SPINDOWN = (1 << 12), /* don't spindown before hibernation */ 191 ATA_FLAG_NO_HIBERNATE_SPINDOWN = (1 << 12), /* don't spindown before hibernation */
192 ATA_FLAG_DEBUGMSG = (1 << 13), 192 ATA_FLAG_DEBUGMSG = (1 << 13),
193 ATA_FLAG_FPDMA_AA = (1 << 14), /* driver supports Auto-Activate */
193 ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */ 194 ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
194 ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */ 195 ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
195 ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */ 196 ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
@@ -386,6 +387,7 @@ enum {
386 ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firmware update warning */ 387 ATA_HORKAGE_FIRMWARE_WARN = (1 << 12), /* firmware update warning */
387 ATA_HORKAGE_1_5_GBPS = (1 << 13), /* force 1.5 Gbps */ 388 ATA_HORKAGE_1_5_GBPS = (1 << 13), /* force 1.5 Gbps */
388 ATA_HORKAGE_NOSETXFER = (1 << 14), /* skip SETXFER, SATA only */ 389 ATA_HORKAGE_NOSETXFER = (1 << 14), /* skip SETXFER, SATA only */
390 ATA_HORKAGE_BROKEN_FPDMA_AA = (1 << 15), /* skip AA */
389 391
390 /* DMA mask for user DMA control: User visible values; DO NOT 392 /* DMA mask for user DMA control: User visible values; DO NOT
391 renumber */ 393 renumber */