[PATCH] omap_udc dma off-by-one fix
The change to make DMA work two bytes at a time omitted an important tweak that affects the file_storage gadget: it needs to recognize when the host writes an odd number of bytes. (The network layer ignores such extra bytes.) This patch resolves that issue by checking the relevant bit and adjusting the rx byte count, so that for example a legal 13 byte request doesn't morph into an illegal 14 byte one any more. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
1fcb4454cb
commit
cb97c5c9d0
|
@ -691,7 +691,7 @@ static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
|
finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status, int one)
|
||||||
{
|
{
|
||||||
u16 count;
|
u16 count;
|
||||||
|
|
||||||
|
@ -699,6 +699,8 @@ finish_out_dma(struct omap_ep *ep, struct omap_req *req, int status)
|
||||||
ep->dma_counter = (u16) (req->req.dma + req->req.actual);
|
ep->dma_counter = (u16) (req->req.dma + req->req.actual);
|
||||||
count = dma_dest_len(ep, req->req.dma + req->req.actual);
|
count = dma_dest_len(ep, req->req.dma + req->req.actual);
|
||||||
count += req->req.actual;
|
count += req->req.actual;
|
||||||
|
if (one)
|
||||||
|
count--;
|
||||||
if (count <= req->req.length)
|
if (count <= req->req.length)
|
||||||
req->req.actual = count;
|
req->req.actual = count;
|
||||||
|
|
||||||
|
@ -747,7 +749,7 @@ static void dma_irq(struct omap_udc *udc, u16 irq_src)
|
||||||
if (!list_empty(&ep->queue)) {
|
if (!list_empty(&ep->queue)) {
|
||||||
req = container_of(ep->queue.next,
|
req = container_of(ep->queue.next,
|
||||||
struct omap_req, queue);
|
struct omap_req, queue);
|
||||||
finish_out_dma(ep, req, 0);
|
finish_out_dma(ep, req, 0, dman_stat & UDC_DMA_RX_SB);
|
||||||
}
|
}
|
||||||
UDC_IRQ_SRC_REG = UDC_RXN_EOT;
|
UDC_IRQ_SRC_REG = UDC_RXN_EOT;
|
||||||
|
|
||||||
|
@ -925,7 +927,7 @@ static void dma_channel_release(struct omap_ep *ep)
|
||||||
while (UDC_RXDMA_CFG_REG & mask)
|
while (UDC_RXDMA_CFG_REG & mask)
|
||||||
udelay(10);
|
udelay(10);
|
||||||
if (req)
|
if (req)
|
||||||
finish_out_dma(ep, req, -ECONNRESET);
|
finish_out_dma(ep, req, -ECONNRESET, 0);
|
||||||
}
|
}
|
||||||
omap_free_dma(ep->lch);
|
omap_free_dma(ep->lch);
|
||||||
ep->dma_channel = 0;
|
ep->dma_channel = 0;
|
||||||
|
|
Loading…
Reference in New Issue