summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-07-26 09:54:22 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-08-03 17:30:00 -0700
commit237092bf034a648611f61eb1f0965e9ba1b08871 (patch)
tree64dec996bf6840cd2cdfcfbd51909015b64246df /drivers/misc
parent2c84c2970c1acf83827aa97ab0e6addc3d2aa960 (diff)
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 <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/mei/client.c27
-rw-r--r--drivers/misc/mei/client.h1
-rw-r--r--drivers/misc/mei/hbm.c6
-rw-r--r--drivers/misc/mei/main.c21
-rw-r--r--drivers/misc/mei/mei_dev.h2
5 files changed, 53 insertions, 4 deletions
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
@@ -1351,6 +1351,33 @@ out:
}
/**
+ * 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
*
* @cl: host client
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
@@ -651,6 +651,26 @@ out:
}
/**
+ * 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
*
* @device: device pointer
@@ -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;