diff options
| author | Arvind M <am@nvidia.com> | 2020-08-25 07:34:27 -0400 |
|---|---|---|
| committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2021-01-05 05:26:12 -0500 |
| commit | e8530a7c63dfb4a46eec51295b17fba60de8f5c7 (patch) | |
| tree | b527f516c6f8b002b789b8943e1840b338cd05d1 | |
| parent | a47b24973e9d7c5dcb75cd4ded39dd109274b791 (diff) | |
nvdla: kmd: handle {RELEASE,ALLOC}_QUEUE ioctls
[1] This commit separates the allocation and deallocation
of mission critical resources away from open() and close()
[2] It is achieved through introduction of NVDLA_IOCTL_{ALLOC,RELEASE}
IOCTLs.
[3] nvdla_buffer_* APIs introduced to facilitate easier split.
Jira DLA-4175
Bug 3200422
Bug 200628173
Change-Id: I3fb07ecaff69c62ec5eb9e5bea39b07ae1624240
Signed-off-by: Arvind M <am@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2403689
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2412585
GVS: Gerrit_Virtual_Submit
Tested-by: Bharat Nihalani <bnihalani@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: Mitch Harwell <mharwell@nvidia.com>
Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
| -rw-r--r-- | drivers/video/tegra/host/nvdla/nvdla_buffer.c | 14 | ||||
| -rw-r--r-- | drivers/video/tegra/host/nvdla/nvdla_buffer.h | 24 | ||||
| -rw-r--r-- | drivers/video/tegra/host/nvdla/nvdla_ioctl.c | 114 | ||||
| -rw-r--r-- | include/uapi/linux/nvhost_nvdla_ioctl.h | 6 |
4 files changed, 142 insertions, 16 deletions
diff --git a/drivers/video/tegra/host/nvdla/nvdla_buffer.c b/drivers/video/tegra/host/nvdla/nvdla_buffer.c index 1d7fabfb6..cdbb23f80 100644 --- a/drivers/video/tegra/host/nvdla/nvdla_buffer.c +++ b/drivers/video/tegra/host/nvdla/nvdla_buffer.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * NVHOST buffer management for T194 | 2 | * NVHOST buffer management for T194 |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2016-2018, NVIDIA Corporation. All rights reserved. | 4 | * Copyright (c) 2016-2020, NVIDIA Corporation. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -236,6 +236,18 @@ nvdla_buffer_init_err: | |||
| 236 | return ERR_PTR(err); | 236 | return ERR_PTR(err); |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | bool nvdla_buffer_is_valid(struct nvdla_buffers *nvdla_buffers) | ||
| 240 | { | ||
| 241 | /* Currently there is only one check */ | ||
| 242 | return (nvdla_buffers->pdev != NULL); | ||
| 243 | } | ||
| 244 | |||
| 245 | void nvdla_buffer_set_platform_device(struct nvdla_buffers *nvdla_buffers, | ||
| 246 | struct platform_device *pdev) | ||
| 247 | { | ||
| 248 | nvdla_buffers->pdev = pdev; | ||
| 249 | } | ||
| 250 | |||
| 239 | int nvdla_buffer_submit_pin(struct nvdla_buffers *nvdla_buffers, | 251 | int nvdla_buffer_submit_pin(struct nvdla_buffers *nvdla_buffers, |
| 240 | struct dma_buf **dmabufs, u32 count, | 252 | struct dma_buf **dmabufs, u32 count, |
| 241 | dma_addr_t *paddr, size_t *psize, | 253 | dma_addr_t *paddr, size_t *psize, |
diff --git a/drivers/video/tegra/host/nvdla/nvdla_buffer.h b/drivers/video/tegra/host/nvdla/nvdla_buffer.h index 2bb0e57c1..0353e83ed 100644 --- a/drivers/video/tegra/host/nvdla/nvdla_buffer.h +++ b/drivers/video/tegra/host/nvdla/nvdla_buffer.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * NVDLA Buffer Management Header | 2 | * NVDLA Buffer Management Header |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2019, NVIDIA Corporation. All rights reserved. | 4 | * Copyright (c) 2019-2020, NVIDIA Corporation. All rights reserved. |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms and conditions of the GNU General Public License, | 7 | * under the terms and conditions of the GNU General Public License, |
| @@ -60,6 +60,28 @@ struct nvdla_buffers { | |||
| 60 | struct nvdla_buffers *nvdla_buffer_init(struct platform_device *pdev); | 60 | struct nvdla_buffers *nvdla_buffer_init(struct platform_device *pdev); |
| 61 | 61 | ||
| 62 | /** | 62 | /** |
| 63 | * @brief Checks for validity of nvdla_buffer | ||
| 64 | * | ||
| 65 | * This function checks the validity of buffer and is | ||
| 66 | * recommended to be called prior to any buffer operations | ||
| 67 | * | ||
| 68 | * @param nvdla_buffers Pointer to nvdla_buffers struct | ||
| 69 | * @return true on buffer being valid, and false otherwise | ||
| 70 | **/ | ||
| 71 | bool nvdla_buffer_is_valid(struct nvdla_buffers *nvdla_buffers); | ||
| 72 | |||
| 73 | /** | ||
| 74 | * @brief Sets host1x platform device corresponding to nvdla_buffer | ||
| 75 | * | ||
| 76 | * This function resets the platform_device pdev information of nvdla_buffer. | ||
| 77 | * | ||
| 78 | * @param nvdla_buffers Pointer to nvdla_buffers struct | ||
| 79 | * @param pdev Pointer to NvHost device | ||
| 80 | **/ | ||
| 81 | void nvdla_buffer_set_platform_device(struct nvdla_buffers *nvdla_buffers, | ||
| 82 | struct platform_device *pdev); | ||
| 83 | |||
| 84 | /** | ||
| 63 | * @brief Pin the memhandle using dma_buf functions | 85 | * @brief Pin the memhandle using dma_buf functions |
| 64 | * | 86 | * |
| 65 | * This function maps the buffer memhandle list passed from user side | 87 | * This function maps the buffer memhandle list passed from user side |
diff --git a/drivers/video/tegra/host/nvdla/nvdla_ioctl.c b/drivers/video/tegra/host/nvdla/nvdla_ioctl.c index 12bfabecc..1cea4d54c 100644 --- a/drivers/video/tegra/host/nvdla/nvdla_ioctl.c +++ b/drivers/video/tegra/host/nvdla/nvdla_ioctl.c | |||
| @@ -178,6 +178,12 @@ static int nvdla_pin(struct nvdla_private *priv, void *arg) | |||
| 178 | 178 | ||
| 179 | nvdla_dbg_fn(pdev, ""); | 179 | nvdla_dbg_fn(pdev, ""); |
| 180 | 180 | ||
| 181 | if (!nvdla_buffer_is_valid(priv->buffers)) { | ||
| 182 | nvdla_dbg_err(pdev, "Invalid buffer\n"); | ||
| 183 | err = -EINVAL; | ||
| 184 | goto fail_to_get_val_arg; | ||
| 185 | } | ||
| 186 | |||
| 181 | if (!buf_list) { | 187 | if (!buf_list) { |
| 182 | nvdla_dbg_err(pdev, "Invalid argument ptr in pin\n"); | 188 | nvdla_dbg_err(pdev, "Invalid argument ptr in pin\n"); |
| 183 | err = -EINVAL; | 189 | err = -EINVAL; |
| @@ -233,6 +239,12 @@ static int nvdla_unpin(struct nvdla_private *priv, void *arg) | |||
| 233 | 239 | ||
| 234 | nvdla_dbg_fn(pdev, ""); | 240 | nvdla_dbg_fn(pdev, ""); |
| 235 | 241 | ||
| 242 | if (!nvdla_buffer_is_valid(priv->buffers)) { | ||
| 243 | nvdla_dbg_err(pdev, "Invalid buffer\n"); | ||
| 244 | err = -EINVAL; | ||
| 245 | goto fail_to_get_val_arg; | ||
| 246 | } | ||
| 247 | |||
| 236 | if (!buf_list) { | 248 | if (!buf_list) { |
| 237 | nvdla_dbg_err(pdev, "Invalid argument for pointer\n"); | 249 | nvdla_dbg_err(pdev, "Invalid argument for pointer\n"); |
| 238 | err = -EINVAL; | 250 | err = -EINVAL; |
| @@ -930,6 +942,70 @@ exit: | |||
| 930 | return 0; | 942 | return 0; |
| 931 | } | 943 | } |
| 932 | 944 | ||
| 945 | static int nvdla_queue_alloc_handler(struct nvdla_private *priv, void *arg) | ||
| 946 | { | ||
| 947 | int err = 0; | ||
| 948 | struct platform_device *pdev = priv->pdev; | ||
| 949 | struct nvhost_device_data *pdata = platform_get_drvdata(pdev); | ||
| 950 | struct nvdla_device *nvdla_dev = pdata->private_data; | ||
| 951 | |||
| 952 | /* Currently unused and kept to be consistent with other handlers. */ | ||
| 953 | (void) arg; | ||
| 954 | |||
| 955 | /* If queue is already allocated, error out. */ | ||
| 956 | if (unlikely(NULL != priv->queue)) { | ||
| 957 | nvdla_dbg_err(pdev, "Queue already allocated"); | ||
| 958 | err = -EINVAL; | ||
| 959 | goto fail; | ||
| 960 | } | ||
| 961 | |||
| 962 | /* Allocate the queue */ | ||
| 963 | priv->queue = nvdla_queue_alloc(nvdla_dev->pool, MAX_NVDLA_TASK_COUNT, | ||
| 964 | nvdla_dev->submit_mode == NVDLA_SUBMIT_MODE_CHANNEL); | ||
| 965 | if (IS_ERR(priv->queue)) { | ||
| 966 | err = PTR_ERR(priv->queue); | ||
| 967 | priv->queue = NULL; | ||
| 968 | goto fail; | ||
| 969 | } | ||
| 970 | |||
| 971 | /* Set nvdla_buffers platform device */ | ||
| 972 | nvdla_buffer_set_platform_device(priv->buffers, priv->queue->vm_pdev); | ||
| 973 | |||
| 974 | fail: | ||
| 975 | return err; | ||
| 976 | } | ||
| 977 | |||
| 978 | static int nvdla_queue_release_handler(struct nvdla_private *priv, void *arg) | ||
| 979 | { | ||
| 980 | int err = 0; | ||
| 981 | struct platform_device *pdev = priv->pdev; | ||
| 982 | |||
| 983 | /** | ||
| 984 | * Note: This functiona shall be reached directly either | ||
| 985 | * [1] NVDLA_IOCTL_RELEASE_QUEUE ioctl call. | ||
| 986 | * [2] when fd is closed before releasing the queue. | ||
| 987 | **/ | ||
| 988 | |||
| 989 | /* Currently unused and kept to be consistent with other handlers. */ | ||
| 990 | (void) arg; | ||
| 991 | |||
| 992 | /* If no queue is allocated, error out. */ | ||
| 993 | if (unlikely(NULL == priv->queue)) { | ||
| 994 | nvdla_dbg_err(pdev, "No queue to be released."); | ||
| 995 | err = -EINVAL; | ||
| 996 | goto fail; | ||
| 997 | } | ||
| 998 | |||
| 999 | /* Release the queue */ | ||
| 1000 | (void) nvdla_queue_abort(priv->queue); | ||
| 1001 | nvdla_queue_put(priv->queue); | ||
| 1002 | |||
| 1003 | priv->queue = NULL; | ||
| 1004 | fail: | ||
| 1005 | return err; | ||
| 1006 | } | ||
| 1007 | |||
| 1008 | |||
| 933 | static int nvdla_submit(struct nvdla_private *priv, void *arg) | 1009 | static int nvdla_submit(struct nvdla_private *priv, void *arg) |
| 934 | { | 1010 | { |
| 935 | struct nvdla_submit_args *args = | 1011 | struct nvdla_submit_args *args = |
| @@ -1097,6 +1173,12 @@ static long nvdla_ioctl(struct file *file, unsigned int cmd, | |||
| 1097 | |||
