From: Thinh Nguyen Date: Wed, 11 Dec 2024 00:34:03 +0000 (+0000) Subject: usb: gadget: f_tcm: Stall on invalid CBW X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=a4d7274d07ae4b3e77b3b35f46cab7c90b95ef21;p=users%2Fhch%2Fmisc.git usb: gadget: f_tcm: Stall on invalid CBW If the BOT command CBW is invalid, make sure to respond by setting status endpoint STALL until the next proper CBW or reset. Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/96022e2d5225f01a20263a4ba9c2e2c8a63328b8.1733876548.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c index 0c7a41568f40..7ea48845f8c3 100644 --- a/drivers/usb/gadget/function/f_tcm.c +++ b/drivers/usb/gadget/function/f_tcm.c @@ -287,8 +287,17 @@ static void bot_cmd_complete(struct usb_ep *ep, struct usb_request *req) return; ret = bot_submit_command(fu, req->buf, req->actual); - if (ret) + if (ret) { pr_err("%s(%d): %d\n", __func__, __LINE__, ret); + if (!(fu->flags & USBG_BOT_WEDGED)) + usb_ep_set_wedge(fu->ep_in); + + fu->flags |= USBG_BOT_WEDGED; + bot_enqueue_cmd_cbw(fu); + } else if (fu->flags & USBG_BOT_WEDGED) { + fu->flags &= ~USBG_BOT_WEDGED; + usb_ep_clear_halt(fu->ep_in); + } } static int bot_prepare_reqs(struct f_uas *fu) @@ -442,6 +451,11 @@ static int usbg_bot_setup(struct usb_function *f, case US_BULK_RESET_REQUEST: /* XXX maybe we should remove previous requests for IN + OUT */ + if (fu->flags & USBG_BOT_WEDGED) { + fu->flags &= ~USBG_BOT_WEDGED; + usb_ep_clear_halt(fu->ep_in); + } + bot_enqueue_cmd_cbw(fu); return 0; } diff --git a/drivers/usb/gadget/function/tcm.h b/drivers/usb/gadget/function/tcm.h index f6d6c86d10b3..009974d81d66 100644 --- a/drivers/usb/gadget/function/tcm.h +++ b/drivers/usb/gadget/function/tcm.h @@ -130,6 +130,7 @@ struct f_uas { #define USBG_USE_STREAMS (1 << 2) #define USBG_IS_BOT (1 << 3) #define USBG_BOT_CMD_PEND (1 << 4) +#define USBG_BOT_WEDGED (1 << 5) struct usbg_cdb cmd[USBG_NUM_CMDS]; struct usb_ep *ep_in;