gpu: nvgpu: Vidmem support for PMU

Add vidmem support for PMU. Introduces pmu_surface, which abstracts
the memory used, and allocator helpers for both sysmem and vidmem.

JIRA DNVGPU-85

Change-Id: I61ce137c7007d82010e900759bf8acaf31fba286
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: http://git-master/r/1196518
Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com>
Reviewed-on: http://git-master/r/1203125
(cherry picked from commit 665f5748108c50fe0c9b4c1486b9d74869477668)
Reviewed-on: http://git-master/r/1217628
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Mahantesh Kumbar
2016-07-26 14:37:59 +05:30
committed by mobile promotions
parent 919b642214
commit 38e2722024
3 changed files with 138 additions and 8 deletions

View File

@@ -403,6 +403,8 @@ struct gpu_ops {
struct pmu_gk20a *pmu, void *pmu_alloc_ptr);
void (*pmu_allocation_set_dmem_offset)(struct pmu_gk20a *pmu,
void *pmu_alloc_ptr, u32 offset);
void * (*pmu_allocation_get_fb_addr)(
struct pmu_gk20a *pmu, void *pmu_alloc_ptr);
void (*get_pmu_init_msg_pmu_queue_params)(
struct pmu_queue *queue, u32 id,
void *pmu_init_msg);

View File

@@ -520,6 +520,14 @@ static u32 *pmu_allocation_get_dmem_offset_addr_v3(struct pmu_gk20a *pmu,
return &pmu_a_ptr->alloc.dmem.offset;
}
void *pmu_allocation_get_fb_addr_v3(
struct pmu_gk20a *pmu, void *pmu_alloc_ptr)
{
struct pmu_allocation_v3 *pmu_a_ptr =
(struct pmu_allocation_v3 *)pmu_alloc_ptr;
return (void *)&pmu_a_ptr->alloc.fb;
}
static u32 *pmu_allocation_get_dmem_offset_addr_v2(struct pmu_gk20a *pmu,
void *pmu_alloc_ptr)
{
@@ -1500,7 +1508,8 @@ int gk20a_init_pmu(struct pmu_gk20a *pmu)
pmu_allocation_get_dmem_offset_addr_v3;
g->ops.pmu_ver.pmu_allocation_set_dmem_offset =
pmu_allocation_set_dmem_offset_v3;
g->ops.pmu_ver.pmu_allocation_get_fb_addr =
pmu_allocation_get_fb_addr_v3;
if(pmu->desc->app_version != APP_VERSION_NV_GPU &&
pmu->desc->app_version != APP_VERSION_NV_GPU_1) {
g->ops.pmu_ver.get_pmu_init_msg_pmu_queue_params =
@@ -3763,6 +3772,27 @@ static int pmu_response_handle(struct pmu_gk20a *pmu,
pv->pmu_allocation_get_dmem_offset(pmu,
pv->get_pmu_seq_out_a_ptr(seq)));
if (seq->out_mem != NULL) {
memset(pv->pmu_allocation_get_fb_addr(pmu,
pv->get_pmu_seq_out_a_ptr(seq)), 0x0,
pv->get_pmu_allocation_struct_size(pmu));
gk20a_pmu_surface_free(g, seq->out_mem);
if (seq->out_mem != seq->in_mem)
kfree(seq->out_mem);
else
seq->out_mem = NULL;
}
if (seq->in_mem != NULL) {
memset(pv->pmu_allocation_get_fb_addr(pmu,
pv->get_pmu_seq_in_a_ptr(seq)), 0x0,
pv->get_pmu_allocation_struct_size(pmu));
gk20a_pmu_surface_free(g, seq->in_mem);
kfree(seq->in_mem);
}
if (seq->callback)
seq->callback(g, msg, seq->cb_params, seq->desc, ret);
@@ -4356,6 +4386,53 @@ clean_up:
return err;
}
void gk20a_pmu_surface_describe(struct gk20a *g, struct mem_desc *mem,
struct flcn_mem_desc_v0 *fb)
{
fb->address.lo = u64_lo32(mem->gpu_va);
fb->address.hi = u64_hi32(mem->gpu_va);
fb->params = ((u32)mem->size & 0xFFFFFF);
fb->params |= (GK20A_PMU_DMAIDX_VIRT << 24);
}
int gk20a_pmu_vidmem_surface_alloc(struct gk20a *g, struct mem_desc *mem,
u32 size)
{
struct mm_gk20a *mm = &g->mm;
struct vm_gk20a *vm = &mm->pmu.vm;
int err;
err = gk20a_gmmu_alloc_map_vid(vm, size, mem);
if (err) {
gk20a_err(g->dev, "memory allocation failed");
return -ENOMEM;
}
return 0;
}
int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct mem_desc *mem,
u32 size)
{
struct mm_gk20a *mm = &g->mm;
struct vm_gk20a *vm = &mm->pmu.vm;
int err;
err = gk20a_gmmu_alloc_map_sys(vm, size, mem);
if (err) {
gk20a_err(g->dev, "failed to allocate memory\n");
return -ENOMEM;
}
return 0;
}
void gk20a_pmu_surface_free(struct gk20a *g, struct mem_desc *mem)
{
gk20a_gmmu_free_attr(g, DMA_ATTR_NO_KERNEL_MAPPING, mem);
memset(mem, 0, sizeof(struct mem_desc));
}
int gk20a_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd,
struct pmu_msg *msg, struct pmu_payload *payload,
u32 queue_id, pmu_callback callback, void* cb_param,
@@ -4425,9 +4502,28 @@ int gk20a_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd,
if (!*(pv->pmu_allocation_get_dmem_offset_addr(pmu, in)))
goto clean_up;
pmu_copy_to_dmem(pmu, (pv->pmu_allocation_get_dmem_offset(pmu,
in)),
payload->in.buf, payload->in.size, 0);
if (payload->in.fb_size != 0x0) {
seq->in_mem = kzalloc(sizeof(struct mem_desc),
GFP_KERNEL);
if (!seq->in_mem) {
err = -ENOMEM;
goto clean_up;
}
gk20a_pmu_vidmem_surface_alloc(g, seq->in_mem,
payload->in.fb_size);
gk20a_pmu_surface_describe(g, seq->in_mem,
(struct flcn_mem_desc_v0 *)
pv->pmu_allocation_get_fb_addr(pmu, in));
gk20a_mem_wr_n(g, seq->in_mem, 0,
payload->in.buf, payload->in.fb_size);
} else {
pmu_copy_to_dmem(pmu,
(pv->pmu_allocation_get_dmem_offset(pmu, in)),
payload->in.buf, payload->in.size, 0);
}
pv->pmu_allocation_set_dmem_size(pmu,
pv->get_pmu_seq_in_a_ptr(seq),
pv->pmu_allocation_get_dmem_size(pmu, in));
@@ -4442,28 +4538,45 @@ int gk20a_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd,
pv->pmu_allocation_set_dmem_size(pmu, out,
(u16)payload->out.size);
if (payload->out.buf != payload->in.buf) {
if (payload->in.buf != payload->out.buf) {
*(pv->pmu_allocation_get_dmem_offset_addr(pmu, out)) =
gk20a_alloc(&pmu->dmem,
pv->pmu_allocation_get_dmem_size(pmu, out));
if (!*(pv->pmu_allocation_get_dmem_offset_addr(pmu,
out)))
out)))
goto clean_up;
if (payload->out.fb_size != 0x0) {
seq->out_mem = kzalloc(sizeof(struct mem_desc),
GFP_KERNEL);
if (!seq->out_mem) {
err = -ENOMEM;
goto clean_up;
}
gk20a_pmu_vidmem_surface_alloc(g, seq->out_mem,
payload->out.fb_size);
gk20a_pmu_surface_describe(g, seq->out_mem,
(struct flcn_mem_desc_v0 *)
pv->pmu_allocation_get_fb_addr(pmu,
out));
}
} else {
BUG_ON(in == NULL);
seq->out_mem = seq->in_mem;
pv->pmu_allocation_set_dmem_offset(pmu, out,
pv->pmu_allocation_get_dmem_offset(pmu, in));
}
pv->pmu_allocation_set_dmem_size(pmu,
pv->get_pmu_seq_out_a_ptr(seq),
pv->pmu_allocation_get_dmem_size(pmu, out));
pv->pmu_allocation_set_dmem_offset(pmu,
pv->get_pmu_seq_out_a_ptr(seq),
pv->pmu_allocation_get_dmem_offset(pmu, out));
}
seq->state = PMU_SEQ_STATE_USED;
err = pmu_write_cmd(pmu, cmd, queue_id, timeout);
if (err)

View File

@@ -525,6 +525,12 @@ struct pmu_payload {
} in, out;
};
struct pmu_surface {
struct mem_desc vidmem_desc;
struct mem_desc sysmem_desc;
struct flcn_mem_desc_v0 params;
};
typedef void (*pmu_callback)(struct gk20a *, struct pmu_msg *, void *, u32,
u32);
@@ -539,12 +545,14 @@ struct pmu_sequence {
struct pmu_allocation_v2 in_v2;
struct pmu_allocation_v3 in_v3;
};
struct mem_desc *in_mem;
union {
struct pmu_allocation_v0 out_v0;
struct pmu_allocation_v1 out_v1;
struct pmu_allocation_v2 out_v2;
struct pmu_allocation_v3 out_v3;
};
struct mem_desc *out_mem;
u8 *out_payload;
pmu_callback callback;
void* cb_params;
@@ -797,4 +805,11 @@ int gk20a_pmu_reset(struct gk20a *g);
int pmu_idle(struct pmu_gk20a *pmu);
int pmu_enable_hw(struct pmu_gk20a *pmu, bool enable);
void gk20a_pmu_surface_free(struct gk20a *g, struct mem_desc *mem);
void gk20a_pmu_surface_describe(struct gk20a *g, struct mem_desc *mem,
struct flcn_mem_desc_v0 *fb);
int gk20a_pmu_vidmem_surface_alloc(struct gk20a *g, struct mem_desc *mem,
u32 size);
int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct mem_desc *mem,
u32 size);
#endif /*__PMU_GK20A_H__*/