[S390] dasd: revalidate server for new pathgroup
authorStefan Haberland <stefan.haberland@de.ibm.com>
Wed, 18 Jan 2012 17:03:41 +0000 (18:03 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Wed, 18 Jan 2012 17:03:42 +0000 (18:03 +0100)
If a pathgroup is established we get an event and have to revalidate
the server to propagate supported features like PAV and enable them.

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 eef27a1..110137e 100644 (file)
@@ -3261,6 +3261,12 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
                        device->path_data.tbvpm |= eventlpm;
                        dasd_schedule_device_bh(device);
                }
+               if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+                       DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+                                     "Pathgroup re-established\n");
+                       if (device->discipline->kick_validate)
+                               device->discipline->kick_validate(device);
+               }
        }
        dasd_put_device(device);
 }
index 1b6e7ea..70880be 100644 (file)
@@ -1550,6 +1550,24 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
                        "returned rc=%d", private->uid.ssid, rc);
 }
 
+/*
+ * worker to do a validate server in case of a lost pathgroup
+ */
+static void dasd_eckd_do_validate_server(struct work_struct *work)
+{
+       struct dasd_device *device = container_of(work, struct dasd_device,
+                                                 kick_validate);
+       dasd_eckd_validate_server(device);
+       dasd_put_device(device);
+}
+
+static void dasd_eckd_kick_validate_server(struct dasd_device *device)
+{
+       dasd_get_device(device);
+       /* queue call to do_validate_server to the kernel event daemon. */
+       schedule_work(&device->kick_validate);
+}
+
 static u32 get_fcx_max_data(struct dasd_device *device)
 {
 #if defined(CONFIG_64BIT)
@@ -1595,6 +1613,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        int readonly;
        unsigned long value;
 
+       /* setup work queue for validate server*/
+       INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server);
+
        if (!ccw_device_is_pathgroup(device->cdev)) {
                dev_warn(&device->cdev->dev,
                         "A channel path group could not be established\n");
@@ -4259,6 +4280,7 @@ static struct dasd_discipline dasd_eckd_discipline = {
        .restore = dasd_eckd_restore_device,
        .reload = dasd_eckd_reload_device,
        .get_uid = dasd_eckd_get_uid,
+       .kick_validate = dasd_eckd_kick_validate_server,
 };
 
 static int __init
index afe8c33..33a6743 100644 (file)
@@ -355,6 +355,7 @@ struct dasd_discipline {
        int (*reload) (struct dasd_device *);
 
        int (*get_uid) (struct dasd_device *, struct dasd_uid *);
+       void (*kick_validate) (struct dasd_device *);
 };
 
 extern struct dasd_discipline *dasd_diag_discipline_pointer;
@@ -455,6 +456,7 @@ struct dasd_device {
        struct work_struct kick_work;
        struct work_struct restore_device;
        struct work_struct reload_device;
+       struct work_struct kick_validate;
        struct timer_list timer;
 
        debug_info_t *debug_area;