From: Alexander Usyskin <alexander.usys...@intel.com>

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.usys...@intel.com>
Signed-off-by: Tomas Winkler <tomas.wink...@intel.com>
---
 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

Reply via email to