diff options
author | Darrick J. Wong <djwong@us.ibm.com> | 2006-10-30 18:18:39 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-11-15 13:14:16 -0500 |
commit | f456393e195e0aa16029985f63cd93b601a0d315 (patch) | |
tree | dc4b9d4c0705d5fe2d94669b1a75053f52755cb7 /drivers/scsi/libsas | |
parent | b4d38e38e66f8e1b32a1b1c00e533175314c8d56 (diff) |
[SCSI] libsas: modify error handler to use scsi_eh_* functions
This patch adds an EH done queue to sas_ha, converts the error handling
strategy function and the sas_scsi_task_done functions in libsas to use
the scsi_eh_* commands for error'd commands, and adds checks for the
INITIATOR_ABORTED flag so that we do the right thing if a sas_task has
been aborted by the initiator.
Signed-off-by: Darrick J. Wong <djwong@us.ibm.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 2 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 29 |
2 files changed, 27 insertions, 4 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", |