diff options
-rw-r--r-- | drivers/s390/cio/device.h | 3 | ||||
-rw-r--r-- | drivers/s390/cio/device_ops.c | 61 | ||||
-rw-r--r-- | drivers/s390/cio/device_pgid.c | 66 |
3 files changed, 60 insertions, 70 deletions
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 23c1e19776d8..065b1be98e2c 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -125,9 +125,6 @@ void ccw_device_verify_done(struct ccw_device *, int); void ccw_device_disband_start(struct ccw_device *); void ccw_device_disband_done(struct ccw_device *, int); -void ccw_device_stlck_start(struct ccw_device *, void *, void *, void *); -void ccw_device_stlck_done(struct ccw_device *, void *, int); - int ccw_device_stlck(struct ccw_device *); /* Helper function for machine check handling. */ diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 5be77254547c..a69f702a2fcc 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c @@ -456,67 +456,6 @@ __u8 ccw_device_get_path_mask(struct ccw_device *cdev) return sch->lpm; } -struct stlck_data { - struct completion done; - int rc; -}; - -void ccw_device_stlck_done(struct ccw_device *cdev, void *data, int rc) -{ - struct stlck_data *sdata = data; - - sdata->rc = rc; - complete(&sdata->done); -} - -/* - * Perform unconditional reserve + release. - */ -int ccw_device_stlck(struct ccw_device *cdev) -{ - struct subchannel *sch = to_subchannel(cdev->dev.parent); - struct stlck_data data; - u8 *buffer; - int rc; - - /* Check if steal lock operation is valid for this device. */ - if (cdev->drv) { - if (!cdev->private->options.force) - return -EINVAL; - } - buffer = kzalloc(64, GFP_DMA | GFP_KERNEL); - if (!buffer) - return -ENOMEM; - init_completion(&data.done); - data.rc = -EIO; - spin_lock_irq(sch->lock); - rc = cio_enable_subchannel(sch, (u32) (addr_t) sch); - if (rc) - goto out_unlock; - /* Perform operation. */ - cdev->private->state = DEV_STATE_STEAL_LOCK; - ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]); - spin_unlock_irq(sch->lock); - /* Wait for operation to finish. */ - if (wait_for_completion_interruptible(&data.done)) { - /* Got a signal. */ - spin_lock_irq(sch->lock); - ccw_request_cancel(cdev); - spin_unlock_irq(sch->lock); - wait_for_completion(&data.done); - } - rc = data.rc; - /* Check results. */ - spin_lock_irq(sch->lock); - cio_disable_subchannel(sch); - cdev->private->state = DEV_STATE_BOXED; -out_unlock: - spin_unlock_irq(sch->lock); - kfree(buffer); - - return rc; -} - /** * chp_get_chp_desc - return newly allocated channel-path descriptor * @cdev: device to obtain the descriptor for diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 148b3fadac00..da246b67edfe 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c @@ -9,9 +9,10 @@ #include <linux/kernel.h> #include <linux/string.h> +#include <linux/bitops.h> #include <linux/types.h> #include <linux/errno.h> -#include <linux/bitops.h> +#include <linux/slab.h> #include <asm/ccwdev.h> #include <asm/cio.h> @@ -616,6 +617,11 @@ void ccw_device_disband_start(struct ccw_device *cdev) ccw_request_start(cdev); } +struct stlck_data { + struct completion done; + int rc; +}; + static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2) { struct ccw_request *req = &cdev->private->req; @@ -634,7 +640,10 @@ static void stlck_build_cp(struct ccw_device *cdev, void *buf1, void *buf2) static void stlck_callback(struct ccw_device *cdev, void *data, int rc) { - ccw_device_stlck_done(cdev, data, rc); + struct stlck_data *sdata = data; + + sdata->rc = rc; + complete(&sdata->done); } /** @@ -645,11 +654,9 @@ static void stlck_callback(struct ccw_device *cdev, void *data, int rc) * @buf2: data pointer used in channel program * * Execute a channel program on @cdev to release an existing PGID reservation. - * When finished, call ccw_device_stlck_done with a return code specifying the - * result. */ -void ccw_device_stlck_start(struct ccw_device *cdev, void *data, void *buf1, - void *buf2) +static void ccw_device_stlck_start(struct ccw_device *cdev, void *data, + void *buf1, void *buf2) { struct subchannel *sch = to_subchannel(cdev->dev.parent); struct ccw_request *req = &cdev->private->req; @@ -667,3 +674,50 @@ void ccw_device_stlck_start(struct ccw_device *cdev, void *data, void *buf1, ccw_request_start(cdev); } +/* + * Perform unconditional reserve + release. + */ +int ccw_device_stlck(struct ccw_device *cdev) +{ + struct subchannel *sch = to_subchannel(cdev->dev.parent); + struct stlck_data data; + u8 *buffer; + int rc; + + /* Check if steal lock operation is valid for this device. */ + if (cdev->drv) { + if (!cdev->private->options.force) + return -EINVAL; + } + buffer = kzalloc(64, GFP_DMA | GFP_KERNEL); + if (!buffer) + return -ENOMEM; + init_completion(&data.done); + data.rc = -EIO; + spin_lock_irq(sch->lock); + rc = cio_enable_subchannel(sch, (u32) (addr_t) sch); + if (rc) + goto out_unlock; + /* Perform operation. */ + cdev->private->state = DEV_STATE_STEAL_LOCK; + ccw_device_stlck_start(cdev, &data, &buffer[0], &buffer[32]); + spin_unlock_irq(sch->lock); + /* Wait for operation to finish. */ + if (wait_for_completion_interruptible(&data.done)) { + /* Got a signal. */ + spin_lock_irq(sch->lock); + ccw_request_cancel(cdev); + spin_unlock_irq(sch->lock); + wait_for_completion(&data.done); + } + rc = data.rc; + /* Check results. */ + spin_lock_irq(sch->lock); + cio_disable_subchannel(sch); + cdev->private->state = DEV_STATE_BOXED; +out_unlock: + spin_unlock_irq(sch->lock); + kfree(buffer); + + return rc; +} |