From 1be4ae7011dfda269a9d3642d69a4b0daa639ea0 Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Fri, 22 Jul 2022 18:04:35 +0530 Subject: [PATCH] usb: gadget: cdev: Requeue the request in cser_resume if start_rx fails Consider a case where dut enters suspend before port_bridge is started. In that case, ep_queue in start_rx function fails as dut is in suspend mode. The expectation is that when host resumes the DUT, the request must be requeued in cser_resume as ep_queue of start_rx which was called earlier was a failure. Change-Id: I87015f00267af20450d625e2ea7a19a9de45c79a Signed-off-by: Rohith Kollalsi --- drivers/usb/gadget/function/f_cdev.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index 33d3a37dafd9..bef28623462d 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -138,6 +138,7 @@ struct f_cdev { unsigned long nbytes_from_port_bridge; struct dentry *debugfs_root; + bool setup_pending; /* To test remote wakeup using debugfs */ u8 debugfs_rw_enable; @@ -548,6 +549,7 @@ static int usb_cser_set_alt(struct usb_function *f, unsigned int intf, } static int port_notify_serial_state(struct cserial *cser); +static void usb_cser_start_rx(struct f_cdev *port); static void usb_cser_resume(struct usb_function *f) { @@ -566,6 +568,13 @@ static void usb_cser_resume(struct usb_function *f) port_notify_serial_state(&port->port_usb); spin_lock_irqsave(&port->port_lock, flags); + + /* process pending read request */ + if (port->setup_pending) { + pr_info("%s: start_rx called due to rx_out error.\n", __func__); + port->setup_pending = false; + usb_cser_start_rx(port); + } in = port->port_usb.in; /* process any pending requests */ list_for_each_entry_safe(req, t, &port->write_pending, list) { @@ -1055,7 +1064,10 @@ static void usb_cser_start_rx(struct f_cdev *port) pr_err("port(%d):%pK usb ep(%s) queue failed\n", port->port_num, port, ep->name); list_add(&req->list, pool); + port->setup_pending = true; break; + } else { + port->setup_pending = false; } }