From 01d8a2072e4adedc6b7af03d7dd6ee57fdad7a13 Mon Sep 17 00:00:00 2001 From: Xu Yang Date: Mon, 29 Jan 2024 17:37:39 +0800 Subject: [PATCH] BACKPORT: usb: roles: don't get/set_role() when usb_role_switch is unregistered There is a possibility that usb_role_switch device is unregistered before the user put usb_role_switch. In this case, the user may still want to get/set_role() since the user can't sense the changes of usb_role_switch. This will add a flag to show if usb_role_switch is already registered and avoid unwanted behaviors. Fixes: fde0aa6c175a ("usb: common: Small class for USB role switches") Change-Id: I59b864185b8260ff4d51807005a3b50080cf61c9 cc: stable@vger.kernel.org Signed-off-by: Xu Yang Acked-by: Heikki Krogerus Link: https://lore.kernel.org/r/20240129093739.2371530-2-xu.yang_2@nxp.com Signed-off-by: Greg Kroah-Hartman Signed-off-by: William Wu (cherry picked from commit b787a3e781759026a6212736ef8e52cf83d1821a) --- drivers/usb/roles/class.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/drivers/usb/roles/class.c b/drivers/usb/roles/class.c index 32e6d19f7011..435addc7fd56 100644 --- a/drivers/usb/roles/class.c +++ b/drivers/usb/roles/class.c @@ -20,6 +20,9 @@ struct usb_role_switch { struct device dev; struct mutex lock; /* device lock*/ enum usb_role role; +#ifdef CONFIG_NO_GKI + bool registered; +#endif /* From descriptor */ struct device *usb2_port; @@ -46,6 +49,11 @@ int usb_role_switch_set_role(struct usb_role_switch *sw, enum usb_role role) if (IS_ERR_OR_NULL(sw)) return 0; +#ifdef CONFIG_NO_GKI + if (!sw->registered) + return -EOPNOTSUPP; +#endif + mutex_lock(&sw->lock); ret = sw->set(sw, role); @@ -74,6 +82,11 @@ enum usb_role usb_role_switch_get_role(struct usb_role_switch *sw) if (IS_ERR_OR_NULL(sw)) return USB_ROLE_NONE; +#ifdef CONFIG_NO_GKI + if (!sw->registered) + return USB_ROLE_NONE; +#endif + mutex_lock(&sw->lock); if (sw->get) @@ -351,6 +364,10 @@ usb_role_switch_register(struct device *parent, return ERR_PTR(ret); } +#ifdef CONFIG_NO_GKI + sw->registered = true; +#endif + /* TODO: Symlinks for the host port and the device controller. */ return sw; @@ -365,8 +382,12 @@ EXPORT_SYMBOL_GPL(usb_role_switch_register); */ void usb_role_switch_unregister(struct usb_role_switch *sw) { - if (!IS_ERR_OR_NULL(sw)) + if (!IS_ERR_OR_NULL(sw)) { +#ifdef CONFIG_NO_GKI + sw->registered = false; +#endif device_unregister(&sw->dev); + } } EXPORT_SYMBOL_GPL(usb_role_switch_unregister);