Commit 60f3eac3 authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky

s390/cmf: simplify cmb_copy_wait

No need for refcounting - the data can be on stack. Also change
the locking in this function to only use spin_lock_irq (the
function waits, thus it's never called from IRQ context).
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: default avatarPeter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent eeec1e43
...@@ -319,83 +319,57 @@ static int cmf_copy_block(struct ccw_device *cdev) ...@@ -319,83 +319,57 @@ static int cmf_copy_block(struct ccw_device *cdev)
struct copy_block_struct { struct copy_block_struct {
wait_queue_head_t wait; wait_queue_head_t wait;
int ret; int ret;
struct kref kref;
}; };
static void cmf_copy_block_release(struct kref *kref)
{
struct copy_block_struct *copy_block;
copy_block = container_of(kref, struct copy_block_struct, kref);
kfree(copy_block);
}
static int cmf_cmb_copy_wait(struct ccw_device *cdev) static int cmf_cmb_copy_wait(struct ccw_device *cdev)
{ {
struct copy_block_struct *copy_block; struct copy_block_struct copy_block;
int ret; int ret = -ENODEV;
unsigned long flags;
spin_lock_irqsave(cdev->ccwlock, flags); spin_lock_irq(cdev->ccwlock);
if (!cdev->private->cmb) { if (!cdev->private->cmb)
ret = -ENODEV;
goto out;
}
copy_block = kzalloc(sizeof(struct copy_block_struct), GFP_ATOMIC);
if (!copy_block) {
ret = -ENOMEM;
goto out; goto out;
}
init_waitqueue_head(&copy_block->wait);
kref_init(&copy_block->kref);
ret = cmf_copy_block(cdev); ret = cmf_copy_block(cdev);
if (ret != -EBUSY) if (ret != -EBUSY)
goto out_put; goto out;
if (cdev->private->state != DEV_STATE_ONLINE) { if (cdev->private->state != DEV_STATE_ONLINE)
ret = -EBUSY; goto out;
goto out_put;
} init_waitqueue_head(&copy_block.wait);
copy_block.ret = CMF_PENDING;
cdev->private->state = DEV_STATE_CMFUPDATE; cdev->private->state = DEV_STATE_CMFUPDATE;
copy_block->ret = CMF_PENDING; cdev->private->cmb_wait = &copy_block;
cdev->private->cmb_wait = copy_block; spin_unlock_irq(cdev->ccwlock);
spin_unlock_irqrestore(cdev->ccwlock, flags); ret = wait_event_interruptible(copy_block.wait,
if (wait_event_interruptible(copy_block->wait, copy_block.ret != CMF_PENDING);
copy_block->ret != CMF_PENDING)) { spin_lock_irq(cdev->ccwlock);
spin_lock_irqsave(cdev->ccwlock, flags); if (ret) {
if (copy_block->ret == CMF_PENDING) { if (copy_block.ret == CMF_PENDING) {
copy_block->ret = -ERESTARTSYS; copy_block.ret = -ERESTARTSYS;
if (cdev->private->state == DEV_STATE_CMFUPDATE) if (cdev->private->state == DEV_STATE_CMFUPDATE)
cdev->private->state = DEV_STATE_ONLINE; cdev->private->state = DEV_STATE_ONLINE;
} }
spin_unlock_irqrestore(cdev->ccwlock, flags);
} }
spin_lock_irqsave(cdev->ccwlock, flags);
cdev->private->cmb_wait = NULL; cdev->private->cmb_wait = NULL;
ret = copy_block->ret; ret = copy_block.ret;
out_put:
kref_put(&copy_block->kref, cmf_copy_block_release);
out: out:
spin_unlock_irqrestore(cdev->ccwlock, flags); spin_unlock_irq(cdev->ccwlock);
return ret; return ret;
} }
void cmf_retry_copy_block(struct ccw_device *cdev) void cmf_retry_copy_block(struct ccw_device *cdev)
{ {
struct copy_block_struct *copy_block; struct copy_block_struct *copy_block = cdev->private->cmb_wait;
copy_block = cdev->private->cmb_wait; if (!copy_block)
if (!copy_block) {
WARN_ON(1);
return; return;
}
kref_get(&copy_block->kref);
copy_block->ret = cmf_copy_block(cdev); copy_block->ret = cmf_copy_block(cdev);
wake_up(&copy_block->wait); wake_up(&copy_block->wait);
kref_put(&copy_block->kref, cmf_copy_block_release);
} }
static void cmf_generic_reset(struct ccw_device *cdev) static void cmf_generic_reset(struct ccw_device *cdev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment