diff options
Diffstat (limited to 'drivers/s390/block/dasd_3990_erp.c')
-rw-r--r-- | drivers/s390/block/dasd_3990_erp.c | 358 |
1 files changed, 126 insertions, 232 deletions
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index c02f960eae15..c361ab69ec00 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -26,158 +26,6 @@ struct DCTL_data { | |||
26 | 26 | ||
27 | /* | 27 | /* |
28 | ***************************************************************************** | 28 | ***************************************************************************** |
29 | * SECTION ERP EXAMINATION | ||
30 | ***************************************************************************** | ||
31 | */ | ||
32 | |||
33 | /* | ||
34 | * DASD_3990_ERP_EXAMINE_24 | ||
35 | * | ||
36 | * DESCRIPTION | ||
37 | * Checks only for fatal (unrecoverable) error. | ||
38 | * A detailed examination of the sense data is done later outside | ||
39 | * the interrupt handler. | ||
40 | * | ||
41 | * Each bit configuration leading to an action code 2 (Exit with | ||
42 | * programming error or unusual condition indication) | ||
43 | * are handled as fatal errors. | ||
44 | * | ||
45 | * All other configurations are handled as recoverable errors. | ||
46 | * | ||
47 | * RETURN VALUES | ||
48 | * dasd_era_fatal for all fatal (unrecoverable errors) | ||
49 | * dasd_era_recover for all others. | ||
50 | */ | ||
51 | static dasd_era_t | ||
52 | dasd_3990_erp_examine_24(struct dasd_ccw_req * cqr, char *sense) | ||
53 | { | ||
54 | |||
55 | struct dasd_device *device = cqr->device; | ||
56 | |||
57 | /* check for 'Command Reject' */ | ||
58 | if ((sense[0] & SNS0_CMD_REJECT) && | ||
59 | (!(sense[2] & SNS2_ENV_DATA_PRESENT))) { | ||
60 | |||
61 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
62 | "EXAMINE 24: Command Reject detected - " | ||
63 | "fatal error"); | ||
64 | |||
65 | return dasd_era_fatal; | ||
66 | } | ||
67 | |||
68 | /* check for 'Invalid Track Format' */ | ||
69 | if ((sense[1] & SNS1_INV_TRACK_FORMAT) && | ||
70 | (!(sense[2] & SNS2_ENV_DATA_PRESENT))) { | ||
71 | |||
72 | DEV_MESSAGE(KERN_ERR, device, "%s", | ||
73 | "EXAMINE 24: Invalid Track Format detected " | ||
74 | "- fatal error"); | ||
75 | |||
76 | return dasd_era_fatal; | ||
77 | } | ||
78 | |||
79 | /* check for 'No Record Found' */ | ||
80 | if (sense[1] & SNS1_NO_REC_FOUND) { | ||
81 | |||
82 | /* FIXME: fatal error ?!? */ | ||
83 | DEV_MESSAGE(KERN_ERR, device, | ||
84 | "EXAMINE 24: No Record Found detected %s", | ||
85 | device->state <= DASD_STATE_BASIC ? | ||
86 | " " : "- fatal error"); | ||
87 | |||
88 | return dasd_era_fatal; | ||
89 | } | ||
90 | |||
91 | /* return recoverable for all others */ | ||
92 | return dasd_era_recover; | ||
93 | } /* END dasd_3990_erp_examine_24 */ | ||
94 | |||
95 | /* | ||
96 | * DASD_3990_ERP_EXAMINE_32 | ||
97 | * | ||
98 | * DESCRIPTION | ||
99 | * Checks only for fatal/no/recoverable error. | ||
100 | * A detailed examination of the sense data is done later outside | ||
101 | * the interrupt handler. | ||
102 | * | ||
103 | * RETURN VALUES | ||
104 | * dasd_era_none no error | ||
105 | * dasd_era_fatal for all fatal (unrecoverable errors) | ||
106 | * dasd_era_recover for recoverable others. | ||
107 | */ | ||
108 | static dasd_era_t | ||
109 | dasd_3990_erp_examine_32(struct dasd_ccw_req * cqr, char *sense) | ||
110 | { | ||
111 | |||
112 | struct dasd_device *device = cqr->device; | ||
113 | |||
114 | switch (sense[25]) { | ||
115 | case 0x00: | ||
116 | return dasd_era_none; | ||
117 | |||
118 | case 0x01: | ||
119 | DEV_MESSAGE(KERN_ERR, device, "%s", "EXAMINE 32: fatal error"); | ||
120 | |||
121 | return dasd_era_fatal; | ||
122 | |||
123 | default: | ||
124 | |||
125 | return dasd_era_recover; | ||
126 | } | ||
127 | |||
128 | } /* end dasd_3990_erp_examine_32 */ | ||
129 | |||
130 | /* | ||
131 | * DASD_3990_ERP_EXAMINE | ||
132 | * | ||
133 | * DESCRIPTION | ||
134 | * Checks only for fatal/no/recover error. | ||
135 | * A detailed examination of the sense data is done later outside | ||
136 | * the interrupt handler. | ||
137 | * | ||
138 | * The logic is based on the 'IBM 3990 Storage Control Reference' manual | ||
139 | * 'Chapter 7. Error Recovery Procedures'. | ||
140 | * | ||
141 | * RETURN VALUES | ||
142 | * dasd_era_none no error | ||
143 | * dasd_era_fatal for all fatal (unrecoverable errors) | ||
144 | * dasd_era_recover for all others. | ||
145 | */ | ||
146 | dasd_era_t | ||
147 | dasd_3990_erp_examine(struct dasd_ccw_req * cqr, struct irb * irb) | ||
148 | { | ||
149 | |||
150 | char *sense = irb->ecw; | ||
151 | dasd_era_t era = dasd_era_recover; | ||
152 | struct dasd_device *device = cqr->device; | ||
153 | |||
154 | /* check for successful execution first */ | ||
155 | if (irb->scsw.cstat == 0x00 && | ||
156 | irb->scsw.dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END)) | ||
157 | return dasd_era_none; | ||
158 | |||
159 | /* distinguish between 24 and 32 byte sense data */ | ||
160 | if (sense[27] & DASD_SENSE_BIT_0) { | ||
161 | |||
162 | era = dasd_3990_erp_examine_24(cqr, sense); | ||
163 | |||
164 | } else { | ||
165 | |||
166 | era = dasd_3990_erp_examine_32(cqr, sense); | ||
167 | |||
168 | } | ||
169 | |||
170 | /* log the erp chain if fatal error occurred */ | ||
171 | if ((era == dasd_era_fatal) && (device->state >= DASD_STATE_READY)) { | ||
172 | dasd_log_sense(cqr, irb); | ||
173 | } | ||
174 | |||
175 | return era; | ||
176 | |||
177 | } /* END dasd_3990_erp_examine */ | ||
178 | |||
179 | /* | ||
180 | ***************************************************************************** | ||
181 | * SECTION ERP HANDLING | 29 | * SECTION ERP HANDLING |
182 | ***************************************************************************** | 30 | ***************************************************************************** |
183 | */ | 31 | */ |
@@ -206,7 +54,7 @@ dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status) | |||
206 | { | 54 | { |
207 | struct dasd_ccw_req *cqr = erp->refers; | 55 | struct dasd_ccw_req *cqr = erp->refers; |
208 | 56 | ||
209 | dasd_free_erp_request(erp, erp->device); | 57 | dasd_free_erp_request(erp, erp->memdev); |
210 | cqr->status = final_status; | 58 | cqr->status = final_status; |
211 | return cqr; | 59 | return cqr; |
212 | 60 | ||
@@ -224,15 +72,17 @@ static void | |||
224 | dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) | 72 | dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires) |
225 | { | 73 | { |
226 | 74 | ||
227 | struct dasd_device *device = erp->device; | 75 | struct dasd_device *device = erp->startdev; |
76 | unsigned long flags; | ||
228 | 77 | ||
229 | DEV_MESSAGE(KERN_INFO, device, | 78 | DEV_MESSAGE(KERN_INFO, device, |
230 | "blocking request queue for %is", expires/HZ); | 79 | "blocking request queue for %is", expires/HZ); |
231 | 80 | ||
81 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
232 | device->stopped |= DASD_STOPPED_PENDING; | 82 | device->stopped |= DASD_STOPPED_PENDING; |
233 | erp->status = DASD_CQR_QUEUED; | 83 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); |
234 | 84 | erp->status = DASD_CQR_FILLED; | |
235 | dasd_set_timer(device, expires); | 85 | dasd_block_set_timer(device->block, expires); |
236 | } | 86 | } |
237 | 87 | ||
238 | /* | 88 | /* |
@@ -251,7 +101,7 @@ static struct dasd_ccw_req * | |||
251 | dasd_3990_erp_int_req(struct dasd_ccw_req * erp) | 101 | dasd_3990_erp_int_req(struct dasd_ccw_req * erp) |
252 | { | 102 | { |
253 | 103 | ||
254 | struct dasd_device *device = erp->device; | 104 | struct dasd_device *device = erp->startdev; |
255 | 105 | ||
256 | /* first time set initial retry counter and erp_function */ | 106 | /* first time set initial retry counter and erp_function */ |
257 | /* and retry once without blocking queue */ | 107 | /* and retry once without blocking queue */ |
@@ -292,11 +142,14 @@ dasd_3990_erp_int_req(struct dasd_ccw_req * erp) | |||
292 | static void | 142 | static void |
293 | dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | 143 | dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) |
294 | { | 144 | { |
295 | struct dasd_device *device = erp->device; | 145 | struct dasd_device *device = erp->startdev; |
296 | __u8 opm; | 146 | __u8 opm; |
147 | unsigned long flags; | ||
297 | 148 | ||
298 | /* try alternate valid path */ | 149 | /* try alternate valid path */ |
150 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
299 | opm = ccw_device_get_path_mask(device->cdev); | 151 | opm = ccw_device_get_path_mask(device->cdev); |
152 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
300 | //FIXME: start with get_opm ? | 153 | //FIXME: start with get_opm ? |
301 | if (erp->lpm == 0) | 154 | if (erp->lpm == 0) |
302 | erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum); | 155 | erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum); |
@@ -309,9 +162,8 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | |||
309 | "try alternate lpm=%x (lpum=%x / opm=%x)", | 162 | "try alternate lpm=%x (lpum=%x / opm=%x)", |
310 | erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm); | 163 | erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm); |
311 | 164 | ||
312 | /* reset status to queued to handle the request again... */ | 165 | /* reset status to submit the request again... */ |
313 | if (erp->status > DASD_CQR_QUEUED) | 166 | erp->status = DASD_CQR_FILLED; |
314 | erp->status = DASD_CQR_QUEUED; | ||
315 | erp->retries = 1; | 167 | erp->retries = 1; |
316 | } else { | 168 | } else { |
317 | DEV_MESSAGE(KERN_ERR, device, | 169 | DEV_MESSAGE(KERN_ERR, device, |
@@ -320,8 +172,7 @@ dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp) | |||
320 | erp->irb.esw.esw0.sublog.lpum, opm); | 172 | erp->irb.esw.esw0.sublog.lpum, opm); |
321 | 173 | ||
322 | /* post request with permanent error */ | 174 | /* post request with permanent error */ |
323 | if (erp->status > DASD_CQR_QUEUED) | 175 | erp->status = DASD_CQR_FAILED; |
324 | erp->status = DASD_CQR_FAILED; | ||
325 | } | 176 | } |
326 | } /* end dasd_3990_erp_alternate_path */ | 177 | } /* end dasd_3990_erp_alternate_path */ |
327 | 178 | ||
@@ -344,14 +195,14 @@ static struct dasd_ccw_req * | |||
344 | dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) | 195 | dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) |
345 | { | 196 | { |
346 | 197 | ||
347 | struct dasd_device *device = erp->device; | 198 | struct dasd_device *device = erp->startdev; |
348 | struct DCTL_data *DCTL_data; | 199 | struct DCTL_data *DCTL_data; |
349 | struct ccw1 *ccw; | 200 | struct ccw1 *ccw; |
350 | struct dasd_ccw_req *dctl_cqr; | 201 | struct dasd_ccw_req *dctl_cqr; |
351 | 202 | ||
352 | dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1, | 203 | dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1, |
353 | sizeof (struct DCTL_data), | 204 | sizeof(struct DCTL_data), |
354 | erp->device); | 205 | device); |
355 | if (IS_ERR(dctl_cqr)) { | 206 | if (IS_ERR(dctl_cqr)) { |
356 | DEV_MESSAGE(KERN_ERR, device, "%s", | 207 | DEV_MESSAGE(KERN_ERR, device, "%s", |
357 | "Unable to allocate DCTL-CQR"); | 208 | "Unable to allocate DCTL-CQR"); |
@@ -365,13 +216,14 @@ dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier) | |||
365 | DCTL_data->modifier = modifier; | 216 | DCTL_data->modifier = modifier; |
366 | 217 | ||
367 | ccw = dctl_cqr->cpaddr; | 218 | ccw = dctl_cqr->cpaddr; |
368 | memset(ccw, 0, sizeof (struct ccw1)); | 219 | memset(ccw, 0, sizeof(struct ccw1)); |
369 | ccw->cmd_code = CCW_CMD_DCTL; | 220 | ccw->cmd_code = CCW_CMD_DCTL; |
370 | ccw->count = 4; | 221 | ccw->count = 4; |
371 | ccw->cda = (__u32)(addr_t) DCTL_data; | 222 | ccw->cda = (__u32)(addr_t) DCTL_data; |
372 | dctl_cqr->function = dasd_3990_erp_DCTL; | 223 | dctl_cqr->function = dasd_3990_erp_DCTL; |
373 | dctl_cqr->refers = erp; | 224 | dctl_cqr->refers = erp; |
374 | dctl_cqr->device = erp->device; | 225 | dctl_cqr->startdev = device; |
226 | dctl_cqr->memdev = device; | ||
375 | dctl_cqr->magic = erp->magic; | 227 | dctl_cqr->magic = erp->magic; |
376 | dctl_cqr->expires = 5 * 60 * HZ; | 228 | dctl_cqr->expires = 5 * 60 * HZ; |
377 | dctl_cqr->retries = 2; | 229 | dctl_cqr->retries = 2; |
@@ -435,7 +287,7 @@ static struct dasd_ccw_req * | |||
435 | dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | 287 | dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) |
436 | { | 288 | { |
437 | 289 | ||
438 | struct dasd_device *device = erp->device; | 290 | struct dasd_device *device = erp->startdev; |
439 | 291 | ||
440 | /* first time set initial retry counter and erp_function */ | 292 | /* first time set initial retry counter and erp_function */ |
441 | /* and retry once without waiting for state change pending */ | 293 | /* and retry once without waiting for state change pending */ |
@@ -472,7 +324,7 @@ dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense) | |||
472 | "redriving request immediately, " | 324 | "redriving request immediately, " |
473 | "%d retries left", | 325 | "%d retries left", |
474 | erp->retries); | 326 | erp->retries); |
475 | erp->status = DASD_CQR_QUEUED; | 327 | erp->status = DASD_CQR_FILLED; |
476 | } | 328 | } |
477 | } | 329 | } |
478 | 330 | ||
@@ -530,7 +382,7 @@ static void | |||
530 | dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) | 382 | dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense) |
531 | { | 383 | { |
532 | 384 | ||
533 | struct dasd_device *device = erp->device; | 385 | struct dasd_device *device = erp->startdev; |
534 | char msg_format = (sense[7] & 0xF0); | 386 | char msg_format = (sense[7] & 0xF0); |
535 | char msg_no = (sense[7] & 0x0F); | 387 | char msg_no = (sense[7] & 0x0F); |
536 | 388 | ||
@@ -1157,7 +1009,7 @@ static struct dasd_ccw_req * | |||
1157 | dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) | 1009 | dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense) |
1158 | { | 1010 | { |
1159 | 1011 | ||
1160 | struct dasd_device *device = erp->device; | 1012 | struct dasd_device *device = erp->startdev; |
1161 | 1013 | ||
1162 | erp->function = dasd_3990_erp_com_rej; | 1014 | erp->function = dasd_3990_erp_com_rej; |
1163 | 1015 | ||
@@ -1198,7 +1050,7 @@ static struct dasd_ccw_req * | |||
1198 | dasd_3990_erp_bus_out(struct dasd_ccw_req * erp) | 1050 | dasd_3990_erp_bus_out(struct dasd_ccw_req * erp) |
1199 | { | 1051 | { |
1200 | 1052 | ||
1201 | struct dasd_device *device = erp->device; | 1053 | struct dasd_device *device = erp->startdev; |
1202 | 1054 | ||
1203 | /* first time set initial retry counter and erp_function */ | 1055 | /* first time set initial retry counter and erp_function */ |
1204 | /* and retry once without blocking queue */ | 1056 | /* and retry once without blocking queue */ |
@@ -1237,7 +1089,7 @@ static struct dasd_ccw_req * | |||
1237 | dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) | 1089 | dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) |
1238 | { | 1090 | { |
1239 | 1091 | ||
1240 | struct dasd_device *device = erp->device; | 1092 | struct dasd_device *device = erp->startdev; |
1241 | 1093 | ||
1242 | erp->function = dasd_3990_erp_equip_check; | 1094 | erp->function = dasd_3990_erp_equip_check; |
1243 | 1095 | ||
@@ -1279,7 +1131,6 @@ dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense) | |||
1279 | 1131 | ||
1280 | erp = dasd_3990_erp_action_5(erp); | 1132 | erp = dasd_3990_erp_action_5(erp); |
1281 | } | 1133 | } |
1282 | |||
1283 | return erp; | 1134 | return erp; |
1284 | 1135 | ||
1285 | } /* end dasd_3990_erp_equip_check */ | 1136 | } /* end dasd_3990_erp_equip_check */ |
@@ -1299,7 +1150,7 @@ static struct dasd_ccw_req * | |||
1299 | dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) | 1150 | dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense) |
1300 | { | 1151 | { |
1301 | 1152 | ||
1302 | struct dasd_device *device = erp->device; | 1153 | struct dasd_device *device = erp->startdev; |
1303 | 1154 | ||
1304 | erp->function = dasd_3990_erp_data_check; | 1155 | erp->function = dasd_3990_erp_data_check; |
1305 | 1156 | ||
@@ -1358,7 +1209,7 @@ static struct dasd_ccw_req * | |||
1358 | dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense) | 1209 | dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense) |
1359 | { | 1210 | { |
1360 | 1211 | ||
1361 | struct dasd_device *device = erp->device; | 1212 | struct dasd_device *device = erp->startdev; |
1362 | 1213 | ||
1363 | erp->function = dasd_3990_erp_overrun; | 1214 | erp->function = dasd_3990_erp_overrun; |
1364 | 1215 | ||
@@ -1387,7 +1238,7 @@ static struct dasd_ccw_req * | |||
1387 | dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) | 1238 | dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) |
1388 | { | 1239 | { |
1389 | 1240 | ||
1390 | struct dasd_device *device = erp->device; | 1241 | struct dasd_device *device = erp->startdev; |
1391 | 1242 | ||
1392 | erp->function = dasd_3990_erp_inv_format; | 1243 | erp->function = dasd_3990_erp_inv_format; |
1393 | 1244 | ||
@@ -1403,8 +1254,7 @@ dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense) | |||
1403 | 1254 | ||
1404 | } else { | 1255 | } else { |
1405 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1256 | DEV_MESSAGE(KERN_ERR, device, "%s", |
1406 | "Invalid Track Format - Fatal error should have " | 1257 | "Invalid Track Format - Fatal error"); |
1407 | "been handled within the interrupt handler"); | ||
1408 | 1258 | ||
1409 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 1259 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
1410 | } | 1260 | } |
@@ -1428,7 +1278,7 @@ static struct dasd_ccw_req * | |||
1428 | dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense) | 1278 | dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense) |
1429 | { | 1279 | { |
1430 | 1280 | ||
1431 | struct dasd_device *device = default_erp->device; | 1281 | struct dasd_device *device = default_erp->startdev; |
1432 | 1282 | ||
1433 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1283 | DEV_MESSAGE(KERN_ERR, device, "%s", |
1434 | "End-of-Cylinder - must never happen"); | 1284 | "End-of-Cylinder - must never happen"); |
@@ -1453,7 +1303,7 @@ static struct dasd_ccw_req * | |||
1453 | dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) | 1303 | dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) |
1454 | { | 1304 | { |
1455 | 1305 | ||
1456 | struct dasd_device *device = erp->device; | 1306 | struct dasd_device *device = erp->startdev; |
1457 | 1307 | ||
1458 | erp->function = dasd_3990_erp_env_data; | 1308 | erp->function = dasd_3990_erp_env_data; |
1459 | 1309 | ||
@@ -1463,11 +1313,9 @@ dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense) | |||
1463 | 1313 | ||
1464 | /* don't retry on disabled interface */ | 1314 | /* don't retry on disabled interface */ |
1465 | if (sense[7] != 0x0F) { | 1315 | if (sense[7] != 0x0F) { |
1466 | |||
1467 | erp = dasd_3990_erp_action_4(erp, sense); | 1316 | erp = dasd_3990_erp_action_4(erp, sense); |
1468 | } else { | 1317 | } else { |
1469 | 1318 | erp->status = DASD_CQR_FILLED; | |
1470 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_IN_IO); | ||
1471 | } | 1319 | } |
1472 | 1320 | ||
1473 | return erp; | 1321 | return erp; |
@@ -1490,11 +1338,10 @@ static struct dasd_ccw_req * | |||
1490 | dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense) | 1338 | dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense) |
1491 | { | 1339 | { |
1492 | 1340 | ||
1493 | struct dasd_device *device = default_erp->device; | 1341 | struct dasd_device *device = default_erp->startdev; |
1494 | 1342 | ||
1495 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1343 | DEV_MESSAGE(KERN_ERR, device, "%s", |
1496 | "No Record Found - Fatal error should " | 1344 | "No Record Found - Fatal error "); |
1497 | "have been handled within the interrupt handler"); | ||
1498 | 1345 | ||
1499 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); | 1346 | return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED); |
1500 | 1347 | ||
@@ -1517,7 +1364,7 @@ static struct dasd_ccw_req * | |||
1517 | dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) | 1364 | dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) |
1518 | { | 1365 | { |
1519 | 1366 | ||
1520 | struct dasd_device *device = erp->device; | 1367 | struct dasd_device *device = erp->startdev; |
1521 | 1368 | ||
1522 | DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected"); | 1369 | DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected"); |
1523 | 1370 | ||
@@ -1526,6 +1373,43 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp) | |||
1526 | } /* end dasd_3990_erp_file_prot */ | 1373 | } /* end dasd_3990_erp_file_prot */ |
1527 | 1374 | ||
1528 | /* | 1375 | /* |
1376 | * DASD_3990_ERP_INSPECT_ALIAS | ||
1377 | * | ||
1378 | * DESCRIPTION | ||
1379 | * Checks if the original request was started on an alias device. | ||
1380 | * If yes, it modifies the original and the erp request so that | ||
1381 | * the erp request can be started on a base device. | ||
1382 | * | ||
1383 | * PARAMETER | ||
1384 | * erp pointer to the currently created default ERP | ||
1385 | * | ||
1386 | * RETURN VALUES | ||
1387 | * erp pointer to the modified ERP, or NULL | ||
1388 | */ | ||
1389 | |||
1390 | static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( | ||
1391 | struct dasd_ccw_req *erp) | ||
1392 | { | ||
1393 | struct dasd_ccw_req *cqr = erp->refers; | ||
1394 | |||
1395 | if (cqr->block && | ||
1396 | (cqr->block->base != cqr->startdev)) { | ||
1397 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { | ||
1398 | DEV_MESSAGE(KERN_ERR, cqr->startdev, | ||
1399 | "ERP on alias device for request %p," | ||
1400 | " recover on base device %s", cqr, | ||
1401 | cqr->block->base->cdev->dev.bus_id); | ||
1402 | } | ||
1403 | dasd_eckd_reset_ccw_to_base_io(cqr); | ||
1404 | erp->startdev = cqr->block->base; | ||
1405 | erp->function = dasd_3990_erp_inspect_alias; | ||
1406 | return erp; | ||
1407 | } else | ||
1408 | return NULL; | ||
1409 | } | ||
1410 | |||
1411 | |||
1412 | /* | ||
1529 | * DASD_3990_ERP_INSPECT_24 | 1413 | * DASD_3990_ERP_INSPECT_24 |
1530 | * | 1414 | * |
1531 | * DESCRIPTION | 1415 | * DESCRIPTION |
@@ -1623,7 +1507,7 @@ static struct dasd_ccw_req * | |||
1623 | dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) | 1507 | dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense) |
1624 | { | 1508 | { |
1625 | 1509 | ||
1626 | struct dasd_device *device = erp->device; | 1510 | struct dasd_device *device = erp->startdev; |
1627 | 1511 | ||
1628 | erp->retries = 256; | 1512 | erp->retries = 256; |
1629 | erp->function = dasd_3990_erp_action_10_32; | 1513 | erp->function = dasd_3990_erp_action_10_32; |
@@ -1657,13 +1541,14 @@ static struct dasd_ccw_req * | |||
1657 | dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | 1541 | dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) |
1658 | { | 1542 | { |
1659 | 1543 | ||
1660 | struct dasd_device *device = default_erp->device; | 1544 | struct dasd_device *device = default_erp->startdev; |
1661 | __u32 cpa = 0; | 1545 | __u32 cpa = 0; |
1662 | struct dasd_ccw_req *cqr; | 1546 | struct dasd_ccw_req *cqr; |
1663 | struct dasd_ccw_req *erp; | 1547 | struct dasd_ccw_req *erp; |
1664 | struct DE_eckd_data *DE_data; | 1548 | struct DE_eckd_data *DE_data; |
1549 | struct PFX_eckd_data *PFX_data; | ||
1665 | char *LO_data; /* LO_eckd_data_t */ | 1550 | char *LO_data; /* LO_eckd_data_t */ |
1666 | struct ccw1 *ccw; | 1551 | struct ccw1 *ccw, *oldccw; |
1667 | 1552 | ||
1668 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1553 | DEV_MESSAGE(KERN_DEBUG, device, "%s", |
1669 | "Write not finished because of unexpected condition"); | 1554 | "Write not finished because of unexpected condition"); |
@@ -1702,8 +1587,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1702 | /* Build new ERP request including DE/LO */ | 1587 | /* Build new ERP request including DE/LO */ |
1703 | erp = dasd_alloc_erp_request((char *) &cqr->magic, | 1588 | erp = dasd_alloc_erp_request((char *) &cqr->magic, |
1704 | 2 + 1,/* DE/LO + TIC */ | 1589 | 2 + 1,/* DE/LO + TIC */ |
1705 | sizeof (struct DE_eckd_data) + | 1590 | sizeof(struct DE_eckd_data) + |
1706 | sizeof (struct LO_eckd_data), device); | 1591 | sizeof(struct LO_eckd_data), device); |
1707 | 1592 | ||
1708 | if (IS_ERR(erp)) { | 1593 | if (IS_ERR(erp)) { |
1709 | DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP"); | 1594 | DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP"); |
@@ -1712,10 +1597,16 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1712 | 1597 | ||
1713 | /* use original DE */ | 1598 | /* use original DE */ |
1714 | DE_data = erp->data; | 1599 | DE_data = erp->data; |
1715 | memcpy(DE_data, cqr->data, sizeof (struct DE_eckd_data)); | 1600 | oldccw = cqr->cpaddr; |
1601 | if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) { | ||
1602 | PFX_data = cqr->data; | ||
1603 | memcpy(DE_data, &PFX_data->define_extend, | ||
1604 | sizeof(struct DE_eckd_data)); | ||
1605 | } else | ||
1606 | memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data)); | ||
1716 | 1607 | ||
1717 | /* create LO */ | 1608 | /* create LO */ |
1718 | LO_data = erp->data + sizeof (struct DE_eckd_data); | 1609 | LO_data = erp->data + sizeof(struct DE_eckd_data); |
1719 | 1610 | ||
1720 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { | 1611 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { |
1721 | 1612 | ||
@@ -1748,7 +1639,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1748 | 1639 | ||
1749 | /* create DE ccw */ | 1640 | /* create DE ccw */ |
1750 | ccw = erp->cpaddr; | 1641 | ccw = erp->cpaddr; |
1751 | memset(ccw, 0, sizeof (struct ccw1)); | 1642 | memset(ccw, 0, sizeof(struct ccw1)); |
1752 | ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT; | 1643 | ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT; |
1753 | ccw->flags = CCW_FLAG_CC; | 1644 | ccw->flags = CCW_FLAG_CC; |
1754 | ccw->count = 16; | 1645 | ccw->count = 16; |
@@ -1756,7 +1647,7 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1756 | 1647 | ||
1757 | /* create LO ccw */ | 1648 | /* create LO ccw */ |
1758 | ccw++; | 1649 | ccw++; |
1759 | memset(ccw, 0, sizeof (struct ccw1)); | 1650 | memset(ccw, 0, sizeof(struct ccw1)); |
1760 | ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; | 1651 | ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; |
1761 | ccw->flags = CCW_FLAG_CC; | 1652 | ccw->flags = CCW_FLAG_CC; |
1762 | ccw->count = 16; | 1653 | ccw->count = 16; |
@@ -1770,7 +1661,8 @@ dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense) | |||
1770 | /* fill erp related fields */ | 1661 | /* fill erp related fields */ |
1771 | erp->function = dasd_3990_erp_action_1B_32; | 1662 | erp->function = dasd_3990_erp_action_1B_32; |
1772 | erp->refers = default_erp->refers; | 1663 | erp->refers = default_erp->refers; |
1773 | erp->device = device; | 1664 | erp->startdev = device; |
1665 | erp->memdev = device; | ||
1774 | erp->magic = default_erp->magic; | 1666 | erp->magic = default_erp->magic; |
1775 | erp->expires = 0; | 1667 | erp->expires = 0; |
1776 | erp->retries = 256; | 1668 | erp->retries = 256; |
@@ -1803,7 +1695,7 @@ static struct dasd_ccw_req * | |||
1803 | dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | 1695 | dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) |
1804 | { | 1696 | { |
1805 | 1697 | ||
1806 | struct dasd_device *device = previous_erp->device; | 1698 | struct dasd_device *device = previous_erp->startdev; |
1807 | __u32 cpa = 0; | 1699 | __u32 cpa = 0; |
1808 | struct dasd_ccw_req *cqr; | 1700 | struct dasd_ccw_req *cqr; |
1809 | struct dasd_ccw_req *erp; | 1701 | struct dasd_ccw_req *erp; |
@@ -1827,7 +1719,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1827 | DEV_MESSAGE(KERN_DEBUG, device, "%s", | 1719 | DEV_MESSAGE(KERN_DEBUG, device, "%s", |
1828 | "Imprecise ending is set - just retry"); | 1720 | "Imprecise ending is set - just retry"); |
1829 | 1721 | ||
1830 | previous_erp->status = DASD_CQR_QUEUED; | 1722 | previous_erp->status = DASD_CQR_FILLED; |
1831 | 1723 | ||
1832 | return previous_erp; | 1724 | return previous_erp; |
1833 | } | 1725 | } |
@@ -1850,7 +1742,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1850 | erp = previous_erp; | 1742 | erp = previous_erp; |
1851 | 1743 | ||
1852 | /* update the LO with the new returned sense data */ | 1744 | /* update the LO with the new returned sense data */ |
1853 | LO_data = erp->data + sizeof (struct DE_eckd_data); | 1745 | LO_data = erp->data + sizeof(struct DE_eckd_data); |
1854 | 1746 | ||
1855 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { | 1747 | if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) { |
1856 | 1748 | ||
@@ -1889,7 +1781,7 @@ dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense) | |||
1889 | ccw++; /* addr of TIC ccw */ | 1781 | ccw++; /* addr of TIC ccw */ |
1890 | ccw->cda = cpa; | 1782 | ccw->cda = cpa; |
1891 | 1783 | ||
1892 | erp->status = DASD_CQR_QUEUED; | 1784 | erp->status = DASD_CQR_FILLED; |
1893 | 1785 | ||
1894 | return erp; | 1786 | return erp; |
1895 | 1787 | ||
@@ -1968,9 +1860,7 @@ dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense) | |||
1968 | * try further actions. */ | 1860 | * try further actions. */ |
1969 | 1861 | ||
1970 | erp->lpm = 0; | 1862 | erp->lpm = 0; |
1971 | 1863 | erp->status = DASD_CQR_NEED_ERP; | |
1972 | erp->status = DASD_CQR_ERROR; | ||
1973 | |||
1974 | } | 1864 | } |
1975 | } | 1865 | } |
1976 | 1866 | ||
@@ -2047,7 +1937,7 @@ dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense) | |||
2047 | if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { | 1937 | if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) { |
2048 | 1938 | ||
2049 | /* set to suspended duplex state then restart */ | 1939 | /* set to suspended duplex state then restart */ |
2050 | struct dasd_device *device = erp->device; | 1940 | struct dasd_device *device = erp->startdev; |
2051 | 1941 | ||
2052 | DEV_MESSAGE(KERN_ERR, device, "%s", | 1942 | DEV_MESSAGE(KERN_ERR, device, "%s", |
2053 | "Set device to suspended duplex state should be " | 1943 | "Set device to suspended duplex state should be " |
@@ -2081,28 +1971,26 @@ dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense) | |||
2081 | { | 1971 | { |
2082 | 1972 | ||
2083 | if ((erp->function == dasd_3990_erp_compound_retry) && | 1973 | if ((erp->function == dasd_3990_erp_compound_retry) && |
2084 | (erp->status == DASD_CQR_ERROR)) { | 1974 | (erp->status == DASD_CQR_NEED_ERP)) { |
2085 | 1975 | ||
2086 | dasd_3990_erp_compound_path(erp, sense); | 1976 | dasd_3990_erp_compound_path(erp, sense); |
2087 | } | 1977 | } |
2088 | 1978 | ||
2089 | if ((erp->function == dasd_3990_erp_compound_path) && | 1979 | if ((erp->function == dasd_3990_erp_compound_path) && |
2090 | (erp->status == DASD_CQR_ERROR)) { | 1980 | (erp->status == DASD_CQR_NEED_ERP)) { |
2091 | 1981 | ||
2092 | erp = dasd_3990_erp_compound_code(erp, sense); | 1982 | erp = dasd_3990_erp_compound_code(erp, sense); |
2093 | } | 1983 | } |
2094 | 1984 | ||
2095 | if ((erp->function == dasd_3990_erp_compound_code) && | 1985 | if ((erp->function == dasd_3990_erp_compound_code) && |
2096 | (erp->status == DASD_CQR_ERROR)) { | 1986 | (erp->status == DASD_CQR_NEED_ERP)) { |
2097 | 1987 | ||
2098 | dasd_3990_erp_compound_config(erp, sense); | 1988 | dasd_3990_erp_compound_config(erp, sense); |
2099 | } | 1989 | } |
2100 | 1990 | ||
2101 | /* if no compound action ERP specified, the request failed */ | 1991 | /* if no compound action ERP specified, the request failed */ |
2102 | if (erp->status == DASD_CQR_ERROR) { | 1992 | if (erp->status == DASD_CQR_NEED_ERP) |
2103 | |||
2104 | erp->status = DASD_CQR_FAILED; | 1993 | erp->status = DASD_CQR_FAILED; |
2105 | } | ||
2106 | 1994 | ||
2107 | return erp; | 1995 | return erp; |
2108 | 1996 | ||
@@ -2127,7 +2015,7 @@ static struct dasd_ccw_req * | |||
2127 | dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | 2015 | dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) |
2128 | { | 2016 | { |
2129 | 2017 | ||
2130 | struct dasd_device *device = erp->device; | 2018 | struct dasd_device *device = erp->startdev; |
2131 | 2019 | ||
2132 | erp->function = dasd_3990_erp_inspect_32; | 2020 | erp->function = dasd_3990_erp_inspect_32; |
2133 | 2021 | ||
@@ -2149,8 +2037,7 @@ dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense) | |||
2149 | 2037 | ||
2150 | case 0x01: /* fatal error */ | 2038 | case 0x01: /* fatal error */ |
2151 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2039 | DEV_MESSAGE(KERN_ERR, device, "%s", |
2152 | "Fatal error should have been " | 2040 | "Retry not recommended - Fatal error"); |
2153 | "handled within the interrupt handler"); | ||
2154 | 2041 | ||
2155 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); | 2042 | erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED); |
2156 | break; | 2043 | break; |
@@ -2253,6 +2140,11 @@ dasd_3990_erp_inspect(struct dasd_ccw_req * erp) | |||
2253 | /* already set up new ERP ! */ | 2140 | /* already set up new ERP ! */ |
2254 | char *sense = erp->refers->irb.ecw; | 2141 | char *sense = erp->refers->irb.ecw; |
2255 | 2142 | ||
2143 | /* if this problem occured on an alias retry on base */ | ||
2144 | erp_new = dasd_3990_erp_inspect_alias(erp); | ||
2145 | if (erp_new) | ||
2146 | return erp_new; | ||
2147 | |||
2256 | /* distinguish between 24 and 32 byte sense data */ | 2148 | /* distinguish between 24 and 32 byte sense data */ |
2257 | if (sense[27] & DASD_SENSE_BIT_0) { | 2149 | if (sense[27] & DASD_SENSE_BIT_0) { |
2258 | 2150 | ||
@@ -2287,13 +2179,13 @@ static struct dasd_ccw_req * | |||
2287 | dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | 2179 | dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) |
2288 | { | 2180 | { |
2289 | 2181 | ||
2290 | struct dasd_device *device = cqr->device; | 2182 | struct dasd_device *device = cqr->startdev; |
2291 | struct ccw1 *ccw; | 2183 | struct ccw1 *ccw; |
2292 | 2184 | ||
2293 | /* allocate additional request block */ | 2185 | /* allocate additional request block */ |
2294 | struct dasd_ccw_req *erp; | 2186 | struct dasd_ccw_req *erp; |
2295 | 2187 | ||
2296 | erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, cqr->device); | 2188 | erp = dasd_alloc_erp_request((char *) &cqr->magic, 2, 0, device); |
2297 | if (IS_ERR(erp)) { | 2189 | if (IS_ERR(erp)) { |
2298 | if (cqr->retries <= 0) { | 2190 | if (cqr->retries <= 0) { |
2299 | DEV_MESSAGE(KERN_ERR, device, "%s", | 2191 | DEV_MESSAGE(KERN_ERR, device, "%s", |
@@ -2305,7 +2197,7 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2305 | "Unable to allocate ERP request " | 2197 | "Unable to allocate ERP request " |
2306 | "(%i retries left)", | 2198 | "(%i retries left)", |
2307 | cqr->retries); | 2199 | cqr->retries); |
2308 | dasd_set_timer(device, (HZ << 3)); | 2200 | dasd_block_set_timer(device->block, (HZ << 3)); |
2309 | } | 2201 | } |
2310 | return cqr; | 2202 | return cqr; |
2311 | } | 2203 | } |
@@ -2319,7 +2211,9 @@ dasd_3990_erp_add_erp(struct dasd_ccw_req * cqr) | |||
2319 | ccw->cda = (long)(cqr->cpaddr); | 2211 | ccw->cda = (long)(cqr->cpaddr); |
2320 | erp->function = dasd_3990_erp_add_erp; | 2212 | erp->function = dasd_3990_erp_add_erp; |
2321 | erp->refers = cqr; | 2213 | erp->refers = cqr; |
2322 | erp->device = cqr->device; | 2214 | erp->startdev = device; |
2215 | erp->memdev = device; | ||
2216 | erp->block = cqr->block; | ||
2323 | erp->magic = cqr->magic; | 2217 | erp->magic = cqr->magic; |
2324 | erp->expires = 0; | 2218 | erp->expires = 0; |
2325 | erp->retries = 256; | 2219 | erp->retries = 256; |
@@ -2466,7 +2360,7 @@ static struct dasd_ccw_req * | |||
2466 | dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) | 2360 | dasd_3990_erp_further_erp(struct dasd_ccw_req *erp) |
2467 | { | 2361 | { |
2468 | 2362 | ||
2469 | struct dasd_device *device = erp->device; | 2363 | struct dasd_device *device = erp->startdev; |
2470 | char *sense = erp->irb.ecw; | 2364 | char *sense = erp->irb.ecw; |
2471 | 2365 | ||
2472 | /* check for 24 byte sense ERP */ | 2366 | /* check for 24 byte sense ERP */ |
@@ -2557,7 +2451,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2557 | struct dasd_ccw_req *erp) | 2451 | struct dasd_ccw_req *erp) |
2558 | { | 2452 | { |
2559 | 2453 | ||
2560 | struct dasd_device *device = erp_head->device; | 2454 | struct dasd_device *device = erp_head->startdev; |
2561 | struct dasd_ccw_req *erp_done = erp_head; /* finished req */ | 2455 | struct dasd_ccw_req *erp_done = erp_head; /* finished req */ |
2562 | struct dasd_ccw_req *erp_free = NULL; /* req to be freed */ | 2456 | struct dasd_ccw_req *erp_free = NULL; /* req to be freed */ |
2563 | 2457 | ||
@@ -2569,13 +2463,13 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2569 | "original request was lost\n"); | 2463 | "original request was lost\n"); |
2570 | 2464 | ||
2571 | /* remove the request from the device queue */ | 2465 | /* remove the request from the device queue */ |
2572 | list_del(&erp_done->list); | 2466 | list_del(&erp_done->blocklist); |
2573 | 2467 | ||
2574 | erp_free = erp_done; | 2468 | erp_free = erp_done; |
2575 | erp_done = erp_done->refers; | 2469 | erp_done = erp_done->refers; |
2576 | 2470 | ||
2577 | /* free the finished erp request */ | 2471 | /* free the finished erp request */ |
2578 | dasd_free_erp_request(erp_free, erp_free->device); | 2472 | dasd_free_erp_request(erp_free, erp_free->memdev); |
2579 | 2473 | ||
2580 | } /* end while */ | 2474 | } /* end while */ |
2581 | 2475 | ||
@@ -2603,7 +2497,7 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2603 | erp->retries, erp); | 2497 | erp->retries, erp); |
2604 | 2498 | ||
2605 | /* handle the request again... */ | 2499 | /* handle the request again... */ |
2606 | erp->status = DASD_CQR_QUEUED; | 2500 | erp->status = DASD_CQR_FILLED; |
2607 | } | 2501 | } |
2608 | 2502 | ||
2609 | } else { | 2503 | } else { |
@@ -2636,9 +2530,8 @@ dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head, | |||
2636 | struct dasd_ccw_req * | 2530 | struct dasd_ccw_req * |
2637 | dasd_3990_erp_action(struct dasd_ccw_req * cqr) | 2531 | dasd_3990_erp_action(struct dasd_ccw_req * cqr) |
2638 | { | 2532 | { |
2639 | |||
2640 | struct dasd_ccw_req *erp = NULL; | 2533 | struct dasd_ccw_req *erp = NULL; |
2641 | struct dasd_device *device = cqr->device; | 2534 | struct dasd_device *device = cqr->startdev; |
2642 | struct dasd_ccw_req *temp_erp = NULL; | 2535 | struct dasd_ccw_req *temp_erp = NULL; |
2643 | 2536 | ||
2644 | if (device->features & DASD_FEATURE_ERPLOG) { | 2537 | if (device->features & DASD_FEATURE_ERPLOG) { |
@@ -2704,10 +2597,11 @@ dasd_3990_erp_action(struct dasd_ccw_req * cqr) | |||
2704 | } | 2597 | } |
2705 | } | 2598 | } |
2706 | 2599 | ||
2707 | /* enqueue added ERP request */ | 2600 | /* enqueue ERP request if it's a new one */ |
2708 | if (erp->status == DASD_CQR_FILLED) { | 2601 | if (list_empty(&erp->blocklist)) { |
2709 | erp->status = DASD_CQR_QUEUED; | 2602 | cqr->status = DASD_CQR_IN_ERP; |
2710 | list_add(&erp->list, &device->ccw_queue); | 2603 | /* add erp request before the cqr */ |
2604 | list_add_tail(&erp->blocklist, &cqr->blocklist); | ||
2711 | } | 2605 | } |
2712 | 2606 | ||
2713 | return erp; | 2607 | return erp; |