diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/usb/gadget/omap_udc.c | 103 |
1 files changed, 93 insertions, 10 deletions
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 8f9a2b615422..b394e63894d2 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
| @@ -296,6 +296,15 @@ omap_free_request(struct usb_ep *ep, struct usb_request *_req) | |||
| 296 | 296 | ||
| 297 | /*-------------------------------------------------------------------------*/ | 297 | /*-------------------------------------------------------------------------*/ |
| 298 | 298 | ||
| 299 | /* | ||
| 300 | * dma-coherent memory allocation (for dma-capable endpoints) | ||
| 301 | * | ||
| 302 | * NOTE: the dma_*_coherent() API calls suck. Most implementations are | ||
| 303 | * (a) page-oriented, so small buffers lose big; and (b) asymmetric with | ||
| 304 | * respect to calls with irqs disabled: alloc is safe, free is not. | ||
| 305 | * We currently work around (b), but not (a). | ||
| 306 | */ | ||
| 307 | |||
| 299 | static void * | 308 | static void * |
| 300 | omap_alloc_buffer( | 309 | omap_alloc_buffer( |
| 301 | struct usb_ep *_ep, | 310 | struct usb_ep *_ep, |
| @@ -307,6 +316,9 @@ omap_alloc_buffer( | |||
| 307 | void *retval; | 316 | void *retval; |
| 308 | struct omap_ep *ep; | 317 | struct omap_ep *ep; |
| 309 | 318 | ||
| 319 | if (!_ep) | ||
| 320 | return NULL; | ||
| 321 | |||
| 310 | ep = container_of(_ep, struct omap_ep, ep); | 322 | ep = container_of(_ep, struct omap_ep, ep); |
| 311 | if (use_dma && ep->has_dma) { | 323 | if (use_dma && ep->has_dma) { |
| 312 | static int warned; | 324 | static int warned; |
| @@ -326,6 +338,35 @@ omap_alloc_buffer( | |||
| 326 | return retval; | 338 | return retval; |
| 327 | } | 339 | } |
| 328 | 340 | ||
| 341 | static DEFINE_SPINLOCK(buflock); | ||
| 342 | static LIST_HEAD(buffers); | ||
| 343 | |||
| 344 | struct free_record { | ||
| 345 | struct list_head list; | ||
| 346 | struct device *dev; | ||
| 347 | unsigned bytes; | ||
| 348 | dma_addr_t dma; | ||
| 349 | }; | ||
| 350 | |||
| 351 | static void do_free(unsigned long ignored) | ||
| 352 | { | ||
| 353 | spin_lock_irq(&buflock); | ||
| 354 | while (!list_empty(&buffers)) { | ||
| 355 | struct free_record *buf; | ||
| 356 | |||
| 357 | buf = list_entry(buffers.next, struct free_record, list); | ||
| 358 | list_del(&buf->list); | ||
| 359 | spin_unlock_irq(&buflock); | ||
| 360 | |||
| 361 | dma_free_coherent(buf->dev, buf->bytes, buf, buf->dma); | ||
| 362 | |||
| 363 | spin_lock_irq(&buflock); | ||
| 364 | } | ||
| 365 | spin_unlock_irq(&buflock); | ||
| 366 | } | ||
| 367 | |||
| 368 | static DECLARE_TASKLET(deferred_free, do_free, 0); | ||
| 369 | |||
| 329 | static void omap_free_buffer( | 370 | static void omap_free_buffer( |
| 330 | struct usb_ep *_ep, | 371 | struct usb_ep *_ep, |
| 331 | void *buf, | 372 | void *buf, |
| @@ -333,13 +374,29 @@ static void omap_free_buffer( | |||
| 333 | unsigned bytes | 374 | unsigned bytes |
| 334 | ) | 375 | ) |
| 335 | { | 376 | { |
| 336 | struct omap_ep *ep; | 377 | if (!_ep) { |
| 378 | WARN_ON(1); | ||
| 379 | return; | ||
| 380 | } | ||
| 337 | 381 | ||
| 338 | ep = container_of(_ep, struct omap_ep, ep); | 382 | /* free memory into the right allocator */ |
| 339 | if (use_dma && _ep && ep->has_dma) | 383 | if (dma != DMA_ADDR_INVALID) { |
| 340 | dma_free_coherent(ep->udc->gadget.dev.parent, bytes, buf, dma); | 384 | struct omap_ep *ep; |
| 341 | else | 385 | struct free_record *rec = buf; |
| 342 | kfree (buf); | 386 | unsigned long flags; |
| 387 | |||
| 388 | ep = container_of(_ep, struct omap_ep, ep); | ||
| 389 | |||
| 390 | rec->dev = ep->udc->gadget.dev.parent; | ||
| 391 | rec->bytes = bytes; | ||
| 392 | rec->dma = dma; | ||
| 393 | |||
| 394 | spin_lock_irqsave(&buflock, flags); | ||
| 395 | list_add_tail(&rec->list, &buffers); | ||
| 396 | tasklet_schedule(&deferred_free); | ||
| 397 | spin_unlock_irqrestore(&buflock, flags); | ||
| 398 | } else | ||
| 399 | kfree(buf); | ||
| 343 | } | 400 | } |
| 344 | 401 | ||
| 345 | /*-------------------------------------------------------------------------*/ | 402 | /*-------------------------------------------------------------------------*/ |
| @@ -1691,12 +1748,38 @@ ep0out_status_stage: | |||
| 1691 | udc->ep0_pending = 0; | 1748 | udc->ep0_pending = 0; |
| 1692 | break; | 1749 | break; |
| 1693 | case USB_REQ_GET_STATUS: | 1750 | case USB_REQ_GET_STATUS: |
| 1751 | /* USB_ENDPOINT_HALT status? */ | ||
| 1752 | if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT)) | ||
| 1753 | goto intf_status; | ||
| 1754 | |||
| 1755 | /* ep0 never stalls */ | ||
| 1756 | if (!(w_index & 0xf)) | ||
| 1757 | goto zero_status; | ||
| 1758 | |||
| 1759 | /* only active endpoints count */ | ||
| 1760 | ep = &udc->ep[w_index & 0xf]; | ||
| 1761 | if (w_index & USB_DIR_IN) | ||
| 1762 | ep += 16; | ||
| 1763 | if (!ep->desc) | ||
| 1764 | goto do_stall; | ||
| 1765 | |||
| 1766 | /* iso never stalls */ | ||
| 1767 | if (ep->bmAttributes == USB_ENDPOINT_XFER_ISOC) | ||
| 1768 | goto zero_status; | ||
| 1769 | |||
| 1770 | /* FIXME don't assume non-halted endpoints!! */ | ||
| 1771 | ERR("%s status, can't report\n", ep->ep.name); | ||
| 1772 | goto do_stall; | ||
| 1773 | |||
| 1774 | intf_status: | ||
| 1694 | /* return interface status. if we were pedantic, | 1775 | /* return interface status. if we were pedantic, |
| 1695 | * we'd detect non-existent interfaces, and stall. | 1776 | * we'd detect non-existent interfaces, and stall. |
| 1696 | */ | 1777 | */ |
| 1697 | if (u.r.bRequestType | 1778 | if (u.r.bRequestType |
| 1698 | != (USB_DIR_IN|USB_RECIP_INTERFACE)) | 1779 | != (USB_DIR_IN|USB_RECIP_INTERFACE)) |
| 1699 | goto delegate; | 1780 | goto delegate; |
| 1781 | |||
| 1782 | zero_status: | ||
| 1700 | /* return two zero bytes */ | 1783 | /* return two zero bytes */ |
| 1701 | UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; | 1784 | UDC_EP_NUM_REG = UDC_EP_SEL|UDC_EP_DIR; |
| 1702 | UDC_DATA_REG = 0; | 1785 | UDC_DATA_REG = 0; |
| @@ -2068,7 +2151,7 @@ static irqreturn_t omap_udc_iso_irq(int irq, void *_dev) | |||
| 2068 | 2151 | ||
| 2069 | /*-------------------------------------------------------------------------*/ | 2152 | /*-------------------------------------------------------------------------*/ |
| 2070 | 2153 | ||
| 2071 | static inline int machine_needs_vbus_session(void) | 2154 | static inline int machine_without_vbus_sense(void) |
| 2072 | { | 2155 | { |
| 2073 | return (machine_is_omap_innovator() | 2156 | return (machine_is_omap_innovator() |
| 2074 | || machine_is_omap_osk() | 2157 | || machine_is_omap_osk() |
| @@ -2156,7 +2239,7 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver) | |||
| 2156 | /* boards that don't have VBUS sensing can't autogate 48MHz; | 2239 | /* boards that don't have VBUS sensing can't autogate 48MHz; |
| 2157 | * can't enter deep sleep while a gadget driver is active. | 2240 | * can't enter deep sleep while a gadget driver is active. |
| 2158 | */ | 2241 | */ |
| 2159 | if (machine_needs_vbus_session()) | 2242 | if (machine_without_vbus_sense()) |
| 2160 | omap_vbus_session(&udc->gadget, 1); | 2243 | omap_vbus_session(&udc->gadget, 1); |
| 2161 | 2244 | ||
| 2162 | done: | 2245 | done: |
| @@ -2179,7 +2262,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver) | |||
| 2179 | if (udc->dc_clk != NULL) | 2262 | if (udc->dc_clk != NULL) |
| 2180 | omap_udc_enable_clock(1); | 2263 | omap_udc_enable_clock(1); |
| 2181 | 2264 | ||
| 2182 | if (machine_needs_vbus_session()) | 2265 | if (machine_without_vbus_sense()) |
| 2183 | omap_vbus_session(&udc->gadget, 0); | 2266 | omap_vbus_session(&udc->gadget, 0); |
| 2184 | 2267 | ||
| 2185 | if (udc->transceiver) | 2268 | if (udc->transceiver) |
| @@ -2822,7 +2905,7 @@ static int __init omap_udc_probe(struct platform_device *pdev) | |||
| 2822 | hmc = HMC_1510; | 2905 | hmc = HMC_1510; |
| 2823 | type = "(unknown)"; | 2906 | type = "(unknown)"; |
| 2824 | 2907 | ||
| 2825 | if (machine_is_omap_innovator() || machine_is_sx1()) { | 2908 | if (machine_without_vbus_sense()) { |
| 2826 | /* just set up software VBUS detect, and then | 2909 | /* just set up software VBUS detect, and then |
| 2827 | * later rig it so we always report VBUS. | 2910 | * later rig it so we always report VBUS. |
| 2828 | * FIXME without really sensing VBUS, we can't | 2911 | * FIXME without really sensing VBUS, we can't |
