aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/block/dasd.c32
-rw-r--r--drivers/s390/block/dasd_eckd.c1
-rw-r--r--drivers/s390/block/dasd_int.h1
3 files changed, 34 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index f3509120a507..2678a8347729 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -82,6 +82,7 @@ static void dasd_profile_exit(struct dasd_profile *);
82static wait_queue_head_t dasd_init_waitq; 82static wait_queue_head_t dasd_init_waitq;
83static wait_queue_head_t dasd_flush_wq; 83static wait_queue_head_t dasd_flush_wq;
84static wait_queue_head_t generic_waitq; 84static wait_queue_head_t generic_waitq;
85static wait_queue_head_t shutdown_waitq;
85 86
86/* 87/*
87 * Allocate memory for a new device structure. 88 * Allocate memory for a new device structure.
@@ -1994,6 +1995,8 @@ static void dasd_device_tasklet(struct dasd_device *device)
1994 /* Now check if the head of the ccw queue needs to be started. */ 1995 /* Now check if the head of the ccw queue needs to be started. */
1995 __dasd_device_start_head(device); 1996 __dasd_device_start_head(device);
1996 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 1997 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1998 if (waitqueue_active(&shutdown_waitq))
1999 wake_up(&shutdown_waitq);
1997 dasd_put_device(device); 2000 dasd_put_device(device);
1998} 2001}
1999 2002
@@ -2632,6 +2635,8 @@ static void dasd_block_tasklet(struct dasd_block *block)
2632 __dasd_block_start_head(block); 2635 __dasd_block_start_head(block);
2633 spin_unlock(&block->queue_lock); 2636 spin_unlock(&block->queue_lock);
2634 spin_unlock_irq(&block->request_queue_lock); 2637 spin_unlock_irq(&block->request_queue_lock);
2638 if (waitqueue_active(&shutdown_waitq))
2639 wake_up(&shutdown_waitq);
2635 dasd_put_device(block->base); 2640 dasd_put_device(block->base);
2636} 2641}
2637 2642
@@ -3474,6 +3479,32 @@ char *dasd_get_sense(struct irb *irb)
3474} 3479}
3475EXPORT_SYMBOL_GPL(dasd_get_sense); 3480EXPORT_SYMBOL_GPL(dasd_get_sense);
3476 3481
3482static inline int _wait_for_empty_queues(struct dasd_device *device)
3483{
3484 if (device->block)
3485 return list_empty(&device->ccw_queue) &&
3486 list_empty(&device->block->ccw_queue);
3487 else
3488 return list_empty(&device->ccw_queue);
3489}
3490
3491void dasd_generic_shutdown(struct ccw_device *cdev)
3492{
3493 struct dasd_device *device;
3494
3495 device = dasd_device_from_cdev(cdev);
3496 if (IS_ERR(device))
3497 return;
3498
3499 if (device->block)
3500 dasd_schedule_block_bh(device->block);
3501
3502 dasd_schedule_device_bh(device);
3503
3504 wait_event(shutdown_waitq, _wait_for_empty_queues(device));
3505}
3506EXPORT_SYMBOL_GPL(dasd_generic_shutdown);
3507
3477static int __init dasd_init(void) 3508static int __init dasd_init(void)
3478{ 3509{
3479 int rc; 3510 int rc;
@@ -3481,6 +3512,7 @@ static int __init dasd_init(void)
3481 init_waitqueue_head(&dasd_init_waitq); 3512 init_waitqueue_head(&dasd_init_waitq);
3482 init_waitqueue_head(&dasd_flush_wq); 3513 init_waitqueue_head(&dasd_flush_wq);
3483 init_waitqueue_head(&generic_waitq); 3514 init_waitqueue_head(&generic_waitq);
3515 init_waitqueue_head(&shutdown_waitq);
3484 3516
3485 /* register 'common' DASD debug area, used for all DBF_XXX calls */ 3517 /* register 'common' DASD debug area, used for all DBF_XXX calls */
3486 dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long)); 3518 dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long));
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index bc2e8a7c265b..fc0fe30b2ab5 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -4247,6 +4247,7 @@ static struct ccw_driver dasd_eckd_driver = {
4247 .set_online = dasd_eckd_set_online, 4247 .set_online = dasd_eckd_set_online,
4248 .notify = dasd_generic_notify, 4248 .notify = dasd_generic_notify,
4249 .path_event = dasd_generic_path_event, 4249 .path_event = dasd_generic_path_event,
4250 .shutdown = dasd_generic_shutdown,
4250 .freeze = dasd_generic_pm_freeze, 4251 .freeze = dasd_generic_pm_freeze,
4251 .thaw = dasd_generic_restore_device, 4252 .thaw = dasd_generic_restore_device,
4252 .restore = dasd_generic_restore_device, 4253 .restore = dasd_generic_restore_device,
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index c05da00583f0..297ac3b8c8ec 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -686,6 +686,7 @@ int dasd_generic_set_offline (struct ccw_device *cdev);
686int dasd_generic_notify(struct ccw_device *, int); 686int dasd_generic_notify(struct ccw_device *, int);
687int dasd_generic_last_path_gone(struct dasd_device *); 687int dasd_generic_last_path_gone(struct dasd_device *);
688int dasd_generic_path_operational(struct dasd_device *); 688int dasd_generic_path_operational(struct dasd_device *);
689void dasd_generic_shutdown(struct ccw_device *);
689 690
690void dasd_generic_handle_state_change(struct dasd_device *); 691void dasd_generic_handle_state_change(struct dasd_device *);
691int dasd_generic_pm_freeze(struct ccw_device *); 692int dasd_generic_pm_freeze(struct ccw_device *);