diff options
| author | Andi Kleen <andi@basil.nowhere.org> | 2006-11-21 04:22:09 -0500 |
|---|---|---|
| committer | Andi Kleen <andi@basil.nowhere.org> | 2006-11-21 04:22:09 -0500 |
| commit | 1b7f6a626f0ff511c3840678466cbfe1d62c0b29 (patch) | |
| tree | 415e8c838c0067bff384afb8a2c91e5f7c6d11d3 /drivers/scsi/libsas/sas_expander.c | |
| parent | b3edc9cec07ade41aaf1804f7c9e876afa90c862 (diff) | |
| parent | 3f5a6ca31c334011fd929501a078424c0d3f71be (diff) | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/scsi/libsas/sas_expander.c')
| -rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 84 |
1 files changed, 47 insertions, 37 deletions
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 30b8014bcc7a..e34a93435497 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -71,55 +71,65 @@ static void smp_task_done(struct sas_task *task) | |||
| 71 | static int smp_execute_task(struct domain_device *dev, void *req, int req_size, | 71 | static int smp_execute_task(struct domain_device *dev, void *req, int req_size, |
| 72 | void *resp, int resp_size) | 72 | void *resp, int resp_size) |
| 73 | { | 73 | { |
| 74 | int res; | 74 | int res, retry; |
| 75 | struct sas_task *task = sas_alloc_task(GFP_KERNEL); | 75 | struct sas_task *task = NULL; |
| 76 | struct sas_internal *i = | 76 | struct sas_internal *i = |
| 77 | to_sas_internal(dev->port->ha->core.shost->transportt); | 77 | to_sas_internal(dev->port->ha->core.shost->transportt); |
| 78 | 78 | ||
| 79 | if (!task) | 79 | for (retry = 0; retry < 3; retry++) { |
| 80 | return -ENOMEM; | 80 | task = sas_alloc_task(GFP_KERNEL); |
| 81 | 81 | if (!task) | |
| 82 | task->dev = dev; | 82 | return -ENOMEM; |
| 83 | task->task_proto = dev->tproto; | ||
| 84 | sg_init_one(&task->smp_task.smp_req, req, req_size); | ||
| 85 | sg_init_one(&task->smp_task.smp_resp, resp, resp_size); | ||
| 86 | 83 | ||
| 87 | task->task_done = smp_task_done; | 84 | task->dev = dev; |
| 85 | task->task_proto = dev->tproto; | ||
| 86 | sg_init_one(&task->smp_task.smp_req, req, req_size); | ||
| 87 | sg_init_one(&task->smp_task.smp_resp, resp, resp_size); | ||
| 88 | 88 | ||
| 89 | task->timer.data = (unsigned long) task; | 89 | task->task_done = smp_task_done; |
| 90 | task->timer.function = smp_task_timedout; | ||
| 91 | task->timer.expires = jiffies + SMP_TIMEOUT*HZ; | ||
| 92 | add_timer(&task->timer); | ||
| 93 | 90 | ||
| 94 | res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); | 91 | task->timer.data = (unsigned long) task; |
| 92 | task->timer.function = smp_task_timedout; | ||
| 93 | task->timer.expires = jiffies + SMP_TIMEOUT*HZ; | ||
| 94 | add_timer(&task->timer); | ||
| 95 | 95 | ||
| 96 | if (res) { | 96 | res = i->dft->lldd_execute_task(task, 1, GFP_KERNEL); |
| 97 | del_timer(&task->timer); | ||
| 98 | SAS_DPRINTK("executing SMP task failed:%d\n", res); | ||
| 99 | goto ex_err; | ||
| 100 | } | ||
| 101 | 97 | ||
| 102 | wait_for_completion(&task->completion); | 98 | if (res) { |
| 103 | res = -ETASK; | 99 | del_timer(&task->timer); |
| 104 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | 100 | SAS_DPRINTK("executing SMP task failed:%d\n", res); |
| 105 | SAS_DPRINTK("smp task timed out or aborted\n"); | ||
| 106 | i->dft->lldd_abort_task(task); | ||
| 107 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | ||
| 108 | SAS_DPRINTK("SMP task aborted and not done\n"); | ||
| 109 | goto ex_err; | 101 | goto ex_err; |
| 110 | } | 102 | } |
| 103 | |||
| 104 | wait_for_completion(&task->completion); | ||
| 105 | res = -ETASK; | ||
| 106 | if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { | ||
| 107 | SAS_DPRINTK("smp task timed out or aborted\n"); | ||
| 108 | i->dft->lldd_abort_task(task); | ||
| 109 | if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { | ||
| 110 | SAS_DPRINTK("SMP task aborted and not done\n"); | ||
| 111 | goto ex_err; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
| 115 | task->task_status.stat == SAM_GOOD) { | ||
| 116 | res = 0; | ||
| 117 | break; | ||
| 118 | } else { | ||
| 119 | SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " | ||
| 120 | "status 0x%x\n", __FUNCTION__, | ||
| 121 | SAS_ADDR(dev->sas_addr), | ||
| 122 | task->task_status.resp, | ||
| 123 | task->task_status.stat); | ||
| 124 | sas_free_task(task); | ||
| 125 | task = NULL; | ||
| 126 | } | ||
| 111 | } | 127 | } |
| 112 | if (task->task_status.resp == SAS_TASK_COMPLETE && | ||
| 113 | task->task_status.stat == SAM_GOOD) | ||
| 114 | res = 0; | ||
| 115 | else | ||
| 116 | SAS_DPRINTK("%s: task to dev %016llx response: 0x%x " | ||
| 117 | "status 0x%x\n", __FUNCTION__, | ||
| 118 | SAS_ADDR(dev->sas_addr), | ||
| 119 | task->task_status.resp, | ||
| 120 | task->task_status.stat); | ||
| 121 | ex_err: | 128 | ex_err: |
| 122 | sas_free_task(task); | 129 | BUG_ON(retry == 3 && task != NULL); |
| 130 | if (task != NULL) { | ||
| 131 | sas_free_task(task); | ||
| 132 | } | ||
| 123 | return res; | 133 | return res; |
| 124 | } | 134 | } |
| 125 | 135 | ||
