aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2011-12-07 02:24:42 -0500
committerJames Bottomley <JBottomley@Parallels.com>2012-02-19 15:04:52 -0500
commita3a142524aa4b1539a64a55087bf12ffa4b1f94e (patch)
tree2440c6438979cf410ca9231ab77d5115a140eca5
parent3dff5721e4f67e6231dfc419d30aaa7563bfffd4 (diff)
[SCSI] libsas: prevent double completion of scmds from eh
We invoke task->task_done() to free the task in the eh case, but at this point we are prepared for scsi_eh_flush_done_q() to finish off the scmd. Introduce sas_end_task() to capture the final response status from the lldd and free the task. Also take the opportunity to kill this warning. drivers/scsi/libsas/sas_scsi_host.c: In function ‘sas_end_task’: drivers/scsi/libsas/sas_scsi_host.c:102:3: warning: case value ‘2’ not in enumerated type ‘enum exec_status’ [-Wswitch] Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c61
-rw-r--r--include/scsi/libsas.h5
2 files changed, 37 insertions, 29 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index ba5876ccd29a..50db8f971a06 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -49,27 +49,12 @@
49#include <linux/scatterlist.h> 49#include <linux/scatterlist.h>
50#include <linux/libata.h> 50#include <linux/libata.h>
51 51
52/* ---------- SCSI Host glue ---------- */ 52/* record final status and free the task */
53 53static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task)
54static void sas_scsi_task_done(struct sas_task *task)
55{ 54{
56 struct task_status_struct *ts = &task->task_status; 55 struct task_status_struct *ts = &task->task_status;
57 struct scsi_cmnd *sc = task->uldd_task;
58 int hs = 0, stat = 0; 56 int hs = 0, stat = 0;
59 57
60 if (unlikely(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
61 /* Aborted tasks will be completed by the error handler */
62 SAS_DPRINTK("task done but aborted\n");
63 return;
64 }
65
66 if (unlikely(!sc)) {
67 SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
68 list_del_init(&task->list);
69 sas_free_task(task);
70 return;
71 }
72
73 if (ts->resp == SAS_TASK_UNDELIVERED) { 58 if (ts->resp == SAS_TASK_UNDELIVERED) {
74 /* transport error */ 59 /* transport error */
75 hs = DID_NO_CONNECT; 60 hs = DID_NO_CONNECT;
@@ -124,10 +109,32 @@ static void sas_scsi_task_done(struct sas_task *task)
124 break; 109 break;
125 } 110 }
126 } 111 }
127 ASSIGN_SAS_TASK(sc, NULL); 112
128 sc->result = (hs << 16) | stat; 113 sc->result = (hs << 16) | stat;
114 ASSIGN_SAS_TASK(sc, NULL);
129 list_del_init(&task->list); 115 list_del_init(&task->list);
130 sas_free_task(task); 116 sas_free_task(task);
117}
118
119static void sas_scsi_task_done(struct sas_task *task)
120{
121 struct scsi_cmnd *sc = task->uldd_task;
122
123 if (unlikely(task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
124 /* Aborted tasks will be completed by the error handler */
125 SAS_DPRINTK("task done but aborted\n");
126 return;
127 }
128
129 if (unlikely(!sc)) {
130 SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n");
131 list_del_init(&task->list);
132 sas_free_task(task);
133 return;
134 }
135
136 ASSIGN_SAS_TASK(sc, NULL);
137 sas_end_task(sc, task);
131 sc->scsi_done(sc); 138 sc->scsi_done(sc);
132} 139}
133 140
@@ -236,18 +243,16 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
236 struct sas_task *task = TO_SAS_TASK(cmd); 243 struct sas_task *task = TO_SAS_TASK(cmd);
237 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); 244 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
238 245
239 /* remove the aborted task flag to allow the task to be 246 /* At this point, we only get called following an actual abort
240 * completed now. At this point, we only get called following 247 * of the task, so we should be guaranteed not to be racing with
241 * an actual abort of the task, so we should be guaranteed not 248 * any completions from the LLD. Task is freed after this.
242 * to be racing with any completions from the LLD (hence we 249 */
243 * don't need the task state lock to clear the flag) */ 250 sas_end_task(cmd, task);
244 task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; 251
245 /* Now call task_done. However, task will be free'd after
246 * this */
247 task->task_done(task);
248 /* now finish the command and move it on to the error 252 /* now finish the command and move it on to the error
249 * handler done list, this also takes it off the 253 * handler done list, this also takes it off the
250 * error handler pending list */ 254 * error handler pending list.
255 */
251 scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); 256 scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
252} 257}
253 258
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h
index 10eb2ea74431..071041b290d6 100644
--- a/include/scsi/libsas.h
+++ b/include/scsi/libsas.h
@@ -452,7 +452,10 @@ enum service_response {
452}; 452};
453 453
454enum exec_status { 454enum exec_status {
455 /* The SAM_STAT_.. codes fit in the lower 6 bits */ 455 /* The SAM_STAT_.. codes fit in the lower 6 bits, alias some of
456 * them here to silence 'case value not in enumerated type' warnings
457 */
458 __SAM_STAT_CHECK_CONDITION = SAM_STAT_CHECK_CONDITION,
456 459
457 SAS_DEV_NO_RESPONSE = 0x80, 460 SAS_DEV_NO_RESPONSE = 0x80,
458 SAS_DATA_UNDERRUN, 461 SAS_DATA_UNDERRUN,