Commit ebdca8ec authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 's390-6.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

Pull more s390 updates from Vasily Gorbik:

 - Generate a change uevent on unsolicited device end I/O interrupt for
   z/VM unit record devices supported by the vmur driver. This event can
   be used to automatically trigger processing of files as they arrive
   in the z/VM reader.

* tag 's390-6.1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/vmur: generate uevent on unsolicited device end
  s390/vmur: remove unnecessary BUG statement
parents 49857497 bf18140d
......@@ -15,12 +15,14 @@
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/uaccess.h>
#include <asm/cio.h>
#include <asm/ccwdev.h>
#include <asm/debug.h>
#include <asm/diag.h>
#include <asm/scsw.h>
#include "vmur.h"
......@@ -78,6 +80,8 @@ static struct ccw_driver ur_driver = {
static DEFINE_MUTEX(vmur_mutex);
static void ur_uevent(struct work_struct *ws);
/*
* Allocation, freeing, getting and putting of urdev structures
*
......@@ -108,6 +112,7 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
ccw_device_get_id(cdev, &urd->dev_id);
mutex_init(&urd->io_mutex);
init_waitqueue_head(&urd->wait);
INIT_WORK(&urd->uevent_work, ur_uevent);
spin_lock_init(&urd->open_lock);
refcount_set(&urd->ref_count, 1);
urd->cdev = cdev;
......@@ -275,6 +280,18 @@ static int do_ur_io(struct urdev *urd, struct ccw1 *cpa)
return rc;
}
static void ur_uevent(struct work_struct *ws)
{
struct urdev *urd = container_of(ws, struct urdev, uevent_work);
char *envp[] = {
"EVENT=unsol_de", /* Unsolicited device-end interrupt */
NULL
};
kobject_uevent_env(&urd->cdev->dev.kobj, KOBJ_CHANGE, envp);
urdev_put(urd);
}
/*
* ur interrupt handler, called from the ccw_device layer
*/
......@@ -288,12 +305,21 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
irb->scsw.cmd.count);
}
urd = dev_get_drvdata(&cdev->dev);
if (!intparm) {
TRACE("ur_int_handler: unsolicited interrupt\n");
if (scsw_dstat(&irb->scsw) & DEV_STAT_DEV_END) {
/*
* Userspace might be interested in a transition to
* device-ready state.
*/
urdev_get(urd);
schedule_work(&urd->uevent_work);
}
return;
}
urd = dev_get_drvdata(&cdev->dev);
BUG_ON(!urd);
/* On special conditions irb is an error pointer */
if (IS_ERR(irb))
urd->io_request_rc = PTR_ERR(irb);
......@@ -809,7 +835,6 @@ static int ur_probe(struct ccw_device *cdev)
rc = -ENOMEM;
goto fail_urdev_put;
}
cdev->handler = ur_int_handler;
/* validate virtual unit record device */
urd->class = get_urd_class(urd);
......@@ -823,6 +848,7 @@ static int ur_probe(struct ccw_device *cdev)
}
spin_lock_irq(get_ccwdev_lock(cdev));
dev_set_drvdata(&cdev->dev, urd);
cdev->handler = ur_int_handler;
spin_unlock_irq(get_ccwdev_lock(cdev));
mutex_unlock(&vmur_mutex);
......@@ -928,6 +954,10 @@ static int ur_set_offline_force(struct ccw_device *cdev, int force)
rc = -EBUSY;
goto fail_urdev_put;
}
if (cancel_work_sync(&urd->uevent_work)) {
/* Work not run yet - need to release reference here */
urdev_put(urd);
}
device_destroy(vmur_class, urd->char_device->dev);
cdev_del(urd->char_device);
urd->char_device = NULL;
......@@ -963,6 +993,7 @@ static void ur_remove(struct ccw_device *cdev)
spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
urdev_put(dev_get_drvdata(&cdev->dev));
dev_set_drvdata(&cdev->dev, NULL);
cdev->handler = NULL;
spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
mutex_unlock(&vmur_mutex);
......
......@@ -13,6 +13,7 @@
#define _VMUR_H_
#include <linux/refcount.h>
#include <linux/workqueue.h>
#define DEV_CLASS_UR_I 0x20 /* diag210 unit record input device class */
#define DEV_CLASS_UR_O 0x10 /* diag210 unit record output device class */
......@@ -76,6 +77,7 @@ struct urdev {
wait_queue_head_t wait; /* wait queue to serialize open */
int open_flag; /* "urdev is open" flag */
spinlock_t open_lock; /* serialize critical sections */
struct work_struct uevent_work; /* work to send uevent */
};
/*
......
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