[char-misc-next 09/13] mei: bus: use zero vtag for bus clients.

From: Tomas Winkler
Date: Tue Aug 18 2020 - 08:11:03 EST


From: Alexander Usyskin <alexander.usyskin@xxxxxxxxx>

The zero vtag is required for the read flow to work also for
devices on the mei client bus.

Signed-off-by: Alexander Usyskin <alexander.usyskin@xxxxxxxxx>
Signed-off-by: Tomas Winkler <tomas.winkler@xxxxxxxxx>
---
drivers/misc/mei/bus.c | 72 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index fc20a0da5c24..9cdaa7f3af23 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -495,6 +495,68 @@ static void mei_cl_bus_module_put(struct mei_cl_device *cldev)
module_put(cldev->bus->dev->driver->owner);
}

+/**
+ * mei_cl_bus_vtag - get bus vtag entry wrapper
+ * The tag for bus client is always first.
+ *
+ * @cl: host client
+ *
+ * Return: bus vtag or NULL
+ */
+static inline struct mei_cl_vtag *mei_cl_bus_vtag(struct mei_cl *cl)
+{
+ return list_first_entry_or_null(&cl->vtag_map,
+ struct mei_cl_vtag, list);
+}
+
+/**
+ * mei_cl_bus_vtag_alloc - add bus client entry to vtag map
+ *
+ * @cldev: me client device
+ *
+ * Return:
+ * * 0 on success
+ * * -ENOMEM if memory allocation failed
+ */
+static int mei_cl_bus_vtag_alloc(struct mei_cl_device *cldev)
+{
+ struct mei_cl *cl = cldev->cl;
+ struct mei_cl_vtag *cl_vtag;
+
+ /*
+ * Bail out if the client does not supports vtags
+ * or has already allocated one
+ */
+ if (mei_cl_vt_support_check(cl) || mei_cl_bus_vtag(cl))
+ return 0;
+
+ cl_vtag = mei_cl_vtag_alloc(NULL, 0);
+ if (IS_ERR(cl_vtag))
+ return -ENOMEM;
+
+ list_add_tail(&cl_vtag->list, &cl->vtag_map);
+
+ return 0;
+}
+
+/**
+ * mei_cl_bus_vtag_free - remove the bus entry from vtag map
+ *
+ * @cldev: me client device
+ */
+static void mei_cl_bus_vtag_free(struct mei_cl_device *cldev)
+{
+ struct mei_cl *cl = cldev->cl;
+ struct mei_cl_vtag *cl_vtag;
+
+ cl_vtag = mei_cl_bus_vtag(cl);
+ if (!cl_vtag)
+ return;
+
+ list_del(&cl_vtag->list);
+ kfree(cl_vtag);
+}
+
/**
* mei_cldev_enable - enable me client device
* create connection with me client
@@ -531,9 +593,15 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
goto out;
}

+ ret = mei_cl_bus_vtag_alloc(cldev);
+ if (ret)
+ goto out;
+
ret = mei_cl_connect(cl, cldev->me_cl, NULL);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&cldev->dev, "cannot connect\n");
+ mei_cl_bus_vtag_free(cldev);
+ }

out:
mutex_unlock(&bus->device_lock);
@@ -586,6 +654,8 @@ int mei_cldev_disable(struct mei_cl_device *cldev)

mutex_lock(&bus->device_lock);

+ mei_cl_bus_vtag_free(cldev);
+
if (!mei_cl_is_connected(cl)) {
dev_dbg(bus->dev, "Already disconnected\n");
err = 0;
--
2.25.4