]> git.pld-linux.org Git - packages/kernel.git/blob - linux-2.4.1-scsi-reset.patch
- obsolete
[packages/kernel.git] / linux-2.4.1-scsi-reset.patch
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;
65 +         SCpnt->request.waiting                = NULL;
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);
This page took 0.133773 seconds and 3 git commands to generate.