video: tegra: host: add sof/eof timestamp support

[1] Fills SOF/EOF timestamp buffer action before SOF/EOF
    signal actions.
[2] Adds action opcode ACTION_WRITE_TIMESTAMP to inform
    firmware for scribbling timestamp buffer.
[3] Decrement MAX_TASKS_PER_SUBMIT from 24 to 16, since existing
    results in stack size > 2048 byts (overflow).

Jira DLA-1992
Jira DLA-1993
Jira DLA-251

Change-Id: Ie16292a963a97fbea68ad6860dcfc39b85c4b55b
Signed-off-by: Arvind M <am@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2121532
Reviewed-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Arvind M
2019-05-18 16:52:19 +05:30
committed by Laxman Dewangan
parent 971fe01893
commit 6e76995152
5 changed files with 188 additions and 3 deletions

View File

@@ -87,6 +87,7 @@
/* write actions */
#define ACTION_WRITE_SEM 0x80
#define ACTION_WRITE_TS_SEM 0x83
#define ACTION_WRITE_TIMESTAMP 0x87
#define ACTION_WRITE_GOS 0xA0
#define ACTION_WRITE_TASK_STATUS 0xC1
@@ -231,6 +232,17 @@ struct dla_action_task_status {
uint16_t status;
} __attribute__ ((packed));
/**
* Timestamp update action structure
*
* OPCODE = 0x87
*
* @address: Address to write timestamp
*/
struct dla_action_timestamp {
uint64_t address;
} __attribute__ ((packed));
/**
* Status notifier structure
*

View File

@@ -103,6 +103,7 @@
#define MAX_NUM_NVDLA_EMU_POSTFENCES 16
#define MAX_NUM_NVDLA_IN_TASK_STATUS MAX_NUM_NVDLA_PREFENCES
#define MAX_NUM_NVDLA_OUT_TASK_STATUS MAX_NUM_NVDLA_POSTFENCES
#define MAX_NUM_NVDLA_OUT_TIMESTAMP 32
#define NUM_PROFILING_POSTACTION 1
#define MAX_COMMANDS_PER_DEVICE 1
@@ -267,12 +268,16 @@ struct nvdla_task {
struct nvdla_status_notify in_task_status[MAX_NUM_NVDLA_IN_TASK_STATUS];
struct nvdla_status_notify sof_task_status[MAX_NUM_NVDLA_OUT_TASK_STATUS];
struct nvdla_status_notify eof_task_status[MAX_NUM_NVDLA_OUT_TASK_STATUS];
struct nvdla_mem_handle sof_timestamps[MAX_NUM_NVDLA_OUT_TIMESTAMP];
struct nvdla_mem_handle eof_timestamps[MAX_NUM_NVDLA_OUT_TIMESTAMP];
struct nvdla_mem_handle memory_handles[NVDLA_MAX_BUFFERS_PER_TASK];
u8 num_prefences;
u8 num_postfences;
u8 num_in_task_status;
u8 num_sof_task_status;
u8 num_eof_task_status;
u8 num_sof_timestamps;
u8 num_eof_timestamps;
u32 num_addresses;
u32 fence;
u32 fence_counter;
@@ -290,6 +295,8 @@ struct nvdla_task {
struct dma_buf *postfences_sem_dmabuf[MAX_NUM_NVDLA_POSTFENCES];
struct dma_buf *sof_task_status_dmabuf[MAX_NUM_NVDLA_OUT_TASK_STATUS];
struct dma_buf *eof_task_status_dmabuf[MAX_NUM_NVDLA_OUT_TASK_STATUS];
struct dma_buf *sof_timestamps_dmabuf[MAX_NUM_NVDLA_OUT_TIMESTAMP];
struct dma_buf *eof_timestamps_dmabuf[MAX_NUM_NVDLA_OUT_TIMESTAMP];
};
struct dla_mem_addr {

View File

@@ -396,6 +396,24 @@ static int nvdla_get_actions(struct nvdla_ioctl_submit_task *user_task,
goto fail;
}
/* get sof timestamps */
if (copy_from_user(task->sof_timestamps,
(void __user*)user_task->sof_timestamps,
(task->num_sof_timestamps * sizeof(struct nvdla_mem_handle)))) {
err = -EFAULT;
nvdla_dbg_err(pdev, "failed to copy sof timestamps");
goto fail;
}
/* get eof timestamps */
if (copy_from_user(task->eof_timestamps,
(void __user*)user_task->eof_timestamps,
(task->num_eof_timestamps * sizeof(struct nvdla_mem_handle)))) {
err = -EFAULT;
nvdla_dbg_err(pdev, "failed to copy eof timestamps");
goto fail;
}
nvdla_dbg_info(pdev, "copying actions done");
fail:
@@ -640,6 +658,18 @@ static int nvdla_val_task_submit_input(struct nvdla_ioctl_submit_task *in_task)
MAX_NUM_NVDLA_OUT_TASK_STATUS);
return -EINVAL;
}
if (in_task->num_sof_timestamps > MAX_NUM_NVDLA_OUT_TIMESTAMP) {
pr_err("sof timestamps[%u] crossing expected[%d]\n",
in_task->num_sof_timestamps,
MAX_NUM_NVDLA_OUT_TIMESTAMP);
return -EINVAL;
}
if (in_task->num_eof_timestamps > MAX_NUM_NVDLA_OUT_TIMESTAMP) {
pr_err("eof timestamps[%u] crossing expected[%d]\n",
in_task->num_eof_timestamps,
MAX_NUM_NVDLA_OUT_TIMESTAMP);
return -EINVAL;
}
if (in_task->num_addresses < 1) {
pr_err("num addresses[%u] should be min one\n",
in_task->num_addresses);
@@ -683,6 +713,8 @@ static int nvdla_fill_task(struct nvdla_queue *queue,
task->num_in_task_status = local_task->num_input_task_status;
task->num_sof_task_status = local_task->num_sof_task_status;
task->num_eof_task_status = local_task->num_eof_task_status;
task->num_sof_timestamps = local_task->num_sof_timestamps;
task->num_eof_timestamps = local_task->num_eof_timestamps;
task->num_addresses = local_task->num_addresses;
task->timeout = local_task->timeout;
@@ -731,6 +763,9 @@ static void nvdla_dump_task(struct nvdla_task *task)
task->num_in_task_status,
task->num_sof_task_status,
task->num_eof_task_status);
nvdla_dbg_info(pdev, "num_sof_timestamps[%u] num_eof_timestamps[%u]",
task->num_sof_timestamps,
task->num_eof_timestamps);
nvdla_dbg_info(pdev, "num_addresses[%u]", task->num_addresses);
for (i = 0; i < task->num_prefences; i++) {
@@ -783,6 +818,20 @@ static void nvdla_dump_task(struct nvdla_task *task)
task->eof_task_status[i].status);
}
for (i = 0; i < task->num_sof_timestamps; i++) {
nvdla_dbg_info(pdev, "SOF timestamp[%d]:"
"handle[%u] offset[%u]",
i, task->sof_timestamps[i].handle,
task->sof_timestamps[i].offset);
}
for (i = 0; i < task->num_eof_timestamps; i++) {
nvdla_dbg_info(pdev, "EOF timestamp[%d]:"
"handle[%u] offset[%u]",
i, task->eof_timestamps[i].handle,
task->eof_timestamps[i].offset);
}
for (i = 0; i < task->num_addresses; i++) {
nvdla_dbg_info(pdev, "Memory Handles[%d]:"
"handle[%u] offset[%u]",

View File

@@ -228,6 +228,25 @@ static int nvdla_unmap_task_memory(struct nvdla_task *task)
}
nvdla_dbg_fn(pdev, "all out task status unmaped");
/* unpin output timestamp memory */
for (ii = 0; ii < task->num_sof_timestamps; ii++) {
if (task->sof_timestamps[ii].handle) {
nvdla_buffer_submit_unpin(task->buffers,
&task->sof_timestamps_dmabuf[ii], 1);
dma_buf_put(task->sof_timestamps_dmabuf[ii]);
}
}
for (ii = 0; ii < task->num_eof_timestamps; ii++) {
if (task->eof_timestamps[ii].handle) {
nvdla_buffer_submit_unpin(task->buffers,
&task->eof_timestamps_dmabuf[ii], 1);
dma_buf_put(task->eof_timestamps_dmabuf[ii]);
}
}
nvdla_dbg_fn(pdev, "all out timestamps unmaped");
return 0;
}
@@ -261,12 +280,15 @@ static void nvdla_task_syncpt_reset(struct nvhost_syncpt *syncpt,
static inline int nvdla_get_max_preaction_size(void)
{
return (((MAX_NUM_NVDLA_PREFENCES + MAX_NUM_NVDLA_IN_TASK_STATUS +
MAX_NUM_NVDLA_OUT_TASK_STATUS) *
MAX_NUM_NVDLA_OUT_TASK_STATUS +
MAX_NUM_NVDLA_OUT_TIMESTAMP) *
sizeof(struct dla_action_opcode)) +
(MAX_NUM_NVDLA_PREFENCES *
sizeof(struct dla_action_semaphore)) +
((MAX_NUM_NVDLA_IN_TASK_STATUS + MAX_NUM_NVDLA_OUT_TASK_STATUS) *
sizeof(struct dla_action_task_status)) +
(MAX_NUM_NVDLA_OUT_TIMESTAMP *
sizeof(struct dla_action_timestamp)) +
sizeof(struct dla_action_opcode));
}
@@ -274,6 +296,7 @@ static inline int nvdla_get_max_postaction_size(void)
{
return (((MAX_NUM_NVDLA_POSTFENCES +
MAX_NUM_NVDLA_OUT_TASK_STATUS +
MAX_NUM_NVDLA_OUT_TIMESTAMP +
NUM_PROFILING_POSTACTION) *
sizeof(struct dla_action_opcode)) +
(MAX_NUM_NVDLA_POSTFENCES *
@@ -281,6 +304,8 @@ static inline int nvdla_get_max_postaction_size(void)
((MAX_NUM_NVDLA_OUT_TASK_STATUS +
NUM_PROFILING_POSTACTION) *
sizeof(struct dla_action_task_status)) +
(MAX_NUM_NVDLA_OUT_TIMESTAMP *
sizeof(struct dla_action_timestamp)) +
sizeof(struct dla_action_opcode));
}
@@ -436,6 +461,18 @@ static u8 *add_status_action(u8 *mem, uint8_t op, uint64_t addr,
return mem + sizeof(struct dla_action_task_status);
}
static u8 *add_timestamp_action(u8 *mem, uint8_t op, uint64_t addr)
{
struct dla_action_timestamp *action;
mem = add_opcode(mem, op);
action = (struct dla_action_timestamp *)mem;
action->address = addr;
return mem + sizeof(struct dla_action_timestamp);
}
static u8 *add_gos_action(u8 *mem, uint8_t op, uint8_t index, uint16_t offset,
uint32_t value)
{
@@ -918,6 +955,50 @@ fail:
return err;
}
static int nvdla_fill_timestamp_write_action(struct nvdla_task *task,
struct nvdla_mem_handle *timestamp,
struct dma_buf **dma_buf,
u8 **mem_next)
{
int err = 0;
struct nvdla_buffers *buffers = task->buffers;
struct nvdla_queue *queue = task->queue;
struct platform_device *pdev = queue->pool->pdev;
dma_addr_t dma_addr;
size_t dma_size;
u8 *next = *mem_next;
nvdla_dbg_info(pdev, "h[%u] o[%u]",
timestamp->handle,
timestamp->offset);
*dma_buf = dma_buf_get(timestamp->handle);
if (IS_ERR_OR_NULL(*dma_buf)) {
*dma_buf = NULL;
nvdla_dbg_err(pdev, "fail to get buf");
err = -EINVAL;
goto fail;
}
if (nvdla_buffer_submit_pin(buffers,
dma_buf, 1, &dma_addr, &dma_size, NULL)) {
nvdla_dbg_err(pdev, "fail to pin timestamp");
err = -EINVAL;
goto fail;
}
next = add_timestamp_action(next, ACTION_WRITE_TIMESTAMP,
dma_addr + timestamp->offset);
*mem_next = next;
fail:
return err;
}
static int nvdla_fill_postactions(struct nvdla_task *task)
{
int err = 0;
@@ -941,6 +1022,20 @@ static int nvdla_fill_postactions(struct nvdla_task *task)
next = add_status_action(next, ACTION_WRITE_TASK_STATUS,
task->task_desc_pa + nvdla_profile_status_offset(task), 0);
/* fill eof timestamp actions */
for (i = 0; i < task->num_eof_timestamps; i++) {
err = nvdla_fill_timestamp_write_action(task,
&task->eof_timestamps[i],
&task->eof_timestamps_dmabuf[i],
&next);
if (err < 0) {
nvdla_dbg_err(pdev,
"failed to fill eof timestamp[%d]",
i);
goto fail;
}
}
/* fill output task status */
for (i = 0; i < task->num_eof_task_status; i++) {
err = nvdla_fill_taskstatus_write_action(task,
@@ -1043,6 +1138,20 @@ static int nvdla_fill_preactions(struct nvdla_task *task)
}
}
/* fill sof timestamp actions */
for (i = 0; i < task->num_sof_timestamps; i++) {
err = nvdla_fill_timestamp_write_action(task,
&task->sof_timestamps[i],
&task->sof_timestamps_dmabuf[i],
&next);
if (err < 0) {
nvdla_dbg_err(pdev,
"failed to fill sof timestamp[%d]",
i);
goto fail;
}
}
/* fill all preactions signals */
for (i = 0; i < task->num_prefences; i++) {
/* update action */

View File

@@ -79,7 +79,7 @@ struct nvdla_pin_unpin_args {
struct nvdla_submit_args {
__u64 tasks;
__u16 num_tasks;
#define MAX_TASKS_PER_SUBMIT 24
#define MAX_TASKS_PER_SUBMIT 16
#define NVDLA_SUBMIT_FLAGS_ATOMIC (1 << 0)
__u16 flags;
__u32 version;
@@ -127,6 +127,8 @@ struct nvdla_mem_handle {
* @num_input_task_status number of input task status
* @num_sof_task_status number of sof task status
* @num_eof_task_status number of eof task status
* @num_sof_timestamps number of sof timestamp
* @num_eof_timestamps number of eof timestamp
* @flags flags for bitwise task info embeddeing
* @reserved reserved for future use
* @prefences pointer to pre-fence struct table
@@ -134,6 +136,8 @@ struct nvdla_mem_handle {
* @input_task_status pointer to input task status struct table
* @sof_task_status pointer to sof task status struct table
* @eof_task_status pointer to eof task status struct table
* @sof_timestamps pointer to sof timestamp handle list
* @eof_timestamps pointer to eof timestamp handle list
* @num_addresses total number of addressed passed in structure
* @address_list pointer to address list
* @timeout task timeout
@@ -145,7 +149,9 @@ struct nvdla_ioctl_submit_task {
__u8 num_input_task_status;
__u8 num_sof_task_status;
__u8 num_eof_task_status;
__u8 reserved0[3];
__u8 num_sof_timestamps;
__u8 num_eof_timestamps;
__u8 reserved0[1];
#define NVDLA_MAX_BUFFERS_PER_TASK (6144)
__u32 num_addresses;
__u16 flags;
@@ -157,6 +163,8 @@ struct nvdla_ioctl_submit_task {
__u64 input_task_status;
__u64 sof_task_status;
__u64 eof_task_status;
__u64 sof_timestamps;
__u64 eof_timestamps;
__u64 address_list;
__u64 timeout;
};