2 * File...........: linux/drivers/s390/block/dasd_diag.c
3 * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
4 * Based on.......: linux/drivers/s390/block/mdisk.c
5 * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
6 * Bugreports.to..: <Linux390@de.ibm.com>
7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
12 #include <linux/config.h>
13 #include <linux/stddef.h>
14 #include <linux/kernel.h>
15 #include <linux/slab.h>
16 #include <linux/hdreg.h> /* HDIO_GETGEO */
17 #include <linux/bio.h>
18 #include <linux/module.h>
19 #include <linux/init.h>
22 #include <asm/debug.h>
23 #include <asm/ebcdic.h>
25 #include <asm/s390_ext.h>
26 #include <asm/todclk.h>
29 #include "dasd_diag.h"
33 #endif /* PRINTK_HEADER */
34 #define PRINTK_HEADER "dasd(diag):"
36 MODULE_LICENSE("GPL");
38 struct dasd_discipline dasd_diag_discipline
;
40 struct dasd_diag_private
{
41 struct dasd_diag_characteristics rdc_data
;
42 struct dasd_diag_rw_io iob
;
43 struct dasd_diag_init_io iib
;
44 unsigned int pt_block
;
47 struct dasd_diag_req
{
49 struct dasd_diag_bio bio
[0];
53 dia250(void *iob
, int cmd
)
57 __asm__
__volatile__(" lhi %0,3\n"
64 #ifndef CONFIG_ARCH_S390X
65 ".section __ex_table,\"a\"\n"
70 ".section __ex_table,\"a\"\n"
76 : "d" (cmd
), "d" ((void *) __pa(iob
))
82 mdsk_init_io(struct dasd_device
* device
, int blocksize
, int offset
, int size
)
84 struct dasd_diag_private
*private;
85 struct dasd_diag_init_io
*iib
;
88 private = (struct dasd_diag_private
*) device
->private;
90 memset(iib
, 0, sizeof (struct dasd_diag_init_io
));
92 iib
->dev_nr
= _ccw_device_get_device_number(device
->cdev
);
93 iib
->block_size
= blocksize
;
96 iib
->end_block
= size
;
98 rc
= dia250(iib
, INIT_BIO
);
103 static __inline__
int
104 mdsk_term_io(struct dasd_device
* device
)
106 struct dasd_diag_private
*private;
107 struct dasd_diag_init_io
*iib
;
110 private = (struct dasd_diag_private
*) device
->private;
112 memset(iib
, 0, sizeof (struct dasd_diag_init_io
));
113 iib
->dev_nr
= _ccw_device_get_device_number(device
->cdev
);
114 rc
= dia250(iib
, TERM_BIO
);
119 dasd_start_diag(struct dasd_ccw_req
* cqr
)
121 struct dasd_device
*device
;
122 struct dasd_diag_private
*private;
123 struct dasd_diag_req
*dreq
;
126 device
= cqr
->device
;
127 private = (struct dasd_diag_private
*) device
->private;
128 dreq
= (struct dasd_diag_req
*) cqr
->data
;
130 private->iob
.dev_nr
= _ccw_device_get_device_number(device
->cdev
);
131 private->iob
.key
= 0;
132 private->iob
.flags
= 2; /* do asynchronous io */
133 private->iob
.block_count
= dreq
->block_count
;
134 private->iob
.interrupt_params
= (u32
)(addr_t
) cqr
;
135 private->iob
.bio_list
= __pa(dreq
->bio
);
137 cqr
->startclk
= get_clock();
139 rc
= dia250(&private->iob
, RW_BIO
);
141 DEV_MESSAGE(KERN_WARNING
, device
, "dia250 returned CC %d", rc
);
142 cqr
->status
= DASD_CQR_ERROR
;
143 } else if (rc
== 0) {
144 cqr
->status
= DASD_CQR_DONE
;
145 dasd_schedule_bh(device
);
147 cqr
->status
= DASD_CQR_IN_IO
;
154 dasd_ext_handler(struct pt_regs
*regs
, __u16 code
)
156 struct dasd_ccw_req
*cqr
, *next
;
157 struct dasd_device
*device
;
158 unsigned long long expires
;
164 * Get the external interruption subcode. VM stores
165 * this in the 'cpu address' field associated with
166 * the external interrupt. For diag 250 the subcode
169 if ((S390_lowcore
.cpu_addr
& 0xff00) != 0x0300)
171 status
= *((char *) &S390_lowcore
.ext_params
+ 5);
172 ip
= S390_lowcore
.ext_params
;
174 if (!ip
) { /* no intparm: unsolicited interrupt */
175 MESSAGE(KERN_DEBUG
, "%s", "caught unsolicited interrupt");
178 cqr
= (struct dasd_ccw_req
*)(addr_t
) ip
;
179 device
= (struct dasd_device
*) cqr
->device
;
180 if (strncmp(device
->discipline
->ebcname
, (char *) &cqr
->magic
, 4)) {
181 DEV_MESSAGE(KERN_WARNING
, device
,
182 " magic number of dasd_ccw_req 0x%08X doesn't"
183 " match discipline 0x%08X",
184 cqr
->magic
, *(int *) (&device
->discipline
->name
));
188 /* get irq lock to modify request queue */
189 spin_lock_irqsave(get_ccwdev_lock(device
->cdev
), flags
);
191 cqr
->stopclk
= get_clock();
195 cqr
->status
= DASD_CQR_DONE
;
196 /* Start first request on queue if possible -> fast_io. */
197 if (!list_empty(&device
->ccw_queue
)) {
198 next
= list_entry(device
->ccw_queue
.next
,
199 struct dasd_ccw_req
, list
);
200 if (next
->status
== DASD_CQR_QUEUED
) {
201 if (dasd_start_diag(next
) == 0)
202 expires
= next
->expires
;
204 DEV_MESSAGE(KERN_WARNING
, device
, "%s",
205 "Interrupt fastpath "
210 cqr
->status
= DASD_CQR_FAILED
;
213 dasd_set_timer(device
, expires
);
215 dasd_clear_timer(device
);
216 dasd_schedule_bh(device
);
218 spin_unlock_irqrestore(get_ccwdev_lock(device
->cdev
), flags
);
222 dasd_diag_check_device(struct dasd_device
*device
)
224 struct dasd_diag_private
*private;
225 struct dasd_diag_characteristics
*rdc_data
;
226 struct dasd_diag_bio bio
;
231 private = (struct dasd_diag_private
*) device
->private;
232 if (private == NULL
) {
233 private = kmalloc(sizeof(struct dasd_diag_private
),GFP_KERNEL
);
234 if (private == NULL
) {
235 DEV_MESSAGE(KERN_WARNING
, device
, "%s",
236 "memory allocation failed for private data");
239 device
->private = (void *) private;
241 /* Read Device Characteristics */
242 rdc_data
= (void *) &(private->rdc_data
);
243 rdc_data
->dev_nr
= _ccw_device_get_device_number(device
->cdev
);
244 rdc_data
->rdc_len
= sizeof (struct dasd_diag_characteristics
);
246 rc
= diag210((struct diag210
*) rdc_data
);
250 /* Figure out position of label block */
251 switch (private->rdc_data
.vdev_class
) {
253 private->pt_block
= 1;
256 private->pt_block
= 2;
262 DBF_DEV_EVENT(DBF_INFO
, device
,
263 "%04X: %04X on real %04X/%02X",
266 rdc_data
->rdev_type
, rdc_data
->rdev_model
);
268 /* terminate all outstanding operations */
269 mdsk_term_io(device
);
271 /* figure out blocksize of device */
272 label
= (long *) get_zeroed_page(GFP_KERNEL
);
274 DEV_MESSAGE(KERN_WARNING
, device
, "%s",
275 "No memory to allocate initialization request");
278 /* try all sizes - needed for ECKD devices */
279 for (bsize
= 512; bsize
<= PAGE_SIZE
; bsize
<<= 1) {
280 mdsk_init_io(device
, bsize
, 0, 64);
281 memset(&bio
, 0, sizeof (struct dasd_diag_bio
));
282 bio
.type
= MDSK_READ_REQ
;
283 bio
.block_number
= private->pt_block
+ 1;
284 bio
.buffer
= __pa(label
);
285 memset(&private->iob
, 0, sizeof (struct dasd_diag_rw_io
));
286 private->iob
.dev_nr
= rdc_data
->dev_nr
;
287 private->iob
.key
= 0;
288 private->iob
.flags
= 0; /* do synchronous io */
289 private->iob
.block_count
= 1;
290 private->iob
.interrupt_params
= 0;
291 private->iob
.bio_list
= __pa(&bio
);
292 if (dia250(&private->iob
, RW_BIO
) == 0)
294 mdsk_term_io(device
);
296 if (bsize
<= PAGE_SIZE
&& label
[0] == 0xc3d4e2f1) {
297 /* get formatted blocksize from label block */
298 bsize
= (int) label
[3];
299 device
->blocks
= label
[7];
300 device
->bp_block
= bsize
;
301 device
->s2b_shift
= 0; /* bits to shift 512 to get a block */
302 for (sb
= 512; sb
< bsize
; sb
= sb
<< 1)
305 DEV_MESSAGE(KERN_INFO
, device
,
306 "capacity (%dkB blks): %ldkB",
307 (device
->bp_block
>> 10),
308 (device
->blocks
<< device
->s2b_shift
) >> 1);
311 if (bsize
> PAGE_SIZE
)
312 DEV_MESSAGE(KERN_WARNING
, device
, "%s",
313 "DIAG access failed");
315 DEV_MESSAGE(KERN_WARNING
, device
, "%s",
316 "volume is not CMS formatted");
319 free_page((long) label
);
324 dasd_diag_fill_geometry(struct dasd_device
*device
, struct hd_geometry
*geo
)
326 if (dasd_check_blocksize(device
->bp_block
) != 0)
328 geo
->cylinders
= (device
->blocks
<< device
->s2b_shift
) >> 10;
330 geo
->sectors
= 128 >> device
->s2b_shift
;
335 dasd_diag_examine_error(struct dasd_ccw_req
* cqr
, struct irb
* stat
)
337 return dasd_era_fatal
;
341 dasd_diag_erp_action(struct dasd_ccw_req
* cqr
)
343 return dasd_default_erp_action
;
347 dasd_diag_erp_postaction(struct dasd_ccw_req
* cqr
)
349 return dasd_default_erp_postaction
;
352 static struct dasd_ccw_req
*
353 dasd_diag_build_cp(struct dasd_device
* device
, struct request
*req
)
355 struct dasd_ccw_req
*cqr
;
356 struct dasd_diag_req
*dreq
;
357 struct dasd_diag_bio
*dbio
;
362 sector_t recid
, first_rec
, last_rec
;
363 unsigned blksize
, off
;
364 unsigned char rw_cmd
;
367 if (rq_data_dir(req
) == READ
)
368 rw_cmd
= MDSK_READ_REQ
;
369 else if (rq_data_dir(req
) == WRITE
)
370 rw_cmd
= MDSK_WRITE_REQ
;
372 return ERR_PTR(-EINVAL
);
373 blksize
= device
->bp_block
;
374 /* Calculate record id of first and last block. */
375 first_rec
= req
->sector
>> device
->s2b_shift
;
376 last_rec
= (req
->sector
+ req
->nr_sectors
- 1) >> device
->s2b_shift
;
377 /* Check struct bio and count the number of blocks for the request. */
379 rq_for_each_bio(bio
, req
) {
380 bio_for_each_segment(bv
, bio
, i
) {
381 if (bv
->bv_len
& (blksize
- 1))
382 /* Fba can only do full blocks. */
383 return ERR_PTR(-EINVAL
);
384 count
+= bv
->bv_len
>> (device
->s2b_shift
+ 9);
388 if (count
!= last_rec
- first_rec
+ 1)
389 return ERR_PTR(-EINVAL
);
390 /* Build the request */
391 datasize
= sizeof(struct dasd_diag_req
) +
392 count
*sizeof(struct dasd_diag_bio
);
393 cqr
= dasd_smalloc_request(dasd_diag_discipline
.name
, 0,
398 dreq
= (struct dasd_diag_req
*) cqr
->data
;
399 dreq
->block_count
= count
;
402 rq_for_each_bio(bio
, req
) {
403 bio_for_each_segment(bv
, bio
, i
) {
404 dst
= page_address(bv
->bv_page
) + bv
->bv_offset
;
405 for (off
= 0; off
< bv
->bv_len
; off
+= blksize
) {
406 memset(dbio
, 0, sizeof (struct dasd_diag_bio
));
408 dbio
->block_number
= recid
+ 1;
409 dbio
->buffer
= __pa(dst
);
416 cqr
->buildclk
= get_clock();
417 cqr
->device
= device
;
418 cqr
->expires
= 50 * HZ
; /* 50 seconds */
419 cqr
->status
= DASD_CQR_FILLED
;
424 dasd_diag_free_cp(struct dasd_ccw_req
*cqr
, struct request
*req
)
428 status
= cqr
->status
== DASD_CQR_DONE
;
429 dasd_sfree_request(cqr
, cqr
->device
);
434 dasd_diag_fill_info(struct dasd_device
* device
,
435 struct dasd_information2_t
* info
)
437 struct dasd_diag_private
*private;
439 private = (struct dasd_diag_private
*) device
->private;
440 info
->label_block
= private->pt_block
;
441 info
->FBA_layout
= 1;
442 info
->format
= DASD_FORMAT_LDL
;
443 info
->characteristics_size
= sizeof (struct dasd_diag_characteristics
);
444 memcpy(info
->characteristics
,
445 &((struct dasd_diag_private
*) device
->private)->rdc_data
,
446 sizeof (struct dasd_diag_characteristics
));
447 info
->confdata_size
= 0;
452 dasd_diag_dump_sense(struct dasd_device
*device
, struct dasd_ccw_req
* req
,
455 DEV_MESSAGE(KERN_ERR
, device
, "%s",
456 "dump sense not available for DIAG data");
460 * max_blocks is dependent on the amount of storage that is available
461 * in the static io buffer for each device. Currently each device has
462 * 8192 bytes (=2 pages). dasd diag is only relevant for 31 bit.
463 * The struct dasd_ccw_req has 96 bytes, the struct dasd_diag_req has
464 * 8 bytes and the struct dasd_diag_bio for each block has 16 bytes.
466 * (8192 - 96 - 8) / 16 = 505.5 blocks at maximum.
467 * We want to fit two into the available memory so that we can immediately
468 * start the next request if one finishes off. That makes 252.75 blocks
469 * for one request. Give a little safety and the result is 240.
471 struct dasd_discipline dasd_diag_discipline
= {
472 .owner
= THIS_MODULE
,
476 .check_device
= dasd_diag_check_device
,
477 .fill_geometry
= dasd_diag_fill_geometry
,
478 .start_IO
= dasd_start_diag
,
479 .examine_error
= dasd_diag_examine_error
,
480 .erp_action
= dasd_diag_erp_action
,
481 .erp_postaction
= dasd_diag_erp_postaction
,
482 .build_cp
= dasd_diag_build_cp
,
483 .free_cp
= dasd_diag_free_cp
,
484 .dump_sense
= dasd_diag_dump_sense
,
485 .fill_info
= dasd_diag_fill_info
,
491 if (!MACHINE_IS_VM
) {
492 MESSAGE_LOG(KERN_INFO
,
493 "Machine is not VM: %s "
494 "discipline not initializing",
495 dasd_diag_discipline
.name
);
498 ASCEBC(dasd_diag_discipline
.ebcname
, 4);
501 register_external_interrupt(0x2603, dasd_ext_handler
);
502 dasd_diag_discipline_pointer
= &dasd_diag_discipline
;
507 dasd_diag_cleanup(void)
509 if (!MACHINE_IS_VM
) {
510 MESSAGE_LOG(KERN_INFO
,
511 "Machine is not VM: %s "
512 "discipline not cleaned",
513 dasd_diag_discipline
.name
);
516 unregister_external_interrupt(0x2603, dasd_ext_handler
);
518 dasd_diag_discipline_pointer
= NULL
;
521 module_init(dasd_diag_init
);
522 module_exit(dasd_diag_cleanup
);
525 * Overrides for Emacs so that we follow Linus's tabbing style.
526 * Emacs will notice this stuff at the end of the file and automatically
527 * adjust the settings for this buffer only. This must remain at the end
529 * ---------------------------------------------------------------------------
532 * c-brace-imaginary-offset: 0
534 * c-argdecl-indent: 4
536 * c-continued-statement-offset: 4
537 * c-continued-brace-offset: 0
538 * indent-tabs-mode: 1