diff options
-rw-r--r-- | drivers/s390/block/dasd.c | 6 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 22 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 2 |
3 files changed, 30 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index eef27a197c0..110137e7ec8 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -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); } diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1b6e7ea9347..70880be2601 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -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 diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index afe8c33422e..33a6743ddc5 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -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; |