aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@us.ibm.com>2006-10-30 18:18:39 -0500
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-11-15 13:14:16 -0500
commitf456393e195e0aa16029985f63cd93b601a0d315 (patch)
treedc4b9d4c0705d5fe2d94669b1a75053f52755cb7
parentb4d38e38e66f8e1b32a1b1c00e533175314c8d56 (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>
-rw-r--r--drivers/scsi/libsas/sas_init.c2
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c29
-rw-r--r--include/scsi/libsas.h9
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
117Undo_ports: 119Undo_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 }
493out: 507out:
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;
496clear_q: 511clear_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
537static inline struct sas_task *sas_alloc_task(gfp_t flags) 540static inline struct sas_task *sas_alloc_task(gfp_t flags)
538{ 541{