summaryrefslogtreecommitdiff
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.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8bc71ca61e7f..c41b9eeabe7c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -759,7 +759,7 @@ int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev,
tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
tf->flags |= tf_flags;
- if (ata_ncq_enabled(dev) && likely(tag != ATA_TAG_INTERNAL)) {
+ if (ata_ncq_enabled(dev) && !ata_tag_internal(tag)) {
/* yay, NCQ */
if (!lba_48_ok(block, n_block))
return -ERANGE;
@@ -1570,8 +1570,9 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
u8 command = tf->command;
int auto_timeout = 0;
struct ata_queued_cmd *qc;
- unsigned int tag, preempted_tag;
- u32 preempted_sactive, preempted_qc_active;
+ unsigned int preempted_tag;
+ u32 preempted_sactive;
+ u64 preempted_qc_active;
int preempted_nr_active_links;
DECLARE_COMPLETION_ONSTACK(wait);
unsigned long flags;
@@ -1587,20 +1588,10 @@ unsigned ata_exec_internal_sg(struct ata_device *dev,
}
/* initialize internal qc */
+ qc = __ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
- /* XXX: Tag 0 is used for drivers with legacy EH as some
- * drivers choke if any other tag is given. This breaks
- * ata_tag_internal() test for those drivers. Don't use new
- * EH stuff without converting to it.
- */
- if (ap->ops->error_handler)
- tag = ATA_TAG_INTERNAL;
- else
- tag = 0;
-
- qc = __ata_qc_from_tag(ap, tag);
-
- qc->tag = tag;
+ qc->tag = ATA_TAG_INTERNAL;
+ qc->hw_tag = 0;
qc->scsicmd = NULL;
qc->ap = ap;
qc->dev = dev;
@@ -2295,7 +2286,7 @@ static int ata_dev_config_ncq(struct ata_device *dev,
return 0;
}
if (ap->flags & ATA_FLAG_NCQ) {
- hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE - 1);
+ hdepth = min(ap->scsi_host->can_queue, ATA_MAX_QUEUE);
dev->flags |= ATA_DFLAG_NCQ;
}
@@ -3573,9 +3564,11 @@ static int ata_dev_set_mode(struct ata_device *dev)
DPRINTK("xfer_shift=%u, xfer_mode=0x%x\n",
dev->xfer_shift, (int)dev->xfer_mode);
- ata_dev_info(dev, "configured for %s%s\n",
- ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)),
- dev_err_whine);
+ if (!(ehc->i.flags & ATA_EHI_QUIET) ||
+ ehc->i.flags & ATA_EHI_DID_HARDRESET)
+ ata_dev_info(dev, "configured for %s%s\n",
+ ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)),
+ dev_err_whine);
return 0;
@@ -4493,6 +4486,10 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
/* https://bugzilla.kernel.org/show_bug.cgi?id=15573 */
{ "C300-CTFDDAC128MAG", "0001", ATA_HORKAGE_NONCQ, },
+ /* Some Sandisk SSDs lock up hard with NCQ enabled. Reported on
+ SD7SN6S256G and SD8SN8U256G */
+ { "SanDisk SD[78]SN*G", NULL, ATA_HORKAGE_NONCQ, },
+
/* devices which puke on READ_NATIVE_MAX */
{ "HDS724040KLSA80", "KFAOA20N", ATA_HORKAGE_BROKEN_HPA, },
{ "WDC WD3200JD-00KLB0", "WD-WCAMR1130137", ATA_HORKAGE_BROKEN_HPA },
@@ -4549,7 +4546,13 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
ATA_HORKAGE_ZERO_AFTER_TRIM |
ATA_HORKAGE_NOLPM, },
+ /* These specific Samsung models/firmware-revs do not handle LPM well */
+ { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
+ { "SAMSUNG SSD PM830 mSATA *", "CXM13D1Q", ATA_HORKAGE_NOLPM, },
+
/* devices that don't properly handle queued TRIM commands */
+ { "Micron_M500IT_*", "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
+ ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Micron_M500_*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Crucial_CT*M500*", NULL, ATA_HORKAGE_NO_NCQ_TRIM |
@@ -5123,7 +5126,7 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag)
}
qc = __ata_qc_from_tag(ap, tag);
- qc->tag = tag;
+ qc->tag = qc->hw_tag = tag;
qc->scsicmd = NULL;
qc->ap = ap;
qc->dev = dev;
@@ -5153,7 +5156,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
qc->flags = 0;
tag = qc->tag;
- if (likely(ata_tag_valid(tag))) {
+ if (ata_tag_valid(tag)) {
qc->tag = ATA_TAG_POISON;
if (ap->flags & ATA_FLAG_SAS_HOST)
ata_sas_free_tag(tag, ap);
@@ -5175,7 +5178,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
/* command should be marked inactive atomically with qc completion */
if (ata_is_ncq(qc->tf.protocol)) {
- link->sactive &= ~(1 << qc->tag);
+ link->sactive &= ~(1 << qc->hw_tag);
if (!link->sactive)
ap->nr_active_links--;
} else {
@@ -5193,7 +5196,7 @@ void __ata_qc_complete(struct ata_queued_cmd *qc)
* is called. (when rc != 0 and atapi request sense is needed)
*/
qc->flags &= ~ATA_QCFLAG_ACTIVE;
- ap->qc_active &= ~(1 << qc->tag);
+ ap->qc_active &= ~(1ULL << qc->tag);
/* call completion callback */
qc->complete_fn(qc);
@@ -5350,29 +5353,29 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
* RETURNS:
* Number of completed commands on success, -errno otherwise.
*/
-int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active)
+int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active)
{
int nr_done = 0;
- u32 done_mask;
+ u64 done_mask;
done_mask = ap->qc_active ^ qc_active;
if (unlikely(done_mask & qc_active)) {
- ata_port_err(ap, "illegal qc_active transition (%08x->%08x)\n",
+ ata_port_err(ap, "illegal qc_active transition (%08llx->%08llx)\n",
ap->qc_active, qc_active);
return -EINVAL;
}
while (done_mask) {
struct ata_queued_cmd *qc;
- unsigned int tag = __ffs(done_mask);
+ unsigned int tag = __ffs64(done_mask);
qc = ata_qc_from_tag(ap, tag);
if (qc) {
ata_qc_complete(qc);
nr_done++;
}
- done_mask &= ~(1 << tag);
+ done_mask &= ~(1ULL << tag);
}
return nr_done;
@@ -5403,11 +5406,11 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
WARN_ON_ONCE(ap->ops->error_handler && ata_tag_valid(link->active_tag));
if (ata_is_ncq(prot)) {
- WARN_ON_ONCE(link->sactive & (1 << qc->tag));
+ WARN_ON_ONCE(link->sactive & (1 << qc->hw_tag));
if (!link->sactive)
ap->nr_active_links++;
- link->sactive |= 1 << qc->tag;
+ link->sactive |= 1 << qc->hw_tag;
} else {
WARN_ON_ONCE(link->sactive);
@@ -5416,7 +5419,7 @@ void ata_qc_issue(struct ata_queued_cmd *qc)
}
qc->flags |= ATA_QCFLAG_ACTIVE;
- ap->qc_active |= 1 << qc->tag;
+ ap->qc_active |= 1ULL << qc->tag;
/*
* We guarantee to LLDs that they will have at least one
@@ -6415,7 +6418,7 @@ void ata_host_init(struct ata_host *host, struct device *dev,
{
spin_lock_init(&host->lock);
mutex_init(&host->eh_mutex);
- host->n_tags = ATA_MAX_QUEUE - 1;
+ host->n_tags = ATA_MAX_QUEUE;
host->dev = dev;
host->ops = ops;
}
@@ -6497,7 +6500,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
{
int i, rc;
- host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE - 1);
+ host->n_tags = clamp(sht->can_queue, 1, ATA_MAX_QUEUE);
/* host must have been started */
if (!(host->flags & ATA_HOST_STARTED)) {