After fsg_unbind() is called on UMS teardown, the fsg_main_thread() which also invokes handle_exception() is unlikely to run afterward. Therefore, any exceptions raised in fsg_unbind(), and also exceptions raised in fsg_common_release() which is called from both fsg_unbind() and fsg_common_init() fail path, will remain unhandled.
This leads to a problem where FSG_STATE_TERMINATED/EXIT handling is not performed on UMS exit and the do_set_interface(..., NULL) which shuts down endpoints is also not performed, leaving the endpoints enabled. The CI UDC driver does check for repeated enablement of endpoints and returns -EBUSY if an endpoint is enabled repeatedly. That prevents UMS from being started after it was exited once already. That is, running "ums 0 mmc 0 ; ums 0 mmc 0" on U-Boot command line will lead to one successful and one failed UMS session. The later session ends up triggering fsg_is_set() assertion in fsg_setup() and triggers a panic(). Fix this by synchronously invoking the do_set_interface() from both fsg_unbind() and fsg_common_release(). That makes the unbind behave as intended, as if the fsg_main_thread() ran after fsg_unbind() and handled the outstanding raised exceptions. Signed-off-by: Marek Vasut <[email protected]> --- Cc: Mattijs Korpershoek <[email protected]> Cc: Tom Rini <[email protected]> Cc: [email protected] --- drivers/usb/gadget/f_mass_storage.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 7eb667c130d..76ee08dc5e8 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2565,8 +2565,8 @@ static void fsg_common_release(struct fsg_common *common) { /* If the thread isn't already dead, tell it to exit now */ if (common->state != FSG_STATE_TERMINATED) { - raise_exception(common, FSG_STATE_EXIT); - wait_for_completion(&common->thread_notifier); + do_set_interface(common, NULL); + common->state = FSG_STATE_EXIT; } if (likely(common->luns)) { @@ -2647,8 +2647,8 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) DBG(fsg, "unbind\n"); if (fsg->common->fsg == fsg) { - fsg->common->new_fsg = NULL; - raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + do_set_interface(fsg->common, NULL); + fsg->common->state = FSG_STATE_CONFIG_CHANGE; } fsg_common_release(fsg->common); -- 2.53.0
