Linux USB
 help / color / mirror / Atom feed
* [PATCH 0/4] usb: gadget: dummy_hcd: fixes found while testing virtio-usb
@ 2026-08-07  7:54 Igor Skalkin
  2026-08-07  7:54 ` [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket Igor Skalkin
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Igor Skalkin @ 2026-08-07  7:54 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Alan Stern, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni, Igor Skalkin

This series fixes several bugs in dummy_hcd found while testing a
virtio-usb transport under a type-1 hypervisor, using two Linux VMs:

         host VM                            guest VM
    +----------------+                  +----------------+
    |    testusb     |                  |     g_zero     |
    +-------|--------+                  +--------^-------+
            v                                     |
    +----------------+                  +----------------+
    |   dummy_hcd    |                  |   dummy_hcd    |
    |  (host port)   |<---- virtio ---->| (virtual UDC)  |
    +----------------+                  +----------------+

Most of the failures we hit were in our own virtio-usb code, but
after switching the testing from HighSpeed to SuperSpeed a few
issues traced back to dummy_hcd itself:

 - patch 1 fixes an incorrect SuperSpeed ep0 maxpacket value
 - patch 2 fixes a false -EOVERFLOW reported for legitimate bounded
   IN completions
 - patch 3 fixes broken SG transfer handling when a URB is serviced
   across multiple chunks
 - patch 4 sets no_sg_constraint, since dummy_hcd has no hardware DMA
   alignment requirement and should not reject SG URBs based on
   maxpacket alignment

Igor Skalkin (4):
  usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket
  usb: gadget: dummy_hcd: fix false overflow on bounded IN
  usb: gadget: dummy_hcd: fix SG transfer handling across chunks
  usb: gadget: dummy_hcd: set no_sg_constraint on the host controller

 drivers/usb/gadget/udc/dummy_hcd.c | 72 +++++++++++++-----------------
 1 file changed, 30 insertions(+), 42 deletions(-)

-- 
2.49.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket
  2026-08-07  7:54 [PATCH 0/4] usb: gadget: dummy_hcd: fixes found while testing virtio-usb Igor Skalkin
@ 2026-08-07  7:54 ` Igor Skalkin
  2026-08-07 21:15   ` Alan Stern
  2026-08-07  7:54 ` [PATCH 2/4] usb: gadget: dummy_hcd: fix false overflow on bounded IN Igor Skalkin
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Igor Skalkin @ 2026-08-07  7:54 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Alan Stern, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni, Igor Skalkin

For USB_SPEED_SUPER, dummy_hcd sets ep0 maxpacket to 9.
That is incorrect for SuperSpeed ep0 and breaks short packet handling
in control transfer tests.

Set ep0 maxpacket to 512 for SuperSpeed.

Fixes: 1cd8fd2887e1 ("usb: gadget: dummy_hcd: add SuperSpeed support")
Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
---
 drivers/usb/gadget/udc/dummy_hcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index f47903461ed5..29f671c7b319 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -896,7 +896,7 @@ static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
 static void dummy_udc_update_ep0(struct dummy *dum)
 {
 	if (dum->gadget.speed == USB_SPEED_SUPER)
-		dum->ep[0].ep.maxpacket = 9;
+		dum->ep[0].ep.maxpacket = 512;
 	else
 		dum->ep[0].ep.maxpacket = 64;
 }
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] usb: gadget: dummy_hcd: fix false overflow on bounded IN
  2026-08-07  7:54 [PATCH 0/4] usb: gadget: dummy_hcd: fixes found while testing virtio-usb Igor Skalkin
  2026-08-07  7:54 ` [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket Igor Skalkin
@ 2026-08-07  7:54 ` Igor Skalkin
  2026-08-07 21:19   ` Alan Stern
  2026-08-07  7:54 ` [PATCH 3/4] usb: gadget: dummy_hcd: fix SG transfer handling across chunks Igor Skalkin
  2026-08-07  7:54 ` [PATCH 4/4] usb: gadget: dummy_hcd: set no_sg_constraint on the host controller Igor Skalkin
  3 siblings, 1 reply; 9+ messages in thread
From: Igor Skalkin @ 2026-08-07  7:54 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Alan Stern, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni, Igor Skalkin

In transfer(), the IN short-packet path reports -EOVERFLOW when
dev_len > host_len.

For IN transfers this is a valid bounded completion: the host asked for
host_len bytes and the transfer is limited by the host buffer. It is not
an overflow condition.

Treat bounded IN short completion as success.

This fixes spurious failures in usbtest bulk IN varying-length cases.

Assisted-by: OpenCode:claude-sonnet-5
Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
---
 drivers/usb/gadget/udc/dummy_hcd.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 29f671c7b319..5384806347ab 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -1486,11 +1486,13 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
 				req->req.status = 0;
 				*status = 0;
 			} else if (to_host) {
+				/*
+				 * Host requested fewer bytes than the gadget
+				 * request currently has pending. This is a
+				 * normal bounded IN transfer, not overflow.
+				 */
 				req->req.status = 0;
-				if (dev_len > host_len)
-					*status = -EOVERFLOW;
-				else
-					*status = 0;
+				*status = 0;
 			} else {
 				*status = 0;
 				if (host_len > dev_len)
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] usb: gadget: dummy_hcd: fix SG transfer handling across chunks
  2026-08-07  7:54 [PATCH 0/4] usb: gadget: dummy_hcd: fixes found while testing virtio-usb Igor Skalkin
  2026-08-07  7:54 ` [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket Igor Skalkin
  2026-08-07  7:54 ` [PATCH 2/4] usb: gadget: dummy_hcd: fix false overflow on bounded IN Igor Skalkin
@ 2026-08-07  7:54 ` Igor Skalkin
  2026-08-07 21:31   ` Alan Stern
  2026-08-07  7:54 ` [PATCH 4/4] usb: gadget: dummy_hcd: set no_sg_constraint on the host controller Igor Skalkin
  3 siblings, 1 reply; 9+ messages in thread
From: Igor Skalkin @ 2026-08-07  7:54 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Alan Stern, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni, Igor Skalkin

dummy_perform_transfer() may be called multiple times for the same URB
as the transfer is progressed in chunks.  The previous sg_miter-based
implementation kept iterator state in struct urbp between calls; on
resumed chunks sg_miter_next() would advance past the already-consumed
segment, causing -EINVAL and broken transfers.

Replace the stateful iterator with sg_miter_skip() to seek to the
correct SG position (urb->actual_length bytes in) on every call,
followed by a fresh manual walk for the requested chunk length.  This
makes each call self-contained and correct regardless of how many
partial transfers have already occurred.

Return -EINVAL if the total copied length does not match the requested
length (e.g. SG list exhausted prematurely).

Fixes: 14fce33a960a ("usb: gadget: dummy_hcd: add sg support")
Assisted-by: OpenCode:claude-sonnet-5
Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
---
 drivers/usb/gadget/udc/dummy_hcd.c | 59 +++++++++++-------------------
 1 file changed, 22 insertions(+), 37 deletions(-)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 5384806347ab..7597c9e9fa66 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -229,8 +229,6 @@ static const struct {
 struct urbp {
 	struct urb		*urb;
 	struct list_head	urbp_list;
-	struct sg_mapping_iter	miter;
-	u32			miter_started;
 };
 
 
@@ -1278,7 +1276,6 @@ static int dummy_urb_enqueue(
 	if (!urbp)
 		return -ENOMEM;
 	urbp->urb = urb;
-	urbp->miter_started = 0;
 
 	dum_hcd = hcd_to_dummy_hcd(hcd);
 	spin_lock_irqsave(&dum_hcd->dum->lock, flags);
@@ -1345,12 +1342,11 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
 		u32 len)
 {
 	void *ubuf, *rbuf;
-	struct urbp *urbp = urb->hcpriv;
 	int to_host;
-	struct sg_mapping_iter *miter = &urbp->miter;
 	u32 trans = 0;
-	u32 this_sg;
-	bool next_sg;
+	u32 req_len = len;
+	struct sg_mapping_iter miter;
+	u32 flags = SG_MITER_ATOMIC;
 
 	to_host = usb_urb_dir_in(urb);
 	rbuf = req->req.buf + req->req.actual;
@@ -1364,46 +1360,35 @@ static int dummy_perform_transfer(struct urb *urb, struct dummy_request *req,
 		return len;
 	}
 
-	if (!urbp->miter_started) {
-		u32 flags = SG_MITER_ATOMIC;
+	if (to_host)
+		flags |= SG_MITER_TO_SG;
+	else
+		flags |= SG_MITER_FROM_SG;
 
-		if (to_host)
-			flags |= SG_MITER_TO_SG;
-		else
-			flags |= SG_MITER_FROM_SG;
+	sg_miter_start(&miter, urb->sg, urb->num_sgs, flags);
 
-		sg_miter_start(miter, urb->sg, urb->num_sgs, flags);
-		urbp->miter_started = 1;
-	}
-	next_sg = sg_miter_next(miter);
-	if (next_sg == false) {
-		WARN_ON_ONCE(1);
+	if (!sg_miter_skip(&miter, urb->actual_length)) {
+		sg_miter_stop(&miter);
 		return -EINVAL;
 	}
-	do {
-		ubuf = miter->addr;
-		this_sg = min_t(u32, len, miter->length);
-		miter->consumed = this_sg;
-		trans += this_sg;
+
+	while (len && sg_miter_next(&miter)) {
+		u32 chunk = min_t(u32, len, miter.length);
 
 		if (to_host)
-			memcpy(ubuf, rbuf, this_sg);
+			memcpy(miter.addr, rbuf + trans, chunk);
 		else
-			memcpy(rbuf, ubuf, this_sg);
-		len -= this_sg;
+			memcpy(rbuf + trans, miter.addr, chunk);
+		miter.consumed = chunk;
+		trans += chunk;
+		len -= chunk;
+	}
 
-		if (!len)
-			break;
-		next_sg = sg_miter_next(miter);
-		if (next_sg == false) {
-			WARN_ON_ONCE(1);
-			return -EINVAL;
-		}
+	sg_miter_stop(&miter);
 
-		rbuf += this_sg;
-	} while (1);
+	if (unlikely(trans != req_len))
+		return -EINVAL;
 
-	sg_miter_stop(miter);
 	return trans;
 }
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] usb: gadget: dummy_hcd: set no_sg_constraint on the host controller
  2026-08-07  7:54 [PATCH 0/4] usb: gadget: dummy_hcd: fixes found while testing virtio-usb Igor Skalkin
                   ` (2 preceding siblings ...)
  2026-08-07  7:54 ` [PATCH 3/4] usb: gadget: dummy_hcd: fix SG transfer handling across chunks Igor Skalkin
@ 2026-08-07  7:54 ` Igor Skalkin
  2026-08-07 21:23   ` Alan Stern
  3 siblings, 1 reply; 9+ messages in thread
From: Igor Skalkin @ 2026-08-07  7:54 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Alan Stern, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni, Igor Skalkin

dummy_hcd copies data in software and has no hardware DMA alignment
requirement.  Set no_sg_constraint = 1 so the USB core does not reject
SG URBs whose non-final segments are not a multiple of the endpoint
maxpacket size.

For SuperSpeed bulk endpoints maxpacket is 1024 bytes; usbtest generates
SG lists with varying segment sizes (e.g. 512 bytes) that are valid
transfers but not maxpacket-aligned, causing usb_submit_urb to return
-EINVAL before the URB reaches the host controller.

Assisted-by: OpenCode:claude-sonnet-5
Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
---
 drivers/usb/gadget/udc/dummy_hcd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 7597c9e9fa66..2cfb1d035b34 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -2550,6 +2550,7 @@ static int dummy_setup(struct usb_hcd *hcd)
 
 	dum = *((void **)dev_get_platdata(hcd->self.controller));
 	hcd->self.sg_tablesize = ~0;
+	hcd->self.no_sg_constraint = 1;
 	if (usb_hcd_is_primary_hcd(hcd)) {
 		dum->hs_hcd = hcd_to_dummy_hcd(hcd);
 		dum->hs_hcd->dum = dum;
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket
  2026-08-07  7:54 ` [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket Igor Skalkin
@ 2026-08-07 21:15   ` Alan Stern
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Stern @ 2026-08-07 21:15 UTC (permalink / raw)
  To: Igor Skalkin
  Cc: Greg Kroah-Hartman, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni

On Fri, Aug 07, 2026 at 09:54:35AM +0200, Igor Skalkin wrote:
> For USB_SPEED_SUPER, dummy_hcd sets ep0 maxpacket to 9.
> That is incorrect for SuperSpeed ep0 and breaks short packet handling
> in control transfer tests.
> 
> Set ep0 maxpacket to 512 for SuperSpeed.
> 
> Fixes: 1cd8fd2887e1 ("usb: gadget: dummy_hcd: add SuperSpeed support")
> Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
> ---

Acked-by: Alan Stern <stern@rowland.harvard.edu>

>  drivers/usb/gadget/udc/dummy_hcd.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
> index f47903461ed5..29f671c7b319 100644
> --- a/drivers/usb/gadget/udc/dummy_hcd.c
> +++ b/drivers/usb/gadget/udc/dummy_hcd.c
> @@ -896,7 +896,7 @@ static int dummy_set_selfpowered(struct usb_gadget *_gadget, int value)
>  static void dummy_udc_update_ep0(struct dummy *dum)
>  {
>  	if (dum->gadget.speed == USB_SPEED_SUPER)
> -		dum->ep[0].ep.maxpacket = 9;
> +		dum->ep[0].ep.maxpacket = 512;
>  	else
>  		dum->ep[0].ep.maxpacket = 64;
>  }
> -- 
> 2.49.0
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/4] usb: gadget: dummy_hcd: fix false overflow on bounded IN
  2026-08-07  7:54 ` [PATCH 2/4] usb: gadget: dummy_hcd: fix false overflow on bounded IN Igor Skalkin
@ 2026-08-07 21:19   ` Alan Stern
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Stern @ 2026-08-07 21:19 UTC (permalink / raw)
  To: Igor Skalkin
  Cc: Greg Kroah-Hartman, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni

On Fri, Aug 07, 2026 at 09:54:36AM +0200, Igor Skalkin wrote:
> In transfer(), the IN short-packet path reports -EOVERFLOW when
> dev_len > host_len.
> 
> For IN transfers this is a valid bounded completion: the host asked for
> host_len bytes and the transfer is limited by the host buffer. It is not
> an overflow condition.

I don't know what you mean by this.  It is true that transfers are 
limited by the size of the host buffer.  Nevertheless, when a device 
tries to send a packet containing more data than the buffer can hold, 
the result is a -EOVERFLOW error, by definition.

If it weren't, what do you think _would_ constitute an overflow error?

> Treat bounded IN short completion as success.

Absolutely not.  This is completely wrong.  NAK.

> This fixes spurious failures in usbtest bulk IN varying-length cases.

What spurious failures?

Alan Stern

> 
> Assisted-by: OpenCode:claude-sonnet-5
> Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
> ---
>  drivers/usb/gadget/udc/dummy_hcd.c | 10 ++++++----
>  1 file changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
> index 29f671c7b319..5384806347ab 100644
> --- a/drivers/usb/gadget/udc/dummy_hcd.c
> +++ b/drivers/usb/gadget/udc/dummy_hcd.c
> @@ -1486,11 +1486,13 @@ static int transfer(struct dummy_hcd *dum_hcd, struct urb *urb,
>  				req->req.status = 0;
>  				*status = 0;
>  			} else if (to_host) {
> +				/*
> +				 * Host requested fewer bytes than the gadget
> +				 * request currently has pending. This is a
> +				 * normal bounded IN transfer, not overflow.
> +				 */
>  				req->req.status = 0;
> -				if (dev_len > host_len)
> -					*status = -EOVERFLOW;
> -				else
> -					*status = 0;
> +				*status = 0;
>  			} else {
>  				*status = 0;
>  				if (host_len > dev_len)
> -- 
> 2.49.0
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 4/4] usb: gadget: dummy_hcd: set no_sg_constraint on the host controller
  2026-08-07  7:54 ` [PATCH 4/4] usb: gadget: dummy_hcd: set no_sg_constraint on the host controller Igor Skalkin
@ 2026-08-07 21:23   ` Alan Stern
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Stern @ 2026-08-07 21:23 UTC (permalink / raw)
  To: Igor Skalkin
  Cc: Greg Kroah-Hartman, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni

On Fri, Aug 07, 2026 at 09:54:38AM +0200, Igor Skalkin wrote:
> dummy_hcd copies data in software and has no hardware DMA alignment
> requirement.  Set no_sg_constraint = 1 so the USB core does not reject
> SG URBs whose non-final segments are not a multiple of the endpoint
> maxpacket size.

It is true that dummy_hcd's software implementation has no inherent DMA 
alignment requirement.  But dummy_hcd is meant as a testing tool; it 
emulates real controllers some of which _do_ have alignment 
requirements.

> For SuperSpeed bulk endpoints maxpacket is 1024 bytes; usbtest generates
> SG lists with varying segment sizes (e.g. 512 bytes) that are valid
> transfers but not maxpacket-aligned, causing usb_submit_urb to return
> -EINVAL before the URB reaches the host controller.

This is the appropriate response when emulating, for example, an EHCI 
controller.

A better solution to the problem would be to set no_sg_constraint at 
runtime, according to whether the connection speed is SuperSpeed or 
faster.

Alan Stern

> Assisted-by: OpenCode:claude-sonnet-5
> Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
> ---
>  drivers/usb/gadget/udc/dummy_hcd.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
> index 7597c9e9fa66..2cfb1d035b34 100644
> --- a/drivers/usb/gadget/udc/dummy_hcd.c
> +++ b/drivers/usb/gadget/udc/dummy_hcd.c
> @@ -2550,6 +2550,7 @@ static int dummy_setup(struct usb_hcd *hcd)
>  
>  	dum = *((void **)dev_get_platdata(hcd->self.controller));
>  	hcd->self.sg_tablesize = ~0;
> +	hcd->self.no_sg_constraint = 1;
>  	if (usb_hcd_is_primary_hcd(hcd)) {
>  		dum->hs_hcd = hcd_to_dummy_hcd(hcd);
>  		dum->hs_hcd->dum = dum;
> -- 
> 2.49.0
> 

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] usb: gadget: dummy_hcd: fix SG transfer handling across chunks
  2026-08-07  7:54 ` [PATCH 3/4] usb: gadget: dummy_hcd: fix SG transfer handling across chunks Igor Skalkin
@ 2026-08-07 21:31   ` Alan Stern
  0 siblings, 0 replies; 9+ messages in thread
From: Alan Stern @ 2026-08-07 21:31 UTC (permalink / raw)
  To: Igor Skalkin
  Cc: Greg Kroah-Hartman, Felipe Balbi, Tatyana Brokhman, Kees Cook,
	Sebastian Andrzej Siewior, Sebastian Urban, Seungjin Bae,
	linux-usb, linux-kernel, Trilok Soni

On Fri, Aug 07, 2026 at 09:54:37AM +0200, Igor Skalkin wrote:
> dummy_perform_transfer() may be called multiple times for the same URB
> as the transfer is progressed in chunks.  The previous sg_miter-based
> implementation kept iterator state in struct urbp between calls; on
> resumed chunks sg_miter_next() would advance past the already-consumed
> segment, causing -EINVAL and broken transfers.

That definitely is a bug.

> Replace the stateful iterator with sg_miter_skip() to seek to the
> correct SG position (urb->actual_length bytes in) on every call,
> followed by a fresh manual walk for the requested chunk length.  This
> makes each call self-contained and correct regardless of how many
> partial transfers have already occurred.

Doesn't it make more sense to use sg_miter_skip() after each time part
of the mapping is consumed, so that the next iteration will start off
exactly where it needs to be?  That way you avoid the work, on each
iteration, of going back to the beginning and accounting for the
portion already used.

Alan Stern

> Return -EINVAL if the total copied length does not match the requested
> length (e.g. SG list exhausted prematurely).
> 
> Fixes: 14fce33a960a ("usb: gadget: dummy_hcd: add sg support")
> Assisted-by: OpenCode:claude-sonnet-5
> Signed-off-by: Igor Skalkin <igor.skalkin@oss.qualcomm.com>
> ---


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-08-07 21:31 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-07  7:54 [PATCH 0/4] usb: gadget: dummy_hcd: fixes found while testing virtio-usb Igor Skalkin
2026-08-07  7:54 ` [PATCH 1/4] usb: gadget: dummy_hcd: fix SuperSpeed ep0 maxpacket Igor Skalkin
2026-08-07 21:15   ` Alan Stern
2026-08-07  7:54 ` [PATCH 2/4] usb: gadget: dummy_hcd: fix false overflow on bounded IN Igor Skalkin
2026-08-07 21:19   ` Alan Stern
2026-08-07  7:54 ` [PATCH 3/4] usb: gadget: dummy_hcd: fix SG transfer handling across chunks Igor Skalkin
2026-08-07 21:31   ` Alan Stern
2026-08-07  7:54 ` [PATCH 4/4] usb: gadget: dummy_hcd: set no_sg_constraint on the host controller Igor Skalkin
2026-08-07 21:23   ` Alan Stern

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox