Commit b7a5100b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge branch 'for-greg' of git://gitorious.org/usb/usb into work

parents 82442723 07a8cdd2
...@@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb, ...@@ -1330,6 +1330,8 @@ static int map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
*/ */
if (usb_endpoint_xfer_control(&urb->ep->desc)) { if (usb_endpoint_xfer_control(&urb->ep->desc)) {
if (hcd->self.uses_pio_for_control)
return ret;
if (hcd->self.uses_dma) { if (hcd->self.uses_dma) {
urb->setup_dma = dma_map_single( urb->setup_dma = dma_map_single(
hcd->self.controller, hcd->self.controller,
......
...@@ -2116,12 +2116,15 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) ...@@ -2116,12 +2116,15 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
* Otherwise, wait till the gadget driver hooks up. * Otherwise, wait till the gadget driver hooks up.
*/ */
if (!is_otg_enabled(musb) && is_host_enabled(musb)) { if (!is_otg_enabled(musb) && is_host_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
MUSB_HST_MODE(musb); MUSB_HST_MODE(musb);
musb->xceiv->default_a = 1; musb->xceiv->default_a = 1;
musb->xceiv->state = OTG_STATE_A_IDLE; musb->xceiv->state = OTG_STATE_A_IDLE;
status = usb_add_hcd(musb_to_hcd(musb), -1, 0); status = usb_add_hcd(musb_to_hcd(musb), -1, 0);
hcd->self.uses_pio_for_control = 1;
DBG(1, "%s mode, status %d, devctl %02x %c\n", DBG(1, "%s mode, status %d, devctl %02x %c\n",
"HOST", status, "HOST", status,
musb_readb(musb->mregs, MUSB_DEVCTL), musb_readb(musb->mregs, MUSB_DEVCTL),
......
...@@ -92,6 +92,59 @@ ...@@ -92,6 +92,59 @@
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* Maps the buffer to dma */
static inline void map_dma_buffer(struct musb_request *request,
struct musb *musb)
{
if (request->request.dma == DMA_ADDR_INVALID) {
request->request.dma = dma_map_single(
musb->controller,
request->request.buf,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
request->mapped = 1;
} 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;
}
}
/* 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 (request->request.dma == DMA_ADDR_INVALID) {
DBG(20, "not unmapping a never mapped buffer\n");
return;
}
if (request->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 {
dma_sync_single_for_cpu(musb->controller,
request->request.dma,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
}
}
/* /*
* Immediately complete a request. * Immediately complete a request.
* *
...@@ -119,24 +172,8 @@ __acquires(ep->musb->lock) ...@@ -119,24 +172,8 @@ __acquires(ep->musb->lock)
ep->busy = 1; ep->busy = 1;
spin_unlock(&musb->lock); spin_unlock(&musb->lock);
if (is_dma_capable()) { if (is_dma_capable() && ep->dma)
if (req->mapped) { unmap_dma_buffer(req, musb);
dma_unmap_single(musb->controller,
req->request.dma,
req->request.length,
req->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
req->request.dma = DMA_ADDR_INVALID;
req->mapped = 0;
} else if (req->request.dma != DMA_ADDR_INVALID)
dma_sync_single_for_cpu(musb->controller,
req->request.dma,
req->request.length,
req->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
}
if (request->status == 0) if (request->status == 0)
DBG(5, "%s done request %p, %d/%d\n", DBG(5, "%s done request %p, %d/%d\n",
ep->end_point.name, request, ep->end_point.name, request,
...@@ -395,6 +432,13 @@ static void txstate(struct musb *musb, struct musb_request *req) ...@@ -395,6 +432,13 @@ static void txstate(struct musb *musb, struct musb_request *req)
#endif #endif
if (!use_dma) { if (!use_dma) {
/*
* Unmap the dma buffer back to cpu if dma channel
* programming fails
*/
if (is_dma_capable() && musb_ep->dma)
unmap_dma_buffer(req, musb);
musb_write_fifo(musb_ep->hw_ep, fifo_count, musb_write_fifo(musb_ep->hw_ep, fifo_count,
(u8 *) (request->buf + request->actual)); (u8 *) (request->buf + request->actual));
request->actual += fifo_count; request->actual += fifo_count;
...@@ -713,6 +757,21 @@ static void rxstate(struct musb *musb, struct musb_request *req) ...@@ -713,6 +757,21 @@ static void rxstate(struct musb *musb, struct musb_request *req)
return; return;
} }
#endif #endif
/*
* Unmap the dma buffer back to cpu if dma channel
* programming fails. This buffer is mapped if the
* channel allocation is successful
*/
if (is_dma_capable() && musb_ep->dma) {
unmap_dma_buffer(req, musb);
/*
* Clear DMAENAB and AUTOCLEAR for the
* PIO mode transfer
*/
csr &= ~(MUSB_RXCSR_DMAENAB | MUSB_RXCSR_AUTOCLEAR);
musb_writew(epio, MUSB_RXCSR, csr);
}
musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *) musb_read_fifo(musb_ep->hw_ep, fifo_count, (u8 *)
(request->buf + request->actual)); (request->buf + request->actual));
...@@ -837,7 +896,9 @@ void musb_g_rx(struct musb *musb, u8 epnum) ...@@ -837,7 +896,9 @@ void musb_g_rx(struct musb *musb, u8 epnum)
if (!request) if (!request)
return; return;
} }
#if defined(CONFIG_USB_INVENTRA_DMA) || defined(CONFIG_USB_TUSB_OMAP_DMA)
exit: exit:
#endif
/* Analyze request */ /* Analyze request */
rxstate(musb, to_musb_request(request)); rxstate(musb, to_musb_request(request));
} }
...@@ -1150,26 +1211,9 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req, ...@@ -1150,26 +1211,9 @@ static int musb_gadget_queue(struct usb_ep *ep, struct usb_request *req,
request->epnum = musb_ep->current_epnum; request->epnum = musb_ep->current_epnum;
request->tx = musb_ep->is_in; request->tx = musb_ep->is_in;
if (is_dma_capable() && musb_ep->dma) { if (is_dma_capable() && musb_ep->dma)
if (request->request.dma == DMA_ADDR_INVALID) { map_dma_buffer(request, musb);
request->request.dma = dma_map_single( else
musb->controller,
request->request.buf,
request->request.length,
request->tx
? DMA_TO_DEVICE
: DMA_FROM_DEVICE);
request->mapped = 1;
} 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;
}
} else
request->mapped = 0; request->mapped = 0;
spin_lock_irqsave(&musb->lock, lockflags); spin_lock_irqsave(&musb->lock, lockflags);
...@@ -1789,6 +1833,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -1789,6 +1833,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
if (is_otg_enabled(musb)) { if (is_otg_enabled(musb)) {
struct usb_hcd *hcd = musb_to_hcd(musb);
DBG(3, "OTG startup...\n"); DBG(3, "OTG startup...\n");
/* REVISIT: funcall to other code, which also /* REVISIT: funcall to other code, which also
...@@ -1803,6 +1849,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver, ...@@ -1803,6 +1849,8 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
musb->gadget_driver = NULL; musb->gadget_driver = NULL;
musb->g.dev.driver = NULL; musb->g.dev.driver = NULL;
spin_unlock_irqrestore(&musb->lock, flags); spin_unlock_irqrestore(&musb->lock, flags);
} else {
hcd->self.uses_pio_for_control = 1;
} }
} }
} }
......
...@@ -313,6 +313,10 @@ struct usb_bus { ...@@ -313,6 +313,10 @@ struct usb_bus {
int busnum; /* Bus number (in order of reg) */ int busnum; /* Bus number (in order of reg) */
const char *bus_name; /* stable id (PCI slot_name etc) */ const char *bus_name; /* stable id (PCI slot_name etc) */
u8 uses_dma; /* Does the host controller use DMA? */ u8 uses_dma; /* Does the host controller use DMA? */
u8 uses_pio_for_control; /*
* Does the host controller use PIO
* for control transfers?
*/
u8 otg_port; /* 0, or number of OTG/HNP port */ u8 otg_port; /* 0, or number of OTG/HNP port */
unsigned is_b_host:1; /* true during some HNP roleswitches */ unsigned is_b_host:1; /* true during some HNP roleswitches */
unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */ unsigned b_hnp_enable:1; /* OTG: did A-Host enable HNP? */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment