summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci-mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci-mem.c')
-rw-r--r--drivers/usb/host/xhci-mem.c84
1 files changed, 53 insertions, 31 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 21cd03b662a..72b75306265 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -64,8 +64,9 @@ void xhci_inval_cache(uintptr_t addr, u32 len)
* @param ptr pointer to "segement" to be freed
* Return: none
*/
-static void xhci_segment_free(struct xhci_segment *seg)
+static void xhci_segment_free(struct xhci_ctrl *ctrl, struct xhci_segment *seg)
{
+ xhci_dma_unmap(ctrl, seg->dma, SEGMENT_SIZE);
free(seg->trbs);
seg->trbs = NULL;
@@ -78,7 +79,7 @@ static void xhci_segment_free(struct xhci_segment *seg)
* @param ptr pointer to "ring" to be freed
* Return: none
*/
-static void xhci_ring_free(struct xhci_ring *ring)
+static void xhci_ring_free(struct xhci_ctrl *ctrl, struct xhci_ring *ring)
{
struct xhci_segment *seg;
struct xhci_segment *first_seg;
@@ -89,10 +90,10 @@ static void xhci_ring_free(struct xhci_ring *ring)
seg = first_seg->next;
while (seg != first_seg) {
struct xhci_segment *next = seg->next;
- xhci_segment_free(seg);
+ xhci_segment_free(ctrl, seg);
seg = next;
}
- xhci_segment_free(first_seg);
+ xhci_segment_free(ctrl, first_seg);
free(ring);
}
@@ -105,12 +106,20 @@ static void xhci_ring_free(struct xhci_ring *ring)
*/
static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
{
+ struct xhci_hccr *hccr = ctrl->hccr;
+ int num_sp;
+
if (!ctrl->scratchpad)
return;
+ num_sp = HCS_MAX_SCRATCHPAD(xhci_readl(&hccr->cr_hcsparams2));
+ xhci_dma_unmap(ctrl, ctrl->scratchpad->sp_array[0],
+ num_sp * ctrl->page_size);
+ xhci_dma_unmap(ctrl, ctrl->dcbaa->dev_context_ptrs[0],
+ num_sp * sizeof(u64));
ctrl->dcbaa->dev_context_ptrs[0] = 0;
- free(xhci_bus_to_virt(ctrl, le64_to_cpu(ctrl->scratchpad->sp_array[0])));
+ free(ctrl->scratchpad->scratchpad);
free(ctrl->scratchpad->sp_array);
free(ctrl->scratchpad);
ctrl->scratchpad = NULL;
@@ -122,8 +131,10 @@ static void xhci_scratchpad_free(struct xhci_ctrl *ctrl)
* @param ptr pointer to "xhci_container_ctx" to be freed
* Return: none
*/
-static void xhci_free_container_ctx(struct xhci_container_ctx *ctx)
+static void xhci_free_container_ctx(struct xhci_ctrl *ctrl,
+ struct xhci_container_ctx *ctx)
{
+ xhci_dma_unmap(ctrl, ctx->dma, ctx->size);
free(ctx->bytes);
free(ctx);
}
@@ -153,12 +164,12 @@ static void xhci_free_virt_devices(struct xhci_ctrl *ctrl)
for (i = 0; i < 31; ++i)
if (virt_dev->eps[i].ring)
- xhci_ring_free(virt_dev->eps[i].ring);
+ xhci_ring_free(ctrl, virt_dev->eps[i].ring);
if (virt_dev->in_ctx)
- xhci_free_container_ctx(virt_dev->in_ctx);
+ xhci_free_container_ctx(ctrl, virt_dev->in_ctx);
if (virt_dev->out_ctx)
- xhci_free_container_ctx(virt_dev->out_ctx);
+ xhci_free_container_ctx(ctrl, virt_dev->out_ctx);
free(virt_dev);
/* make sure we are pointing to NULL */
@@ -174,11 +185,15 @@ static void xhci_free_virt_devices(struct xhci_ctrl *ctrl)
*/
void xhci_cleanup(struct xhci_ctrl *ctrl)
{
- xhci_ring_free(ctrl->event_ring);
- xhci_ring_free(ctrl->cmd_ring);
+ xhci_ring_free(ctrl, ctrl->event_ring);
+ xhci_ring_free(ctrl, ctrl->cmd_ring);
xhci_scratchpad_free(ctrl);
xhci_free_virt_devices(ctrl);
+ xhci_dma_unmap(ctrl, ctrl->erst.erst_dma_addr,
+ sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS);
free(ctrl->erst.entries);
+ xhci_dma_unmap(ctrl, ctrl->dcbaa->dma,
+ sizeof(struct xhci_device_context_array));
free(ctrl->dcbaa);
memset(ctrl, '\0', sizeof(struct xhci_ctrl));
}
@@ -218,15 +233,13 @@ static void xhci_link_segments(struct xhci_ctrl *ctrl, struct xhci_segment *prev
struct xhci_segment *next, bool link_trbs)
{
u32 val;
- u64 val_64 = 0;
if (!prev || !next)
return;
prev->next = next;
if (link_trbs) {
- val_64 = xhci_virt_to_bus(ctrl, next->trbs);
prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
- cpu_to_le64(val_64);
+ cpu_to_le64(next->dma);
/*
* Set the last TRB in the segment to
@@ -273,7 +286,7 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring)
* @param none
* Return: pointer to the newly allocated SEGMENT
*/
-static struct xhci_segment *xhci_segment_alloc(void)
+static struct xhci_segment *xhci_segment_alloc(struct xhci_ctrl *ctrl)
{
struct xhci_segment *seg;
@@ -281,6 +294,7 @@ static struct xhci_segment *xhci_segment_alloc(void)
BUG_ON(!seg);
seg->trbs = xhci_malloc(SEGMENT_SIZE);
+ seg->dma = xhci_dma_map(ctrl, seg->trbs, SEGMENT_SIZE);
seg->next = NULL;
@@ -314,7 +328,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
if (num_segs == 0)
return ring;
- ring->first_seg = xhci_segment_alloc();
+ ring->first_seg = xhci_segment_alloc(ctrl);
BUG_ON(!ring->first_seg);
num_segs--;
@@ -323,7 +337,7 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_ctrl *ctrl, unsigned int num_segs,
while (num_segs > 0) {
struct xhci_segment *next;
- next = xhci_segment_alloc();
+ next = xhci_segment_alloc(ctrl);
BUG_ON(!next);
xhci_link_segments(ctrl, prev, next, link_trbs);
@@ -372,7 +386,8 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
if (!scratchpad->sp_array)
goto fail_sp2;
- val_64 = xhci_virt_to_bus(ctrl, scratchpad->sp_array);
+ val_64 = xhci_dma_map(ctrl, scratchpad->sp_array,
+ num_sp * sizeof(u64));
ctrl->dcbaa->dev_context_ptrs[0] = cpu_to_le64(val_64);
xhci_flush_cache((uintptr_t)&ctrl->dcbaa->dev_context_ptrs[0],
@@ -386,16 +401,18 @@ static int xhci_scratchpad_alloc(struct xhci_ctrl *ctrl)
}
BUG_ON(i == 16);
- page_size = 1 << (i + 12);
- buf = memalign(page_size, num_sp * page_size);
+ ctrl->page_size = 1 << (i + 12);
+ buf = memalign(ctrl->page_size, num_sp * ctrl->page_size);
if (!buf)
goto fail_sp3;
- memset(buf, '\0', num_sp * page_size);
- xhci_flush_cache((uintptr_t)buf, num_sp * page_size);
+ memset(buf, '\0', num_sp * ctrl->page_size);
+ xhci_flush_cache((uintptr_t)buf, num_sp * ctrl->page_size);
+ scratchpad->scratchpad = buf;
+ val_64 = xhci_dma_map(ctrl, buf, num_sp * ctrl->page_size);
for (i = 0; i < num_sp; i++) {
- val_64 = xhci_virt_to_bus(ctrl, buf + i * page_size);
scratchpad->sp_array[i] = cpu_to_le64(val_64);
+ val_64 += ctrl->page_size;
}
xhci_flush_cache((uintptr_t)scratchpad->sp_array,
@@ -437,6 +454,7 @@ static struct xhci_container_ctx
ctx->size += CTX_SIZE(xhci_readl(&ctrl->hccr->cr_hccparams));
ctx->bytes = xhci_malloc(ctx->size);
+ ctx->dma = xhci_dma_map(ctrl, ctx->bytes, ctx->size);
return ctx;
}
@@ -487,7 +505,7 @@ int xhci_alloc_virt_device(struct xhci_ctrl *ctrl, unsigned int slot_id)
/* Allocate endpoint 0 ring */
virt_dev->eps[0].ring = xhci_ring_alloc(ctrl, 1, true);
- byte_64 = xhci_virt_to_bus(ctrl, virt_dev->out_ctx->bytes);
+ byte_64 = virt_dev->out_ctx->dma;
/* Point to output device context in dcbaa. */
ctrl->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(byte_64);
@@ -523,15 +541,16 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
return -ENOMEM;
}
- val_64 = xhci_virt_to_bus(ctrl, ctrl->dcbaa);
+ ctrl->dcbaa->dma = xhci_dma_map(ctrl, ctrl->dcbaa,
+ sizeof(struct xhci_device_context_array));
/* Set the pointer in DCBAA register */
- xhci_writeq(&hcor->or_dcbaap, val_64);
+ xhci_writeq(&hcor->or_dcbaap, ctrl->dcbaa->dma);
/* Command ring control pointer register initialization */
ctrl->cmd_ring = xhci_ring_alloc(ctrl, 1, true);
/* Set the address in the Command Ring Control register */
- trb_64 = xhci_virt_to_bus(ctrl, ctrl->cmd_ring->first_seg->trbs);
+ trb_64 = ctrl->cmd_ring->first_seg->dma;
val_64 = xhci_readq(&hcor->or_crcr);
val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
(trb_64 & (u64) ~CMD_RING_RSVD_BITS) |
@@ -555,6 +574,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
ctrl->event_ring = xhci_ring_alloc(ctrl, ERST_NUM_SEGS, false);
ctrl->erst.entries = xhci_malloc(sizeof(struct xhci_erst_entry) *
ERST_NUM_SEGS);
+ ctrl->erst.erst_dma_addr = xhci_dma_map(ctrl, ctrl->erst.entries,
+ sizeof(struct xhci_erst_entry) * ERST_NUM_SEGS);
ctrl->erst.num_entries = ERST_NUM_SEGS;
@@ -562,7 +583,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
val < ERST_NUM_SEGS;
val++) {
struct xhci_erst_entry *entry = &ctrl->erst.entries[val];
- trb_64 = xhci_virt_to_bus(ctrl, seg->trbs);
+ trb_64 = seg->dma;
entry->seg_addr = cpu_to_le64(trb_64);
entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
entry->rsvd = 0;
@@ -571,7 +592,8 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
xhci_flush_cache((uintptr_t)ctrl->erst.entries,
ERST_NUM_SEGS * sizeof(struct xhci_erst_entry));
- deq = xhci_virt_to_bus(ctrl, ctrl->event_ring->dequeue);
+ deq = xhci_trb_virt_to_dma(ctrl->event_ring->deq_seg,
+ ctrl->event_ring->dequeue);
/* Update HC event ring dequeue pointer */
xhci_writeq(&ctrl->ir_set->erst_dequeue,
@@ -586,7 +608,7 @@ int xhci_mem_init(struct xhci_ctrl *ctrl, struct xhci_hccr *hccr,
/* this is the event ring segment table pointer */
val_64 = xhci_readq(&ctrl->ir_set->erst_base);
val_64 &= ERST_PTR_MASK;
- val_64 |= xhci_virt_to_bus(ctrl, ctrl->erst.entries) & ~ERST_PTR_MASK;
+ val_64 |= ctrl->erst.erst_dma_addr & ~ERST_PTR_MASK;
xhci_writeq(&ctrl->ir_set->erst_base, val_64);
@@ -849,7 +871,7 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl,
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3));
- trb_64 = xhci_virt_to_bus(ctrl, virt_dev->eps[0].ring->first_seg->trbs);
+ trb_64 = virt_dev->eps[0].ring->first_seg->dma;
ep0_ctx->deq = cpu_to_le64(trb_64 | virt_dev->eps[0].ring->cycle_state);
/*