diff options
Diffstat (limited to 'drivers/scsi/libsas/sas_scsi_host.c')
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 33 |
1 files changed, 13 insertions, 20 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 6de9681ace82..ceab5e5c41c2 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -223,6 +223,7 @@ out_done: | |||
223 | static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) | 223 | static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) |
224 | { | 224 | { |
225 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); | 225 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); |
226 | struct domain_device *dev = cmd_to_domain_dev(cmd); | ||
226 | struct sas_task *task = TO_SAS_TASK(cmd); | 227 | struct sas_task *task = TO_SAS_TASK(cmd); |
227 | 228 | ||
228 | /* At this point, we only get called following an actual abort | 229 | /* At this point, we only get called following an actual abort |
@@ -231,6 +232,14 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) | |||
231 | */ | 232 | */ |
232 | sas_end_task(cmd, task); | 233 | sas_end_task(cmd, task); |
233 | 234 | ||
235 | if (dev_is_sata(dev)) { | ||
236 | /* defer commands to libata so that libata EH can | ||
237 | * handle ata qcs correctly | ||
238 | */ | ||
239 | list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q); | ||
240 | return; | ||
241 | } | ||
242 | |||
234 | /* now finish the command and move it on to the error | 243 | /* now finish the command and move it on to the error |
235 | * handler done list, this also takes it off the | 244 | * handler done list, this also takes it off the |
236 | * error handler pending list. | 245 | * error handler pending list. |
@@ -238,22 +247,6 @@ static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) | |||
238 | scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); | 247 | scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); |
239 | } | 248 | } |
240 | 249 | ||
241 | static void sas_eh_defer_cmd(struct scsi_cmnd *cmd) | ||
242 | { | ||
243 | struct domain_device *dev = cmd_to_domain_dev(cmd); | ||
244 | struct sas_ha_struct *ha = dev->port->ha; | ||
245 | struct sas_task *task = TO_SAS_TASK(cmd); | ||
246 | |||
247 | if (!dev_is_sata(dev)) { | ||
248 | sas_eh_finish_cmd(cmd); | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | /* report the timeout to libata */ | ||
253 | sas_end_task(cmd, task); | ||
254 | list_move_tail(&cmd->eh_entry, &ha->eh_ata_q); | ||
255 | } | ||
256 | |||
257 | static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) | 250 | static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) |
258 | { | 251 | { |
259 | struct scsi_cmnd *cmd, *n; | 252 | struct scsi_cmnd *cmd, *n; |
@@ -261,7 +254,7 @@ static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd | |||
261 | list_for_each_entry_safe(cmd, n, error_q, eh_entry) { | 254 | list_for_each_entry_safe(cmd, n, error_q, eh_entry) { |
262 | if (cmd->device->sdev_target == my_cmd->device->sdev_target && | 255 | if (cmd->device->sdev_target == my_cmd->device->sdev_target && |
263 | cmd->device->lun == my_cmd->device->lun) | 256 | cmd->device->lun == my_cmd->device->lun) |
264 | sas_eh_defer_cmd(cmd); | 257 | sas_eh_finish_cmd(cmd); |
265 | } | 258 | } |
266 | } | 259 | } |
267 | 260 | ||
@@ -631,12 +624,12 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * | |||
631 | case TASK_IS_DONE: | 624 | case TASK_IS_DONE: |
632 | SAS_DPRINTK("%s: task 0x%p is done\n", __func__, | 625 | SAS_DPRINTK("%s: task 0x%p is done\n", __func__, |
633 | task); | 626 | task); |
634 | sas_eh_defer_cmd(cmd); | 627 | sas_eh_finish_cmd(cmd); |
635 | continue; | 628 | continue; |
636 | case TASK_IS_ABORTED: | 629 | case TASK_IS_ABORTED: |
637 | SAS_DPRINTK("%s: task 0x%p is aborted\n", | 630 | SAS_DPRINTK("%s: task 0x%p is aborted\n", |
638 | __func__, task); | 631 | __func__, task); |
639 | sas_eh_defer_cmd(cmd); | 632 | sas_eh_finish_cmd(cmd); |
640 | continue; | 633 | continue; |
641 | case TASK_IS_AT_LU: | 634 | case TASK_IS_AT_LU: |
642 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); | 635 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); |
@@ -647,7 +640,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * | |||
647 | "recovered\n", | 640 | "recovered\n", |
648 | SAS_ADDR(task->dev), | 641 | SAS_ADDR(task->dev), |
649 | cmd->device->lun); | 642 | cmd->device->lun); |
650 | sas_eh_defer_cmd(cmd); | 643 | sas_eh_finish_cmd(cmd); |
651 | sas_scsi_clear_queue_lu(work_q, cmd); | 644 | sas_scsi_clear_queue_lu(work_q, cmd); |
652 | goto Again; | 645 | goto Again; |
653 | } | 646 | } |