Skip to content

Commit 48075a6

Browse files
committed
Merge branch 'etnaviv/next' of https://git.pengutronix.de/git/lst/linux into drm-next
This time we've added support for reporting of GPU load via the common fdinfo format, as already supported by multiple other drivers. Improved diagnostic messages for MMU faults. And finally added experimental support for driving the VeriSilicon NPU cores, which are very close relatives to the GPU designs, so close in fact that they can run the same compute instruction set, but with a big NN-fabric/matrix/tensor execution array glued to the side. Signed-off-by: Dave Airlie <[email protected]> From: Lucas Stach <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2 parents 78e9800 + 4c22c61 commit 48075a6

File tree

10 files changed

+238
-57
lines changed

10 files changed

+238
-57
lines changed

drivers/gpu/drm/etnaviv/etnaviv_drv.c

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "etnaviv_gem.h"
2323
#include "etnaviv_mmu.h"
2424
#include "etnaviv_perfmon.h"
25+
#include "common.xml.h"
2526

2627
/*
2728
* DRM operations:
@@ -56,6 +57,11 @@ static int etnaviv_open(struct drm_device *dev, struct drm_file *file)
5657
if (!ctx)
5758
return -ENOMEM;
5859

60+
ret = xa_alloc_cyclic(&priv->active_contexts, &ctx->id, ctx,
61+
xa_limit_32b, &priv->next_context_id, GFP_KERNEL);
62+
if (ret < 0)
63+
goto out_free;
64+
5965
ctx->mmu = etnaviv_iommu_context_init(priv->mmu_global,
6066
priv->cmdbuf_suballoc);
6167
if (!ctx->mmu) {
@@ -99,6 +105,8 @@ static void etnaviv_postclose(struct drm_device *dev, struct drm_file *file)
99105

100106
etnaviv_iommu_context_put(ctx->mmu);
101107

108+
xa_erase(&priv->active_contexts, ctx->id);
109+
102110
kfree(ctx);
103111
}
104112

@@ -468,7 +476,47 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = {
468476
ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW),
469477
};
470478

471-
DEFINE_DRM_GEM_FOPS(fops);
479+
static void etnaviv_fop_show_fdinfo(struct seq_file *m, struct file *f)
480+
{
481+
struct drm_file *file = f->private_data;
482+
struct drm_device *dev = file->minor->dev;
483+
struct etnaviv_drm_private *priv = dev->dev_private;
484+
struct etnaviv_file_private *ctx = file->driver_priv;
485+
486+
/*
487+
* For a description of the text output format used here, see
488+
* Documentation/gpu/drm-usage-stats.rst.
489+
*/
490+
seq_printf(m, "drm-driver:\t%s\n", dev->driver->name);
491+
seq_printf(m, "drm-client-id:\t%u\n", ctx->id);
492+
493+
for (int i = 0; i < ETNA_MAX_PIPES; i++) {
494+
struct etnaviv_gpu *gpu = priv->gpu[i];
495+
char engine[10] = "UNK";
496+
int cur = 0;
497+
498+
if (!gpu)
499+
continue;
500+
501+
if (gpu->identity.features & chipFeatures_PIPE_2D)
502+
cur = snprintf(engine, sizeof(engine), "2D");
503+
if (gpu->identity.features & chipFeatures_PIPE_3D)
504+
cur = snprintf(engine + cur, sizeof(engine) - cur,
505+
"%s3D", cur ? "/" : "");
506+
if (gpu->identity.nn_core_count > 0)
507+
cur = snprintf(engine + cur, sizeof(engine) - cur,
508+
"%sNN", cur ? "/" : "");
509+
510+
seq_printf(m, "drm-engine-%s:\t%llu ns\n", engine,
511+
ctx->sched_entity[i].elapsed_ns);
512+
}
513+
}
514+
515+
static const struct file_operations fops = {
516+
.owner = THIS_MODULE,
517+
DRM_GEM_FOPS,
518+
.show_fdinfo = etnaviv_fop_show_fdinfo,
519+
};
472520

473521
static const struct drm_driver etnaviv_drm_driver = {
474522
.driver_features = DRIVER_GEM | DRIVER_RENDER,
@@ -514,6 +562,8 @@ static int etnaviv_bind(struct device *dev)
514562

515563
dma_set_max_seg_size(dev, SZ_2G);
516564

565+
xa_init_flags(&priv->active_contexts, XA_FLAGS_ALLOC);
566+
517567
mutex_init(&priv->gem_lock);
518568
INIT_LIST_HEAD(&priv->gem_list);
519569
priv->num_gpus = 0;
@@ -563,6 +613,8 @@ static void etnaviv_unbind(struct device *dev)
563613

564614
etnaviv_cmdbuf_suballoc_destroy(priv->cmdbuf_suballoc);
565615

616+
xa_destroy(&priv->active_contexts);
617+
566618
drm->dev_private = NULL;
567619
kfree(priv);
568620

drivers/gpu/drm/etnaviv/etnaviv_drv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/sizes.h>
1313
#include <linux/time64.h>
1414
#include <linux/types.h>
15+
#include <linux/xarray.h>
1516

1617
#include <drm/drm_drv.h>
1718
#include <drm/drm_gem.h>
@@ -28,6 +29,7 @@ struct etnaviv_iommu_global;
2829
#define ETNAVIV_SOFTPIN_START_ADDRESS SZ_4M /* must be >= SUBALLOC_SIZE */
2930

3031
struct etnaviv_file_private {
32+
int id;
3133
struct etnaviv_iommu_context *mmu;
3234
struct drm_sched_entity sched_entity[ETNA_MAX_PIPES];
3335
};
@@ -40,6 +42,9 @@ struct etnaviv_drm_private {
4042
struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc;
4143
struct etnaviv_iommu_global *mmu_global;
4244

45+
struct xarray active_contexts;
46+
u32 next_context_id;
47+
4348
/* list of GEM objects: */
4449
struct mutex gem_lock;
4550
struct list_head gem_list;

drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,11 @@ static void submit_cleanup(struct kref *kref)
393393
wake_up_all(&submit->gpu->fence_event);
394394

395395
if (submit->out_fence) {
396-
/* first remove from IDR, so fence can not be found anymore */
397-
mutex_lock(&submit->gpu->fence_lock);
398-
idr_remove(&submit->gpu->fence_idr, submit->out_fence_id);
399-
mutex_unlock(&submit->gpu->fence_lock);
396+
/*
397+
* Remove from user fence array before dropping the reference,
398+
* so fence can not be found in lookup anymore.
399+
*/
400+
xa_erase(&submit->gpu->user_fences, submit->out_fence_id);
400401
dma_fence_put(submit->out_fence);
401402
}
402403

drivers/gpu/drm/etnaviv/etnaviv_gpu.c

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -773,6 +773,10 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu)
773773
goto fail;
774774
}
775775

776+
if (gpu->identity.nn_core_count > 0)
777+
dev_warn(gpu->dev, "etnaviv has been instantiated on a NPU, "
778+
"for which the UAPI is still experimental\n");
779+
776780
/* Exclude VG cores with FE2.0 */
777781
if (gpu->identity.features & chipFeatures_PIPE_VG &&
778782
gpu->identity.features & chipFeatures_FE20) {
@@ -957,6 +961,8 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m)
957961
gpu->identity.vertex_cache_size);
958962
seq_printf(m, "\t shader_core_count: %d\n",
959963
gpu->identity.shader_core_count);
964+
seq_printf(m, "\t nn_core_count: %d\n",
965+
gpu->identity.nn_core_count);
960966
seq_printf(m, "\t pixel_pipes: %d\n",
961967
gpu->identity.pixel_pipes);
962968
seq_printf(m, "\t vertex_output_buffer_size: %d\n",
@@ -1240,7 +1246,7 @@ int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
12401246
* pretends we didn't find a fence in that case.
12411247
*/
12421248
rcu_read_lock();
1243-
fence = idr_find(&gpu->fence_idr, id);
1249+
fence = xa_load(&gpu->user_fences, id);
12441250
if (fence)
12451251
fence = dma_fence_get_rcu(fence);
12461252
rcu_read_unlock();
@@ -1450,6 +1456,15 @@ static void sync_point_worker(struct work_struct *work)
14501456

14511457
static void dump_mmu_fault(struct etnaviv_gpu *gpu)
14521458
{
1459+
static const char *fault_reasons[] = {
1460+
"slave not present",
1461+
"page not present",
1462+
"write violation",
1463+
"out of bounds",
1464+
"read security violation",
1465+
"write security violation",
1466+
};
1467+
14531468
u32 status_reg, status;
14541469
int i;
14551470

@@ -1462,18 +1477,25 @@ static void dump_mmu_fault(struct etnaviv_gpu *gpu)
14621477
dev_err_ratelimited(gpu->dev, "MMU fault status 0x%08x\n", status);
14631478

14641479
for (i = 0; i < 4; i++) {
1480+
const char *reason = "unknown";
14651481
u32 address_reg;
1482+
u32 mmu_status;
14661483

1467-
if (!(status & (VIVS_MMUv2_STATUS_EXCEPTION0__MASK << (i * 4))))
1484+
mmu_status = (status >> (i * 4)) & VIVS_MMUv2_STATUS_EXCEPTION0__MASK;
1485+
if (!mmu_status)
14681486
continue;
14691487

1488+
if ((mmu_status - 1) < ARRAY_SIZE(fault_reasons))
1489+
reason = fault_reasons[mmu_status - 1];
1490+
14701491
if (gpu->sec_mode == ETNA_SEC_NONE)
14711492
address_reg = VIVS_MMUv2_EXCEPTION_ADDR(i);
14721493
else
14731494
address_reg = VIVS_MMUv2_SEC_EXCEPTION_ADDR;
14741495

1475-
dev_err_ratelimited(gpu->dev, "MMU %d fault addr 0x%08x\n", i,
1476-
gpu_read(gpu, address_reg));
1496+
dev_err_ratelimited(gpu->dev,
1497+
"MMU %d fault (%s) addr 0x%08x\n",
1498+
i, reason, gpu_read(gpu, address_reg));
14771499
}
14781500
}
14791501

@@ -1629,7 +1651,6 @@ static int etnaviv_gpu_hw_suspend(struct etnaviv_gpu *gpu)
16291651
return etnaviv_gpu_clk_disable(gpu);
16301652
}
16311653

1632-
#ifdef CONFIG_PM
16331654
static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
16341655
{
16351656
int ret;
@@ -1645,7 +1666,6 @@ static int etnaviv_gpu_hw_resume(struct etnaviv_gpu *gpu)
16451666

16461667
return 0;
16471668
}
1648-
#endif
16491669

16501670
static int
16511671
etnaviv_gpu_cooling_get_max_state(struct thermal_cooling_device *cdev,
@@ -1713,18 +1733,17 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
17131733
if (ret)
17141734
goto out_workqueue;
17151735

1716-
#ifdef CONFIG_PM
1717-
ret = pm_runtime_get_sync(gpu->dev);
1718-
#else
1719-
ret = etnaviv_gpu_clk_enable(gpu);
1720-
#endif
1736+
if (IS_ENABLED(CONFIG_PM))
1737+
ret = pm_runtime_get_sync(gpu->dev);
1738+
else
1739+
ret = etnaviv_gpu_clk_enable(gpu);
17211740
if (ret < 0)
17221741
goto out_sched;
17231742

17241743

17251744
gpu->drm = drm;
17261745
gpu->fence_context = dma_fence_context_alloc(1);
1727-
idr_init(&gpu->fence_idr);
1746+
xa_init_flags(&gpu->user_fences, XA_FLAGS_ALLOC);
17281747
spin_lock_init(&gpu->fence_spinlock);
17291748

17301749
INIT_WORK(&gpu->sync_point_work, sync_point_worker);
@@ -1761,12 +1780,12 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
17611780

17621781
etnaviv_sched_fini(gpu);
17631782

1764-
#ifdef CONFIG_PM
1765-
pm_runtime_get_sync(gpu->dev);
1766-
pm_runtime_put_sync_suspend(gpu->dev);
1767-
#else
1768-
etnaviv_gpu_hw_suspend(gpu);
1769-
#endif
1783+
if (IS_ENABLED(CONFIG_PM)) {
1784+
pm_runtime_get_sync(gpu->dev);
1785+
pm_runtime_put_sync_suspend(gpu->dev);
1786+
} else {
1787+
etnaviv_gpu_hw_suspend(gpu);
1788+
}
17701789

17711790
if (gpu->mmu_context)
17721791
etnaviv_iommu_context_put(gpu->mmu_context);
@@ -1778,7 +1797,7 @@ static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
17781797
}
17791798

17801799
gpu->drm = NULL;
1781-
idr_destroy(&gpu->fence_idr);
1800+
xa_destroy(&gpu->user_fences);
17821801

17831802
if (IS_ENABLED(CONFIG_DRM_ETNAVIV_THERMAL))
17841803
thermal_cooling_device_unregister(gpu->cooling);
@@ -1810,7 +1829,7 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
18101829

18111830
gpu->dev = &pdev->dev;
18121831
mutex_init(&gpu->lock);
1813-
mutex_init(&gpu->fence_lock);
1832+
mutex_init(&gpu->sched_lock);
18141833

18151834
/* Map registers: */
18161835
gpu->mmio = devm_platform_ioremap_resource(pdev, 0);
@@ -1880,7 +1899,6 @@ static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
18801899
return 0;
18811900
}
18821901

1883-
#ifdef CONFIG_PM
18841902
static int etnaviv_gpu_rpm_suspend(struct device *dev)
18851903
{
18861904
struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
@@ -1923,18 +1941,16 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
19231941

19241942
return 0;
19251943
}
1926-
#endif
19271944

19281945
static const struct dev_pm_ops etnaviv_gpu_pm_ops = {
1929-
SET_RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume,
1930-
NULL)
1946+
RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume, NULL)
19311947
};
19321948

19331949
struct platform_driver etnaviv_gpu_driver = {
19341950
.driver = {
19351951
.name = "etnaviv-gpu",
19361952
.owner = THIS_MODULE,
1937-
.pm = &etnaviv_gpu_pm_ops,
1953+
.pm = pm_ptr(&etnaviv_gpu_pm_ops),
19381954
.of_match_table = etnaviv_gpu_match,
19391955
},
19401956
.probe = etnaviv_gpu_platform_probe,

drivers/gpu/drm/etnaviv/etnaviv_gpu.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ struct etnaviv_chip_identity {
5151
/* Number of shader cores. */
5252
u32 shader_core_count;
5353

54+
/* Number of Neural Network cores. */
55+
u32 nn_core_count;
56+
5457
/* Size of the vertex cache. */
5558
u32 vertex_cache_size;
5659

@@ -100,6 +103,7 @@ struct etnaviv_gpu {
100103
struct etnaviv_chip_identity identity;
101104
enum etnaviv_sec_mode sec_mode;
102105
struct workqueue_struct *wq;
106+
struct mutex sched_lock;
103107
struct drm_gpu_scheduler sched;
104108
bool initialized;
105109
bool fe_running;
@@ -117,8 +121,8 @@ struct etnaviv_gpu {
117121
u32 idle_mask;
118122

119123
/* Fencing support */
120-
struct mutex fence_lock;
121-
struct idr fence_idr;
124+
struct xarray user_fences;
125+
u32 next_user_fence;
122126
u32 next_fence;
123127
u32 completed_fence;
124128
wait_queue_head_t fence_event;

0 commit comments

Comments
 (0)