aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd_diag.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd_diag.c')
-rw-r--r--drivers/s390/block/dasd_diag.c64
1 files changed, 37 insertions, 27 deletions
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 7478423b53bb..ab8754e566bc 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -6,7 +6,7 @@
6 * Bugreports.to..: <Linux390@de.ibm.com> 6 * Bugreports.to..: <Linux390@de.ibm.com>
7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 7 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
8 * 8 *
9 * $Revision: 1.49 $ 9 * $Revision: 1.51 $
10 */ 10 */
11 11
12#include <linux/config.h> 12#include <linux/config.h>
@@ -67,9 +67,9 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
67static __inline__ int 67static __inline__ int
68dia250(void *iob, int cmd) 68dia250(void *iob, int cmd)
69{ 69{
70 typedef struct { 70 typedef union {
71 char _[max(sizeof (struct dasd_diag_init_io), 71 struct dasd_diag_init_io init_io;
72 sizeof (struct dasd_diag_rw_io))]; 72 struct dasd_diag_rw_io rw_io;
73 } addr_type; 73 } addr_type;
74 int rc; 74 int rc;
75 75
@@ -190,7 +190,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
190 private->iob.flags = DASD_DIAG_RWFLAG_ASYNC; 190 private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
191 private->iob.block_count = dreq->block_count; 191 private->iob.block_count = dreq->block_count;
192 private->iob.interrupt_params = (addr_t) cqr; 192 private->iob.interrupt_params = (addr_t) cqr;
193 private->iob.bio_list = __pa(dreq->bio); 193 private->iob.bio_list = dreq->bio;
194 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; 194 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
195 195
196 cqr->startclk = get_clock(); 196 cqr->startclk = get_clock();
@@ -394,47 +394,57 @@ dasd_diag_check_device(struct dasd_device *device)
394 memset(&bio, 0, sizeof (struct dasd_diag_bio)); 394 memset(&bio, 0, sizeof (struct dasd_diag_bio));
395 bio.type = MDSK_READ_REQ; 395 bio.type = MDSK_READ_REQ;
396 bio.block_number = private->pt_block + 1; 396 bio.block_number = private->pt_block + 1;
397 bio.buffer = __pa(label); 397 bio.buffer = label;
398 memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io)); 398 memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));
399 private->iob.dev_nr = rdc_data->dev_nr; 399 private->iob.dev_nr = rdc_data->dev_nr;
400 private->iob.key = 0; 400 private->iob.key = 0;
401 private->iob.flags = 0; /* do synchronous io */ 401 private->iob.flags = 0; /* do synchronous io */
402 private->iob.block_count = 1; 402 private->iob.block_count = 1;
403 private->iob.interrupt_params = 0; 403 private->iob.interrupt_params = 0;
404 private->iob.bio_list = __pa(&bio); 404 private->iob.bio_list = &bio;
405 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; 405 private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
406 rc = dia250(&private->iob, RW_BIO); 406 rc = dia250(&private->iob, RW_BIO);
407 if (rc == 0 || rc == 3) 407 if (rc == 3) {
408 break; 408 DEV_MESSAGE(KERN_WARNING, device, "%s",
409 "DIAG call failed");
410 rc = -EOPNOTSUPP;
411 goto out;
412 }
409 mdsk_term_io(device); 413 mdsk_term_io(device);
414 if (rc == 0)
415 break;
410 } 416 }
411 if (rc == 3) { 417 if (bsize > PAGE_SIZE) {
412 DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed");
413 rc = -EOPNOTSUPP;
414 } else if (rc != 0) {
415 DEV_MESSAGE(KERN_WARNING, device, "device access failed " 418 DEV_MESSAGE(KERN_WARNING, device, "device access failed "
416 "(rc=%d)", rc); 419 "(rc=%d)", rc);
417 rc = -EIO; 420 rc = -EIO;
421 goto out;
422 }
423 /* check for label block */
424 if (memcmp(label->label_id, DASD_DIAG_CMS1,
425 sizeof(DASD_DIAG_CMS1)) == 0) {
426 /* get formatted blocksize from label block */
427 bsize = (unsigned int) label->block_size;
428 device->blocks = (unsigned long) label->block_count;
429 } else
430 device->blocks = end_block;
431 device->bp_block = bsize;
432 device->s2b_shift = 0; /* bits to shift 512 to get a block */
433 for (sb = 512; sb < bsize; sb = sb << 1)
434 device->s2b_shift++;
435 rc = mdsk_init_io(device, device->bp_block, 0, NULL);
436 if (rc) {
437 DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization "
438 "failed (rc=%d)", rc);
439 rc = -EIO;
418 } else { 440 } else {
419 if (memcmp(label->label_id, DASD_DIAG_CMS1,
420 sizeof(DASD_DIAG_CMS1)) == 0) {
421 /* get formatted blocksize from label block */
422 bsize = (unsigned int) label->block_size;
423 device->blocks = (unsigned long) label->block_count;
424 } else
425 device->blocks = end_block;
426 device->bp_block = bsize;
427 device->s2b_shift = 0; /* bits to shift 512 to get a block */
428 for (sb = 512; sb < bsize; sb = sb << 1)
429 device->s2b_shift++;
430
431 DEV_MESSAGE(KERN_INFO, device, 441 DEV_MESSAGE(KERN_INFO, device,
432 "(%ld B/blk): %ldkB", 442 "(%ld B/blk): %ldkB",
433 (unsigned long) device->bp_block, 443 (unsigned long) device->bp_block,
434 (unsigned long) (device->blocks << 444 (unsigned long) (device->blocks <<
435 device->s2b_shift) >> 1); 445 device->s2b_shift) >> 1);
436 rc = 0;
437 } 446 }
447out:
438 free_page((long) label); 448 free_page((long) label);
439 return rc; 449 return rc;
440} 450}
@@ -529,7 +539,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
529 memset(dbio, 0, sizeof (struct dasd_diag_bio)); 539 memset(dbio, 0, sizeof (struct dasd_diag_bio));
530 dbio->type = rw_cmd; 540 dbio->type = rw_cmd;
531 dbio->block_number = recid + 1; 541 dbio->block_number = recid + 1;
532 dbio->buffer = __pa(dst); 542 dbio->buffer = dst;
533 dbio++; 543 dbio++;
534 dst += blksize; 544 dst += blksize;
535 recid++; 545 recid++;