blob: 4cee45916144ada5d3dbb259c9a701d1e2f0e6e6 [file] [log] [blame]
Horst Hummel138c0142006-06-29 14:58:12 +02001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * File...........: linux/drivers/s390/block/dasd_3990_erp.c
Horst Hummel138c0142006-06-29 14:58:12 +02003 * Author(s)......: Horst Hummel <Horst.Hummel@de.ibm.com>
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 * Holger Smolinski <Holger.Smolinski@de.ibm.com>
5 * Bugreports.to..: <Linux390@de.ibm.com>
6 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
7 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07008 */
9
10#include <linux/timer.h>
11#include <linux/slab.h>
12#include <asm/idals.h>
13#include <asm/todclk.h>
14
15#define PRINTK_HEADER "dasd_erp(3990): "
16
17#include "dasd_int.h"
18#include "dasd_eckd.h"
19
20
21struct DCTL_data {
22 unsigned char subcommand; /* e.g Inhibit Write, Enable Write,... */
23 unsigned char modifier; /* Subcommand modifier */
24 unsigned short res; /* reserved */
25} __attribute__ ((packed));
26
27/*
Horst Hummel138c0142006-06-29 14:58:12 +020028 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -070029 * SECTION ERP HANDLING
Horst Hummel138c0142006-06-29 14:58:12 +020030 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 */
32/*
Horst Hummel138c0142006-06-29 14:58:12 +020033 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -070034 * 24 and 32 byte sense ERP functions
Horst Hummel138c0142006-06-29 14:58:12 +020035 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -070036 */
37
38/*
Horst Hummel138c0142006-06-29 14:58:12 +020039 * DASD_3990_ERP_CLEANUP
Linus Torvalds1da177e2005-04-16 15:20:36 -070040 *
41 * DESCRIPTION
42 * Removes the already build but not necessary ERP request and sets
43 * the status of the original cqr / erp to the given (final) status
44 *
45 * PARAMETER
46 * erp request to be blocked
Horst Hummel138c0142006-06-29 14:58:12 +020047 * final_status either DASD_CQR_DONE or DASD_CQR_FAILED
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 *
49 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +020050 * cqr original cqr
Linus Torvalds1da177e2005-04-16 15:20:36 -070051 */
52static struct dasd_ccw_req *
53dasd_3990_erp_cleanup(struct dasd_ccw_req * erp, char final_status)
54{
55 struct dasd_ccw_req *cqr = erp->refers;
56
Stefan Weinhuber8e09f212008-01-26 14:11:23 +010057 dasd_free_erp_request(erp, erp->memdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -070058 cqr->status = final_status;
59 return cqr;
60
61} /* end dasd_3990_erp_cleanup */
62
63/*
Horst Hummel138c0142006-06-29 14:58:12 +020064 * DASD_3990_ERP_BLOCK_QUEUE
Linus Torvalds1da177e2005-04-16 15:20:36 -070065 *
66 * DESCRIPTION
67 * Block the given device request queue to prevent from further
68 * processing until the started timer has expired or an related
69 * interrupt was received.
70 */
71static void
72dasd_3990_erp_block_queue(struct dasd_ccw_req * erp, int expires)
73{
74
Stefan Weinhuber8e09f212008-01-26 14:11:23 +010075 struct dasd_device *device = erp->startdev;
76 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
78 DEV_MESSAGE(KERN_INFO, device,
79 "blocking request queue for %is", expires/HZ);
80
Stefan Weinhuber8e09f212008-01-26 14:11:23 +010081 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 device->stopped |= DASD_STOPPED_PENDING;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +010083 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
84 erp->status = DASD_CQR_FILLED;
85 dasd_block_set_timer(device->block, expires);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086}
87
88/*
Horst Hummel138c0142006-06-29 14:58:12 +020089 * DASD_3990_ERP_INT_REQ
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 *
91 * DESCRIPTION
92 * Handles 'Intervention Required' error.
93 * This means either device offline or not installed.
94 *
95 * PARAMETER
96 * erp current erp
97 * RETURN VALUES
98 * erp modified erp
99 */
100static struct dasd_ccw_req *
101dasd_3990_erp_int_req(struct dasd_ccw_req * erp)
102{
103
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100104 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105
106 /* first time set initial retry counter and erp_function */
107 /* and retry once without blocking queue */
108 /* (this enables easier enqueing of the cqr) */
109 if (erp->function != dasd_3990_erp_int_req) {
110
111 erp->retries = 256;
112 erp->function = dasd_3990_erp_int_req;
113
114 } else {
115
116 /* issue a message and wait for 'device ready' interrupt */
117 DEV_MESSAGE(KERN_ERR, device, "%s",
118 "is offline or not installed - "
119 "INTERVENTION REQUIRED!!");
120
121 dasd_3990_erp_block_queue(erp, 60*HZ);
122 }
123
124 return erp;
125
126} /* end dasd_3990_erp_int_req */
127
128/*
Horst Hummel138c0142006-06-29 14:58:12 +0200129 * DASD_3990_ERP_ALTERNATE_PATH
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 *
131 * DESCRIPTION
132 * Repeat the operation on a different channel path.
133 * If all alternate paths have been tried, the request is posted with a
134 * permanent error.
135 *
136 * PARAMETER
137 * erp pointer to the current ERP
138 *
139 * RETURN VALUES
140 * erp modified pointer to the ERP
141 */
142static void
143dasd_3990_erp_alternate_path(struct dasd_ccw_req * erp)
144{
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100145 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 __u8 opm;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100147 unsigned long flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 /* try alternate valid path */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100150 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 opm = ccw_device_get_path_mask(device->cdev);
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100152 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700153 //FIXME: start with get_opm ?
154 if (erp->lpm == 0)
155 erp->lpm = LPM_ANYPATH & ~(erp->irb.esw.esw0.sublog.lpum);
156 else
157 erp->lpm &= ~(erp->irb.esw.esw0.sublog.lpum);
158
159 if ((erp->lpm & opm) != 0x00) {
160
161 DEV_MESSAGE(KERN_DEBUG, device,
162 "try alternate lpm=%x (lpum=%x / opm=%x)",
163 erp->lpm, erp->irb.esw.esw0.sublog.lpum, opm);
164
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100165 /* reset status to submit the request again... */
166 erp->status = DASD_CQR_FILLED;
Stefan Haberland6c5f57c2008-02-05 16:50:46 +0100167 erp->retries = 10;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700168 } else {
169 DEV_MESSAGE(KERN_ERR, device,
170 "No alternate channel path left (lpum=%x / "
171 "opm=%x) -> permanent error",
172 erp->irb.esw.esw0.sublog.lpum, opm);
173
174 /* post request with permanent error */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100175 erp->status = DASD_CQR_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700176 }
177} /* end dasd_3990_erp_alternate_path */
178
179/*
180 * DASD_3990_ERP_DCTL
181 *
182 * DESCRIPTION
Horst Hummel138c0142006-06-29 14:58:12 +0200183 * Setup cqr to do the Diagnostic Control (DCTL) command with an
Linus Torvalds1da177e2005-04-16 15:20:36 -0700184 * Inhibit Write subcommand (0x20) and the given modifier.
185 *
186 * PARAMETER
187 * erp pointer to the current (failed) ERP
188 * modifier subcommand modifier
Horst Hummel138c0142006-06-29 14:58:12 +0200189 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700190 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +0200191 * dctl_cqr pointer to NEW dctl_cqr
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192 *
193 */
194static struct dasd_ccw_req *
195dasd_3990_erp_DCTL(struct dasd_ccw_req * erp, char modifier)
196{
197
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100198 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700199 struct DCTL_data *DCTL_data;
200 struct ccw1 *ccw;
201 struct dasd_ccw_req *dctl_cqr;
202
203 dctl_cqr = dasd_alloc_erp_request((char *) &erp->magic, 1,
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100204 sizeof(struct DCTL_data),
205 device);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700206 if (IS_ERR(dctl_cqr)) {
207 DEV_MESSAGE(KERN_ERR, device, "%s",
208 "Unable to allocate DCTL-CQR");
209 erp->status = DASD_CQR_FAILED;
210 return erp;
211 }
212
213 DCTL_data = dctl_cqr->data;
214
215 DCTL_data->subcommand = 0x02; /* Inhibit Write */
216 DCTL_data->modifier = modifier;
217
218 ccw = dctl_cqr->cpaddr;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100219 memset(ccw, 0, sizeof(struct ccw1));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 ccw->cmd_code = CCW_CMD_DCTL;
221 ccw->count = 4;
222 ccw->cda = (__u32)(addr_t) DCTL_data;
223 dctl_cqr->function = dasd_3990_erp_DCTL;
224 dctl_cqr->refers = erp;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100225 dctl_cqr->startdev = device;
226 dctl_cqr->memdev = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227 dctl_cqr->magic = erp->magic;
228 dctl_cqr->expires = 5 * 60 * HZ;
229 dctl_cqr->retries = 2;
230
231 dctl_cqr->buildclk = get_clock();
232
233 dctl_cqr->status = DASD_CQR_FILLED;
234
235 return dctl_cqr;
236
237} /* end dasd_3990_erp_DCTL */
238
239/*
Horst Hummel138c0142006-06-29 14:58:12 +0200240 * DASD_3990_ERP_ACTION_1
Linus Torvalds1da177e2005-04-16 15:20:36 -0700241 *
242 * DESCRIPTION
243 * Setup ERP to do the ERP action 1 (see Reference manual).
244 * Repeat the operation on a different channel path.
245 * If all alternate paths have been tried, the request is posted with a
246 * permanent error.
247 * Note: duplex handling is not implemented (yet).
248 *
249 * PARAMETER
250 * erp pointer to the current ERP
251 *
252 * RETURN VALUES
253 * erp pointer to the ERP
254 *
255 */
256static struct dasd_ccw_req *
257dasd_3990_erp_action_1(struct dasd_ccw_req * erp)
258{
259
260 erp->function = dasd_3990_erp_action_1;
261
262 dasd_3990_erp_alternate_path(erp);
263
264 return erp;
265
266} /* end dasd_3990_erp_action_1 */
267
268/*
Horst Hummel138c0142006-06-29 14:58:12 +0200269 * DASD_3990_ERP_ACTION_4
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270 *
271 * DESCRIPTION
272 * Setup ERP to do the ERP action 4 (see Reference manual).
273 * Set the current request to PENDING to block the CQR queue for that device
274 * until the state change interrupt appears.
275 * Use a timer (20 seconds) to retry the cqr if the interrupt is still
276 * missing.
277 *
278 * PARAMETER
279 * sense sense data of the actual error
280 * erp pointer to the current ERP
281 *
282 * RETURN VALUES
283 * erp pointer to the ERP
284 *
285 */
286static struct dasd_ccw_req *
287dasd_3990_erp_action_4(struct dasd_ccw_req * erp, char *sense)
288{
289
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100290 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700291
292 /* first time set initial retry counter and erp_function */
293 /* and retry once without waiting for state change pending */
294 /* interrupt (this enables easier enqueing of the cqr) */
295 if (erp->function != dasd_3990_erp_action_4) {
296
297 DEV_MESSAGE(KERN_INFO, device, "%s",
298 "dasd_3990_erp_action_4: first time retry");
299
300 erp->retries = 256;
301 erp->function = dasd_3990_erp_action_4;
302
303 } else {
Stefan Haberland6c5f57c2008-02-05 16:50:46 +0100304 if (sense && (sense[25] == 0x1D)) { /* state change pending */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700305
Horst Hummel138c0142006-06-29 14:58:12 +0200306 DEV_MESSAGE(KERN_INFO, device,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700307 "waiting for state change pending "
308 "interrupt, %d retries left",
309 erp->retries);
Horst Hummel138c0142006-06-29 14:58:12 +0200310
Linus Torvalds1da177e2005-04-16 15:20:36 -0700311 dasd_3990_erp_block_queue(erp, 30*HZ);
312
Stefan Haberland6c5f57c2008-02-05 16:50:46 +0100313 } else if (sense && (sense[25] == 0x1E)) { /* busy */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314 DEV_MESSAGE(KERN_INFO, device,
315 "busy - redriving request later, "
316 "%d retries left",
317 erp->retries);
318 dasd_3990_erp_block_queue(erp, HZ);
319 } else {
320
321 /* no state change pending - retry */
Horst Hummel138c0142006-06-29 14:58:12 +0200322 DEV_MESSAGE (KERN_INFO, device,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700323 "redriving request immediately, "
Horst Hummel138c0142006-06-29 14:58:12 +0200324 "%d retries left",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325 erp->retries);
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100326 erp->status = DASD_CQR_FILLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700327 }
328 }
329
330 return erp;
331
332} /* end dasd_3990_erp_action_4 */
333
334/*
Horst Hummel138c0142006-06-29 14:58:12 +0200335 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 * 24 byte sense ERP functions (only)
Horst Hummel138c0142006-06-29 14:58:12 +0200337 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -0700338 */
339
340/*
Horst Hummel138c0142006-06-29 14:58:12 +0200341 * DASD_3990_ERP_ACTION_5
Linus Torvalds1da177e2005-04-16 15:20:36 -0700342 *
343 * DESCRIPTION
344 * Setup ERP to do the ERP action 5 (see Reference manual).
345 * NOTE: Further handling is done in xxx_further_erp after the retries.
346 *
347 * PARAMETER
348 * erp pointer to the current ERP
349 *
350 * RETURN VALUES
351 * erp pointer to the ERP
352 *
353 */
354static struct dasd_ccw_req *
355dasd_3990_erp_action_5(struct dasd_ccw_req * erp)
356{
357
358 /* first of all retry */
359 erp->retries = 10;
360 erp->function = dasd_3990_erp_action_5;
361
362 return erp;
363
364} /* end dasd_3990_erp_action_5 */
365
366/*
367 * DASD_3990_HANDLE_ENV_DATA
368 *
369 * DESCRIPTION
370 * Handles 24 byte 'Environmental data present'.
371 * Does a analysis of the sense data (message Format)
372 * and prints the error messages.
373 *
374 * PARAMETER
375 * sense current sense data
Horst Hummel138c0142006-06-29 14:58:12 +0200376 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 * RETURN VALUES
378 * void
379 */
380static void
381dasd_3990_handle_env_data(struct dasd_ccw_req * erp, char *sense)
382{
383
Stefan Weinhuber8e09f212008-01-26 14:11:23 +0100384 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385 char msg_format = (sense[7] & 0xF0);
386 char msg_no = (sense[7] & 0x0F);
387
388 switch (msg_format) {
389 case 0x00: /* Format 0 - Program or System Checks */
390
391 if (sense[1] & 0x10) { /* check message to operator bit */
392
393 switch (msg_no) {
394 case 0x00: /* No Message */
395 break;
396 case 0x01:
397 DEV_MESSAGE(KERN_WARNING, device, "%s",
398 "FORMAT 0 - Invalid Command");
399 break;
400 case 0x02:
401 DEV_MESSAGE(KERN_WARNING, device, "%s",
402 "FORMAT 0 - Invalid Command "
403 "Sequence");
404 break;
405 case 0x03:
406 DEV_MESSAGE(KERN_WARNING, device, "%s",
407 "FORMAT 0 - CCW Count less than "
408 "required");
409 break;
410 case 0x04:
411 DEV_MESSAGE(KERN_WARNING, device, "%s",
412 "FORMAT 0 - Invalid Parameter");
413 break;
414 case 0x05:
415 DEV_MESSAGE(KERN_WARNING, device, "%s",
416 "FORMAT 0 - Diagnostic of Sepecial"
417 " Command Violates File Mask");
418 break;
419 case 0x07:
420 DEV_MESSAGE(KERN_WARNING, device, "%s",
421 "FORMAT 0 - Channel Returned with "
422 "Incorrect retry CCW");
423 break;
424 case 0x08:
425 DEV_MESSAGE(KERN_WARNING, device, "%s",
426 "FORMAT 0 - Reset Notification");
427 break;
428 case 0x09:
429 DEV_MESSAGE(KERN_WARNING, device, "%s",
430 "FORMAT 0 - Storage Path Restart");
431 break;
432 case 0x0A:
433 DEV_MESSAGE(KERN_WARNING, device,
434 "FORMAT 0 - Channel requested "
435 "... %02x", sense[8]);
436 break;
437 case 0x0B:
438 DEV_MESSAGE(KERN_WARNING, device, "%s",
439 "FORMAT 0 - Invalid Defective/"
440 "Alternate Track Pointer");
441 break;
442 case 0x0C:
443 DEV_MESSAGE(KERN_WARNING, device, "%s",
444 "FORMAT 0 - DPS Installation "
445 "Check");
446 break;
447 case 0x0E:
448 DEV_MESSAGE(KERN_WARNING, device, "%s",
449 "FORMAT 0 - Command Invalid on "
450 "Secondary Address");
451 break;
452 case 0x0F:
453 DEV_MESSAGE(KERN_WARNING, device,
454 "FORMAT 0 - Status Not As "
455 "Required: reason %02x", sense[8]);
456 break;
457 default:
458 DEV_MESSAGE(KERN_WARNING, device, "%s",
459 "FORMAT 0 - Reseved");
460 }
461 } else {
462 switch (msg_no) {
463 case 0x00: /* No Message */
464 break;
465 case 0x01:
466 DEV_MESSAGE(KERN_WARNING, device, "%s",
467 "FORMAT 0 - Device Error Source");
468 break;
469 case 0x02:
470 DEV_MESSAGE(KERN_WARNING, device, "%s",
471 "FORMAT 0 - Reserved");
472 break;
473 case 0x03:
474 DEV_MESSAGE(KERN_WARNING, device,
475 "FORMAT 0 - Device Fenced - "
476 "device = %02x", sense[4]);
477 break;
478 case 0x04:
479 DEV_MESSAGE(KERN_WARNING, device, "%s",
480 "FORMAT 0 - Data Pinned for "
481 "Device");
482 break;
483 default:
484 DEV_MESSAGE(KERN_WARNING, device, "%s",
485 "FORMAT 0 - Reserved");
486 }
487 }
488 break;
489
490 case 0x10: /* Format 1 - Device Equipment Checks */
491 switch (msg_no) {
492 case 0x00: /* No Message */
493 break;
494 case 0x01:
495 DEV_MESSAGE(KERN_WARNING, device, "%s",
496 "FORMAT 1 - Device Status 1 not as "
497 "expected");
498 break;
499 case 0x03:
500 DEV_MESSAGE(KERN_WARNING, device, "%s",
501 "FORMAT 1 - Index missing");
502 break;
503 case 0x04:
504 DEV_MESSAGE(KERN_WARNING, device, "%s",
505 "FORMAT 1 - Interruption cannot be reset");
506 break;
507 case 0x05:
508 DEV_MESSAGE(KERN_WARNING, device, "%s",
509 "FORMAT 1 - Device did not respond to "
510 "selection");
511 break;
512 case 0x06:
513 DEV_MESSAGE(KERN_WARNING, device, "%s",
514 "FORMAT 1 - Device check-2 error or Set "
515 "Sector is not complete");
516 break;
517 case 0x07:
518 DEV_MESSAGE(KERN_WARNING, device, "%s",
519 "FORMAT 1 - Head address does not "
520 "compare");
521 break;
522 case 0x08:
523 DEV_MESSAGE(KERN_WARNING, device, "%s",
524 "FORMAT 1 - Device status 1 not valid");
525 break;
526 case 0x09:
527 DEV_MESSAGE(KERN_WARNING, device, "%s",
528 "FORMAT 1 - Device not ready");
529 break;
530 case 0x0A:
531 DEV_MESSAGE(KERN_WARNING, device, "%s",
532 "FORMAT 1 - Track physical address did "
533 "not compare");
534 break;
535 case 0x0B:
536 DEV_MESSAGE(KERN_WARNING, device, "%s",
537 "FORMAT 1 - Missing device address bit");
538 break;
539 case 0x0C:
540 DEV_MESSAGE(KERN_WARNING, device, "%s",
541 "FORMAT 1 - Drive motor switch is off");
542 break;
543 case 0x0D:
544 DEV_MESSAGE(KERN_WARNING, device, "%s",
545 "FORMAT 1 - Seek incomplete");
546 break;
547 case 0x0E:
548 DEV_MESSAGE(KERN_WARNING, device, "%s",
549 "FORMAT 1 - Cylinder address did not "
550 "compare");
551 break;
552 case 0x0F:
553 DEV_MESSAGE(KERN_WARNING, device, "%s",
554 "FORMAT 1 - Offset active cannot be "
555 "reset");
556 break;
557 default:
558 DEV_MESSAGE(KERN_WARNING, device, "%s",
559 "FORMAT 1 - Reserved");
560 }
561 break;
562
563 case 0x20: /* Format 2 - 3990 Equipment Checks */
564 switch (msg_no) {
565 case 0x08:
566 DEV_MESSAGE(KERN_WARNING, device, "%s",
567 "FORMAT 2 - 3990 check-2 error");
568 break;
569 case 0x0E:
570 DEV_MESSAGE(KERN_WARNING, device, "%s",
571 "FORMAT 2 - Support facility errors");
572 break;
573 case 0x0F:
574 DEV_MESSAGE(KERN_WARNING, device,
575 "FORMAT 2 - Microcode detected error %02x",
576 sense[8]);
577 break;
578 default:
579 DEV_MESSAGE(KERN_WARNING, device, "%s",
580 "FORMAT 2 - Reserved");
581 }
582 break;
583
584 case 0x30: /* Format 3 - 3990 Control Checks */
585 switch (msg_no) {
586 case 0x0F:
587 DEV_MESSAGE(KERN_WARNING, device, "%s",
588 "FORMAT 3 - Allegiance terminated");
589 break;
590 default:
591 DEV_MESSAGE(KERN_WARNING, device, "%s",
592 "FORMAT 3 - Reserved");
593 }
594 break;
595
596 case 0x40: /* Format 4 - Data Checks */
597 switch (msg_no) {
598 case 0x00:
599 DEV_MESSAGE(KERN_WARNING, device, "%s",
600 "FORMAT 4 - Home address area error");
601 break;
602 case 0x01:
603 DEV_MESSAGE(KERN_WARNING, device, "%s",
604 "FORMAT 4 - Count area error");
605 break;
606 case 0x02:
607 DEV_MESSAGE(KERN_WARNING, device, "%s",
608 "FORMAT 4 - Key area error");
609 break;
610 case 0x03:
611 DEV_MESSAGE(KERN_WARNING, device, "%s",
612 "FORMAT 4 - Data area error");
613 break;
614 case 0x04:
615 DEV_MESSAGE(KERN_WARNING, device, "%s",
616 "FORMAT 4 - No sync byte in home address "
617 "area");
618 break;
619 case 0x05:
620 DEV_MESSAGE(KERN_WARNING, device, "%s",
621 "FORMAT 4 - No sync byte in count address "
622 "area");
623 break;
624 case 0x06:
625 DEV_MESSAGE(KERN_WARNING, device, "%s",
626 "FORMAT 4 - No sync byte in key area");
627 break;
628 case 0x07:
629 DEV_MESSAGE(KERN_WARNING, device, "%s",
630 "FORMAT 4 - No sync byte in data area");
631 break;
632 case 0x08:
633 DEV_MESSAGE(KERN_WARNING, device, "%s",
634 "FORMAT 4 - Home address area error; "
635 "offset active");
636 break;
637 case 0x09:
638 DEV_MESSAGE(KERN_WARNING, device, "%s",
639 "FORMAT 4 - Count area error; offset "
640 "active");
641 break;
642 case 0x0A:
643 DEV_MESSAGE(KERN_WARNING, device, "%s",
644 "FORMAT 4 - Key area error; offset "
645 "active");
646 break;
647 case 0x0B:
648 DEV_MESSAGE(KERN_WARNING, device, "%s",
649 "FORMAT 4 - Data area error; "
650 "offset active");
651 break;
652 case 0x0C:
653 DEV_MESSAGE(KERN_WARNING, device, "%s",
654 "FORMAT 4 - No sync byte in home "
655 "address area; offset active");
656 break;
657 case 0x0D:
658 DEV_MESSAGE(KERN_WARNING, device, "%s",
659 "FORMAT 4 - No syn byte in count "
660 "address area; offset active");
661 break;
662 case 0x0E:
663 DEV_MESSAGE(KERN_WARNING, device, "%s",
664 "FORMAT 4 - No sync byte in key area; "
665 "offset active");
666 break;
667 case 0x0F:
668 DEV_MESSAGE(KERN_WARNING, device, "%s",
669 "FORMAT 4 - No syn byte in data area; "
670 "offset active");
671 break;
672 default:
673 DEV_MESSAGE(KERN_WARNING, device, "%s",
674 "FORMAT 4 - Reserved");
675 }
676 break;
677
678 case 0x50: /* Format 5 - Data Check with displacement information */
679 switch (msg_no) {
680 case 0x00:
681 DEV_MESSAGE(KERN_WARNING, device, "%s",
682 "FORMAT 5 - Data Check in the "
683 "home address area");
684 break;
685 case 0x01:
686 DEV_MESSAGE(KERN_WARNING, device, "%s",
687 "FORMAT 5 - Data Check in the count area");
688 break;
689 case 0x02:
690 DEV_MESSAGE(KERN_WARNING, device, "%s",
691 "FORMAT 5 - Data Check in the key area");
692 break;
693 case 0x03:
694 DEV_MESSAGE(KERN_WARNING, device, "%s",
695 "FORMAT 5 - Data Check in the data area");
696 break;
697 case 0x08:
698 DEV_MESSAGE(KERN_WARNING, device, "%s",
699 "FORMAT 5 - Data Check in the "
700 "home address area; offset active");
701 break;
702 case 0x09:
703 DEV_MESSAGE(KERN_WARNING, device, "%s",
704 "FORMAT 5 - Data Check in the count area; "
705 "offset active");
706 break;
707 case 0x0A:
708 DEV_MESSAGE(KERN_WARNING, device, "%s",
709 "FORMAT 5 - Data Check in the key area; "
710 "offset active");
711 break;
712 case 0x0B:
713 DEV_MESSAGE(KERN_WARNING, device, "%s",
714 "FORMAT 5 - Data Check in the data area; "
715 "offset active");
716 break;
717 default:
718 DEV_MESSAGE(KERN_WARNING, device, "%s",
719 "FORMAT 5 - Reserved");
720 }
721 break;
722
723 case 0x60: /* Format 6 - Usage Statistics/Overrun Errors */
724 switch (msg_no) {
725 case 0x00:
726 DEV_MESSAGE(KERN_WARNING, device, "%s",
727 "FORMAT 6 - Overrun on channel A");
728 break;
729 case 0x01:
730 DEV_MESSAGE(KERN_WARNING, device, "%s",
731 "FORMAT 6 - Overrun on channel B");
732 break;
733 case 0x02:
734 DEV_MESSAGE(KERN_WARNING, device, "%s",
735 "FORMAT 6 - Overrun on channel C");
736 break;
737 case 0x03:
738 DEV_MESSAGE(KERN_WARNING, device, "%s",
739 "FORMAT 6 - Overrun on channel D");
740 break;
741 case 0x04:
742 DEV_MESSAGE(KERN_WARNING, device, "%s",
743 "FORMAT 6 - Overrun on channel E");
744 break;
745 case 0x05:
746 DEV_MESSAGE(KERN_WARNING, device, "%s",
747 "FORMAT 6 - Overrun on channel F");
748 break;
749 case 0x06:
750 DEV_MESSAGE(KERN_WARNING, device, "%s",
751 "FORMAT 6 - Overrun on channel G");
752 break;
753 case 0x07:
754 DEV_MESSAGE(KERN_WARNING, device, "%s",
755 "FORMAT 6 - Overrun on channel H");
756 break;
757 default:
758 DEV_MESSAGE(KERN_WARNING, device, "%s",
759 "FORMAT 6 - Reserved");
760 }
761 break;
762
763 case 0x70: /* Format 7 - Device Connection Control Checks */
764 switch (msg_no) {
765 case 0x00:
766 DEV_MESSAGE(KERN_WARNING, device, "%s",
767 "FORMAT 7 - RCC initiated by a connection "
768 "check alert");
769 break;
770 case 0x01:
771 DEV_MESSAGE(KERN_WARNING, device, "%s",
772 "FORMAT 7 - RCC 1 sequence not "
773 "successful");
774 break;
775 case 0x02:
776 DEV_MESSAGE(KERN_WARNING, device, "%s",
777 "FORMAT 7 - RCC 1 and RCC 2 sequences not "
778 "successful");
779 break;
780 case 0x03:
781 DEV_MESSAGE(KERN_WARNING, device, "%s",
782 "FORMAT 7 - Invalid tag-in during "
783 "selection sequence");
784 break;
785 case 0x04:
786 DEV_MESSAGE(KERN_WARNING, device, "%s",
787 "FORMAT 7 - extra RCC required");
788 break;
789 case 0x05:
790 DEV_MESSAGE(KERN_WARNING, device, "%s",
791 "FORMAT 7 - Invalid DCC selection "
792 "response or timeout");
793 break;
794 case 0x06:
795 DEV_MESSAGE(KERN_WARNING, device, "%s",
796 "FORMAT 7 - Missing end operation; device "
797 "transfer complete");
798 break;
799 case 0x07:
800 DEV_MESSAGE(KERN_WARNING, device, "%s",
801 "FORMAT 7 - Missing end operation; device "
802 "transfer incomplete");
803 break;
804 case 0x08:
805 DEV_MESSAGE(KERN_WARNING, device, "%s",
806 "FORMAT 7 - Invalid tag-in for an "
807 "immediate command sequence");
808 break;
809 case 0x09:
810 DEV_MESSAGE(KERN_WARNING, device, "%s",
811 "FORMAT 7 - Invalid tag-in for an "
812 "extended command sequence");
813 break;
814 case 0x0A:
815 DEV_MESSAGE(KERN_WARNING, device, "%s",
816 "FORMAT 7 - 3990 microcode time out when "
817 "stopping selection");
818 break;
819 case 0x0B:
820 DEV_MESSAGE(KERN_WARNING, device, "%s",
821 "FORMAT 7 - No response to selection "
822 "after a poll interruption");
823 break;
824 case 0x0C:
825 DEV_MESSAGE(KERN_WARNING, device, "%s",
826 "FORMAT 7 - Permanent path error (DASD "
827 "controller not available)");
828 break;
829 case 0x0D:
830 DEV_MESSAGE(KERN_WARNING, device, "%s",
831 "FORMAT 7 - DASD controller not available"
832 " on disconnected command chain");
833 break;
834 default:
835 DEV_MESSAGE(KERN_WARNING, device, "%s",
836 "FORMAT 7 - Reserved");
837 }
838 break;
839
840 case 0x80: /* Format 8 - Additional Device Equipment Checks */
841 switch (msg_no) {
842 case 0x00: /* No Message */
843 case 0x01:
844 DEV_MESSAGE(KERN_WARNING, device, "%s",
845 "FORMAT 8 - Error correction code "
846 "hardware fault");
847 break;
848 case 0x03:
849 DEV_MESSAGE(KERN_WARNING, device, "%s",
850 "FORMAT 8 - Unexpected end operation "
851 "response code");
852 break;
853 case 0x04:
854 DEV_MESSAGE(KERN_WARNING, device, "%s",
855 "FORMAT 8 - End operation with transfer "
856 "count not zero");
857 break;
858 case 0x05:
859 DEV_MESSAGE(KERN_WARNING, device, "%s",
860 "FORMAT 8 - End operation with transfer "
861 "count zero");
862 break;
863 case 0x06:
864 DEV_MESSAGE(KERN_WARNING, device, "%s",
865 "FORMAT 8 - DPS checks after a system "
866 "reset or selective reset");
867 break;
868 case 0x07:
869 DEV_MESSAGE(KERN_WARNING, device, "%s",
870 "FORMAT 8 - DPS cannot be filled");
871 break;
872 case 0x08:
873 DEV_MESSAGE(KERN_WARNING, device, "%s",
874 "FORMAT 8 - Short busy time-out during "
875 "device selection");
876 break;
877 case 0x09:
878 DEV_MESSAGE(KERN_WARNING, device, "%s",
879 "FORMAT 8 - DASD controller failed to "
880 "set or reset the long busy latch");
881 break;
882 case 0x0A:
883 DEV_MESSAGE(KERN_WARNING, device, "%s",
884 "FORMAT 8 - No interruption from device "
885 "during a command chain");
886 break;
887 default:
888 DEV_MESSAGE(KERN_WARNING, device, "%s",
889 "FORMAT 8 - Reserved");
890 }
891 break;
892
893 case 0x90: /* Format 9 - Device Read, Write, and Seek Checks */
894 switch (msg_no) {
895 case 0x00:
896 break; /* No Message */
897 case 0x06:
898 DEV_MESSAGE(KERN_WARNING, device, "%s",
899 "FORMAT 9 - Device check-2 error");
900 break;
901 case 0x07:
902 DEV_MESSAGE(KERN_WARNING, device, "%s",
903 "FORMAT 9 - Head address did not compare");
904 break;
905 case 0x0A:
906 DEV_MESSAGE(KERN_WARNING, device, "%s",
907 "FORMAT 9 - Track physical address did "
908 "not compare while oriented");
909 break;
910 case 0x0E:
911 DEV_MESSAGE(KERN_WARNING, device, "%s",
912 "FORMAT 9 - Cylinder address did not "
913 "compare");
914 break;
915 default:
916 DEV_MESSAGE(KERN_WARNING, device, "%s",
917 "FORMAT 9 - Reserved");
918 }
919 break;
920
921 case 0xF0: /* Format F - Cache Storage Checks */
922 switch (msg_no) {
923 case 0x00:
924 DEV_MESSAGE(KERN_WARNING, device, "%s",
925 "FORMAT F - Operation Terminated");
926 break;
927 case 0x01:
928 DEV_MESSAGE(KERN_WARNING, device, "%s",
929 "FORMAT F - Subsystem Processing Error");
930 break;
931 case 0x02:
932 DEV_MESSAGE(KERN_WARNING, device, "%s",
933 "FORMAT F - Cache or nonvolatile storage "
934 "equipment failure");
935 break;
936 case 0x04:
937 DEV_MESSAGE(KERN_WARNING, device, "%s",
938 "FORMAT F - Caching terminated");
939 break;
940 case 0x06:
941 DEV_MESSAGE(KERN_WARNING, device, "%s",
942 "FORMAT F - Cache fast write access not "
943 "authorized");
944 break;
945 case 0x07:
946 DEV_MESSAGE(KERN_WARNING, device, "%s",
947 "FORMAT F - Track format incorrect");
948 break;
949 case 0x09:
950 DEV_MESSAGE(KERN_WARNING, device, "%s",
951 "FORMAT F - Caching reinitiated");
952 break;
953 case 0x0A:
954 DEV_MESSAGE(KERN_WARNING, device, "%s",
955 "FORMAT F - Nonvolatile storage "
956 "terminated");
957 break;
958 case 0x0B:
959 DEV_MESSAGE(KERN_WARNING, device, "%s",
960 "FORMAT F - Volume is suspended duplex");
Stefan Weinhuber20c64462006-03-24 03:15:25 -0800961 /* call extended error reporting (EER) */
962 dasd_eer_write(device, erp->refers,
963 DASD_EER_PPRCSUSPEND);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 break;
965 case 0x0C:
966 DEV_MESSAGE(KERN_WARNING, device, "%s",
967 "FORMAT F - Subsystem status connot be "
968 "determined");
969 break;
970 case 0x0D:
971 DEV_MESSAGE(KERN_WARNING, device, "%s",
972 "FORMAT F - Caching status reset to "
973 "default");
974 break;
975 case 0x0E:
976 DEV_MESSAGE(KERN_WARNING, device, "%s",
977 "FORMAT F - DASD Fast Write inhibited");
978 break;
979 default:
980 DEV_MESSAGE(KERN_WARNING, device, "%s",
981 "FORMAT D - Reserved");
982 }
983 break;
984
985 default: /* unknown message format - should not happen */
986 DEV_MESSAGE (KERN_WARNING, device,
987 "unknown message format %02x",
988 msg_format);
989 break;
990 } /* end switch message format */
991
992} /* end dasd_3990_handle_env_data */
993
994/*
995 * DASD_3990_ERP_COM_REJ
996 *
997 * DESCRIPTION
998 * Handles 24 byte 'Command Reject' error.
999 *
1000 * PARAMETER
1001 * erp current erp_head
1002 * sense current sense data
Horst Hummel138c0142006-06-29 14:58:12 +02001003 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +02001005 * erp 'new' erp_head - pointer to new ERP
Linus Torvalds1da177e2005-04-16 15:20:36 -07001006 */
1007static struct dasd_ccw_req *
1008dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
1009{
1010
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001011 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012
1013 erp->function = dasd_3990_erp_com_rej;
1014
1015 /* env data present (ACTION 10 - retry should work) */
1016 if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1017
1018 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1019 "Command Reject - environmental data present");
1020
1021 dasd_3990_handle_env_data(erp, sense);
1022
1023 erp->retries = 5;
1024
1025 } else {
1026 /* fatal error - set status to FAILED */
1027 DEV_MESSAGE(KERN_ERR, device, "%s",
1028 "Command Reject - Fatal error");
1029
1030 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
1031 }
1032
1033 return erp;
1034
1035} /* end dasd_3990_erp_com_rej */
1036
1037/*
Horst Hummel138c0142006-06-29 14:58:12 +02001038 * DASD_3990_ERP_BUS_OUT
Linus Torvalds1da177e2005-04-16 15:20:36 -07001039 *
1040 * DESCRIPTION
1041 * Handles 24 byte 'Bus Out Parity Check' error.
1042 *
1043 * PARAMETER
1044 * erp current erp_head
1045 * RETURN VALUES
1046 * erp new erp_head - pointer to new ERP
1047 */
1048static struct dasd_ccw_req *
1049dasd_3990_erp_bus_out(struct dasd_ccw_req * erp)
1050{
1051
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001052 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 /* first time set initial retry counter and erp_function */
1055 /* and retry once without blocking queue */
1056 /* (this enables easier enqueing of the cqr) */
1057 if (erp->function != dasd_3990_erp_bus_out) {
1058 erp->retries = 256;
1059 erp->function = dasd_3990_erp_bus_out;
1060
1061 } else {
1062
1063 /* issue a message and wait for 'device ready' interrupt */
1064 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1065 "bus out parity error or BOPC requested by "
1066 "channel");
1067
1068 dasd_3990_erp_block_queue(erp, 60*HZ);
1069
1070 }
1071
1072 return erp;
1073
1074} /* end dasd_3990_erp_bus_out */
1075
1076/*
1077 * DASD_3990_ERP_EQUIP_CHECK
1078 *
1079 * DESCRIPTION
1080 * Handles 24 byte 'Equipment Check' error.
1081 *
1082 * PARAMETER
1083 * erp current erp_head
1084 * RETURN VALUES
1085 * erp new erp_head - pointer to new ERP
1086 */
1087static struct dasd_ccw_req *
1088dasd_3990_erp_equip_check(struct dasd_ccw_req * erp, char *sense)
1089{
1090
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001091 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092
1093 erp->function = dasd_3990_erp_equip_check;
1094
1095 if (sense[1] & SNS1_WRITE_INHIBITED) {
1096
1097 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1098 "Write inhibited path encountered");
1099
1100 /* vary path offline */
1101 DEV_MESSAGE(KERN_ERR, device, "%s",
1102 "Path should be varied off-line. "
1103 "This is not implemented yet \n - please report "
1104 "to linux390@de.ibm.com");
1105
1106 erp = dasd_3990_erp_action_1(erp);
1107
1108 } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1109
1110 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1111 "Equipment Check - " "environmental data present");
1112
1113 dasd_3990_handle_env_data(erp, sense);
1114
1115 erp = dasd_3990_erp_action_4(erp, sense);
1116
1117 } else if (sense[1] & SNS1_PERM_ERR) {
1118
1119 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1120 "Equipment Check - retry exhausted or "
1121 "undesirable");
1122
1123 erp = dasd_3990_erp_action_1(erp);
1124
1125 } else {
1126 /* all other equipment checks - Action 5 */
1127 /* rest is done when retries == 0 */
1128 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1129 "Equipment check or processing error");
1130
1131 erp = dasd_3990_erp_action_5(erp);
1132 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 return erp;
1134
1135} /* end dasd_3990_erp_equip_check */
1136
1137/*
1138 * DASD_3990_ERP_DATA_CHECK
1139 *
1140 * DESCRIPTION
1141 * Handles 24 byte 'Data Check' error.
1142 *
1143 * PARAMETER
1144 * erp current erp_head
1145 * RETURN VALUES
1146 * erp new erp_head - pointer to new ERP
1147 */
1148static struct dasd_ccw_req *
1149dasd_3990_erp_data_check(struct dasd_ccw_req * erp, char *sense)
1150{
1151
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001152 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153
1154 erp->function = dasd_3990_erp_data_check;
1155
1156 if (sense[2] & SNS2_CORRECTABLE) { /* correctable data check */
1157
1158 /* issue message that the data has been corrected */
1159 DEV_MESSAGE(KERN_EMERG, device, "%s",
1160 "Data recovered during retry with PCI "
1161 "fetch mode active");
1162
1163 /* not possible to handle this situation in Linux */
1164 panic("No way to inform application about the possibly "
1165 "incorrect data");
1166
1167 } else if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1168
1169 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1170 "Uncorrectable data check recovered secondary "
1171 "addr of duplex pair");
1172
1173 erp = dasd_3990_erp_action_4(erp, sense);
1174
1175 } else if (sense[1] & SNS1_PERM_ERR) {
1176
1177 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1178 "Uncorrectable data check with internal "
1179 "retry exhausted");
1180
1181 erp = dasd_3990_erp_action_1(erp);
1182
1183 } else {
1184 /* all other data checks */
1185 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1186 "Uncorrectable data check with retry count "
1187 "exhausted...");
1188
1189 erp = dasd_3990_erp_action_5(erp);
1190 }
1191
1192 return erp;
1193
1194} /* end dasd_3990_erp_data_check */
1195
1196/*
1197 * DASD_3990_ERP_OVERRUN
1198 *
1199 * DESCRIPTION
1200 * Handles 24 byte 'Overrun' error.
1201 *
1202 * PARAMETER
1203 * erp current erp_head
1204 * RETURN VALUES
1205 * erp new erp_head - pointer to new ERP
1206 */
1207static struct dasd_ccw_req *
1208dasd_3990_erp_overrun(struct dasd_ccw_req * erp, char *sense)
1209{
1210
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001211 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
1213 erp->function = dasd_3990_erp_overrun;
1214
1215 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1216 "Overrun - service overrun or overrun"
1217 " error requested by channel");
1218
1219 erp = dasd_3990_erp_action_5(erp);
1220
1221 return erp;
1222
1223} /* end dasd_3990_erp_overrun */
1224
1225/*
1226 * DASD_3990_ERP_INV_FORMAT
1227 *
1228 * DESCRIPTION
1229 * Handles 24 byte 'Invalid Track Format' error.
1230 *
1231 * PARAMETER
1232 * erp current erp_head
1233 * RETURN VALUES
1234 * erp new erp_head - pointer to new ERP
1235 */
1236static struct dasd_ccw_req *
1237dasd_3990_erp_inv_format(struct dasd_ccw_req * erp, char *sense)
1238{
1239
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001240 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001241
1242 erp->function = dasd_3990_erp_inv_format;
1243
1244 if (sense[2] & SNS2_ENV_DATA_PRESENT) {
1245
1246 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1247 "Track format error when destaging or "
1248 "staging data");
1249
1250 dasd_3990_handle_env_data(erp, sense);
1251
1252 erp = dasd_3990_erp_action_4(erp, sense);
1253
1254 } else {
1255 DEV_MESSAGE(KERN_ERR, device, "%s",
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001256 "Invalid Track Format - Fatal error");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001257
1258 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
1259 }
1260
1261 return erp;
1262
1263} /* end dasd_3990_erp_inv_format */
1264
1265/*
1266 * DASD_3990_ERP_EOC
1267 *
1268 * DESCRIPTION
1269 * Handles 24 byte 'End-of-Cylinder' error.
1270 *
1271 * PARAMETER
1272 * erp already added default erp
1273 * RETURN VALUES
1274 * erp pointer to original (failed) cqr.
1275 */
1276static struct dasd_ccw_req *
1277dasd_3990_erp_EOC(struct dasd_ccw_req * default_erp, char *sense)
1278{
1279
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001280 struct dasd_device *device = default_erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282 DEV_MESSAGE(KERN_ERR, device, "%s",
1283 "End-of-Cylinder - must never happen");
1284
1285 /* implement action 7 - BUG */
1286 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
1287
1288} /* end dasd_3990_erp_EOC */
1289
1290/*
1291 * DASD_3990_ERP_ENV_DATA
1292 *
1293 * DESCRIPTION
1294 * Handles 24 byte 'Environmental-Data Present' error.
1295 *
1296 * PARAMETER
1297 * erp current erp_head
1298 * RETURN VALUES
1299 * erp new erp_head - pointer to new ERP
1300 */
1301static struct dasd_ccw_req *
1302dasd_3990_erp_env_data(struct dasd_ccw_req * erp, char *sense)
1303{
1304
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001305 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001306
1307 erp->function = dasd_3990_erp_env_data;
1308
1309 DEV_MESSAGE(KERN_DEBUG, device, "%s", "Environmental data present");
1310
1311 dasd_3990_handle_env_data(erp, sense);
1312
1313 /* don't retry on disabled interface */
1314 if (sense[7] != 0x0F) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001315 erp = dasd_3990_erp_action_4(erp, sense);
1316 } else {
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001317 erp->status = DASD_CQR_FILLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001318 }
1319
1320 return erp;
1321
1322} /* end dasd_3990_erp_env_data */
1323
1324/*
1325 * DASD_3990_ERP_NO_REC
1326 *
1327 * DESCRIPTION
1328 * Handles 24 byte 'No Record Found' error.
1329 *
1330 * PARAMETER
1331 * erp already added default ERP
Horst Hummel138c0142006-06-29 14:58:12 +02001332 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333 * RETURN VALUES
1334 * erp new erp_head - pointer to new ERP
1335 */
1336static struct dasd_ccw_req *
1337dasd_3990_erp_no_rec(struct dasd_ccw_req * default_erp, char *sense)
1338{
1339
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001340 struct dasd_device *device = default_erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341
1342 DEV_MESSAGE(KERN_ERR, device, "%s",
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001343 "No Record Found - Fatal error ");
Linus Torvalds1da177e2005-04-16 15:20:36 -07001344
1345 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
1346
1347} /* end dasd_3990_erp_no_rec */
1348
1349/*
1350 * DASD_3990_ERP_FILE_PROT
1351 *
1352 * DESCRIPTION
1353 * Handles 24 byte 'File Protected' error.
1354 * Note: Seek related recovery is not implemented because
1355 * wee don't use the seek command yet.
1356 *
1357 * PARAMETER
1358 * erp current erp_head
1359 * RETURN VALUES
1360 * erp new erp_head - pointer to new ERP
1361 */
1362static struct dasd_ccw_req *
1363dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
1364{
1365
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001366 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367
1368 DEV_MESSAGE(KERN_ERR, device, "%s", "File Protected");
1369
1370 return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
1371
1372} /* end dasd_3990_erp_file_prot */
1373
1374/*
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001375 * DASD_3990_ERP_INSPECT_ALIAS
1376 *
1377 * DESCRIPTION
1378 * Checks if the original request was started on an alias device.
1379 * If yes, it modifies the original and the erp request so that
1380 * the erp request can be started on a base device.
1381 *
1382 * PARAMETER
1383 * erp pointer to the currently created default ERP
1384 *
1385 * RETURN VALUES
1386 * erp pointer to the modified ERP, or NULL
1387 */
1388
1389static struct dasd_ccw_req *dasd_3990_erp_inspect_alias(
1390 struct dasd_ccw_req *erp)
1391{
1392 struct dasd_ccw_req *cqr = erp->refers;
1393
1394 if (cqr->block &&
1395 (cqr->block->base != cqr->startdev)) {
1396 if (cqr->startdev->features & DASD_FEATURE_ERPLOG) {
1397 DEV_MESSAGE(KERN_ERR, cqr->startdev,
1398 "ERP on alias device for request %p,"
1399 " recover on base device %s", cqr,
Kay Sievers2a0217d2008-10-10 21:33:09 +02001400 dev_name(&cqr->block->base->cdev->dev));
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001401 }
1402 dasd_eckd_reset_ccw_to_base_io(cqr);
1403 erp->startdev = cqr->block->base;
1404 erp->function = dasd_3990_erp_inspect_alias;
1405 return erp;
1406 } else
1407 return NULL;
1408}
1409
1410
1411/*
Horst Hummel138c0142006-06-29 14:58:12 +02001412 * DASD_3990_ERP_INSPECT_24
Linus Torvalds1da177e2005-04-16 15:20:36 -07001413 *
1414 * DESCRIPTION
1415 * Does a detailed inspection of the 24 byte sense data
Horst Hummel138c0142006-06-29 14:58:12 +02001416 * and sets up a related error recovery action.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001417 *
1418 * PARAMETER
1419 * sense sense data of the actual error
1420 * erp pointer to the currently created default ERP
1421 *
1422 * RETURN VALUES
1423 * erp pointer to the (addtitional) ERP
1424 */
1425static struct dasd_ccw_req *
1426dasd_3990_erp_inspect_24(struct dasd_ccw_req * erp, char *sense)
1427{
1428
1429 struct dasd_ccw_req *erp_filled = NULL;
1430
1431 /* Check sense for .... */
1432 /* 'Command Reject' */
1433 if ((erp_filled == NULL) && (sense[0] & SNS0_CMD_REJECT)) {
1434 erp_filled = dasd_3990_erp_com_rej(erp, sense);
1435 }
1436 /* 'Intervention Required' */
1437 if ((erp_filled == NULL) && (sense[0] & SNS0_INTERVENTION_REQ)) {
1438 erp_filled = dasd_3990_erp_int_req(erp);
1439 }
1440 /* 'Bus Out Parity Check' */
1441 if ((erp_filled == NULL) && (sense[0] & SNS0_BUS_OUT_CHECK)) {
1442 erp_filled = dasd_3990_erp_bus_out(erp);
1443 }
1444 /* 'Equipment Check' */
1445 if ((erp_filled == NULL) && (sense[0] & SNS0_EQUIPMENT_CHECK)) {
1446 erp_filled = dasd_3990_erp_equip_check(erp, sense);
1447 }
1448 /* 'Data Check' */
1449 if ((erp_filled == NULL) && (sense[0] & SNS0_DATA_CHECK)) {
1450 erp_filled = dasd_3990_erp_data_check(erp, sense);
1451 }
1452 /* 'Overrun' */
1453 if ((erp_filled == NULL) && (sense[0] & SNS0_OVERRUN)) {
1454 erp_filled = dasd_3990_erp_overrun(erp, sense);
1455 }
1456 /* 'Invalid Track Format' */
1457 if ((erp_filled == NULL) && (sense[1] & SNS1_INV_TRACK_FORMAT)) {
1458 erp_filled = dasd_3990_erp_inv_format(erp, sense);
1459 }
1460 /* 'End-of-Cylinder' */
1461 if ((erp_filled == NULL) && (sense[1] & SNS1_EOC)) {
1462 erp_filled = dasd_3990_erp_EOC(erp, sense);
1463 }
1464 /* 'Environmental Data' */
1465 if ((erp_filled == NULL) && (sense[2] & SNS2_ENV_DATA_PRESENT)) {
1466 erp_filled = dasd_3990_erp_env_data(erp, sense);
1467 }
1468 /* 'No Record Found' */
1469 if ((erp_filled == NULL) && (sense[1] & SNS1_NO_REC_FOUND)) {
1470 erp_filled = dasd_3990_erp_no_rec(erp, sense);
1471 }
1472 /* 'File Protected' */
1473 if ((erp_filled == NULL) && (sense[1] & SNS1_FILE_PROTECTED)) {
1474 erp_filled = dasd_3990_erp_file_prot(erp);
1475 }
1476 /* other (unknown) error - do default ERP */
1477 if (erp_filled == NULL) {
1478
1479 erp_filled = erp;
1480 }
1481
1482 return erp_filled;
1483
1484} /* END dasd_3990_erp_inspect_24 */
1485
1486/*
Horst Hummel138c0142006-06-29 14:58:12 +02001487 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -07001488 * 32 byte sense ERP functions (only)
Horst Hummel138c0142006-06-29 14:58:12 +02001489 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 */
1491
1492/*
Horst Hummel138c0142006-06-29 14:58:12 +02001493 * DASD_3990_ERPACTION_10_32
Linus Torvalds1da177e2005-04-16 15:20:36 -07001494 *
1495 * DESCRIPTION
1496 * Handles 32 byte 'Action 10' of Single Program Action Codes.
1497 * Just retry and if retry doesn't work, return with error.
1498 *
1499 * PARAMETER
1500 * erp current erp_head
Horst Hummel138c0142006-06-29 14:58:12 +02001501 * sense current sense data
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 * RETURN VALUES
1503 * erp modified erp_head
1504 */
1505static struct dasd_ccw_req *
1506dasd_3990_erp_action_10_32(struct dasd_ccw_req * erp, char *sense)
1507{
1508
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001509 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510
1511 erp->retries = 256;
1512 erp->function = dasd_3990_erp_action_10_32;
1513
1514 DEV_MESSAGE(KERN_DEBUG, device, "%s", "Perform logging requested");
1515
1516 return erp;
1517
1518} /* end dasd_3990_erp_action_10_32 */
1519
1520/*
1521 * DASD_3990_ERP_ACTION_1B_32
1522 *
1523 * DESCRIPTION
1524 * Handles 32 byte 'Action 1B' of Single Program Action Codes.
Horst Hummel138c0142006-06-29 14:58:12 +02001525 * A write operation could not be finished because of an unexpected
Linus Torvalds1da177e2005-04-16 15:20:36 -07001526 * condition.
Horst Hummel138c0142006-06-29 14:58:12 +02001527 * The already created 'default erp' is used to get the link to
1528 * the erp chain, but it can not be used for this recovery
Linus Torvalds1da177e2005-04-16 15:20:36 -07001529 * action because it contains no DE/LO data space.
1530 *
1531 * PARAMETER
1532 * default_erp already added default erp.
Horst Hummel138c0142006-06-29 14:58:12 +02001533 * sense current sense data
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 *
1535 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +02001536 * erp new erp or
Linus Torvalds1da177e2005-04-16 15:20:36 -07001537 * default_erp in case of imprecise ending or error
1538 */
1539static struct dasd_ccw_req *
1540dasd_3990_erp_action_1B_32(struct dasd_ccw_req * default_erp, char *sense)
1541{
1542
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001543 struct dasd_device *device = default_erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544 __u32 cpa = 0;
1545 struct dasd_ccw_req *cqr;
1546 struct dasd_ccw_req *erp;
1547 struct DE_eckd_data *DE_data;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001548 struct PFX_eckd_data *PFX_data;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001549 char *LO_data; /* LO_eckd_data_t */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001550 struct ccw1 *ccw, *oldccw;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551
1552 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1553 "Write not finished because of unexpected condition");
1554
1555 default_erp->function = dasd_3990_erp_action_1B_32;
1556
1557 /* determine the original cqr */
1558 cqr = default_erp;
1559
1560 while (cqr->refers != NULL) {
1561 cqr = cqr->refers;
1562 }
1563
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01001564 if (scsw_is_tm(&cqr->irb.scsw)) {
1565 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
1566 "32 bit sense, action 1B is not defined"
1567 " in transport mode - just retry");
1568 return default_erp;
1569 }
1570
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571 /* for imprecise ending just do default erp */
1572 if (sense[1] & 0x01) {
1573
1574 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1575 "Imprecise ending is set - just retry");
1576
1577 return default_erp;
1578 }
1579
1580 /* determine the address of the CCW to be restarted */
1581 /* Imprecise ending is not set -> addr from IRB-SCSW */
Peter Oberparleiter23d805b2008-07-14 09:58:50 +02001582 cpa = default_erp->refers->irb.scsw.cmd.cpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
1584 if (cpa == 0) {
1585
1586 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1587 "Unable to determine address of the CCW "
1588 "to be restarted");
1589
1590 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
1591 }
1592
1593 /* Build new ERP request including DE/LO */
1594 erp = dasd_alloc_erp_request((char *) &cqr->magic,
1595 2 + 1,/* DE/LO + TIC */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001596 sizeof(struct DE_eckd_data) +
1597 sizeof(struct LO_eckd_data), device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001598
1599 if (IS_ERR(erp)) {
1600 DEV_MESSAGE(KERN_ERR, device, "%s", "Unable to allocate ERP");
1601 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
1602 }
1603
1604 /* use original DE */
1605 DE_data = erp->data;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001606 oldccw = cqr->cpaddr;
1607 if (oldccw->cmd_code == DASD_ECKD_CCW_PFX) {
1608 PFX_data = cqr->data;
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01001609 memcpy(DE_data, &PFX_data->define_extent,
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001610 sizeof(struct DE_eckd_data));
1611 } else
1612 memcpy(DE_data, cqr->data, sizeof(struct DE_eckd_data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001613
1614 /* create LO */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001615 LO_data = erp->data + sizeof(struct DE_eckd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001616
1617 if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
1618
1619 DEV_MESSAGE(KERN_ERR, device, "%s",
1620 "BUG - this should not happen");
1621
1622 return dasd_3990_erp_cleanup(default_erp, DASD_CQR_FAILED);
1623 }
1624
1625 if ((sense[7] & 0x3F) == 0x01) {
1626 /* operation code is WRITE DATA -> data area orientation */
1627 LO_data[0] = 0x81;
1628
1629 } else if ((sense[7] & 0x3F) == 0x03) {
1630 /* operation code is FORMAT WRITE -> index orientation */
1631 LO_data[0] = 0xC3;
1632
1633 } else {
1634 LO_data[0] = sense[7]; /* operation */
1635 }
1636
1637 LO_data[1] = sense[8]; /* auxiliary */
1638 LO_data[2] = sense[9];
1639 LO_data[3] = sense[3]; /* count */
1640 LO_data[4] = sense[29]; /* seek_addr.cyl */
1641 LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */
1642 LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */
1643
1644 memcpy(&(LO_data[8]), &(sense[11]), 8);
1645
1646 /* create DE ccw */
1647 ccw = erp->cpaddr;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001648 memset(ccw, 0, sizeof(struct ccw1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001649 ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
1650 ccw->flags = CCW_FLAG_CC;
1651 ccw->count = 16;
1652 ccw->cda = (__u32)(addr_t) DE_data;
1653
1654 /* create LO ccw */
1655 ccw++;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001656 memset(ccw, 0, sizeof(struct ccw1));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001657 ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
1658 ccw->flags = CCW_FLAG_CC;
1659 ccw->count = 16;
1660 ccw->cda = (__u32)(addr_t) LO_data;
1661
1662 /* TIC to the failed ccw */
1663 ccw++;
1664 ccw->cmd_code = CCW_CMD_TIC;
1665 ccw->cda = cpa;
1666
1667 /* fill erp related fields */
1668 erp->function = dasd_3990_erp_action_1B_32;
1669 erp->refers = default_erp->refers;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001670 erp->startdev = device;
1671 erp->memdev = device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672 erp->magic = default_erp->magic;
1673 erp->expires = 0;
1674 erp->retries = 256;
1675 erp->buildclk = get_clock();
1676 erp->status = DASD_CQR_FILLED;
1677
1678 /* remove the default erp */
1679 dasd_free_erp_request(default_erp, device);
1680
1681 return erp;
1682
1683} /* end dasd_3990_erp_action_1B_32 */
1684
1685/*
1686 * DASD_3990_UPDATE_1B
1687 *
1688 * DESCRIPTION
Horst Hummel138c0142006-06-29 14:58:12 +02001689 * Handles the update to the 32 byte 'Action 1B' of Single Program
Linus Torvalds1da177e2005-04-16 15:20:36 -07001690 * Action Codes in case the first action was not successful.
1691 * The already created 'previous_erp' is the currently not successful
Horst Hummel138c0142006-06-29 14:58:12 +02001692 * ERP.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693 *
1694 * PARAMETER
1695 * previous_erp already created previous erp.
Horst Hummel138c0142006-06-29 14:58:12 +02001696 * sense current sense data
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +02001698 * erp modified erp
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699 */
1700static struct dasd_ccw_req *
1701dasd_3990_update_1B(struct dasd_ccw_req * previous_erp, char *sense)
1702{
1703
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001704 struct dasd_device *device = previous_erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705 __u32 cpa = 0;
1706 struct dasd_ccw_req *cqr;
1707 struct dasd_ccw_req *erp;
1708 char *LO_data; /* struct LO_eckd_data */
1709 struct ccw1 *ccw;
1710
1711 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1712 "Write not finished because of unexpected condition"
1713 " - follow on");
1714
1715 /* determine the original cqr */
1716 cqr = previous_erp;
1717
1718 while (cqr->refers != NULL) {
1719 cqr = cqr->refers;
1720 }
1721
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01001722 if (scsw_is_tm(&cqr->irb.scsw)) {
1723 DBF_DEV_EVENT(DBF_WARNING, device, "%s",
1724 "32 bit sense, action 1B, update,"
1725 " in transport mode - just retry");
1726 return previous_erp;
1727 }
1728
Linus Torvalds1da177e2005-04-16 15:20:36 -07001729 /* for imprecise ending just do default erp */
1730 if (sense[1] & 0x01) {
1731
1732 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1733 "Imprecise ending is set - just retry");
1734
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001735 previous_erp->status = DASD_CQR_FILLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001736
1737 return previous_erp;
1738 }
1739
1740 /* determine the address of the CCW to be restarted */
1741 /* Imprecise ending is not set -> addr from IRB-SCSW */
Peter Oberparleiter23d805b2008-07-14 09:58:50 +02001742 cpa = previous_erp->irb.scsw.cmd.cpa;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001743
1744 if (cpa == 0) {
1745
1746 DEV_MESSAGE(KERN_DEBUG, device, "%s",
1747 "Unable to determine address of the CCW "
1748 "to be restarted");
1749
1750 previous_erp->status = DASD_CQR_FAILED;
1751
1752 return previous_erp;
1753 }
1754
1755 erp = previous_erp;
1756
1757 /* update the LO with the new returned sense data */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001758 LO_data = erp->data + sizeof(struct DE_eckd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001759
1760 if ((sense[3] == 0x01) && (LO_data[1] & 0x01)) {
1761
1762 DEV_MESSAGE(KERN_ERR, device, "%s",
1763 "BUG - this should not happen");
1764
1765 previous_erp->status = DASD_CQR_FAILED;
1766
1767 return previous_erp;
1768 }
1769
1770 if ((sense[7] & 0x3F) == 0x01) {
1771 /* operation code is WRITE DATA -> data area orientation */
1772 LO_data[0] = 0x81;
1773
1774 } else if ((sense[7] & 0x3F) == 0x03) {
1775 /* operation code is FORMAT WRITE -> index orientation */
1776 LO_data[0] = 0xC3;
1777
1778 } else {
1779 LO_data[0] = sense[7]; /* operation */
1780 }
1781
1782 LO_data[1] = sense[8]; /* auxiliary */
1783 LO_data[2] = sense[9];
1784 LO_data[3] = sense[3]; /* count */
1785 LO_data[4] = sense[29]; /* seek_addr.cyl */
1786 LO_data[5] = sense[30]; /* seek_addr.cyl 2nd byte */
1787 LO_data[7] = sense[31]; /* seek_addr.head 2nd byte */
1788
1789 memcpy(&(LO_data[8]), &(sense[11]), 8);
1790
1791 /* TIC to the failed ccw */
1792 ccw = erp->cpaddr; /* addr of DE ccw */
1793 ccw++; /* addr of LE ccw */
1794 ccw++; /* addr of TIC ccw */
1795 ccw->cda = cpa;
1796
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001797 erp->status = DASD_CQR_FILLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001798
1799 return erp;
1800
1801} /* end dasd_3990_update_1B */
1802
1803/*
Horst Hummel138c0142006-06-29 14:58:12 +02001804 * DASD_3990_ERP_COMPOUND_RETRY
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 *
1806 * DESCRIPTION
1807 * Handles the compound ERP action retry code.
1808 * NOTE: At least one retry is done even if zero is specified
1809 * by the sense data. This makes enqueueing of the request
1810 * easier.
1811 *
1812 * PARAMETER
1813 * sense sense data of the actual error
1814 * erp pointer to the currently created ERP
1815 *
1816 * RETURN VALUES
1817 * erp modified ERP pointer
1818 *
1819 */
1820static void
1821dasd_3990_erp_compound_retry(struct dasd_ccw_req * erp, char *sense)
1822{
1823
1824 switch (sense[25] & 0x03) {
1825 case 0x00: /* no not retry */
1826 erp->retries = 1;
1827 break;
1828
1829 case 0x01: /* retry 2 times */
1830 erp->retries = 2;
1831 break;
1832
1833 case 0x02: /* retry 10 times */
1834 erp->retries = 10;
1835 break;
1836
1837 case 0x03: /* retry 256 times */
1838 erp->retries = 256;
1839 break;
1840
1841 default:
1842 BUG();
1843 }
1844
1845 erp->function = dasd_3990_erp_compound_retry;
1846
1847} /* end dasd_3990_erp_compound_retry */
1848
1849/*
Horst Hummel138c0142006-06-29 14:58:12 +02001850 * DASD_3990_ERP_COMPOUND_PATH
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 *
1852 * DESCRIPTION
1853 * Handles the compound ERP action for retry on alternate
1854 * channel path.
1855 *
1856 * PARAMETER
1857 * sense sense data of the actual error
1858 * erp pointer to the currently created ERP
1859 *
1860 * RETURN VALUES
1861 * erp modified ERP pointer
1862 *
1863 */
1864static void
1865dasd_3990_erp_compound_path(struct dasd_ccw_req * erp, char *sense)
1866{
1867
1868 if (sense[25] & DASD_SENSE_BIT_3) {
1869 dasd_3990_erp_alternate_path(erp);
1870
1871 if (erp->status == DASD_CQR_FAILED) {
Horst Hummel138c0142006-06-29 14:58:12 +02001872 /* reset the lpm and the status to be able to
Linus Torvalds1da177e2005-04-16 15:20:36 -07001873 * try further actions. */
1874
1875 erp->lpm = 0;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001876 erp->status = DASD_CQR_NEED_ERP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877 }
1878 }
1879
1880 erp->function = dasd_3990_erp_compound_path;
1881
1882} /* end dasd_3990_erp_compound_path */
1883
1884/*
Horst Hummel138c0142006-06-29 14:58:12 +02001885 * DASD_3990_ERP_COMPOUND_CODE
Linus Torvalds1da177e2005-04-16 15:20:36 -07001886 *
1887 * DESCRIPTION
1888 * Handles the compound ERP action for retry code.
1889 *
1890 * PARAMETER
1891 * sense sense data of the actual error
1892 * erp pointer to the currently created ERP
1893 *
1894 * RETURN VALUES
1895 * erp NEW ERP pointer
1896 *
1897 */
1898static struct dasd_ccw_req *
1899dasd_3990_erp_compound_code(struct dasd_ccw_req * erp, char *sense)
1900{
1901
1902 if (sense[25] & DASD_SENSE_BIT_2) {
1903
1904 switch (sense[28]) {
1905 case 0x17:
Horst Hummel138c0142006-06-29 14:58:12 +02001906 /* issue a Diagnostic Control command with an
Robert P. J. Day3a4fa0a2007-10-19 23:10:43 +02001907 * Inhibit Write subcommand and controller modifier */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908 erp = dasd_3990_erp_DCTL(erp, 0x20);
1909 break;
Horst Hummel138c0142006-06-29 14:58:12 +02001910
Linus Torvalds1da177e2005-04-16 15:20:36 -07001911 case 0x25:
1912 /* wait for 5 seconds and retry again */
1913 erp->retries = 1;
Horst Hummel138c0142006-06-29 14:58:12 +02001914
Linus Torvalds1da177e2005-04-16 15:20:36 -07001915 dasd_3990_erp_block_queue (erp, 5*HZ);
1916 break;
Horst Hummel138c0142006-06-29 14:58:12 +02001917
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 default:
1919 /* should not happen - continue */
1920 break;
1921 }
1922 }
1923
1924 erp->function = dasd_3990_erp_compound_code;
1925
1926 return erp;
1927
1928} /* end dasd_3990_erp_compound_code */
1929
1930/*
Horst Hummel138c0142006-06-29 14:58:12 +02001931 * DASD_3990_ERP_COMPOUND_CONFIG
Linus Torvalds1da177e2005-04-16 15:20:36 -07001932 *
1933 * DESCRIPTION
1934 * Handles the compound ERP action for configruation
1935 * dependent error.
1936 * Note: duplex handling is not implemented (yet).
1937 *
1938 * PARAMETER
1939 * sense sense data of the actual error
1940 * erp pointer to the currently created ERP
1941 *
1942 * RETURN VALUES
1943 * erp modified ERP pointer
1944 *
1945 */
1946static void
1947dasd_3990_erp_compound_config(struct dasd_ccw_req * erp, char *sense)
1948{
1949
1950 if ((sense[25] & DASD_SENSE_BIT_1) && (sense[26] & DASD_SENSE_BIT_2)) {
1951
1952 /* set to suspended duplex state then restart */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001953 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954
1955 DEV_MESSAGE(KERN_ERR, device, "%s",
1956 "Set device to suspended duplex state should be "
1957 "done!\n"
1958 "This is not implemented yet (for compound ERP)"
1959 " - please report to linux390@de.ibm.com");
1960
1961 }
1962
1963 erp->function = dasd_3990_erp_compound_config;
1964
1965} /* end dasd_3990_erp_compound_config */
1966
1967/*
Horst Hummel138c0142006-06-29 14:58:12 +02001968 * DASD_3990_ERP_COMPOUND
Linus Torvalds1da177e2005-04-16 15:20:36 -07001969 *
1970 * DESCRIPTION
Horst Hummel138c0142006-06-29 14:58:12 +02001971 * Does the further compound program action if
Linus Torvalds1da177e2005-04-16 15:20:36 -07001972 * compound retry was not successful.
1973 *
1974 * PARAMETER
1975 * sense sense data of the actual error
1976 * erp pointer to the current (failed) ERP
1977 *
1978 * RETURN VALUES
1979 * erp (additional) ERP pointer
1980 *
1981 */
1982static struct dasd_ccw_req *
1983dasd_3990_erp_compound(struct dasd_ccw_req * erp, char *sense)
1984{
1985
1986 if ((erp->function == dasd_3990_erp_compound_retry) &&
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001987 (erp->status == DASD_CQR_NEED_ERP)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001988
1989 dasd_3990_erp_compound_path(erp, sense);
1990 }
1991
1992 if ((erp->function == dasd_3990_erp_compound_path) &&
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001993 (erp->status == DASD_CQR_NEED_ERP)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001994
1995 erp = dasd_3990_erp_compound_code(erp, sense);
1996 }
1997
1998 if ((erp->function == dasd_3990_erp_compound_code) &&
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01001999 (erp->status == DASD_CQR_NEED_ERP)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002000
2001 dasd_3990_erp_compound_config(erp, sense);
2002 }
2003
2004 /* if no compound action ERP specified, the request failed */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002005 if (erp->status == DASD_CQR_NEED_ERP)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002006 erp->status = DASD_CQR_FAILED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002007
2008 return erp;
2009
2010} /* end dasd_3990_erp_compound */
2011
2012/*
Stefan Haberlandf60c7682008-04-17 07:46:08 +02002013 *DASD_3990_ERP_HANDLE_SIM
2014 *
2015 *DESCRIPTION
2016 * inspects the SIM SENSE data and starts an appropriate action
2017 *
2018 * PARAMETER
2019 * sense sense data of the actual error
2020 *
2021 * RETURN VALUES
2022 * none
2023 */
2024void
2025dasd_3990_erp_handle_sim(struct dasd_device *device, char *sense)
2026{
2027 /* print message according to log or message to operator mode */
2028 if ((sense[24] & DASD_SIM_MSG_TO_OP) || (sense[1] & 0x10)) {
2029
2030 /* print SIM SRC from RefCode */
2031 DEV_MESSAGE(KERN_ERR, device, "SIM - SRC: "
2032 "%02x%02x%02x%02x", sense[22],
2033 sense[23], sense[11], sense[12]);
2034 } else if (sense[24] & DASD_SIM_LOG) {
2035 /* print SIM SRC Refcode */
2036 DEV_MESSAGE(KERN_WARNING, device, "SIM - SRC: "
2037 "%02x%02x%02x%02x", sense[22],
2038 sense[23], sense[11], sense[12]);
2039 }
2040}
2041
2042/*
Horst Hummel138c0142006-06-29 14:58:12 +02002043 * DASD_3990_ERP_INSPECT_32
Linus Torvalds1da177e2005-04-16 15:20:36 -07002044 *
2045 * DESCRIPTION
2046 * Does a detailed inspection of the 32 byte sense data
Horst Hummel138c0142006-06-29 14:58:12 +02002047 * and sets up a related error recovery action.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002048 *
2049 * PARAMETER
2050 * sense sense data of the actual error
2051 * erp pointer to the currently created default ERP
2052 *
2053 * RETURN VALUES
2054 * erp_filled pointer to the ERP
2055 *
2056 */
2057static struct dasd_ccw_req *
2058dasd_3990_erp_inspect_32(struct dasd_ccw_req * erp, char *sense)
2059{
2060
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002061 struct dasd_device *device = erp->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062
2063 erp->function = dasd_3990_erp_inspect_32;
2064
Stefan Haberlandf60c7682008-04-17 07:46:08 +02002065 /* check for SIM sense data */
2066 if ((sense[6] & DASD_SIM_SENSE) == DASD_SIM_SENSE)
2067 dasd_3990_erp_handle_sim(device, sense);
2068
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069 if (sense[25] & DASD_SENSE_BIT_0) {
2070
2071 /* compound program action codes (byte25 bit 0 == '1') */
2072 dasd_3990_erp_compound_retry(erp, sense);
2073
2074 } else {
2075
2076 /* single program action codes (byte25 bit 0 == '0') */
2077 switch (sense[25]) {
2078
2079 case 0x00: /* success - use default ERP for retries */
2080 DEV_MESSAGE(KERN_DEBUG, device, "%s",
2081 "ERP called for successful request"
2082 " - just retry");
2083 break;
2084
2085 case 0x01: /* fatal error */
2086 DEV_MESSAGE(KERN_ERR, device, "%s",
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002087 "Retry not recommended - Fatal error");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
2089 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
2090 break;
2091
2092 case 0x02: /* intervention required */
2093 case 0x03: /* intervention required during dual copy */
2094 erp = dasd_3990_erp_int_req(erp);
2095 break;
2096
2097 case 0x0F: /* length mismatch during update write command */
2098 DEV_MESSAGE(KERN_ERR, device, "%s",
2099 "update write command error - should not "
2100 "happen;\n"
2101 "Please send this message together with "
2102 "the above sense data to linux390@de."
2103 "ibm.com");
2104
2105 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
2106 break;
2107
2108 case 0x10: /* logging required for other channel program */
2109 erp = dasd_3990_erp_action_10_32(erp, sense);
2110 break;
2111
2112 case 0x15: /* next track outside defined extend */
2113 DEV_MESSAGE(KERN_ERR, device, "%s",
2114 "next track outside defined extend - "
2115 "should not happen;\n"
2116 "Please send this message together with "
2117 "the above sense data to linux390@de."
2118 "ibm.com");
2119
2120 erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
2121 break;
2122
2123 case 0x1B: /* unexpected condition during write */
2124
2125 erp = dasd_3990_erp_action_1B_32(erp, sense);
2126 break;
2127
2128 case 0x1C: /* invalid data */
2129 DEV_MESSAGE(KERN_EMERG, device, "%s",
2130 "Data recovered during retry with PCI "
2131 "fetch mode active");
2132
2133 /* not possible to handle this situation in Linux */
2134 panic
2135 ("Invalid data - No way to inform application "
2136 "about the possibly incorrect data");
2137 break;
2138
2139 case 0x1D: /* state-change pending */
2140 DEV_MESSAGE(KERN_DEBUG, device, "%s",
2141 "A State change pending condition exists "
2142 "for the subsystem or device");
2143
2144 erp = dasd_3990_erp_action_4(erp, sense);
2145 break;
2146
2147 case 0x1E: /* busy */
2148 DEV_MESSAGE(KERN_DEBUG, device, "%s",
2149 "Busy condition exists "
2150 "for the subsystem or device");
2151 erp = dasd_3990_erp_action_4(erp, sense);
2152 break;
2153
2154 default: /* all others errors - default erp */
2155 break;
2156 }
2157 }
2158
2159 return erp;
2160
2161} /* end dasd_3990_erp_inspect_32 */
2162
2163/*
Horst Hummel138c0142006-06-29 14:58:12 +02002164 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -07002165 * main ERP control fuctions (24 and 32 byte sense)
Horst Hummel138c0142006-06-29 14:58:12 +02002166 *****************************************************************************
Linus Torvalds1da177e2005-04-16 15:20:36 -07002167 */
2168
2169/*
Stefan Haberland6c5f57c2008-02-05 16:50:46 +01002170 * DASD_3990_ERP_CONTROL_CHECK
2171 *
2172 * DESCRIPTION
2173 * Does a generic inspection if a control check occured and sets up
2174 * the related error recovery procedure
2175 *
2176 * PARAMETER
2177 * erp pointer to the currently created default ERP
2178 *
2179 * RETURN VALUES
2180 * erp_filled pointer to the erp
2181 */
2182
2183static struct dasd_ccw_req *
2184dasd_3990_erp_control_check(struct dasd_ccw_req *erp)
2185{
2186 struct dasd_device *device = erp->startdev;
2187
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002188 if (scsw_cstat(&erp->refers->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK
Stefan Haberland6c5f57c2008-02-05 16:50:46 +01002189 | SCHN_STAT_CHN_CTRL_CHK)) {
2190 DEV_MESSAGE(KERN_DEBUG, device, "%s",
2191 "channel or interface control check");
2192 erp = dasd_3990_erp_action_4(erp, NULL);
2193 }
2194 return erp;
2195}
2196
2197/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 * DASD_3990_ERP_INSPECT
2199 *
2200 * DESCRIPTION
2201 * Does a detailed inspection for sense data by calling either
2202 * the 24-byte or the 32-byte inspection routine.
2203 *
2204 * PARAMETER
2205 * erp pointer to the currently created default ERP
2206 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +02002207 * erp_new contens was possibly modified
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 */
2209static struct dasd_ccw_req *
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002210dasd_3990_erp_inspect(struct dasd_ccw_req *erp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211{
2212
2213 struct dasd_ccw_req *erp_new = NULL;
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002214 char *sense;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002215
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002216 /* if this problem occured on an alias retry on base */
2217 erp_new = dasd_3990_erp_inspect_alias(erp);
2218 if (erp_new)
2219 return erp_new;
2220
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002221 /* sense data are located in the refers record of the
2222 * already set up new ERP !
2223 * check if concurrent sens is available
2224 */
2225 sense = dasd_get_sense(&erp->refers->irb);
2226 if (!sense)
Stefan Haberland6c5f57c2008-02-05 16:50:46 +01002227 erp_new = dasd_3990_erp_control_check(erp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 /* distinguish between 24 and 32 byte sense data */
Stefan Haberland6c5f57c2008-02-05 16:50:46 +01002229 else if (sense[27] & DASD_SENSE_BIT_0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002230
2231 /* inspect the 24 byte sense data */
2232 erp_new = dasd_3990_erp_inspect_24(erp, sense);
2233
2234 } else {
2235
2236 /* inspect the 32 byte sense data */
2237 erp_new = dasd_3990_erp_inspect_32(erp, sense);
2238
2239 } /* end distinguish between 24 and 32 byte sense data */
2240
2241 return erp_new;
2242}
2243
2244/*
2245 * DASD_3990_ERP_ADD_ERP
Horst Hummel138c0142006-06-29 14:58:12 +02002246 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002247 * DESCRIPTION
2248 * This funtion adds an additional request block (ERP) to the head of
2249 * the given cqr (or erp).
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002250 * For a command mode cqr the erp is initialized as an default erp
2251 * (retry TIC).
2252 * For transport mode we make a copy of the original TCW (points to
2253 * the original TCCB, TIDALs, etc.) but give it a fresh
2254 * TSB so the original sense data will not be changed.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002255 *
2256 * PARAMETER
Horst Hummel138c0142006-06-29 14:58:12 +02002257 * cqr head of the current ERP-chain (or single cqr if
Linus Torvalds1da177e2005-04-16 15:20:36 -07002258 * first error)
2259 * RETURN VALUES
2260 * erp pointer to new ERP-chain head
2261 */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002262static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263{
2264
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002265 struct dasd_device *device = cqr->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002266 struct ccw1 *ccw;
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002267 struct dasd_ccw_req *erp;
2268 int cplength, datasize;
2269 struct tcw *tcw;
2270 struct tsb *tsb;
2271
2272 if (cqr->cpmode == 1) {
2273 cplength = 0;
2274 datasize = sizeof(struct tcw) + sizeof(struct tsb);
2275 } else {
2276 cplength = 2;
2277 datasize = 0;
2278 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002279
2280 /* allocate additional request block */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002281 erp = dasd_alloc_erp_request((char *) &cqr->magic,
2282 cplength, datasize, device);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 if (IS_ERR(erp)) {
2284 if (cqr->retries <= 0) {
2285 DEV_MESSAGE(KERN_ERR, device, "%s",
2286 "Unable to allocate ERP request");
2287 cqr->status = DASD_CQR_FAILED;
2288 cqr->stopclk = get_clock ();
2289 } else {
2290 DEV_MESSAGE (KERN_ERR, device,
2291 "Unable to allocate ERP request "
2292 "(%i retries left)",
2293 cqr->retries);
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002294 dasd_block_set_timer(device->block, (HZ << 3));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295 }
2296 return cqr;
2297 }
2298
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002299 if (cqr->cpmode == 1) {
2300 /* make a shallow copy of the original tcw but set new tsb */
2301 erp->cpmode = 1;
2302 erp->cpaddr = erp->data;
2303 tcw = erp->data;
2304 tsb = (struct tsb *) &tcw[1];
2305 *tcw = *((struct tcw *)cqr->cpaddr);
2306 tcw->tsb = (long)tsb;
2307 } else {
2308 /* initialize request with default TIC to current ERP/CQR */
2309 ccw = erp->cpaddr;
2310 ccw->cmd_code = CCW_CMD_NOOP;
2311 ccw->flags = CCW_FLAG_CC;
2312 ccw++;
2313 ccw->cmd_code = CCW_CMD_TIC;
2314 ccw->cda = (long)(cqr->cpaddr);
2315 }
2316
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317 erp->function = dasd_3990_erp_add_erp;
2318 erp->refers = cqr;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002319 erp->startdev = device;
2320 erp->memdev = device;
2321 erp->block = cqr->block;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322 erp->magic = cqr->magic;
2323 erp->expires = 0;
2324 erp->retries = 256;
2325 erp->buildclk = get_clock();
Linus Torvalds1da177e2005-04-16 15:20:36 -07002326 erp->status = DASD_CQR_FILLED;
2327
2328 return erp;
2329}
2330
2331/*
Horst Hummel138c0142006-06-29 14:58:12 +02002332 * DASD_3990_ERP_ADDITIONAL_ERP
2333 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334 * DESCRIPTION
2335 * An additional ERP is needed to handle the current error.
2336 * Add ERP to the head of the ERP-chain containing the ERP processing
2337 * determined based on the sense data.
2338 *
2339 * PARAMETER
Horst Hummel138c0142006-06-29 14:58:12 +02002340 * cqr head of the current ERP-chain (or single cqr if
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341 * first error)
2342 *
2343 * RETURN VALUES
2344 * erp pointer to new ERP-chain head
2345 */
2346static struct dasd_ccw_req *
2347dasd_3990_erp_additional_erp(struct dasd_ccw_req * cqr)
2348{
2349
2350 struct dasd_ccw_req *erp = NULL;
2351
2352 /* add erp and initialize with default TIC */
2353 erp = dasd_3990_erp_add_erp(cqr);
2354
2355 /* inspect sense, determine specific ERP if possible */
2356 if (erp != cqr) {
2357
2358 erp = dasd_3990_erp_inspect(erp);
2359 }
2360
2361 return erp;
2362
2363} /* end dasd_3990_erp_additional_erp */
2364
2365/*
2366 * DASD_3990_ERP_ERROR_MATCH
2367 *
2368 * DESCRIPTION
2369 * Check if the device status of the given cqr is the same.
2370 * This means that the failed CCW and the relevant sense data
2371 * must match.
2372 * I don't distinguish between 24 and 32 byte sense because in case of
2373 * 24 byte sense byte 25 and 27 is set as well.
2374 *
2375 * PARAMETER
Horst Hummel138c0142006-06-29 14:58:12 +02002376 * cqr1 first cqr, which will be compared with the
Linus Torvalds1da177e2005-04-16 15:20:36 -07002377 * cqr2 second cqr.
2378 *
2379 * RETURN VALUES
2380 * match 'boolean' for match found
2381 * returns 1 if match found, otherwise 0.
2382 */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002383static int dasd_3990_erp_error_match(struct dasd_ccw_req *cqr1,
2384 struct dasd_ccw_req *cqr2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385{
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002386 char *sense1, *sense2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002387
Stefan Weinhuber5c12f242008-03-05 12:37:10 +01002388 if (cqr1->startdev != cqr2->startdev)
2389 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002390
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002391 sense1 = dasd_get_sense(&cqr1->irb);
2392 sense2 = dasd_get_sense(&cqr2->irb);
Stefan Haberland6c5f57c2008-02-05 16:50:46 +01002393
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002394 /* one request has sense data, the other not -> no match, return 0 */
2395 if (!sense1 != !sense2)
2396 return 0;
2397 /* no sense data in both cases -> check cstat for IFCC */
2398 if (!sense1 && !sense2) {
2399 if ((scsw_cstat(&cqr1->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |
2400 SCHN_STAT_CHN_CTRL_CHK)) ==
2401 (scsw_cstat(&cqr2->irb.scsw) & (SCHN_STAT_INTF_CTRL_CHK |
2402 SCHN_STAT_CHN_CTRL_CHK)))
Stefan Haberland6c5f57c2008-02-05 16:50:46 +01002403 return 1; /* match with ifcc*/
2404 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 /* check sense data; byte 0-2,25,27 */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002406 if (!(sense1 && sense2 &&
2407 (memcmp(sense1, sense2, 3) == 0) &&
2408 (sense1[27] == sense2[27]) &&
2409 (sense1[25] == sense2[25]))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002410
2411 return 0; /* sense doesn't match */
2412 }
2413
2414 return 1; /* match */
2415
2416} /* end dasd_3990_erp_error_match */
2417
2418/*
2419 * DASD_3990_ERP_IN_ERP
2420 *
2421 * DESCRIPTION
2422 * check if the current error already happened before.
2423 * quick exit if current cqr is not an ERP (cqr->refers=NULL)
2424 *
2425 * PARAMETER
2426 * cqr failed cqr (either original cqr or already an erp)
2427 *
2428 * RETURN VALUES
Horst Hummel138c0142006-06-29 14:58:12 +02002429 * erp erp-pointer to the already defined error
Linus Torvalds1da177e2005-04-16 15:20:36 -07002430 * recovery procedure OR
2431 * NULL if a 'new' error occurred.
2432 */
2433static struct dasd_ccw_req *
2434dasd_3990_erp_in_erp(struct dasd_ccw_req *cqr)
2435{
2436
2437 struct dasd_ccw_req *erp_head = cqr, /* save erp chain head */
2438 *erp_match = NULL; /* save erp chain head */
2439 int match = 0; /* 'boolean' for matching error found */
2440
2441 if (cqr->refers == NULL) { /* return if not in erp */
2442 return NULL;
2443 }
2444
2445 /* check the erp/cqr chain for current error */
2446 do {
2447 match = dasd_3990_erp_error_match(erp_head, cqr->refers);
2448 erp_match = cqr; /* save possible matching erp */
2449 cqr = cqr->refers; /* check next erp/cqr in queue */
2450
2451 } while ((cqr->refers != NULL) && (!match));
2452
2453 if (!match) {
2454 return NULL; /* no match was found */
2455 }
2456
2457 return erp_match; /* return address of matching erp */
2458
2459} /* END dasd_3990_erp_in_erp */
2460
2461/*
2462 * DASD_3990_ERP_FURTHER_ERP (24 & 32 byte sense)
2463 *
2464 * DESCRIPTION
Horst Hummel138c0142006-06-29 14:58:12 +02002465 * No retry is left for the current ERP. Check what has to be done
Linus Torvalds1da177e2005-04-16 15:20:36 -07002466 * with the ERP.
2467 * - do further defined ERP action or
Horst Hummel138c0142006-06-29 14:58:12 +02002468 * - wait for interrupt or
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469 * - exit with permanent error
2470 *
2471 * PARAMETER
2472 * erp ERP which is in progress with no retry left
2473 *
2474 * RETURN VALUES
2475 * erp modified/additional ERP
2476 */
2477static struct dasd_ccw_req *
2478dasd_3990_erp_further_erp(struct dasd_ccw_req *erp)
2479{
2480
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002481 struct dasd_device *device = erp->startdev;
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002482 char *sense = dasd_get_sense(&erp->irb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002483
2484 /* check for 24 byte sense ERP */
2485 if ((erp->function == dasd_3990_erp_bus_out) ||
2486 (erp->function == dasd_3990_erp_action_1) ||
2487 (erp->function == dasd_3990_erp_action_4)) {
2488
2489 erp = dasd_3990_erp_action_1(erp);
2490
2491 } else if (erp->function == dasd_3990_erp_action_5) {
2492
2493 /* retries have not been successful */
2494 /* prepare erp for retry on different channel path */
2495 erp = dasd_3990_erp_action_1(erp);
2496
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002497 if (sense && !(sense[2] & DASD_SENSE_BIT_0)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002498
Horst Hummel138c0142006-06-29 14:58:12 +02002499 /* issue a Diagnostic Control command with an
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500 * Inhibit Write subcommand */
2501
2502 switch (sense[25]) {
2503 case 0x17:
2504 case 0x57:{ /* controller */
2505 erp = dasd_3990_erp_DCTL(erp, 0x20);
2506 break;
2507 }
2508 case 0x18:
2509 case 0x58:{ /* channel path */
2510 erp = dasd_3990_erp_DCTL(erp, 0x40);
2511 break;
2512 }
2513 case 0x19:
2514 case 0x59:{ /* storage director */
2515 erp = dasd_3990_erp_DCTL(erp, 0x80);
2516 break;
2517 }
2518 default:
2519 DEV_MESSAGE(KERN_DEBUG, device,
2520 "invalid subcommand modifier 0x%x "
2521 "for Diagnostic Control Command",
2522 sense[25]);
2523 }
2524 }
2525
2526 /* check for 32 byte sense ERP */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002527 } else if (sense &&
2528 ((erp->function == dasd_3990_erp_compound_retry) ||
2529 (erp->function == dasd_3990_erp_compound_path) ||
2530 (erp->function == dasd_3990_erp_compound_code) ||
2531 (erp->function == dasd_3990_erp_compound_config))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002532
2533 erp = dasd_3990_erp_compound(erp, sense);
2534
2535 } else {
2536 /* No retry left and no additional special handling */
2537 /*necessary */
2538 DEV_MESSAGE(KERN_ERR, device,
2539 "no retries left for erp %p - "
2540 "set status to FAILED", erp);
2541
2542 erp->status = DASD_CQR_FAILED;
2543 }
2544
2545 return erp;
2546
2547} /* end dasd_3990_erp_further_erp */
2548
2549/*
Horst Hummel138c0142006-06-29 14:58:12 +02002550 * DASD_3990_ERP_HANDLE_MATCH_ERP
Linus Torvalds1da177e2005-04-16 15:20:36 -07002551 *
2552 * DESCRIPTION
2553 * An error occurred again and an ERP has been detected which is already
Horst Hummel138c0142006-06-29 14:58:12 +02002554 * used to handle this error (e.g. retries).
Linus Torvalds1da177e2005-04-16 15:20:36 -07002555 * All prior ERP's are asumed to be successful and therefore removed
2556 * from queue.
Horst Hummel138c0142006-06-29 14:58:12 +02002557 * If retry counter of matching erp is already 0, it is checked if further
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 * action is needed (besides retry) or if the ERP has failed.
2559 *
2560 * PARAMETER
2561 * erp_head first ERP in ERP-chain
2562 * erp ERP that handles the actual error.
2563 * (matching erp)
2564 *
2565 * RETURN VALUES
2566 * erp modified/additional ERP
2567 */
2568static struct dasd_ccw_req *
2569dasd_3990_erp_handle_match_erp(struct dasd_ccw_req *erp_head,
2570 struct dasd_ccw_req *erp)
2571{
2572
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002573 struct dasd_device *device = erp_head->startdev;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574 struct dasd_ccw_req *erp_done = erp_head; /* finished req */
2575 struct dasd_ccw_req *erp_free = NULL; /* req to be freed */
2576
2577 /* loop over successful ERPs and remove them from chanq */
2578 while (erp_done != erp) {
2579
2580 if (erp_done == NULL) /* end of chain reached */
2581 panic(PRINTK_HEADER "Programming error in ERP! The "
2582 "original request was lost\n");
2583
2584 /* remove the request from the device queue */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002585 list_del(&erp_done->blocklist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002586
2587 erp_free = erp_done;
2588 erp_done = erp_done->refers;
2589
2590 /* free the finished erp request */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002591 dasd_free_erp_request(erp_free, erp_free->memdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592
2593 } /* end while */
2594
2595 if (erp->retries > 0) {
2596
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002597 char *sense = dasd_get_sense(&erp->refers->irb);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002598
2599 /* check for special retries */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002600 if (sense && erp->function == dasd_3990_erp_action_4) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601
2602 erp = dasd_3990_erp_action_4(erp, sense);
2603
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002604 } else if (sense &&
2605 erp->function == dasd_3990_erp_action_1B_32) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002606
2607 erp = dasd_3990_update_1B(erp, sense);
2608
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002609 } else if (sense && erp->function == dasd_3990_erp_int_req) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610
2611 erp = dasd_3990_erp_int_req(erp);
2612
2613 } else {
2614 /* simple retry */
2615 DEV_MESSAGE(KERN_DEBUG, device,
2616 "%i retries left for erp %p",
2617 erp->retries, erp);
2618
2619 /* handle the request again... */
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002620 erp->status = DASD_CQR_FILLED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002621 }
2622
2623 } else {
2624 /* no retry left - check for further necessary action */
2625 /* if no further actions, handle rest as permanent error */
2626 erp = dasd_3990_erp_further_erp(erp);
2627 }
2628
2629 return erp;
2630
2631} /* end dasd_3990_erp_handle_match_erp */
2632
2633/*
2634 * DASD_3990_ERP_ACTION
2635 *
2636 * DESCRIPTION
Joe Perches5d67d162008-01-26 14:11:20 +01002637 * control routine for 3990 erp actions.
Linus Torvalds1da177e2005-04-16 15:20:36 -07002638 * Has to be called with the queue lock (namely the s390_irq_lock) acquired.
2639 *
2640 * PARAMETER
2641 * cqr failed cqr (either original cqr or already an erp)
2642 *
2643 * RETURN VALUES
2644 * erp erp-pointer to the head of the ERP action chain.
2645 * This means:
2646 * - either a ptr to an additional ERP cqr or
Horst Hummel138c0142006-06-29 14:58:12 +02002647 * - the original given cqr (which's status might
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 * be modified)
2649 */
2650struct dasd_ccw_req *
2651dasd_3990_erp_action(struct dasd_ccw_req * cqr)
2652{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002653 struct dasd_ccw_req *erp = NULL;
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002654 struct dasd_device *device = cqr->startdev;
Horst Hummel9575bf22006-12-08 15:54:15 +01002655 struct dasd_ccw_req *temp_erp = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002656
Horst Hummel9575bf22006-12-08 15:54:15 +01002657 if (device->features & DASD_FEATURE_ERPLOG) {
2658 /* print current erp_chain */
2659 DEV_MESSAGE(KERN_ERR, device, "%s",
2660 "ERP chain at BEGINNING of ERP-ACTION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002661 for (temp_erp = cqr;
2662 temp_erp != NULL; temp_erp = temp_erp->refers) {
2663
2664 DEV_MESSAGE(KERN_ERR, device,
2665 " erp %p (%02x) refers to %p",
2666 temp_erp, temp_erp->status,
2667 temp_erp->refers);
2668 }
2669 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670
Coly Li73ac36e2009-01-07 18:09:16 -08002671 /* double-check if current erp/cqr was successful */
Stefan Weinhuberf3eb5382009-03-26 15:23:48 +01002672 if ((scsw_cstat(&cqr->irb.scsw) == 0x00) &&
2673 (scsw_dstat(&cqr->irb.scsw) ==
Peter Oberparleiter23d805b2008-07-14 09:58:50 +02002674 (DEV_STAT_CHN_END | DEV_STAT_DEV_END))) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07002675
2676 DEV_MESSAGE(KERN_DEBUG, device,
2677 "ERP called for successful request %p"
2678 " - NO ERP necessary", cqr);
2679
2680 cqr->status = DASD_CQR_DONE;
2681
2682 return cqr;
2683 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002684
2685 /* check if error happened before */
2686 erp = dasd_3990_erp_in_erp(cqr);
2687
2688 if (erp == NULL) {
2689 /* no matching erp found - set up erp */
2690 erp = dasd_3990_erp_additional_erp(cqr);
2691 } else {
2692 /* matching erp found - set all leading erp's to DONE */
2693 erp = dasd_3990_erp_handle_match_erp(cqr, erp);
2694 }
2695
Horst Hummel9575bf22006-12-08 15:54:15 +01002696 if (device->features & DASD_FEATURE_ERPLOG) {
2697 /* print current erp_chain */
2698 DEV_MESSAGE(KERN_ERR, device, "%s",
2699 "ERP chain at END of ERP-ACTION");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 for (temp_erp = erp;
2701 temp_erp != NULL; temp_erp = temp_erp->refers) {
2702
2703 DEV_MESSAGE(KERN_ERR, device,
2704 " erp %p (%02x) refers to %p",
2705 temp_erp, temp_erp->status,
2706 temp_erp->refers);
2707 }
2708 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07002709
Stefan Weinhuber8e09f212008-01-26 14:11:23 +01002710 /* enqueue ERP request if it's a new one */
2711 if (list_empty(&erp->blocklist)) {
2712 cqr->status = DASD_CQR_IN_ERP;
2713 /* add erp request before the cqr */
2714 list_add_tail(&erp->blocklist, &cqr->blocklist);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002715 }
2716
2717 return erp;
2718
2719} /* end dasd_3990_erp_action */