diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2015-07-26 09:54:19 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-08-03 17:30:00 -0700 |
commit | b38a362fad6686dd580a50590053a76ded601a0b (patch) | |
tree | b5901f25be614d5fbf8e3d70d8120ed214eaca7a /drivers/misc/mei/client.c | |
parent | 51678ccb7b12dd428a84d466ff379a5e2d717f1f (diff) |
mei: add a handler that waits for notification on event
mei_cl_notify_get is to be called by a host client
to wait, receive, and ack the event notification.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/client.c')
-rw-r--r-- | drivers/misc/mei/client.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index fae4050413a2..d9396838774c 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -555,6 +555,7 @@ void mei_cl_init(struct mei_cl *cl, struct mei_device *dev) init_waitqueue_head(&cl->wait); init_waitqueue_head(&cl->rx_wait); init_waitqueue_head(&cl->tx_wait); + init_waitqueue_head(&cl->ev_wait); INIT_LIST_HEAD(&cl->rd_completed); INIT_LIST_HEAD(&cl->rd_pending); INIT_LIST_HEAD(&cl->link); @@ -1350,6 +1351,51 @@ out: } /** + * mei_cl_notify_get - get or wait for notification event + * + * @cl: host client + * @block: this request is blocking + * @notify_ev: true if notification event was received + * + * Locking: called under "dev->device_lock" lock + * + * Return: 0 on such and error otherwise. + */ +int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev) +{ + struct mei_device *dev; + int rets; + + *notify_ev = false; + + if (WARN_ON(!cl || !cl->dev)) + return -ENODEV; + + dev = cl->dev; + + if (!mei_cl_is_connected(cl)) + return -ENODEV; + + if (cl->notify_ev) + goto out; + + if (!block) + return -EAGAIN; + + mutex_unlock(&dev->device_lock); + rets = wait_event_interruptible(cl->ev_wait, cl->notify_ev); + mutex_lock(&dev->device_lock); + + if (rets < 0) + return rets; + +out: + *notify_ev = cl->notify_ev; + cl->notify_ev = false; + return 0; +} + +/** * mei_cl_read_start - the start read client message function. * * @cl: host client @@ -1701,6 +1747,12 @@ void mei_cl_all_wakeup(struct mei_device *dev) cl_dbg(dev, cl, "Waking up writing client!\n"); wake_up_interruptible(&cl->tx_wait); } + + /* synchronized under device mutex */ + if (waitqueue_active(&cl->ev_wait)) { + cl_dbg(dev, cl, "Waking up waiting for event clients!\n"); + wake_up_interruptible(&cl->ev_wait); + } } } |