mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: Add host1x support
Add support for the upstream host1x driver with the 'Host1x/Tegra UAPI' series [0] applied. The host1x support is only enabled if the kernel configuration variable CONFIG_TEGRA_HOST1X_NEXT is set. Please note that the initial implementation only supports Tegra194. [0] https://patchwork.ozlabs.org/project/linux-tegra/list/?series=206532 Bug 3156385 Change-Id: If531a8b866b48ba5a2af021756a4b5d158b8d59a Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2429981 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: Sagar Kamble <skamble@nvidia.com> Reviewed-by: svc-mobile-coverity <svc-mobile-coverity@nvidia.com> Reviewed-by: svc-mobile-misra <svc-mobile-misra@nvidia.com> Reviewed-by: svc-mobile-cert <svc-mobile-cert@nvidia.com> Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: automaticguardword <automaticguardword@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Alex Waterman
parent
18d1b1b536
commit
8c94013c4d
@@ -138,6 +138,7 @@ nvgpu_mem:
|
|||||||
nvhost:
|
nvhost:
|
||||||
sources: [ os/linux/nvhost.c,
|
sources: [ os/linux/nvhost.c,
|
||||||
os/linux/nvhost_common.c,
|
os/linux/nvhost_common.c,
|
||||||
|
os/linux/nvhost_host1x.c,
|
||||||
os/linux/nvhost_priv.h ]
|
os/linux/nvhost_priv.h ]
|
||||||
|
|
||||||
nvlink:
|
nvlink:
|
||||||
|
|||||||
@@ -470,8 +470,15 @@ nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
|||||||
os/linux/os_fence_syncpt.o
|
os/linux/os_fence_syncpt.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_TEGRA_GK20A_NVHOST_HOST1X),y)
|
||||||
|
nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
||||||
|
os/linux/nvhost_host1x.o
|
||||||
|
else
|
||||||
|
nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
||||||
|
os/linux/nvhost.o
|
||||||
|
endif
|
||||||
|
|
||||||
nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
||||||
os/linux/nvhost.o \
|
|
||||||
os/linux/nvhost_common.o \
|
os/linux/nvhost_common.o \
|
||||||
hal/sync/syncpt_cmdbuf_gk20a.o \
|
hal/sync/syncpt_cmdbuf_gk20a.o \
|
||||||
hal/sync/syncpt_cmdbuf_gv11b.o \
|
hal/sync/syncpt_cmdbuf_gv11b.o \
|
||||||
|
|||||||
@@ -69,6 +69,10 @@ CONFIG_NVGPU_FECS_TRACE := y
|
|||||||
ifdef CONFIG_TEGRA_GRHOST
|
ifdef CONFIG_TEGRA_GRHOST
|
||||||
CONFIG_TEGRA_GK20A_NVHOST := y
|
CONFIG_TEGRA_GK20A_NVHOST := y
|
||||||
endif
|
endif
|
||||||
|
ifdef CONFIG_TEGRA_HOST1X_NEXT
|
||||||
|
CONFIG_TEGRA_GK20A_NVHOST := y
|
||||||
|
CONFIG_TEGRA_GK20A_NVHOST_HOST1X := y
|
||||||
|
endif
|
||||||
|
|
||||||
# Enable support for GPUs on PCIe bus.
|
# Enable support for GPUs on PCIe bus.
|
||||||
ifeq ($(CONFIG_PCI),y)
|
ifeq ($(CONFIG_PCI),y)
|
||||||
@@ -185,6 +189,9 @@ endif
|
|||||||
ifeq ($(CONFIG_TEGRA_GK20A_NVHOST),y)
|
ifeq ($(CONFIG_TEGRA_GK20A_NVHOST),y)
|
||||||
ccflags-y += -DCONFIG_TEGRA_GK20A_NVHOST
|
ccflags-y += -DCONFIG_TEGRA_GK20A_NVHOST
|
||||||
endif
|
endif
|
||||||
|
ifeq ($(CONFIG_TEGRA_GK20A_NVHOST_HOST1X),y)
|
||||||
|
ccflags-y += -DCONFIG_TEGRA_GK20A_NVHOST_HOST1X
|
||||||
|
endif
|
||||||
ifeq ($(CONFIG_NVGPU_DGPU),y)
|
ifeq ($(CONFIG_NVGPU_DGPU),y)
|
||||||
ccflags-y += -DCONFIG_NVGPU_DGPU
|
ccflags-y += -DCONFIG_NVGPU_DGPU
|
||||||
endif
|
endif
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
* DEALINGS IN THE SOFTWARE.
|
* DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_NVGPU_SYNCFD_NONE
|
#if !defined(CONFIG_NVGPU_SYNCFD_NONE) && !defined(CONFIG_TEGRA_GK20A_NVHOST_HOST1X)
|
||||||
#include <uapi/linux/nvhost_ioctl.h>
|
#include <uapi/linux/nvhost_ioctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -25,16 +25,28 @@
|
|||||||
#ifndef NVGPU_OS_FENCE_SYNCPT_H
|
#ifndef NVGPU_OS_FENCE_SYNCPT_H
|
||||||
#define NVGPU_OS_FENCE_SYNCPT_H
|
#define NVGPU_OS_FENCE_SYNCPT_H
|
||||||
|
|
||||||
|
#if defined(CONFIG_TEGRA_GK20A_NVHOST_HOST1X)
|
||||||
|
#include <linux/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <nvgpu/errno.h>
|
#include <nvgpu/errno.h>
|
||||||
|
|
||||||
struct nvgpu_os_fence;
|
struct nvgpu_os_fence;
|
||||||
struct nvhost_ctrl_sync_fence_info;
|
|
||||||
struct nvgpu_nvhost_dev;
|
struct nvgpu_nvhost_dev;
|
||||||
|
|
||||||
struct nvgpu_os_fence_syncpt {
|
struct nvgpu_os_fence_syncpt {
|
||||||
struct nvgpu_os_fence *fence;
|
struct nvgpu_os_fence *fence;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(CONFIG_TEGRA_GK20A_NVHOST_HOST1X)
|
||||||
|
struct nvhost_ctrl_sync_fence_info {
|
||||||
|
__u32 id;
|
||||||
|
__u32 thresh;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
struct nvhost_ctrl_sync_fence_info;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_TEGRA_GK20A_NVHOST) && !defined(CONFIG_NVGPU_SYNCFD_NONE)
|
#if defined(CONFIG_TEGRA_GK20A_NVHOST) && !defined(CONFIG_NVGPU_SYNCFD_NONE)
|
||||||
|
|
||||||
int nvgpu_os_fence_syncpt_create(struct nvgpu_os_fence *fence_out,
|
int nvgpu_os_fence_syncpt_create(struct nvgpu_os_fence *fence_out,
|
||||||
|
|||||||
416
drivers/gpu/nvgpu/os/linux/nvhost_host1x.c
Normal file
416
drivers/gpu/nvgpu/os/linux/nvhost_host1x.c
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/dma-fence.h>
|
||||||
|
#include <linux/file.h>
|
||||||
|
#include <linux/host1x-next.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/sync_file.h>
|
||||||
|
|
||||||
|
#include <nvgpu/os_fence.h>
|
||||||
|
#include <nvgpu/os_fence_syncpts.h>
|
||||||
|
#include <nvgpu/nvhost.h>
|
||||||
|
#include <nvgpu/gk20a.h>
|
||||||
|
|
||||||
|
#include "nvhost_priv.h"
|
||||||
|
|
||||||
|
#define TEGRA194_SYNCPT_PAGE_SIZE 0x1000
|
||||||
|
#define TEGRA194_SYNCPT_SHIM_BASE 0x60000000
|
||||||
|
#define TEGRA194_SYNCPT_SHIM_SIZE 0x00400000
|
||||||
|
|
||||||
|
static const struct of_device_id host1x_match[] = {
|
||||||
|
{ .compatible = "nvidia,tegra186-host1x", },
|
||||||
|
{ .compatible = "nvidia,tegra194-host1x", },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
int nvgpu_get_nvhost_dev(struct gk20a *g)
|
||||||
|
{
|
||||||
|
struct platform_device *host1x_pdev;
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
np = of_find_matching_node(NULL, host1x_match);
|
||||||
|
if (!np) {
|
||||||
|
nvgpu_warn(g, "Failed to find host1x, syncpt support disabled");
|
||||||
|
nvgpu_set_enabled(g, NVGPU_HAS_SYNCPOINTS, false);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
host1x_pdev = of_find_device_by_node(np);
|
||||||
|
if (!host1x_pdev) {
|
||||||
|
nvgpu_warn(g, "host1x device not available");
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
}
|
||||||
|
|
||||||
|
g->nvhost = nvgpu_kzalloc(g, sizeof(struct nvgpu_nvhost_dev));
|
||||||
|
if (!g->nvhost)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
g->nvhost->host1x_pdev = host1x_pdev;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_module_busy_ext(struct nvgpu_nvhost_dev *nvhost_dev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_module_idle_ext(struct nvgpu_nvhost_dev *nvhost_dev) { }
|
||||||
|
|
||||||
|
void nvgpu_nvhost_debug_dump_device(struct nvgpu_nvhost_dev *nvhost_dev) { }
|
||||||
|
|
||||||
|
const char *nvgpu_nvhost_syncpt_get_name(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
int id)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nvgpu_nvhost_syncpt_is_valid_pt_ext(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (WARN_ON(!host1x))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (!sp)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nvgpu_nvhost_syncpt_is_expired_ext(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id, u32 thresh)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (WARN_ON(!host1x))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (WARN_ON(!sp))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (host1x_syncpt_wait(sp, thresh, 0, NULL))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nvgpu_host1x_cb {
|
||||||
|
struct dma_fence_cb cb;
|
||||||
|
void (*notifier)(void *, int);
|
||||||
|
void *notifier_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void nvgpu_host1x_cb_func(struct dma_fence *f, struct dma_fence_cb *cb)
|
||||||
|
{
|
||||||
|
struct nvgpu_host1x_cb *host1x_cb;
|
||||||
|
|
||||||
|
host1x_cb = container_of(cb, struct nvgpu_host1x_cb, cb);
|
||||||
|
host1x_cb->notifier(host1x_cb->notifier_data, 0);
|
||||||
|
dma_fence_put(f);
|
||||||
|
kfree(host1x_cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_intr_register_notifier(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id, u32 thresh,
|
||||||
|
void (*notifier)(void *, int),
|
||||||
|
void *notifier_data)
|
||||||
|
{
|
||||||
|
struct dma_fence *fence;
|
||||||
|
struct nvgpu_host1x_cb *cb;
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (!host1x)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (!sp)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
fence = host1x_fence_create(sp, thresh);
|
||||||
|
if (IS_ERR(fence)) {
|
||||||
|
pr_err("error %d during construction of fence!",
|
||||||
|
(int)PTR_ERR(fence));
|
||||||
|
return PTR_ERR(fence);
|
||||||
|
}
|
||||||
|
|
||||||
|
cb = kzalloc(sizeof(*cb), GFP_KERNEL);
|
||||||
|
if (!cb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
cb->notifier = notifier;
|
||||||
|
cb->notifier_data = notifier_data;
|
||||||
|
|
||||||
|
err = dma_fence_add_callback(fence, &cb->cb, nvgpu_host1x_cb_func);
|
||||||
|
if (err < 0) {
|
||||||
|
dma_fence_put(fence);
|
||||||
|
kfree(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_syncpt_set_minval(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id, u32 val)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
u32 cur;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (WARN_ON(!host1x))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (WARN_ON(!sp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cur = host1x_syncpt_read(sp);
|
||||||
|
|
||||||
|
while (cur++ != val)
|
||||||
|
host1x_syncpt_incr(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_syncpt_put_ref_ext(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (WARN_ON(!host1x))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (WARN_ON(!sp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
host1x_syncpt_put(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvgpu_nvhost_get_syncpt_client_managed(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
const char *syncpt_name)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (!host1x)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_alloc(host1x, HOST1X_SYNCPT_CLIENT_MANAGED,
|
||||||
|
syncpt_name);
|
||||||
|
if (!sp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return host1x_syncpt_id(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_syncpt_wait_timeout_ext(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id, u32 thresh, u32 timeout,
|
||||||
|
u32 waiter_index)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (!host1x)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (!sp)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
return host1x_syncpt_wait(sp, thresh, timeout, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_syncpt_read_ext_check(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id, u32 *val)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (!host1x)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (!sp)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
*val = host1x_syncpt_read(sp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_syncpt_set_safe_state(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u32 id)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
u32 val, cur;
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(nvhost_dev->host1x_pdev);
|
||||||
|
if (WARN_ON(!host1x))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add large number of increments to current value
|
||||||
|
* so that all waiters on this syncpoint are released
|
||||||
|
*/
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, id);
|
||||||
|
if (WARN_ON(!sp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cur = host1x_syncpt_read(sp);
|
||||||
|
val = cur + 1000;
|
||||||
|
|
||||||
|
while (cur++ != val)
|
||||||
|
host1x_syncpt_incr(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_get_syncpt_aperture(struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
|
u64 *base, size_t *size)
|
||||||
|
{
|
||||||
|
struct device_node *np = nvhost_dev->host1x_pdev->dev.of_node;
|
||||||
|
|
||||||
|
if (of_device_is_compatible(np, "nvidia,tegra194-host1x")) {
|
||||||
|
*base = TEGRA194_SYNCPT_SHIM_BASE;
|
||||||
|
*size = TEGRA194_SYNCPT_SHIM_SIZE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(struct gk20a *g,
|
||||||
|
u32 syncpt_id)
|
||||||
|
{
|
||||||
|
struct platform_device *host1x_pdev = g->nvhost->host1x_pdev;
|
||||||
|
struct device_node *np = host1x_pdev->dev.of_node;
|
||||||
|
|
||||||
|
if (of_device_is_compatible(np, "nvidia,tegra194-host1x"))
|
||||||
|
return syncpt_id * TEGRA194_SYNCPT_PAGE_SIZE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_fence_install(struct nvhost_fence *fence, int fd)
|
||||||
|
{
|
||||||
|
struct dma_fence *f = (struct dma_fence *)fence;
|
||||||
|
struct sync_file *file = sync_file_create(f);
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dma_fence_get(f);
|
||||||
|
fd_install(fd, file->file);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_fence_put(struct nvhost_fence *fence)
|
||||||
|
{
|
||||||
|
dma_fence_put((struct dma_fence *)fence);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_fence_dup(struct nvhost_fence *fence)
|
||||||
|
{
|
||||||
|
dma_fence_get((struct dma_fence *)fence);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nvhost_fence *nvgpu_nvhost_fence_create(struct platform_device *pdev,
|
||||||
|
struct nvhost_ctrl_sync_fence_info *pts,
|
||||||
|
u32 num_pts, const char *name)
|
||||||
|
{
|
||||||
|
struct host1x_syncpt *sp;
|
||||||
|
struct host1x *host1x;
|
||||||
|
|
||||||
|
if (num_pts != 1)
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
host1x = platform_get_drvdata(pdev);
|
||||||
|
if (!host1x)
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
|
||||||
|
sp = host1x_syncpt_get_by_id_noref(host1x, pts->id);
|
||||||
|
if (WARN_ON(!sp))
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
|
return (struct nvhost_fence *)host1x_fence_create(sp, pts->thresh);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct nvhost_fence *nvgpu_nvhost_fence_get(int fd)
|
||||||
|
{
|
||||||
|
return (struct nvhost_fence *)sync_file_get_fence(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 nvgpu_nvhost_fence_num_pts(struct nvhost_fence *fence)
|
||||||
|
{
|
||||||
|
struct dma_fence_array *array;
|
||||||
|
|
||||||
|
array = to_dma_fence_array((struct dma_fence *)fence);
|
||||||
|
if (!array)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return array->num_fences;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_fence_foreach_pt(struct nvhost_fence *fence,
|
||||||
|
int (*iter)(struct nvhost_ctrl_sync_fence_info, void *),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct nvhost_ctrl_sync_fence_info info;
|
||||||
|
struct dma_fence_array *array;
|
||||||
|
int i, err;
|
||||||
|
|
||||||
|
array = to_dma_fence_array((struct dma_fence *)fence);
|
||||||
|
if (!array) {
|
||||||
|
err = host1x_fence_extract((struct dma_fence *)fence, &info.id,
|
||||||
|
&info.thresh);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return iter(info, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < array->num_fences; ++i) {
|
||||||
|
err = host1x_fence_extract(array->fences[i], &info.id,
|
||||||
|
&info.thresh);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = iter(info, data);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -14,7 +14,9 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if !defined(CONFIG_TEGRA_GK20A_NVHOST_HOST1X)
|
||||||
#include <uapi/linux/nvhost_ioctl.h>
|
#include <uapi/linux/nvhost_ioctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <linux/err.h>
|
#include <linux/err.h>
|
||||||
#include <nvgpu/errno.h>
|
#include <nvgpu/errno.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user