diff options
Diffstat (limited to 'drivers/scsi')
26 files changed, 372 insertions, 329 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); | |||
102 | int asd_clear_aca(struct domain_device *, u8 *lun); | 102 | int asd_clear_aca(struct domain_device *, u8 *lun); |
103 | int asd_clear_task_set(struct domain_device *, u8 *lun); | 103 | int asd_clear_task_set(struct domain_device *, u8 *lun); |
104 | int asd_lu_reset(struct domain_device *, u8 *lun); | 104 | int asd_lu_reset(struct domain_device *, u8 *lun); |
105 | int asd_I_T_nexus_reset(struct domain_device *dev); | ||
105 | int asd_query_task(struct sas_task *); | 106 | int 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 | ||
56 | static 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); | 58 | struct 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 | ||
70 | static void asd_clear_nexus_tasklet_complete(struct asd_ascb *ascb, | 74 | static 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 | ||
83 | static void asd_clear_nexus_timedout(unsigned long data) | 89 | static 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; \ | ||
114 | out_err: \ | 129 | out_err: \ |
115 | asd_ascb_free(ascb); \ | 130 | asd_ascb_free(ascb); \ |
116 | return res | 131 | return res |
@@ -118,9 +133,6 @@ out_err: \ | |||
118 | int asd_clear_nexus_ha(struct sas_ha_struct *sas_ha) | 133 | int 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) | |||
130 | int asd_clear_nexus_port(struct asd_sas_port *port) | 142 | int 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 | 152 | enum clear_nexus_phase { |
144 | static int asd_clear_nexus_I_T(struct domain_device *dev) | 153 | NEXUS_PHASE_PRE, |
154 | NEXUS_PHASE_POST, | ||
155 | NEXUS_PHASE_RESUME, | ||
156 | }; | ||
157 | |||
158 | static 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 | |
180 | int 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 | ||
160 | static int asd_clear_nexus_I_T_L(struct domain_device *dev, u8 *lun) | 216 | static 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) | |||
213 | static void asd_tmf_timedout(unsigned long data) | 260 | static 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 | ||
223 | static int asd_get_tmf_resp_tasklet(struct asd_ascb *ascb, | 270 | static 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, | |||
269 | static void asd_tmf_tasklet_complete(struct asd_ascb *ascb, | 316 | static 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 | ||
286 | static inline int asd_clear_nexus(struct sas_task *task) | 339 | static 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 | } |
476 | out_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 | } |
482 | out: | 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; | ||
574 | out_err: | 648 | out_err: |
575 | asd_ascb_free(ascb); | 649 | asd_ascb_free(ascb); |
576 | return res; | 650 | return res; |
diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index 57786502e3ec..0393707bdfce 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h | |||
@@ -48,7 +48,7 @@ struct class_device_attribute; | |||
48 | /*The limit of outstanding scsi command that firmware can handle*/ | 48 | /*The limit of outstanding scsi command that firmware can handle*/ |
49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 | 49 | #define ARCMSR_MAX_OUTSTANDING_CMD 256 |
50 | #define ARCMSR_MAX_FREECCB_NUM 320 | 50 | #define ARCMSR_MAX_FREECCB_NUM 320 |
51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/12/24" | 51 | #define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2008/02/27" |
52 | #define ARCMSR_SCSI_INITIATOR_ID 255 | 52 | #define ARCMSR_SCSI_INITIATOR_ID 255 |
53 | #define ARCMSR_MAX_XFER_SECTORS 512 | 53 | #define ARCMSR_MAX_XFER_SECTORS 512 |
54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 | 54 | #define ARCMSR_MAX_XFER_SECTORS_B 4096 |
diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 6d67f5c0eb8e..27ebd336409b 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c | |||
@@ -160,7 +160,7 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application, | |||
160 | static void gdth_clear_events(void); | 160 | static void gdth_clear_events(void); |
161 | 161 | ||
162 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | 162 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, |
163 | char *buffer, ushort count, int to_buffer); | 163 | char *buffer, ushort count); |
164 | static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); | 164 | static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); |
165 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); | 165 | static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); |
166 | 166 | ||
@@ -182,7 +182,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, | |||
182 | unsigned int cmd, unsigned long arg); | 182 | unsigned int cmd, unsigned long arg); |
183 | 183 | ||
184 | static void gdth_flush(gdth_ha_str *ha); | 184 | static void gdth_flush(gdth_ha_str *ha); |
185 | static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); | ||
186 | static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); | 185 | static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); |
187 | static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, | 186 | static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, |
188 | struct gdth_cmndinfo *cmndinfo); | 187 | struct gdth_cmndinfo *cmndinfo); |
@@ -417,12 +416,6 @@ static inline void gdth_set_sglist(struct scsi_cmnd *cmd, | |||
417 | #include "gdth_proc.h" | 416 | #include "gdth_proc.h" |
418 | #include "gdth_proc.c" | 417 | #include "gdth_proc.c" |
419 | 418 | ||
420 | /* notifier block to get a notify on system shutdown/halt/reboot */ | ||
421 | static struct notifier_block gdth_notifier = { | ||
422 | gdth_halt, NULL, 0 | ||
423 | }; | ||
424 | static int notifier_disabled = 0; | ||
425 | |||
426 | static gdth_ha_str *gdth_find_ha(int hanum) | 419 | static gdth_ha_str *gdth_find_ha(int hanum) |
427 | { | 420 | { |
428 | gdth_ha_str *ha; | 421 | gdth_ha_str *ha; |
@@ -445,8 +438,8 @@ static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha) | |||
445 | for (i=0; i<GDTH_MAXCMDS; ++i) { | 438 | for (i=0; i<GDTH_MAXCMDS; ++i) { |
446 | if (ha->cmndinfo[i].index == 0) { | 439 | if (ha->cmndinfo[i].index == 0) { |
447 | priv = &ha->cmndinfo[i]; | 440 | priv = &ha->cmndinfo[i]; |
448 | priv->index = i+1; | ||
449 | memset(priv, 0, sizeof(*priv)); | 441 | memset(priv, 0, sizeof(*priv)); |
442 | priv->index = i+1; | ||
450 | break; | 443 | break; |
451 | } | 444 | } |
452 | } | 445 | } |
@@ -493,7 +486,6 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, | |||
493 | gdth_ha_str *ha = shost_priv(sdev->host); | 486 | gdth_ha_str *ha = shost_priv(sdev->host); |
494 | Scsi_Cmnd *scp; | 487 | Scsi_Cmnd *scp; |
495 | struct gdth_cmndinfo cmndinfo; | 488 | struct gdth_cmndinfo cmndinfo; |
496 | struct scatterlist one_sg; | ||
497 | DECLARE_COMPLETION_ONSTACK(wait); | 489 | DECLARE_COMPLETION_ONSTACK(wait); |
498 | int rval; | 490 | int rval; |
499 | 491 | ||
@@ -507,13 +499,10 @@ int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, | |||
507 | /* use request field to save the ptr. to completion struct. */ | 499 | /* use request field to save the ptr. to completion struct. */ |
508 | scp->request = (struct request *)&wait; | 500 | scp->request = (struct request *)&wait; |
509 | scp->timeout_per_command = timeout*HZ; | 501 | scp->timeout_per_command = timeout*HZ; |
510 | sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd)); | ||
511 | gdth_set_sglist(scp, &one_sg); | ||
512 | gdth_set_sg_count(scp, 1); | ||
513 | gdth_set_bufflen(scp, sizeof(*gdtcmd)); | ||
514 | scp->cmd_len = 12; | 502 | scp->cmd_len = 12; |
515 | memcpy(scp->cmnd, cmnd, 12); | 503 | memcpy(scp->cmnd, cmnd, 12); |
516 | cmndinfo.priority = IOCTL_PRI; | 504 | cmndinfo.priority = IOCTL_PRI; |
505 | cmndinfo.internal_cmd_str = gdtcmd; | ||
517 | cmndinfo.internal_command = 1; | 506 | cmndinfo.internal_command = 1; |
518 | 507 | ||
519 | TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0])); | 508 | TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0])); |
@@ -2355,7 +2344,7 @@ static void gdth_next(gdth_ha_str *ha) | |||
2355 | * buffers, kmap_atomic() as needed. | 2344 | * buffers, kmap_atomic() as needed. |
2356 | */ | 2345 | */ |
2357 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | 2346 | static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, |
2358 | char *buffer, ushort count, int to_buffer) | 2347 | char *buffer, ushort count) |
2359 | { | 2348 | { |
2360 | ushort cpcount,i, max_sg = gdth_sg_count(scp); | 2349 | ushort cpcount,i, max_sg = gdth_sg_count(scp); |
2361 | ushort cpsum,cpnow; | 2350 | ushort cpsum,cpnow; |
@@ -2381,10 +2370,7 @@ static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, | |||
2381 | } | 2370 | } |
2382 | local_irq_save(flags); | 2371 | local_irq_save(flags); |
2383 | address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset; | 2372 | address = kmap_atomic(sg_page(sl), KM_BIO_SRC_IRQ) + sl->offset; |
2384 | if (to_buffer) | 2373 | memcpy(address, buffer, cpnow); |
2385 | memcpy(buffer, address, cpnow); | ||
2386 | else | ||
2387 | memcpy(address, buffer, cpnow); | ||
2388 | flush_dcache_page(sg_page(sl)); | 2374 | flush_dcache_page(sg_page(sl)); |
2389 | kunmap_atomic(address, KM_BIO_SRC_IRQ); | 2375 | kunmap_atomic(address, KM_BIO_SRC_IRQ); |
2390 | local_irq_restore(flags); | 2376 | local_irq_restore(flags); |
@@ -2438,7 +2424,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
2438 | strcpy(inq.vendor,ha->oem_name); | 2424 | strcpy(inq.vendor,ha->oem_name); |
2439 | sprintf(inq.product,"Host Drive #%02d",t); | 2425 | sprintf(inq.product,"Host Drive #%02d",t); |
2440 | strcpy(inq.revision," "); | 2426 | strcpy(inq.revision," "); |
2441 | gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0); | 2427 | gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data)); |
2442 | break; | 2428 | break; |
2443 | 2429 | ||
2444 | case REQUEST_SENSE: | 2430 | case REQUEST_SENSE: |
@@ -2448,7 +2434,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
2448 | sd.key = NO_SENSE; | 2434 | sd.key = NO_SENSE; |
2449 | sd.info = 0; | 2435 | sd.info = 0; |
2450 | sd.add_length= 0; | 2436 | sd.add_length= 0; |
2451 | gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0); | 2437 | gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data)); |
2452 | break; | 2438 | break; |
2453 | 2439 | ||
2454 | case MODE_SENSE: | 2440 | case MODE_SENSE: |
@@ -2460,7 +2446,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
2460 | mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; | 2446 | mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; |
2461 | mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; | 2447 | mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; |
2462 | mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); | 2448 | mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); |
2463 | gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0); | 2449 | gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data)); |
2464 | break; | 2450 | break; |
2465 | 2451 | ||
2466 | case READ_CAPACITY: | 2452 | case READ_CAPACITY: |
@@ -2470,7 +2456,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
2470 | else | 2456 | else |
2471 | rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); | 2457 | rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); |
2472 | rdc.block_length = cpu_to_be32(SECTOR_SIZE); | 2458 | rdc.block_length = cpu_to_be32(SECTOR_SIZE); |
2473 | gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0); | 2459 | gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data)); |
2474 | break; | 2460 | break; |
2475 | 2461 | ||
2476 | case SERVICE_ACTION_IN: | 2462 | case SERVICE_ACTION_IN: |
@@ -2482,7 +2468,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
2482 | rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); | 2468 | rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); |
2483 | rdc16.block_length = cpu_to_be32(SECTOR_SIZE); | 2469 | rdc16.block_length = cpu_to_be32(SECTOR_SIZE); |
2484 | gdth_copy_internal_data(ha, scp, (char*)&rdc16, | 2470 | gdth_copy_internal_data(ha, scp, (char*)&rdc16, |
2485 | sizeof(gdth_rdcap16_data), 0); | 2471 | sizeof(gdth_rdcap16_data)); |
2486 | } else { | 2472 | } else { |
2487 | scp->result = DID_ABORT << 16; | 2473 | scp->result = DID_ABORT << 16; |
2488 | } | 2474 | } |
@@ -2852,6 +2838,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) | |||
2852 | static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | 2838 | static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) |
2853 | { | 2839 | { |
2854 | register gdth_cmd_str *cmdp; | 2840 | register gdth_cmd_str *cmdp; |
2841 | struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); | ||
2855 | int cmd_index; | 2842 | int cmd_index; |
2856 | 2843 | ||
2857 | cmdp= ha->pccb; | 2844 | cmdp= ha->pccb; |
@@ -2860,7 +2847,7 @@ static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) | |||
2860 | if (ha->type==GDT_EISA && ha->cmd_cnt>0) | 2847 | if (ha->type==GDT_EISA && ha->cmd_cnt>0) |
2861 | return 0; | 2848 | return 0; |
2862 | 2849 | ||
2863 | gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1); | 2850 | *cmdp = *cmndinfo->internal_cmd_str; |
2864 | cmdp->RequestBuffer = scp; | 2851 | cmdp->RequestBuffer = scp; |
2865 | 2852 | ||
2866 | /* search free command index */ | 2853 | /* search free command index */ |
@@ -3794,6 +3781,8 @@ static void gdth_timeout(ulong data) | |||
3794 | gdth_ha_str *ha; | 3781 | gdth_ha_str *ha; |
3795 | ulong flags; | 3782 | ulong flags; |
3796 | 3783 | ||
3784 | BUG_ON(list_empty(&gdth_instances)); | ||
3785 | |||
3797 | ha = list_first_entry(&gdth_instances, gdth_ha_str, list); | 3786 | ha = list_first_entry(&gdth_instances, gdth_ha_str, list); |
3798 | spin_lock_irqsave(&ha->smp_lock, flags); | 3787 | spin_lock_irqsave(&ha->smp_lock, flags); |
3799 | 3788 | ||
@@ -4669,45 +4658,6 @@ static void gdth_flush(gdth_ha_str *ha) | |||
4669 | } | 4658 | } |
4670 | } | 4659 | } |
4671 | 4660 | ||
4672 | /* shutdown routine */ | ||
4673 | static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) | ||
4674 | { | ||
4675 | gdth_ha_str *ha; | ||
4676 | #ifndef __alpha__ | ||
4677 | gdth_cmd_str gdtcmd; | ||
4678 | char cmnd[MAX_COMMAND_SIZE]; | ||
4679 | #endif | ||
4680 | |||
4681 | if (notifier_disabled) | ||
4682 | return NOTIFY_OK; | ||
4683 | |||
4684 | TRACE2(("gdth_halt() event %d\n",(int)event)); | ||
4685 | if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) | ||
4686 | return NOTIFY_DONE; | ||
4687 | |||
4688 | notifier_disabled = 1; | ||
4689 | printk("GDT-HA: Flushing all host drives .. "); | ||
4690 | list_for_each_entry(ha, &gdth_instances, list) { | ||
4691 | gdth_flush(ha); | ||
4692 | |||
4693 | #ifndef __alpha__ | ||
4694 | /* controller reset */ | ||
4695 | memset(cmnd, 0xff, MAX_COMMAND_SIZE); | ||
4696 | gdtcmd.BoardNode = LOCALBOARD; | ||
4697 | gdtcmd.Service = CACHESERVICE; | ||
4698 | gdtcmd.OpCode = GDT_RESET; | ||
4699 | TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum)); | ||
4700 | gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL); | ||
4701 | #endif | ||
4702 | } | ||
4703 | printk("Done.\n"); | ||
4704 | |||
4705 | #ifdef GDTH_STATISTICS | ||
4706 | del_timer(&gdth_timer); | ||
4707 | #endif | ||
4708 | return NOTIFY_OK; | ||
4709 | } | ||
4710 | |||
4711 | /* configure lun */ | 4661 | /* configure lun */ |
4712 | static int gdth_slave_configure(struct scsi_device *sdev) | 4662 | static int gdth_slave_configure(struct scsi_device *sdev) |
4713 | { | 4663 | { |
@@ -5142,13 +5092,13 @@ static void gdth_remove_one(gdth_ha_str *ha) | |||
5142 | 5092 | ||
5143 | scsi_remove_host(shp); | 5093 | scsi_remove_host(shp); |
5144 | 5094 | ||
5095 | gdth_flush(ha); | ||
5096 | |||
5145 | if (ha->sdev) { | 5097 | if (ha->sdev) { |
5146 | scsi_free_host_dev(ha->sdev); | 5098 | scsi_free_host_dev(ha->sdev); |
5147 | ha->sdev = NULL; | 5099 | ha->sdev = NULL; |
5148 | } | 5100 | } |
5149 | 5101 | ||
5150 | gdth_flush(ha); | ||
5151 | |||
5152 | if (shp->irq) | 5102 | if (shp->irq) |
5153 | free_irq(shp->irq,ha); | 5103 | free_irq(shp->irq,ha); |
5154 | 5104 | ||
@@ -5174,6 +5124,24 @@ static void gdth_remove_one(gdth_ha_str *ha) | |||
5174 | scsi_host_put(shp); | 5124 | scsi_host_put(shp); |
5175 | } | 5125 | } |
5176 | 5126 | ||
5127 | static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) | ||
5128 | { | ||
5129 | gdth_ha_str *ha; | ||
5130 | |||
5131 | TRACE2(("gdth_halt() event %d\n", (int)event)); | ||
5132 | if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF) | ||
5133 | return NOTIFY_DONE; | ||
5134 | |||
5135 | list_for_each_entry(ha, &gdth_instances, list) | ||
5136 | gdth_flush(ha); | ||
5137 | |||
5138 | return NOTIFY_OK; | ||
5139 | } | ||
5140 | |||
5141 | static struct notifier_block gdth_notifier = { | ||
5142 | gdth_halt, NULL, 0 | ||
5143 | }; | ||
5144 | |||
5177 | static int __init gdth_init(void) | 5145 | static int __init gdth_init(void) |
5178 | { | 5146 | { |
5179 | if (disable) { | 5147 | if (disable) { |
@@ -5236,7 +5204,6 @@ static int __init gdth_init(void) | |||
5236 | add_timer(&gdth_timer); | 5204 | add_timer(&gdth_timer); |
5237 | #endif | 5205 | #endif |
5238 | major = register_chrdev(0,"gdth", &gdth_fops); | 5206 | major = register_chrdev(0,"gdth", &gdth_fops); |
5239 | notifier_disabled = 0; | ||
5240 | register_reboot_notifier(&gdth_notifier); | 5207 | register_reboot_notifier(&gdth_notifier); |
5241 | gdth_polling = FALSE; | 5208 | gdth_polling = FALSE; |
5242 | return 0; | 5209 | return 0; |
@@ -5246,14 +5213,15 @@ static void __exit gdth_exit(void) | |||
5246 | { | 5213 | { |
5247 | gdth_ha_str *ha; | 5214 | gdth_ha_str *ha; |
5248 | 5215 | ||
5249 | list_for_each_entry(ha, &gdth_instances, list) | 5216 | unregister_chrdev(major, "gdth"); |
5250 | gdth_remove_one(ha); | 5217 | unregister_reboot_notifier(&gdth_notifier); |
5251 | 5218 | ||
5252 | #ifdef GDTH_STATISTICS | 5219 | #ifdef GDTH_STATISTICS |
5253 | del_timer(&gdth_timer); | 5220 | del_timer_sync(&gdth_timer); |
5254 | #endif | 5221 | #endif |
5255 | unregister_chrdev(major,"gdth"); | 5222 | |
5256 | unregister_reboot_notifier(&gdth_notifier); | 5223 | list_for_each_entry(ha, &gdth_instances, list) |
5224 | gdth_remove_one(ha); | ||
5257 | } | 5225 | } |
5258 | 5226 | ||
5259 | module_init(gdth_init); | 5227 | module_init(gdth_init); |
diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 1434c6b0297c..26e4e92515e0 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h | |||
@@ -915,6 +915,7 @@ typedef struct { | |||
915 | struct gdth_cmndinfo { /* per-command private info */ | 915 | struct gdth_cmndinfo { /* per-command private info */ |
916 | int index; | 916 | int index; |
917 | int internal_command; /* don't call scsi_done */ | 917 | int internal_command; /* don't call scsi_done */ |
918 | gdth_cmd_str *internal_cmd_str; /* crier for internal messages*/ | ||
918 | dma_addr_t sense_paddr; /* sense dma-addr */ | 919 | dma_addr_t sense_paddr; /* sense dma-addr */ |
919 | unchar priority; | 920 | unchar priority; |
920 | int timeout; | 921 | int timeout; |
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index bd62131b97a1..e5881e92d0fb 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c | |||
@@ -290,7 +290,7 @@ static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, | |||
290 | int err = 0; | 290 | int err = 0; |
291 | 291 | ||
292 | dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], | 292 | dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], |
293 | cmd->usg_sg); | 293 | scsi_sg_count(sc)); |
294 | 294 | ||
295 | if (scsi_sg_count(sc)) | 295 | if (scsi_sg_count(sc)) |
296 | err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); | 296 | err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); |
@@ -838,9 +838,6 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) | |||
838 | if (!shost) | 838 | if (!shost) |
839 | goto free_vport; | 839 | goto free_vport; |
840 | shost->transportt = ibmvstgt_transport_template; | 840 | shost->transportt = ibmvstgt_transport_template; |
841 | err = scsi_tgt_alloc_queue(shost); | ||
842 | if (err) | ||
843 | goto put_host; | ||
844 | 841 | ||
845 | target = host_to_srp_target(shost); | 842 | target = host_to_srp_target(shost); |
846 | target->shost = shost; | 843 | target->shost = shost; |
@@ -872,6 +869,10 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) | |||
872 | if (err) | 869 | if (err) |
873 | goto destroy_queue; | 870 | goto destroy_queue; |
874 | 871 | ||
872 | err = scsi_tgt_alloc_queue(shost); | ||
873 | if (err) | ||
874 | goto destroy_queue; | ||
875 | |||
875 | return 0; | 876 | return 0; |
876 | destroy_queue: | 877 | destroy_queue: |
877 | crq_queue_destroy(target); | 878 | crq_queue_destroy(target); |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 59f8445eab0d..bdd7de7da39a 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -1708,8 +1708,8 @@ iscsi_session_setup(struct iscsi_transport *iscsit, | |||
1708 | qdepth = ISCSI_DEF_CMD_PER_LUN; | 1708 | qdepth = ISCSI_DEF_CMD_PER_LUN; |
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | if (!is_power_of_2(cmds_max) || | 1711 | if (!is_power_of_2(cmds_max) || cmds_max >= ISCSI_MGMT_ITT_OFFSET || |
1712 | cmds_max >= ISCSI_MGMT_ITT_OFFSET) { | 1712 | cmds_max < 2) { |
1713 | if (cmds_max != 0) | 1713 | if (cmds_max != 0) |
1714 | printk(KERN_ERR "iscsi: invalid can_queue of %d. " | 1714 | printk(KERN_ERR "iscsi: invalid can_queue of %d. " |
1715 | "can_queue must be a power of 2 and between " | 1715 | "can_queue must be a power of 2 and between " |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 7cd05b599a12..b0e5ac372a32 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
@@ -236,12 +236,12 @@ static void sas_ata_phy_reset(struct ata_port *ap) | |||
236 | struct domain_device *dev = ap->private_data; | 236 | struct domain_device *dev = ap->private_data; |
237 | struct sas_internal *i = | 237 | struct sas_internal *i = |
238 | to_sas_internal(dev->port->ha->core.shost->transportt); | 238 | to_sas_internal(dev->port->ha->core.shost->transportt); |
239 | int res = 0; | 239 | int res = TMF_RESP_FUNC_FAILED; |
240 | 240 | ||
241 | if (i->dft->lldd_I_T_nexus_reset) | 241 | if (i->dft->lldd_I_T_nexus_reset) |
242 | res = i->dft->lldd_I_T_nexus_reset(dev); | 242 | res = i->dft->lldd_I_T_nexus_reset(dev); |
243 | 243 | ||
244 | if (res) | 244 | if (res != TMF_RESP_FUNC_COMPLETE) |
245 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__); | 245 | SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __FUNCTION__); |
246 | 246 | ||
247 | switch (dev->sata_dev.command_set) { | 247 | switch (dev->sata_dev.command_set) { |
@@ -656,21 +656,6 @@ out: | |||
656 | return res; | 656 | return res; |
657 | } | 657 | } |
658 | 658 | ||
659 | static void sas_sata_propagate_sas_addr(struct domain_device *dev) | ||
660 | { | ||
661 | unsigned long flags; | ||
662 | struct asd_sas_port *port = dev->port; | ||
663 | struct asd_sas_phy *phy; | ||
664 | |||
665 | BUG_ON(dev->parent); | ||
666 | |||
667 | memcpy(port->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
668 | spin_lock_irqsave(&port->phy_list_lock, flags); | ||
669 | list_for_each_entry(phy, &port->phy_list, port_phy_el) | ||
670 | memcpy(phy->attached_sas_addr, dev->sas_addr, SAS_ADDR_SIZE); | ||
671 | spin_unlock_irqrestore(&port->phy_list_lock, flags); | ||
672 | } | ||
673 | |||
674 | #define ATA_IDENTIFY_DEV 0xEC | 659 | #define ATA_IDENTIFY_DEV 0xEC |
675 | #define ATA_IDENTIFY_PACKET_DEV 0xA1 | 660 | #define ATA_IDENTIFY_PACKET_DEV 0xA1 |
676 | #define ATA_SET_FEATURES 0xEF | 661 | #define ATA_SET_FEATURES 0xEF |
@@ -728,26 +713,6 @@ static int sas_discover_sata_dev(struct domain_device *dev) | |||
728 | goto out_err; | 713 | goto out_err; |
729 | } | 714 | } |
730 | cont1: | 715 | cont1: |
731 | /* Get WWN */ | ||
732 | if (dev->port->oob_mode != SATA_OOB_MODE) { | ||
733 | memcpy(dev->sas_addr, dev->sata_dev.rps_resp.rps.stp_sas_addr, | ||
734 | SAS_ADDR_SIZE); | ||
735 | } else if (dev->sata_dev.command_set == ATA_COMMAND_SET && | ||
736 | (le16_to_cpu(dev->sata_dev.identify_device[108]) & 0xF000) | ||
737 | == 0x5000) { | ||
738 | int i; | ||
739 | |||
740 | for (i = 0; i < 4; i++) { | ||
741 | dev->sas_addr[2*i] = | ||
742 | (le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0xFF00) >> 8; | ||
743 | dev->sas_addr[2*i+1] = | ||
744 | le16_to_cpu(dev->sata_dev.identify_device[108+i]) & 0x00FF; | ||
745 | } | ||
746 | } | ||
747 | sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); | ||
748 | if (!dev->parent) | ||
749 | sas_sata_propagate_sas_addr(dev); | ||
750 | |||
751 | /* XXX Hint: register this SATA device with SATL. | 716 | /* XXX Hint: register this SATA device with SATL. |
752 | When this returns, dev->sata_dev->lu is alive and | 717 | When this returns, dev->sata_dev->lu is alive and |
753 | present. | 718 | present. |
diff --git a/drivers/scsi/libsas/sas_port.c b/drivers/scsi/libsas/sas_port.c index e1e2d085c920..39ae68a3b0ef 100644 --- a/drivers/scsi/libsas/sas_port.c +++ b/drivers/scsi/libsas/sas_port.c | |||
@@ -92,9 +92,6 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
92 | if (!port->phy) | 92 | if (!port->phy) |
93 | port->phy = phy->phy; | 93 | port->phy = phy->phy; |
94 | 94 | ||
95 | SAS_DPRINTK("phy%d added to port%d, phy_mask:0x%x\n", phy->id, | ||
96 | port->id, port->phy_mask); | ||
97 | |||
98 | if (*(u64 *)port->attached_sas_addr == 0) { | 95 | if (*(u64 *)port->attached_sas_addr == 0) { |
99 | port->class = phy->class; | 96 | port->class = phy->class; |
100 | memcpy(port->attached_sas_addr, phy->attached_sas_addr, | 97 | memcpy(port->attached_sas_addr, phy->attached_sas_addr, |
@@ -115,6 +112,11 @@ static void sas_form_port(struct asd_sas_phy *phy) | |||
115 | } | 112 | } |
116 | sas_port_add_phy(port->port, phy->phy); | 113 | sas_port_add_phy(port->port, phy->phy); |
117 | 114 | ||
115 | SAS_DPRINTK("%s added to %s, phy_mask:0x%x (%16llx)\n", | ||
116 | phy->phy->dev.bus_id,port->port->dev.bus_id, | ||
117 | port->phy_mask, | ||
118 | SAS_ADDR(port->attached_sas_addr)); | ||
119 | |||
118 | if (port->port_dev) | 120 | if (port->port_dev) |
119 | port->port_dev->pathways = port->num_phys; | 121 | port->port_dev->pathways = port->num_phys; |
120 | 122 | ||
@@ -255,12 +257,11 @@ void sas_porte_hard_reset(struct work_struct *work) | |||
255 | static void sas_init_port(struct asd_sas_port *port, | 257 | static void sas_init_port(struct asd_sas_port *port, |
256 | struct sas_ha_struct *sas_ha, int i) | 258 | struct sas_ha_struct *sas_ha, int i) |
257 | { | 259 | { |
260 | memset(port, 0, sizeof(*port)); | ||
258 | port->id = i; | 261 | port->id = i; |
259 | INIT_LIST_HEAD(&port->dev_list); | 262 | INIT_LIST_HEAD(&port->dev_list); |
260 | spin_lock_init(&port->phy_list_lock); | 263 | spin_lock_init(&port->phy_list_lock); |
261 | INIT_LIST_HEAD(&port->phy_list); | 264 | INIT_LIST_HEAD(&port->phy_list); |
262 | port->num_phys = 0; | ||
263 | port->phy_mask = 0; | ||
264 | port->ha = sas_ha; | 265 | port->ha = sas_ha; |
265 | 266 | ||
266 | spin_lock_init(&port->dev_list_lock); | 267 | spin_lock_init(&port->dev_list_lock); |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 704ea06a6e50..1f8241563c6c 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
@@ -434,7 +434,7 @@ static int sas_recover_I_T(struct domain_device *dev) | |||
434 | } | 434 | } |
435 | 435 | ||
436 | /* Find the sas_phy that's attached to this device */ | 436 | /* Find the sas_phy that's attached to this device */ |
437 | static struct sas_phy *find_local_sas_phy(struct domain_device *dev) | 437 | struct sas_phy *sas_find_local_phy(struct domain_device *dev) |
438 | { | 438 | { |
439 | struct domain_device *pdev = dev->parent; | 439 | struct domain_device *pdev = dev->parent; |
440 | struct ex_phy *exphy = NULL; | 440 | struct ex_phy *exphy = NULL; |
@@ -456,6 +456,7 @@ static struct sas_phy *find_local_sas_phy(struct domain_device *dev) | |||
456 | BUG_ON(!exphy); | 456 | BUG_ON(!exphy); |
457 | return exphy->phy; | 457 | return exphy->phy; |
458 | } | 458 | } |
459 | EXPORT_SYMBOL_GPL(sas_find_local_phy); | ||
459 | 460 | ||
460 | /* Attempt to send a LUN reset message to a device */ | 461 | /* Attempt to send a LUN reset message to a device */ |
461 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | 462 | int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) |
@@ -482,7 +483,7 @@ int sas_eh_device_reset_handler(struct scsi_cmnd *cmd) | |||
482 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | 483 | int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) |
483 | { | 484 | { |
484 | struct domain_device *dev = cmd_to_domain_dev(cmd); | 485 | struct domain_device *dev = cmd_to_domain_dev(cmd); |
485 | struct sas_phy *phy = find_local_sas_phy(dev); | 486 | struct sas_phy *phy = sas_find_local_phy(dev); |
486 | int res; | 487 | int res; |
487 | 488 | ||
488 | res = sas_phy_reset(phy, 1); | 489 | res = sas_phy_reset(phy, 1); |
@@ -497,10 +498,10 @@ int sas_eh_bus_reset_handler(struct scsi_cmnd *cmd) | |||
497 | } | 498 | } |
498 | 499 | ||
499 | /* Try to reset a device */ | 500 | /* Try to reset a device */ |
500 | static int try_to_reset_cmd_device(struct Scsi_Host *shost, | 501 | static int try_to_reset_cmd_device(struct scsi_cmnd *cmd) |
501 | struct scsi_cmnd *cmd) | ||
502 | { | 502 | { |
503 | int res; | 503 | int res; |
504 | struct Scsi_Host *shost = cmd->device->host; | ||
504 | 505 | ||
505 | if (!shost->hostt->eh_device_reset_handler) | 506 | if (!shost->hostt->eh_device_reset_handler) |
506 | goto try_bus_reset; | 507 | goto try_bus_reset; |
@@ -540,6 +541,12 @@ Again: | |||
540 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; | 541 | need_reset = task->task_state_flags & SAS_TASK_NEED_DEV_RESET; |
541 | spin_unlock_irqrestore(&task->task_state_lock, flags); | 542 | spin_unlock_irqrestore(&task->task_state_lock, flags); |
542 | 543 | ||
544 | if (need_reset) { | ||
545 | SAS_DPRINTK("%s: task 0x%p requests reset\n", | ||
546 | __FUNCTION__, task); | ||
547 | goto reset; | ||
548 | } | ||
549 | |||
543 | SAS_DPRINTK("trying to find task 0x%p\n", task); | 550 | SAS_DPRINTK("trying to find task 0x%p\n", task); |
544 | res = sas_scsi_find_task(task); | 551 | res = sas_scsi_find_task(task); |
545 | 552 | ||
@@ -550,18 +557,15 @@ Again: | |||
550 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, | 557 | SAS_DPRINTK("%s: task 0x%p is done\n", __FUNCTION__, |
551 | task); | 558 | task); |
552 | sas_eh_finish_cmd(cmd); | 559 | sas_eh_finish_cmd(cmd); |
553 | if (need_reset) | ||
554 | try_to_reset_cmd_device(shost, cmd); | ||
555 | continue; | 560 | continue; |
556 | case TASK_IS_ABORTED: | 561 | case TASK_IS_ABORTED: |
557 | SAS_DPRINTK("%s: task 0x%p is aborted\n", | 562 | SAS_DPRINTK("%s: task 0x%p is aborted\n", |
558 | __FUNCTION__, task); | 563 | __FUNCTION__, task); |
559 | sas_eh_finish_cmd(cmd); | 564 | sas_eh_finish_cmd(cmd); |
560 | if (need_reset) | ||
561 | try_to_reset_cmd_device(shost, cmd); | ||
562 | continue; | 565 | continue; |
563 | case TASK_IS_AT_LU: | 566 | case TASK_IS_AT_LU: |
564 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); | 567 | SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task); |
568 | reset: | ||
565 | tmf_resp = sas_recover_lu(task->dev, cmd); | 569 | tmf_resp = sas_recover_lu(task->dev, cmd); |
566 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 570 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
567 | SAS_DPRINTK("dev %016llx LU %x is " | 571 | SAS_DPRINTK("dev %016llx LU %x is " |
@@ -569,8 +573,6 @@ Again: | |||
569 | SAS_ADDR(task->dev), | 573 | SAS_ADDR(task->dev), |
570 | cmd->device->lun); | 574 | cmd->device->lun); |
571 | sas_eh_finish_cmd(cmd); | 575 | sas_eh_finish_cmd(cmd); |
572 | if (need_reset) | ||
573 | try_to_reset_cmd_device(shost, cmd); | ||
574 | sas_scsi_clear_queue_lu(work_q, cmd); | 576 | sas_scsi_clear_queue_lu(work_q, cmd); |
575 | goto Again; | 577 | goto Again; |
576 | } | 578 | } |
@@ -581,15 +583,15 @@ Again: | |||
581 | task); | 583 | task); |
582 | tmf_resp = sas_recover_I_T(task->dev); | 584 | tmf_resp = sas_recover_I_T(task->dev); |
583 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { | 585 | if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { |
586 | struct domain_device *dev = task->dev; | ||
584 | SAS_DPRINTK("I_T %016llx recovered\n", | 587 | SAS_DPRINTK("I_T %016llx recovered\n", |
585 | SAS_ADDR(task->dev->sas_addr)); | 588 | SAS_ADDR(task->dev->sas_addr)); |
586 | sas_eh_finish_cmd(cmd); | 589 | sas_eh_finish_cmd(cmd); |
587 | if (need_reset) | 590 | sas_scsi_clear_queue_I_T(work_q, dev); |
588 | try_to_reset_cmd_device(shost, cmd); | ||
589 | sas_scsi_clear_queue_I_T(work_q, task->dev); | ||
590 | goto Again; | 591 | goto Again; |
591 | } | 592 | } |
592 | /* Hammer time :-) */ | 593 | /* Hammer time :-) */ |
594 | try_to_reset_cmd_device(cmd); | ||
593 | if (i->dft->lldd_clear_nexus_port) { | 595 | if (i->dft->lldd_clear_nexus_port) { |
594 | struct asd_sas_port *port = task->dev->port; | 596 | struct asd_sas_port *port = task->dev->port; |
595 | SAS_DPRINTK("clearing nexus for port:%d\n", | 597 | SAS_DPRINTK("clearing nexus for port:%d\n", |
@@ -599,8 +601,6 @@ Again: | |||
599 | SAS_DPRINTK("clear nexus port:%d " | 601 | SAS_DPRINTK("clear nexus port:%d " |
600 | "succeeded\n", port->id); | 602 | "succeeded\n", port->id); |
601 | sas_eh_finish_cmd(cmd); | 603 | sas_eh_finish_cmd(cmd); |
602 | if (need_reset) | ||
603 | try_to_reset_cmd_device(shost, cmd); | ||
604 | sas_scsi_clear_queue_port(work_q, | 604 | sas_scsi_clear_queue_port(work_q, |
605 | port); | 605 | port); |
606 | goto Again; | 606 | goto Again; |
@@ -613,8 +613,6 @@ Again: | |||
613 | SAS_DPRINTK("clear nexus ha " | 613 | SAS_DPRINTK("clear nexus ha " |
614 | "succeeded\n"); | 614 | "succeeded\n"); |
615 | sas_eh_finish_cmd(cmd); | 615 | sas_eh_finish_cmd(cmd); |
616 | if (need_reset) | ||
617 | try_to_reset_cmd_device(shost, cmd); | ||
618 | goto clear_q; | 616 | goto clear_q; |
619 | } | 617 | } |
620 | } | 618 | } |
@@ -628,8 +626,6 @@ Again: | |||
628 | cmd->device->lun); | 626 | cmd->device->lun); |
629 | 627 | ||
630 | sas_eh_finish_cmd(cmd); | 628 | sas_eh_finish_cmd(cmd); |
631 | if (need_reset) | ||
632 | try_to_reset_cmd_device(shost, cmd); | ||
633 | goto clear_q; | 629 | goto clear_q; |
634 | } | 630 | } |
635 | } | 631 | } |
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c index d4a6ac3c9c47..5ec0665b3a3d 100644 --- a/drivers/scsi/mvsas.c +++ b/drivers/scsi/mvsas.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <asm/io.h> | 40 | #include <asm/io.h> |
41 | 41 | ||
42 | #define DRV_NAME "mvsas" | 42 | #define DRV_NAME "mvsas" |
43 | #define DRV_VERSION "0.5" | 43 | #define DRV_VERSION "0.5.1" |
44 | #define _MV_DUMP 0 | 44 | #define _MV_DUMP 0 |
45 | #define MVS_DISABLE_NVRAM | 45 | #define MVS_DISABLE_NVRAM |
46 | #define MVS_DISABLE_MSI | 46 | #define MVS_DISABLE_MSI |
@@ -1005,7 +1005,7 @@ err_out: | |||
1005 | return rc; | 1005 | return rc; |
1006 | #else | 1006 | #else |
1007 | /* FIXME , For SAS target mode */ | 1007 | /* FIXME , For SAS target mode */ |
1008 | memcpy(buf, "\x00\x00\xab\x11\x30\x04\x05\x50", 8); | 1008 | memcpy(buf, "\x50\x05\x04\x30\x11\xab\x00\x00", 8); |
1009 | return 0; | 1009 | return 0; |
1010 | #endif | 1010 | #endif |
1011 | } | 1011 | } |
@@ -1330,7 +1330,7 @@ static int mvs_int_rx(struct mvs_info *mvi, bool self_clear) | |||
1330 | 1330 | ||
1331 | mvs_hba_cq_dump(mvi); | 1331 | mvs_hba_cq_dump(mvi); |
1332 | 1332 | ||
1333 | if (unlikely(rx_desc & RXQ_DONE)) | 1333 | if (likely(rx_desc & RXQ_DONE)) |
1334 | mvs_slot_complete(mvi, rx_desc); | 1334 | mvs_slot_complete(mvi, rx_desc); |
1335 | if (rx_desc & RXQ_ATTN) { | 1335 | if (rx_desc & RXQ_ATTN) { |
1336 | attn = true; | 1336 | attn = true; |
@@ -2720,9 +2720,8 @@ static int __devinit mvs_hw_init(struct mvs_info *mvi) | |||
2720 | msleep(100); | 2720 | msleep(100); |
2721 | /* init and reset phys */ | 2721 | /* init and reset phys */ |
2722 | for (i = 0; i < mvi->chip->n_phy; i++) { | 2722 | for (i = 0; i < mvi->chip->n_phy; i++) { |
2723 | /* FIXME: is this the correct dword order? */ | 2723 | u32 lo = be32_to_cpu(*(u32 *)&mvi->sas_addr[4]); |
2724 | u32 lo = *((u32 *)&mvi->sas_addr[0]); | 2724 | u32 hi = be32_to_cpu(*(u32 *)&mvi->sas_addr[0]); |
2725 | u32 hi = *((u32 *)&mvi->sas_addr[4]); | ||
2726 | 2725 | ||
2727 | mvs_detect_porttype(mvi, i); | 2726 | mvs_detect_porttype(mvi, i); |
2728 | 2727 | ||
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index 0cd614a0fa73..fad6cb5cba28 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c | |||
@@ -124,7 +124,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) | |||
124 | } | 124 | } |
125 | req_len += sgpnt->length; | 125 | req_len += sgpnt->length; |
126 | } | 126 | } |
127 | scsi_set_resid(cmd, req_len - act_len); | 127 | scsi_set_resid(cmd, buflen - act_len); |
128 | return 0; | 128 | return 0; |
129 | } | 129 | } |
130 | 130 | ||
@@ -427,7 +427,7 @@ static struct scsi_host_template ps3rom_host_template = { | |||
427 | .cmd_per_lun = 1, | 427 | .cmd_per_lun = 1, |
428 | .emulated = 1, /* only sg driver uses this */ | 428 | .emulated = 1, /* only sg driver uses this */ |
429 | .max_sectors = PS3ROM_MAX_SECTORS, | 429 | .max_sectors = PS3ROM_MAX_SECTORS, |
430 | .use_clustering = ENABLE_CLUSTERING, | 430 | .use_clustering = DISABLE_CLUSTERING, |
431 | .module = THIS_MODULE, | 431 | .module = THIS_MODULE, |
432 | }; | 432 | }; |
433 | 433 | ||
diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index 6226d88479f5..c1808763d40e 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c | |||
@@ -39,7 +39,7 @@ qla2x00_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) | |||
39 | ms_pkt->entry_count = 1; | 39 | ms_pkt->entry_count = 1; |
40 | SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER); | 40 | SET_TARGET_ID(ha, ms_pkt->loop_id, SIMPLE_NAME_SERVER); |
41 | ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); | 41 | ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); |
42 | ms_pkt->timeout = __constant_cpu_to_le16(25); | 42 | ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); |
43 | ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | 43 | ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); |
44 | ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); | 44 | ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); |
45 | ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); | 45 | ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); |
@@ -75,7 +75,7 @@ qla24xx_prep_ms_iocb(scsi_qla_host_t *ha, uint32_t req_size, uint32_t rsp_size) | |||
75 | ct_pkt->entry_type = CT_IOCB_TYPE; | 75 | ct_pkt->entry_type = CT_IOCB_TYPE; |
76 | ct_pkt->entry_count = 1; | 76 | ct_pkt->entry_count = 1; |
77 | ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS); | 77 | ct_pkt->nport_handle = __constant_cpu_to_le16(NPH_SNS); |
78 | ct_pkt->timeout = __constant_cpu_to_le16(25); | 78 | ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); |
79 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | 79 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); |
80 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); | 80 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); |
81 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); | 81 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); |
@@ -1144,7 +1144,7 @@ qla2x00_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | |||
1144 | ms_pkt->entry_count = 1; | 1144 | ms_pkt->entry_count = 1; |
1145 | SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id); | 1145 | SET_TARGET_ID(ha, ms_pkt->loop_id, ha->mgmt_svr_loop_id); |
1146 | ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); | 1146 | ms_pkt->control_flags = __constant_cpu_to_le16(CF_READ | CF_HEAD_TAG); |
1147 | ms_pkt->timeout = __constant_cpu_to_le16(59); | 1147 | ms_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); |
1148 | ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | 1148 | ms_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); |
1149 | ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); | 1149 | ms_pkt->total_dsd_count = __constant_cpu_to_le16(2); |
1150 | ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); | 1150 | ms_pkt->rsp_bytecount = cpu_to_le32(rsp_size); |
@@ -1181,7 +1181,7 @@ qla24xx_prep_ms_fdmi_iocb(scsi_qla_host_t *ha, uint32_t req_size, | |||
1181 | ct_pkt->entry_type = CT_IOCB_TYPE; | 1181 | ct_pkt->entry_type = CT_IOCB_TYPE; |
1182 | ct_pkt->entry_count = 1; | 1182 | ct_pkt->entry_count = 1; |
1183 | ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); | 1183 | ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); |
1184 | ct_pkt->timeout = __constant_cpu_to_le16(59); | 1184 | ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); |
1185 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | 1185 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); |
1186 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); | 1186 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); |
1187 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); | 1187 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); |
@@ -1761,7 +1761,7 @@ qla24xx_prep_ms_fm_iocb(scsi_qla_host_t *ha, uint32_t req_size, | |||
1761 | ct_pkt->entry_type = CT_IOCB_TYPE; | 1761 | ct_pkt->entry_type = CT_IOCB_TYPE; |
1762 | ct_pkt->entry_count = 1; | 1762 | ct_pkt->entry_count = 1; |
1763 | ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); | 1763 | ct_pkt->nport_handle = cpu_to_le16(ha->mgmt_svr_loop_id); |
1764 | ct_pkt->timeout = __constant_cpu_to_le16(59); | 1764 | ct_pkt->timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); |
1765 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); | 1765 | ct_pkt->cmd_dsd_count = __constant_cpu_to_le16(1); |
1766 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); | 1766 | ct_pkt->rsp_dsd_count = __constant_cpu_to_le16(1); |
1767 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); | 1767 | ct_pkt->rsp_byte_count = cpu_to_le32(rsp_size); |
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index d5c7853e7eba..364be7d06875 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c | |||
@@ -1733,8 +1733,8 @@ qla2x00_nvram_config(scsi_qla_host_t *ha) | |||
1733 | ha->login_timeout = nv->login_timeout; | 1733 | ha->login_timeout = nv->login_timeout; |
1734 | icb->login_timeout = nv->login_timeout; | 1734 | icb->login_timeout = nv->login_timeout; |
1735 | 1735 | ||
1736 | /* Set minimum RATOV to 200 tenths of a second. */ | 1736 | /* Set minimum RATOV to 100 tenths of a second. */ |
1737 | ha->r_a_tov = 200; | 1737 | ha->r_a_tov = 100; |
1738 | 1738 | ||
1739 | ha->loop_reset_delay = nv->reset_delay; | 1739 | ha->loop_reset_delay = nv->reset_delay; |
1740 | 1740 | ||
@@ -3645,8 +3645,8 @@ qla24xx_nvram_config(scsi_qla_host_t *ha) | |||
3645 | ha->login_timeout = le16_to_cpu(nv->login_timeout); | 3645 | ha->login_timeout = le16_to_cpu(nv->login_timeout); |
3646 | icb->login_timeout = cpu_to_le16(nv->login_timeout); | 3646 | icb->login_timeout = cpu_to_le16(nv->login_timeout); |
3647 | 3647 | ||
3648 | /* Set minimum RATOV to 200 tenths of a second. */ | 3648 | /* Set minimum RATOV to 100 tenths of a second. */ |
3649 | ha->r_a_tov = 200; | 3649 | ha->r_a_tov = 100; |
3650 | 3650 | ||
3651 | ha->loop_reset_delay = nv->reset_delay; | 3651 | ha->loop_reset_delay = nv->reset_delay; |
3652 | 3652 | ||
@@ -4022,7 +4022,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha) | |||
4022 | return; | 4022 | return; |
4023 | 4023 | ||
4024 | ret = qla2x00_stop_firmware(ha); | 4024 | ret = qla2x00_stop_firmware(ha); |
4025 | for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) { | 4025 | for (retries = 5; ret != QLA_SUCCESS && ret != QLA_FUNCTION_TIMEOUT && |
4026 | retries ; retries--) { | ||
4026 | qla2x00_reset_chip(ha); | 4027 | qla2x00_reset_chip(ha); |
4027 | if (qla2x00_chip_diag(ha) != QLA_SUCCESS) | 4028 | if (qla2x00_chip_diag(ha) != QLA_SUCCESS) |
4028 | continue; | 4029 | continue; |
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 14e6f22944b7..f0337036c7bb 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c | |||
@@ -958,6 +958,11 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) | |||
958 | } | 958 | } |
959 | } | 959 | } |
960 | 960 | ||
961 | /* Check for overrun. */ | ||
962 | if (IS_FWI2_CAPABLE(ha) && comp_status == CS_COMPLETE && | ||
963 | scsi_status & SS_RESIDUAL_OVER) | ||
964 | comp_status = CS_DATA_OVERRUN; | ||
965 | |||
961 | /* | 966 | /* |
962 | * Based on Host and scsi status generate status code for Linux | 967 | * Based on Host and scsi status generate status code for Linux |
963 | */ | 968 | */ |
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 99d29fff836d..bb103580e1ba 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c | |||
@@ -2206,7 +2206,7 @@ qla24xx_abort_target(fc_port_t *fcport) | |||
2206 | tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; | 2206 | tsk->p.tsk.entry_type = TSK_MGMT_IOCB_TYPE; |
2207 | tsk->p.tsk.entry_count = 1; | 2207 | tsk->p.tsk.entry_count = 1; |
2208 | tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); | 2208 | tsk->p.tsk.nport_handle = cpu_to_le16(fcport->loop_id); |
2209 | tsk->p.tsk.timeout = __constant_cpu_to_le16(25); | 2209 | tsk->p.tsk.timeout = cpu_to_le16(ha->r_a_tov / 10 * 2); |
2210 | tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET); | 2210 | tsk->p.tsk.control_flags = __constant_cpu_to_le32(TCF_TARGET_RESET); |
2211 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; | 2211 | tsk->p.tsk.port_id[0] = fcport->d_id.b.al_pa; |
2212 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; | 2212 | tsk->p.tsk.port_id[1] = fcport->d_id.b.area; |
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index c5742cc15abb..ea08a129fee9 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h | |||
@@ -7,7 +7,7 @@ | |||
7 | /* | 7 | /* |
8 | * Driver version | 8 | * Driver version |
9 | */ | 9 | */ |
10 | #define QLA2XXX_VERSION "8.02.00-k8" | 10 | #define QLA2XXX_VERSION "8.02.00-k9" |
11 | 11 | ||
12 | #define QLA_DRIVER_MAJOR_VER 8 | 12 | #define QLA_DRIVER_MAJOR_VER 8 |
13 | #define QLA_DRIVER_MINOR_VER 2 | 13 | #define QLA_DRIVER_MINOR_VER 2 |
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 10b3b9a620f3..109c5f5985ec 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -1299,9 +1299,9 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, | |||
1299 | ddb_entry->fw_ddb_device_state = state; | 1299 | ddb_entry->fw_ddb_device_state = state; |
1300 | /* Device is back online. */ | 1300 | /* Device is back online. */ |
1301 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { | 1301 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { |
1302 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); | ||
1302 | atomic_set(&ddb_entry->port_down_timer, | 1303 | atomic_set(&ddb_entry->port_down_timer, |
1303 | ha->port_down_retry_count); | 1304 | ha->port_down_retry_count); |
1304 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); | ||
1305 | atomic_set(&ddb_entry->relogin_retry_count, 0); | 1305 | atomic_set(&ddb_entry->relogin_retry_count, 0); |
1306 | atomic_set(&ddb_entry->relogin_timer, 0); | 1306 | atomic_set(&ddb_entry->relogin_timer, 0); |
1307 | clear_bit(DF_RELOGIN, &ddb_entry->flags); | 1307 | clear_bit(DF_RELOGIN, &ddb_entry->flags); |
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index c3c59d763037..8b92f348f02c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c | |||
@@ -75,6 +75,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd); | |||
75 | static int qla4xxx_slave_alloc(struct scsi_device *device); | 75 | static int qla4xxx_slave_alloc(struct scsi_device *device); |
76 | static int qla4xxx_slave_configure(struct scsi_device *device); | 76 | static int qla4xxx_slave_configure(struct scsi_device *device); |
77 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); | 77 | static void qla4xxx_slave_destroy(struct scsi_device *sdev); |
78 | static void qla4xxx_scan_start(struct Scsi_Host *shost); | ||
78 | 79 | ||
79 | static struct scsi_host_template qla4xxx_driver_template = { | 80 | static struct scsi_host_template qla4xxx_driver_template = { |
80 | .module = THIS_MODULE, | 81 | .module = THIS_MODULE, |
@@ -90,6 +91,7 @@ static struct scsi_host_template qla4xxx_driver_template = { | |||
90 | .slave_destroy = qla4xxx_slave_destroy, | 91 | .slave_destroy = qla4xxx_slave_destroy, |
91 | 92 | ||
92 | .scan_finished = iscsi_scan_finished, | 93 | .scan_finished = iscsi_scan_finished, |
94 | .scan_start = qla4xxx_scan_start, | ||
93 | 95 | ||
94 | .this_id = -1, | 96 | .this_id = -1, |
95 | .cmd_per_lun = 3, | 97 | .cmd_per_lun = 3, |
@@ -299,6 +301,18 @@ struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha) | |||
299 | return ddb_entry; | 301 | return ddb_entry; |
300 | } | 302 | } |
301 | 303 | ||
304 | static void qla4xxx_scan_start(struct Scsi_Host *shost) | ||
305 | { | ||
306 | struct scsi_qla_host *ha = shost_priv(shost); | ||
307 | struct ddb_entry *ddb_entry, *ddbtemp; | ||
308 | |||
309 | /* finish setup of sessions that were already setup in firmware */ | ||
310 | list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { | ||
311 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) | ||
312 | qla4xxx_add_sess(ddb_entry); | ||
313 | } | ||
314 | } | ||
315 | |||
302 | /* | 316 | /* |
303 | * Timer routines | 317 | * Timer routines |
304 | */ | 318 | */ |
@@ -864,8 +878,9 @@ static void qla4xxx_flush_active_srbs(struct scsi_qla_host *ha) | |||
864 | * qla4xxx_recover_adapter - recovers adapter after a fatal error | 878 | * qla4xxx_recover_adapter - recovers adapter after a fatal error |
865 | * @ha: Pointer to host adapter structure. | 879 | * @ha: Pointer to host adapter structure. |
866 | * @renew_ddb_list: Indicates what to do with the adapter's ddb list | 880 | * @renew_ddb_list: Indicates what to do with the adapter's ddb list |
867 | * after adapter recovery has completed. | 881 | * |
868 | * 0=preserve ddb list, 1=destroy and rebuild ddb list | 882 | * renew_ddb_list value can be 0=preserve ddb list, 1=destroy and rebuild |
883 | * ddb list. | ||
869 | **/ | 884 | **/ |
870 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | 885 | static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, |
871 | uint8_t renew_ddb_list) | 886 | uint8_t renew_ddb_list) |
@@ -874,6 +889,7 @@ static int qla4xxx_recover_adapter(struct scsi_qla_host *ha, | |||
874 | 889 | ||
875 | /* Stall incoming I/O until we are done */ | 890 | /* Stall incoming I/O until we are done */ |
876 | clear_bit(AF_ONLINE, &ha->flags); | 891 | clear_bit(AF_ONLINE, &ha->flags); |
892 | |||
877 | DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, | 893 | DEBUG2(printk("scsi%ld: %s calling qla4xxx_cmd_wait\n", ha->host_no, |
878 | __func__)); | 894 | __func__)); |
879 | 895 | ||
@@ -1176,7 +1192,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1176 | int ret = -ENODEV, status; | 1192 | int ret = -ENODEV, status; |
1177 | struct Scsi_Host *host; | 1193 | struct Scsi_Host *host; |
1178 | struct scsi_qla_host *ha; | 1194 | struct scsi_qla_host *ha; |
1179 | struct ddb_entry *ddb_entry, *ddbtemp; | ||
1180 | uint8_t init_retry_count = 0; | 1195 | uint8_t init_retry_count = 0; |
1181 | char buf[34]; | 1196 | char buf[34]; |
1182 | 1197 | ||
@@ -1295,13 +1310,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1295 | if (ret) | 1310 | if (ret) |
1296 | goto probe_failed; | 1311 | goto probe_failed; |
1297 | 1312 | ||
1298 | /* Update transport device information for all devices. */ | ||
1299 | list_for_each_entry_safe(ddb_entry, ddbtemp, &ha->ddb_list, list) { | ||
1300 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) | ||
1301 | if (qla4xxx_add_sess(ddb_entry)) | ||
1302 | goto remove_host; | ||
1303 | } | ||
1304 | |||
1305 | printk(KERN_INFO | 1313 | printk(KERN_INFO |
1306 | " QLogic iSCSI HBA Driver version: %s\n" | 1314 | " QLogic iSCSI HBA Driver version: %s\n" |
1307 | " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", | 1315 | " QLogic ISP%04x @ %s, host#=%ld, fw=%02d.%02d.%02d.%02d\n", |
@@ -1311,10 +1319,6 @@ static int __devinit qla4xxx_probe_adapter(struct pci_dev *pdev, | |||
1311 | scsi_scan_host(host); | 1319 | scsi_scan_host(host); |
1312 | return 0; | 1320 | return 0; |
1313 | 1321 | ||
1314 | remove_host: | ||
1315 | qla4xxx_free_ddb_list(ha); | ||
1316 | scsi_remove_host(host); | ||
1317 | |||
1318 | probe_failed: | 1322 | probe_failed: |
1319 | qla4xxx_free_adapter(ha); | 1323 | qla4xxx_free_adapter(ha); |
1320 | scsi_host_put(ha->host); | 1324 | scsi_host_put(ha->host); |
@@ -1600,9 +1604,12 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) | |||
1600 | return FAILED; | 1604 | return FAILED; |
1601 | } | 1605 | } |
1602 | 1606 | ||
1603 | if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) { | 1607 | /* make sure the dpc thread is stopped while we reset the hba */ |
1608 | clear_bit(AF_ONLINE, &ha->flags); | ||
1609 | flush_workqueue(ha->dpc_thread); | ||
1610 | |||
1611 | if (qla4xxx_recover_adapter(ha, PRESERVE_DDB_LIST) == QLA_SUCCESS) | ||
1604 | return_status = SUCCESS; | 1612 | return_status = SUCCESS; |
1605 | } | ||
1606 | 1613 | ||
1607 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", | 1614 | dev_info(&ha->pdev->dev, "HOST RESET %s.\n", |
1608 | return_status == FAILED ? "FAILED" : "SUCCEDED"); | 1615 | return_status == FAILED ? "FAILED" : "SUCCEDED"); |
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index fecba05b4e77..e5c6f6af8765 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c | |||
@@ -757,7 +757,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd) | |||
757 | "Notifying upper driver of completion " | 757 | "Notifying upper driver of completion " |
758 | "(result %x)\n", cmd->result)); | 758 | "(result %x)\n", cmd->result)); |
759 | 759 | ||
760 | good_bytes = scsi_bufflen(cmd); | 760 | good_bytes = scsi_bufflen(cmd) + cmd->request->extra_len; |
761 | if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { | 761 | if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { |
762 | drv = scsi_cmd_to_driver(cmd); | 762 | drv = scsi_cmd_to_driver(cmd); |
763 | if (drv->done) | 763 | if (drv->done) |
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 1dc165ad17fb..e67c14e31bab 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c | |||
@@ -1577,8 +1577,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, | |||
1577 | } | 1577 | } |
1578 | 1578 | ||
1579 | /** | 1579 | /** |
1580 | * scsi_scan_target - scan a target id, possibly including all LUNs on the | 1580 | * scsi_scan_target - scan a target id, possibly including all LUNs on the target. |
1581 | * target. | ||
1582 | * @parent: host to scan | 1581 | * @parent: host to scan |
1583 | * @channel: channel to scan | 1582 | * @channel: channel to scan |
1584 | * @id: target id to scan | 1583 | * @id: target id to scan |
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 3677fbb30b72..a0f308bd145b 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
@@ -103,7 +103,6 @@ struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, | |||
103 | if (!cmd) | 103 | if (!cmd) |
104 | goto release_rq; | 104 | goto release_rq; |
105 | 105 | ||
106 | memset(cmd, 0, sizeof(*cmd)); | ||
107 | cmd->sc_data_direction = data_dir; | 106 | cmd->sc_data_direction = data_dir; |
108 | cmd->jiffies_at_alloc = jiffies; | 107 | cmd->jiffies_at_alloc = jiffies; |
109 | cmd->request = rq; | 108 | cmd->request = rq; |
@@ -382,6 +381,11 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, | |||
382 | scsi_release_buffers(cmd); | 381 | scsi_release_buffers(cmd); |
383 | goto unmap_rq; | 382 | goto unmap_rq; |
384 | } | 383 | } |
384 | /* | ||
385 | * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the | ||
386 | * length for us. | ||
387 | */ | ||
388 | cmd->sdb.length = rq->data_len; | ||
385 | 389 | ||
386 | return 0; | 390 | return 0; |
387 | 391 | ||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 9981682d5302..ca7bb6f63bde 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #define ISCSI_SESSION_ATTRS 19 | 33 | #define ISCSI_SESSION_ATTRS 19 |
34 | #define ISCSI_CONN_ATTRS 13 | 34 | #define ISCSI_CONN_ATTRS 13 |
35 | #define ISCSI_HOST_ATTRS 4 | 35 | #define ISCSI_HOST_ATTRS 4 |
36 | #define ISCSI_TRANSPORT_VERSION "2.0-868" | 36 | #define ISCSI_TRANSPORT_VERSION "2.0-869" |
37 | 37 | ||
38 | struct iscsi_internal { | 38 | struct iscsi_internal { |
39 | int daemon_pid; | 39 | int daemon_pid; |
@@ -373,24 +373,25 @@ static void session_recovery_timedout(struct work_struct *work) | |||
373 | scsi_target_unblock(&session->dev); | 373 | scsi_target_unblock(&session->dev); |
374 | } | 374 | } |
375 | 375 | ||
376 | static void __iscsi_unblock_session(struct iscsi_cls_session *session) | 376 | static void __iscsi_unblock_session(struct work_struct *work) |
377 | { | ||
378 | if (!cancel_delayed_work(&session->recovery_work)) | ||
379 | flush_workqueue(iscsi_eh_timer_workq); | ||
380 | scsi_target_unblock(&session->dev); | ||
381 | } | ||
382 | |||
383 | void iscsi_unblock_session(struct iscsi_cls_session *session) | ||
384 | { | 377 | { |
378 | struct iscsi_cls_session *session = | ||
379 | container_of(work, struct iscsi_cls_session, | ||
380 | unblock_work); | ||
385 | struct Scsi_Host *shost = iscsi_session_to_shost(session); | 381 | struct Scsi_Host *shost = iscsi_session_to_shost(session); |
386 | struct iscsi_host *ihost = shost->shost_data; | 382 | struct iscsi_host *ihost = shost->shost_data; |
387 | unsigned long flags; | 383 | unsigned long flags; |
388 | 384 | ||
385 | /* | ||
386 | * The recovery and unblock work get run from the same workqueue, | ||
387 | * so try to cancel it if it was going to run after this unblock. | ||
388 | */ | ||
389 | cancel_delayed_work(&session->recovery_work); | ||
389 | spin_lock_irqsave(&session->lock, flags); | 390 | spin_lock_irqsave(&session->lock, flags); |
390 | session->state = ISCSI_SESSION_LOGGED_IN; | 391 | session->state = ISCSI_SESSION_LOGGED_IN; |
391 | spin_unlock_irqrestore(&session->lock, flags); | 392 | spin_unlock_irqrestore(&session->lock, flags); |
392 | 393 | /* start IO */ | |
393 | __iscsi_unblock_session(session); | 394 | scsi_target_unblock(&session->dev); |
394 | /* | 395 | /* |
395 | * Only do kernel scanning if the driver is properly hooked into | 396 | * Only do kernel scanning if the driver is properly hooked into |
396 | * the async scanning code (drivers like iscsi_tcp do login and | 397 | * the async scanning code (drivers like iscsi_tcp do login and |
@@ -401,20 +402,43 @@ void iscsi_unblock_session(struct iscsi_cls_session *session) | |||
401 | atomic_inc(&ihost->nr_scans); | 402 | atomic_inc(&ihost->nr_scans); |
402 | } | 403 | } |
403 | } | 404 | } |
405 | |||
406 | /** | ||
407 | * iscsi_unblock_session - set a session as logged in and start IO. | ||
408 | * @session: iscsi session | ||
409 | * | ||
410 | * Mark a session as ready to accept IO. | ||
411 | */ | ||
412 | void iscsi_unblock_session(struct iscsi_cls_session *session) | ||
413 | { | ||
414 | queue_work(iscsi_eh_timer_workq, &session->unblock_work); | ||
415 | /* | ||
416 | * make sure all the events have completed before tell the driver | ||
417 | * it is safe | ||
418 | */ | ||
419 | flush_workqueue(iscsi_eh_timer_workq); | ||
420 | } | ||
404 | EXPORT_SYMBOL_GPL(iscsi_unblock_session); | 421 | EXPORT_SYMBOL_GPL(iscsi_unblock_session); |
405 | 422 | ||
406 | void iscsi_block_session(struct iscsi_cls_session *session) | 423 | static void __iscsi_block_session(struct work_struct *work) |
407 | { | 424 | { |
425 | struct iscsi_cls_session *session = | ||
426 | container_of(work, struct iscsi_cls_session, | ||
427 | block_work); | ||
408 | unsigned long flags; | 428 | unsigned long flags; |
409 | 429 | ||
410 | spin_lock_irqsave(&session->lock, flags); | 430 | spin_lock_irqsave(&session->lock, flags); |
411 | session->state = ISCSI_SESSION_FAILED; | 431 | session->state = ISCSI_SESSION_FAILED; |
412 | spin_unlock_irqrestore(&session->lock, flags); | 432 | spin_unlock_irqrestore(&session->lock, flags); |
413 | |||
414 | scsi_target_block(&session->dev); | 433 | scsi_target_block(&session->dev); |
415 | queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work, | 434 | queue_delayed_work(iscsi_eh_timer_workq, &session->recovery_work, |
416 | session->recovery_tmo * HZ); | 435 | session->recovery_tmo * HZ); |
417 | } | 436 | } |
437 | |||
438 | void iscsi_block_session(struct iscsi_cls_session *session) | ||
439 | { | ||
440 | queue_work(iscsi_eh_timer_workq, &session->block_work); | ||
441 | } | ||
418 | EXPORT_SYMBOL_GPL(iscsi_block_session); | 442 | EXPORT_SYMBOL_GPL(iscsi_block_session); |
419 | 443 | ||
420 | static void __iscsi_unbind_session(struct work_struct *work) | 444 | static void __iscsi_unbind_session(struct work_struct *work) |
@@ -463,6 +487,8 @@ iscsi_alloc_session(struct Scsi_Host *shost, | |||
463 | INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); | 487 | INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); |
464 | INIT_LIST_HEAD(&session->host_list); | 488 | INIT_LIST_HEAD(&session->host_list); |
465 | INIT_LIST_HEAD(&session->sess_list); | 489 | INIT_LIST_HEAD(&session->sess_list); |
490 | INIT_WORK(&session->unblock_work, __iscsi_unblock_session); | ||
491 | INIT_WORK(&session->block_work, __iscsi_block_session); | ||
466 | INIT_WORK(&session->unbind_work, __iscsi_unbind_session); | 492 | INIT_WORK(&session->unbind_work, __iscsi_unbind_session); |
467 | INIT_WORK(&session->scan_work, iscsi_scan_session); | 493 | INIT_WORK(&session->scan_work, iscsi_scan_session); |
468 | spin_lock_init(&session->lock); | 494 | spin_lock_init(&session->lock); |
@@ -575,24 +601,25 @@ void iscsi_remove_session(struct iscsi_cls_session *session) | |||
575 | list_del(&session->sess_list); | 601 | list_del(&session->sess_list); |
576 | spin_unlock_irqrestore(&sesslock, flags); | 602 | spin_unlock_irqrestore(&sesslock, flags); |
577 | 603 | ||
604 | /* make sure there are no blocks/unblocks queued */ | ||
605 | flush_workqueue(iscsi_eh_timer_workq); | ||
606 | /* make sure the timedout callout is not running */ | ||
607 | if (!cancel_delayed_work(&session->recovery_work)) | ||
608 | flush_workqueue(iscsi_eh_timer_workq); | ||
578 | /* | 609 | /* |
579 | * If we are blocked let commands flow again. The lld or iscsi | 610 | * If we are blocked let commands flow again. The lld or iscsi |
580 | * layer should set up the queuecommand to fail commands. | 611 | * layer should set up the queuecommand to fail commands. |
612 | * We assume that LLD will not be calling block/unblock while | ||
613 | * removing the session. | ||
581 | */ | 614 | */ |
582 | spin_lock_irqsave(&session->lock, flags); | 615 | spin_lock_irqsave(&session->lock, flags); |
583 | session->state = ISCSI_SESSION_FREE; | 616 | session->state = ISCSI_SESSION_FREE; |
584 | spin_unlock_irqrestore(&session->lock, flags); | 617 | spin_unlock_irqrestore(&session->lock, flags); |
585 | __iscsi_unblock_session(session); | ||
586 | __iscsi_unbind_session(&session->unbind_work); | ||
587 | 618 | ||
588 | /* flush running scans */ | 619 | scsi_target_unblock(&session->dev); |
620 | /* flush running scans then delete devices */ | ||
589 | flush_workqueue(ihost->scan_workq); | 621 | flush_workqueue(ihost->scan_workq); |
590 | /* | 622 | __iscsi_unbind_session(&session->unbind_work); |
591 | * If the session dropped while removing devices then we need to make | ||
592 | * sure it is not blocked | ||
593 | */ | ||
594 | if (!cancel_delayed_work(&session->recovery_work)) | ||
595 | flush_workqueue(iscsi_eh_timer_workq); | ||
596 | 623 | ||
597 | /* hw iscsi may not have removed all connections from session */ | 624 | /* hw iscsi may not have removed all connections from session */ |
598 | err = device_for_each_child(&session->dev, NULL, | 625 | err = device_for_each_child(&session->dev, NULL, |
@@ -802,23 +829,16 @@ EXPORT_SYMBOL_GPL(iscsi_recv_pdu); | |||
802 | 829 | ||
803 | void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) | 830 | void iscsi_conn_error(struct iscsi_cls_conn *conn, enum iscsi_err error) |
804 | { | 831 | { |
805 | struct iscsi_cls_session *session = iscsi_conn_to_session(conn); | ||
806 | struct nlmsghdr *nlh; | 832 | struct nlmsghdr *nlh; |
807 | struct sk_buff *skb; | 833 | struct sk_buff *skb; |
808 | struct iscsi_uevent *ev; | 834 | struct iscsi_uevent *ev; |
809 | struct iscsi_internal *priv; | 835 | struct iscsi_internal *priv; |
810 | int len = NLMSG_SPACE(sizeof(*ev)); | 836 | int len = NLMSG_SPACE(sizeof(*ev)); |
811 | unsigned long flags; | ||
812 | 837 | ||
813 | priv = iscsi_if_transport_lookup(conn->transport); | 838 | priv = iscsi_if_transport_lookup(conn->transport); |
814 | if (!priv) | 839 | if (!priv) |
815 | return; | 840 | return; |
816 | 841 | ||
817 | spin_lock_irqsave(&session->lock, flags); | ||
818 | if (session->state == ISCSI_SESSION_LOGGED_IN) | ||
819 | session->state = ISCSI_SESSION_FAILED; | ||
820 | spin_unlock_irqrestore(&session->lock, flags); | ||
821 | |||
822 | skb = alloc_skb(len, GFP_ATOMIC); | 842 | skb = alloc_skb(len, GFP_ATOMIC); |
823 | if (!skb) { | 843 | if (!skb) { |
824 | iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored " | 844 | iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored " |