Loading drivers/usb/dwc3/gadget.c +98 −17 Original line number Original line Diff line number Diff line Loading @@ -65,6 +65,22 @@ void dwc3_map_buffer_to_dma(struct dwc3_request *req) return; return; } } if (req->request.num_sgs) { int mapped; mapped = dma_map_sg(dwc->dev, req->request.sg, req->request.num_sgs, req->direction ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (mapped < 0) { dev_err(dwc->dev, "failed to map SGs\n"); return; } req->request.num_mapped_sgs = mapped; return; } if (req->request.dma == DMA_ADDR_INVALID) { if (req->request.dma == DMA_ADDR_INVALID) { req->request.dma = dma_map_single(dwc->dev, req->request.buf, req->request.dma = dma_map_single(dwc->dev, req->request.buf, req->request.length, req->direction req->request.length, req->direction Loading @@ -82,6 +98,17 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) return; return; } } if (req->request.num_mapped_sgs) { req->request.dma = DMA_ADDR_INVALID; dma_unmap_sg(dwc->dev, req->request.sg, req->request.num_sgs, req->direction ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->request.num_mapped_sgs = 0; return; } if (req->mapped) { if (req->mapped) { dma_unmap_single(dwc->dev, req->request.dma, dma_unmap_single(dwc->dev, req->request.dma, req->request.length, req->direction req->request.length, req->direction Loading @@ -97,7 +124,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc; if (req->queued) { if (req->queued) { if (req->request.num_mapped_sgs) dep->busy_slot += req->request.num_mapped_sgs; else dep->busy_slot++; dep->busy_slot++; /* /* * Skip LINK TRB. We can't use req->trb and check for * Skip LINK TRB. We can't use req->trb and check for * DWC3_TRBCTL_LINK_TRB because it points the TRB we just * DWC3_TRBCTL_LINK_TRB because it points the TRB we just Loading @@ -108,6 +139,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, dep->busy_slot++; dep->busy_slot++; } } list_del(&req->list); list_del(&req->list); req->trb = NULL; if (req->request.status == -EINPROGRESS) if (req->request.status == -EINPROGRESS) req->request.status = status; req->request.status = status; Loading Loading @@ -545,13 +577,20 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, * @req: dwc3_request pointer * @req: dwc3_request pointer */ */ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, static void dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_request *req, unsigned last) struct dwc3_request *req, dma_addr_t dma, unsigned length, unsigned last, unsigned chain) { { struct dwc3 *dwc = dep->dwc; struct dwc3_trb_hw *trb_hw; struct dwc3_trb_hw *trb_hw; struct dwc3_trb trb; struct dwc3_trb trb; unsigned int cur_slot; unsigned int cur_slot; dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n", dep->name, req, (unsigned long long) dma, length, last ? " last" : "", chain ? " chain" : ""); trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; cur_slot = dep->free_slot; cur_slot = dep->free_slot; dep->free_slot++; dep->free_slot++; Loading @@ -561,15 +600,18 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, usb_endpoint_xfer_isoc(dep->desc)) usb_endpoint_xfer_isoc(dep->desc)) return; return; dwc3_gadget_move_request_queued(req); memset(&trb, 0, sizeof(trb)); memset(&trb, 0, sizeof(trb)); if (!req->trb) { dwc3_gadget_move_request_queued(req); req->trb = trb_hw; req->trb = trb_hw; req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); } if (usb_endpoint_xfer_isoc(dep->desc)) { if (usb_endpoint_xfer_isoc(dep->desc)) { trb.isp_imi = true; trb.isp_imi = true; trb.csp = true; trb.csp = true; } else { } else { trb.chn = chain; trb.lst = last; trb.lst = last; } } Loading Loading @@ -601,12 +643,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); BUG(); } } trb.length = req->request.length; trb.length = length; trb.bplh = req->request.dma; trb.bplh = dma; trb.hwo = true; trb.hwo = true; dwc3_trb_to_hw(&trb, trb_hw); dwc3_trb_to_hw(&trb, trb_hw); req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); } } /* /* Loading Loading @@ -663,21 +704,60 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) return; return; list_for_each_entry_safe(req, n, &dep->request_list, list) { list_for_each_entry_safe(req, n, &dep->request_list, list) { unsigned length; dma_addr_t dma; if (req->request.num_mapped_sgs > 0) { struct usb_request *request = &req->request; struct scatterlist *sg = request->sg; struct scatterlist *s; int i; for_each_sg(sg, s, request->num_mapped_sgs, i) { unsigned chain = true; length = sg_dma_len(s); dma = sg_dma_address(s); if (i == (request->num_mapped_sgs - 1) || sg_is_last(s)) { last_one = true; chain = false; } trbs_left--; if (!trbs_left) last_one = true; if (last_one) chain = false; dwc3_prepare_one_trb(dep, req, dma, length, last_one, chain); if (last_one) break; } } else { dma = req->request.dma; length = req->request.length; trbs_left--; trbs_left--; if (!trbs_left) if (!trbs_left) last_one = 1; last_one = 1; /* Is this the last request? */ /* Is this the last request? */ if (list_empty(&dep->request_list)) if (list_is_last(&req->list, &dep->request_list)) last_one = 1; last_one = 1; dwc3_prepare_one_trb(dep, req, last_one); dwc3_prepare_one_trb(dep, req, dma, length, last_one, false); if (last_one) if (last_one) break; break; } } } } } static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, int start_new) int start_new) Loading Loading @@ -1989,6 +2069,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.dev.parent = dwc->dev; dwc->gadget.dev.parent = dwc->dev; dwc->gadget.sg_supported = true; dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); Loading Loading
drivers/usb/dwc3/gadget.c +98 −17 Original line number Original line Diff line number Diff line Loading @@ -65,6 +65,22 @@ void dwc3_map_buffer_to_dma(struct dwc3_request *req) return; return; } } if (req->request.num_sgs) { int mapped; mapped = dma_map_sg(dwc->dev, req->request.sg, req->request.num_sgs, req->direction ? DMA_TO_DEVICE : DMA_FROM_DEVICE); if (mapped < 0) { dev_err(dwc->dev, "failed to map SGs\n"); return; } req->request.num_mapped_sgs = mapped; return; } if (req->request.dma == DMA_ADDR_INVALID) { if (req->request.dma == DMA_ADDR_INVALID) { req->request.dma = dma_map_single(dwc->dev, req->request.buf, req->request.dma = dma_map_single(dwc->dev, req->request.buf, req->request.length, req->direction req->request.length, req->direction Loading @@ -82,6 +98,17 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) return; return; } } if (req->request.num_mapped_sgs) { req->request.dma = DMA_ADDR_INVALID; dma_unmap_sg(dwc->dev, req->request.sg, req->request.num_sgs, req->direction ? DMA_TO_DEVICE : DMA_FROM_DEVICE); req->request.num_mapped_sgs = 0; return; } if (req->mapped) { if (req->mapped) { dma_unmap_single(dwc->dev, req->request.dma, dma_unmap_single(dwc->dev, req->request.dma, req->request.length, req->direction req->request.length, req->direction Loading @@ -97,7 +124,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, struct dwc3 *dwc = dep->dwc; struct dwc3 *dwc = dep->dwc; if (req->queued) { if (req->queued) { if (req->request.num_mapped_sgs) dep->busy_slot += req->request.num_mapped_sgs; else dep->busy_slot++; dep->busy_slot++; /* /* * Skip LINK TRB. We can't use req->trb and check for * Skip LINK TRB. We can't use req->trb and check for * DWC3_TRBCTL_LINK_TRB because it points the TRB we just * DWC3_TRBCTL_LINK_TRB because it points the TRB we just Loading @@ -108,6 +139,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, dep->busy_slot++; dep->busy_slot++; } } list_del(&req->list); list_del(&req->list); req->trb = NULL; if (req->request.status == -EINPROGRESS) if (req->request.status == -EINPROGRESS) req->request.status = status; req->request.status = status; Loading Loading @@ -545,13 +577,20 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, * @req: dwc3_request pointer * @req: dwc3_request pointer */ */ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, static void dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_request *req, unsigned last) struct dwc3_request *req, dma_addr_t dma, unsigned length, unsigned last, unsigned chain) { { struct dwc3 *dwc = dep->dwc; struct dwc3_trb_hw *trb_hw; struct dwc3_trb_hw *trb_hw; struct dwc3_trb trb; struct dwc3_trb trb; unsigned int cur_slot; unsigned int cur_slot; dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n", dep->name, req, (unsigned long long) dma, length, last ? " last" : "", chain ? " chain" : ""); trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; cur_slot = dep->free_slot; cur_slot = dep->free_slot; dep->free_slot++; dep->free_slot++; Loading @@ -561,15 +600,18 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, usb_endpoint_xfer_isoc(dep->desc)) usb_endpoint_xfer_isoc(dep->desc)) return; return; dwc3_gadget_move_request_queued(req); memset(&trb, 0, sizeof(trb)); memset(&trb, 0, sizeof(trb)); if (!req->trb) { dwc3_gadget_move_request_queued(req); req->trb = trb_hw; req->trb = trb_hw; req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); } if (usb_endpoint_xfer_isoc(dep->desc)) { if (usb_endpoint_xfer_isoc(dep->desc)) { trb.isp_imi = true; trb.isp_imi = true; trb.csp = true; trb.csp = true; } else { } else { trb.chn = chain; trb.lst = last; trb.lst = last; } } Loading Loading @@ -601,12 +643,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, BUG(); BUG(); } } trb.length = req->request.length; trb.length = length; trb.bplh = req->request.dma; trb.bplh = dma; trb.hwo = true; trb.hwo = true; dwc3_trb_to_hw(&trb, trb_hw); dwc3_trb_to_hw(&trb, trb_hw); req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); } } /* /* Loading Loading @@ -663,21 +704,60 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) return; return; list_for_each_entry_safe(req, n, &dep->request_list, list) { list_for_each_entry_safe(req, n, &dep->request_list, list) { unsigned length; dma_addr_t dma; if (req->request.num_mapped_sgs > 0) { struct usb_request *request = &req->request; struct scatterlist *sg = request->sg; struct scatterlist *s; int i; for_each_sg(sg, s, request->num_mapped_sgs, i) { unsigned chain = true; length = sg_dma_len(s); dma = sg_dma_address(s); if (i == (request->num_mapped_sgs - 1) || sg_is_last(s)) { last_one = true; chain = false; } trbs_left--; if (!trbs_left) last_one = true; if (last_one) chain = false; dwc3_prepare_one_trb(dep, req, dma, length, last_one, chain); if (last_one) break; } } else { dma = req->request.dma; length = req->request.length; trbs_left--; trbs_left--; if (!trbs_left) if (!trbs_left) last_one = 1; last_one = 1; /* Is this the last request? */ /* Is this the last request? */ if (list_empty(&dep->request_list)) if (list_is_last(&req->list, &dep->request_list)) last_one = 1; last_one = 1; dwc3_prepare_one_trb(dep, req, last_one); dwc3_prepare_one_trb(dep, req, dma, length, last_one, false); if (last_one) if (last_one) break; break; } } } } } static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, int start_new) int start_new) Loading Loading @@ -1989,6 +2069,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.max_speed = USB_SPEED_SUPER; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.speed = USB_SPEED_UNKNOWN; dwc->gadget.dev.parent = dwc->dev; dwc->gadget.dev.parent = dwc->dev; dwc->gadget.sg_supported = true; dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); Loading