Re: [PATCH v4] usbip: Don't submit special requests twice

From: Hongren Zheng
Date: Sun May 05 2024 - 11:32:09 EST


On Sun, Dec 17, 2023 at 08:30:40PM +0100, Simon Holesch wrote:
> Skip submitting URBs, when identical requests were already sent in
> tweak_special_requests(). Instead call the completion handler directly
> to return the result of the URB.

Reproduced the behavior and this patch fixed the bahavior

>
> Even though submitting those requests twice should be harmless, there
> are USB devices that react poorly to some duplicated requests.
>
> One example is the ChipIdea controller implementation in U-Boot: The
> second SET_CONFIURATION request makes U-Boot disable and re-enable all
> endpoints. Re-enabling an endpoint in the ChipIdea controller, however,
> was broken until U-Boot commit b272c8792502 ("usb: ci: Fix gadget
> reinit").
>
> Signed-off-by: Simon Holesch <simon@xxxxxxxxxx>
> Acked-by: Shuah Khan <skhan@xxxxxxxxxxxxxxxxxxx>
> ---

> /*
> @@ -468,6 +477,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
> int support_sg = 1;
> int np = 0;
> int ret, i;
> + int is_tweaked;
>
> if (pipe == -1)
> return;
> @@ -580,8 +590,7 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
> priv->urbs[i]->pipe = pipe;
> priv->urbs[i]->complete = stub_complete;
>
> - /* no need to submit an intercepted request, but harmless? */
> - tweak_special_requests(priv->urbs[i]);
> + is_tweaked = tweak_special_requests(priv->urbs[i]);

One question though, if there are mutiple urbs and one of them is
SET CONFIGURATION, then all of them would not be submitted,
as is_tweaked is a *global* flag instead of a per-urb flag.

Now it is assumed that when the urb is SET CONFIGURATION then
num_urbs is 1. I assume it just happens to be the case and I do
not know if it holds for all scenario.

>
> masking_bogus_flags(priv->urbs[i]);
> }
> @@ -594,22 +603,32 @@ static void stub_recv_cmd_submit(struct stub_device *sdev,
>
> /* urb is now ready to submit */
> for (i = 0; i < priv->num_urbs; i++) {
> - ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL);
> + if (!is_tweaked) {
> + ret = usb_submit_urb(priv->urbs[i], GFP_KERNEL);
>
> - if (ret == 0)
> - usbip_dbg_stub_rx("submit urb ok, seqnum %u\n",
> - pdu->base.seqnum);
> - else {
> - dev_err(&udev->dev, "submit_urb error, %d\n", ret);
> - usbip_dump_header(pdu);
> - usbip_dump_urb(priv->urbs[i]);
> + if (ret == 0)
> + usbip_dbg_stub_rx("submit urb ok, seqnum %u\n",
> + pdu->base.seqnum);
> + else {
> + dev_err(&udev->dev, "submit_urb error, %d\n", ret);
> + usbip_dump_header(pdu);
> + usbip_dump_urb(priv->urbs[i]);
>
> + /*
> + * Pessimistic.
> + * This connection will be discarded.
> + */
> + usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
> + break;
> + }
> + } else {
> /*
> - * Pessimistic.
> - * This connection will be discarded.
> + * An identical URB was already submitted in
> + * tweak_special_requests(). Skip submitting this URB to not
> + * duplicate the request.
> */
> - usbip_event_add(ud, SDEV_EVENT_ERROR_SUBMIT);
> - break;
> + priv->urbs[i]->status = 0;
> + stub_complete(priv->urbs[i]);
> }
> }
>
> --
> 2.43.0
>