Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

usb: typec: mux: Take care of driver module reference counting

Functions typec_mux_get() and typec_switch_get() already
make sure that the mux device reference count is
incremented, but the same must be done to the driver module
as well to prevent the drivers from being unloaded in the
middle of operation.

This fixes a potential "BUG: unable to handle kernel paging
request at ..." from happening.

Fixes: 93dd2112c7b2 ("usb: typec: mux: Get the mux identifier from function parameter")
Acked-by: Hans de Goede <hdegoede@redhat.com>
Tested-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Heikki Krogerus and committed by
Greg Kroah-Hartman
3e3b8196 16c4cb19

+13 -4
+13 -4
drivers/usb/typec/mux.c
··· 9 9 10 10 #include <linux/device.h> 11 11 #include <linux/list.h> 12 + #include <linux/module.h> 12 13 #include <linux/mutex.h> 13 14 #include <linux/usb/typec_mux.h> 14 15 ··· 50 49 mutex_lock(&switch_lock); 51 50 sw = device_connection_find_match(dev, "typec-switch", NULL, 52 51 typec_switch_match); 53 - if (!IS_ERR_OR_NULL(sw)) 52 + if (!IS_ERR_OR_NULL(sw)) { 53 + WARN_ON(!try_module_get(sw->dev->driver->owner)); 54 54 get_device(sw->dev); 55 + } 55 56 mutex_unlock(&switch_lock); 56 57 57 58 return sw; ··· 68 65 */ 69 66 void typec_switch_put(struct typec_switch *sw) 70 67 { 71 - if (!IS_ERR_OR_NULL(sw)) 68 + if (!IS_ERR_OR_NULL(sw)) { 69 + module_put(sw->dev->driver->owner); 72 70 put_device(sw->dev); 71 + } 73 72 } 74 73 EXPORT_SYMBOL_GPL(typec_switch_put); 75 74 ··· 141 136 142 137 mutex_lock(&mux_lock); 143 138 mux = device_connection_find_match(dev, name, NULL, typec_mux_match); 144 - if (!IS_ERR_OR_NULL(mux)) 139 + if (!IS_ERR_OR_NULL(mux)) { 140 + WARN_ON(!try_module_get(mux->dev->driver->owner)); 145 141 get_device(mux->dev); 142 + } 146 143 mutex_unlock(&mux_lock); 147 144 148 145 return mux; ··· 159 152 */ 160 153 void typec_mux_put(struct typec_mux *mux) 161 154 { 162 - if (!IS_ERR_OR_NULL(mux)) 155 + if (!IS_ERR_OR_NULL(mux)) { 156 + module_put(mux->dev->driver->owner); 163 157 put_device(mux->dev); 158 + } 164 159 } 165 160 EXPORT_SYMBOL_GPL(typec_mux_put); 166 161