summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/video/tegra/host/bus_client.c17
-rw-r--r--drivers/video/tegra/host/chip_support.h4
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t20.c2
-rw-r--r--drivers/video/tegra/host/gr3d/gr3d_t30.c2
-rw-r--r--drivers/video/tegra/host/host1x/host1x_cdma.c2
-rw-r--r--drivers/video/tegra/host/host1x/host1x_channel.c4
-rw-r--r--drivers/video/tegra/host/host1x/host1x_debug.c17
-rw-r--r--drivers/video/tegra/host/mpe/mpe.c2
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.c12
-rw-r--r--drivers/video/tegra/host/nvhost_cdma.h4
-rw-r--r--drivers/video/tegra/host/nvhost_channel.h7
-rw-r--r--drivers/video/tegra/host/nvhost_job.c285
-rw-r--r--drivers/video/tegra/host/nvhost_job.h27
-rw-r--r--include/trace/events/nvhost.h18
14 files changed, 171 insertions, 232 deletions
diff --git a/drivers/video/tegra/host/bus_client.c b/drivers/video/tegra/host/bus_client.c
index fd632a6ea9c5..822f8f3a456d 100644
--- a/drivers/video/tegra/host/bus_client.c
+++ b/drivers/video/tegra/host/bus_client.c
@@ -166,7 +166,7 @@ static int set_submit(struct nvhost_channel_userctx *ctx)
return -EFAULT;
}
- ctx->job = nvhost_job_realloc(ctx->job,
+ ctx->job = nvhost_job_alloc(ctx->ch,
ctx->hwctx,
&ctx->hdr,
ctx->nvmap,
@@ -241,13 +241,17 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
consumed = sizeof(struct nvhost_reloc);
if (remaining < consumed)
break;
- if (copy_from_user(&job->pinarray[job->num_pins],
+ if (copy_from_user(&job->pinarray[job->num_relocs],
buf, consumed)) {
err = -EFAULT;
break;
}
- trace_nvhost_channel_write_reloc(chname);
- job->num_pins++;
+ trace_nvhost_channel_write_reloc(chname,
+ job->pinarray[job->num_relocs].patch_mem,
+ job->pinarray[job->num_relocs].patch_offset,
+ job->pinarray[job->num_relocs].pin_mem,
+ job->pinarray[job->num_relocs].pin_offset);
+ job->num_relocs++;
hdr->num_relocs--;
} else if (hdr->num_waitchks) {
int numwaitchks =
@@ -269,7 +273,7 @@ static ssize_t nvhost_channelwrite(struct file *filp, const char __user *buf,
hdr->num_waitchks -= numwaitchks;
} else if (priv->num_relocshifts) {
int next_shift =
- job->num_pins - priv->num_relocshifts;
+ job->num_relocs - priv->num_relocshifts;
consumed = sizeof(struct nvhost_reloc_shift);
if (remaining < consumed)
break;
@@ -337,6 +341,9 @@ static int nvhost_ioctl_channel_flush(
if (err)
nvhost_job_unpin(ctx->job);
+ nvhost_job_put(ctx->job);
+ ctx->job = NULL;
+
return err;
}
diff --git a/drivers/video/tegra/host/chip_support.h b/drivers/video/tegra/host/chip_support.h
index edc5f6a51574..173a36065458 100644
--- a/drivers/video/tegra/host/chip_support.h
+++ b/drivers/video/tegra/host/chip_support.h
@@ -31,7 +31,7 @@ struct nvhost_syncpt;
struct nvhost_waitchk;
struct nvhost_userctx_timeout;
struct nvhost_channel;
-struct nvmap_handle;
+struct nvmap_handle_ref;
struct nvmap_client;
struct nvhost_hwctx;
struct nvhost_cdma;
@@ -77,7 +77,7 @@ struct nvhost_chip_support {
void (*destroy)(struct push_buffer *);
void (*push_to)(struct push_buffer *,
struct nvmap_client *,
- struct nvmap_handle *,
+ struct nvmap_handle_ref *,
u32 op1, u32 op2);
void (*pop_from)(struct push_buffer *,
unsigned int slots);
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t20.c b/drivers/video/tegra/host/gr3d/gr3d_t20.c
index c0efac03b882..5645f5b2b0c6 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t20.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t20.c
@@ -138,7 +138,7 @@ static void save_push_v0(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
nvhost_cdma_push_gather(cdma,
nvhost_get_host(nctx->channel->dev)->nvmap,
- p->save_buf->handle,
+ p->save_buf,
0,
nvhost_opcode_gather(p->save_size),
p->save_phys);
diff --git a/drivers/video/tegra/host/gr3d/gr3d_t30.c b/drivers/video/tegra/host/gr3d/gr3d_t30.c
index 93d98dfa645c..57f4c779eff8 100644
--- a/drivers/video/tegra/host/gr3d/gr3d_t30.c
+++ b/drivers/video/tegra/host/gr3d/gr3d_t30.c
@@ -145,7 +145,7 @@ static void save_push_v1(struct nvhost_hwctx *nctx, struct nvhost_cdma *cdma)
/* gather the save buffer */
nvhost_cdma_push_gather(cdma,
nvhost_get_host(nctx->channel->dev)->nvmap,
- p->save_buf->handle,
+ p->save_buf,
0,
nvhost_opcode_gather(p->save_size),
p->save_phys);
diff --git a/drivers/video/tegra/host/host1x/host1x_cdma.c b/drivers/video/tegra/host/host1x/host1x_cdma.c
index fcb1f05f0025..4569c3d62494 100644
--- a/drivers/video/tegra/host/host1x/host1x_cdma.c
+++ b/drivers/video/tegra/host/host1x/host1x_cdma.c
@@ -137,7 +137,7 @@ static void push_buffer_destroy(struct push_buffer *pb)
*/
static void push_buffer_push_to(struct push_buffer *pb,
struct nvmap_client *client,
- struct nvmap_handle *handle, u32 op1, u32 op2)
+ struct nvmap_handle_ref *handle, u32 op1, u32 op2)
{
u32 cur = pb->cur;
u32 *p = (u32 *)((u32)pb->mapped + cur);
diff --git a/drivers/video/tegra/host/host1x/host1x_channel.c b/drivers/video/tegra/host/host1x/host1x_channel.c
index 8c4a7a5c74ad..0b4d07cb9e47 100644
--- a/drivers/video/tegra/host/host1x/host1x_channel.c
+++ b/drivers/video/tegra/host/host1x/host1x_channel.c
@@ -143,7 +143,7 @@ static void submit_ctxrestore(struct nvhost_job *job)
/* Send restore buffer to channel */
nvhost_cdma_push_gather(&ch->cdma,
host->nvmap,
- nvmap_ref_to_handle(ctx->restore),
+ ctx->restore,
0,
nvhost_opcode_gather(ctx->restore_size),
ctx->restore_phys);
@@ -188,7 +188,7 @@ void submit_gathers(struct nvhost_job *job)
u32 op2 = job->gathers[i].mem;
nvhost_cdma_push_gather(&job->ch->cdma,
job->nvmap,
- nvmap_id_to_handle(job->gathers[i].mem_id),
+ job->gathers[i].ref,
job->gathers[i].offset,
op1, op2);
}
diff --git a/drivers/video/tegra/host/host1x/host1x_debug.c b/drivers/video/tegra/host/host1x/host1x_debug.c
index 76483d82528b..a5574a0fb60a 100644
--- a/drivers/video/tegra/host/host1x/host1x_debug.c
+++ b/drivers/video/tegra/host/host1x/host1x_debug.c
@@ -169,32 +169,27 @@ static void show_channel_gather(struct output *o, u32 addr,
struct push_buffer *pb = &cdma->push_buffer;
u32 cur = addr - pb->phys;
struct nvmap_client_handle *nvmap = &pb->nvmap[cur/8];
- struct nvmap_handle_ref ref;
u32 *map_addr, offset;
phys_addr_t pin_addr;
int state, count, i;
if (!nvmap->handle || !nvmap->client
- || atomic_read(&nvmap->handle->ref) < 1) {
+ || atomic_read(&nvmap->handle->handle->ref) < 1) {
nvhost_debug_output(o, "[already deallocated]\n");
return;
}
- /* Create a fake nvmap_handle_ref - nvmap requires it
- * but accesses only the first field - nvmap_handle */
- ref.handle = nvmap->handle;
-
- map_addr = nvmap_mmap(&ref);
+ map_addr = nvmap_mmap(nvmap->handle);
if (!map_addr) {
nvhost_debug_output(o, "[could not mmap]\n");
return;
}
/* Get base address from nvmap */
- pin_addr = nvmap_pin(nvmap->client, &ref);
+ pin_addr = nvmap_pin(nvmap->client, nvmap->handle);
if (IS_ERR_VALUE(pin_addr)) {
nvhost_debug_output(o, "[couldn't pin]\n");
- nvmap_munmap(&ref, map_addr);
+ nvmap_munmap(nvmap->handle, map_addr);
return;
}
@@ -215,8 +210,8 @@ static void show_channel_gather(struct output *o, u32 addr,
*(map_addr + offset/4 + i),
cdma);
}
- nvmap_unpin(nvmap->client, &ref);
- nvmap_munmap(&ref, map_addr);
+ nvmap_unpin(nvmap->client, nvmap->handle);
+ nvmap_munmap(nvmap->handle, map_addr);
#endif
}
diff --git a/drivers/video/tegra/host/mpe/mpe.c b/drivers/video/tegra/host/mpe/mpe.c
index d8c9da7e9a76..3fe2fcd8bb50 100644
--- a/drivers/video/tegra/host/mpe/mpe.c
+++ b/drivers/video/tegra/host/mpe/mpe.c
@@ -502,7 +502,7 @@ static void ctxmpe_save_push(struct nvhost_hwctx *nctx,
struct host1x_hwctx_handler *h = host1x_hwctx_handler(ctx);
nvhost_cdma_push_gather(cdma,
nvhost_get_host(nctx->channel->dev)->nvmap,
- h->save_buf->handle,
+ h->save_buf,
0,
nvhost_opcode_gather(h->save_size),
h->save_phys);
diff --git a/drivers/video/tegra/host/nvhost_cdma.c b/drivers/video/tegra/host/nvhost_cdma.c
index a72e18f16ac7..b1f138317cc1 100644
--- a/drivers/video/tegra/host/nvhost_cdma.c
+++ b/drivers/video/tegra/host/nvhost_cdma.c
@@ -371,15 +371,13 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job)
}
static void trace_write_gather(struct nvhost_cdma *cdma,
- struct nvmap_handle *handle,
+ struct nvmap_handle_ref *ref,
u32 offset, u32 words)
{
- struct nvmap_handle_ref ref;
void *mem = NULL;
if (nvhost_debug_trace_cmdbuf) {
- ref.handle = handle;
- mem = nvmap_mmap(&ref);
+ mem = nvmap_mmap(ref);
if (IS_ERR_OR_NULL(mem))
mem = NULL;
};
@@ -393,12 +391,12 @@ static void trace_write_gather(struct nvhost_cdma *cdma,
for (i = 0; i < words; i += TRACE_MAX_LENGTH) {
trace_nvhost_cdma_push_gather(
cdma_to_channel(cdma)->dev->name,
- (u32)handle,
+ (u32)ref->handle,
min(words - i, TRACE_MAX_LENGTH),
offset + i * sizeof(u32),
mem);
}
- nvmap_munmap(&ref, mem);
+ nvmap_munmap(ref, mem);
}
}
@@ -421,7 +419,7 @@ void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2)
*/
void nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
struct nvmap_client *client,
- struct nvmap_handle *handle,
+ struct nvmap_handle_ref *handle,
u32 offset, u32 op1, u32 op2)
{
u32 slots_free = cdma->slots_free;
diff --git a/drivers/video/tegra/host/nvhost_cdma.h b/drivers/video/tegra/host/nvhost_cdma.h
index e6f51179150f..98393f0cc765 100644
--- a/drivers/video/tegra/host/nvhost_cdma.h
+++ b/drivers/video/tegra/host/nvhost_cdma.h
@@ -48,7 +48,7 @@ struct nvhost_job;
struct nvmap_client_handle {
struct nvmap_client *client;
- struct nvmap_handle *handle;
+ struct nvmap_handle_ref *handle;
};
struct push_buffer {
@@ -113,7 +113,7 @@ int nvhost_cdma_begin(struct nvhost_cdma *cdma, struct nvhost_job *job);
void nvhost_cdma_push(struct nvhost_cdma *cdma, u32 op1, u32 op2);
void nvhost_cdma_push_gather(struct nvhost_cdma *cdma,
struct nvmap_client *client,
- struct nvmap_handle *handle, u32 offset, u32 op1, u32 op2);
+ struct nvmap_handle_ref *handle, 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);
diff --git a/drivers/video/tegra/host/nvhost_channel.h b/drivers/video/tegra/host/nvhost_channel.h
index eac51731547b..a8f16f0c5abc 100644
--- a/drivers/video/tegra/host/nvhost_channel.h
+++ b/drivers/video/tegra/host/nvhost_channel.h
@@ -36,13 +36,6 @@ struct nvhost_device;
struct nvhost_channel;
struct nvhost_hwctx;
-struct nvhost_channel_gather {
- u32 words;
- phys_addr_t mem;
- u32 mem_id;
- int offset;
-};
-
struct nvhost_channel {
int refcount;
int chid;
diff --git a/drivers/video/tegra/host/nvhost_job.c b/drivers/video/tegra/host/nvhost_job.c
index 71f2ab0e751f..11d65964e2c9 100644
--- a/drivers/video/tegra/host/nvhost_job.c
+++ b/drivers/video/tegra/host/nvhost_job.c
@@ -23,6 +23,7 @@
#include <linux/err.h>
#include <linux/vmalloc.h>
#include <linux/nvmap.h>
+#include <trace/events/nvhost.h>
#include "nvhost_channel.h"
#include "nvhost_job.h"
#include "nvhost_hwctx.h"
@@ -33,128 +34,41 @@
static int job_size(struct nvhost_submit_hdr_ext *hdr)
{
- int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0;
+ int num_relocs = hdr ? hdr->num_relocs : 0;
int num_waitchks = hdr ? hdr->num_waitchks : 0;
+ int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
+ int num_unpins = num_cmdbufs + num_relocs;
return sizeof(struct nvhost_job)
- + num_pins * sizeof(struct nvmap_pinarray_elem)
- + num_pins * sizeof(struct nvmap_handle *)
- + num_waitchks * sizeof(struct nvhost_waitchk);
-}
-
-static int gather_size(int num_cmdbufs)
-{
- return num_cmdbufs * sizeof(struct nvhost_channel_gather);
-}
-
-static void free_gathers(struct nvhost_job *job)
-{
- if (job->gathers) {
- nvmap_munmap(job->gather_mem, job->gathers);
- job->gathers = NULL;
- }
- if (job->gather_mem) {
- nvmap_free(job->nvmap, job->gather_mem);
- job->gather_mem = NULL;
- }
-}
-
-static int alloc_gathers(struct nvhost_job *job,
- int num_cmdbufs)
-{
- int err = 0;
-
- job->gather_mem = NULL;
- job->gathers = NULL;
- job->gather_mem_size = 0;
-
- if (num_cmdbufs) {
- /* Allocate memory */
- job->gather_mem = nvmap_alloc(job->nvmap,
- gather_size(num_cmdbufs),
- 32, NVMAP_HANDLE_CACHEABLE, 0);
- if (IS_ERR_OR_NULL(job->gather_mem)) {
- err = job->gather_mem ? PTR_ERR(job->gather_mem) : -ENOMEM;
- job->gather_mem = NULL;
- goto error;
- }
- job->gather_mem_size = gather_size(num_cmdbufs);
-
- /* Map memory to kernel */
- job->gathers = nvmap_mmap(job->gather_mem);
- if (IS_ERR_OR_NULL(job->gathers)) {
- err = job->gathers ? PTR_ERR(job->gathers) : -ENOMEM;
- job->gathers = NULL;
- goto error;
- }
- }
-
- return 0;
-
-error:
- free_gathers(job);
- return err;
-}
-
-static int realloc_gathers(struct nvhost_job *oldjob,
- struct nvhost_job *newjob,
- int num_cmdbufs)
-{
- int err = 0;
-
- /* Check if we can reuse gather buffer */
- if (oldjob->gather_mem_size < gather_size(num_cmdbufs)
- || oldjob->nvmap != newjob->nvmap) {
- free_gathers(oldjob);
- err = alloc_gathers(newjob, num_cmdbufs);
- } else {
- newjob->gather_mem = oldjob->gather_mem;
- newjob->gathers = oldjob->gathers;
- newjob->gather_mem_size = oldjob->gather_mem_size;
-
- oldjob->gather_mem = NULL;
- oldjob->gathers = NULL;
- oldjob->gather_mem_size = 0;
- }
- return err;
+ + num_relocs * sizeof(struct nvmap_pinarray_elem)
+ + num_unpins * sizeof(struct nvmap_handle_ref *)
+ + num_waitchks * sizeof(struct nvhost_waitchk)
+ + num_cmdbufs * sizeof(struct nvhost_job_gather);
}
static void init_fields(struct nvhost_job *job,
struct nvhost_submit_hdr_ext *hdr,
int priority, int clientid)
{
- int num_pins = hdr ? (hdr->num_relocs + hdr->num_cmdbufs)*2 : 0;
+ int num_relocs = hdr ? hdr->num_relocs : 0;
int num_waitchks = hdr ? hdr->num_waitchks : 0;
+ int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
+ int num_unpins = num_cmdbufs + num_relocs;
void *mem = job;
/* First init state to zero */
- job->num_gathers = 0;
- job->num_pins = 0;
- job->num_unpins = 0;
- job->num_waitchk = 0;
- job->waitchk_mask = 0;
- job->syncpt_id = 0;
- job->syncpt_incrs = 0;
- job->syncpt_end = 0;
job->priority = priority;
job->clientid = clientid;
- job->null_kickoff = false;
- job->first_get = 0;
- job->num_slots = 0;
/* Redistribute memory to the structs */
mem += sizeof(struct nvhost_job);
- if (num_pins) {
- job->pinarray = mem;
- mem += num_pins * sizeof(struct nvmap_pinarray_elem);
- job->unpins = mem;
- mem += num_pins * sizeof(struct nvmap_handle *);
- } else {
- job->pinarray = NULL;
- job->unpins = NULL;
- }
-
+ job->pinarray = num_relocs ? mem : NULL;
+ mem += num_relocs * sizeof(struct nvmap_pinarray_elem);
+ job->unpins = num_unpins ? mem : NULL;
+ mem += num_unpins * sizeof(struct nvmap_handle_ref *);
job->waitchk = num_waitchks ? mem : NULL;
+ mem += num_waitchks * sizeof(struct nvhost_waitchk);
+ job->gathers = num_cmdbufs ? mem : NULL;
/* Copy information from header */
if (hdr) {
@@ -172,8 +86,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
int clientid)
{
struct nvhost_job *job = NULL;
- int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
- int err = 0;
job = vzalloc(job_size(hdr));
if (!job)
@@ -186,10 +98,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
hwctx->h->get(hwctx);
job->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL;
- err = alloc_gathers(job, num_cmdbufs);
- if (err)
- goto error;
-
init_fields(job, hdr, priority, clientid);
return job;
@@ -200,46 +108,6 @@ error:
return NULL;
}
-struct nvhost_job *nvhost_job_realloc(
- struct nvhost_job *oldjob,
- struct nvhost_hwctx *hwctx,
- struct nvhost_submit_hdr_ext *hdr,
- struct nvmap_client *nvmap,
- int priority, int clientid)
-{
- struct nvhost_job *newjob = NULL;
- int num_cmdbufs = hdr ? hdr->num_cmdbufs : 0;
- int err = 0;
-
- newjob = vzalloc(job_size(hdr));
- if (!newjob)
- goto error;
- kref_init(&newjob->ref);
- newjob->ch = oldjob->ch;
- newjob->hwctx = hwctx;
- if (hwctx)
- newjob->hwctx->h->get(newjob->hwctx);
- newjob->timeout = oldjob->timeout;
- newjob->nvmap = nvmap ? nvmap_client_get(nvmap) : NULL;
-
- err = realloc_gathers(oldjob, newjob, num_cmdbufs);
- if (err)
- goto error;
-
- nvhost_job_put(oldjob);
-
- init_fields(newjob, hdr, priority, clientid);
-
- return newjob;
-
-error:
- if (newjob)
- nvhost_job_put(newjob);
- if (oldjob)
- nvhost_job_put(oldjob);
- return NULL;
-}
-
void nvhost_job_get(struct nvhost_job *job)
{
kref_get(&job->ref);
@@ -253,10 +121,6 @@ static void job_free(struct kref *ref)
job->hwctxref->h->put(job->hwctxref);
if (job->hwctx)
job->hwctx->h->put(job->hwctx);
- if (job->gathers)
- nvmap_munmap(job->gather_mem, job->gathers);
- if (job->gather_mem)
- nvmap_free(job->nvmap, job->gather_mem);
if (job->nvmap)
nvmap_client_put(job->nvmap);
vfree(job);
@@ -280,42 +144,119 @@ void nvhost_job_put(struct nvhost_job *job)
void nvhost_job_add_gather(struct nvhost_job *job,
u32 mem_id, u32 words, u32 offset)
{
- struct nvmap_pinarray_elem *pin;
- struct nvhost_channel_gather *cur_gather =
+ struct nvhost_job_gather *cur_gather =
&job->gathers[job->num_gathers];
- pin = &job->pinarray[job->num_pins++];
- pin->patch_mem = (u32)nvmap_ref_to_handle(job->gather_mem);
- pin->patch_offset = (void *)&(cur_gather->mem) - (void *)job->gathers;
- pin->pin_mem = nvmap_convert_handle_u2k(mem_id);
- pin->pin_offset = offset;
cur_gather->words = words;
cur_gather->mem_id = mem_id;
cur_gather->offset = offset;
job->num_gathers += 1;
}
-int nvhost_job_pin(struct nvhost_job *job)
+static int do_relocs(struct nvhost_job *job, u32 patch_mem, void *patch_addr)
{
- int err = 0;
+ phys_addr_t pin_phys;
+ int i;
+ u32 mem_id = 0;
+ struct nvmap_handle_ref *pin_ref = NULL;
+
+ /* pin & patch the relocs for one gather */
+ for (i = 0; i < job->num_relocs; i++) {
+ struct nvmap_pinarray_elem *pin = &job->pinarray[i];
+
+ /* skip all other gathers */
+ if (patch_mem != pin->patch_mem)
+ continue;
+
+ /* check if pin-mem is same as previous */
+ if (pin->pin_mem != mem_id) {
+ pin_ref = nvmap_duplicate_handle_id(job->nvmap,
+ pin->pin_mem);
+ if (IS_ERR(pin_ref))
+ return PTR_ERR(pin_ref);
+
+ pin_phys = nvmap_pin(job->nvmap, pin_ref);
+ if (IS_ERR((void *)pin_phys)) {
+ nvmap_free(job->nvmap, pin_ref);
+ return pin_phys;
+ }
+
+ mem_id = pin->pin_mem;
+ job->unpins[job->num_unpins++] = pin_ref;
+ }
+
+ __raw_writel((pin_phys + pin->pin_offset) >> pin->reloc_shift,
+ (patch_addr + pin->patch_offset));
+
+ /* Different gathers might have same mem_id. This ensures we
+ * perform reloc only once per gather memid. */
+ pin->patch_mem = 0;
+ }
+
+ return 0;
+}
- /* pin mem handles and patch physical addresses */
- job->num_unpins = nvmap_pin_array(job->nvmap,
- nvmap_ref_to_handle(job->gather_mem),
- job->pinarray, job->num_pins,
- job->unpins);
- if (job->num_unpins < 0)
- err = job->num_unpins;
+int nvhost_job_pin(struct nvhost_job *job)
+{
+ int err = 0, i = 0;
+ phys_addr_t gather_phys = 0;
+ void *gather_addr = NULL;
+
+ /* pin gathers */
+ for (i = 0; i < job->num_gathers; i++) {
+ struct nvhost_job_gather *g = &job->gathers[i];
+
+ /* process each gather mem only once */
+ if (!g->ref) {
+ g->ref = nvmap_duplicate_handle_id(job->nvmap,
+ job->gathers[i].mem_id);
+ if (IS_ERR(g->ref)) {
+ err = PTR_ERR(g->ref);
+ g->ref = NULL;
+ break;
+ }
+
+ gather_phys = nvmap_pin(job->nvmap, g->ref);
+ if (IS_ERR((void *)gather_phys)) {
+ nvmap_free(job->nvmap, g->ref);
+ err = gather_phys;
+ break;
+ }
+
+ /* store the gather ref into unpin array */
+ job->unpins[job->num_unpins++] = g->ref;
+
+ gather_addr = nvmap_mmap(g->ref);
+ if (!gather_addr) {
+ err = -ENOMEM;
+ break;
+ }
+
+ err = do_relocs(job, g->mem_id, gather_addr);
+ nvmap_munmap(g->ref, gather_addr);
+
+ if (err)
+ break;
+ }
+ g->mem = gather_phys + g->offset;
+ }
+ wmb();
return err;
}
void nvhost_job_unpin(struct nvhost_job *job)
{
- nvmap_unpin_handles(job->nvmap, job->unpins,
- job->num_unpins);
+ int i;
+
+ for (i = 0; i < job->num_unpins; i++) {
+ nvmap_unpin(job->nvmap, job->unpins[i]);
+ nvmap_free(job->nvmap, job->unpins[i]);
+ }
+
memset(job->unpins, BAD_MAGIC,
- job->num_unpins * sizeof(struct nvmap_handle *));
+ job->num_unpins * sizeof(struct nvmap_handle_ref *));
+ job->num_unpins = 0;
}
/**
diff --git a/drivers/video/tegra/host/nvhost_job.h b/drivers/video/tegra/host/nvhost_job.h
index ad9d1af60da1..48555a231412 100644
--- a/drivers/video/tegra/host/nvhost_job.h
+++ b/drivers/video/tegra/host/nvhost_job.h
@@ -29,6 +29,14 @@ struct nvmap_client;
struct nvhost_waitchk;
struct nvmap_handle;
+struct nvhost_job_gather {
+ u32 words;
+ phys_addr_t mem;
+ u32 mem_id;
+ int offset;
+ struct nvmap_handle_ref *ref;
+};
+
/*
* Each submit is tracked as a nvhost_job.
*/
@@ -50,10 +58,8 @@ struct nvhost_job {
struct nvmap_client *nvmap;
/* Gathers and their memory */
- struct nvmap_handle_ref *gather_mem;
- struct nvhost_channel_gather *gathers;
+ struct nvhost_job_gather *gathers;
int num_gathers;
- int gather_mem_size;
/* Wait checks to be processed at submit time */
struct nvhost_waitchk *waitchk;
@@ -62,8 +68,8 @@ struct nvhost_job {
/* Array of handles to be pinned & unpinned */
struct nvmap_pinarray_elem *pinarray;
- int num_pins;
- struct nvmap_handle **unpins;
+ int num_relocs;
+ struct nvmap_handle_ref **unpins;
int num_unpins;
/* Sync point id, number of increments and end related to the submit */
@@ -99,17 +105,6 @@ struct nvhost_job *nvhost_job_alloc(struct nvhost_channel *ch,
int priority, int clientid);
/*
- * Allocate memory for a job. Just enough memory will be allocated to
- * accomodate the submit announced in submit header. Gather memory from
- * oldjob will be reused, and nvhost_job_put() will be called to it.
- */
-struct nvhost_job *nvhost_job_realloc(struct nvhost_job *oldjob,
- struct nvhost_hwctx *hwctx,
- struct nvhost_submit_hdr_ext *hdr,
- struct nvmap_client *nvmap,
- int priority, int clientid);
-
-/*
* Add a gather to a job.
*/
void nvhost_job_add_gather(struct nvhost_job *job,
diff --git a/include/trace/events/nvhost.h b/include/trace/events/nvhost.h
index 4bb79e30fc19..6358fedf4482 100644
--- a/include/trace/events/nvhost.h
+++ b/include/trace/events/nvhost.h
@@ -194,20 +194,30 @@ TRACE_EVENT(nvhost_cdma_push_gather,
);
TRACE_EVENT(nvhost_channel_write_reloc,
- TP_PROTO(const char *name),
+ TP_PROTO(const char *name, u32 cmdbuf_mem, u32 cmdbuf_offset,
+ u32 target, u32 target_offset),
- TP_ARGS(name),
+ TP_ARGS(name, cmdbuf_mem, cmdbuf_offset, target, target_offset),
TP_STRUCT__entry(
__field(const char *, name)
+ __field(u32, cmdbuf_mem)
+ __field(u32, cmdbuf_offset)
+ __field(u32, target)
+ __field(u32, target_offset)
),
TP_fast_assign(
__entry->name = name;
+ __entry->cmdbuf_mem = cmdbuf_mem;
+ __entry->cmdbuf_offset = cmdbuf_offset;
+ __entry->target = target;
+ __entry->target_offset = target_offset;
),
- TP_printk("name=%s",
- __entry->name)
+ TP_printk("name=%s, cmdbuf_mem=%08x, cmdbuf_offset=%04x, target=%08x, target_offset=%04x",
+ __entry->name, __entry->cmdbuf_mem, __entry->cmdbuf_offset,
+ __entry->target, __entry->target_offset)
);
TRACE_EVENT(nvhost_channel_write_waitchks,