mei: implement fasync for event notification
authorTomas Winkler <tomas.winkler@intel.com>
Sun, 26 Jul 2015 06:54:22 +0000 (09:54 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 4 Aug 2015 00:30:00 +0000 (17:30 -0700)
A process can be informed about client notification also via
SIGIO with POLL_PRI event.

Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/client.c
drivers/misc/mei/client.h
drivers/misc/mei/hbm.c
drivers/misc/mei/main.c
drivers/misc/mei/mei_dev.h

index d9396838774c50db2afdf11610b209520d573589..db2436aee2dc6e4f22d0adeb8206c1264eefbab4 100644 (file)
@@ -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
  *
index 58a4b49701fe0b720033be3cbdc092419e4aabb4..1c7cad07d7319e187a8c6784440cad897f28678f 100644 (file)
@@ -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);
index 70c94a9cd9052b2134c414a2e9a1839772b07107..7f53597e697a95063f74a275e96288a09595ce29 100644 (file)
@@ -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);
 }
 
 /**
index 17b356f26686108dc87b882f640511a69f4019ec..b2f2486b3d757cd1bba127d8328177716d539591 100644 (file)
@@ -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
 };
 
index 6f8f5e1e909ecd31059b31c0007f97218ae8eddc..c960aaa538c042c0b8a3410ff5d993bfb8c6f3d4 100644 (file)
@@ -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;