summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2019-02-25 12:09:28 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-03-23 22:11:12 +0300
commit1cfec56130907b513d01d04688859d39f9563b2c (patch)
tree28495b049a87b983de8711242ff11cb34e79724e /drivers
parent55ced4559dbf812384a8e0dc74b6f33866e132b1 (diff)
downloadlinux-1cfec56130907b513d01d04688859d39f9563b2c.tar.xz
mei: bus: move hw module get/put to probe/release
commit b5958faa34e2f99f3475ad89c52d98dfea079d33 upstream. Fix unbalanced module reference counting during internal reset, which prevents the drivers unloading. Tracking mei_me/txe modules on mei client bus via mei_cldev_enable/disable is error prone due to possible internal reset flow, where clients are disconnected underneath. Moving reference counting to probe and release of mei bus client driver solves this issue in simplest way, as each client provides only a single connection to a client bus driver. Cc: <stable@vger.kernel.org> Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/misc/mei/bus.c21
1 files changed, 10 insertions, 11 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index fc3872fe7b25..c383322ec2ba 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -541,17 +541,9 @@ int mei_cldev_enable(struct mei_cl_device *cldev)
goto out;
}
- if (!mei_cl_bus_module_get(cldev)) {
- dev_err(&cldev->dev, "get hw module failed");
- ret = -ENODEV;
- 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_module_put(cldev);
- }
out:
mutex_unlock(&bus->device_lock);
@@ -614,7 +606,6 @@ int mei_cldev_disable(struct mei_cl_device *cldev)
if (err < 0)
dev_err(bus->dev, "Could not disconnect from the ME client\n");
- mei_cl_bus_module_put(cldev);
out:
/* Flush queues and remove any pending read */
mei_cl_flush_queues(cl, NULL);
@@ -725,9 +716,16 @@ static int mei_cl_device_probe(struct device *dev)
if (!id)
return -ENODEV;
+ if (!mei_cl_bus_module_get(cldev)) {
+ dev_err(&cldev->dev, "get hw module failed");
+ return -ENODEV;
+ }
+
ret = cldrv->probe(cldev, id);
- if (ret)
+ if (ret) {
+ mei_cl_bus_module_put(cldev);
return ret;
+ }
__module_get(THIS_MODULE);
return 0;
@@ -755,6 +753,7 @@ static int mei_cl_device_remove(struct device *dev)
mei_cldev_unregister_callbacks(cldev);
+ mei_cl_bus_module_put(cldev);
module_put(THIS_MODULE);
dev->driver = NULL;
return ret;