From: Tomas Winkler Date: Sun, 26 Jul 2015 06:54:22 +0000 (+0300) Subject: mei: implement fasync for event notification X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=237092bf034a648611f61eb1f0965e9ba1b08871;p=linux-beck.git mei: implement fasync for event notification A process can be informed about client notification also via SIGIO with POLL_PRI event. Signed-off-by: Tomas Winkler Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index d9396838774c..db2436aee2dc 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -1350,6 +1350,33 @@ out: return rets; } +/** + * mei_cl_notify - raise notification + * + * @cl: host client + * + * Locking: called under "dev->device_lock" lock + */ +void mei_cl_notify(struct mei_cl *cl) +{ + struct mei_device *dev; + + if (!cl || !cl->dev) + return; + + dev = cl->dev; + + if (!cl->notify_en) + return; + + cl_dbg(dev, cl, "notify event"); + cl->notify_ev = true; + wake_up_interruptible_all(&cl->ev_wait); + + if (cl->ev_async) + kill_fasync(&cl->ev_async, SIGIO, POLL_PRI); +} + /** * mei_cl_notify_get - get or wait for notification event * diff --git a/drivers/misc/mei/client.h b/drivers/misc/mei/client.h index 58a4b49701fe..1c7cad07d731 100644 --- a/drivers/misc/mei/client.h +++ b/drivers/misc/mei/client.h @@ -225,6 +225,7 @@ int mei_cl_notify_request(struct mei_cl *cl, struct file *file, u8 request); int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list); int mei_cl_notify_get(struct mei_cl *cl, bool block, bool *notify_ev); +void mei_cl_notify(struct mei_cl *cl); void mei_cl_all_disconnect(struct mei_device *dev); void mei_cl_all_wakeup(struct mei_device *dev); diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 70c94a9cd905..7f53597e697a 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c @@ -514,10 +514,8 @@ static void mei_hbm_cl_notify(struct mei_device *dev, struct mei_cl *cl; cl = mei_hbm_cl_find_by_cmd(dev, cmd); - if (cl && cl->notify_en) { - cl->notify_ev = true; - wake_up_interruptible(&cl->ev_wait); - } + if (cl) + mei_cl_notify(cl); } /** diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 17b356f26686..b2f2486b3d75 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c @@ -650,6 +650,26 @@ out: return mask; } +/** + * mei_fasync - asynchronous io support + * + * @fd: file descriptor + * @file: pointer to file structure + * @band: band bitmap + * + * Return: poll mask + */ +static int mei_fasync(int fd, struct file *file, int band) +{ + + struct mei_cl *cl = file->private_data; + + if (!mei_cl_is_connected(cl)) + return POLLERR; + + return fasync_helper(fd, file, band, &cl->ev_async); +} + /** * fw_status_show - mei device attribute show method * @@ -702,6 +722,7 @@ static const struct file_operations mei_fops = { .release = mei_release, .write = mei_write, .poll = mei_poll, + .fasync = mei_fasync, .llseek = no_llseek }; diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 6f8f5e1e909e..c960aaa538c0 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h @@ -236,6 +236,7 @@ struct mei_cl_cb { * @rx_wait: wait queue for rx completion * @wait: wait queue for management operation * @ev_wait: notification wait queue + * @ev_async: event async notification * @status: connection status * @me_cl: fw client connected * @host_client_id: host id @@ -258,6 +259,7 @@ struct mei_cl { wait_queue_head_t rx_wait; wait_queue_head_t wait; wait_queue_head_t ev_wait; + struct fasync_struct *ev_async; int status; struct mei_me_client *me_cl; u8 host_client_id;