From 6fca97a958bc3c67566aa91eafc6a5be2e66d6b3 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Tue, 6 Oct 2009 10:34:15 +0200 Subject: [S390] dasd: fix race condition in resume code There is a race while re-reading the device characteristics. After cleaning the memory area a cqr is build which reads the device characteristics. This may take a rather long time and the device characteristics structure is zero during this. Now it could be possible that the block tasklet starts working and a new cqr will be build. The build_cp command refers to the device characteristics structure and this may lead into a divide by zero exception. Fix this by re-reading the device characteristics into a temporary structur and copy the data to the original structure. Also take the ccwdev_lock. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/s390/block/dasd.c') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index dad0449475b6..53b8c255360a 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2508,8 +2508,6 @@ int dasd_generic_restore_device(struct ccw_device *cdev) device->stopped &= ~DASD_UNRESUMED_PM; dasd_schedule_device_bh(device); - if (device->block) - dasd_schedule_block_bh(device->block); if (device->discipline->restore) rc = device->discipline->restore(device); @@ -2520,6 +2518,9 @@ int dasd_generic_restore_device(struct ccw_device *cdev) */ device->stopped |= DASD_UNRESUMED_PM; + if (device->block) + dasd_schedule_block_bh(device->block); + dasd_put_device(device); return 0; } -- cgit v1.2.2 From d9fa9441ed6e0467d7d41de730581874c997e658 Mon Sep 17 00:00:00 2001 From: Stefan Haberland Date: Wed, 14 Oct 2009 12:43:48 +0200 Subject: [S390] dasd: use idal for device characteristics If the rdc_buffer is above 2G we need indirect addresssing so we have to use an idaw to give the rdc_buffer to the ccw. If the rdc_buffer is under 2G nothing changes. Signed-off-by: Stefan Haberland Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/s390/block/dasd.c') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 53b8c255360a..aaccc8ecfa8f 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2533,6 +2533,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, { struct dasd_ccw_req *cqr; struct ccw1 *ccw; + unsigned long *idaw; cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device); @@ -2546,9 +2547,17 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, ccw = cqr->cpaddr; ccw->cmd_code = CCW_CMD_RDC; - ccw->cda = (__u32)(addr_t)rdc_buffer; - ccw->count = rdc_buffer_size; + if (idal_is_needed(rdc_buffer, rdc_buffer_size)) { + idaw = (unsigned long *) (cqr->data); + ccw->cda = (__u32)(addr_t) idaw; + ccw->flags = CCW_FLAG_IDA; + idaw = idal_create_words(idaw, rdc_buffer, rdc_buffer_size); + } else { + ccw->cda = (__u32)(addr_t) rdc_buffer; + ccw->flags = 0; + } + ccw->count = rdc_buffer_size; cqr->startdev = device; cqr->memdev = device; cqr->expires = 10*HZ; -- cgit v1.2.2