Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 280939
b: refs/heads/master
c: eeb720f
h: refs/heads/master
i:
  280937: d2c2946
  280935: d89a1f4
v: v3
  • Loading branch information
Felipe Balbi committed Dec 21, 2011
1 parent 2d5f35b commit f54660a
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 18 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 42f8eb7a1087442e9710ce75b355c0f28aadbf96
refs/heads/master: eeb720fb21d61dfc3aac780e721150998ef603af
115 changes: 98 additions & 17 deletions trunk/drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@ void dwc3_map_buffer_to_dma(struct dwc3_request *req)
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) {
req->request.dma = dma_map_single(dwc->dev, req->request.buf,
req->request.length, req->direction
Expand All @@ -82,6 +98,17 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req)
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) {
dma_unmap_single(dwc->dev, req->request.dma,
req->request.length, req->direction
Expand All @@ -97,7 +124,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
struct dwc3 *dwc = dep->dwc;

if (req->queued) {
dep->busy_slot++;
if (req->request.num_mapped_sgs)
dep->busy_slot += req->request.num_mapped_sgs;
else
dep->busy_slot++;

/*
* Skip LINK TRB. We can't use req->trb and check for
* DWC3_TRBCTL_LINK_TRB because it points the TRB we just
Expand All @@ -108,6 +139,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
dep->busy_slot++;
}
list_del(&req->list);
req->trb = NULL;

if (req->request.status == -EINPROGRESS)
req->request.status = status;
Expand Down Expand Up @@ -545,13 +577,20 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
* @req: dwc3_request pointer
*/
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 trb;

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];
cur_slot = dep->free_slot;
dep->free_slot++;
Expand All @@ -561,15 +600,18 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
usb_endpoint_xfer_isoc(dep->desc))
return;

dwc3_gadget_move_request_queued(req);
memset(&trb, 0, sizeof(trb));

req->trb = trb_hw;
if (!req->trb) {
dwc3_gadget_move_request_queued(req);
req->trb = trb_hw;
req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw);
}

if (usb_endpoint_xfer_isoc(dep->desc)) {
trb.isp_imi = true;
trb.csp = true;
} else {
trb.chn = chain;
trb.lst = last;
}

Expand Down Expand Up @@ -601,12 +643,11 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
BUG();
}

trb.length = req->request.length;
trb.bplh = req->request.dma;
trb.length = length;
trb.bplh = dma;
trb.hwo = true;

dwc3_trb_to_hw(&trb, trb_hw);
req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw);
}

/*
Expand Down Expand Up @@ -663,19 +704,58 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting)
return;

list_for_each_entry_safe(req, n, &dep->request_list, list) {
trbs_left--;
unsigned length;
dma_addr_t dma;

if (!trbs_left)
last_one = 1;
if (req->request.num_mapped_sgs > 0) {
struct usb_request *request = &req->request;
struct scatterlist *sg = request->sg;
struct scatterlist *s;
int i;

/* Is this the last request? */
if (list_empty(&dep->request_list))
last_one = 1;
for_each_sg(sg, s, request->num_mapped_sgs, i) {
unsigned chain = true;

dwc3_prepare_one_trb(dep, req, last_one);
length = sg_dma_len(s);
dma = sg_dma_address(s);

if (last_one)
break;
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--;

if (!trbs_left)
last_one = 1;

/* Is this the last request? */
if (list_is_last(&req->list, &dep->request_list))
last_one = 1;

dwc3_prepare_one_trb(dep, req, dma, length,
last_one, false);

if (last_one)
break;
}
}
}

Expand Down Expand Up @@ -1989,6 +2069,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc)
dwc->gadget.max_speed = USB_SPEED_SUPER;
dwc->gadget.speed = USB_SPEED_UNKNOWN;
dwc->gadget.dev.parent = dwc->dev;
dwc->gadget.sg_supported = true;

dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask);

Expand Down

0 comments on commit f54660a

Please sign in to comment.