diff options
author | Shaohua Li <shaohua.li@intel.com> | 2009-07-26 21:24:35 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2009-09-01 19:47:19 -0400 |
commit | 388539f3ff0cf1de926b03f94e1eec112358f74d (patch) | |
tree | 6840b76ede7e27e27eb9aaf516f827beba16c5ad | |
parent | 2fc37adba0fb05760b8635c6706773af828ccf3c (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.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 36 | ||||
-rw-r--r-- | include/linux/ata.h | 4 | ||||
-rw-r--r-- | include/linux/libata.h | 2 |
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 | ||
2302 | static void ata_dev_config_ncq(struct ata_device *dev, | 2302 | static 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 */ |