aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c32
1 files changed, 32 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));