diff mbox series

usb: gadget: aspeed_udc: fix handling of tx_len == 0

Message ID YrMsU9HvdBm5YrRH@kili (mailing list archive)
State Superseded
Headers show
Series usb: gadget: aspeed_udc: fix handling of tx_len == 0 | expand

Commit Message

Dan Carpenter June 22, 2022, 2:50 p.m. UTC
The bug is that we should still enter this loop if "tx_len" is zero.

After adding the "last" variable, then the "chunk >= 0" condition is no
longer required but I left it for readability.

Reported-by: Neal Liu <neal_liu@aspeedtech.com>
Fixes: c09b1f372e74 ("usb: gadget: aspeed_udc: cleanup loop in ast_dma_descriptor_setup()")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
---
 drivers/usb/gadget/udc/aspeed_udc.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

Comments

Neal Liu June 23, 2022, 1:41 a.m. UTC | #1
> The bug is that we should still enter this loop if "tx_len" is zero.
> 
> After adding the "last" variable, then the "chunk >= 0" condition is no longer
> required but I left it for readability.
> 

Use either "chunk >=0" or "last".
I think the former is more simpler.

> Reported-by: Neal Liu <neal_liu@aspeedtech.com>
> Fixes: c09b1f372e74 ("usb: gadget: aspeed_udc: cleanup loop in
> ast_dma_descriptor_setup()")
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
> ---
>  drivers/usb/gadget/udc/aspeed_udc.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/usb/gadget/udc/aspeed_udc.c
> b/drivers/usb/gadget/udc/aspeed_udc.c
> index d75a4e070bf7..01968e2167f9 100644
> --- a/drivers/usb/gadget/udc/aspeed_udc.c
> +++ b/drivers/usb/gadget/udc/aspeed_udc.c
> @@ -476,6 +476,7 @@ static int ast_dma_descriptor_setup(struct ast_udc_ep
> *ep, u32 dma_buf,  {
>  	struct ast_udc_dev *udc = ep->udc;
>  	struct device *dev = &udc->pdev->dev;
> +	bool last = false;
>  	int chunk, count;
>  	u32 offset;
> 
> @@ -493,14 +494,16 @@ static int ast_dma_descriptor_setup(struct
> ast_udc_ep *ep, u32 dma_buf,
>  	       "tx_len", tx_len);
> 
>  	/* Create Descriptor Lists */
> -	while (chunk > 0 && count < AST_UDC_DESCS_COUNT) {
> +	while (chunk >= 0 && !last && count < AST_UDC_DESCS_COUNT) {
> 
>  		ep->descs[ep->descs_wptr].des_0 = dma_buf + offset;
> 
> -		if (chunk > ep->chunk_max)
> +		if (chunk > ep->chunk_max) {
>  			ep->descs[ep->descs_wptr].des_1 = ep->chunk_max;
> -		else
> +		} else {
>  			ep->descs[ep->descs_wptr].des_1 = chunk;
> +			last = true;
> +		}
> 
>  		chunk -= ep->chunk_max;
> 
> --
> 2.35.1
Dan Carpenter June 23, 2022, 6:43 a.m. UTC | #2
On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > The bug is that we should still enter this loop if "tx_len" is zero.
> > 
> > After adding the "last" variable, then the "chunk >= 0" condition is no longer
> > required but I left it for readability.
> > 
> 
> Use either "chunk >=0" or "last".
> I think the former is more simpler.

chunk >= 0 doesn't work.  last works but I think this way is more
readable.

regards,
dan carpenter
Dan Carpenter June 23, 2022, 7:22 a.m. UTC | #3
On Thu, Jun 23, 2022 at 09:43:20AM +0300, Dan Carpenter wrote:
> On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > > The bug is that we should still enter this loop if "tx_len" is zero.
> > > 
> > > After adding the "last" variable, then the "chunk >= 0" condition is no longer
> > > required but I left it for readability.
> > > 
> > 
> > Use either "chunk >=0" or "last".
> > I think the former is more simpler.
> 
> chunk >= 0 doesn't work.  last works but I think this way is more
> readable.

Fine, I can remove the chunk >= 0.  But you can see why your idea of
removing the "last" doesn't work, right?  I mean maybe it does work and
there was a bug in the original code?  Could you please look at that so
we're for sure writing correct code?

regards,
dan carpenter
Neal Liu June 23, 2022, 7:52 a.m. UTC | #4
> On Thu, Jun 23, 2022 at 09:43:20AM +0300, Dan Carpenter wrote:
> > On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > > > The bug is that we should still enter this loop if "tx_len" is zero.
> > > >
> > > > After adding the "last" variable, then the "chunk >= 0" condition
> > > > is no longer required but I left it for readability.
> > > >
> > >
> > > Use either "chunk >=0" or "last".
> > > I think the former is more simpler.
> >
> > chunk >= 0 doesn't work.  last works but I think this way is more
> > readable.
> 
> Fine, I can remove the chunk >= 0.  But you can see why your idea of
> removing the "last" doesn't work, right?  I mean maybe it does work and
> there was a bug in the original code?  Could you please look at that so we're
> for sure writing correct code?
> 

Why removing the "last" doesn't work? If "chunk == 0", it would go through while loop once, and chunk will be negative (chunk -= ep->chunk_max).

Best Regards,
-Neal
Dan Carpenter June 23, 2022, 7:55 a.m. UTC | #5
On Thu, Jun 23, 2022 at 07:52:28AM +0000, Neal Liu wrote:
> > On Thu, Jun 23, 2022 at 09:43:20AM +0300, Dan Carpenter wrote:
> > > On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > > > > The bug is that we should still enter this loop if "tx_len" is zero.
> > > > >
> > > > > After adding the "last" variable, then the "chunk >= 0" condition
> > > > > is no longer required but I left it for readability.
> > > > >
> > > >
> > > > Use either "chunk >=0" or "last".
> > > > I think the former is more simpler.
> > >
> > > chunk >= 0 doesn't work.  last works but I think this way is more
> > > readable.
> > 
> > Fine, I can remove the chunk >= 0.  But you can see why your idea of
> > removing the "last" doesn't work, right?  I mean maybe it does work and
> > there was a bug in the original code?  Could you please look at that so we're
> > for sure writing correct code?
> > 
> 
> Why removing the "last" doesn't work? If "chunk == 0", it would go through while loop once, and chunk will be negative (chunk -= ep->chunk_max).
> 

chunk -= ep->chunk_max could set chunk to zero.

regards,
dan carpenter
Neal Liu June 23, 2022, 8:37 a.m. UTC | #6
> On Thu, Jun 23, 2022 at 07:52:28AM +0000, Neal Liu wrote:
> > > On Thu, Jun 23, 2022 at 09:43:20AM +0300, Dan Carpenter wrote:
> > > > On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > > > > > The bug is that we should still enter this loop if "tx_len" is zero.
> > > > > >
> > > > > > After adding the "last" variable, then the "chunk >= 0"
> > > > > > condition is no longer required but I left it for readability.
> > > > > >
> > > > >
> > > > > Use either "chunk >=0" or "last".
> > > > > I think the former is more simpler.
> > > >
> > > > chunk >= 0 doesn't work.  last works but I think this way is more
> > > > readable.
> > >
> > > Fine, I can remove the chunk >= 0.  But you can see why your idea of
> > > removing the "last" doesn't work, right?  I mean maybe it does work
> > > and there was a bug in the original code?  Could you please look at
> > > that so we're for sure writing correct code?
> > >
> >
> > Why removing the "last" doesn't work? If "chunk == 0", it would go through
> while loop once, and chunk will be negative (chunk -= ep->chunk_max).
> >
> 
> chunk -= ep->chunk_max could set chunk to zero.
> 
Looks reasonable. Feel free to add:

Reviewed-by: Neal Liu <neal_liu@aspeedtech.com>

Thanks
Herrenschmidt, Benjamin June 24, 2022, 6:17 a.m. UTC | #7
On Thu, 2022-06-23 at 09:43 +0300, Dan Carpenter wrote:
> On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > > The bug is that we should still enter this loop if "tx_len" is
> > > zero.
> > > 
> > > After adding the "last" variable, then the "chunk >= 0" condition
> > > is no longer
> > > required but I left it for readability.
> > > 
> > 
> > Use either "chunk >=0" or "last".
> > I think the former is more simpler.
> 
> chunk >= 0 doesn't work.  last works but I think this way is more
> readable.

Hrm... what is that driver ? I've missed it ... is the code lifted from
aspeed-vhub ? If yes, should we instead make it a common code base ?
And if there are bug fixes on one they might apply to the other as
well...

Neal, is that "UDC" IP block the same that resides under the vhub ? If
yes then this really needs to be a common driver instead, using the
code existing in aspeed-vhub, simply making it able to work without a
parent vhub pointer.

Cheers,
Ben.
Dan Carpenter June 24, 2022, 6:34 a.m. UTC | #8
On Fri, Jun 24, 2022 at 06:17:31AM +0000, Herrenschmidt, Benjamin wrote:
> On Thu, 2022-06-23 at 09:43 +0300, Dan Carpenter wrote:
> > On Thu, Jun 23, 2022 at 01:41:49AM +0000, Neal Liu wrote:
> > > > The bug is that we should still enter this loop if "tx_len" is
> > > > zero.
> > > > 
> > > > After adding the "last" variable, then the "chunk >= 0" condition
> > > > is no longer
> > > > required but I left it for readability.
> > > > 
> > > 
> > > Use either "chunk >=0" or "last".
> > > I think the former is more simpler.
> > 
> > chunk >= 0 doesn't work.  last works but I think this way is more
> > readable.
> 
> Hrm... what is that driver ? I've missed it ... is the code lifted from
> aspeed-vhub ? If yes, should we instead make it a common code base ?
> And if there are bug fixes on one they might apply to the other as
> well...

No, I'm the person who introduced the bug so it's unique to this driver.

regards,
dan carpenter
Benjamin Herrenschmidt June 24, 2022, 6:39 a.m. UTC | #9
(switching back to my normal "community" email)

On Fri, 2022-06-24 at 09:34 +0300, Dan Carpenter wrote:
> > Hrm... what is that driver ? I've missed it ... is the code lifted
> > from
> > aspeed-vhub ? If yes, should we instead make it a common code base
> > ?
> > And if there are bug fixes on one they might apply to the other as
> > well...
> 
> 
> No, I'm the person who introduced the bug so it's unique to this
> driver.

Ok thanks. That said, the code looks fairly similar to the vhub code,
so my comment stands, if this is the same IP block, which it appears to
be, the driver should be common.

IE. The vhub is made of a virtual hub with a bunch of UDCs underneath,
this appears to address the ast2600 "new" standalone (no hub) variant
of said UDC if I'm not mistaken.

The way I structured the code in vhub, it shouldn't be overly difficult
to make it standalone. I wrote (and maintain) aspeed-vhub and would be
happy to work on this if I got sent an ast2600 board.

Cheers,
Ben.
Neal Liu June 24, 2022, 7:46 a.m. UTC | #10
> (switching back to my normal "community" email)
> 
> On Fri, 2022-06-24 at 09:34 +0300, Dan Carpenter wrote:
> > > Hrm... what is that driver ? I've missed it ... is the code lifted
> > > from aspeed-vhub ? If yes, should we instead make it a common code
> > > base ?
> > > And if there are bug fixes on one they might apply to the other as
> > > well...
> >
> >
> > No, I'm the person who introduced the bug so it's unique to this
> > driver.
> 
> Ok thanks. That said, the code looks fairly similar to the vhub code, so my
> comment stands, if this is the same IP block, which it appears to be, the driver
> should be common.
> 
> IE. The vhub is made of a virtual hub with a bunch of UDCs underneath, this
> appears to address the ast2600 "new" standalone (no hub) variant of said UDC
> if I'm not mistaken.
> 
> The way I structured the code in vhub, it shouldn't be overly difficult to make it
> standalone. I wrote (and maintain) aspeed-vhub and would be happy to work
> on this if I got sent an ast2600 board.
> 

Hi Ben, This UDC is the independent IP. The ast2600 board can run aspeed-vhub & aspeed_udc simultaneously with different USB port.
I think it's no need to restruct the code in vhub.
Benjamin Herrenschmidt June 27, 2022, 1:30 a.m. UTC | #11
On Fri, 2022-06-24 at 07:46 +0000, Neal Liu wrote:
> > 
> Hi Ben, This UDC is the independent IP. The ast2600 board can run
> aspeed-vhub & aspeed_udc simultaneously with different USB port.
> I think it's no need to restruct the code in vhub.

But is it a copy of the same base IP block ? IE, is the fundamental HW
interface of the independent UDC operating the same way with the same
register layout as one of the ports of the vHUB ?

I don't like having multiple drivers for the same hardware... if it's
different enough, then let's keep it separate, but if not, we should
definitely split the udc from the existing vhub code so that the same
driver can operate standalone or beneath a vhub. 

Cheers,
Ben.
Neal Liu June 28, 2022, 7:17 a.m. UTC | #12
> On Fri, 2022-06-24 at 07:46 +0000, Neal Liu wrote:
> > >
> > Hi Ben, This UDC is the independent IP. The ast2600 board can run
> > aspeed-vhub & aspeed_udc simultaneously with different USB port.
> > I think it's no need to restruct the code in vhub.
> 
> But is it a copy of the same base IP block ? IE, is the fundamental HW interface
> of the independent UDC operating the same way with the same register layout
> as one of the ports of the vHUB ?
> 
> I don't like having multiple drivers for the same hardware... if it's different
> enough, then let's keep it separate, but if not, we should definitely split the udc
> from the existing vhub code so that the same driver can operate standalone or
> beneath a vhub.
> 

Based on ast2600 hardware design, it's similar, but not exactly the same.
I need more time to extract the differences and evaluate it if it could utilize vhub.

> Cheers,
> Ben.
diff mbox series

Patch

diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
index d75a4e070bf7..01968e2167f9 100644
--- a/drivers/usb/gadget/udc/aspeed_udc.c
+++ b/drivers/usb/gadget/udc/aspeed_udc.c
@@ -476,6 +476,7 @@  static int ast_dma_descriptor_setup(struct ast_udc_ep *ep, u32 dma_buf,
 {
 	struct ast_udc_dev *udc = ep->udc;
 	struct device *dev = &udc->pdev->dev;
+	bool last = false;
 	int chunk, count;
 	u32 offset;
 
@@ -493,14 +494,16 @@  static int ast_dma_descriptor_setup(struct ast_udc_ep *ep, u32 dma_buf,
 	       "tx_len", tx_len);
 
 	/* Create Descriptor Lists */
-	while (chunk > 0 && count < AST_UDC_DESCS_COUNT) {
+	while (chunk >= 0 && !last && count < AST_UDC_DESCS_COUNT) {
 
 		ep->descs[ep->descs_wptr].des_0 = dma_buf + offset;
 
-		if (chunk > ep->chunk_max)
+		if (chunk > ep->chunk_max) {
 			ep->descs[ep->descs_wptr].des_1 = ep->chunk_max;
-		else
+		} else {
 			ep->descs[ep->descs_wptr].des_1 = chunk;
+			last = true;
+		}
 
 		chunk -= ep->chunk_max;