[S390] dasd: re-initialize read_conf buffer for retries
Stefan Haberland [Sun, 30 Oct 2011 14:16:57 +0000 (15:16 +0100)]
The buffer for read configuration data has to be initialized with an
EBCDIC string to show support for extended UIDs to z/VM.
If this read configuration data CQR needs to be retried, the buffer
may have changed in between. So re-initialize the buffer to get a
correct extended UID under z/VM.

Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>

drivers/s390/block/dasd.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_int.h

index 3b94b65..ce2a780 100644 (file)
@@ -2059,13 +2059,14 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr)
 /*
  * Wakeup helper for the 'sleep_on' functions.
  */
-static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
+void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data)
 {
        spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev));
        cqr->callback_data = DASD_SLEEPON_END_TAG;
        spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev));
        wake_up(&generic_waitq);
 }
+EXPORT_SYMBOL_GPL(dasd_wakeup_cb);
 
 static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
 {
@@ -2165,7 +2166,9 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
                } else
                        wait_event(generic_waitq, !(device->stopped));
 
-               cqr->callback = dasd_wakeup_cb;
+               if (!cqr->callback)
+                       cqr->callback = dasd_wakeup_cb;
+
                cqr->callback_data = DASD_SLEEPON_START_TAG;
                dasd_add_request_tail(cqr);
                if (interruptible) {
index 0e9c4dc..cb1bbc2 100644 (file)
@@ -844,6 +844,30 @@ static void dasd_eckd_fill_rcd_cqr(struct dasd_device *device,
        set_bit(DASD_CQR_VERIFY_PATH, &cqr->flags);
 }
 
+/*
+ * Wakeup helper for read_conf
+ * if the cqr is not done and needs some error recovery
+ * the buffer has to be re-initialized with the EBCDIC "V1.0"
+ * to show support for virtual device SNEQ
+ */
+static void read_conf_cb(struct dasd_ccw_req *cqr, void *data)
+{
+       struct ccw1 *ccw;
+       __u8 *rcd_buffer;
+
+       if (cqr->status !=  DASD_CQR_DONE) {
+               ccw = cqr->cpaddr;
+               rcd_buffer = (__u8 *)((addr_t) ccw->cda);
+               memset(rcd_buffer, 0, sizeof(*rcd_buffer));
+
+               rcd_buffer[0] = 0xE5;
+               rcd_buffer[1] = 0xF1;
+               rcd_buffer[2] = 0x4B;
+               rcd_buffer[3] = 0xF0;
+       }
+       dasd_wakeup_cb(cqr, data);
+}
+
 static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
                                           struct dasd_ccw_req *cqr,
                                           __u8 *rcd_buffer,
@@ -863,6 +887,7 @@ static int dasd_eckd_read_conf_immediately(struct dasd_device *device,
        clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags);
        set_bit(DASD_CQR_ALLOW_SLOCK, &cqr->flags);
        cqr->retries = 5;
+       cqr->callback = read_conf_cb;
        rc = dasd_sleep_on_immediatly(cqr);
        return rc;
 }
@@ -900,6 +925,7 @@ static int dasd_eckd_read_conf_lpm(struct dasd_device *device,
                goto out_error;
        }
        dasd_eckd_fill_rcd_cqr(device, cqr, rcd_buf, lpm);
+       cqr->callback = read_conf_cb;
        ret = dasd_sleep_on(cqr);
        /*
         * on success we update the user input parms
index 1dd12bd..563bf8a 100644 (file)
@@ -643,6 +643,7 @@ struct dasd_ccw_req *
 dasd_smalloc_request(int , int, int, struct dasd_device *);
 void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *);
 void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *);
+void dasd_wakeup_cb(struct dasd_ccw_req *, void *);
 
 static inline int
 dasd_kmalloc_set_cda(struct ccw1 *ccw, void *cda, struct dasd_device *device)