Skip to content

Commit bf18140

Browse files
oberparVasily Gorbik
authored andcommitted
s390/vmur: generate uevent on unsolicited device end
When a traditional channel-attached device transitions from not-ready to ready state, an unsolicited DEVICE END I/O interrupt is raised. This happens for example when a new file arrives in the z/VM virtual reader device. Change the Linux kernel to generate a change uevent when such an interrupt occurs for any online unit record devices supported by the vmur driver. This can be useful to automatically trigger processing of files as they arrive in the reader device. A sample udev rule for running a program when this event occurs looks as follows: ENV{DRIVER}=="vmur", ACTION=="change", ENV{EVENT}=="unsol_de", \ RUN{program}="/path/to/program" The rule can be tested using the following steps: 1. Set reader device online (assuming default reader device number 000c) $ chzdev -ea 0.0.000c 2. Force a ready-state transition using z/VM's READY CP command $ vmcp ready 000c Suggested-by: Alan Altmark <Alan_Altmark@us.ibm.com> Reviewed-by: Heiko Carstens <hca@linux.ibm.com> Reviewed-by: Sven Schnelle <svens@linux.ibm.com> Signed-off-by: Peter Oberparleiter <oberpar@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
1 parent f3e59ff commit bf18140

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

drivers/s390/char/vmur.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
#include <linux/cdev.h>
1616
#include <linux/slab.h>
1717
#include <linux/module.h>
18+
#include <linux/kobject.h>
1819

1920
#include <linux/uaccess.h>
2021
#include <asm/cio.h>
2122
#include <asm/ccwdev.h>
2223
#include <asm/debug.h>
2324
#include <asm/diag.h>
25+
#include <asm/scsw.h>
2426

2527
#include "vmur.h"
2628

@@ -78,6 +80,8 @@ static struct ccw_driver ur_driver = {
7880

7981
static DEFINE_MUTEX(vmur_mutex);
8082

83+
static void ur_uevent(struct work_struct *ws);
84+
8185
/*
8286
* Allocation, freeing, getting and putting of urdev structures
8387
*
@@ -108,6 +112,7 @@ static struct urdev *urdev_alloc(struct ccw_device *cdev)
108112
ccw_device_get_id(cdev, &urd->dev_id);
109113
mutex_init(&urd->io_mutex);
110114
init_waitqueue_head(&urd->wait);
115+
INIT_WORK(&urd->uevent_work, ur_uevent);
111116
spin_lock_init(&urd->open_lock);
112117
refcount_set(&urd->ref_count, 1);
113118
urd->cdev = cdev;
@@ -275,6 +280,18 @@ static int do_ur_io(struct urdev *urd, struct ccw1 *cpa)
275280
return rc;
276281
}
277282

283+
static void ur_uevent(struct work_struct *ws)
284+
{
285+
struct urdev *urd = container_of(ws, struct urdev, uevent_work);
286+
char *envp[] = {
287+
"EVENT=unsol_de", /* Unsolicited device-end interrupt */
288+
NULL
289+
};
290+
291+
kobject_uevent_env(&urd->cdev->dev.kobj, KOBJ_CHANGE, envp);
292+
urdev_put(urd);
293+
}
294+
278295
/*
279296
* ur interrupt handler, called from the ccw_device layer
280297
*/
@@ -288,11 +305,21 @@ static void ur_int_handler(struct ccw_device *cdev, unsigned long intparm,
288305
intparm, irb->scsw.cmd.cstat, irb->scsw.cmd.dstat,
289306
irb->scsw.cmd.count);
290307
}
308+
urd = dev_get_drvdata(&cdev->dev);
291309
if (!intparm) {
292310
TRACE("ur_int_handler: unsolicited interrupt\n");
311+
312+
if (scsw_dstat(&irb->scsw) & DEV_STAT_DEV_END) {
313+
/*
314+
* Userspace might be interested in a transition to
315+
* device-ready state.
316+
*/
317+
urdev_get(urd);
318+
schedule_work(&urd->uevent_work);
319+
}
320+
293321
return;
294322
}
295-
urd = dev_get_drvdata(&cdev->dev);
296323
/* On special conditions irb is an error pointer */
297324
if (IS_ERR(irb))
298325
urd->io_request_rc = PTR_ERR(irb);
@@ -927,6 +954,10 @@ static int ur_set_offline_force(struct ccw_device *cdev, int force)
927954
rc = -EBUSY;
928955
goto fail_urdev_put;
929956
}
957+
if (cancel_work_sync(&urd->uevent_work)) {
958+
/* Work not run yet - need to release reference here */
959+
urdev_put(urd);
960+
}
930961
device_destroy(vmur_class, urd->char_device->dev);
931962
cdev_del(urd->char_device);
932963
urd->char_device = NULL;

drivers/s390/char/vmur.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define _VMUR_H_
1414

1515
#include <linux/refcount.h>
16+
#include <linux/workqueue.h>
1617

1718
#define DEV_CLASS_UR_I 0x20 /* diag210 unit record input device class */
1819
#define DEV_CLASS_UR_O 0x10 /* diag210 unit record output device class */
@@ -76,6 +77,7 @@ struct urdev {
7677
wait_queue_head_t wait; /* wait queue to serialize open */
7778
int open_flag; /* "urdev is open" flag */
7879
spinlock_t open_lock; /* serialize critical sections */
80+
struct work_struct uevent_work; /* work to send uevent */
7981
};
8082

8183
/*

0 commit comments

Comments
 (0)