Skip to content

Commit

Permalink
usb: dwc3: gadget: re-factor dwc3_prepare_trbs()
Browse files Browse the repository at this point in the history
In order to make it easier to add SG support,
let's split the big loop out to its own function.

Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Felipe Balbi committed Dec 21, 2011
1 parent 898c608 commit c71fc37
Showing 1 changed file with 78 additions and 68 deletions.
146 changes: 78 additions & 68 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,78 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep,
kfree(req);
}

/**
* dwc3_prepare_one_trb - setup one TRB from one request
* @dep: endpoint for which this request is prepared
* @req: dwc3_request pointer
*/
static int dwc3_prepare_one_trb(struct dwc3_ep *dep,
struct dwc3_request *req, unsigned last)
{
struct dwc3_trb_hw *trb_hw;
struct dwc3_trb trb;

unsigned int cur_slot;

trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
cur_slot = dep->free_slot;
dep->free_slot++;

/* Skip the LINK-TRB on ISOC */
if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
usb_endpoint_xfer_isoc(dep->desc))
return 0;

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

req->trb = trb_hw;

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

if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
trb.sid_sofn = req->request.stream_id;

switch (usb_endpoint_type(dep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
break;

case USB_ENDPOINT_XFER_ISOC:
trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;

/* IOC every DWC3_TRB_NUM / 4 so we can refill */
if (!(cur_slot % (DWC3_TRB_NUM / 4)))
trb.ioc = last;
break;

case USB_ENDPOINT_XFER_BULK:
case USB_ENDPOINT_XFER_INT:
trb.trbctl = DWC3_TRBCTL_NORMAL;
break;
default:
/*
* This is only possible with faulty memory because we
* checked it already :)
*/
BUG();
}

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

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

return 0;
}

/*
* dwc3_prepare_trbs - setup TRBs from requests
* @dep: endpoint for which requests are being prepared
Expand All @@ -552,14 +624,14 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep,
bool starting)
{
struct dwc3_request *req, *n, *ret = NULL;
struct dwc3_trb_hw *trb_hw;
struct dwc3_trb trb;
u32 trbs_left;
unsigned int last_one = 0;

BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM);

/* the first request must not be queued */
trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK;

/*
* if busy & slot are equal than it is either full or empty. If we are
* starting to proceed requests then we are empty. Otherwise we ar
Expand Down Expand Up @@ -594,25 +666,11 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep,
return NULL;

list_for_each_entry_safe(req, n, &dep->request_list, list) {
unsigned int last_one = 0;
unsigned int cur_slot;

trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK];
cur_slot = dep->free_slot;
dep->free_slot++;

/* Skip the LINK-TRB on ISOC */
if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) &&
usb_endpoint_xfer_isoc(dep->desc))
continue;

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

/* Is our TRB pool empty? */
if (!trbs_left)
last_one = 1;

/* Is this the last request? */
if (list_empty(&dep->request_list))
last_one = 1;
Expand All @@ -625,57 +683,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep,
* While we're debugging the problem, as a workaround to
* multiple TRBs handling, use only one TRB at a time.
*/
last_one = 1;

req->trb = trb_hw;
if (!ret)
ret = req;

trb.bplh = req->request.dma;

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

if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable)
trb.sid_sofn = req->request.stream_id;

switch (usb_endpoint_type(dep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP;
break;

case USB_ENDPOINT_XFER_ISOC:
trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST;

/* IOC every DWC3_TRB_NUM / 4 so we can refill */
if (!(cur_slot % (DWC3_TRB_NUM / 4)))
trb.ioc = last_one;
break;

case USB_ENDPOINT_XFER_BULK:
case USB_ENDPOINT_XFER_INT:
trb.trbctl = DWC3_TRBCTL_NORMAL;
break;
default:
/*
* This is only possible with faulty memory because we
* checked it already :)
*/
BUG();
}

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

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

if (last_one)
break;
dwc3_prepare_one_trb(dep, req, true);
ret = req;
break;
}

return ret;
Expand Down

0 comments on commit c71fc37

Please sign in to comment.