Skip to content

Commit

Permalink
usb: musb: maintain three states for buffer mappings instead of two
Browse files Browse the repository at this point in the history
If dma buffers are mapped by a higher layer, with a boolean musb_request.mapped
it is still possible to call dma_sync_single_for_device() from
musb_g_giveback(), even if txstate()/rxstate() has called unmap_dma_buffer()
before falling back to pio mode.

Moreover, check for musb_ep->dma is moved within map_dma_buffer() so where
applicable checks for it are removed. And where possible, checks for
is_dma_capable() are merged with buffer map state check.

Signed-off-by: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Mian Yousaf Kaukab authored and Felipe Balbi committed Feb 1, 2011
1 parent 0662481 commit c65bfa6
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 21 deletions.
45 changes: 25 additions & 20 deletions drivers/usb/musb/musb_gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,19 @@

/* ----------------------------------------------------------------------- */

#define is_buffer_mapped(req) (is_dma_capable() && \
(req->map_state != UN_MAPPED))

/* Maps the buffer to dma */

static inline void map_dma_buffer(struct musb_request *request,
struct musb *musb)
struct musb *musb, struct musb_ep *musb_ep)
{
request->map_state = UN_MAPPED;

if (!is_dma_capable() || !musb_ep->dma)
return;

if (request->request.dma == DMA_ADDR_INVALID) {
request->request.dma = dma_map_single(
musb->controller,
Expand All @@ -105,44 +113,46 @@ static inline void map_dma_buffer(struct musb_request *request,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
request->mapped = 1;
request->map_state = MUSB_MAPPED;
} else {
dma_sync_single_for_device(musb->controller,
request->request.dma,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
request->mapped = 0;
request->map_state = PRE_MAPPED;
}
}

/* Unmap the buffer from dma and maps it back to cpu */
static inline void unmap_dma_buffer(struct musb_request *request,
struct musb *musb)
{
if (!is_buffer_mapped(request))
return;

if (request->request.dma == DMA_ADDR_INVALID) {
DBG(20, "not unmapping a never mapped buffer\n");
return;
}
if (request->mapped) {
if (request->map_state == MUSB_MAPPED) {
dma_unmap_single(musb->controller,
request->request.dma,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
request->request.dma = DMA_ADDR_INVALID;
request->mapped = 0;
} else {
} else { /* PRE_MAPPED */
dma_sync_single_for_cpu(musb->controller,
request->request.dma,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);

}
request->map_state = UN_MAPPED;
}

/*
Expand Down Expand Up @@ -172,8 +182,7 @@ __acquires(ep->musb->lock)

ep->busy = 1;
spin_unlock(&musb->lock);
if (is_dma_capable() && ep->dma)
unmap_dma_buffer(req, musb);
unmap_dma_buffer(req, musb);
if (request->status == 0)
DBG(5, "%s done request %p, %d/%d\n",
ep->end_point.name, request,
Expand Down Expand Up @@ -335,7 +344,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
csr);

#ifndef CONFIG_MUSB_PIO_ONLY
if (is_dma_capable() && musb_ep->dma) {
if (is_buffer_mapped(req)) {
struct dma_controller *c = musb->dma_controller;
size_t request_size;

Expand Down Expand Up @@ -436,8 +445,7 @@ static void txstate(struct musb *musb, struct musb_request *req)
* Unmap the dma buffer back to cpu if dma channel
* programming fails
*/
if (is_dma_capable() && musb_ep->dma)
unmap_dma_buffer(req, musb);
unmap_dma_buffer(req, musb);

musb_write_fifo(musb_ep->hw_ep, fifo_count,
(u8 *) (request->buf + request->actual));
Expand Down Expand Up @@ -627,7 +635,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
return;
}

if (is_cppi_enabled() && musb_ep->dma) {
if (is_cppi_enabled() && is_buffer_mapped(req)) {
struct dma_controller *c = musb->dma_controller;
struct dma_channel *channel = musb_ep->dma;

Expand Down Expand Up @@ -658,7 +666,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
len = musb_readw(epio, MUSB_RXCOUNT);
if (request->actual < request->length) {
#ifdef CONFIG_USB_INVENTRA_DMA
if (is_dma_capable() && musb_ep->dma) {
if (is_buffer_mapped(req)) {
struct dma_controller *c;
struct dma_channel *channel;
int use_dma = 0;
Expand Down Expand Up @@ -742,7 +750,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
fifo_count = min_t(unsigned, len, fifo_count);

#ifdef CONFIG_USB_TUSB_OMAP_DMA
if (tusb_dma_omap() && musb_ep->dma) {
if (tusb_dma_omap() && is_buffer_mapped(req)) {
struct dma_controller *c = musb->dma_controller;
struct dma_channel *channel = musb_ep->dma;
u32 dma_addr = request->dma + request->actual;
Expand All @@ -762,7 +770,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
* programming fails. This buffer is mapped if the
* channel allocation is successful
*/
if (is_dma_capable() && musb_ep->dma) {
if (is_buffer_mapped(req)) {
unmap_dma_buffer(req, musb);

/*
Expand Down Expand Up @@ -1222,10 +1230,7 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
request->epnum = musb_ep->current_epnum;
request->tx = musb_ep->is_in;

if (is_dma_capable() && musb_ep->dma)
map_dma_buffer(request, musb);
else
request->mapped = 0;
map_dma_buffer(request, musb, musb_ep);

spin_lock_irqsave(&musb->lock, lockflags);

Expand Down
8 changes: 7 additions & 1 deletion drivers/usb/musb/musb_gadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,19 @@
#ifndef __MUSB_GADGET_H
#define __MUSB_GADGET_H

enum buffer_map_state {
UN_MAPPED = 0,
PRE_MAPPED,
MUSB_MAPPED
};

struct musb_request {
struct usb_request request;
struct musb_ep *ep;
struct musb *musb;
u8 tx; /* endpoint direction */
u8 epnum;
u8 mapped;
enum buffer_map_state map_state;
};

static inline struct musb_request *to_musb_request(struct usb_request *req)
Expand Down

0 comments on commit c65bfa6

Please sign in to comment.