Skip to content

Commit

Permalink
Merge tag 's390-6.1-2' of git://git.kernel.org/pub/scm/linux/kernel/g…
Browse files Browse the repository at this point in the history
…it/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
  • Loading branch information
torvalds committed Oct 14, 2022
2 parents 4985749 + bf18140 commit ebdca8e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 3 deletions.
37 changes: 34 additions & 3 deletions drivers/s390/char/vmur.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
*/
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions drivers/s390/char/vmur.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
};

/*
Expand Down

0 comments on commit ebdca8e

Please sign in to comment.