mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-22 17:36:20 +03:00
gpu: nvgpu: Prepare for adding host1x support
To prepare for supporting the upstream host1x driver with NVGPU, move functions that are common using either the upstream host1x driver or the downstream nvhost driver into a common file. Bug 3156385 Change-Id: I33a3b55cfa3eb4c03b7047b62f26a75f407b2dd4 Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2429980 Reviewed-by: automaticguardword <automaticguardword@nvidia.com> Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Alex Waterman
parent
29dc4e509a
commit
d16259ccc9
@@ -137,6 +137,7 @@ nvgpu_mem:
|
|||||||
|
|
||||||
nvhost:
|
nvhost:
|
||||||
sources: [ os/linux/nvhost.c,
|
sources: [ os/linux/nvhost.c,
|
||||||
|
os/linux/nvhost_common.c,
|
||||||
os/linux/nvhost_priv.h ]
|
os/linux/nvhost_priv.h ]
|
||||||
|
|
||||||
nvlink:
|
nvlink:
|
||||||
|
|||||||
@@ -472,6 +472,7 @@ endif
|
|||||||
|
|
||||||
nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
nvgpu-$(CONFIG_TEGRA_GK20A_NVHOST) += \
|
||||||
os/linux/nvhost.o \
|
os/linux/nvhost.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 \
|
||||||
hal/sync/syncpt_cmdbuf_gv11b_fusa.o \
|
hal/sync/syncpt_cmdbuf_gv11b_fusa.o \
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
|
||||||
#include <nvgpu/gk20a.h>
|
#include <nvgpu/gk20a.h>
|
||||||
|
#include <nvgpu/os_fence.h>
|
||||||
|
#include <nvgpu/os_fence_syncpts.h>
|
||||||
#include <nvgpu/nvhost.h>
|
#include <nvgpu/nvhost.h>
|
||||||
#include <nvgpu/enabled.h>
|
#include <nvgpu/enabled.h>
|
||||||
#include <nvgpu/dma.h>
|
#include <nvgpu/dma.h>
|
||||||
@@ -64,28 +66,6 @@ int nvgpu_get_nvhost_dev(struct gk20a *g)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nvgpu_free_nvhost_dev(struct gk20a *g)
|
|
||||||
{
|
|
||||||
if (nvgpu_iommuable(g) && !nvgpu_is_enabled(g, NVGPU_SUPPORT_NVLINK)) {
|
|
||||||
struct device *dev = dev_from_gk20a(g);
|
|
||||||
struct nvgpu_mem *mem = &g->syncpt_mem;
|
|
||||||
|
|
||||||
dma_unmap_sg_attrs(dev, mem->priv.sgt->sgl, 1,
|
|
||||||
DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
|
|
||||||
sg_free_table(mem->priv.sgt);
|
|
||||||
nvgpu_kfree(g, mem->priv.sgt);
|
|
||||||
}
|
|
||||||
nvgpu_kfree(g, g->nvhost);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nvgpu_has_syncpoints(struct gk20a *g)
|
|
||||||
{
|
|
||||||
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
|
|
||||||
|
|
||||||
return nvgpu_is_enabled(g, NVGPU_HAS_SYNCPOINTS) &&
|
|
||||||
!l->disable_syncpoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nvgpu_nvhost_module_busy_ext(
|
int nvgpu_nvhost_module_busy_ext(
|
||||||
struct nvgpu_nvhost_dev *nvhost_dev)
|
struct nvgpu_nvhost_dev *nvhost_dev)
|
||||||
{
|
{
|
||||||
@@ -190,32 +170,6 @@ void nvgpu_nvhost_syncpt_set_safe_state(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int nvgpu_nvhost_create_symlink(struct gk20a *g)
|
|
||||||
{
|
|
||||||
struct device *dev = dev_from_gk20a(g);
|
|
||||||
int err = 0;
|
|
||||||
|
|
||||||
if (g->nvhost &&
|
|
||||||
(dev->parent != &g->nvhost->host1x_pdev->dev)) {
|
|
||||||
err = sysfs_create_link(&g->nvhost->host1x_pdev->dev.kobj,
|
|
||||||
&dev->kobj,
|
|
||||||
dev_name(dev));
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nvgpu_nvhost_remove_symlink(struct gk20a *g)
|
|
||||||
{
|
|
||||||
struct device *dev = dev_from_gk20a(g);
|
|
||||||
|
|
||||||
if (g->nvhost &&
|
|
||||||
(dev->parent != &g->nvhost->host1x_pdev->dev)) {
|
|
||||||
sysfs_remove_link(&g->nvhost->host1x_pdev->dev.kobj,
|
|
||||||
dev_name(dev));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int nvgpu_nvhost_get_syncpt_aperture(
|
int nvgpu_nvhost_get_syncpt_aperture(
|
||||||
struct nvgpu_nvhost_dev *nvhost_dev,
|
struct nvgpu_nvhost_dev *nvhost_dev,
|
||||||
u64 *base, size_t *size)
|
u64 *base, size_t *size)
|
||||||
@@ -229,81 +183,3 @@ u32 nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(struct gk20a *g,
|
|||||||
{
|
{
|
||||||
return nvhost_syncpt_unit_interface_get_byte_offset(syncpt_id);
|
return nvhost_syncpt_unit_interface_get_byte_offset(syncpt_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
int nvgpu_nvhost_syncpt_init(struct gk20a *g)
|
|
||||||
{
|
|
||||||
int err = 0;
|
|
||||||
struct nvgpu_mem *mem = &g->syncpt_mem;
|
|
||||||
|
|
||||||
if (!nvgpu_has_syncpoints(g))
|
|
||||||
return -ENOSYS;
|
|
||||||
|
|
||||||
err = nvgpu_get_nvhost_dev(g);
|
|
||||||
if (err) {
|
|
||||||
nvgpu_err(g, "host1x device not available");
|
|
||||||
err = -ENOSYS;
|
|
||||||
goto fail_sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = nvgpu_nvhost_get_syncpt_aperture(
|
|
||||||
g->nvhost,
|
|
||||||
&g->syncpt_unit_base,
|
|
||||||
&g->syncpt_unit_size);
|
|
||||||
if (err) {
|
|
||||||
nvgpu_err(g, "Failed to get syncpt interface");
|
|
||||||
err = -ENOSYS;
|
|
||||||
goto fail_sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If IOMMU is enabled, create iova for syncpt region. This iova is then
|
|
||||||
* used to create nvgpu_mem for syncpt by nvgpu_mem_create_from_phys.
|
|
||||||
* For entire syncpt shim read-only mapping full iova range is used and
|
|
||||||
* for a given syncpt read-write mapping only a part of iova range is
|
|
||||||
* used. Instead of creating another variable to store the sgt,
|
|
||||||
* g->syncpt_mem's priv field is used which later on is needed for
|
|
||||||
* freeing the mapping in deinit.
|
|
||||||
*/
|
|
||||||
if (nvgpu_iommuable(g) && !nvgpu_is_enabled(g, NVGPU_SUPPORT_NVLINK)) {
|
|
||||||
struct device *dev = dev_from_gk20a(g);
|
|
||||||
struct scatterlist *sg;
|
|
||||||
|
|
||||||
mem->priv.sgt = nvgpu_kzalloc(g, sizeof(struct sg_table));
|
|
||||||
if (!mem->priv.sgt) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto fail_sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = sg_alloc_table(mem->priv.sgt, 1, GFP_KERNEL);
|
|
||||||
if (err) {
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto fail_kfree;
|
|
||||||
}
|
|
||||||
sg = mem->priv.sgt->sgl;
|
|
||||||
sg_set_page(sg, phys_to_page(g->syncpt_unit_base),
|
|
||||||
g->syncpt_unit_size, 0);
|
|
||||||
err = dma_map_sg_attrs(dev, sg, 1,
|
|
||||||
DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
|
|
||||||
/* dma_map_sg_attrs returns 0 on errors */
|
|
||||||
if (err == 0) {
|
|
||||||
nvgpu_err(g, "iova creation for syncpoint failed");
|
|
||||||
err = -ENOMEM;
|
|
||||||
goto fail_sgt;
|
|
||||||
}
|
|
||||||
g->syncpt_unit_base = sg_dma_address(sg);
|
|
||||||
}
|
|
||||||
|
|
||||||
g->syncpt_size =
|
|
||||||
nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(g, 1);
|
|
||||||
nvgpu_info(g, "syncpt_unit_base %llx syncpt_unit_size %zx size %x\n",
|
|
||||||
g->syncpt_unit_base, g->syncpt_unit_size,
|
|
||||||
g->syncpt_size);
|
|
||||||
return 0;
|
|
||||||
fail_sgt:
|
|
||||||
sg_free_table(mem->priv.sgt);
|
|
||||||
fail_kfree:
|
|
||||||
nvgpu_kfree(g, mem->priv.sgt);
|
|
||||||
fail_sync:
|
|
||||||
nvgpu_set_enabled(g, NVGPU_HAS_SYNCPOINTS, false);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|||||||
154
drivers/gpu/nvgpu/os/linux/nvhost_common.c
Normal file
154
drivers/gpu/nvgpu/os/linux/nvhost_common.c
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017-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-mapping.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include <nvgpu/gk20a.h>
|
||||||
|
#include <nvgpu/nvhost.h>
|
||||||
|
#include <nvgpu/dma.h>
|
||||||
|
|
||||||
|
#include "nvhost_priv.h"
|
||||||
|
|
||||||
|
#include "os_linux.h"
|
||||||
|
#include "module.h"
|
||||||
|
|
||||||
|
void nvgpu_free_nvhost_dev(struct gk20a *g)
|
||||||
|
{
|
||||||
|
if (nvgpu_iommuable(g) && !nvgpu_is_enabled(g, NVGPU_SUPPORT_NVLINK)) {
|
||||||
|
struct device *dev = dev_from_gk20a(g);
|
||||||
|
struct nvgpu_mem *mem = &g->syncpt_mem;
|
||||||
|
|
||||||
|
dma_unmap_sg_attrs(dev, mem->priv.sgt->sgl, 1,
|
||||||
|
DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
|
||||||
|
sg_free_table(mem->priv.sgt);
|
||||||
|
nvgpu_kfree(g, mem->priv.sgt);
|
||||||
|
}
|
||||||
|
nvgpu_kfree(g, g->nvhost);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nvgpu_has_syncpoints(struct gk20a *g)
|
||||||
|
{
|
||||||
|
struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
|
||||||
|
|
||||||
|
return nvgpu_is_enabled(g, NVGPU_HAS_SYNCPOINTS) &&
|
||||||
|
!l->disable_syncpoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_create_symlink(struct gk20a *g)
|
||||||
|
{
|
||||||
|
struct device *dev = dev_from_gk20a(g);
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
if (g->nvhost &&
|
||||||
|
(dev->parent != &g->nvhost->host1x_pdev->dev)) {
|
||||||
|
err = sysfs_create_link(&g->nvhost->host1x_pdev->dev.kobj,
|
||||||
|
&dev->kobj,
|
||||||
|
dev_name(dev));
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nvgpu_nvhost_remove_symlink(struct gk20a *g)
|
||||||
|
{
|
||||||
|
struct device *dev = dev_from_gk20a(g);
|
||||||
|
|
||||||
|
if (g->nvhost &&
|
||||||
|
(dev->parent != &g->nvhost->host1x_pdev->dev)) {
|
||||||
|
sysfs_remove_link(&g->nvhost->host1x_pdev->dev.kobj,
|
||||||
|
dev_name(dev));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int nvgpu_nvhost_syncpt_init(struct gk20a *g)
|
||||||
|
{
|
||||||
|
int err = 0;
|
||||||
|
struct nvgpu_mem *mem = &g->syncpt_mem;
|
||||||
|
|
||||||
|
if (!nvgpu_has_syncpoints(g))
|
||||||
|
return -ENOSYS;
|
||||||
|
|
||||||
|
err = nvgpu_get_nvhost_dev(g);
|
||||||
|
if (err) {
|
||||||
|
nvgpu_err(g, "host1x device not available");
|
||||||
|
err = -ENOSYS;
|
||||||
|
goto fail_sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nvgpu_nvhost_get_syncpt_aperture(
|
||||||
|
g->nvhost,
|
||||||
|
&g->syncpt_unit_base,
|
||||||
|
&g->syncpt_unit_size);
|
||||||
|
if (err) {
|
||||||
|
nvgpu_err(g, "Failed to get syncpt interface");
|
||||||
|
err = -ENOSYS;
|
||||||
|
goto fail_sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If IOMMU is enabled, create iova for syncpt region. This iova is then
|
||||||
|
* used to create nvgpu_mem for syncpt by nvgpu_mem_create_from_phys.
|
||||||
|
* For entire syncpt shim read-only mapping full iova range is used and
|
||||||
|
* for a given syncpt read-write mapping only a part of iova range is
|
||||||
|
* used. Instead of creating another variable to store the sgt,
|
||||||
|
* g->syncpt_mem's priv field is used which later on is needed for
|
||||||
|
* freeing the mapping in deinit.
|
||||||
|
*/
|
||||||
|
if (nvgpu_iommuable(g) && !nvgpu_is_enabled(g, NVGPU_SUPPORT_NVLINK)) {
|
||||||
|
struct device *dev = dev_from_gk20a(g);
|
||||||
|
struct scatterlist *sg;
|
||||||
|
|
||||||
|
mem->priv.sgt = nvgpu_kzalloc(g, sizeof(struct sg_table));
|
||||||
|
if (!mem->priv.sgt) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto fail_sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sg_alloc_table(mem->priv.sgt, 1, GFP_KERNEL);
|
||||||
|
if (err) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto fail_kfree;
|
||||||
|
}
|
||||||
|
sg = mem->priv.sgt->sgl;
|
||||||
|
sg_set_page(sg, phys_to_page(g->syncpt_unit_base),
|
||||||
|
g->syncpt_unit_size, 0);
|
||||||
|
err = dma_map_sg_attrs(dev, sg, 1,
|
||||||
|
DMA_BIDIRECTIONAL, DMA_ATTR_SKIP_CPU_SYNC);
|
||||||
|
/* dma_map_sg_attrs returns 0 on errors */
|
||||||
|
if (err == 0) {
|
||||||
|
nvgpu_err(g, "iova creation for syncpoint failed");
|
||||||
|
err = -ENOMEM;
|
||||||
|
goto fail_sgt;
|
||||||
|
}
|
||||||
|
g->syncpt_unit_base = sg_dma_address(sg);
|
||||||
|
}
|
||||||
|
|
||||||
|
g->syncpt_size =
|
||||||
|
nvgpu_nvhost_syncpt_unit_interface_get_byte_offset(g, 1);
|
||||||
|
nvgpu_info(g, "syncpt_unit_base %llx syncpt_unit_size %zx size %x\n",
|
||||||
|
g->syncpt_unit_base, g->syncpt_unit_size,
|
||||||
|
g->syncpt_size);
|
||||||
|
return 0;
|
||||||
|
fail_sgt:
|
||||||
|
sg_free_table(mem->priv.sgt);
|
||||||
|
fail_kfree:
|
||||||
|
nvgpu_kfree(g, mem->priv.sgt);
|
||||||
|
fail_sync:
|
||||||
|
nvgpu_set_enabled(g, NVGPU_HAS_SYNCPOINTS, false);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user