diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-23 15:29:16 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-23 15:29:16 -0500 |
commit | b23c9cc0ce652089a2f0af8c7f1541f10dc9b5db (patch) | |
tree | d2e429bbb74c268c071790761e4a2b59d96ea3f7 /drivers/scsi/libsas | |
parent | 1e8352784abaedb424e63fa700e93e6c1307785f (diff) | |
parent | cfb37ae1e9d31fe2c1d21734ab51405e0c3afb7e (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-rc-fixes-2.6: (25 commits)
[SCSI] qlogicpt: section fixes
[SCSI] mvsas: convert from rough draft to working driver
[SCSI] mvsas: Add Marvell 6440 SAS/SATA driver
[SCSI] libsas: correctly flush the LU queue on error recovery
[SCSI] aic94xx: fix sequencer hang on error recovery
[SCSI] st: compile fix when DEBUG set to one
[SCSI] stex: stex_internal_copy should be called with sg_count in struct st_ccb
[SCSI] stex: stex_direct_copy shouldn't call dma_map_sg
[SCSI] lpfc: Balance locking
[SCSI] qla4xxx: fix up residual handling
[SCSI] libsas: fix error handling
[SCSI] arcmsr: fix message allocation
[SCSI] mptbase: fix use-after-free's
[SCSI] iscsi transport: make 2 functions static
[SCSI] lpfc: make lpfc_disable_node() static
[SCSI] ips: fix data buffer accessors conversion bug
[SCSI] gdth: don't call pci_free_consistent under spinlock
[SCSI] qla2xxx: fix compile warning for printk format
[SCSI] aic7xx: mitigate HOST_MSG_LOOP invalid SCB ff panic
[SCSI] scsi_debug: disable clustering
...
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 68 |
1 files changed, 43 insertions, 25 deletions
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index f869fba86807..704ea06a6e50 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -51,10 +51,14 @@ static void sas_scsi_task_done(struct sas_task *task) | |||
51 | { | 51 | { |
52 | struct task_status_struct *ts = &task->task_status; | 52 | struct task_status_struct *ts = &task->task_status; |
53 | struct scsi_cmnd *sc = task->uldd_task; | 53 | struct scsi_cmnd *sc = task->uldd_task; |
54 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host); | ||
55 | unsigned ts_flags = task->task_state_flags; | ||
56 | int hs = 0, stat = 0; | 54 | int hs = 0, stat = 0; |
57 | 55 | ||
56 | if (unlikely(task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | ||
57 | /* Aborted tasks will be completed by the error handler */ | ||
58 | SAS_DPRINTK("task done but aborted\n"); | ||
59 | return; | ||
60 | } | ||
61 | |||
58 | if (unlikely(!sc)) { | 62 | if (unlikely(!sc)) { |
59 | SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n"); | 63 | SAS_DPRINTK("task_done called with non existing SCSI cmnd!\n"); |
60 | list_del_init(&task->list); | 64 | list_del_init(&task->list); |
@@ -120,11 +124,7 @@ static void sas_scsi_task_done(struct sas_task *task) | |||
120 | sc->result = (hs << 16) | stat; | 124 | sc->result = (hs << 16) | stat; |
121 | list_del_init(&task->list); | 125 | list_del_init(&task->list); |
122 | sas_free_task(task); | 126 | sas_free_task(task); |
123 | /* This is very ugly but this is how SCSI Core works. */ | 127 | sc->scsi_done(sc); |
124 | if (ts_flags & SAS_TASK_STATE_ABORTED) | ||
125 | scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q); | ||
126 | else | ||
127 | sc->scsi_done(sc); | ||
128 | } | 128 | } |
129 | 129 | ||
130 | static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd) | 130 | static enum task_attribute sas_scsi_get_task_attr(struct scsi_cmnd *cmd) |
@@ -255,13 +255,34 @@ out: | |||
255 | return res; | 255 | return res; |
256 | } | 256 | } |
257 | 257 | ||
258 | static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) | ||
259 | { | ||
260 | struct sas_task *task = TO_SAS_TASK(cmd); | ||
261 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host); | ||
262 | |||
263 | /* remove the aborted task flag to allow the task to be | ||
264 | * completed now. At this point, we only get called following | ||
265 | * an actual abort of the task, so we should be guaranteed not | ||
266 | * to be racing with any completions from the LLD (hence we | ||
267 | * don't need the task state lock to clear the flag) */ | ||
268 | task->task_state_flags &= ~SAS_TASK_STATE_ABORTED; | ||
269 | /* Now call task_done. However, task will be free'd after | ||
270 | * this */ | ||
271 | task->task_done(task); | ||
272 | /* now finish the command and move it on to the error | ||
273 | * handler done list, this also takes it off the | ||
274 | * error handler pending list */ | ||
275 | scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q); | ||
276 | } | ||
277 | |||
258 | static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) | 278 | static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd) |
259 | { | 279 | { |
260 | struct scsi_cmnd *cmd, *n; | 280 | struct scsi_cmnd *cmd, *n; |
261 | 281 | ||
262 | list_for_each_entry_safe(cmd, n, error_q, eh_entry) { | 282 | list_for_each_entry_safe(cmd, n, error_q, eh_entry) { |
263 | if (cmd == my_cmd) | 283 | if (cmd->device->sdev_target == my_cmd->device->sdev_target && |
264 | list_del_init(&cmd->eh_entry); | 284 | cmd->device->lun == my_cmd->device->lun) |
285 | sas_eh_finish_cmd(cmd); | ||
265 | } | 286 | } |
266 | } | 287 | } |
267 | 288 | ||
@@ -274,7 +295,7 @@ static void sas_scsi_clear_queue_I_T(struct list_head *error_q, | |||
274 | struct domain_device *x = cmd_to_domain_dev(cmd); | 295 | struct domain_device *x = cmd_to_domain_dev(cmd); |
275 | 296 | ||
276 | if (x == dev) | 297 | if (x == dev) |
277 | list_del_init(&cmd->eh_entry); | 298 | sas_eh_finish_cmd(cmd); |
278 | } | 299 | } |
279 | } | 300 | } |
280 | 301 | ||
@@ -288,7 +309,7 @@ static void sas_scsi_clear_queue_port(struct list_head *error_q, | |||
288 | struct asd_sas_port *x = dev->port; | 309 | struct asd_sas_port *x = dev->port; |
289 | 310 | ||
290 | if (x == port) | 311 | if (x == port) |
291 | list_del_init(&cmd->eh_entry); | 312 | sas_eh_finish_cmd(cmd); |
292 | } | 313 | } |
293 | } | 314 | } |
294 | 315 | ||
@@ -528,14 +549,14 @@ Again: | |||
528 | case TASK_IS_DONE: | 549 | case TASK_IS_DONE: |
529 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, | 550 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, |
530 | task); | 551 | task); |
531 | task->task_done(task); | 552 | sas_eh_finish_cmd(cmd); |
532 | if (need_reset) | 553 | if (need_reset) |
533 | try_to_reset_cmd_device(shost, cmd); | 554 | try_to_reset_cmd_device(shost, cmd); |
534 | continue; | 555 | continue; |
535 | case TASK_IS_ABORTED: | 556 | case TASK_IS_ABORTED: |
536 | SAS_DPRINTK("%s: task 0x%p is aborted\n", | 557 | SAS_DPRINTK("%s: task 0x%p is aborted\n", |
537 | __FUNCTION__, task); | 558 | __FUNCTION__, task); |
538 | task->task_done(task); | 559 | sas_eh_finish_cmd(cmd); |
539 | if (need_reset) | 560 | if (need_reset) |
540 | try_to_reset_cmd_device(shost, cmd); | 561 | try_to_reset_cmd_device(shost, cmd); |
541 | continue; | 562 | continue; |
@@ -547,7 +568,7 @@ Again: | |||
547 | "recovered\n", | 568 | "recovered\n", |
548 | SAS_ADDR(task->dev), | 569 | SAS_ADDR(task->dev), |
549 | cmd->device->lun); | 570 | cmd->device->lun); |
550 | task->task_done(task); | 571 | sas_eh_finish_cmd(cmd); |
551 | if (need_reset) | 572 | if (need_reset) |
552 | try_to_reset_cmd_device(shost, cmd); | 573 | try_to_reset_cmd_device(shost, cmd); |
553 | sas_scsi_clear_queue_lu(work_q, cmd); | 574 | sas_scsi_clear_queue_lu(work_q, cmd); |
@@ -562,7 +583,7 @@ Again: | |||
562 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 583 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
563 | SAS_DPRINTK("I_T %016llx recovered\n", | 584 | SAS_DPRINTK("I_T %016llx recovered\n", |
564 | SAS_ADDR(task->dev->sas_addr)); | 585 | SAS_ADDR(task->dev->sas_addr)); |
565 | task->task_done(task); | 586 | sas_eh_finish_cmd(cmd); |
566 | if (need_reset) | 587 | if (need_reset) |
567 | try_to_reset_cmd_device(shost, cmd); | 588 | try_to_reset_cmd_device(shost, cmd); |
568 | sas_scsi_clear_queue_I_T(work_q, task->dev); | 589 | sas_scsi_clear_queue_I_T(work_q, task->dev); |
@@ -577,7 +598,7 @@ Again: | |||
577 | if (res == TMF_RESP_FUNC_COMPLETE) { | 598 | if (res == TMF_RESP_FUNC_COMPLETE) { |
578 | SAS_DPRINTK("clear nexus port:%d " | 599 | SAS_DPRINTK("clear nexus port:%d " |
579 | "succeeded\n", port->id); | 600 | "succeeded\n", port->id); |
580 | task->task_done(task); | 601 | sas_eh_finish_cmd(cmd); |
581 | if (need_reset) | 602 | if (need_reset) |
582 | try_to_reset_cmd_device(shost, cmd); | 603 | try_to_reset_cmd_device(shost, cmd); |
583 | sas_scsi_clear_queue_port(work_q, | 604 | sas_scsi_clear_queue_port(work_q, |
@@ -591,10 +612,10 @@ Again: | |||
591 | if (res == TMF_RESP_FUNC_COMPLETE) { | 612 | if (res == TMF_RESP_FUNC_COMPLETE) { |
592 | SAS_DPRINTK("clear nexus ha " | 613 | SAS_DPRINTK("clear nexus ha " |
593 | "succeeded\n"); | 614 | "succeeded\n"); |
594 | task->task_done(task); | 615 | sas_eh_finish_cmd(cmd); |
595 | if (need_reset) | 616 | if (need_reset) |
596 | try_to_reset_cmd_device(shost, cmd); | 617 | try_to_reset_cmd_device(shost, cmd); |
597 | goto out; | 618 | goto clear_q; |
598 | } | 619 | } |
599 | } | 620 | } |
600 | /* If we are here -- this means that no amount | 621 | /* If we are here -- this means that no amount |
@@ -606,21 +627,18 @@ Again: | |||
606 | SAS_ADDR(task->dev->sas_addr), | 627 | SAS_ADDR(task->dev->sas_addr), |
607 | cmd->device->lun); | 628 | cmd->device->lun); |
608 | 629 | ||
609 | task->task_done(task); | 630 | sas_eh_finish_cmd(cmd); |
610 | if (need_reset) | 631 | if (need_reset) |
611 | try_to_reset_cmd_device(shost, cmd); | 632 | try_to_reset_cmd_device(shost, cmd); |
612 | goto clear_q; | 633 | goto clear_q; |
613 | } | 634 | } |
614 | } | 635 | } |
615 | out: | ||
616 | return list_empty(work_q); | 636 | return list_empty(work_q); |
617 | clear_q: | 637 | clear_q: |
618 | SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__); | 638 | SAS_DPRINTK("--- Exit %s -- clear_q\n", __FUNCTION__); |
619 | list_for_each_entry_safe(cmd, n, work_q, eh_entry) { | 639 | list_for_each_entry_safe(cmd, n, work_q, eh_entry) |
620 | struct sas_task *task = TO_SAS_TASK(cmd); | 640 | sas_eh_finish_cmd(cmd); |
621 | list_del_init(&cmd->eh_entry); | 641 | |
622 | task->task_done(task); | ||
623 | } | ||
624 | return list_empty(work_q); | 642 | return list_empty(work_q); |
625 | } | 643 | } |
626 | 644 | ||