Commit 3b5fcc9a authored by Gregory Herrero's avatar Gregory Herrero Committed by Felipe Balbi

usb: dwc2: host: use kmem cache to allocate descriptors

Kmem caches help to get correct boundary for descriptor buffers
which need to be 512 bytes aligned for dwc2 controller.
Two kmem caches are needed for generic descriptors and for
hs isochronous descriptors which doesn't have same size.
Acked-by: default avatarJohn Youn <johnyoun@synopsys.com>
Signed-off-by: default avatarGregory Herrero <gregory.herrero@intel.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent e23b8a54
...@@ -686,6 +686,8 @@ struct dwc2_hregs_backup { ...@@ -686,6 +686,8 @@ struct dwc2_hregs_backup {
* @frame_list: Frame list * @frame_list: Frame list
* @frame_list_dma: Frame list DMA address * @frame_list_dma: Frame list DMA address
* @frame_list_sz: Frame list size * @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: * These are for peripheral mode:
* *
...@@ -806,6 +808,8 @@ struct dwc2_hsotg { ...@@ -806,6 +808,8 @@ struct dwc2_hsotg {
u32 *frame_list; u32 *frame_list;
dma_addr_t frame_list_dma; dma_addr_t frame_list_dma;
u32 frame_list_sz; u32 frame_list_sz;
struct kmem_cache *desc_gen_cache;
struct kmem_cache *desc_hsisoc_cache;
#ifdef DEBUG #ifdef DEBUG
u32 frrem_samples; u32 frrem_samples;
......
...@@ -3146,6 +3146,47 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) ...@@ -3146,6 +3146,47 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
if (!hsotg->status_buf) if (!hsotg->status_buf)
goto error3; 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->otg_port = 1;
hsotg->frame_list = NULL; hsotg->frame_list = NULL;
hsotg->frame_list_dma = 0; hsotg->frame_list_dma = 0;
...@@ -3169,7 +3210,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) ...@@ -3169,7 +3210,7 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
*/ */
retval = usb_add_hcd(hcd, irq, IRQF_SHARED); retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval < 0) if (retval < 0)
goto error3; goto error4;
device_wakeup_enable(hcd->self.controller); device_wakeup_enable(hcd->self.controller);
...@@ -3179,6 +3220,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq) ...@@ -3179,6 +3220,9 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
return 0; return 0;
error4:
kmem_cache_destroy(hsotg->desc_gen_cache);
kmem_cache_destroy(hsotg->desc_hsisoc_cache);
error3: error3:
dwc2_hcd_release(hsotg); dwc2_hcd_release(hsotg);
error2: error2:
...@@ -3219,6 +3263,10 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg) ...@@ -3219,6 +3263,10 @@ void dwc2_hcd_remove(struct dwc2_hsotg *hsotg)
usb_remove_hcd(hcd); usb_remove_hcd(hcd);
hsotg->priv = NULL; hsotg->priv = NULL;
kmem_cache_destroy(hsotg->desc_gen_cache);
kmem_cache_destroy(hsotg->desc_hsisoc_cache);
dwc2_hcd_release(hsotg); dwc2_hcd_release(hsotg);
usb_put_hcd(hcd); usb_put_hcd(hcd);
......
...@@ -87,10 +87,18 @@ static u16 dwc2_frame_incr_val(struct dwc2_qh *qh) ...@@ -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, static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh,
gfp_t flags) 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) * qh->desc_list_sz = sizeof(struct dwc2_hcd_dma_desc) *
dwc2_max_desc_num(qh); 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) if (!qh->desc_list)
return -ENOMEM; return -ENOMEM;
...@@ -113,10 +121,18 @@ static int dwc2_desc_list_alloc(struct dwc2_hsotg *hsotg, struct dwc2_qh *qh, ...@@ -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) 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) { if (qh->desc_list) {
dma_unmap_single(hsotg->dev, qh->desc_list_dma, dma_unmap_single(hsotg->dev, qh->desc_list_dma,
qh->desc_list_sz, DMA_FROM_DEVICE); qh->desc_list_sz, DMA_FROM_DEVICE);
kfree(qh->desc_list); kmem_cache_free(desc_cache, qh->desc_list);
qh->desc_list = NULL; qh->desc_list = NULL;
} }
......
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