usb reconnect issue in one ums session under u-boot for imx8mm

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

usb reconnect issue in one ums session under u-boot for imx8mm

2,159件の閲覧回数
xcr-619
Contributor I

Hi iMX8 experts,

I am running u-boot version "imx_v2020.04_5.4.70_2.3.0" for an imx8mm based board, I am tring to run "ums 0 mmc 2" to emulate the EMMC as an USB mass storage device to windows host, the emulated device can not be enabled(error code 10) on the windows host when I do reconnect cycle in one ums session. however, everything is okay before I plug-out the USB cable. I have to stop current ums session and start a new one once the USB cable disconnect. thus make the emulate device can not be remap to another virtual machine. could you please help on fixing this?

0 件の賞賛
返信
3 返答(返信)

2,136件の閲覧回数
AldoG
NXP TechSupport
NXP TechSupport

Hello,

Could you share the steps that you are following so I may replicate on my side?

Also, is it a custom board or are you trying with our EVK?

Best regards,
Aldo.

0 件の賞賛
返信

2,104件の閲覧回数
gyohng
Contributor I

Hi,

I don't know if this is the same problem I'm having...

It seems that u-boot has a bug, which prevents reconnection in the ums mode. I.e., if you run the ums command, you only get one shot at connecting the device. If the OS reinitialises the USB connection, or if you unplug and replug the cable - it won't negotiate.

I think this has to do with u-boot, as I tried with a different (non-NXP) platform just for the sake of testing it, and it behaves the same way.

In my case, it prevents me from connecting the UMS device to a virtual machine, as this implies double-initialisation (host first, VM Guest USB takeover), and this is where the ums mode fails.

Thanks,
George.

0 件の賞賛
返信

2,093件の閲覧回数
xcr-619
Contributor I

Yes, It's exactly the same issue with ci_udc driver, neither the gadget speed nor the status was not properly handled at reset state, we are luckly fixed this issue finally, here is the solution:

----------------------------------------------------------------------------------

--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -374,7 +374,12 @@
static int ci_ep_disable(struct usb_ep *ep)
{
struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep);
+ struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor;
+ const struct usb_endpoint_descriptor *desc = ep->desc;
+ int num;

+ num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
+ writel(0, &udc->epctrl[num]);
ci_ep->desc = NULL;
ep->desc = NULL;
return 0;
@@ -598,7 +603,10 @@
* check will save a lot of debugging time.
*/
printf("%s: ep0 transaction already in progress\n", __func__);
- return -EPROTO;
+ return -EINPROGRESS;
+ }
+ if (USB_SPEED_UNKNOWN == controller.gadget.speed) {
+ return -ESHUTDOWN;
}

ret = ci_bounce(ci_req, in);
@@ -786,6 +794,27 @@
writel((1<<16) | (1 << 0), &udc->epctrl[0]);
}

+void ci_nuke(struct ci_ep *ep, int status)
+{
+ struct ci_req *req;
+
+ while(!list_empty(&ep->queue)) {
+ req = list_first_entry(&ep->queue, struct ci_req, queue);
+ list_del_init(&req->queue);
+ req->req.status = status;
+ req->req.complete(&ep->ep, &req->req);
+ }
+ ep->req_primed = false;
+}
+
+static void throw_away_all_urb(struct ci_drv *cd)
+{
+ int i;
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ ci_nuke(&cd->ep[i], -ECONNRESET);
+ }
+}
+
static void stop_activity(void)
{
int i, num, in;
@@ -820,6 +849,7 @@
unsigned n = readl(&udc->usbsts);
writel(n, &udc->usbsts);
int bit, i, num, in;
+ int speed = USB_SPEED_UNKNOWN;

n &= (STS_SLI | STS_URI | STS_PCI | STS_UI | STS_UEI);
if (n == 0)
@@ -827,14 +857,21 @@

if (n & STS_URI) {
DBG("-- reset --\n");
+ controller.gadget.speed = speed;
stop_activity();
+ throw_away_all_urb(&controller);
+ if (controller.driver)
+ controller.driver->reset(&controller.gadget);
+ return;
}
- if (n & STS_SLI)
+ if (n & STS_SLI) {
+ if (controller.driver)
+ controller.driver->suspend(&controller.gadget);
DBG("-- suspend --\n");
-
+ }
if (n & STS_PCI) {
int max = 64;
- int speed = USB_SPEED_FULL;
+

#ifdef CONFIG_CI_UDC_HAS_HOSTPC
bit = (readl(&udc->hostpc1_devlc) >> 25) & 3;
@@ -842,15 +879,22 @@
bit = (readl(&udc->portsc) >> 26) & 3;
#endif
DBG("-- portchange %x %s\n", bit, (bit == 2) ? "High" : "Full");
- if (bit == 2) {
- speed = USB_SPEED_HIGH;
- max = 512;
+ if (3 == bit) {
+ if (controller.driver)
+ controller.driver->disconnect(&controller.gadget);
+ } else {
+ if (bit == 2) {
+ speed = USB_SPEED_HIGH;
+ max = 512;
+ } else {
+ speed = USB_SPEED_FULL;
+ }
+ for (i = 1; i < NUM_ENDPOINTS; i++) {
+ if (controller.ep[i].ep.maxpacket > max)
+ controller.ep[i].ep.maxpacket = max;
+ }
}
controller.gadget.speed = speed;
- for (i = 1; i < NUM_ENDPOINTS; i++) {
- if (controller.ep[i].ep.maxpacket > max)
- controller.ep[i].ep.maxpacket = max;
- }
}

if (n & STS_UEI)
--- a/drivers/usb/gadget/f_mass_storage.c
+++ b/drivers/usb/gadget/f_mass_storage.c
@@ -2052,7 +2052,13 @@
struct fsg_common *common = fsg->common;

/* Was this a real packet? Should it be ignored? */
- if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
+ if (req->status) {
+ if (-ECONNRESET == req->status)
+ return 0;
+ return -EINVAL;
+ }
+
+ if (test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags))
return -EINVAL;

/* Is the CBW valid? */
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -292,7 +292,7 @@
u8 *data = req->buf;
u8 report = data[0];

- if (status != 0) {
+ if ((status) && (-EINPROGRESS != status)) {
pr_err("Status: %d\n", status);
return;
}
@@ -378,7 +378,7 @@
u8 report = data[0];
int datalen = req->actual - 1;

- if (status != 0) {
+ if ((status) && (-EINPROGRESS != status)) {
pr_err("Status: %d\n", status);
return;
}
@@ -431,7 +431,7 @@
struct f_sdp *sdp = req->context;
int status = req->status;

- if (status != 0) {
+ if ((status) && (-EINPROGRESS != status)) {
pr_err("Status: %d\n", status);
return;
}

0 件の賞賛
返信