diff options
Diffstat (limited to 'drivers/scsi/libsas')
-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 | ||