diff options
author | Jiri Kosina <jkosina@suse.cz> | 2017-05-02 11:02:41 +0200 |
---|---|---|
committer | Jiri Kosina <jkosina@suse.cz> | 2017-05-02 11:02:41 +0200 |
commit | 4d6ca227c768b50b05cf183974b40abe444e9d0c (patch) | |
tree | bf953d8e895281053548b9967a2c4b58d641df00 /drivers/misc/mei/bus.c | |
parent | 800f3eef8ebc1264e9c135bfa892c8ae41fa4792 (diff) | |
parent | af22a610bc38508d5ea760507d31be6b6983dfa8 (diff) |
Merge branch 'for-4.12/asus' into for-linus
Diffstat (limited to 'drivers/misc/mei/bus.c')
-rw-r--r-- | drivers/misc/mei/bus.c | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c index 2d9c5dd06e42..df5f78ae3d25 100644 --- a/drivers/misc/mei/bus.c +++ b/drivers/misc/mei/bus.c @@ -16,7 +16,7 @@ #include <linux/module.h> #include <linux/device.h> #include <linux/kernel.h> -#include <linux/sched.h> +#include <linux/sched/signal.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/slab.h> @@ -499,6 +499,25 @@ out: EXPORT_SYMBOL_GPL(mei_cldev_enable); /** + * mei_cldev_unregister_callbacks - internal wrapper for unregistering + * callbacks. + * + * @cldev: client device + */ +static void mei_cldev_unregister_callbacks(struct mei_cl_device *cldev) +{ + if (cldev->rx_cb) { + cancel_work_sync(&cldev->rx_work); + cldev->rx_cb = NULL; + } + + if (cldev->notif_cb) { + cancel_work_sync(&cldev->notif_work); + cldev->notif_cb = NULL; + } +} + +/** * mei_cldev_disable - disable me client device * disconnect form the me client * @@ -519,6 +538,8 @@ int mei_cldev_disable(struct mei_cl_device *cldev) bus = cldev->bus; + mei_cldev_unregister_callbacks(cldev); + mutex_lock(&bus->device_lock); if (!mei_cl_is_connected(cl)) { @@ -542,6 +563,37 @@ out: EXPORT_SYMBOL_GPL(mei_cldev_disable); /** + * mei_cl_bus_module_get - acquire module of the underlying + * hw module. + * + * @cl: host client + * + * Return: true on success; false if the module was removed. + */ +bool mei_cl_bus_module_get(struct mei_cl *cl) +{ + struct mei_cl_device *cldev = cl->cldev; + + if (!cldev) + return true; + + return try_module_get(cldev->bus->dev->driver->owner); +} + +/** + * mei_cl_bus_module_put - release the underlying hw module. + * + * @cl: host client + */ +void mei_cl_bus_module_put(struct mei_cl *cl) +{ + struct mei_cl_device *cldev = cl->cldev; + + if (cldev) + module_put(cldev->bus->dev->driver->owner); +} + +/** * mei_cl_device_find - find matching entry in the driver id table * * @cldev: me client device @@ -665,19 +717,12 @@ static int mei_cl_device_remove(struct device *dev) if (!cldev || !dev->driver) return 0; - if (cldev->rx_cb) { - cancel_work_sync(&cldev->rx_work); - cldev->rx_cb = NULL; - } - if (cldev->notif_cb) { - cancel_work_sync(&cldev->notif_work); - cldev->notif_cb = NULL; - } - cldrv = to_mei_cl_driver(dev->driver); if (cldrv->remove) ret = cldrv->remove(cldev); + mei_cldev_unregister_callbacks(cldev); + module_put(THIS_MODULE); dev->driver = NULL; return ret; |