Skip to content

Commit ebdca8e

Browse files
committed
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
2 parents 4985749 + bf18140 commit ebdca8e

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

drivers/s390/char/vmur.c

Lines changed: 34 additions & 3 deletions
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,12 +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);
296-
BUG_ON(!urd);
297323
/* On special conditions irb is an error pointer */
298324
if (IS_ERR(irb))
299325
urd->io_request_rc = PTR_ERR(irb);
@@ -809,7 +835,6 @@ static int ur_probe(struct ccw_device *cdev)
809835
rc = -ENOMEM;
810836
goto fail_urdev_put;
811837
}
812-
cdev->handler = ur_int_handler;
813838

814839
/* validate virtual unit record device */
815840
urd->class = get_urd_class(urd);
@@ -823,6 +848,7 @@ static int ur_probe(struct ccw_device *cdev)
823848
}
824849
spin_lock_irq(get_ccwdev_lock(cdev));
825850
dev_set_drvdata(&cdev->dev, urd);
851+
cdev->handler = ur_int_handler;
826852
spin_unlock_irq(get_ccwdev_lock(cdev));
827853

828854
mutex_unlock(&vmur_mutex);
@@ -928,6 +954,10 @@ static int ur_set_offline_force(struct ccw_device *cdev, int force)
928954
rc = -EBUSY;
929955
goto fail_urdev_put;
930956
}
957+
if (cancel_work_sync(&urd->uevent_work)) {
958+
/* Work not run yet - need to release reference here */
959+
urdev_put(urd);
960+
}
931961
device_destroy(vmur_class, urd->char_device->dev);
932962
cdev_del(urd->char_device);
933963
urd->char_device = NULL;
@@ -963,6 +993,7 @@ static void ur_remove(struct ccw_device *cdev)
963993
spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
964994
urdev_put(dev_get_drvdata(&cdev->dev));
965995
dev_set_drvdata(&cdev->dev, NULL);
996+
cdev->handler = NULL;
966997
spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
967998

968999
mutex_unlock(&vmur_mutex);

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)