diff options
author | Vahram Aharonyan <vahrama@synopsys.com> | 2016-11-09 19:28:03 -0800 |
---|---|---|
committer | Felipe Balbi <felipe.balbi@linux.intel.com> | 2016-11-18 13:54:20 +0200 |
commit | 5f54c54b0ba835d547b86c65cc2076d62650ba77 (patch) | |
tree | 949665af9f75cfbff485a1e606118b485f62e7c1 /drivers/usb/dwc2 | |
parent | cf77b5fb9b39445947e8027872c63cc16fb480fb (diff) |
usb: dwc2: gadget: Add DDMA chain pointers to dwc2_hsotg_ep structure
Add DMA descriptor members to the dwc2_hsotg_ep structure.
Signed-off-by: Vahram Aharonyan <vahrama@synopsys.com>
Signed-off-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Diffstat (limited to 'drivers/usb/dwc2')
-rw-r--r-- | drivers/usb/dwc2/core.h | 7 | ||||
-rw-r--r-- | drivers/usb/dwc2/gadget.c | 33 |
2 files changed, 38 insertions, 2 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h index 26d4c1716adf..4094d3dee25a 100644 --- a/drivers/usb/dwc2/core.h +++ b/drivers/usb/dwc2/core.h @@ -172,6 +172,9 @@ struct dwc2_hsotg_req; * @periodic: Set if this is a periodic ep, such as Interrupt * @isochronous: Set if this is a isochronous ep * @send_zlp: Set if we need to send a zero-length packet. + * @desc_list_dma: The DMA address of descriptor chain currently in use. + * @desc_list: Pointer to descriptor DMA chain head currently in use. + * @desc_count: Count of entries within the DMA descriptor chain of EP. * @total_data: The total number of data bytes done. * @fifo_size: The size of the FIFO (for periodic IN endpoints) * @fifo_load: The amount of data loaded into the FIFO (periodic IN) @@ -219,6 +222,10 @@ struct dwc2_hsotg_ep { #define TARGET_FRAME_INITIAL 0xFFFFFFFF bool frame_overrun; + dma_addr_t desc_list_dma; + struct dwc2_dma_desc *desc_list; + u8 desc_count; + char name[10]; }; diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 4c1098f84431..3264375231f4 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -3077,6 +3077,18 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, dev_dbg(hsotg->dev, "%s: read DxEPCTL=0x%08x from 0x%08x\n", __func__, epctrl, epctrl_reg); + /* Allocate DMA descriptor chain for non-ctrl endpoints */ + if (using_desc_dma(hsotg)) { + hs_ep->desc_list = dma_alloc_coherent(hsotg->dev, + MAX_DMA_DESC_NUM_GENERIC * + sizeof(struct dwc2_dma_desc), + &hs_ep->desc_list_dma, GFP_KERNEL); + if (!hs_ep->desc_list) { + ret = -ENOMEM; + goto error2; + } + } + spin_lock_irqsave(&hsotg->lock, flags); epctrl &= ~(DXEPCTL_EPTYPE_MASK | DXEPCTL_MPS_MASK); @@ -3160,7 +3172,7 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, dev_err(hsotg->dev, "%s: No suitable fifo found\n", __func__); ret = -ENOMEM; - goto error; + goto error1; } hsotg->fifo_map |= 1 << fifo_index; epctrl |= DXEPCTL_TXFNUM(fifo_index); @@ -3182,8 +3194,17 @@ static int dwc2_hsotg_ep_enable(struct usb_ep *ep, /* enable the endpoint interrupt */ dwc2_hsotg_ctrl_epint(hsotg, index, dir_in, 1); -error: +error1: spin_unlock_irqrestore(&hsotg->lock, flags); + +error2: + if (ret && using_desc_dma(hsotg) && hs_ep->desc_list) { + dma_free_coherent(hsotg->dev, MAX_DMA_DESC_NUM_GENERIC * + sizeof(struct dwc2_dma_desc), + hs_ep->desc_list, hs_ep->desc_list_dma); + hs_ep->desc_list = NULL; + } + return ret; } @@ -3208,6 +3229,14 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep) return -EINVAL; } + /* Remove DMA memory allocated for non-control Endpoints */ + if (using_desc_dma(hsotg)) { + dma_free_coherent(hsotg->dev, MAX_DMA_DESC_NUM_GENERIC * + sizeof(struct dwc2_dma_desc), + hs_ep->desc_list, hs_ep->desc_list_dma); + hs_ep->desc_list = NULL; + } + epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index); spin_lock_irqsave(&hsotg->lock, flags); |