@@ -40,6 +40,11 @@ static const struct bus_type gadget_bus_type;
40
40
* @allow_connect: Indicates whether UDC is allowed to be pulled up.
41
41
* Set/cleared by gadget_(un)bind_driver() after gadget driver is bound or
42
42
* unbound.
43
+ * @connect_lock: protects udc->started, gadget->connect,
44
+ * gadget->allow_connect and gadget->deactivate. The routines
45
+ * usb_gadget_connect_locked(), usb_gadget_disconnect_locked(),
46
+ * usb_udc_connect_control_locked(), usb_gadget_udc_start_locked() and
47
+ * usb_gadget_udc_stop_locked() are called with this lock held.
43
48
*
44
49
* This represents the internal data structure which is used by the UDC-class
45
50
* to hold information about udc driver and gadget together.
@@ -53,6 +58,7 @@ struct usb_udc {
53
58
bool started ;
54
59
bool allow_connect ;
55
60
struct work_struct vbus_work ;
61
+ struct mutex connect_lock ;
56
62
};
57
63
58
64
static struct class * udc_class ;
@@ -692,17 +698,8 @@ int usb_gadget_vbus_disconnect(struct usb_gadget *gadget)
692
698
}
693
699
EXPORT_SYMBOL_GPL (usb_gadget_vbus_disconnect );
694
700
695
- /**
696
- * usb_gadget_connect - software-controlled connect to USB host
697
- * @gadget:the peripheral being connected
698
- *
699
- * Enables the D+ (or potentially D-) pullup. The host will start
700
- * enumerating this gadget when the pullup is active and a VBUS session
701
- * is active (the link is powered).
702
- *
703
- * Returns zero on success, else negative errno.
704
- */
705
- int usb_gadget_connect (struct usb_gadget * gadget )
701
+ static int usb_gadget_connect_locked (struct usb_gadget * gadget )
702
+ __must_hold (& gadget - > udc - > connect_lock )
706
703
{
707
704
int ret = 0 ;
708
705
@@ -711,10 +708,12 @@ int usb_gadget_connect(struct usb_gadget *gadget)
711
708
goto out ;
712
709
}
713
710
714
- if (gadget -> deactivated || !gadget -> udc -> allow_connect ) {
711
+ if (gadget -> deactivated || !gadget -> udc -> allow_connect || ! gadget -> udc -> started ) {
715
712
/*
716
- * If gadget is deactivated we only save new state.
717
- * Gadget will be connected automatically after activation.
713
+ * If the gadget isn't usable (because it is deactivated,
714
+ * unbound, or not yet started), we only save the new state.
715
+ * The gadget will be connected automatically when it is
716
+ * activated/bound/started.
718
717
*/
719
718
gadget -> connected = true;
720
719
goto out ;
@@ -729,22 +728,31 @@ int usb_gadget_connect(struct usb_gadget *gadget)
729
728
730
729
return ret ;
731
730
}
732
- EXPORT_SYMBOL_GPL (usb_gadget_connect );
733
731
734
732
/**
735
- * usb_gadget_disconnect - software-controlled disconnect from USB host
736
- * @gadget:the peripheral being disconnected
737
- *
738
- * Disables the D+ (or potentially D-) pullup, which the host may see
739
- * as a disconnect (when a VBUS session is active). Not all systems
740
- * support software pullup controls.
733
+ * usb_gadget_connect - software-controlled connect to USB host
734
+ * @gadget:the peripheral being connected
741
735
*
742
- * Following a successful disconnect, invoke the ->disconnect() callback
743
- * for the current gadget driver so that UDC drivers don't need to.
736
+ * Enables the D+ (or potentially D-) pullup. The host will start
737
+ * enumerating this gadget when the pullup is active and a VBUS session
738
+ * is active (the link is powered).
744
739
*
745
740
* Returns zero on success, else negative errno.
746
741
*/
747
- int usb_gadget_disconnect (struct usb_gadget * gadget )
742
+ int usb_gadget_connect (struct usb_gadget * gadget )
743
+ {
744
+ int ret ;
745
+
746
+ mutex_lock (& gadget -> udc -> connect_lock );
747
+ ret = usb_gadget_connect_locked (gadget );
748
+ mutex_unlock (& gadget -> udc -> connect_lock );
749
+
750
+ return ret ;
751
+ }
752
+ EXPORT_SYMBOL_GPL (usb_gadget_connect );
753
+
754
+ static int usb_gadget_disconnect_locked (struct usb_gadget * gadget )
755
+ __must_hold (& gadget - > udc - > connect_lock )
748
756
{
749
757
int ret = 0 ;
750
758
@@ -756,7 +764,7 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
756
764
if (!gadget -> connected )
757
765
goto out ;
758
766
759
- if (gadget -> deactivated ) {
767
+ if (gadget -> deactivated || ! gadget -> udc -> started ) {
760
768
/*
761
769
* If gadget is deactivated we only save new state.
762
770
* Gadget will stay disconnected after activation.
@@ -779,6 +787,30 @@ int usb_gadget_disconnect(struct usb_gadget *gadget)
779
787
780
788
return ret ;
781
789
}
790
+
791
+ /**
792
+ * usb_gadget_disconnect - software-controlled disconnect from USB host
793
+ * @gadget:the peripheral being disconnected
794
+ *
795
+ * Disables the D+ (or potentially D-) pullup, which the host may see
796
+ * as a disconnect (when a VBUS session is active). Not all systems
797
+ * support software pullup controls.
798
+ *
799
+ * Following a successful disconnect, invoke the ->disconnect() callback
800
+ * for the current gadget driver so that UDC drivers don't need to.
801
+ *
802
+ * Returns zero on success, else negative errno.
803
+ */
804
+ int usb_gadget_disconnect (struct usb_gadget * gadget )
805
+ {
806
+ int ret ;
807
+
808
+ mutex_lock (& gadget -> udc -> connect_lock );
809
+ ret = usb_gadget_disconnect_locked (gadget );
810
+ mutex_unlock (& gadget -> udc -> connect_lock );
811
+
812
+ return ret ;
813
+ }
782
814
EXPORT_SYMBOL_GPL (usb_gadget_disconnect );
783
815
784
816
/**
@@ -796,13 +828,14 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
796
828
{
797
829
int ret = 0 ;
798
830
831
+ mutex_lock (& gadget -> udc -> connect_lock );
799
832
if (gadget -> deactivated )
800
- goto out ;
833
+ goto unlock ;
801
834
802
835
if (gadget -> connected ) {
803
- ret = usb_gadget_disconnect (gadget );
836
+ ret = usb_gadget_disconnect_locked (gadget );
804
837
if (ret )
805
- goto out ;
838
+ goto unlock ;
806
839
807
840
/*
808
841
* If gadget was being connected before deactivation, we want
@@ -812,7 +845,8 @@ int usb_gadget_deactivate(struct usb_gadget *gadget)
812
845
}
813
846
gadget -> deactivated = true;
814
847
815
- out :
848
+ unlock :
849
+ mutex_unlock (& gadget -> udc -> connect_lock );
816
850
trace_usb_gadget_deactivate (gadget , ret );
817
851
818
852
return ret ;
@@ -832,8 +866,9 @@ int usb_gadget_activate(struct usb_gadget *gadget)
832
866
{
833
867
int ret = 0 ;
834
868
869
+ mutex_lock (& gadget -> udc -> connect_lock );
835
870
if (!gadget -> deactivated )
836
- goto out ;
871
+ goto unlock ;
837
872
838
873
gadget -> deactivated = false;
839
874
@@ -842,9 +877,11 @@ int usb_gadget_activate(struct usb_gadget *gadget)
842
877
* while it was being deactivated, we call usb_gadget_connect().
843
878
*/
844
879
if (gadget -> connected )
845
- ret = usb_gadget_connect (gadget );
880
+ ret = usb_gadget_connect_locked (gadget );
881
+ mutex_unlock (& gadget -> udc -> connect_lock );
846
882
847
- out :
883
+ unlock :
884
+ mutex_unlock (& gadget -> udc -> connect_lock );
848
885
trace_usb_gadget_activate (gadget , ret );
849
886
850
887
return ret ;
@@ -1083,19 +1120,22 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state);
1083
1120
1084
1121
/* ------------------------------------------------------------------------- */
1085
1122
1086
- static void usb_udc_connect_control (struct usb_udc * udc )
1123
+ /* Acquire connect_lock before calling this function. */
1124
+ static void usb_udc_connect_control_locked (struct usb_udc * udc ) __must_hold (& udc - > connect_lock )
1087
1125
{
1088
1126
if (udc -> vbus )
1089
- usb_gadget_connect (udc -> gadget );
1127
+ usb_gadget_connect_locked (udc -> gadget );
1090
1128
else
1091
- usb_gadget_disconnect (udc -> gadget );
1129
+ usb_gadget_disconnect_locked (udc -> gadget );
1092
1130
}
1093
1131
1094
1132
static void vbus_event_work (struct work_struct * work )
1095
1133
{
1096
1134
struct usb_udc * udc = container_of (work , struct usb_udc , vbus_work );
1097
1135
1098
- usb_udc_connect_control (udc );
1136
+ mutex_lock (& udc -> connect_lock );
1137
+ usb_udc_connect_control_locked (udc );
1138
+ mutex_unlock (& udc -> connect_lock );
1099
1139
}
1100
1140
1101
1141
/**
@@ -1144,7 +1184,7 @@ void usb_gadget_udc_reset(struct usb_gadget *gadget,
1144
1184
EXPORT_SYMBOL_GPL (usb_gadget_udc_reset );
1145
1185
1146
1186
/**
1147
- * usb_gadget_udc_start - tells usb device controller to start up
1187
+ * usb_gadget_udc_start_locked - tells usb device controller to start up
1148
1188
* @udc: The UDC to be started
1149
1189
*
1150
1190
* This call is issued by the UDC Class driver when it's about
@@ -1155,8 +1195,11 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset);
1155
1195
* necessary to have it powered on.
1156
1196
*
1157
1197
* Returns zero on success, else negative errno.
1198
+ *
1199
+ * Caller should acquire connect_lock before invoking this function.
1158
1200
*/
1159
- static inline int usb_gadget_udc_start (struct usb_udc * udc )
1201
+ static inline int usb_gadget_udc_start_locked (struct usb_udc * udc )
1202
+ __must_hold (& udc - > connect_lock )
1160
1203
{
1161
1204
int ret ;
1162
1205
@@ -1173,7 +1216,7 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc)
1173
1216
}
1174
1217
1175
1218
/**
1176
- * usb_gadget_udc_stop - tells usb device controller we don't need it anymore
1219
+ * usb_gadget_udc_stop_locked - tells usb device controller we don't need it anymore
1177
1220
* @udc: The UDC to be stopped
1178
1221
*
1179
1222
* This call is issued by the UDC Class driver after calling
@@ -1182,8 +1225,11 @@ static inline int usb_gadget_udc_start(struct usb_udc *udc)
1182
1225
* The details are implementation specific, but it can go as
1183
1226
* far as powering off UDC completely and disable its data
1184
1227
* line pullups.
1228
+ *
1229
+ * Caller should acquire connect lock before invoking this function.
1185
1230
*/
1186
- static inline void usb_gadget_udc_stop (struct usb_udc * udc )
1231
+ static inline void usb_gadget_udc_stop_locked (struct usb_udc * udc )
1232
+ __must_hold (& udc - > connect_lock )
1187
1233
{
1188
1234
if (!udc -> started ) {
1189
1235
dev_err (& udc -> dev , "UDC had already stopped\n" );
@@ -1342,6 +1388,7 @@ int usb_add_gadget(struct usb_gadget *gadget)
1342
1388
1343
1389
udc -> gadget = gadget ;
1344
1390
gadget -> udc = udc ;
1391
+ mutex_init (& udc -> connect_lock );
1345
1392
1346
1393
udc -> started = false;
1347
1394
@@ -1545,12 +1592,16 @@ static int gadget_bind_driver(struct device *dev)
1545
1592
if (ret )
1546
1593
goto err_bind ;
1547
1594
1548
- ret = usb_gadget_udc_start (udc );
1549
- if (ret )
1595
+ mutex_lock (& udc -> connect_lock );
1596
+ ret = usb_gadget_udc_start_locked (udc );
1597
+ if (ret ) {
1598
+ mutex_unlock (& udc -> connect_lock );
1550
1599
goto err_start ;
1600
+ }
1551
1601
usb_gadget_enable_async_callbacks (udc );
1552
1602
udc -> allow_connect = true;
1553
- usb_udc_connect_control (udc );
1603
+ usb_udc_connect_control_locked (udc );
1604
+ mutex_unlock (& udc -> connect_lock );
1554
1605
1555
1606
kobject_uevent (& udc -> dev .kobj , KOBJ_CHANGE );
1556
1607
return 0 ;
@@ -1583,12 +1634,14 @@ static void gadget_unbind_driver(struct device *dev)
1583
1634
1584
1635
udc -> allow_connect = false;
1585
1636
cancel_work_sync (& udc -> vbus_work );
1586
- usb_gadget_disconnect (gadget );
1637
+ mutex_lock (& udc -> connect_lock );
1638
+ usb_gadget_disconnect_locked (gadget );
1587
1639
usb_gadget_disable_async_callbacks (udc );
1588
1640
if (gadget -> irq )
1589
1641
synchronize_irq (gadget -> irq );
1590
1642
udc -> driver -> unbind (gadget );
1591
- usb_gadget_udc_stop (udc );
1643
+ usb_gadget_udc_stop_locked (udc );
1644
+ mutex_unlock (& udc -> connect_lock );
1592
1645
1593
1646
mutex_lock (& udc_lock );
1594
1647
driver -> is_bound = false;
@@ -1674,11 +1727,15 @@ static ssize_t soft_connect_store(struct device *dev,
1674
1727
}
1675
1728
1676
1729
if (sysfs_streq (buf , "connect" )) {
1677
- usb_gadget_udc_start (udc );
1678
- usb_gadget_connect (udc -> gadget );
1730
+ mutex_lock (& udc -> connect_lock );
1731
+ usb_gadget_udc_start_locked (udc );
1732
+ usb_gadget_connect_locked (udc -> gadget );
1733
+ mutex_unlock (& udc -> connect_lock );
1679
1734
} else if (sysfs_streq (buf , "disconnect" )) {
1680
- usb_gadget_disconnect (udc -> gadget );
1681
- usb_gadget_udc_stop (udc );
1735
+ mutex_lock (& udc -> connect_lock );
1736
+ usb_gadget_disconnect_locked (udc -> gadget );
1737
+ usb_gadget_udc_stop_locked (udc );
1738
+ mutex_unlock (& udc -> connect_lock );
1682
1739
} else {
1683
1740
dev_err (dev , "unsupported command '%s'\n" , buf );
1684
1741
ret = - EINVAL ;
0 commit comments