Skip to content

Commit f22e9b6

Browse files
dolcinigregkh
authored andcommitted
Revert "usb: gadget: udc: core: Invoke usb_gadget_connect only when started"
This reverts commit 0db213e. It introduces an issues with configuring the USB gadget hangs forever on multiple Qualcomm and NXP i.MX SoC at least. Cc: [email protected] Fixes: 0db213e ("usb: gadget: udc: core: Invoke usb_gadget_connect only when started") Reported-by: Stephan Gerhold <[email protected]> Reported-by: Francesco Dolcini <[email protected]> Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Francesco Dolcini <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 5e16172 commit f22e9b6

File tree

1 file changed

+44
-104
lines changed

1 file changed

+44
-104
lines changed

drivers/usb/gadget/udc/core.c

Lines changed: 44 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,6 @@ static const struct bus_type gadget_bus_type;
3737
* @vbus: for udcs who care about vbus status, this value is real vbus status;
3838
* for udcs who do not care about vbus status, this value is always true
3939
* @started: the UDC's started state. True if the UDC had started.
40-
* @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related
41-
* functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked,
42-
* usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are
43-
* called with this lock held.
4440
*
4541
* This represents the internal data structure which is used by the UDC-class
4642
* to hold information about udc driver and gadget together.
@@ -52,7 +48,6 @@ struct usb_udc {
5248
struct list_head list;
5349
bool vbus;
5450
bool started;
55-
struct mutex connect_lock;
5651
};
5752

5853
static struct class *udc_class;
@@ -692,9 +687,17 @@ int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
692687
}
693688
EXPORT_SYMBOL_GPL(usb_gadget_vbus_disconnect);
694689

695-
/* Internal version of usb_gadget_connect needs to be called with connect_lock held. */
696-
static int usb_gadget_connect_locked(struct usb_gadget *gadget)
697-
__must_hold(&gadget->udc->connect_lock)
690+
/**
691+
* usb_gadget_connect - software-controlled connect to USB host
692+
* @gadget:the peripheral being connected
693+
*
694+
* Enables the D+ (or potentially D-) pullup. The host will start
695+
* enumerating this gadget when the pullup is active and a VBUS session
696+
* is active (the link is powered).
697+
*
698+
* Returns zero on success, else negative errno.
699+
*/
700+
int usb_gadget_connect(struct usb_gadget *gadget)
698701
{
699702
int ret = 0;
700703

@@ -703,12 +706,10 @@ static int usb_gadget_connect_locked(struct usb_gadget *gadget)
703706
goto out;
704707
}
705708

706-
if (gadget->deactivated || !gadget->udc->started) {
709+
if (gadget->deactivated) {
707710
/*
708711
* If gadget is deactivated we only save new state.
709712
* Gadget will be connected automatically after activation.
710-
*
711-
* udc first needs to be started before gadget can be pulled up.
712713
*/
713714
gadget->connected = true;
714715
goto out;
@@ -723,32 +724,22 @@ static int usb_gadget_connect_locked(struct usb_gadget *gadget)
723724

724725
return ret;
725726
}
727+
EXPORT_SYMBOL_GPL(usb_gadget_connect);
726728

727729
/**
728-
* usb_gadget_connect - software-controlled connect to USB host
729-
* @gadget:the peripheral being connected
730+
* usb_gadget_disconnect - software-controlled disconnect from USB host
731+
* @gadget:the peripheral being disconnected
730732
*
731-
* Enables the D+ (or potentially D-) pullup. The host will start
732-
* enumerating this gadget when the pullup is active and a VBUS session
733-
* is active (the link is powered).
733+
* Disables the D+ (or potentially D-) pullup, which the host may see
734+
* as a disconnect (when a VBUS session is active). Not all systems
735+
* support software pullup controls.
736+
*
737+
* Following a successful disconnect, invoke the ->disconnect() callback
738+
* for the current gadget driver so that UDC drivers don't need to.
734739
*
735740
* Returns zero on success, else negative errno.
736741
*/
737-
int usb_gadget_connect(struct usb_gadget *gadget)
738-
{
739-
int ret;
740-
741-
mutex_lock(&gadget->udc->connect_lock);
742-
ret = usb_gadget_connect_locked(gadget);
743-
mutex_unlock(&gadget->udc->connect_lock);
744-
745-
return ret;
746-
}
747-
EXPORT_SYMBOL_GPL(usb_gadget_connect);
748-
749-
/* Internal version of usb_gadget_disconnect needs to be called with connect_lock held. */
750-
static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
751-
__must_hold(&gadget->udc->connect_lock)
742+
int usb_gadget_disconnect(struct usb_gadget *gadget)
752743
{
753744
int ret = 0;
754745

@@ -760,12 +751,10 @@ static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
760751
if (!gadget->connected)
761752
goto out;
762753

763-
if (gadget->deactivated || !gadget->udc->started) {
754+
if (gadget->deactivated) {
764755
/*
765756
* If gadget is deactivated we only save new state.
766757
* Gadget will stay disconnected after activation.
767-
*
768-
* udc should have been started before gadget being pulled down.
769758
*/
770759
gadget->connected = false;
771760
goto out;
@@ -785,30 +774,6 @@ static int usb_gadget_disconnect_locked(struct usb_gadget *gadget)
785774

786775
return ret;
787776
}
788-
789-
/**
790-
* usb_gadget_disconnect - software-controlled disconnect from USB host
791-
* @gadget:the peripheral being disconnected
792-
*
793-
* Disables the D+ (or potentially D-) pullup, which the host may see
794-
* as a disconnect (when a VBUS session is active). Not all systems
795-
* support software pullup controls.
796-
*
797-
* Following a successful disconnect, invoke the ->disconnect() callback
798-
* for the current gadget driver so that UDC drivers don't need to.
799-
*
800-
* Returns zero on success, else negative errno.
801-
*/
802-
int usb_gadget_disconnect(struct usb_gadget *gadget)
803-
{
804-
int ret;
805-
806-
mutex_lock(&gadget->udc->connect_lock);
807-
ret = usb_gadget_disconnect_locked(gadget);
808-
mutex_unlock(&gadget->udc->connect_lock);
809-
810-
return ret;
811-
}
812777
EXPORT_SYMBOL_GPL(usb_gadget_disconnect);
813778

814779
/**
@@ -829,11 +794,10 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
829794
if (gadget->deactivated)
830795
goto out;
831796

832-
mutex_lock(&gadget->udc->connect_lock);
833797
if (gadget->connected) {
834-
ret = usb_gadget_disconnect_locked(gadget);
798+
ret = usb_gadget_disconnect(gadget);
835799
if (ret)
836-
goto unlock;
800+
goto out;
837801

838802
/*
839803
* If gadget was being connected before deactivation, we want
@@ -843,8 +807,6 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
843807
}
844808
gadget->deactivated = true;
845809

846-
unlock:
847-
mutex_unlock(&gadget->udc->connect_lock);
848810
out:
849811
trace_usb_gadget_deactivate(gadget, ret);
850812

@@ -868,16 +830,14 @@ int usb_gadget_activate(struct usb_gadget *gadget)
868830
if (!gadget->deactivated)
869831
goto out;
870832

871-
mutex_lock(&gadget->udc->connect_lock);
872833
gadget->deactivated = false;
873834

874835
/*
875836
* If gadget has been connected before deactivation, or became connected
876837
* while it was being deactivated, we call usb_gadget_connect().
877838
*/
878839
if (gadget->connected)
879-
ret = usb_gadget_connect_locked(gadget);
880-
mutex_unlock(&gadget->udc->connect_lock);
840+
ret = usb_gadget_connect(gadget);
881841

882842
out:
883843
trace_usb_gadget_activate(gadget, ret);
@@ -1118,13 +1078,12 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
11181078

11191079
/* ------------------------------------------------------------------------- */
11201080

1121-
/* Acquire connect_lock before calling this function. */
1122-
static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock)
1081+
static void usb_udc_connect_control(struct usb_udc *udc)
11231082
{
1124-
if (udc->vbus && udc->started)
1125-
usb_gadget_connect_locked(udc->gadget);
1083+
if (udc->vbus)
1084+
usb_gadget_connect(udc->gadget);
11261085
else
1127-
usb_gadget_disconnect_locked(udc->gadget);
1086+
usb_gadget_disconnect(udc->gadget);
11281087
}
11291088

11301089
/**
@@ -1140,12 +1099,10 @@ void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status)
11401099
{
11411100
struct usb_udc *udc = gadget->udc;
11421101

1143-
mutex_lock(&udc->connect_lock);
11441102
if (udc) {
11451103
udc->vbus = status;
1146-
usb_udc_connect_control_locked(udc);
1104+
usb_udc_connect_control(udc);
11471105
}
1148-
mutex_unlock(&udc->connect_lock);
11491106
}
11501107
EXPORT_SYMBOL_GPL(usb_udc_vbus_handler);
11511108

@@ -1167,7 +1124,7 @@ void usb_gadget_udc_reset(struct usb_gadget *gadget,
11671124
EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
11681125

11691126
/**
1170-
* usb_gadget_udc_start_locked - tells usb device controller to start up
1127+
* usb_gadget_udc_start - tells usb device controller to start up
11711128
* @udc: The UDC to be started
11721129
*
11731130
* This call is issued by the UDC Class driver when it's about
@@ -1178,11 +1135,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
11781135
* necessary to have it powered on.
11791136
*
11801137
* Returns zero on success, else negative errno.
1181-
*
1182-
* Caller should acquire connect_lock before invoking this function.
11831138
*/
1184-
static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
1185-
__must_hold(&udc->connect_lock)
1139+
static inline int usb_gadget_udc_start(struct usb_udc *udc)
11861140
{
11871141
int ret;
11881142

@@ -1199,7 +1153,7 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
11991153
}
12001154

12011155
/**
1202-
* usb_gadget_udc_stop_locked - tells usb device controller we don't need it anymore
1156+
* usb_gadget_udc_stop - tells usb device controller we don't need it anymore
12031157
* @udc: The UDC to be stopped
12041158
*
12051159
* This call is issued by the UDC Class driver after calling
@@ -1208,11 +1162,8 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc)
12081162
* The details are implementation specific, but it can go as
12091163
* far as powering off UDC completely and disable its data
12101164
* line pullups.
1211-
*
1212-
* Caller should acquire connect lock before invoking this function.
12131165
*/
1214-
static inline void usb_gadget_udc_stop_locked(struct usb_udc *udc)
1215-
__must_hold(&udc->connect_lock)
1166+
static inline void usb_gadget_udc_stop(struct usb_udc *udc)
12161167
{
12171168
if (!udc->started) {
12181169
dev_err(&udc->dev, "UDC had already stopped\n");
@@ -1371,7 +1322,6 @@ int usb_add_gadget(struct usb_gadget *gadget)
13711322

13721323
udc->gadget = gadget;
13731324
gadget->udc = udc;
1374-
mutex_init(&udc->connect_lock);
13751325

13761326
udc->started = false;
13771327

@@ -1573,15 +1523,11 @@ static int gadget_bind_driver(struct device *dev)
15731523
if (ret)
15741524
goto err_bind;
15751525

1576-
mutex_lock(&udc->connect_lock);
1577-
ret = usb_gadget_udc_start_locked(udc);
1578-
if (ret) {
1579-
mutex_unlock(&udc->connect_lock);
1526+
ret = usb_gadget_udc_start(udc);
1527+
if (ret)
15801528
goto err_start;
1581-
}
15821529
usb_gadget_enable_async_callbacks(udc);
1583-
usb_udc_connect_control_locked(udc);
1584-
mutex_unlock(&udc->connect_lock);
1530+
usb_udc_connect_control(udc);
15851531

15861532
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
15871533
return 0;
@@ -1612,14 +1558,12 @@ static void gadget_unbind_driver(struct device *dev)
16121558

16131559
kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE);
16141560

1615-
mutex_lock(&udc->connect_lock);
1616-
usb_gadget_disconnect_locked(gadget);
1561+
usb_gadget_disconnect(gadget);
16171562
usb_gadget_disable_async_callbacks(udc);
16181563
if (gadget->irq)
16191564
synchronize_irq(gadget->irq);
16201565
udc->driver->unbind(gadget);
1621-
usb_gadget_udc_stop_locked(udc);
1622-
mutex_unlock(&udc->connect_lock);
1566+
usb_gadget_udc_stop(udc);
16231567

16241568
mutex_lock(&udc_lock);
16251569
driver->is_bound = false;
@@ -1705,15 +1649,11 @@ static ssize_t soft_connect_store(struct device *dev,
17051649
}
17061650

17071651
if (sysfs_streq(buf, "connect")) {
1708-
mutex_lock(&udc->connect_lock);
1709-
usb_gadget_udc_start_locked(udc);
1710-
usb_gadget_connect_locked(udc->gadget);
1711-
mutex_unlock(&udc->connect_lock);
1652+
usb_gadget_udc_start(udc);
1653+
usb_gadget_connect(udc->gadget);
17121654
} else if (sysfs_streq(buf, "disconnect")) {
1713-
mutex_lock(&udc->connect_lock);
1714-
usb_gadget_disconnect_locked(udc->gadget);
1715-
usb_gadget_udc_stop_locked(udc);
1716-
mutex_unlock(&udc->connect_lock);
1655+
usb_gadget_disconnect(udc->gadget);
1656+
usb_gadget_udc_stop(udc);
17171657
} else {
17181658
dev_err(dev, "unsupported command '%s'\n", buf);
17191659
ret = -EINVAL;

0 commit comments

Comments
 (0)