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 | |
| 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>
| -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 | } |
