diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/dwc2/core.h | 4 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd.c | 50 | ||||
-rw-r--r-- | drivers/usb/dwc2/hcd_ddma.c | 20 |
3 files changed, 71 insertions, 3 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index e7cc54268f2f..baee2bc1e8a8 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -686,6 +686,8 @@ struct dwc2_hregs_backup { * @frame_list: Frame list * @frame_list_dma: Frame list DMA address * @frame_list_sz: Frame list size + * @desc_gen_cache: Kmem cache for generic descriptors + * @desc_hsisoc_cache: Kmem cache for hs isochronous descriptors * * These are for peripheral mode: * @@ -806,6 +808,8 @@ struct dwc2_hsotg { u32 *frame_list; dma_addr_t frame_list_dma; u32 frame_list_sz; + struct kmem_cache *desc_gen_cache; + struct kmem_cache *desc_hsisoc_cache; #ifdef DEBUG u32 frrem_samples; diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 7fd4f41e12a7..b2afe913d559 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -3146,6 +3146,47 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) if (!hsotg->status_buf) goto error3; + /* + * Create kmem caches to handle descriptor buffers in descriptor + * DMA mode. + * Alignment must be set to 512 bytes. + */ + if (hsotg->core_params->dma_desc_enable || + hsotg->core_params->dma_desc_fs_enable) { + hsotg->desc_gen_cache = kmem_cache_create("dwc2-gen-desc", + sizeof(struct dwc2_hcd_dma_desc) * + MAX_DMA_DESC_NUM_GENERIC, 512, SLAB_CACHE_DMA, + NULL); + if (!hsotg->desc_gen_cache) { + dev_err(hsotg->dev, + "unable to create dwc2 generic desc cache\n"); + + /* + * Disable descriptor dma mode since it will not be + * usable. + */ + hsotg->core_params->dma_desc_enable = 0; + hsotg->core_params->dma_desc_fs_enable = 0; + } + + hsotg->desc_hsisoc_cache = kmem_cache_create("dwc2-hsisoc-desc", + sizeof(struct dwc2_hcd_dma_desc) * + MAX_DMA_DESC_NUM_HS_ISOC, 512, 0, NULL); + if (!hsotg->desc_hsisoc_cache) { + dev_err(hsotg->dev, + "unable to create dwc2 hs isoc desc cache\n"); + + kmem_cache_destroy(hsotg->desc_gen_cache); + + /* + * Disable descriptor dma mode since it will not be + * usable. + */ + hsotg->core_params->dma_desc_enable = 0; + hsotg->core_params->dma_desc_fs_enable = 0; + } + } + hsotg->otg_port = 1; hsotg->frame_list = NULL; hsotg->frame_list_dma = 0; @@ -3169,7 +3210,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) */ retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval < 0) - goto error3; + goto error4; device_wakeup_enable(hcd->self.controller); @@ -3179,6 +3220,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) return 0; +error4: + kmem_cache_destroy(hsotg->desc_gen_cache); + kmem_cache_destroy(hsotg->desc_hsisoc_cache); error3: dwc2_hcd_release(hsotg); error2: @@ -3219,6 +3263,10 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) usb_remove_hcd(hcd); hsotg->priv = NULL; + + kmem_cache_destroy(hsotg->desc_gen_cache); + kmem_cache_destroy(hsotg->desc_hsisoc_cache); + dwc2_hcd_release(hsotg); usb_put_hcd(hcd); diff --git a/drivers/usb/dwc2/hcd_ddma.c b/drivers/usb/dwc2/hcd_ddma.c index 85d7816d29f1..36606fc33c0d 100644 --- a/drivers/usb/dwc2/hcd_ddma.c +++ b/drivers/usb/dwc2/hcd_ddma.c @@ -87,10 +87,18 @@ static u16 dwc2_frame_incr_val(struct dwc2_qh *qh) static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, gfp_t flags) { + struct kmem_cache *desc_cache; + + if (qh->ep_type == USB_ENDPOINT_XFER_ISOC + && qh->dev_speed == USB_SPEED_HIGH) + desc_cache = hsotg->desc_hsisoc_cache; + else + desc_cache = hsotg->desc_gen_cache; + qh->desc_list_sz = sizeof(struct dwc2_hcd_dma_desc) * dwc2_max_desc_num(qh); - qh->desc_list = kzalloc(qh->desc_list_sz, flags | GFP_DMA); + qh->desc_list = kmem_cache_zalloc(desc_cache, flags | GFP_DMA); if (!qh->desc_list) return -ENOMEM; @@ -113,10 +121,18 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, static void dwc2_desc_list_free(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh) { + struct kmem_cache *desc_cache; + + if (qh->ep_type == USB_ENDPOINT_XFER_ISOC + && qh->dev_speed == USB_SPEED_HIGH) + desc_cache = hsotg->desc_hsisoc_cache; + else + desc_cache = hsotg->desc_gen_cache; + if (qh->desc_list) { dma_unmap_single(hsotg->dev, qh->desc_list_dma, qh->desc_list_sz, DMA_FROM_DEVICE); - kfree(qh->desc_list); + kmem_cache_free(desc_cache, qh->desc_list); qh->desc_list = NULL; } |