aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/aic94xx
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aic94xx')
-rw-r--r--drivers/scsi/aic94xx/aic94xx.h1
-rw-r--r--drivers/scsi/aic94xx/aic94xx_hwi.h3
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_task.c4
-rw-r--r--drivers/scsi/aic94xx/aic94xx_tmf.c304
5 files changed, 195 insertions, 119 deletions
diff --git a/drivers/scsi/aic94xx/aic94xx.h b/drivers/scsi/aic94xx/aic94xx.h
index 32f513b1b78a..eb8efdcefe48 100644
--- a/drivers/scsi/aic94xx/aic94xx.h
+++ b/drivers/scsi/aic94xx/aic94xx.h
@@ -102,6 +102,7 @@ int asd_abort_task_set(struct domain_device *, u8 *lun);
102int asd_clear_aca(struct domain_device *, u8 *lun); 102int asd_clear_aca(struct domain_device *, u8 *lun);
103int asd_clear_task_set(struct domain_device *, u8 *lun); 103int asd_clear_task_set(struct domain_device *, u8 *lun);
104int asd_lu_reset(struct domain_device *, u8 *lun); 104int asd_lu_reset(struct domain_device *, u8 *lun);
105int asd_I_T_nexus_reset(struct domain_device *dev);
105int asd_query_task(struct sas_task *); 106int asd_query_task(struct sas_task *);
106 107
107/* ---------- Adapter and Port management ---------- */ 108/* ---------- Adapter and Port management ---------- */
diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h
index 150f6706d23f..abc757559c1a 100644
--- a/drivers/scsi/aic94xx/aic94xx_hwi.h
+++ b/drivers/scsi/aic94xx/aic94xx_hwi.h
@@ -140,7 +140,7 @@ struct asd_ascb {
140 140
141 /* internally generated command */ 141 /* internally generated command */
142 struct timer_list timer; 142 struct timer_list timer;
143 struct completion completion; 143 struct completion *completion;
144 u8 tag_valid:1; 144 u8 tag_valid:1;
145 __be16 tag; /* error recovery only */ 145 __be16 tag; /* error recovery only */
146 146
@@ -294,7 +294,6 @@ static inline void asd_init_ascb(struct asd_ha_struct *asd_ha,
294 ascb->timer.function = NULL; 294 ascb->timer.function = NULL;
295 init_timer(&ascb->timer); 295 init_timer(&ascb->timer);
296 ascb->tc_index = -1; 296 ascb->tc_index = -1;
297 init_completion(&ascb->completion);
298} 297}
299 298
300/* Must be called with the tc_index_lock held! 299/* Must be called with the tc_index_lock held!
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 5d761eb67442..88d1e731b65e 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -1003,7 +1003,7 @@ static struct sas_domain_function_template aic94xx_transport_functions = {
1003 .lldd_abort_task_set = asd_abort_task_set, 1003 .lldd_abort_task_set = asd_abort_task_set,
1004 .lldd_clear_aca = asd_clear_aca, 1004 .lldd_clear_aca = asd_clear_aca,
1005 .lldd_clear_task_set = asd_clear_task_set, 1005 .lldd_clear_task_set = asd_clear_task_set,
1006 .lldd_I_T_nexus_reset = NULL, 1006 .lldd_I_T_nexus_reset = asd_I_T_nexus_reset,
1007 .lldd_lu_reset = asd_lu_reset, 1007 .lldd_lu_reset = asd_lu_reset,
1008 .lldd_query_task = asd_query_task, 1008 .lldd_query_task = asd_query_task,
1009 1009
diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c
index 965d4bb999d9..008df9ab92a5 100644
--- a/drivers/scsi/aic94xx/aic94xx_task.c
+++ b/drivers/scsi/aic94xx/aic94xx_task.c
@@ -343,11 +343,13 @@ Again:
343 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR; 343 task->task_state_flags &= ~SAS_TASK_AT_INITIATOR;
344 task->task_state_flags |= SAS_TASK_STATE_DONE; 344 task->task_state_flags |= SAS_TASK_STATE_DONE;
345 if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) { 345 if (unlikely((task->task_state_flags & SAS_TASK_STATE_ABORTED))) {
346 struct completion *completion = ascb->completion;
346 spin_unlock_irqrestore(&task->task_state_lock, flags); 347 spin_unlock_irqrestore(&task->task_state_lock, flags);
347 ASD_DPRINTK("task 0x%p done with opcode 0x%x resp 0x%x " 348 ASD_DPRINTK("task 0x%p done with opcode 0x%x resp 0x%x "
348 "stat 0x%x but aborted by upper layer!\n", 349 "stat 0x%x but aborted by upper layer!\n",
349 task, opcode, ts->resp, ts->stat); 350 task, opcode, ts->resp, ts->stat);
350 complete(&ascb->completion); 351 if (completion)
352 complete(completion);
351 } else { 353 } else {
352 spin_unlock_irqrestore(&task->task_state_lock, flags); 354 spin_unlock_irqrestore(&task->task_state_lock, flags);
353 task->lldd_task = NULL; 355 task->lldd_task = NULL;
diff --git a/drivers/scsi/aic94xx/aic94xx_tmf.c b/drivers/scsi/aic94xx/aic94xx_tmf.c
index 144f5ad20453..b9ac8f703a1d 100644
--- a/drivers/scsi/aic94xx/aic94xx_tmf.c
+++ b/drivers/scsi/aic94xx/aic94xx_tmf.c
@@ -53,50 +53,64 @@ static int asd_enqueue_internal(struct asd_ascb *ascb,
53 return res; 53 return res;
54} 54}
55 55
56static inline void asd_timedout_common(unsigned long data) 56/* ---------- CLEAR NEXUS ---------- */
57{
58 struct asd_ascb *ascb = (void *) data;
59 struct asd_seq_data *seq = &ascb->ha->seq;
60 unsigned long flags;
61 57
62 spin_lock_irqsave(&seq->pend_q_lock, flags); 58struct tasklet_completion_status {
63 seq->pending--; 59 int dl_opcode;
64 list_del_init(&ascb->list); 60 int tmf_state;
65 spin_unlock_irqrestore(&seq->pend_q_lock, flags); 61 u8 tag_valid:1;
66} 62 __be16 tag;
63};
64
65#define DECLARE_TCS(tcs) \
66 struct tasklet_completion_status tcs = { \
67 .dl_opcode = 0, \
68 .tmf_state = 0, \
69 .tag_valid = 0, \
70 .tag = 0, \
71 }
67 72
68/* ---------- CLEAR NEXUS ---------- */
69 73
70static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb, 74static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb,
71 struct done_list_struct *dl) 75 struct done_list_struct *dl)
72{ 76{
77 struct tasklet_completion_status *tcs = ascb->uldd_task;
73 ASD_DPRINTK("%s: here\n", __FUNCTION__); 78 ASD_DPRINTK("%s: here\n", __FUNCTION__);
74 if (!del_timer(&ascb->timer)) { 79 if (!del_timer(&ascb->timer)) {
75 ASD_DPRINTK("%s: couldn't delete timer\n", __FUNCTION__); 80 ASD_DPRINTK("%s: couldn't delete timer\n", __FUNCTION__);
76 return; 81 return;
77 } 82 }
78 ASD_DPRINTK("%s: opcode: 0x%x\n", __FUNCTION__, dl->opcode); 83 ASD_DPRINTK("%s: opcode: 0x%x\n", __FUNCTION__, dl->opcode);
79 ascb->uldd_task = (void *) (unsigned long) dl->opcode; 84 tcs->dl_opcode = dl->opcode;
80 complete(&ascb->completion); 85 complete(ascb->completion);
86 asd_ascb_free(ascb);
81} 87}
82 88
83static void asd_clear_nexus_timedout(unsigned long data) 89static void asd_clear_nexus_timedout(unsigned long data)
84{ 90{
85 struct asd_ascb *ascb = (void *) data; 91 struct asd_ascb *ascb = (void *)data;
92 struct tasklet_completion_status *tcs = ascb->uldd_task;
86 93
87 ASD_DPRINTK("%s: here\n", __FUNCTION__); 94 ASD_DPRINTK("%s: here\n", __FUNCTION__);
88 asd_timedout_common(data); 95 tcs->dl_opcode = TMF_RESP_FUNC_FAILED;
89 ascb->uldd_task = (void *) TMF_RESP_FUNC_FAILED; 96 complete(ascb->completion);
90 complete(&ascb->completion);
91} 97}
92 98
93#define CLEAR_NEXUS_PRE \ 99#define CLEAR_NEXUS_PRE \
100 struct asd_ascb *ascb; \
101 struct scb *scb; \
102 int res; \
103 DECLARE_COMPLETION_ONSTACK(completion); \
104 DECLARE_TCS(tcs); \
105 \
94 ASD_DPRINTK("%s: PRE\n", __FUNCTION__); \ 106 ASD_DPRINTK("%s: PRE\n", __FUNCTION__); \
95 res = 1; \ 107 res = 1; \
96 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \ 108 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); \
97 if (!ascb) \ 109 if (!ascb) \
98 return -ENOMEM; \ 110 return -ENOMEM; \
99 \ 111 \
112 ascb->completion = &completion; \
113 ascb->uldd_task = &tcs; \
100 scb = ascb->scb; \ 114 scb = ascb->scb; \
101 scb->header.opcode = CLEAR_NEXUS 115 scb->header.opcode = CLEAR_NEXUS
102 116
@@ -107,10 +121,11 @@ static void asd_clear_nexus_timedout(unsigned long data)
107 if (res) \ 121 if (res) \
108 goto out_err; \ 122 goto out_err; \
109 ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __FUNCTION__); \ 123 ASD_DPRINTK("%s: clear nexus posted, waiting...\n", __FUNCTION__); \
110 wait_for_completion(&ascb->completion); \ 124 wait_for_completion(&completion); \
111 res = (int) (unsigned long) ascb->uldd_task; \ 125 res = tcs.dl_opcode; \
112 if (res == TC_NO_ERROR) \ 126 if (res == TC_NO_ERROR) \
113 res = TMF_RESP_FUNC_COMPLETE; \ 127 res = TMF_RESP_FUNC_COMPLETE; \
128 return res; \
114out_err: \ 129out_err: \
115 asd_ascb_free(ascb); \ 130 asd_ascb_free(ascb); \
116 return res 131 return res
@@ -118,9 +133,6 @@ out_err: \
118int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha) 133int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha)
119{ 134{
120 struct asd_ha_struct *asd_ha = sas_ha->lldd_ha; 135 struct asd_ha_struct *asd_ha = sas_ha->lldd_ha;
121 struct asd_ascb *ascb;
122 struct scb *scb;
123 int res;
124 136
125 CLEAR_NEXUS_PRE; 137 CLEAR_NEXUS_PRE;
126 scb->clear_nexus.nexus = NEXUS_ADAPTER; 138 scb->clear_nexus.nexus = NEXUS_ADAPTER;
@@ -130,9 +142,6 @@ int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha)
130int asd_clear_nexus_port(struct asd_sas_port *port) 142int asd_clear_nexus_port(struct asd_sas_port *port)
131{ 143{
132 struct asd_ha_struct *asd_ha = port->ha->lldd_ha; 144 struct asd_ha_struct *asd_ha = port->ha->lldd_ha;
133 struct asd_ascb *ascb;
134 struct scb *scb;
135 int res;
136 145
137 CLEAR_NEXUS_PRE; 146 CLEAR_NEXUS_PRE;
138 scb->clear_nexus.nexus = NEXUS_PORT; 147 scb->clear_nexus.nexus = NEXUS_PORT;
@@ -140,29 +149,73 @@ int asd_clear_nexus_port(struct asd_sas_port *port)
140 CLEAR_NEXUS_POST; 149 CLEAR_NEXUS_POST;
141} 150}
142 151
143#if 0 152enum clear_nexus_phase {
144static int asd_clear_nexus_I_T(struct domain_device *dev) 153 NEXUS_PHASE_PRE,
154 NEXUS_PHASE_POST,
155 NEXUS_PHASE_RESUME,
156};
157
158static int asd_clear_nexus_I_T(struct domain_device *dev,
159 enum clear_nexus_phase phase)
145{ 160{
146 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 161 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
147 struct asd_ascb *ascb;
148 struct scb *scb;
149 int res;
150 162
151 CLEAR_NEXUS_PRE; 163 CLEAR_NEXUS_PRE;
152 scb->clear_nexus.nexus = NEXUS_I_T; 164 scb->clear_nexus.nexus = NEXUS_I_T;
153 scb->clear_nexus.flags = SEND_Q | EXEC_Q | NOTINQ; 165 switch (phase) {
166 case NEXUS_PHASE_PRE:
167 scb->clear_nexus.flags = EXEC_Q | SUSPEND_TX;
168 break;
169 case NEXUS_PHASE_POST:
170 scb->clear_nexus.flags = SEND_Q | NOTINQ;
171 break;
172 case NEXUS_PHASE_RESUME:
173 scb->clear_nexus.flags = RESUME_TX;
174 }
154 scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long) 175 scb->clear_nexus.conn_handle = cpu_to_le16((u16)(unsigned long)
155 dev->lldd_dev); 176 dev->lldd_dev);
156 CLEAR_NEXUS_POST; 177 CLEAR_NEXUS_POST;
157} 178}
158#endif 179
180int asd_I_T_nexus_reset(struct domain_device *dev)
181{
182 int res, tmp_res, i;
183 struct sas_phy *phy = sas_find_local_phy(dev);
184 /* Standard mandates link reset for ATA (type 0) and
185 * hard reset for SSP (type 1) */
186 int reset_type = (dev->dev_type == SATA_DEV ||
187 (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1;
188
189 asd_clear_nexus_I_T(dev, NEXUS_PHASE_PRE);
190 /* send a hard reset */
191 ASD_DPRINTK("sending %s reset to %s\n",
192 reset_type ? "hard" : "soft", phy->dev.bus_id);
193 res = sas_phy_reset(phy, reset_type);
194 if (res == TMF_RESP_FUNC_COMPLETE) {
195 /* wait for the maximum settle time */
196 msleep(500);
197 /* clear all outstanding commands (keep nexus suspended) */
198 asd_clear_nexus_I_T(dev, NEXUS_PHASE_POST);
199 }
200 for (i = 0 ; i < 3; i++) {
201 tmp_res = asd_clear_nexus_I_T(dev, NEXUS_PHASE_RESUME);
202 if (tmp_res == TC_RESUME)
203 return res;
204 msleep(500);
205 }
206
207 /* This is a bit of a problem: the sequencer is still suspended
208 * and is refusing to resume. Hope it will resume on a bigger hammer
209 * or the disk is lost */
210 dev_printk(KERN_ERR, &phy->dev,
211 "Failed to resume nexus after reset 0x%x\n", tmp_res);
212
213 return TMF_RESP_FUNC_FAILED;
214}
159 215
160static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun) 216static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun)
161{ 217{
162 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha; 218 struct asd_ha_struct *asd_ha = dev->port->ha->lldd_ha;
163 struct asd_ascb *ascb;
164 struct scb *scb;
165 int res;
166 219
167 CLEAR_NEXUS_PRE; 220 CLEAR_NEXUS_PRE;
168 scb->clear_nexus.nexus = NEXUS_I_T_L; 221 scb->clear_nexus.nexus = NEXUS_I_T_L;
@@ -177,9 +230,6 @@ static int asd_clear_nexus_tag(struct sas_task *task)
177{ 230{
178 struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha; 231 struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
179 struct asd_ascb *tascb = task->lldd_task; 232 struct asd_ascb *tascb = task->lldd_task;
180 struct asd_ascb *ascb;
181 struct scb *scb;
182 int res;
183 233
184 CLEAR_NEXUS_PRE; 234 CLEAR_NEXUS_PRE;
185 scb->clear_nexus.nexus = NEXUS_TAG; 235 scb->clear_nexus.nexus = NEXUS_TAG;
@@ -195,9 +245,6 @@ static int asd_clear_nexus_index(struct sas_task *task)
195{ 245{
196 struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha; 246 struct asd_ha_struct *asd_ha = task->dev->port->ha->lldd_ha;
197 struct asd_ascb *tascb = task->lldd_task; 247 struct asd_ascb *tascb = task->lldd_task;
198 struct asd_ascb *ascb;
199 struct scb *scb;
200 int res;
201 248
202 CLEAR_NEXUS_PRE; 249 CLEAR_NEXUS_PRE;
203 scb->clear_nexus.nexus = NEXUS_TRANS_CX; 250 scb->clear_nexus.nexus = NEXUS_TRANS_CX;
@@ -213,11 +260,11 @@ static int asd_clear_nexus_index(struct sas_task *task)
213static void asd_tmf_timedout(unsigned long data) 260static void asd_tmf_timedout(unsigned long data)
214{ 261{
215 struct asd_ascb *ascb = (void *) data; 262 struct asd_ascb *ascb = (void *) data;
263 struct tasklet_completion_status *tcs = ascb->uldd_task;
216 264
217 ASD_DPRINTK("tmf timed out\n"); 265 ASD_DPRINTK("tmf timed out\n");
218 asd_timedout_common(data); 266 tcs->tmf_state = TMF_RESP_FUNC_FAILED;
219 ascb->uldd_task = (void *) TMF_RESP_FUNC_FAILED; 267 complete(ascb->completion);
220 complete(&ascb->completion);
221} 268}
222 269
223static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb, 270static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb,
@@ -269,18 +316,24 @@ static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb,
269static void asd_tmf_tasklet_complete(struct asd_ascb *ascb, 316static void asd_tmf_tasklet_complete(struct asd_ascb *ascb,
270 struct done_list_struct *dl) 317 struct done_list_struct *dl)
271{ 318{
319 struct tasklet_completion_status *tcs;
320
272 if (!del_timer(&ascb->timer)) 321 if (!del_timer(&ascb->timer))
273 return; 322 return;
274 323
324 tcs = ascb->uldd_task;
275 ASD_DPRINTK("tmf tasklet complete\n"); 325 ASD_DPRINTK("tmf tasklet complete\n");
276 326
277 if (dl->opcode == TC_SSP_RESP) 327 tcs->dl_opcode = dl->opcode;
278 ascb->uldd_task = (void *) (unsigned long) 328
279 asd_get_tmf_resp_tasklet(ascb, dl); 329 if (dl->opcode == TC_SSP_RESP) {
280 else 330 tcs->tmf_state = asd_get_tmf_resp_tasklet(ascb, dl);
281 ascb->uldd_task = (void *) 0xFF00 + (unsigned long) dl->opcode; 331 tcs->tag_valid = ascb->tag_valid;
332 tcs->tag = ascb->tag;
333 }
282 334
283 complete(&ascb->completion); 335 complete(ascb->completion);
336 asd_ascb_free(ascb);
284} 337}
285 338
286static inline int asd_clear_nexus(struct sas_task *task) 339static inline int asd_clear_nexus(struct sas_task *task)
@@ -288,15 +341,19 @@ static inline int asd_clear_nexus(struct sas_task *task)
288 int res = TMF_RESP_FUNC_FAILED; 341 int res = TMF_RESP_FUNC_FAILED;
289 int leftover; 342 int leftover;
290 struct asd_ascb *tascb = task->lldd_task; 343 struct asd_ascb *tascb = task->lldd_task;
344 DECLARE_COMPLETION_ONSTACK(completion);
291 unsigned long flags; 345 unsigned long flags;
292 346
347 tascb->completion = &completion;
348
293 ASD_DPRINTK("task not done, clearing nexus\n"); 349 ASD_DPRINTK("task not done, clearing nexus\n");
294 if (tascb->tag_valid) 350 if (tascb->tag_valid)
295 res = asd_clear_nexus_tag(task); 351 res = asd_clear_nexus_tag(task);
296 else 352 else
297 res = asd_clear_nexus_index(task); 353 res = asd_clear_nexus_index(task);
298 leftover = wait_for_completion_timeout(&tascb->completion, 354 leftover = wait_for_completion_timeout(&completion,
299 AIC94XX_SCB_TIMEOUT); 355 AIC94XX_SCB_TIMEOUT);
356 tascb->completion = NULL;
300 ASD_DPRINTK("came back from clear nexus\n"); 357 ASD_DPRINTK("came back from clear nexus\n");
301 spin_lock_irqsave(&task->task_state_lock, flags); 358 spin_lock_irqsave(&task->task_state_lock, flags);
302 if (leftover < 1) 359 if (leftover < 1)
@@ -350,6 +407,11 @@ int asd_abort_task(struct sas_task *task)
350 struct asd_ascb *ascb = NULL; 407 struct asd_ascb *ascb = NULL;
351 struct scb *scb; 408 struct scb *scb;
352 int leftover; 409 int leftover;
410 DECLARE_TCS(tcs);
411 DECLARE_COMPLETION_ONSTACK(completion);
412 DECLARE_COMPLETION_ONSTACK(tascb_completion);
413
414 tascb->completion = &tascb_completion;
353 415
354 spin_lock_irqsave(&task->task_state_lock, flags); 416 spin_lock_irqsave(&task->task_state_lock, flags);
355 if (task->task_state_flags & SAS_TASK_STATE_DONE) { 417 if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -363,8 +425,10 @@ int asd_abort_task(struct sas_task *task)
363 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); 425 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
364 if (!ascb) 426 if (!ascb)
365 return -ENOMEM; 427 return -ENOMEM;
366 scb = ascb->scb;
367 428
429 ascb->uldd_task = &tcs;
430 ascb->completion = &completion;
431 scb = ascb->scb;
368 scb->header.opcode = SCB_ABORT_TASK; 432 scb->header.opcode = SCB_ABORT_TASK;
369 433
370 switch (task->task_proto) { 434 switch (task->task_proto) {
@@ -406,13 +470,12 @@ int asd_abort_task(struct sas_task *task)
406 res = asd_enqueue_internal(ascb, asd_tmf_tasklet_complete, 470 res = asd_enqueue_internal(ascb, asd_tmf_tasklet_complete,
407 asd_tmf_timedout); 471 asd_tmf_timedout);
408 if (res) 472 if (res)
409 goto out; 473 goto out_free;
410 wait_for_completion(&ascb->completion); 474 wait_for_completion(&completion);
411 ASD_DPRINTK("tmf came back\n"); 475 ASD_DPRINTK("tmf came back\n");
412 476
413 res = (int) (unsigned long) ascb->uldd_task; 477 tascb->tag = tcs.tag;
414 tascb->tag = ascb->tag; 478 tascb->tag_valid = tcs.tag_valid;
415 tascb->tag_valid = ascb->tag_valid;
416 479
417 spin_lock_irqsave(&task->task_state_lock, flags); 480 spin_lock_irqsave(&task->task_state_lock, flags);
418 if (task->task_state_flags & SAS_TASK_STATE_DONE) { 481 if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -423,63 +486,68 @@ int asd_abort_task(struct sas_task *task)
423 } 486 }
424 spin_unlock_irqrestore(&task->task_state_lock, flags); 487 spin_unlock_irqrestore(&task->task_state_lock, flags);
425 488
426 switch (res) { 489 if (tcs.dl_opcode == TC_SSP_RESP) {
427 /* The task to be aborted has been sent to the device. 490 /* The task to be aborted has been sent to the device.
428 * We got a Response IU for the ABORT TASK TMF. */ 491 * We got a Response IU for the ABORT TASK TMF. */
429 case TC_NO_ERROR + 0xFF00: 492 if (tcs.tmf_state == TMF_RESP_FUNC_COMPLETE)
430 case TMF_RESP_FUNC_COMPLETE: 493 res = asd_clear_nexus(task);
431 case TMF_RESP_FUNC_FAILED: 494 else
432 res = asd_clear_nexus(task); 495 res = tcs.tmf_state;
433 break; 496 } else if (tcs.dl_opcode == TC_NO_ERROR &&
434 case TMF_RESP_INVALID_FRAME: 497 tcs.tmf_state == TMF_RESP_FUNC_FAILED) {
435 case TMF_RESP_OVERLAPPED_TAG: 498 /* timeout */
436 case TMF_RESP_FUNC_ESUPP:
437 case TMF_RESP_NO_LUN:
438 goto out_done; break;
439 }
440 /* In the following we assume that the managing layer
441 * will _never_ make a mistake, when issuing ABORT TASK.
442 */
443 switch (res) {
444 default:
445 res = asd_clear_nexus(task);
446 /* fallthrough */
447 case TC_NO_ERROR + 0xFF00:
448 case TMF_RESP_FUNC_COMPLETE:
449 break;
450 /* The task hasn't been sent to the device xor we never got
451 * a (sane) Response IU for the ABORT TASK TMF.
452 */
453 case TF_NAK_RECV + 0xFF00:
454 res = TMF_RESP_INVALID_FRAME;
455 break;
456 case TF_TMF_TASK_DONE + 0xFF00: /* done but not reported yet */
457 res = TMF_RESP_FUNC_FAILED; 499 res = TMF_RESP_FUNC_FAILED;
458 leftover = wait_for_completion_timeout(&tascb->completion, 500 } else {
459 AIC94XX_SCB_TIMEOUT); 501 /* In the following we assume that the managing layer
460 spin_lock_irqsave(&task->task_state_lock, flags); 502 * will _never_ make a mistake, when issuing ABORT
461 if (leftover < 1) 503 * TASK.
504 */
505 switch (tcs.dl_opcode) {
506 default:
507 res = asd_clear_nexus(task);
508 /* fallthrough */
509 case TC_NO_ERROR:
510 break;
511 /* The task hasn't been sent to the device xor
512 * we never got a (sane) Response IU for the
513 * ABORT TASK TMF.
514 */
515 case TF_NAK_RECV:
516 res = TMF_RESP_INVALID_FRAME;
517 break;
518 case TF_TMF_TASK_DONE: /* done but not reported yet */
462 res = TMF_RESP_FUNC_FAILED; 519 res = TMF_RESP_FUNC_FAILED;
463 if (task->task_state_flags & SAS_TASK_STATE_DONE) 520 leftover =
521 wait_for_completion_timeout(&tascb_completion,
522 AIC94XX_SCB_TIMEOUT);
523 spin_lock_irqsave(&task->task_state_lock, flags);
524 if (leftover < 1)
525 res = TMF_RESP_FUNC_FAILED;
526 if (task->task_state_flags & SAS_TASK_STATE_DONE)
527 res = TMF_RESP_FUNC_COMPLETE;
528 spin_unlock_irqrestore(&task->task_state_lock, flags);
529 break;
530 case TF_TMF_NO_TAG:
531 case TF_TMF_TAG_FREE: /* the tag is in the free list */
532 case TF_TMF_NO_CONN_HANDLE: /* no such device */
464 res = TMF_RESP_FUNC_COMPLETE; 533 res = TMF_RESP_FUNC_COMPLETE;
465 spin_unlock_irqrestore(&task->task_state_lock, flags); 534 break;
466 goto out_done; 535 case TF_TMF_NO_CTX: /* not in seq, or proto != SSP */
467 case TF_TMF_NO_TAG + 0xFF00: 536 res = TMF_RESP_FUNC_ESUPP;
468 case TF_TMF_TAG_FREE + 0xFF00: /* the tag is in the free list */ 537 break;
469 case TF_TMF_NO_CONN_HANDLE + 0xFF00: /* no such device */ 538 }
470 res = TMF_RESP_FUNC_COMPLETE;
471 goto out_done;
472 case TF_TMF_NO_CTX + 0xFF00: /* not in seq, or proto != SSP */
473 res = TMF_RESP_FUNC_ESUPP;
474 goto out;
475 } 539 }
476out_done: 540 out_done:
541 tascb->completion = NULL;
477 if (res == TMF_RESP_FUNC_COMPLETE) { 542 if (res == TMF_RESP_FUNC_COMPLETE) {
478 task->lldd_task = NULL; 543 task->lldd_task = NULL;
479 mb(); 544 mb();
480 asd_ascb_free(tascb); 545 asd_ascb_free(tascb);
481 } 546 }
482out: 547 ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res);
548 return res;
549
550 out_free:
483 asd_ascb_free(ascb); 551 asd_ascb_free(ascb);
484 ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res); 552 ASD_DPRINTK("task 0x%p aborted, res: 0x%x\n", task, res);
485 return res; 553 return res;
@@ -507,6 +575,8 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
507 struct asd_ascb *ascb; 575 struct asd_ascb *ascb;
508 int res = 1; 576 int res = 1;
509 struct scb *scb; 577 struct scb *scb;
578 DECLARE_COMPLETION_ONSTACK(completion);
579 DECLARE_TCS(tcs);
510 580
511 if (!(dev->tproto & SAS_PROTOCOL_SSP)) 581 if (!(dev->tproto & SAS_PROTOCOL_SSP))
512 return TMF_RESP_FUNC_ESUPP; 582 return TMF_RESP_FUNC_ESUPP;
@@ -514,6 +584,9 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
514 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL); 584 ascb = asd_ascb_alloc_list(asd_ha, &res, GFP_KERNEL);
515 if (!ascb) 585 if (!ascb)
516 return -ENOMEM; 586 return -ENOMEM;
587
588 ascb->completion = &completion;
589 ascb->uldd_task = &tcs;
517 scb = ascb->scb; 590 scb = ascb->scb;
518 591
519 if (tmf == TMF_QUERY_TASK) 592 if (tmf == TMF_QUERY_TASK)
@@ -546,31 +619,32 @@ static int asd_initiate_ssp_tmf(struct domain_device *dev, u8 *lun,
546 asd_tmf_timedout); 619 asd_tmf_timedout);
547 if (res) 620 if (res)
548 goto out_err; 621 goto out_err;
549 wait_for_completion(&ascb->completion); 622 wait_for_completion(&completion);
550 res = (int) (unsigned long) ascb->uldd_task;
551 623
552 switch (res) { 624 switch (tcs.dl_opcode) {
553 case TC_NO_ERROR + 0xFF00: 625 case TC_NO_ERROR:
554 res = TMF_RESP_FUNC_COMPLETE; 626 res = TMF_RESP_FUNC_COMPLETE;
555 break; 627 break;
556 case TF_NAK_RECV + 0xFF00: 628 case TF_NAK_RECV:
557 res = TMF_RESP_INVALID_FRAME; 629 res = TMF_RESP_INVALID_FRAME;
558 break; 630 break;
559 case TF_TMF_TASK_DONE + 0xFF00: 631 case TF_TMF_TASK_DONE:
560 res = TMF_RESP_FUNC_FAILED; 632 res = TMF_RESP_FUNC_FAILED;
561 break; 633 break;
562 case TF_TMF_NO_TAG + 0xFF00: 634 case TF_TMF_NO_TAG:
563 case TF_TMF_TAG_FREE + 0xFF00: /* the tag is in the free list */ 635 case TF_TMF_TAG_FREE: /* the tag is in the free list */
564 case TF_TMF_NO_CONN_HANDLE + 0xFF00: /* no such device */ 636 case TF_TMF_NO_CONN_HANDLE: /* no such device */
565 res = TMF_RESP_FUNC_COMPLETE; 637 res = TMF_RESP_FUNC_COMPLETE;
566 break; 638 break;
567 case TF_TMF_NO_CTX + 0xFF00: /* not in seq, or proto != SSP */ 639 case TF_TMF_NO_CTX: /* not in seq, or proto != SSP */
568 res = TMF_RESP_FUNC_ESUPP; 640 res = TMF_RESP_FUNC_ESUPP;
569 break; 641 break;
570 default: 642 default:
571 /* Allow TMF response codes to propagate upwards */ 643 /* Allow TMF response codes to propagate upwards */
644 res = tcs.dl_opcode;
572 break; 645 break;
573 } 646 }
647 return res;
574out_err: 648out_err:
575 asd_ascb_free(ascb); 649 asd_ascb_free(ascb);
576 return res; 650 return res;