mei: bus: use zero vtag for bus clients.
authorAlexander Usyskin <alexander.usyskin@intel.com>
Tue, 18 Aug 2020 11:51:43 +0000 (14:51 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 18 Aug 2020 13:44:44 +0000 (15:44 +0200)
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@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20200818115147.2567012-10-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/misc/mei/bus.c

index fc20a0d..9cdaa7f 100644 (file)
@@ -496,6 +496,68 @@ static void mei_cl_bus_module_put(struct mei_cl_device *cldev)
 }
 
 /**
+ * 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;