Skip to content

Commit ed57b76

Browse files
Chandana Kishori Chiluverugregkh
authored andcommitted
usb: gadget: configfs: Preserve function ordering after bind failure
commit 6cd0fe9 upstream. When binding the ConfigFS gadget to a UDC, the functions in each configuration are added in list order. However, if usb_add_function() fails, the failed function is put back on its configuration's func_list and purge_configs_funcs() is called to further clean up. purge_configs_funcs() iterates over the configurations and functions in forward order, calling unbind() on each of the previously added functions. But after doing so, each function gets moved to the tail of the configuration's func_list. This results in reshuffling the original order of the functions within a configuration such that the failed function now appears first even though it may have originally appeared in the middle or even end of the list. At this point if the ConfigFS gadget is attempted to re-bind to the UDC, the functions will be added in a different order than intended, with the only recourse being to remove and relink the functions all over again. An example of this as follows: ln -s functions/mass_storage.0 configs/c.1 ln -s functions/ncm.0 configs/c.1 ln -s functions/ffs.adb configs/c.1 # oops, forgot to start adbd echo "<udc device>" > UDC # fails start adbd echo "<udc device>" > UDC # now succeeds, but... # bind order is # "ADB", mass_storage, ncm [30133.118289] configfs-gadget gadget: adding 'Mass Storage Function'/ffffff810af87200 to config 'c'/ffffff817d6a2520 [30133.119875] configfs-gadget gadget: adding 'cdc_network'/ffffff80f48d1a00 to config 'c'/ffffff817d6a2520 [30133.119974] using random self ethernet address [30133.120002] using random host ethernet address [30133.139604] usb0: HOST MAC 3e:27:46:ba:3e:26 [30133.140015] usb0: MAC 6e:28:7e:42:66:6a [30133.140062] configfs-gadget gadget: adding 'Function FS Gadget'/ffffff80f3868438 to config 'c'/ffffff817d6a2520 [30133.140081] configfs-gadget gadget: adding 'Function FS Gadget'/ffffff80f3868438 --> -19 [30133.140098] configfs-gadget gadget: unbind function 'Mass Storage Function'/ffffff810af87200 [30133.140119] configfs-gadget gadget: unbind function 'cdc_network'/ffffff80f48d1a00 [30133.173201] configfs-gadget a600000.dwc3: failed to start g1: -19 [30136.661933] init: starting service 'adbd'... [30136.700126] read descriptors [30136.700413] read strings [30138.574484] configfs-gadget gadget: adding 'Function FS Gadget'/ffffff80f3868438 to config 'c'/ffffff817d6a2520 [30138.575497] configfs-gadget gadget: adding 'Mass Storage Function'/ffffff810af87200 to config 'c'/ffffff817d6a2520 [30138.575554] configfs-gadget gadget: adding 'cdc_network'/ffffff80f48d1a00 to config 'c'/ffffff817d6a2520 [30138.575631] using random self ethernet address [30138.575660] using random host ethernet address [30138.595338] usb0: HOST MAC 2e:cf:43:cd:ca:c8 [30138.597160] usb0: MAC 6a:f0:9f:ee:82:a0 [30138.791490] configfs-gadget gadget: super-speed config #1: c Fix this by reversing the iteration order of the functions in purge_config_funcs() when unbinding them, and adding them back to the config's func_list at the head instead of the tail. This ensures that we unbind and unwind back to the original list order. Fixes: 88af8bb ("usb: gadget: the start of the configfs interface") Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org> Signed-off-by: Jack Pham <jackp@codeaurora.org> Reviewed-by: Peter Chen <peter.chen@nxp.com> Link: https://lore.kernel.org/r/20201229224443.31623-1-jackp@codeaurora.org Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8ca9626 commit ed57b76

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

drivers/usb/gadget/configfs.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,9 +1248,9 @@ static void purge_configs_funcs(struct gadget_info *gi)
12481248

12491249
cfg = container_of(c, struct config_usb_cfg, c);
12501250

1251-
list_for_each_entry_safe(f, tmp, &c->functions, list) {
1251+
list_for_each_entry_safe_reverse(f, tmp, &c->functions, list) {
12521252

1253-
list_move_tail(&f->list, &cfg->func_list);
1253+
list_move(&f->list, &cfg->func_list);
12541254
if (f->unbind) {
12551255
dev_dbg(&gi->cdev.gadget->dev,
12561256
"unbind function '%s'/%p\n",

0 commit comments

Comments
 (0)