usb: chipidea: handle single role for usb role class
authorJun Li <jun.li@nxp.com>
Wed, 22 Jan 2020 01:46:59 +0000 (01:46 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 22 Jan 2020 06:54:26 +0000 (07:54 +0100)
If usb port is configed to be single role, but usb role class
is trying to set unavailable role, don't try to do role change.

Signed-off-by: Jun Li <jun.li@nxp.com>
Signed-off-by: Peter Chen <peter.chen@nxp.com>
Link: https://lore.kernel.org/r/20200122014639.22667-2-peter.chen@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/core.c

index 6911aef500e98f3154235a5d7b85fe867e83c947..d49d5e1235d03645db205a83820f8ee7be4dcd8b 100644 (file)
@@ -302,6 +302,16 @@ static inline enum usb_role ci_role_to_usb_role(struct ci_hdrc *ci)
                return USB_ROLE_NONE;
 }
 
+static inline enum ci_role usb_role_to_ci_role(enum usb_role role)
+{
+       if (role == USB_ROLE_HOST)
+               return CI_ROLE_HOST;
+       else if (role == USB_ROLE_DEVICE)
+               return CI_ROLE_GADGET;
+       else
+               return CI_ROLE_END;
+}
+
 /**
  * hw_read_id_reg: reads from a identification register
  * @ci: the controller
index dce5db41501c3412d06e506907683f3e6ec62cde..52139c2a99240ef3f3f997cf8ac26ea03e2bba19 100644 (file)
@@ -618,9 +618,11 @@ static int ci_usb_role_switch_set(struct device *dev, enum usb_role role)
        struct ci_hdrc *ci = dev_get_drvdata(dev);
        struct ci_hdrc_cable *cable = NULL;
        enum usb_role current_role = ci_role_to_usb_role(ci);
+       enum ci_role ci_role = usb_role_to_ci_role(role);
        unsigned long flags;
 
-       if (current_role == role)
+       if ((ci_role != CI_ROLE_END && !ci->roles[ci_role]) ||
+           (current_role == role))
                return 0;
 
        pm_runtime_get_sync(ci->dev);