diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-09-20 09:59:05 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-09-20 09:59:05 -0400 |
commit | a00bfd7147c0c5c04a59f7adcb0e6d8948b90a6e (patch) | |
tree | ffe3eb5ede49bf5a14fe31f3270d917fc4bc9c7a /drivers/s390/block/dasd.c | |
parent | 47addc84b450fd5e391ab118e178645cb0bbd89d (diff) |
[S390] dasd deadlock after state change pending interrupt.
The dasd_device_from_cdev function is called from interrupt context
to get the struct dasd_device associated with a ccw device. The
driver_data of the ccw device points to the dasd_devmap structure
which contains the pointer to the dasd_device structure. The lock
that protects the dasd_devmap structure is acquire with out irqsave.
To prevent the deadlock in dasd_device_from_cdev if it is called
from interrupt context the dependency to the dasd_devmap structure
needs to be removed. Let the driver_data of the ccw device point
to the dasd_device structure directly and use the ccw device lock
to protect the access.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r-- | drivers/s390/block/dasd.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 25c1ef6dfd44..3cd87f85f702 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -893,7 +893,7 @@ dasd_handle_killed_request(struct ccw_device *cdev, unsigned long intparm) | |||
893 | 893 | ||
894 | device = (struct dasd_device *) cqr->device; | 894 | device = (struct dasd_device *) cqr->device; |
895 | if (device == NULL || | 895 | if (device == NULL || |
896 | device != dasd_device_from_cdev(cdev) || | 896 | device != dasd_device_from_cdev_locked(cdev) || |
897 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { | 897 | strncmp(device->discipline->ebcname, (char *) &cqr->magic, 4)) { |
898 | MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", | 898 | MESSAGE(KERN_DEBUG, "invalid device in request: bus_id %s", |
899 | cdev->dev.bus_id); | 899 | cdev->dev.bus_id); |
@@ -970,7 +970,7 @@ dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
970 | /* first of all check for state change pending interrupt */ | 970 | /* first of all check for state change pending interrupt */ |
971 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; | 971 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; |
972 | if ((irb->scsw.dstat & mask) == mask) { | 972 | if ((irb->scsw.dstat & mask) == mask) { |
973 | device = dasd_device_from_cdev(cdev); | 973 | device = dasd_device_from_cdev_locked(cdev); |
974 | if (!IS_ERR(device)) { | 974 | if (!IS_ERR(device)) { |
975 | dasd_handle_state_change_pending(device); | 975 | dasd_handle_state_change_pending(device); |
976 | dasd_put_device(device); | 976 | dasd_put_device(device); |