diff options
author | Dan Williams <dan.j.williams@intel.com> | 2011-12-07 02:24:42 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-19 15:04:52 -0500 |
commit | a3a142524aa4b1539a64a55087bf12ffa4b1f94e (patch) | |
tree | 2440c6438979cf410ca9231ab77d5115a140eca5 | |
parent | 3dff5721e4f67e6231dfc419d30aaa7563bfffd4 (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.c | 61 | ||||
-rw-r--r-- | include/scsi/libsas.h | 5 |
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 | 53 | static void sas_end_task(struct scsi_cmnd *sc, struct sas_task *task) | |
54 | static 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 | |||
119 | static 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 | ||
454 | enum exec_status { | 454 | enum 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, |