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
7981static 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 );
0 commit comments