summaryrefslogtreecommitdiff
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 20:49:09 +0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-07-24 20:49:09 +0400
commite017507f37d5cb8b541df165a824958bc333bec3 (patch)
tree87ab0986474486623d9957efda9f3f9ea3b14069 /drivers/s390/block/dasd.c
parent759e2a253aaefbb6da9253d517a5a8fe1801ce0f (diff)
parent27f6b416626a240e1b46f646d2e0c5266f4eac95 (diff)
downloadlinux-e017507f37d5cb8b541df165a824958bc333bec3.tar.xz
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 changes from Martin Schwidefsky: "No new functions, a few changes to make the code more robust, some cleanups and bug fixes." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (21 commits) s390/vtimer: rework virtual timer interface s390/dis: Add the servc instruction to the disassembler. s390/comments: unify copyright messages and remove file names s390/lgr: Add init check to lgr_info_log() s390/cpu init: use __get_cpu_var instead of per_cpu s390/idle: reduce size of s390_idle_data structure s390/idle: fix sequence handling vs cpu hotplug s390/ap: resend enable adapter interrupt request. s390/hypfs: Add missing get_next_ino() s390/dasd: add shutdown action s390/ipl: Fix ipib handling for "dumpreipl" shutdown action s390/smp: make absolute lowcore / cpu restart parameter accesses more robust s390/vmlogrdr: cleanup driver attribute usage s390/vmlogrdr: cleanup device attribute usage s390/ccwgroup: remove unused ccwgroup_device member s390/cio/chp: cleanup attribute usage s390/sigp: use sigp order code defines in assembly code s390/smp: use sigp cpu status definitions s390/smp/kvm: unifiy sigp definitions s390/smp: remove redundant check ...
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index f3509120a507..15370a2c5ff0 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1,5 +1,4 @@
/*
- * File...........: linux/drivers/s390/block/dasd.c
* Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
* Horst Hummel <Horst.Hummel@de.ibm.com>
* Carsten Otte <Cotte@de.ibm.com>
@@ -52,7 +51,7 @@ void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
- " Copyright 2000 IBM Corporation");
+ " Copyright IBM Corp. 2000");
MODULE_SUPPORTED_DEVICE("dasd");
MODULE_LICENSE("GPL");
@@ -82,6 +81,7 @@ static void dasd_profile_exit(struct dasd_profile *);
static wait_queue_head_t dasd_init_waitq;
static wait_queue_head_t dasd_flush_wq;
static wait_queue_head_t generic_waitq;
+static wait_queue_head_t shutdown_waitq;
/*
* Allocate memory for a new device structure.
@@ -1994,6 +1994,8 @@ static void dasd_device_tasklet(struct dasd_device *device)
/* Now check if the head of the ccw queue needs to be started. */
__dasd_device_start_head(device);
spin_unlock_irq(get_ccwdev_lock(device->cdev));
+ if (waitqueue_active(&shutdown_waitq))
+ wake_up(&shutdown_waitq);
dasd_put_device(device);
}
@@ -2632,6 +2634,8 @@ static void dasd_block_tasklet(struct dasd_block *block)
__dasd_block_start_head(block);
spin_unlock(&block->queue_lock);
spin_unlock_irq(&block->request_queue_lock);
+ if (waitqueue_active(&shutdown_waitq))
+ wake_up(&shutdown_waitq);
dasd_put_device(block->base);
}
@@ -3474,6 +3478,32 @@ char *dasd_get_sense(struct irb *irb)
}
EXPORT_SYMBOL_GPL(dasd_get_sense);
+static inline int _wait_for_empty_queues(struct dasd_device *device)
+{
+ if (device->block)
+ return list_empty(&device->ccw_queue) &&
+ list_empty(&device->block->ccw_queue);
+ else
+ return list_empty(&device->ccw_queue);
+}
+
+void dasd_generic_shutdown(struct ccw_device *cdev)
+{
+ struct dasd_device *device;
+
+ device = dasd_device_from_cdev(cdev);
+ if (IS_ERR(device))
+ return;
+
+ if (device->block)
+ dasd_schedule_block_bh(device->block);
+
+ dasd_schedule_device_bh(device);
+
+ wait_event(shutdown_waitq, _wait_for_empty_queues(device));
+}
+EXPORT_SYMBOL_GPL(dasd_generic_shutdown);
+
static int __init dasd_init(void)
{
int rc;
@@ -3481,6 +3511,7 @@ static int __init dasd_init(void)
init_waitqueue_head(&dasd_init_waitq);
init_waitqueue_head(&dasd_flush_wq);
init_waitqueue_head(&generic_waitq);
+ init_waitqueue_head(&shutdown_waitq);
/* register 'common' DASD debug area, used for all DBF_XXX calls */
dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long));