Skip to content

Commit

Permalink
usb: dwc3: convert TRBs into bitshifts
Browse files Browse the repository at this point in the history
this will get rid of a useless memcpy on
IRQ handling, thus improving driver performance.

Tested with OMAP5430 running g_mass_storage on
SuperSpeed and HighSpeed.

Note that we are removing the little endian access
of the TRB and all accesses will be in System endianness,
if there happens to be a system in BE, bit 12 of GSBUSCFG0
should be set so that HW does byte invariant BE accesses
when fetching TRBs.

Signed-off-by: Felipe Balbi <balbi@ti.com>
  • Loading branch information
Felipe Balbi committed Feb 13, 2012
1 parent 3b63736 commit f6bafc6
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 162 deletions.
142 changes: 38 additions & 104 deletions drivers/usb/dwc3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@

/* Structures */

struct dwc3_trb_hw;
struct dwc3_trb;

/**
* struct dwc3_event_buffer - Software event buffer representation
Expand Down Expand Up @@ -356,7 +356,7 @@ struct dwc3_ep {
struct list_head request_list;
struct list_head req_queued;

struct dwc3_trb_hw *trb_pool;
struct dwc3_trb *trb_pool;
dma_addr_t trb_pool_dma;
u32 free_slot;
u32 busy_slot;
Expand Down Expand Up @@ -431,102 +431,49 @@ enum dwc3_device_state {
DWC3_CONFIGURED_STATE,
};

/**
* struct dwc3_trb - transfer request block
* @bpl: lower 32bit of the buffer
* @bph: higher 32bit of the buffer
* @length: buffer size (up to 16mb - 1)
* @pcm1: packet count m1
* @trbsts: trb status
* 0 = ok
* 1 = missed isoc
* 2 = setup pending
* @hwo: hardware owner of descriptor
* @lst: last trb
* @chn: chain buffers
* @csp: continue on short packets (only supported on isoc eps)
* @trbctl: trb control
* 1 = normal
* 2 = control-setup
* 3 = control-status-2
* 4 = control-status-3
* 5 = control-data (first trb of data stage)
* 6 = isochronous-first (first trb of service interval)
* 7 = isochronous
* 8 = link trb
* others = reserved
* @isp_imi: interrupt on short packet / interrupt on missed isoc
* @ioc: interrupt on complete
* @sid_sofn: Stream ID / SOF Number
*/
struct dwc3_trb {
u64 bplh;

union {
struct {
u32 length:24;
u32 pcm1:2;
u32 reserved27_26:2;
u32 trbsts:4;
#define DWC3_TRB_STS_OKAY 0
#define DWC3_TRB_STS_MISSED_ISOC 1
#define DWC3_TRB_STS_SETUP_PENDING 2
};
u32 len_pcm;
};

union {
struct {
u32 hwo:1;
u32 lst:1;
u32 chn:1;
u32 csp:1;
u32 trbctl:6;
u32 isp_imi:1;
u32 ioc:1;
u32 reserved13_12:2;
u32 sid_sofn:16;
u32 reserved31_30:2;
};
u32 control;
};
} __packed;
/* TRB Length, PCM and Status */
#define DWC3_TRB_SIZE_MASK (0x00ffffff)
#define DWC3_TRB_SIZE_LENGTH(n) ((n) & DWC3_TRB_SIZE_MASK)
#define DWC3_TRB_SIZE_PCM1(n) (((n) & 0x03) << 24)
#define DWC3_TRB_SIZE_TRBSTS(n) (((n) & (0x0f << 28) >> 28))

#define DWC3_TRBSTS_OK 0
#define DWC3_TRBSTS_MISSED_ISOC 1
#define DWC3_TRBSTS_SETUP_PENDING 2

/* TRB Control */
#define DWC3_TRB_CTRL_HWO (1 << 0)
#define DWC3_TRB_CTRL_LST (1 << 1)
#define DWC3_TRB_CTRL_CHN (1 << 2)
#define DWC3_TRB_CTRL_CSP (1 << 3)
#define DWC3_TRB_CTRL_TRBCTL(n) (((n) & 0x3f) << 4)
#define DWC3_TRB_CTRL_ISP_IMI (1 << 10)
#define DWC3_TRB_CTRL_IOC (1 << 11)
#define DWC3_TRB_CTRL_SID_SOFN(n) (((n) & 0xffff) << 14)

#define DWC3_TRBCTL_NORMAL DWC3_TRB_CTRL_TRBCTL(1)
#define DWC3_TRBCTL_CONTROL_SETUP DWC3_TRB_CTRL_TRBCTL(2)
#define DWC3_TRBCTL_CONTROL_STATUS2 DWC3_TRB_CTRL_TRBCTL(3)
#define DWC3_TRBCTL_CONTROL_STATUS3 DWC3_TRB_CTRL_TRBCTL(4)
#define DWC3_TRBCTL_CONTROL_DATA DWC3_TRB_CTRL_TRBCTL(5)
#define DWC3_TRBCTL_ISOCHRONOUS_FIRST DWC3_TRB_CTRL_TRBCTL(6)
#define DWC3_TRBCTL_ISOCHRONOUS DWC3_TRB_CTRL_TRBCTL(7)
#define DWC3_TRBCTL_LINK_TRB DWC3_TRB_CTRL_TRBCTL(8)

/**
* struct dwc3_trb_hw - transfer request block (hw format)
* struct dwc3_trb - transfer request block (hw format)
* @bpl: DW0-3
* @bph: DW4-7
* @size: DW8-B
* @trl: DWC-F
*/
struct dwc3_trb_hw {
__le32 bpl;
__le32 bph;
__le32 size;
__le32 ctrl;
struct dwc3_trb {
u32 bpl;
u32 bph;
u32 size;
u32 ctrl;
} __packed;

static inline void dwc3_trb_to_hw(struct dwc3_trb *nat, struct dwc3_trb_hw *hw)
{
hw->bpl = cpu_to_le32(lower_32_bits(nat->bplh));
hw->bph = cpu_to_le32(upper_32_bits(nat->bplh));
hw->size = cpu_to_le32p(&nat->len_pcm);
/* HWO is written last */
hw->ctrl = cpu_to_le32p(&nat->control);
}

static inline void dwc3_trb_to_nat(struct dwc3_trb_hw *hw, struct dwc3_trb *nat)
{
u64 bplh;

bplh = le32_to_cpup(&hw->bpl);
bplh |= (u64) le32_to_cpup(&hw->bph) << 32;
nat->bplh = bplh;

nat->len_pcm = le32_to_cpup(&hw->size);
nat->control = le32_to_cpup(&hw->ctrl);
}

/**
* dwc3_hwparams - copy of HWPARAMS registers
* @hwparams0 - GHWPARAMS0
Expand Down Expand Up @@ -573,7 +520,7 @@ struct dwc3_request {
struct dwc3_ep *dep;

u8 epnum;
struct dwc3_trb_hw *trb;
struct dwc3_trb *trb;
dma_addr_t trb_dma;

unsigned direction:1;
Expand Down Expand Up @@ -624,7 +571,7 @@ struct dwc3_request {
*/
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
struct dwc3_trb_hw *ep0_trb;
struct dwc3_trb *ep0_trb;
void *ep0_bounce;
u8 *setup_buf;
dma_addr_t ctrl_req_addr;
Expand Down Expand Up @@ -691,19 +638,6 @@ struct dwc3 {

/* -------------------------------------------------------------------------- */

#define DWC3_TRBSTS_OK 0
#define DWC3_TRBSTS_MISSED_ISOC 1
#define DWC3_TRBSTS_SETUP_PENDING 2

#define DWC3_TRBCTL_NORMAL 1
#define DWC3_TRBCTL_CONTROL_SETUP 2
#define DWC3_TRBCTL_CONTROL_STATUS2 3
#define DWC3_TRBCTL_CONTROL_STATUS3 4
#define DWC3_TRBCTL_CONTROL_DATA 5
#define DWC3_TRBCTL_ISOCHRONOUS_FIRST 6
#define DWC3_TRBCTL_ISOCHRONOUS 7
#define DWC3_TRBCTL_LINK_TRB 8

/* -------------------------------------------------------------------------- */

struct dwc3_event_type {
Expand Down
34 changes: 16 additions & 18 deletions drivers/usb/dwc3/ep0.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,7 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
u32 len, u32 type)
{
struct dwc3_gadget_ep_cmd_params params;
struct dwc3_trb_hw *trb_hw;
struct dwc3_trb trb;
struct dwc3_trb *trb;
struct dwc3_ep *dep;

int ret;
Expand All @@ -88,19 +87,17 @@ static int dwc3_ep0_start_trans(struct dwc3 *dwc, u8 epnum, dma_addr_t buf_dma,
return 0;
}

trb_hw = dwc->ep0_trb;
memset(&trb, 0, sizeof(trb));
trb = dwc->ep0_trb;

trb.trbctl = type;
trb.bplh = buf_dma;
trb.length = len;
trb->bpl = lower_32_bits(buf_dma);
trb->bph = upper_32_bits(buf_dma);
trb->size = len;
trb->ctrl = type;

trb.hwo = 1;
trb.lst = 1;
trb.ioc = 1;
trb.isp_imi = 1;

dwc3_trb_to_hw(&trb, trb_hw);
trb->ctrl |= (DWC3_TRB_CTRL_HWO
| DWC3_TRB_CTRL_LST
| DWC3_TRB_CTRL_IOC
| DWC3_TRB_CTRL_ISP_IMI);

memset(&params, 0, sizeof(params));
params.param0 = upper_32_bits(dwc->ep0_trb_addr);
Expand Down Expand Up @@ -544,9 +541,10 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
{
struct dwc3_request *r = NULL;
struct usb_request *ur;
struct dwc3_trb trb;
struct dwc3_trb *trb;
struct dwc3_ep *ep0;
u32 transferred;
u32 length;
u8 epnum;

epnum = event->endpoint_number;
Expand All @@ -557,16 +555,16 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
r = next_request(&ep0->request_list);
ur = &r->request;

dwc3_trb_to_nat(dwc->ep0_trb, &trb);
trb = dwc->ep0_trb;
length = trb->size & DWC3_TRB_SIZE_MASK;

if (dwc->ep0_bounced) {

transferred = min_t(u32, ur->length,
ep0->endpoint.maxpacket - trb.length);
ep0->endpoint.maxpacket - length);
memcpy(ur->buf, dwc->ep0_bounce, transferred);
dwc->ep0_bounced = false;
} else {
transferred = ur->length - trb.length;
transferred = ur->length - length;
ur->actual += transferred;
}

Expand Down
Loading

0 comments on commit f6bafc6

Please sign in to comment.