diff options
author | Xiangliang Yu <yuxiangl@marvell.com> | 2011-05-08 07:27:01 -0400 |
---|---|---|
committer | James Bottomley <jbottomley@parallels.com> | 2011-05-24 12:34:01 -0400 |
commit | bb650a1bef73a8c1fd076fae4c4f0701cf3b5f25 (patch) | |
tree | 30434a1ae64125d0d8d2ff0764353d29d022105e /drivers/scsi/libsas | |
parent | 5fd5cc83a886d691ab8cd6d4404ca35e09ce88e3 (diff) |
[SCSI] libsas: fix SATA NCQ error
Current version of libsas can not handle SATA NCQ error.
This patch handle SATA NCQ error as AHCI do.
Signed-off-by: Xiangliang Yu <yuxiangl@marvell.com>
Signed-off-by: James Bottomley <jbottomley@parallels.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 31fc21f4d831..e99301421409 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -99,19 +99,29 @@ static void sas_ata_task_done(struct sas_task *task) | |||
99 | struct sas_ha_struct *sas_ha; | 99 | struct sas_ha_struct *sas_ha; |
100 | enum ata_completion_errors ac; | 100 | enum ata_completion_errors ac; |
101 | unsigned long flags; | 101 | unsigned long flags; |
102 | struct ata_link *link; | ||
102 | 103 | ||
103 | if (!qc) | 104 | if (!qc) |
104 | goto qc_already_gone; | 105 | goto qc_already_gone; |
105 | 106 | ||
106 | dev = qc->ap->private_data; | 107 | dev = qc->ap->private_data; |
107 | sas_ha = dev->port->ha; | 108 | sas_ha = dev->port->ha; |
109 | link = &dev->sata_dev.ap->link; | ||
108 | 110 | ||
109 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | 111 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); |
110 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || | 112 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || |
111 | ((stat->stat == SAM_STAT_CHECK_CONDITION && | 113 | ((stat->stat == SAM_STAT_CHECK_CONDITION && |
112 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { | 114 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { |
113 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); | 115 | ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); |
114 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | 116 | |
117 | if (!link->sactive) { | ||
118 | qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
119 | } else { | ||
120 | link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command); | ||
121 | if (unlikely(link->eh_info.err_mask)) | ||
122 | qc->flags |= ATA_QCFLAG_FAILED; | ||
123 | } | ||
124 | |||
115 | dev->sata_dev.sstatus = resp->sstatus; | 125 | dev->sata_dev.sstatus = resp->sstatus; |
116 | dev->sata_dev.serror = resp->serror; | 126 | dev->sata_dev.serror = resp->serror; |
117 | dev->sata_dev.scontrol = resp->scontrol; | 127 | dev->sata_dev.scontrol = resp->scontrol; |
@@ -121,7 +131,13 @@ static void sas_ata_task_done(struct sas_task *task) | |||
121 | SAS_DPRINTK("%s: SAS error %x\n", __func__, | 131 | SAS_DPRINTK("%s: SAS error %x\n", __func__, |
122 | stat->stat); | 132 | stat->stat); |
123 | /* We saw a SAS error. Send a vague error. */ | 133 | /* We saw a SAS error. Send a vague error. */ |
124 | qc->err_mask = ac; | 134 | if (!link->sactive) { |
135 | qc->err_mask = ac; | ||
136 | } else { | ||
137 | link->eh_info.err_mask |= AC_ERR_DEV; | ||
138 | qc->flags |= ATA_QCFLAG_FAILED; | ||
139 | } | ||
140 | |||
125 | dev->sata_dev.tf.feature = 0x04; /* status err */ | 141 | dev->sata_dev.tf.feature = 0x04; /* status err */ |
126 | dev->sata_dev.tf.command = ATA_ERR; | 142 | dev->sata_dev.tf.command = ATA_ERR; |
127 | } | 143 | } |