mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-25 02:52:51 +03:00
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:
committed by
mobile promotions
parent
919b642214
commit
38e2722024
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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__*/
|
||||
|
||||
Reference in New Issue
Block a user