[PATCH] fastboot: release usb_gadget on reboot commands

Mattijs Korpershoek mkorpershoek at baylibre.com
Thu Jul 21 15:59:55 CEST 2022


When host issues "fastboot reboot fastboot", it's expected that the
board drops the USB connection before resetting.

On some boards, such as Khadas VIM3L and SEI610, this is not the case.

We observe the following error:
$ fastboot reboot fastboot
Rebooting into fastboot                            OKAY [  0.004s]
fastboot: error: Failed to boot into userspace fastboot; one or more components might be unbootable.

This does not happen when we use the RST button on the board, nor
in linux. We might hit a undefined hardware behavior, where D+ and D-
are in an unknown state.

Change the logic in cmd/fastboot.c to do a "reset request" instead of
actually calling reset. This allows us to get out of the infinite loop
in fastboot.c, de-initialize the usb stack and do a clean reset.

Signed-off-by: Mattijs Korpershoek <mkorpershoek at baylibre.com>
---
 cmd/fastboot.c                  |  3 +++
 drivers/usb/gadget/f_fastboot.c |  3 ++-
 drivers/usb/gadget/g_dnl.c      | 17 +++++++++++++++++
 include/g_dnl.h                 |  5 +++++
 4 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/cmd/fastboot.c b/cmd/fastboot.c
index 033a2c95e8f0..97ce311e6d9b 100644
--- a/cmd/fastboot.c
+++ b/cmd/fastboot.c
@@ -87,6 +87,9 @@ exit:
 	g_dnl_clear_detach();
 	usb_gadget_release(controller_index);
 
+	if (g_dnl_should_reset())
+		do_reset(NULL, 0, 0, NULL);
+
 	return ret;
 #else
 	pr_err("Fastboot USB not enabled\n");
diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c
index 8ba55aab9f8f..a00d1ca571d1 100644
--- a/drivers/usb/gadget/f_fastboot.c
+++ b/drivers/usb/gadget/f_fastboot.c
@@ -420,7 +420,8 @@ static int fastboot_tx_write_str(const char *buffer)
 
 static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
 {
-	do_reset(NULL, 0, 0, NULL);
+	g_dnl_trigger_detach();
+	g_dnl_trigger_reset_request();
 }
 
 static unsigned int rx_bytes_expected(struct usb_ep *ep)
diff --git a/drivers/usb/gadget/g_dnl.c b/drivers/usb/gadget/g_dnl.c
index afb7b74f3057..d083a214290d 100644
--- a/drivers/usb/gadget/g_dnl.c
+++ b/drivers/usb/gadget/g_dnl.c
@@ -200,6 +200,23 @@ void g_dnl_clear_detach(void)
 	g_dnl_detach_request = false;
 }
 
+static bool g_dnl_reset_request;
+
+bool g_dnl_should_reset(void)
+{
+	return g_dnl_reset_request;
+}
+
+void g_dnl_trigger_reset_request(void)
+{
+	g_dnl_reset_request = true;
+}
+
+void g_dnl_clear_reset_request(void)
+{
+	g_dnl_reset_request = false;
+}
+
 static int g_dnl_get_bcd_device_number(struct usb_composite_dev *cdev)
 {
 	struct usb_gadget *gadget = cdev->gadget;
diff --git a/include/g_dnl.h b/include/g_dnl.h
index 836ee602c8da..95c772385fa6 100644
--- a/include/g_dnl.h
+++ b/include/g_dnl.h
@@ -43,6 +43,11 @@ void g_dnl_set_product(const char *s);
 bool g_dnl_detach(void);
 void g_dnl_trigger_detach(void);
 void g_dnl_clear_detach(void);
+
+bool g_dnl_should_reset(void);
+void g_dnl_trigger_reset_request(void);
+void g_dnl_clear_reset_request(void);
+
 int run_usb_dnl_gadget(int usbctrl_index, char *usb_dnl_gadget);
 
 #endif /* __G_DOWNLOAD_H_ */
-- 
2.36.1



More information about the U-Boot mailing list