diff options
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 29 | ||||
-rw-r--r-- | include/scsi/libsas.h | 9 |
3 files changed, 33 insertions, 7 deletions
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c index c836a237fb79..a2b479a65908 100644 --- a/drivers/scsi/libsas/sas_init.c +++ b/drivers/scsi/libsas/sas_init.c | |||
@@ -112,6 +112,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha) | |||
112 | } | 112 | } |
113 | } | 113 | } |
114 | 114 | ||
115 | INIT_LIST_HEAD(&sas_ha->eh_done_q); | ||
116 | |||
115 | return 0; | 117 | return 0; |
116 | 118 | ||
117 | Undo_ports: | 119 | Undo_ports: |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index e46e79355b77..6a97b07849b4 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <scsi/scsi_device.h> | 29 | #include <scsi/scsi_device.h> |
30 | #include <scsi/scsi_tcq.h> | 30 | #include <scsi/scsi_tcq.h> |
31 | #include <scsi/scsi.h> | 31 | #include <scsi/scsi.h> |
32 | #include <scsi/scsi_eh.h> | ||
32 | #include <scsi/scsi_transport.h> | 33 | #include <scsi/scsi_transport.h> |
33 | #include <scsi/scsi_transport_sas.h> | 34 | #include <scsi/scsi_transport_sas.h> |
34 | #include "../scsi_sas_internal.h" | 35 | #include "../scsi_sas_internal.h" |
@@ -46,6 +47,7 @@ static void sas_scsi_task_done(struct sas_task *task) | |||
46 | { | 47 | { |
47 | struct task_status_struct *ts = &task->task_status; | 48 | struct task_status_struct *ts = &task->task_status; |
48 | struct scsi_cmnd *sc = task->uldd_task; | 49 | struct scsi_cmnd *sc = task->uldd_task; |
50 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host); | ||
49 | unsigned ts_flags = task->task_state_flags; | 51 | unsigned ts_flags = task->task_state_flags; |
50 | int hs = 0, stat = 0; | 52 | int hs = 0, stat = 0; |
51 | 53 | ||
@@ -116,7 +118,7 @@ static void sas_scsi_task_done(struct sas_task *task) | |||
116 | sas_free_task(task); | 118 | sas_free_task(task); |
117 | /* This is very ugly but this is how SCSI Core works. */ | 119 | /* This is very ugly but this is how SCSI Core works. */ |
118 | if (ts_flags & SAS_TASK_STATE_ABORTED) | 120 | if (ts_flags & SAS_TASK_STATE_ABORTED) |
119 | scsi_finish_command(sc); | 121 | scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q); |
120 | else | 122 | else |
121 | sc->scsi_done(sc); | 123 | sc->scsi_done(sc); |
122 | } | 124 | } |
@@ -307,6 +309,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task) | |||
307 | spin_unlock_irqrestore(&core->task_queue_lock, flags); | 309 | spin_unlock_irqrestore(&core->task_queue_lock, flags); |
308 | } | 310 | } |
309 | 311 | ||
312 | spin_lock_irqsave(&task->task_state_lock, flags); | ||
313 | if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { | ||
314 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
315 | SAS_DPRINTK("%s: task 0x%p already aborted\n", | ||
316 | __FUNCTION__, task); | ||
317 | return TASK_IS_ABORTED; | ||
318 | } | ||
319 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
320 | |||
310 | for (i = 0; i < 5; i++) { | 321 | for (i = 0; i < 5; i++) { |
311 | SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); | 322 | SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task); |
312 | res = si->dft->lldd_abort_task(task); | 323 | res = si->dft->lldd_abort_task(task); |
@@ -409,13 +420,16 @@ Again: | |||
409 | SAS_DPRINTK("going over list...\n"); | 420 | SAS_DPRINTK("going over list...\n"); |
410 | list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { | 421 | list_for_each_entry_safe(cmd, n, &error_q, eh_entry) { |
411 | struct sas_task *task = TO_SAS_TASK(cmd); | 422 | struct sas_task *task = TO_SAS_TASK(cmd); |
423 | list_del_init(&cmd->eh_entry); | ||
412 | 424 | ||
425 | if (!task) { | ||
426 | SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__); | ||
427 | continue; | ||
428 | } | ||
413 | SAS_DPRINTK("trying to find task 0x%p\n", task); | 429 | SAS_DPRINTK("trying to find task 0x%p\n", task); |
414 | list_del_init(&cmd->eh_entry); | ||
415 | res = sas_scsi_find_task(task); | 430 | res = sas_scsi_find_task(task); |
416 | 431 | ||
417 | cmd->eh_eflags = 0; | 432 | cmd->eh_eflags = 0; |
418 | shost->host_failed--; | ||
419 | 433 | ||
420 | switch (res) { | 434 | switch (res) { |
421 | case TASK_IS_DONE: | 435 | case TASK_IS_DONE: |
@@ -491,6 +505,7 @@ Again: | |||
491 | } | 505 | } |
492 | } | 506 | } |
493 | out: | 507 | out: |
508 | scsi_eh_flush_done_q(&ha->eh_done_q); | ||
494 | SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); | 509 | SAS_DPRINTK("--- Exit %s\n", __FUNCTION__); |
495 | return; | 510 | return; |
496 | clear_q: | 511 | clear_q: |
@@ -508,12 +523,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) | |||
508 | unsigned long flags; | 523 | unsigned long flags; |
509 | 524 | ||
510 | if (!task) { | 525 | if (!task) { |
511 | SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", | 526 | SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n", |
512 | cmd, task); | 527 | cmd, task); |
513 | return EH_HANDLED; | 528 | return EH_HANDLED; |
514 | } | 529 | } |
515 | 530 | ||
516 | spin_lock_irqsave(&task->task_state_lock, flags); | 531 | spin_lock_irqsave(&task->task_state_lock, flags); |
532 | if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) { | ||
533 | spin_unlock_irqrestore(&task->task_state_lock, flags); | ||
534 | SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: " | ||
535 | "EH_NOT_HANDLED\n", cmd, task); | ||
536 | return EH_NOT_HANDLED; | ||
537 | } | ||
517 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { | 538 | if (task->task_state_flags & SAS_TASK_STATE_DONE) { |
518 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 539 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
519 | SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", | 540 | SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n", |
diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index 9582e8401669..7bf2e8b9903c 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h | |||
@@ -338,6 +338,8 @@ struct sas_ha_struct { | |||
338 | void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); | 338 | void (*notify_phy_event)(struct asd_sas_phy *, enum phy_event); |
339 | 339 | ||
340 | void *lldd_ha; /* not touched by sas class code */ | 340 | void *lldd_ha; /* not touched by sas class code */ |
341 | |||
342 | struct list_head eh_done_q; | ||
341 | }; | 343 | }; |
342 | 344 | ||
343 | #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) | 345 | #define SHOST_TO_SAS_HA(_shost) (*(struct sas_ha_struct **)(_shost)->hostdata) |
@@ -530,9 +532,10 @@ struct sas_task { | |||
530 | 532 | ||
531 | 533 | ||
532 | 534 | ||
533 | #define SAS_TASK_STATE_PENDING 1 | 535 | #define SAS_TASK_STATE_PENDING 1 |
534 | #define SAS_TASK_STATE_DONE 2 | 536 | #define SAS_TASK_STATE_DONE 2 |
535 | #define SAS_TASK_STATE_ABORTED 4 | 537 | #define SAS_TASK_STATE_ABORTED 4 |
538 | #define SAS_TASK_INITIATOR_ABORTED 8 | ||
536 | 539 | ||
537 | static inline struct sas_task *sas_alloc_task(gfp_t flags) | 540 | static inline struct sas_task *sas_alloc_task(gfp_t flags) |
538 | { | 541 | { |