mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 17:25:35 +03:00
gpu: host1x: Update to Linux v5.19-rc1
Update the host1x driver to align with the latest upstream host1x driver from Linux v5.19-rc1. Please note that the context bus support is not included, because this needs to be built into the kernel. Bug 3724727 Change-Id: Ic6fbe001462d160d1bb24f76038dd755c5550690 Signed-off-by: Jon Hunter <jonathanh@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2739538 Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com> Reviewed-by: Bibek Basu <bbasu@nvidia.com>
This commit is contained in:
committed by
Laxman Dewangan
parent
0955b8b8a5
commit
9edef092b1
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/host1x-next.h>
|
#include <linux/host1x-next.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
@@ -762,7 +763,6 @@ EXPORT_SYMBOL(host1x_client_exit);
|
|||||||
/**
|
/**
|
||||||
* __host1x_client_register() - register a host1x client
|
* __host1x_client_register() - register a host1x client
|
||||||
* @client: host1x client
|
* @client: host1x client
|
||||||
* @key: lock class key for the client-specific mutex
|
|
||||||
*
|
*
|
||||||
* Registers a host1x client with each host1x controller instance. Note that
|
* Registers a host1x client with each host1x controller instance. Note that
|
||||||
* each client will only match their parent host1x controller and will only be
|
* each client will only match their parent host1x controller and will only be
|
||||||
|
|||||||
@@ -75,6 +75,14 @@ struct host1x_channel *host1x_channel_get_index(struct host1x *host,
|
|||||||
return ch;
|
return ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host1x_channel_stop(struct host1x_channel *channel)
|
||||||
|
{
|
||||||
|
struct host1x *host = dev_get_drvdata(channel->dev->parent);
|
||||||
|
|
||||||
|
host1x_hw_cdma_stop(host, &channel->cdma);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(host1x_channel_stop);
|
||||||
|
|
||||||
static void release_channel(struct kref *kref)
|
static void release_channel(struct kref *kref)
|
||||||
{
|
{
|
||||||
struct host1x_channel *channel =
|
struct host1x_channel *channel =
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/seq_file.h>
|
#include <linux/seq_file.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
@@ -52,6 +53,11 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)
|
|||||||
{
|
{
|
||||||
struct host1x *m = dev_get_drvdata(ch->dev->parent);
|
struct host1x *m = dev_get_drvdata(ch->dev->parent);
|
||||||
struct output *o = data;
|
struct output *o = data;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = pm_runtime_resume_and_get(m->dev);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
mutex_lock(&ch->cdma.lock);
|
mutex_lock(&ch->cdma.lock);
|
||||||
mutex_lock(&debug_lock);
|
mutex_lock(&debug_lock);
|
||||||
@@ -64,16 +70,23 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)
|
|||||||
mutex_unlock(&debug_lock);
|
mutex_unlock(&debug_lock);
|
||||||
mutex_unlock(&ch->cdma.lock);
|
mutex_unlock(&ch->cdma.lock);
|
||||||
|
|
||||||
|
pm_runtime_put(m->dev);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_syncpts(struct host1x *m, struct output *o)
|
static void show_syncpts(struct host1x *m, struct output *o, bool show_all)
|
||||||
{
|
{
|
||||||
struct list_head *pos;
|
struct list_head *pos;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
int err;
|
||||||
|
|
||||||
host1x_debug_output(o, "---- syncpts ----\n");
|
host1x_debug_output(o, "---- syncpts ----\n");
|
||||||
|
|
||||||
|
err = pm_runtime_resume_and_get(m->dev);
|
||||||
|
if (err < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
|
for (i = 0; i < host1x_syncpt_nb_pts(m); i++) {
|
||||||
u32 max = host1x_syncpt_read_max(m->syncpt + i);
|
u32 max = host1x_syncpt_read_max(m->syncpt + i);
|
||||||
u32 min = host1x_syncpt_load(m->syncpt + i);
|
u32 min = host1x_syncpt_load(m->syncpt + i);
|
||||||
@@ -84,7 +97,10 @@ static void show_syncpts(struct host1x *m, struct output *o)
|
|||||||
waiters++;
|
waiters++;
|
||||||
spin_unlock(&m->syncpt[i].intr.lock);
|
spin_unlock(&m->syncpt[i].intr.lock);
|
||||||
|
|
||||||
if (!min && !max && !waiters)
|
if (!kref_read(&m->syncpt[i].ref))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!show_all && !min && !max && !waiters)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
host1x_debug_output(o,
|
host1x_debug_output(o,
|
||||||
@@ -101,6 +117,8 @@ static void show_syncpts(struct host1x *m, struct output *o)
|
|||||||
base_val);
|
base_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pm_runtime_put(m->dev);
|
||||||
|
|
||||||
host1x_debug_output(o, "\n");
|
host1x_debug_output(o, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +127,7 @@ static void show_all(struct host1x *m, struct output *o, bool show_fifo)
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
host1x_hw_show_mlocks(m, o);
|
host1x_hw_show_mlocks(m, o);
|
||||||
show_syncpts(m, o);
|
show_syncpts(m, o, true);
|
||||||
host1x_debug_output(o, "---- channels ----\n");
|
host1x_debug_output(o, "---- channels ----\n");
|
||||||
|
|
||||||
for (i = 0; i < m->info->nb_channels; ++i) {
|
for (i = 0; i < m->info->nb_channels; ++i) {
|
||||||
@@ -226,5 +244,5 @@ void host1x_debug_dump_syncpts(struct host1x *host1x)
|
|||||||
.fn = write_to_printk
|
.fn = write_to_printk
|
||||||
};
|
};
|
||||||
|
|
||||||
show_syncpts(host1x, &o);
|
show_syncpts(host1x, &o, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,27 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
|
||||||
|
#include <soc/tegra/common.h>
|
||||||
|
|
||||||
#define CREATE_TRACE_POINTS
|
#define CREATE_TRACE_POINTS
|
||||||
#include <trace/events/host1x.h>
|
#include <trace/events/host1x.h>
|
||||||
#undef CREATE_TRACE_POINTS
|
#undef CREATE_TRACE_POINTS
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
|
||||||
|
#include <asm/dma-iommu.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "bus.h"
|
#include "bus.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@@ -250,6 +259,9 @@ static void host1x_setup_sid_table(struct host1x *host)
|
|||||||
const struct host1x_info *info = host->info;
|
const struct host1x_info *info = host->info;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
if (!info->has_hypervisor)
|
||||||
|
return;
|
||||||
|
|
||||||
for (i = 0; i < info->num_sid_entries; i++) {
|
for (i = 0; i < info->num_sid_entries; i++) {
|
||||||
const struct host1x_sid_entry *entry = &info->sid_table[i];
|
const struct host1x_sid_entry *entry = &info->sid_table[i];
|
||||||
|
|
||||||
@@ -298,6 +310,17 @@ static struct iommu_domain *host1x_iommu_attach(struct host1x *host)
|
|||||||
struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev);
|
struct iommu_domain *domain = iommu_get_domain_for_dev(host->dev);
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
|
||||||
|
if (host->dev->archdata.mapping) {
|
||||||
|
struct dma_iommu_mapping *mapping =
|
||||||
|
to_dma_iommu_mapping(host->dev);
|
||||||
|
arm_iommu_detach_device(host->dev);
|
||||||
|
arm_iommu_release_mapping(mapping);
|
||||||
|
|
||||||
|
domain = iommu_get_domain_for_dev(host->dev);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We may not always want to enable IOMMU support (for example if the
|
* We may not always want to enable IOMMU support (for example if the
|
||||||
* host1x firewall is already enabled and we don't support addressing
|
* host1x firewall is already enabled and we don't support addressing
|
||||||
@@ -407,6 +430,27 @@ static void host1x_iommu_exit(struct host1x *host)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int host1x_get_resets(struct host1x *host)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
host->resets[0].id = "mc";
|
||||||
|
host->resets[1].id = "host1x";
|
||||||
|
host->nresets = ARRAY_SIZE(host->resets);
|
||||||
|
|
||||||
|
err = devm_reset_control_bulk_get_optional_exclusive_released(
|
||||||
|
host->dev, host->nresets, host->resets);
|
||||||
|
if (err) {
|
||||||
|
dev_err(host->dev, "failed to get reset: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WARN_ON(!host->resets[1].rstc))
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int host1x_probe(struct platform_device *pdev)
|
static int host1x_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct host1x *host;
|
struct host1x *host;
|
||||||
@@ -446,7 +490,6 @@ static int host1x_probe(struct platform_device *pdev)
|
|||||||
if (syncpt_irq < 0)
|
if (syncpt_irq < 0)
|
||||||
return syncpt_irq;
|
return syncpt_irq;
|
||||||
|
|
||||||
host1x_bo_cache_init(&host->cache);
|
|
||||||
mutex_init(&host->devices_lock);
|
mutex_init(&host->devices_lock);
|
||||||
INIT_LIST_HEAD(&host->devices);
|
INIT_LIST_HEAD(&host->devices);
|
||||||
INIT_LIST_HEAD(&host->list);
|
INIT_LIST_HEAD(&host->list);
|
||||||
@@ -484,17 +527,16 @@ static int host1x_probe(struct platform_device *pdev)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
host->rst = devm_reset_control_get(&pdev->dev, "host1x");
|
err = host1x_get_resets(host);
|
||||||
if (IS_ERR(host->rst)) {
|
if (err)
|
||||||
err = PTR_ERR(host->rst);
|
|
||||||
dev_err(&pdev->dev, "failed to get reset: %d\n", err);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
|
||||||
|
host1x_bo_cache_init(&host->cache);
|
||||||
|
|
||||||
err = host1x_iommu_init(host);
|
err = host1x_iommu_init(host);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err);
|
dev_err(&pdev->dev, "failed to setup IOMMU: %d\n", err);
|
||||||
return err;
|
goto destroy_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = host1x_channel_list_init(&host->channel_list,
|
err = host1x_channel_list_init(&host->channel_list,
|
||||||
@@ -504,22 +546,10 @@ static int host1x_probe(struct platform_device *pdev)
|
|||||||
goto iommu_exit;
|
goto iommu_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = clk_prepare_enable(host->clk);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(&pdev->dev, "failed to enable clock\n");
|
|
||||||
goto free_channels;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = reset_control_deassert(host->rst);
|
|
||||||
if (err < 0) {
|
|
||||||
dev_err(&pdev->dev, "failed to deassert reset: %d\n", err);
|
|
||||||
goto unprepare_disable;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = host1x_syncpt_init(host);
|
err = host1x_syncpt_init(host);
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "failed to initialize syncpts\n");
|
dev_err(&pdev->dev, "failed to initialize syncpts\n");
|
||||||
goto reset_assert;
|
goto free_channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = host1x_intr_init(host, syncpt_irq);
|
err = host1x_intr_init(host, syncpt_irq);
|
||||||
@@ -528,10 +558,20 @@ static int host1x_probe(struct platform_device *pdev)
|
|||||||
goto deinit_syncpt;
|
goto deinit_syncpt;
|
||||||
}
|
}
|
||||||
|
|
||||||
host1x_debug_init(host);
|
pm_runtime_enable(&pdev->dev);
|
||||||
|
|
||||||
if (host->info->has_hypervisor)
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
|
||||||
host1x_setup_sid_table(host);
|
err = devm_tegra_core_dev_init_opp_table_common(&pdev->dev);
|
||||||
|
if (err)
|
||||||
|
goto pm_disable;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* the driver's code isn't ready yet for the dynamic RPM */
|
||||||
|
err = pm_runtime_resume_and_get(&pdev->dev);
|
||||||
|
if (err)
|
||||||
|
goto pm_disable;
|
||||||
|
|
||||||
|
host1x_debug_init(host);
|
||||||
|
|
||||||
err = host1x_register(host);
|
err = host1x_register(host);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
@@ -547,17 +587,20 @@ unregister:
|
|||||||
host1x_unregister(host);
|
host1x_unregister(host);
|
||||||
deinit_debugfs:
|
deinit_debugfs:
|
||||||
host1x_debug_deinit(host);
|
host1x_debug_deinit(host);
|
||||||
|
|
||||||
|
pm_runtime_put_sync_suspend(&pdev->dev);
|
||||||
|
pm_disable:
|
||||||
|
pm_runtime_disable(&pdev->dev);
|
||||||
|
|
||||||
host1x_intr_deinit(host);
|
host1x_intr_deinit(host);
|
||||||
deinit_syncpt:
|
deinit_syncpt:
|
||||||
host1x_syncpt_deinit(host);
|
host1x_syncpt_deinit(host);
|
||||||
reset_assert:
|
|
||||||
reset_control_assert(host->rst);
|
|
||||||
unprepare_disable:
|
|
||||||
clk_disable_unprepare(host->clk);
|
|
||||||
free_channels:
|
free_channels:
|
||||||
host1x_channel_list_free(&host->channel_list);
|
host1x_channel_list_free(&host->channel_list);
|
||||||
iommu_exit:
|
iommu_exit:
|
||||||
host1x_iommu_exit(host);
|
host1x_iommu_exit(host);
|
||||||
|
destroy_cache:
|
||||||
|
host1x_bo_cache_destroy(&host->cache);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -568,20 +611,95 @@ static int host1x_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
host1x_unregister(host);
|
host1x_unregister(host);
|
||||||
host1x_debug_deinit(host);
|
host1x_debug_deinit(host);
|
||||||
|
|
||||||
|
pm_runtime_force_suspend(&pdev->dev);
|
||||||
|
|
||||||
host1x_intr_deinit(host);
|
host1x_intr_deinit(host);
|
||||||
host1x_syncpt_deinit(host);
|
host1x_syncpt_deinit(host);
|
||||||
reset_control_assert(host->rst);
|
host1x_channel_list_free(&host->channel_list);
|
||||||
clk_disable_unprepare(host->clk);
|
|
||||||
host1x_iommu_exit(host);
|
host1x_iommu_exit(host);
|
||||||
host1x_bo_cache_destroy(&host->cache);
|
host1x_bo_cache_destroy(&host->cache);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused host1x_runtime_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct host1x *host = dev_get_drvdata(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
host1x_intr_stop(host);
|
||||||
|
host1x_syncpt_save(host);
|
||||||
|
|
||||||
|
err = reset_control_bulk_assert(host->nresets, host->resets);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "failed to assert reset: %d\n", err);
|
||||||
|
goto resume_host1x;
|
||||||
|
}
|
||||||
|
|
||||||
|
usleep_range(1000, 2000);
|
||||||
|
|
||||||
|
clk_disable_unprepare(host->clk);
|
||||||
|
reset_control_bulk_release(host->nresets, host->resets);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
resume_host1x:
|
||||||
|
host1x_setup_sid_table(host);
|
||||||
|
host1x_syncpt_restore(host);
|
||||||
|
host1x_intr_start(host);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __maybe_unused host1x_runtime_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct host1x *host = dev_get_drvdata(dev);
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = reset_control_bulk_acquire(host->nresets, host->resets);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "failed to acquire reset: %d\n", err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = clk_prepare_enable(host->clk);
|
||||||
|
if (err) {
|
||||||
|
dev_err(dev, "failed to enable clock: %d\n", err);
|
||||||
|
goto release_reset;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = reset_control_bulk_deassert(host->nresets, host->resets);
|
||||||
|
if (err < 0) {
|
||||||
|
dev_err(dev, "failed to deassert reset: %d\n", err);
|
||||||
|
goto disable_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
host1x_setup_sid_table(host);
|
||||||
|
host1x_syncpt_restore(host);
|
||||||
|
host1x_intr_start(host);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
disable_clk:
|
||||||
|
clk_disable_unprepare(host->clk);
|
||||||
|
release_reset:
|
||||||
|
reset_control_bulk_release(host->nresets, host->resets);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct dev_pm_ops host1x_pm_ops = {
|
||||||
|
SET_RUNTIME_PM_OPS(host1x_runtime_suspend, host1x_runtime_resume,
|
||||||
|
NULL)
|
||||||
|
/* TODO: add system suspend-resume once driver will be ready for that */
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver tegra_host1x_driver = {
|
static struct platform_driver tegra_host1x_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "tegra-host1x",
|
.name = "tegra-host1x",
|
||||||
.of_match_table = host1x_of_match,
|
.of_match_table = host1x_of_match,
|
||||||
|
.pm = &host1x_pm_ops,
|
||||||
},
|
},
|
||||||
.probe = host1x_probe,
|
.probe = host1x_probe,
|
||||||
.remove = host1x_remove,
|
.remove = host1x_remove,
|
||||||
|
|||||||
@@ -118,7 +118,8 @@ struct host1x {
|
|||||||
struct host1x_syncpt_base *bases;
|
struct host1x_syncpt_base *bases;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct reset_control *rst;
|
struct reset_control_bulk_data resets[2];
|
||||||
|
unsigned int nresets;
|
||||||
|
|
||||||
struct iommu_group *group;
|
struct iommu_group *group;
|
||||||
struct iommu_domain *domain;
|
struct iommu_domain *domain;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
#include "intr.h"
|
#include "intr.h"
|
||||||
#include "syncpt.h"
|
#include "syncpt.h"
|
||||||
|
|
||||||
DEFINE_SPINLOCK(lock);
|
static DEFINE_SPINLOCK(lock);
|
||||||
|
|
||||||
struct host1x_syncpt_fence {
|
struct host1x_syncpt_fence {
|
||||||
struct dma_fence base;
|
struct dma_fence base;
|
||||||
|
|||||||
@@ -159,6 +159,27 @@ static void host1x_channel_set_streamid(struct host1x_channel *channel)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void host1x_enable_gather_filter(struct host1x_channel *ch)
|
||||||
|
{
|
||||||
|
#if HOST1X_HW >= 6
|
||||||
|
struct host1x *host = dev_get_drvdata(ch->dev->parent);
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
if (!host->hv_regs)
|
||||||
|
return;
|
||||||
|
|
||||||
|
val = host1x_hypervisor_readl(
|
||||||
|
host, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32));
|
||||||
|
val |= BIT(ch->id % 32);
|
||||||
|
host1x_hypervisor_writel(
|
||||||
|
host, val, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32));
|
||||||
|
#elif HOST1X_HW >= 4
|
||||||
|
host1x_ch_writel(ch,
|
||||||
|
HOST1X_CHANNEL_CHANNELCTRL_KERNEL_FILTER_GBUFFER(1),
|
||||||
|
HOST1X_CHANNEL_CHANNELCTRL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int channel_submit(struct host1x_job *job)
|
static int channel_submit(struct host1x_job *job)
|
||||||
{
|
{
|
||||||
struct host1x_channel *ch = job->channel;
|
struct host1x_channel *ch = job->channel;
|
||||||
@@ -190,6 +211,7 @@ static int channel_submit(struct host1x_job *job)
|
|||||||
}
|
}
|
||||||
|
|
||||||
host1x_channel_set_streamid(ch);
|
host1x_channel_set_streamid(ch);
|
||||||
|
host1x_enable_gather_filter(ch);
|
||||||
|
|
||||||
/* begin a CDMA submit */
|
/* begin a CDMA submit */
|
||||||
err = host1x_cdma_begin(&ch->cdma, job);
|
err = host1x_cdma_begin(&ch->cdma, job);
|
||||||
@@ -251,27 +273,6 @@ error:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enable_gather_filter(struct host1x *host,
|
|
||||||
struct host1x_channel *ch)
|
|
||||||
{
|
|
||||||
#if HOST1X_HW >= 6
|
|
||||||
u32 val;
|
|
||||||
|
|
||||||
if (!host->hv_regs)
|
|
||||||
return;
|
|
||||||
|
|
||||||
val = host1x_hypervisor_readl(
|
|
||||||
host, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32));
|
|
||||||
val |= BIT(ch->id % 32);
|
|
||||||
host1x_hypervisor_writel(
|
|
||||||
host, val, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32));
|
|
||||||
#elif HOST1X_HW >= 4
|
|
||||||
host1x_ch_writel(ch,
|
|
||||||
HOST1X_CHANNEL_CHANNELCTRL_KERNEL_FILTER_GBUFFER(1),
|
|
||||||
HOST1X_CHANNEL_CHANNELCTRL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev,
|
static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev,
|
||||||
unsigned int index)
|
unsigned int index)
|
||||||
{
|
{
|
||||||
@@ -280,7 +281,6 @@ static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev,
|
|||||||
#else
|
#else
|
||||||
ch->regs = dev->regs + index * 0x100;
|
ch->regs = dev->regs + index * 0x100;
|
||||||
#endif
|
#endif
|
||||||
enable_gather_filter(dev, ch);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ struct host1x_client_ops {
|
|||||||
* @parent: pointer to parent structure
|
* @parent: pointer to parent structure
|
||||||
* @usecount: reference count for this structure
|
* @usecount: reference count for this structure
|
||||||
* @lock: mutex for mutually exclusive concurrency
|
* @lock: mutex for mutually exclusive concurrency
|
||||||
|
* @cache: host1x buffer object cache
|
||||||
*/
|
*/
|
||||||
struct host1x_client {
|
struct host1x_client {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
@@ -143,7 +144,7 @@ struct host1x_bo_ops {
|
|||||||
struct host1x_bo *(*get)(struct host1x_bo *bo);
|
struct host1x_bo *(*get)(struct host1x_bo *bo);
|
||||||
void (*put)(struct host1x_bo *bo);
|
void (*put)(struct host1x_bo *bo);
|
||||||
struct host1x_bo_mapping *(*pin)(struct device *dev, struct host1x_bo *bo,
|
struct host1x_bo_mapping *(*pin)(struct device *dev, struct host1x_bo *bo,
|
||||||
enum dma_data_direction direction);
|
enum dma_data_direction dir);
|
||||||
void (*unpin)(struct host1x_bo_mapping *map);
|
void (*unpin)(struct host1x_bo_mapping *map);
|
||||||
void *(*mmap)(struct host1x_bo *bo);
|
void *(*mmap)(struct host1x_bo *bo);
|
||||||
void (*munmap)(struct host1x_bo *bo, void *addr);
|
void (*munmap)(struct host1x_bo *bo, void *addr);
|
||||||
@@ -235,6 +236,7 @@ struct host1x_job;
|
|||||||
|
|
||||||
struct host1x_channel *host1x_channel_request(struct host1x_client *client);
|
struct host1x_channel *host1x_channel_request(struct host1x_client *client);
|
||||||
struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
|
struct host1x_channel *host1x_channel_get(struct host1x_channel *channel);
|
||||||
|
void host1x_channel_stop(struct host1x_channel *channel);
|
||||||
void host1x_channel_put(struct host1x_channel *channel);
|
void host1x_channel_put(struct host1x_channel *channel);
|
||||||
int host1x_job_submit(struct host1x_job *job);
|
int host1x_job_submit(struct host1x_job *job);
|
||||||
|
|
||||||
|
|||||||
@@ -297,14 +297,11 @@ int host1x_intr_init(struct host1x *host, unsigned int irq_sync)
|
|||||||
"host1x_sp_%02u", id);
|
"host1x_sp_%02u", id);
|
||||||
}
|
}
|
||||||
|
|
||||||
host1x_intr_start(host);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void host1x_intr_deinit(struct host1x *host)
|
void host1x_intr_deinit(struct host1x *host)
|
||||||
{
|
{
|
||||||
host1x_intr_stop(host);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void host1x_intr_start(struct host1x *host)
|
void host1x_intr_start(struct host1x *host)
|
||||||
|
|||||||
@@ -141,11 +141,9 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job)
|
|||||||
struct host1x_client *client = job->client;
|
struct host1x_client *client = job->client;
|
||||||
struct device *dev = client->dev;
|
struct device *dev = client->dev;
|
||||||
struct host1x_job_gather *g;
|
struct host1x_job_gather *g;
|
||||||
struct iommu_domain *domain;
|
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
domain = iommu_get_domain_for_dev(dev);
|
|
||||||
job->num_unpins = 0;
|
job->num_unpins = 0;
|
||||||
|
|
||||||
for (i = 0; i < job->num_relocs; i++) {
|
for (i = 0; i < job->num_relocs; i++) {
|
||||||
|
|||||||
@@ -137,12 +137,21 @@ void host1x_syncpt_restore(struct host1x *host)
|
|||||||
struct host1x_syncpt *sp_base = host->syncpt;
|
struct host1x_syncpt *sp_base = host->syncpt;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for (i = 0; i < host1x_syncpt_nb_pts(host); i++)
|
for (i = 0; i < host1x_syncpt_nb_pts(host); i++) {
|
||||||
|
/*
|
||||||
|
* Unassign syncpt from channels for purposes of Tegra186
|
||||||
|
* syncpoint protection. This prevents any channel from
|
||||||
|
* accessing it until it is reassigned.
|
||||||
|
*/
|
||||||
|
host1x_hw_syncpt_assign_to_channel(host, sp_base + i, NULL);
|
||||||
host1x_hw_syncpt_restore(host, sp_base + i);
|
host1x_hw_syncpt_restore(host, sp_base + i);
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < host1x_syncpt_nb_bases(host); i++)
|
for (i = 0; i < host1x_syncpt_nb_bases(host); i++)
|
||||||
host1x_hw_syncpt_restore_wait_base(host, sp_base + i);
|
host1x_hw_syncpt_restore_wait_base(host, sp_base + i);
|
||||||
|
|
||||||
|
host1x_hw_syncpt_enable_protection(host);
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,13 +344,6 @@ int host1x_syncpt_init(struct host1x *host)
|
|||||||
for (i = 0; i < host->info->nb_pts; i++) {
|
for (i = 0; i < host->info->nb_pts; i++) {
|
||||||
syncpt[i].id = i;
|
syncpt[i].id = i;
|
||||||
syncpt[i].host = host;
|
syncpt[i].host = host;
|
||||||
|
|
||||||
/*
|
|
||||||
* Unassign syncpt from channels for purposes of Tegra186
|
|
||||||
* syncpoint protection. This prevents any channel from
|
|
||||||
* accessing it until it is reassigned.
|
|
||||||
*/
|
|
||||||
host1x_hw_syncpt_assign_to_channel(host, &syncpt[i], NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < host->info->nb_bases; i++)
|
for (i = 0; i < host->info->nb_bases; i++)
|
||||||
@@ -351,9 +353,6 @@ int host1x_syncpt_init(struct host1x *host)
|
|||||||
host->syncpt = syncpt;
|
host->syncpt = syncpt;
|
||||||
host->bases = bases;
|
host->bases = bases;
|
||||||
|
|
||||||
host1x_syncpt_restore(host);
|
|
||||||
host1x_hw_syncpt_enable_protection(host);
|
|
||||||
|
|
||||||
/* Allocate sync point to use for clearing waits for expired fences */
|
/* Allocate sync point to use for clearing waits for expired fences */
|
||||||
host->nop_sp = host1x_syncpt_alloc(host, 0, "reserved-nop");
|
host->nop_sp = host1x_syncpt_alloc(host, 0, "reserved-nop");
|
||||||
if (!host->nop_sp)
|
if (!host->nop_sp)
|
||||||
|
|||||||
Reference in New Issue
Block a user