diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 60 |
1 files changed, 57 insertions, 3 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 31fc21f4d831..db9238f2ecb8 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 | } |
@@ -279,6 +295,44 @@ static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class, | |||
279 | return ret; | 295 | return ret; |
280 | } | 296 | } |
281 | 297 | ||
298 | static int sas_ata_soft_reset(struct ata_link *link, unsigned int *class, | ||
299 | unsigned long deadline) | ||
300 | { | ||
301 | struct ata_port *ap = link->ap; | ||
302 | struct domain_device *dev = ap->private_data; | ||
303 | struct sas_internal *i = | ||
304 | to_sas_internal(dev->port->ha->core.shost->transportt); | ||
305 | int res = TMF_RESP_FUNC_FAILED; | ||
306 | int ret = 0; | ||
307 | |||
308 | if (i->dft->lldd_ata_soft_reset) | ||
309 | res = i->dft->lldd_ata_soft_reset(dev); | ||
310 | |||
311 | if (res != TMF_RESP_FUNC_COMPLETE) { | ||
312 | SAS_DPRINTK("%s: Unable to soft reset\n", __func__); | ||
313 | ret = -EAGAIN; | ||
314 | } | ||
315 | |||
316 | switch (dev->sata_dev.command_set) { | ||
317 | case ATA_COMMAND_SET: | ||
318 | SAS_DPRINTK("%s: Found ATA device.\n", __func__); | ||
319 | *class = ATA_DEV_ATA; | ||
320 | break; | ||
321 | case ATAPI_COMMAND_SET: | ||
322 | SAS_DPRINTK("%s: Found ATAPI device.\n", __func__); | ||
323 | *class = ATA_DEV_ATAPI; | ||
324 | break; | ||
325 | default: | ||
326 | SAS_DPRINTK("%s: Unknown SATA command set: %d.\n", | ||
327 | __func__, dev->sata_dev.command_set); | ||
328 | *class = ATA_DEV_UNKNOWN; | ||
329 | break; | ||
330 | } | ||
331 | |||
332 | ap->cbl = ATA_CBL_SATA; | ||
333 | return ret; | ||
334 | } | ||
335 | |||
282 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) | 336 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) |
283 | { | 337 | { |
284 | if (qc->flags & ATA_QCFLAG_FAILED) | 338 | if (qc->flags & ATA_QCFLAG_FAILED) |
@@ -309,7 +363,7 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc) | |||
309 | 363 | ||
310 | static struct ata_port_operations sas_sata_ops = { | 364 | static struct ata_port_operations sas_sata_ops = { |
311 | .prereset = ata_std_prereset, | 365 | .prereset = ata_std_prereset, |
312 | .softreset = NULL, | 366 | .softreset = sas_ata_soft_reset, |
313 | .hardreset = sas_ata_hard_reset, | 367 | .hardreset = sas_ata_hard_reset, |
314 | .postreset = ata_std_postreset, | 368 | .postreset = ata_std_postreset, |
315 | .error_handler = ata_std_error_handler, | 369 | .error_handler = ata_std_error_handler, |