aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/mei/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/mei/bus.c')
-rw-r--r--drivers/misc/mei/bus.c121
1 files changed, 99 insertions, 22 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 9cdaa7f3af23..2907db260fba 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -26,11 +26,12 @@
* @cl: host client
* @buf: buffer to send
* @length: buffer length
+ * @vtag: virtual tag
* @mode: sending mode
*
* Return: written size bytes or < 0 on error
*/
-ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
+ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, u8 vtag,
unsigned int mode)
{
struct mei_device *bus;
@@ -86,6 +87,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
rets = -ENOMEM;
goto out;
}
+ cb->vtag = vtag;
cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
@@ -106,11 +108,12 @@ out:
* @buf: buffer to receive
* @length: buffer length
* @mode: io mode
+ * @vtag: virtual tag
* @timeout: recv timeout, 0 for infinite timeout
*
* Return: read size in bytes of < 0 on error
*/
-ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
+ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, u8 *vtag,
unsigned int mode, unsigned long timeout)
{
struct mei_device *bus;
@@ -196,6 +199,8 @@ copy:
r_length = min_t(size_t, length, cb->buf_idx);
memcpy(buf, cb->buf.data, r_length);
rets = r_length;
+ if (vtag)
+ *vtag = cb->vtag;
free:
mei_cl_del_rd_completed(cl, cb);
@@ -206,40 +211,87 @@ out:
}
/**
- * mei_cldev_send - me device send (write)
+ * mei_cldev_send_vtag - me device send with vtag (write)
*
* @cldev: me client device
* @buf: buffer to send
* @length: buffer length
+ * @vtag: virtual tag
*
- * Return: written size in bytes or < 0 on error
+ * Return:
+ * * written size in bytes
+ * * < 0 on error
*/
-ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
+
+ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
+ u8 vtag)
{
struct mei_cl *cl = cldev->cl;
- return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
+ return __mei_cl_send(cl, buf, length, vtag, MEI_CL_IO_TX_BLOCKING);
}
-EXPORT_SYMBOL_GPL(mei_cldev_send);
+EXPORT_SYMBOL_GPL(mei_cldev_send_vtag);
/**
- * mei_cldev_recv_nonblock - non block client receive (read)
+ * mei_cldev_recv_vtag - client receive with vtag (read)
*
* @cldev: me client device
* @buf: buffer to receive
* @length: buffer length
+ * @vtag: virtual tag
*
- * Return: read size in bytes of < 0 on error
- * -EAGAIN if function will block.
+ * Return:
+ * * read size in bytes
+ * * < 0 on error
*/
-ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
- size_t length)
+
+ssize_t mei_cldev_recv_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
+ u8 *vtag)
{
struct mei_cl *cl = cldev->cl;
- return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
+ return __mei_cl_recv(cl, buf, length, vtag, 0, 0);
}
-EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
+EXPORT_SYMBOL_GPL(mei_cldev_recv_vtag);
+
+/**
+ * mei_cldev_recv_nonblock_vtag - non block client receive with vtag (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to receive
+ * @length: buffer length
+ * @vtag: virtual tag
+ *
+ * Return:
+ * * read size in bytes
+ * * -EAGAIN if function will block.
+ * * < 0 on other error
+ */
+ssize_t mei_cldev_recv_nonblock_vtag(struct mei_cl_device *cldev, u8 *buf,
+ size_t length, u8 *vtag)
+{
+ struct mei_cl *cl = cldev->cl;
+
+ return __mei_cl_recv(cl, buf, length, vtag, MEI_CL_IO_RX_NONBLOCK, 0);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock_vtag);
+
+/**
+ * mei_cldev_send - me device send (write)
+ *
+ * @cldev: me client device
+ * @buf: buffer to send
+ * @length: buffer length
+ *
+ * Return:
+ * * written size in bytes
+ * * < 0 on error
+ */
+ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
+{
+ return mei_cldev_send_vtag(cldev, buf, length, 0);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_send);
/**
* mei_cldev_recv - client receive (read)
@@ -252,13 +304,28 @@ EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
*/
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
- struct mei_cl *cl = cldev->cl;
-
- return __mei_cl_recv(cl, buf, length, 0, 0);
+ return mei_cldev_recv_vtag(cldev, buf, length, NULL);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv);
/**
+ * mei_cldev_recv_nonblock - non block client receive (read)
+ *
+ * @cldev: me client device
+ * @buf: buffer to receive
+ * @length: buffer length
+ *
+ * Return: read size in bytes of < 0 on error
+ * -EAGAIN if function will block.
+ */
+ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
+ size_t length)
+{
+ return mei_cldev_recv_nonblock_vtag(cldev, buf, length, NULL);
+}
+EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
+
+/**
* mei_cl_bus_rx_work - dispatch rx event for a bus device
*
* @work: work
@@ -276,7 +343,8 @@ static void mei_cl_bus_rx_work(struct work_struct *work)
cldev->rx_cb(cldev);
mutex_lock(&bus->device_lock);
- mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ if (mei_cl_is_connected(cldev->cl))
+ mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
mutex_unlock(&bus->device_lock);
}
@@ -364,10 +432,16 @@ int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
mutex_lock(&bus->device_lock);
- ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ if (mei_cl_is_connected(cldev->cl))
+ ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
+ else
+ ret = -ENODEV;
mutex_unlock(&bus->device_lock);
- if (ret && ret != -EBUSY)
+ if (ret && ret != -EBUSY) {
+ cancel_work_sync(&cldev->rx_work);
+ cldev->rx_cb = NULL;
return ret;
+ }
return 0;
}
@@ -401,8 +475,11 @@ int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
mutex_lock(&bus->device_lock);
ret = mei_cl_notify_request(cldev->cl, NULL, 1);
mutex_unlock(&bus->device_lock);
- if (ret)
+ if (ret) {
+ cancel_work_sync(&cldev->notif_work);
+ cldev->notif_cb = NULL;
return ret;
+ }
return 0;
}
@@ -1037,7 +1114,7 @@ static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
}
/**
- * mei_cl_dev_setup - setup me client device
+ * mei_cl_bus_dev_setup - setup me client device
* run fix up routines and set the device name
*
* @bus: mei device