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: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
eeec1e435f
commit
60f3eac3a1
@ -319,83 +319,57 @@ static int cmf_copy_block(struct ccw_device *cdev)
|
||||
struct copy_block_struct {
|
||||
wait_queue_head_t wait;
|
||||
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)
|
||||
{
|
||||
struct copy_block_struct *copy_block;
|
||||
int ret;
|
||||
unsigned long flags;
|
||||
struct copy_block_struct copy_block;
|
||||
int ret = -ENODEV;
|
||||
|
||||
spin_lock_irqsave(cdev->ccwlock, flags);
|
||||
if (!cdev->private->cmb) {
|
||||
ret = -ENODEV;
|
||||
spin_lock_irq(cdev->ccwlock);
|
||||
if (!cdev->private->cmb)
|
||||
goto out;
|
||||
}
|
||||
copy_block = kzalloc(sizeof(struct copy_block_struct), GFP_ATOMIC);
|
||||
if (!copy_block) {
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
init_waitqueue_head(©_block->wait);
|
||||
kref_init(©_block->kref);
|
||||
|
||||
ret = cmf_copy_block(cdev);
|
||||
if (ret != -EBUSY)
|
||||
goto out_put;
|
||||
goto out;
|
||||
|
||||
if (cdev->private->state != DEV_STATE_ONLINE) {
|
||||
ret = -EBUSY;
|
||||
goto out_put;
|
||||
}
|
||||
if (cdev->private->state != DEV_STATE_ONLINE)
|
||||
goto out;
|
||||
|
||||
init_waitqueue_head(©_block.wait);
|
||||
copy_block.ret = CMF_PENDING;
|
||||
|
||||
cdev->private->state = DEV_STATE_CMFUPDATE;
|
||||
copy_block->ret = CMF_PENDING;
|
||||
cdev->private->cmb_wait = copy_block;
|
||||
cdev->private->cmb_wait = ©_block;
|
||||
spin_unlock_irq(cdev->ccwlock);
|
||||
|
||||
spin_unlock_irqrestore(cdev->ccwlock, flags);
|
||||
if (wait_event_interruptible(copy_block->wait,
|
||||
copy_block->ret != CMF_PENDING)) {
|
||||
spin_lock_irqsave(cdev->ccwlock, flags);
|
||||
if (copy_block->ret == CMF_PENDING) {
|
||||
copy_block->ret = -ERESTARTSYS;
|
||||
ret = wait_event_interruptible(copy_block.wait,
|
||||
copy_block.ret != CMF_PENDING);
|
||||
spin_lock_irq(cdev->ccwlock);
|
||||
if (ret) {
|
||||
if (copy_block.ret == CMF_PENDING) {
|
||||
copy_block.ret = -ERESTARTSYS;
|
||||
if (cdev->private->state == DEV_STATE_CMFUPDATE)
|
||||
cdev->private->state = DEV_STATE_ONLINE;
|
||||
}
|
||||
spin_unlock_irqrestore(cdev->ccwlock, flags);
|
||||
}
|
||||
spin_lock_irqsave(cdev->ccwlock, flags);
|
||||
cdev->private->cmb_wait = NULL;
|
||||
ret = copy_block->ret;
|
||||
out_put:
|
||||
kref_put(©_block->kref, cmf_copy_block_release);
|
||||
ret = copy_block.ret;
|
||||
out:
|
||||
spin_unlock_irqrestore(cdev->ccwlock, flags);
|
||||
spin_unlock_irq(cdev->ccwlock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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) {
|
||||
WARN_ON(1);
|
||||
if (!copy_block)
|
||||
return;
|
||||
}
|
||||
kref_get(©_block->kref);
|
||||
|
||||
copy_block->ret = cmf_copy_block(cdev);
|
||||
wake_up(©_block->wait);
|
||||
kref_put(©_block->kref, cmf_copy_block_release);
|
||||
}
|
||||
|
||||
static void cmf_generic_reset(struct ccw_device *cdev)
|
||||
|
Loading…
Reference in New Issue
Block a user