void (*push_to)(struct push_buffer *,
struct mem_mgr *, struct mem_handle *,
u32 op1, u32 op2);
+ void (*_push_to)(struct push_buffer *,
+ dma_addr_t iova,
+ u32 op1, u32 op2);
void (*pop_from)(struct push_buffer *,
unsigned int slots);
u32 (*space)(struct push_buffer *);
pb->cur = (cur + 8) & (PUSH_BUFFER_SIZE - 1);
}
+static void _push_buffer_push_to(struct push_buffer *pb,
+ dma_addr_t iova,
+ u32 op1, u32 op2)
+{
+ u32 cur = pb->cur;
+ u32 *p = (u32 *)((uintptr_t)pb->mapped + cur);
+ u32 cur_nvmap = (cur/8) & (NVHOST_GATHER_QUEUE_SIZE - 1);
+ WARN_ON(cur == pb->fence);
+ *(p++) = op1;
+ *(p++) = op2;
+ pb->client_handle[cur_nvmap].iova = iova;
+ pb->cur = (cur + 8) & (PUSH_BUFFER_SIZE - 1);
+}
+
/**
* Pop a number of two word slots from the push buffer
* Caller must ensure push buffer is not empty
struct mem_mgr_handle *h = &pb->client_handle[cur_fence_nvmap];
h->client = NULL;
h->handle = NULL;
+ h->iova = 0;
}
/* Advance the next write position */
pb->fence = (pb->fence + slots * 8) & (PUSH_BUFFER_SIZE - 1);
.init = push_buffer_init,
.destroy = push_buffer_destroy,
.push_to = push_buffer_push_to,
+ ._push_to = _push_buffer_push_to,
.pop_from = push_buffer_pop_from,
.space = push_buffer_space,
.putptr = push_buffer_putptr,
*
* Tegra Graphics Host HOST1X Hardware Context Interface
*
- * Copyright (c) 2012-2013, NVIDIA Corporation.
+ * Copyright (c) 2012-2013, NVIDIA Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
struct sg_table *restore_sgt;
dma_addr_t restore_phys;
u32 restore_size;
+ u32 *cpuva;
+ dma_addr_t iova;
};
struct host1x_hwctx_handler {
}
}
+static void _trace_write_gather(struct nvhost_cdma *cdma,
+ u32 *cpuva, dma_addr_t iova,
+ u32 offset, u32 words)
+{
+ if (iova) {
+ u32 i;
+ /*
+ * Write in batches of 128 as there seems to be a limit
+ * of how much you can output to ftrace at once.
+ */
+ for (i = 0; i < words; i += TRACE_MAX_LENGTH) {
+ trace_nvhost_cdma_push_gather(
+ cdma_to_channel(cdma)->dev->name,
+ (u32)((uintptr_t)iova),
+ min(words - i, TRACE_MAX_LENGTH),
+ offset + i * sizeof(u32),
+ cpuva);
+ }
+ }
+}
+
/**
* Push two words into a push buffer slot
* Blocks as necessary if the push buffer is full.
cdma_pb_op().push_to(pb, client, handle, op1, op2);
}
+void _nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
+ u32 *cpuva, dma_addr_t iova,
+ u32 offset, u32 op1, u32 op2)
+{
+ u32 slots_free = cdma->slots_free;
+ struct push_buffer *pb = &cdma->push_buffer;
+
+ if (iova)
+ _trace_write_gather(cdma, cpuva, iova, offset, op1 & 0x1fff);
+
+ if (slots_free == 0) {
+ cdma_op().kick(cdma);
+ slots_free = nvhost_cdma_wait_locked(cdma,
+ CDMA_EVENT_PUSH_BUFFER_SPACE);
+ }
+ cdma->slots_free = slots_free - 1;
+ cdma->slots_used++;
+ cdma_pb_op()._push_to(pb, iova, op1, op2);
+}
+
/**
* End a cdma submit
* Kick off DMA, add job to the sync queue, and a number of slots to be freed
struct mem_mgr_handle {
struct mem_mgr *client;
struct mem_handle *handle;
+ dma_addr_t iova;
};
struct push_buffer {
void nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
struct mem_mgr *client,
struct mem_handle *handle, u32 offset, u32 op1, u32 op2);
+void _nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
+ u32 *cpuva, dma_addr_t iova,
+ u32 offset, u32 op1, u32 op2);
void nvhost_cdma_end(struct nvhost_cdma *cdma,
struct nvhost_job *job);
void nvhost_cdma_update(struct nvhost_cdma *cdma);