Skip to content

Commit

Permalink
Merge tag 'drm/tegra/for-6.3-rc1' of https://gitlab.freedesktop.org/d…
Browse files Browse the repository at this point in the history
…rm/tegra into drm-next

drm/tegra: Changes for v6.3-rc1

This set of changes includes a rework of the custom syncpoint interrupt
code to take better advantage of existing DRM/KMS infrastructure.

There's also various bits of cleanup and fixes included.

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Thierry Reding <thierry.reding@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230127170119.495943-1-thierry.reding@gmail.com
  • Loading branch information
Dave Airlie committed Jan 30, 2023
2 parents 54587d9 + 2abdd44 commit dae437d
Show file tree
Hide file tree
Showing 26 changed files with 285 additions and 665 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -7040,7 +7040,7 @@ M: Thierry Reding <thierry.reding@gmail.com>
L: dri-devel@lists.freedesktop.org
L: linux-tegra@vger.kernel.org
S: Supported
T: git git://anongit.freedesktop.org/tegra/linux.git
T: git https://gitlab.freedesktop.org/drm/tegra.git
F: Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-host1x.yaml
F: Documentation/devicetree/bindings/gpu/host1x/
F: drivers/gpu/drm/tegra/
Expand Down
6 changes: 2 additions & 4 deletions drivers/gpu/drm/tegra/dpaux.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,6 @@ static int tegra_dpaux_remove(struct platform_device *pdev)
return 0;
}

#ifdef CONFIG_PM
static int tegra_dpaux_suspend(struct device *dev)
{
struct tegra_dpaux *dpaux = dev_get_drvdata(dev);
Expand Down Expand Up @@ -657,10 +656,9 @@ static int tegra_dpaux_resume(struct device *dev)
clk_disable_unprepare(dpaux->clk);
return err;
}
#endif

static const struct dev_pm_ops tegra_dpaux_pm_ops = {
SET_RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL)
RUNTIME_PM_OPS(tegra_dpaux_suspend, tegra_dpaux_resume, NULL)
};

static const struct tegra_dpaux_soc tegra124_dpaux_soc = {
Expand Down Expand Up @@ -694,7 +692,7 @@ struct platform_driver tegra_dpaux_driver = {
.driver = {
.name = "tegra-dpaux",
.of_match_table = tegra_dpaux_of_match,
.pm = &tegra_dpaux_pm_ops,
.pm = pm_ptr(&tegra_dpaux_pm_ops),
},
.probe = tegra_dpaux_probe,
.remove = tegra_dpaux_remove,
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/tegra/firewall.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ static int fw_check_regs_imm(struct tegra_drm_firewall *fw, u32 offset)
{
bool is_addr;

if (!fw->client->ops->is_addr_reg)
return 0;

is_addr = fw->client->ops->is_addr_reg(fw->client->base.dev, fw->class,
offset);
if (is_addr)
Expand Down
16 changes: 4 additions & 12 deletions drivers/gpu/drm/tegra/nvdec.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,26 +67,18 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,

static int nvdec_boot_falcon(struct nvdec *nvdec)
{
#ifdef CONFIG_IOMMU_API
struct iommu_fwspec *spec = dev_iommu_fwspec_get(nvdec->dev);
#endif
u32 stream_id;
int err;

#ifdef CONFIG_IOMMU_API
if (nvdec->config->supports_sid && spec) {
if (nvdec->config->supports_sid && tegra_dev_iommu_get_stream_id(nvdec->dev, &stream_id)) {
u32 value;

value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) | TRANSCFG_ATT(0, TRANSCFG_SID_HW);
nvdec_writel(nvdec, value, NVDEC_TFBIF_TRANSCFG);

if (spec->num_ids > 0) {
value = spec->ids[0] & 0xffff;

nvdec_writel(nvdec, value, VIC_THI_STREAMID0);
nvdec_writel(nvdec, value, VIC_THI_STREAMID1);
}
nvdec_writel(nvdec, stream_id, VIC_THI_STREAMID0);
nvdec_writel(nvdec, stream_id, VIC_THI_STREAMID1);
}
#endif

err = falcon_boot(&nvdec->falcon);
if (err < 0)
Expand Down
19 changes: 5 additions & 14 deletions drivers/gpu/drm/tegra/submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -609,21 +609,13 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
host1x_memory_context_get(job->memory_context);
}
} else if (context->client->ops->get_streamid_offset) {
#ifdef CONFIG_IOMMU_API
struct iommu_fwspec *spec;

/*
* Job submission will need to temporarily change stream ID,
* so need to tell it what to change it back to.
*/
spec = dev_iommu_fwspec_get(context->client->base.dev);
if (spec && spec->num_ids > 0)
job->engine_fallback_streamid = spec->ids[0] & 0xffff;
else
job->engine_fallback_streamid = 0x7f;
#else
job->engine_fallback_streamid = 0x7f;
#endif
if (!tegra_dev_iommu_get_stream_id(context->client->base.dev,
&job->engine_fallback_streamid))
job->engine_fallback_streamid = TEGRA_STREAM_ID_BYPASS;
}

/* Boot engine. */
Expand Down Expand Up @@ -654,7 +646,7 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
args->syncpt.value = job->syncpt_end;

if (syncobj) {
struct dma_fence *fence = host1x_fence_create(job->syncpt, job->syncpt_end);
struct dma_fence *fence = host1x_fence_create(job->syncpt, job->syncpt_end, true);
if (IS_ERR(fence)) {
err = PTR_ERR(fence);
SUBMIT_ERR(context, "failed to create postfence: %d", err);
Expand All @@ -680,8 +672,7 @@ int tegra_drm_ioctl_channel_submit(struct drm_device *drm, void *data,
kfree(job_data->used_mappings);
}

if (job_data)
kfree(job_data);
kfree(job_data);
put_bo:
gather_bo_put(&bo->base);
unlock:
Expand Down
39 changes: 14 additions & 25 deletions drivers/gpu/drm/tegra/vic.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,41 +56,30 @@ static void vic_writel(struct vic *vic, u32 value, unsigned int offset)

static int vic_boot(struct vic *vic)
{
#ifdef CONFIG_IOMMU_API
struct iommu_fwspec *spec = dev_iommu_fwspec_get(vic->dev);
#endif
u32 fce_ucode_size, fce_bin_data_offset;
u32 fce_ucode_size, fce_bin_data_offset, stream_id;
void *hdr;
int err = 0;

#ifdef CONFIG_IOMMU_API
if (vic->config->supports_sid && spec) {
if (vic->config->supports_sid && tegra_dev_iommu_get_stream_id(vic->dev, &stream_id)) {
u32 value;

value = TRANSCFG_ATT(1, TRANSCFG_SID_FALCON) |
TRANSCFG_ATT(0, TRANSCFG_SID_HW);
vic_writel(vic, value, VIC_TFBIF_TRANSCFG);

if (spec->num_ids > 0) {
value = spec->ids[0] & 0xffff;

/*
* STREAMID0 is used for input/output buffers.
* Initialize it to SID_VIC in case context isolation
* is not enabled, and SID_VIC is used for both firmware
* and data buffers.
*
* If context isolation is enabled, it will be
* overridden by the SETSTREAMID opcode as part of
* each job.
*/
vic_writel(vic, value, VIC_THI_STREAMID0);

/* STREAMID1 is used for firmware loading. */
vic_writel(vic, value, VIC_THI_STREAMID1);
}
/*
* STREAMID0 is used for input/output buffers. Initialize it to SID_VIC in case
* context isolation is not enabled, and SID_VIC is used for both firmware and
* data buffers.
*
* If context isolation is enabled, it will be overridden by the SETSTREAMID
* opcode as part of each job.
*/
vic_writel(vic, stream_id, VIC_THI_STREAMID0);

/* STREAMID1 is used for firmware loading. */
vic_writel(vic, stream_id, VIC_THI_STREAMID1);
}
#endif

/* setup clockgating registers */
vic_writel(vic, CG_IDLE_CG_DLY_CNT(4) |
Expand Down
14 changes: 11 additions & 3 deletions drivers/gpu/host1x/cdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,15 @@ void host1x_cdma_update_sync_queue(struct host1x_cdma *cdma,
host1x_hw_cdma_resume(host1x, cdma, restart_addr);
}

static void cdma_update_work(struct work_struct *work)
{
struct host1x_cdma *cdma = container_of(work, struct host1x_cdma, update_work);

mutex_lock(&cdma->lock);
update_cdma_locked(cdma);
mutex_unlock(&cdma->lock);
}

/*
* Create a cdma
*/
Expand All @@ -499,6 +508,7 @@ int host1x_cdma_init(struct host1x_cdma *cdma)

mutex_init(&cdma->lock);
init_completion(&cdma->complete);
INIT_WORK(&cdma->update_work, cdma_update_work);

INIT_LIST_HEAD(&cdma->sync_queue);

Expand Down Expand Up @@ -679,7 +689,5 @@ void host1x_cdma_end(struct host1x_cdma *cdma,
*/
void host1x_cdma_update(struct host1x_cdma *cdma)
{
mutex_lock(&cdma->lock);
update_cdma_locked(cdma);
mutex_unlock(&cdma->lock);
schedule_work(&cdma->update_work);
}
2 changes: 2 additions & 0 deletions drivers/gpu/host1x/cdma.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/sched.h>
#include <linux/completion.h>
#include <linux/list.h>
#include <linux/workqueue.h>

struct host1x_syncpt;
struct host1x_userctx_timeout;
Expand Down Expand Up @@ -69,6 +70,7 @@ struct host1x_cdma {
struct buffer_timeout timeout; /* channel's timeout state/wq */
bool running;
bool torndown;
struct work_struct update_work;
};

#define cdma_to_channel(cdma) container_of(cdma, struct host1x_channel, cdma)
Expand Down
8 changes: 2 additions & 6 deletions drivers/gpu/host1x/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ int host1x_memory_context_list_init(struct host1x *host1x)
cdl->len = err / 4;

for (i = 0; i < cdl->len; i++) {
struct iommu_fwspec *fwspec;

ctx = &cdl->devs[i];

ctx->host = host1x;
Expand Down Expand Up @@ -70,14 +68,12 @@ int host1x_memory_context_list_init(struct host1x *host1x)
goto del_devices;
}

fwspec = dev_iommu_fwspec_get(&ctx->dev);
if (!fwspec || !device_iommu_mapped(&ctx->dev)) {
if (!tegra_dev_iommu_get_stream_id(&ctx->dev, &ctx->stream_id) ||
!device_iommu_mapped(&ctx->dev)) {
dev_err(host1x->dev, "Context device %d has no IOMMU!\n", i);
device_del(&ctx->dev);
goto del_devices;
}

ctx->stream_id = fwspec->ids[0] & 0xffff;
}

return 0;
Expand Down
7 changes: 4 additions & 3 deletions drivers/gpu/host1x/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo)

static void show_syncpts(struct host1x *m, struct output *o, bool show_all)
{
unsigned long irqflags;
struct list_head *pos;
unsigned int i;
int err;
Expand All @@ -92,10 +93,10 @@ static void show_syncpts(struct host1x *m, struct output *o, bool show_all)
u32 min = host1x_syncpt_load(m->syncpt + i);
unsigned int waiters = 0;

spin_lock(&m->syncpt[i].intr.lock);
list_for_each(pos, &m->syncpt[i].intr.wait_head)
spin_lock_irqsave(&m->syncpt[i].fences.lock, irqflags);
list_for_each(pos, &m->syncpt[i].fences.list)
waiters++;
spin_unlock(&m->syncpt[i].intr.lock);
spin_unlock_irqrestore(&m->syncpt[i].fences.lock, irqflags);

if (!kref_read(&m->syncpt[i].ref))
continue;
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/host1x/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ static int host1x_probe(struct platform_device *pdev)
return PTR_ERR(host->regs);
}

syncpt_irq = platform_get_irq(pdev, 0);
host->syncpt_irq = platform_get_irq(pdev, 0);
if (syncpt_irq < 0)
return syncpt_irq;

Expand Down Expand Up @@ -578,7 +578,7 @@ static int host1x_probe(struct platform_device *pdev)
goto free_contexts;
}

err = host1x_intr_init(host, syncpt_irq);
err = host1x_intr_init(host);
if (err) {
dev_err(&pdev->dev, "failed to initialize interrupts\n");
goto deinit_syncpt;
Expand Down
10 changes: 4 additions & 6 deletions drivers/gpu/host1x/dev.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ struct host1x_syncpt_ops {
};

struct host1x_intr_ops {
int (*init_host_sync)(struct host1x *host, u32 cpm,
void (*syncpt_thresh_work)(struct work_struct *work));
int (*init_host_sync)(struct host1x *host, u32 cpm);
void (*set_syncpt_threshold)(
struct host1x *host, unsigned int id, u32 thresh);
void (*enable_syncpt_intr)(struct host1x *host, unsigned int id);
Expand Down Expand Up @@ -125,6 +124,7 @@ struct host1x {
void __iomem *regs;
void __iomem *hv_regs; /* hypervisor region */
void __iomem *common_regs;
int syncpt_irq;
struct host1x_syncpt *syncpt;
struct host1x_syncpt_base *bases;
struct device *dev;
Expand All @@ -138,7 +138,6 @@ struct host1x {
dma_addr_t iova_end;

struct mutex intr_mutex;
int intr_syncpt_irq;

const struct host1x_syncpt_ops *syncpt_op;
const struct host1x_intr_ops *intr_op;
Expand Down Expand Up @@ -216,10 +215,9 @@ static inline void host1x_hw_syncpt_enable_protection(struct host1x *host)
return host->syncpt_op->enable_protection(host);
}

static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm,
void (*syncpt_thresh_work)(struct work_struct *))
static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm)
{
return host->intr_op->init_host_sync(host, cpm, syncpt_thresh_work);
return host->intr_op->init_host_sync(host, cpm);
}

static inline void host1x_hw_intr_set_syncpt_threshold(struct host1x *host,
Expand Down
Loading

0 comments on commit dae437d

Please sign in to comment.