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 /drivers/ata | |
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>
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/ahci.c | 2 | ||||
-rw-r--r-- | drivers/ata/libata-core.c | 36 |
2 files changed, 30 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) { |