| From 3fbddac3c15330aba80e4318ba1172f900e41a6f Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 18 Jun 2020 21:07:33 +0900 |
| Subject: dmaengine: sh: usb-dmac: set tx_result parameters |
| |
| From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| |
| [ Upstream commit 466257d9968ac79575831250b039dc07566c7b13 ] |
| |
| A client driver (renesas_usbhs) assumed that |
| dmaengine_tx_status() could return the residue even if |
| the transfer was completed. However, this was not correct |
| usage [1] and this caused to break getting the residue after |
| the commit 24461d9792c2 ("dmaengine: virt-dma: Fix access after |
| free in vchan_complete()") actually. So, this is possible to get |
| wrong received size if the usb controller gets a short packet. |
| For example, g_zero driver causes "bad OUT byte" errors. |
| |
| To use the tx_result from the renesas_usbhs driver when |
| the transfer is completed, set the tx_result parameters. |
| |
| Notes that the renesas_usbhs driver needs to update for it. |
| |
| [1] |
| https://lore.kernel.org/dmaengine/20200616165550.GP2324254@vkoul-mobl/ |
| |
| Reported-by: Hien Dang <hien.dang.eb@renesas.com> |
| Fixes: 24461d9792c2 ("dmaengine: virt-dma: Fix access after free in vchan_complete()") |
| Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| Link: https://lore.kernel.org/r/1592482053-19433-1-git-send-email-yoshihiro.shimoda.uh@renesas.com |
| Signed-off-by: Vinod Koul <vkoul@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/dma/sh/usb-dmac.c | 2 ++ |
| 1 file changed, 2 insertions(+) |
| |
| diff --git a/drivers/dma/sh/usb-dmac.c b/drivers/dma/sh/usb-dmac.c |
| index b218a013c2600..8f7ceb698226c 100644 |
| --- a/drivers/dma/sh/usb-dmac.c |
| +++ b/drivers/dma/sh/usb-dmac.c |
| @@ -586,6 +586,8 @@ static void usb_dmac_isr_transfer_end(struct usb_dmac_chan *chan) |
| desc->residue = usb_dmac_get_current_residue(chan, desc, |
| desc->sg_index - 1); |
| desc->done_cookie = desc->vd.tx.cookie; |
| + desc->vd.tx_result.result = DMA_TRANS_NOERROR; |
| + desc->vd.tx_result.residue = desc->residue; |
| vchan_cookie_complete(&desc->vd); |
| |
| /* Restart the next transfer if this driver has a next desc */ |
| -- |
| 2.25.1 |
| |