]>
Commit | Line | Data |
---|---|---|
95e83f51 JR |
1 | Index: linux/2.4/drivers/scsi/scsi.c |
2 | diff -c linux/2.4/drivers/scsi/scsi.c:1.1.1.5 linux/2.4/drivers/scsi/scsi.c:1.1.1.5.2.3 | |
3 | *** linux/2.4/drivers/scsi/scsi.c:1.1.1.5 Thu Feb 22 16:36:55 2001 | |
4 | --- linux/2.4/drivers/scsi/scsi.c Fri Mar 9 14:45:43 2001 | |
5 | *************** | |
6 | *** 146,152 **** | |
7 | --- 146,157 ---- | |
8 | */ | |
9 | extern void scsi_old_done(Scsi_Cmnd * SCpnt); | |
10 | extern void scsi_old_times_out(Scsi_Cmnd * SCpnt); | |
11 | + extern int scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag); | |
12 | ||
13 | + /* | |
14 | + * private interface into the new error handling code | |
15 | + */ | |
16 | + extern int scsi_new_reset(Scsi_Cmnd *SCpnt, unsigned int flag); | |
17 | ||
18 | /* | |
19 | * Function: scsi_initialize_queue() | |
20 | *************** | |
21 | *** 2657,2662 **** | |
22 | --- 2662,2758 ---- | |
23 | */ | |
24 | scsi_release_commandblocks(SDpnt); | |
25 | kfree(SDpnt); | |
26 | + } | |
27 | + | |
28 | + /* Dummy done routine. We don't want the bogus command used for the | |
29 | + * bus/device reset to find its way into the mid-layer so we intercept | |
30 | + * it here */ | |
31 | + static void | |
32 | + scsi_reset_provider_done_command(Scsi_Cmnd *SCpnt) { | |
33 | + /* Empty function. Some low level drivers will call scsi_done | |
34 | + * (and end up here), others won't bother */ | |
35 | + } | |
36 | + | |
37 | + | |
38 | + /* | |
39 | + * Function: scsi_reset_provider | |
40 | + * | |
41 | + * Purpose: Send requested reset to a bus or device at any phase. | |
42 | + * | |
43 | + * Arguments: device - device to send reset to | |
44 | + * flag - reset type (see scsi.h) | |
45 | + * | |
46 | + * Returns: SUCCESS/FAILURE. | |
47 | + * | |
48 | + * Notes: This is used by the SCSI Generic driver to provide | |
49 | + * Bus/Device reset capability. | |
50 | + */ | |
51 | + int | |
52 | + scsi_reset_provider(Scsi_Device *dev, int flag) | |
53 | + { | |
54 | + int rtn; | |
55 | + Scsi_Cmnd SC; | |
56 | + Scsi_Cmnd *SCpnt = ≻ | |
57 | + | |
58 | + memset(&SCpnt->eh_timeout, 0, sizeof(SCpnt->eh_timeout)); | |
59 | + SCpnt->host = dev->host; | |
60 | + SCpnt->device = dev; | |
61 | + SCpnt->target = dev->id; | |
62 | + SCpnt->lun = dev->lun; | |
63 | + SCpnt->channel = dev->channel; | |
64 | + SCpnt->request.rq_status = RQ_SCSI_BUSY; | |
d30bde3e | 65 | + SCpnt->request.waiting = NULL; |
95e83f51 JR |
66 | + SCpnt->use_sg = 0; |
67 | + SCpnt->old_use_sg = 0; | |
68 | + SCpnt->old_cmd_len = 0; | |
69 | + SCpnt->underflow = 0; | |
70 | + SCpnt->transfersize = 0; | |
71 | + SCpnt->resid = 0; | |
72 | + SCpnt->serial_number = 0; | |
73 | + SCpnt->serial_number_at_timeout = 0; | |
74 | + SCpnt->host_scribble = NULL; | |
75 | + SCpnt->next = NULL; | |
76 | + SCpnt->state = SCSI_STATE_INITIALIZING; | |
77 | + SCpnt->owner = SCSI_OWNER_MIDLEVEL; | |
78 | + | |
79 | + | |
80 | + memset(&SCpnt->cmnd, '\0', sizeof(SCpnt->cmnd)); | |
81 | + | |
82 | + SCpnt->scsi_done = scsi_reset_provider_done_command; | |
83 | + SCpnt->done = NULL; | |
84 | + SCpnt->reset_chain = NULL; | |
85 | + | |
86 | + SCpnt->buffer = NULL; | |
87 | + SCpnt->bufflen = 0; | |
88 | + SCpnt->request_buffer = NULL; | |
89 | + SCpnt->request_bufflen = 0; | |
90 | + | |
91 | + SCpnt->internal_timeout = NORMAL_TIMEOUT; | |
92 | + SCpnt->abort_reason = DID_ABORT; | |
93 | + | |
94 | + SCpnt->cmd_len = 0; | |
95 | + | |
96 | + SCpnt->sc_data_direction = SCSI_DATA_UNKNOWN; | |
97 | + SCpnt->sc_request = NULL; | |
98 | + SCpnt->sc_magic = SCSI_CMND_MAGIC; | |
99 | + | |
100 | + /* sometimes the command can get back into the timer chain, so | |
101 | + * use the pid as an identifier */ | |
102 | + SCpnt->pid = 0; | |
103 | + | |
104 | + | |
105 | + if(dev->host->hostt->use_new_eh_code) { | |
106 | + rtn = scsi_new_reset(SCpnt, flag); | |
107 | + } else { | |
108 | + unsigned long flags; | |
109 | + spin_lock_irqsave(&io_request_lock, flags); | |
110 | + rtn = scsi_old_reset(SCpnt, flag); | |
111 | + spin_unlock_irqrestore(&io_request_lock, flags); | |
112 | + } | |
113 | + | |
114 | + scsi_delete_timer(SCpnt); | |
115 | + | |
116 | + return rtn; | |
117 | } | |
118 | ||
119 | /* | |
120 | Index: linux/2.4/drivers/scsi/scsi.h | |
121 | diff -c linux/2.4/drivers/scsi/scsi.h:1.1.1.3 linux/2.4/drivers/scsi/scsi.h:1.1.1.3.6.1 | |
122 | *** linux/2.4/drivers/scsi/scsi.h:1.1.1.3 Thu Jan 11 11:39:27 2001 | |
123 | --- linux/2.4/drivers/scsi/scsi.h Wed Feb 28 17:37:27 2001 | |
124 | *************** | |
125 | *** 842,847 **** | |
126 | --- 842,855 ---- | |
127 | remove_wait_queue(QUEUE, &wait);\ | |
128 | current->state = TASK_RUNNING; \ | |
129 | }; } | |
130 | + /* old style reset request from external source (private to sg.c and | |
131 | + * scsi_error.c, supplied by scsi_obsolete.c) | |
132 | + * */ | |
133 | + #define SCSI_TRY_RESET_DEVICE 1 | |
134 | + #define SCSI_TRY_RESET_BUS 2 | |
135 | + #define SCSI_TRY_RESET_HOST 3 | |
136 | + | |
137 | + extern int scsi_reset_provider(Scsi_Device *, int); | |
138 | ||
139 | #endif | |
140 | ||
141 | Index: linux/2.4/drivers/scsi/scsi_error.c | |
142 | diff -c linux/2.4/drivers/scsi/scsi_error.c:1.1.1.3 linux/2.4/drivers/scsi/scsi_error.c:1.1.1.3.2.2 | |
143 | *** linux/2.4/drivers/scsi/scsi_error.c:1.1.1.3 Thu Feb 22 16:36:51 2001 | |
144 | --- linux/2.4/drivers/scsi/scsi_error.c Fri Mar 16 10:22:36 2001 | |
145 | *************** | |
146 | *** 996,1004 **** | |
147 | case DID_SOFT_ERROR: | |
148 | goto maybe_retry; | |
149 | ||
150 | case DID_BUS_BUSY: | |
151 | case DID_PARITY: | |
152 | - case DID_ERROR: | |
153 | goto maybe_retry; | |
154 | case DID_TIME_OUT: | |
155 | /* | |
156 | --- 996,1012 ---- | |
157 | case DID_SOFT_ERROR: | |
158 | goto maybe_retry; | |
159 | ||
160 | + case DID_ERROR: | |
161 | + if(msg_byte(SCpnt->result) == COMMAND_COMPLETE | |
162 | + && status_byte(SCpnt->result) == RESERVATION_CONFLICT) | |
163 | + /* execute reservation conflict processing | |
164 | + code lower down */ | |
165 | + break; | |
166 | + /* fall through */ | |
167 | + | |
168 | + | |
169 | case DID_BUS_BUSY: | |
170 | case DID_PARITY: | |
171 | goto maybe_retry; | |
172 | case DID_TIME_OUT: | |
173 | /* | |
174 | *************** | |
175 | *** 1065,1072 **** | |
176 | */ | |
177 | return SUCCESS; | |
178 | case BUSY: | |
179 | - case RESERVATION_CONFLICT: | |
180 | goto maybe_retry; | |
181 | default: | |
182 | return FAILED; | |
183 | } | |
184 | --- 1073,1085 ---- | |
185 | */ | |
186 | return SUCCESS; | |
187 | case BUSY: | |
188 | goto maybe_retry; | |
189 | + | |
190 | + case RESERVATION_CONFLICT: | |
191 | + printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", | |
192 | + SCpnt->host->host_no, SCpnt->channel, | |
193 | + SCpnt->device->id, SCpnt->device->lun); | |
194 | + return SUCCESS; /* causes immediate I/O error */ | |
195 | default: | |
196 | return FAILED; | |
197 | } | |
198 | *************** | |
199 | *** 1959,1964 **** | |
200 | --- 1972,2015 ---- | |
201 | */ | |
202 | if (host->eh_notify != NULL) | |
203 | up(host->eh_notify); | |
204 | + } | |
205 | + | |
206 | + /* | |
207 | + * Function: scsi_new_reset | |
208 | + * | |
209 | + * Purpose: Send requested reset to a bus or device at any phase. | |
210 | + * | |
211 | + * Arguments: SCpnt - command ptr to send reset with (usually a dummy) | |
212 | + * flag - reset type (see scsi.h) | |
213 | + * | |
214 | + * Returns: SUCCESS/FAILURE. | |
215 | + * | |
216 | + * Notes: This is used by the SCSI Generic driver to provide | |
217 | + * Bus/Device reset capability. | |
218 | + */ | |
219 | + int | |
220 | + scsi_new_reset(Scsi_Cmnd *SCpnt, int flag) | |
221 | + { | |
222 | + int rtn; | |
223 | + | |
224 | + switch(flag) { | |
225 | + case SCSI_TRY_RESET_DEVICE: | |
226 | + rtn = scsi_try_bus_device_reset(SCpnt, 0); | |
227 | + if(rtn == SUCCESS) | |
228 | + break; | |
229 | + /* fall through */ | |
230 | + case SCSI_TRY_RESET_BUS: | |
231 | + rtn = scsi_try_bus_reset(SCpnt); | |
232 | + if(rtn == SUCCESS) | |
233 | + break; | |
234 | + /* fall through */ | |
235 | + case SCSI_TRY_RESET_HOST: | |
236 | + rtn = scsi_try_host_reset(SCpnt); | |
237 | + break; | |
238 | + default: | |
239 | + rtn = FAILED; | |
240 | + } | |
241 | + return rtn; | |
242 | } | |
243 | ||
244 | /* | |
245 | Index: linux/2.4/drivers/scsi/scsi_obsolete.c | |
246 | diff -c linux/2.4/drivers/scsi/scsi_obsolete.c:1.1.1.3 linux/2.4/drivers/scsi/scsi_obsolete.c:1.1.1.3.2.1 | |
247 | *** linux/2.4/drivers/scsi/scsi_obsolete.c:1.1.1.3 Thu Feb 22 16:37:01 2001 | |
248 | --- linux/2.4/drivers/scsi/scsi_obsolete.c Wed Feb 28 17:37:27 2001 | |
249 | *************** | |
250 | *** 502,512 **** | |
251 | break; | |
252 | ||
253 | case RESERVATION_CONFLICT: | |
254 | ! printk("scsi%d, channel %d : RESERVATION CONFLICT performing" | |
255 | ! " reset.\n", SCpnt->host->host_no, SCpnt->channel); | |
256 | ! scsi_reset(SCpnt, SCSI_RESET_SYNCHRONOUS); | |
257 | ! status = REDO; | |
258 | ! break; | |
259 | default: | |
260 | printk("Internal error %s %d \n" | |
261 | "status byte = %d \n", __FILE__, | |
262 | --- 502,518 ---- | |
263 | break; | |
264 | ||
265 | case RESERVATION_CONFLICT: | |
266 | ! /* Most HAs will return an | |
267 | ! * error for this, so usually | |
268 | ! * reservation conflicts will | |
269 | ! * be processed under | |
270 | ! * DID_ERROR code */ | |
271 | ! printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", | |
272 | ! SCpnt->host->host_no, SCpnt->channel, | |
273 | ! SCpnt->device->id, SCpnt->device->lun); | |
274 | ! status = CMD_FINISHED; /* returns I/O error */ | |
275 | ! break; | |
276 | ! | |
277 | default: | |
278 | printk("Internal error %s %d \n" | |
279 | "status byte = %d \n", __FILE__, | |
280 | *************** | |
281 | *** 556,561 **** | |
282 | --- 562,575 ---- | |
283 | exit = (DRIVER_HARD | SUGGEST_ABORT); | |
284 | break; | |
285 | case DID_ERROR: | |
286 | + if(msg_byte(result) == COMMAND_COMPLETE | |
287 | + && status_byte(result) == RESERVATION_CONFLICT) { | |
288 | + printk("scsi%d (%d,%d,%d) : RESERVATION CONFLICT\n", | |
289 | + SCpnt->host->host_no, SCpnt->channel, | |
290 | + SCpnt->device->id, SCpnt->device->lun); | |
291 | + status = CMD_FINISHED; /* returns I/O error */ | |
292 | + break; | |
293 | + } | |
294 | status = MAYREDO; | |
295 | exit = (DRIVER_HARD | SUGGEST_ABORT); | |
296 | break; | |
297 | *************** | |
298 | *** 1097,1102 **** | |
299 | --- 1111,1141 ---- | |
300 | return rtn; | |
301 | } | |
302 | ||
303 | + | |
304 | + /* This function exports SCSI Bus, Device or Host reset capability | |
305 | + * and is for use with the SCSI generic driver. | |
306 | + */ | |
307 | + int | |
308 | + scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag) | |
309 | + { | |
310 | + int rtn; | |
311 | + unsigned int old_flags = SCSI_RESET_SYNCHRONOUS; | |
312 | + | |
313 | + switch(flag) { | |
314 | + case SCSI_TRY_RESET_DEVICE: | |
315 | + /* no suggestion flags to add, device reset is default */ | |
316 | + break; | |
317 | + case SCSI_TRY_RESET_BUS: | |
318 | + old_flags |= SCSI_RESET_SUGGEST_BUS_RESET; | |
319 | + break; | |
320 | + case SCSI_TRY_RESET_HOST: | |
321 | + old_flags |= SCSI_RESET_SUGGEST_HOST_RESET; | |
322 | + break; | |
323 | + default: | |
324 | + return FAILED; | |
325 | + } | |
326 | + return (scsi_reset(SCpnt, old_flags) == 0) ? SUCCESS : FAILED; | |
327 | + } | |
328 | ||
329 | /* | |
330 | * Overrides for Emacs so that we follow Linus's tabbing style. | |
331 | Index: linux/2.4/drivers/scsi/scsi_syms.c | |
332 | diff -c linux/2.4/drivers/scsi/scsi_syms.c:1.1.1.3 linux/2.4/drivers/scsi/scsi_syms.c:1.1.1.3.2.1 | |
333 | *** linux/2.4/drivers/scsi/scsi_syms.c:1.1.1.3 Thu Feb 22 16:37:31 2001 | |
334 | --- linux/2.4/drivers/scsi/scsi_syms.c Wed Feb 28 17:37:27 2001 | |
335 | *************** | |
336 | *** 84,89 **** | |
337 | --- 84,93 ---- | |
338 | EXPORT_SYMBOL(scsi_deregister_blocked_host); | |
339 | ||
340 | /* | |
341 | + * This symbol is for the sg device only | |
342 | + */ | |
343 | + EXPORT_SYMBOL(scsi_reset_provider); | |
344 | + /* | |
345 | * These are here only while I debug the rest of the scsi stuff. | |
346 | */ | |
347 | EXPORT_SYMBOL(scsi_hostlist); |