]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
s390/cmf: simplify cmb_copy_wait
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Wed, 6 Sep 2017 17:05:29 +0000 (19:05 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 28 Sep 2017 05:29:42 +0000 (07:29 +0200)
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>
drivers/s390/cio/cmf.c

index a8e4c5e13ba8e181b4444798f60673e3e878e0a1..7ed6c865501b00c863609b3bde374017892c4712 100644 (file)
@@ -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;
-               goto out;
-       }
-       copy_block = kzalloc(sizeof(struct copy_block_struct), GFP_ATOMIC);
-       if (!copy_block) {
-               ret = -ENOMEM;
+       spin_lock_irq(cdev->ccwlock);
+       if (!cdev->private->cmb)
                goto out;
-       }
-       init_waitqueue_head(&copy_block->wait);
-       kref_init(&copy_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(&copy_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 = &copy_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(&copy_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(&copy_block->kref);
+
        copy_block->ret = cmf_copy_block(cdev);
        wake_up(&copy_block->wait);
-       kref_put(&copy_block->kref, cmf_copy_block_release);
 }
 
 static void cmf_generic_reset(struct ccw_device *cdev)