]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.1-scsi-reset.patch
run depmod before geninitrd and rc-boot
[packages/kernel.git] / linux-2.4.1-scsi-reset.patch
CommitLineData
95e83f51
JR
1Index: linux/2.4/drivers/scsi/scsi.c
2diff -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 /*
120Index: linux/2.4/drivers/scsi/scsi.h
121diff -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
141Index: linux/2.4/drivers/scsi/scsi_error.c
142diff -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 /*
245Index: linux/2.4/drivers/scsi/scsi_obsolete.c
246diff -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.
331Index: linux/2.4/drivers/scsi/scsi_syms.c
332diff -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);
This page took 0.076655 seconds and 4 git commands to generate.