diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_ata.c')
-rw-r--r-- | drivers/scsi/libsas/sas_ata.c | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 5cb0a2ae5924..903bb441b9f9 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -100,15 +100,31 @@ static void sas_ata_task_done(struct sas_task *task) | |||
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 | struct ata_link *link; |
103 | struct ata_port *ap; | ||
103 | 104 | ||
104 | if (!qc) | 105 | if (!qc) |
105 | goto qc_already_gone; | 106 | goto qc_already_gone; |
106 | 107 | ||
107 | dev = qc->ap->private_data; | 108 | ap = qc->ap; |
109 | dev = ap->private_data; | ||
108 | sas_ha = dev->port->ha; | 110 | sas_ha = dev->port->ha; |
109 | link = &dev->sata_dev.ap->link; | 111 | link = &ap->link; |
112 | |||
113 | spin_lock_irqsave(ap->lock, flags); | ||
114 | /* check if we lost the race with libata/sas_ata_post_internal() */ | ||
115 | if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) { | ||
116 | spin_unlock_irqrestore(ap->lock, flags); | ||
117 | if (qc->scsicmd) | ||
118 | goto qc_already_gone; | ||
119 | else { | ||
120 | /* if eh is not involved and the port is frozen then the | ||
121 | * ata internal abort process has taken responsibility | ||
122 | * for this sas_task | ||
123 | */ | ||
124 | return; | ||
125 | } | ||
126 | } | ||
110 | 127 | ||
111 | spin_lock_irqsave(dev->sata_dev.ap->lock, flags); | ||
112 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || | 128 | if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || |
113 | ((stat->stat == SAM_STAT_CHECK_CONDITION && | 129 | ((stat->stat == SAM_STAT_CHECK_CONDITION && |
114 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { | 130 | dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { |
@@ -143,7 +159,7 @@ static void sas_ata_task_done(struct sas_task *task) | |||
143 | if (qc->scsicmd) | 159 | if (qc->scsicmd) |
144 | ASSIGN_SAS_TASK(qc->scsicmd, NULL); | 160 | ASSIGN_SAS_TASK(qc->scsicmd, NULL); |
145 | ata_qc_complete(qc); | 161 | ata_qc_complete(qc); |
146 | spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); | 162 | spin_unlock_irqrestore(ap->lock, flags); |
147 | 163 | ||
148 | qc_already_gone: | 164 | qc_already_gone: |
149 | list_del_init(&task->list); | 165 | list_del_init(&task->list); |
@@ -325,6 +341,54 @@ static int sas_ata_soft_reset(struct ata_link *link, unsigned int *class, | |||
325 | return ret; | 341 | return ret; |
326 | } | 342 | } |
327 | 343 | ||
344 | /* | ||
345 | * notify the lldd to forget the sas_task for this internal ata command | ||
346 | * that bypasses scsi-eh | ||
347 | */ | ||
348 | static void sas_ata_internal_abort(struct sas_task *task) | ||
349 | { | ||
350 | struct sas_internal *si = | ||
351 | to_sas_internal(task->dev->port->ha->core.shost->transportt); | ||
352 | unsigned long flags; | ||
353 | int res; | ||
354 | |||
355 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
356 | if (task->task_state_flags & SAS_TASK_STATE_ABORTED || | ||
357 | task->task_state_flags & SAS_TASK_STATE_DONE) { | ||
358 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
359 | SAS_DPRINTK("%s: Task %p already finished.\n", __func__, | ||
360 | task); | ||
361 | goto out; | ||
362 | } | ||
363 | task->task_state_flags |= SAS_TASK_STATE_ABORTED; | ||
364 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
365 | |||
366 | res = si->dft->lldd_abort_task(task); | ||
367 | |||
368 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
369 | if (task->task_state_flags & SAS_TASK_STATE_DONE || | ||
370 | res == TMF_RESP_FUNC_COMPLETE) { | ||
371 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
372 | goto out; | ||
373 | } | ||
374 | |||
375 | /* XXX we are not prepared to deal with ->lldd_abort_task() | ||
376 | * failures. TODO: lldds need to unconditionally forget about | ||
377 | * aborted ata tasks, otherwise we (likely) leak the sas task | ||
378 | * here | ||
379 | */ | ||
380 | SAS_DPRINTK("%s: Task %p leaked.\n", __func__, task); | ||
381 | |||
382 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) | ||
383 | task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; | ||
384 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
385 | |||
386 | return; | ||
387 | out: | ||
388 | list_del_init(&task->list); | ||
389 | sas_free_task(task); | ||
390 | } | ||
391 | |||
328 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) | 392 | static void sas_ata_post_internal(struct ata_queued_cmd *qc) |
329 | { | 393 | { |
330 | if (qc->flags & ATA_QCFLAG_FAILED) | 394 | if (qc->flags & ATA_QCFLAG_FAILED) |
@@ -332,10 +396,12 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc) | |||
332 | 396 | ||
333 | if (qc->err_mask) { | 397 | if (qc->err_mask) { |
334 | /* | 398 | /* |
335 | * Find the sas_task and kill it. By this point, | 399 | * Find the sas_task and kill it. By this point, libata |
336 | * libata has decided to kill the qc, so we needn't | 400 | * has decided to kill the qc and has frozen the port. |
337 | * bother with sas_ata_task_done. But we still | 401 | * In this state sas_ata_task_done() will no longer free |
338 | * ought to abort the task. | 402 | * the sas_task, so we need to notify the lldd (via |
403 | * ->lldd_abort_task) that the task is dead and free it | ||
404 | * ourselves. | ||
339 | */ | 405 | */ |
340 | struct sas_task *task = qc->lldd_task; | 406 | struct sas_task *task = qc->lldd_task; |
341 | unsigned long flags; | 407 | unsigned long flags; |
@@ -348,7 +414,7 @@ static void sas_ata_post_internal(struct ata_queued_cmd *qc) | |||
348 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 414 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
349 | 415 | ||
350 | task->uldd_task = NULL; | 416 | task->uldd_task = NULL; |
351 | __sas_task_abort(task); | 417 | sas_ata_internal_abort(task); |
352 | } | 418 | } |
353 | } | 419 | } |
354 | } | 420 | } |