Merge branch 'origin'
[pandora-kernel.git] / drivers / s390 / block / dasd_diag.c
index 7478423..3f9d704 100644 (file)
@@ -6,7 +6,6 @@
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
  *
- * $Revision: 1.49 $
  */
 
 #include <linux/config.h>
@@ -25,6 +24,7 @@
 #include <asm/io.h>
 #include <asm/s390_ext.h>
 #include <asm/todclk.h>
+#include <asm/vtoc.h>
 
 #include "dasd_int.h"
 #include "dasd_diag.h"
@@ -67,14 +67,14 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */
 static __inline__ int
 dia250(void *iob, int cmd)
 {
-       typedef struct {
-               char _[max(sizeof (struct dasd_diag_init_io),
-                          sizeof (struct dasd_diag_rw_io))];
+       typedef union {
+               struct dasd_diag_init_io init_io;
+               struct dasd_diag_rw_io rw_io;
        } addr_type;
        int rc;
 
        __asm__ __volatile__(
-#ifdef CONFIG_ARCH_S390X
+#ifdef CONFIG_64BIT
                "       lghi    %0,3\n"
                "       lgr     0,%3\n"
                "       diag    0,%2,0x250\n"
@@ -190,7 +190,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr)
        private->iob.flags = DASD_DIAG_RWFLAG_ASYNC;
        private->iob.block_count = dreq->block_count;
        private->iob.interrupt_params = (addr_t) cqr;
-       private->iob.bio_list = __pa(dreq->bio);
+       private->iob.bio_list = dreq->bio;
        private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
 
        cqr->startclk = get_clock();
@@ -329,7 +329,7 @@ dasd_diag_check_device(struct dasd_device *device)
        struct dasd_diag_private *private;
        struct dasd_diag_characteristics *rdc_data;
        struct dasd_diag_bio bio;
-       struct dasd_diag_cms_label *label;
+       struct vtoc_cms_label *label;
        blocknum_t end_block;
        unsigned int sb, bsize;
        int rc;
@@ -380,7 +380,7 @@ dasd_diag_check_device(struct dasd_device *device)
        mdsk_term_io(device);
 
        /* figure out blocksize of device */
-       label = (struct dasd_diag_cms_label *) get_zeroed_page(GFP_KERNEL);
+       label = (struct vtoc_cms_label *) get_zeroed_page(GFP_KERNEL);
        if (label == NULL)  {
                DEV_MESSAGE(KERN_WARNING, device, "%s",
                            "No memory to allocate initialization request");
@@ -394,47 +394,57 @@ dasd_diag_check_device(struct dasd_device *device)
                memset(&bio, 0, sizeof (struct dasd_diag_bio));
                bio.type = MDSK_READ_REQ;
                bio.block_number = private->pt_block + 1;
-               bio.buffer = __pa(label);
+               bio.buffer = label;
                memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));
                private->iob.dev_nr = rdc_data->dev_nr;
                private->iob.key = 0;
                private->iob.flags = 0; /* do synchronous io */
                private->iob.block_count = 1;
                private->iob.interrupt_params = 0;
-               private->iob.bio_list = __pa(&bio);
+               private->iob.bio_list = &bio;
                private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
                rc = dia250(&private->iob, RW_BIO);
-               if (rc == 0 || rc == 3)
-                       break;
+               if (rc == 3) {
+                       DEV_MESSAGE(KERN_WARNING, device, "%s",
+                               "DIAG call failed");
+                       rc = -EOPNOTSUPP;
+                       goto out;
+               }
                mdsk_term_io(device);
+               if (rc == 0)
+                       break;
        }
-       if (rc == 3) {
-               DEV_MESSAGE(KERN_WARNING, device, "%s", "DIAG call failed");
-               rc = -EOPNOTSUPP;
-       } else if (rc != 0) {
+       if (bsize > PAGE_SIZE) {
                DEV_MESSAGE(KERN_WARNING, device, "device access failed "
                            "(rc=%d)", rc);
                rc = -EIO;
+               goto out;
+       }
+       /* check for label block */
+       if (memcmp(label->label_id, DASD_DIAG_CMS1,
+                 sizeof(DASD_DIAG_CMS1)) == 0) {
+               /* get formatted blocksize from label block */
+               bsize = (unsigned int) label->block_size;
+               device->blocks = (unsigned long) label->block_count;
+       } else
+               device->blocks = end_block;
+       device->bp_block = bsize;
+       device->s2b_shift = 0;  /* bits to shift 512 to get a block */
+       for (sb = 512; sb < bsize; sb = sb << 1)
+               device->s2b_shift++;
+       rc = mdsk_init_io(device, device->bp_block, 0, NULL);
+       if (rc) {
+               DEV_MESSAGE(KERN_WARNING, device, "DIAG initialization "
+                       "failed (rc=%d)", rc);
+               rc = -EIO;
        } else {
-               if (memcmp(label->label_id, DASD_DIAG_CMS1,
-                         sizeof(DASD_DIAG_CMS1)) == 0) {
-                       /* get formatted blocksize from label block */
-                       bsize = (unsigned int) label->block_size;
-                       device->blocks = (unsigned long) label->block_count;
-               } else
-                       device->blocks = end_block;
-               device->bp_block = bsize;
-               device->s2b_shift = 0;  /* bits to shift 512 to get a block */
-               for (sb = 512; sb < bsize; sb = sb << 1)
-                       device->s2b_shift++;
-               
                DEV_MESSAGE(KERN_INFO, device,
                            "(%ld B/blk): %ldkB",
                            (unsigned long) device->bp_block,
                            (unsigned long) (device->blocks <<
                                device->s2b_shift) >> 1);
-               rc = 0;
        }
+out:
        free_page((long) label);
        return rc;
 }
@@ -529,7 +539,7 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
                                memset(dbio, 0, sizeof (struct dasd_diag_bio));
                                dbio->type = rw_cmd;
                                dbio->block_number = recid + 1;
-                               dbio->buffer = __pa(dst);
+                               dbio->buffer = dst;
                                dbio++;
                                dst += blksize;
                                recid++;
@@ -538,6 +548,8 @@ dasd_diag_build_cp(struct dasd_device * device, struct request *req)
        }
        cqr->retries = DIAG_MAX_RETRIES;
        cqr->buildclk = get_clock();
+       if (req->flags & REQ_FAILFAST)
+               set_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags);
        cqr->device = device;
        cqr->expires = DIAG_TIMEOUT;
        cqr->status = DASD_CQR_FILLED;