2023-05-29 17:31:55

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v5 0/6] drm/etnaviv: add pci device driver support

There is a Vivante GC1000 (v5037) in LS2K1000 and LS7A1000, this GPU is a
PCI device, and it has 2D and 3D cores in the same device. Thus, this patch
series is trying to add PCI device driver support to etnaviv.

Sui Jingfeng (6):
drm/etnaviv: add a dedicated function to register an irq handler
drm/etnaviv: add a dedicated function to get various clocks
drm/etnaviv: add dedicated functions to create and destroy platform
devices
drm/etnaviv: add helpers for private data construction and destruction
drm/etnaviv: expand driver support for the PCI devices
drm/etnaviv: allow usperspace create cached coherent bo

drivers/gpu/drm/etnaviv/Makefile | 1 +
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 183 +++++++++++++------
drivers/gpu/drm/etnaviv/etnaviv_drv.h | 7 +
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 22 ++-
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 9 +-
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 185 ++++++++++++++------
drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 13 ++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c | 88 ++++++++++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h | 10 ++
include/uapi/drm/etnaviv_drm.h | 11 +-
10 files changed, 415 insertions(+), 114 deletions(-)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h

--
2.25.1



2023-05-29 17:35:12

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v5 6/6] drm/etnaviv: allow usperspace create cached coherent bo

cached system RAM is coherent on loongson CPUs, and the GPU and DC allways
snoop the CPU's cache. write-combine caching property is not suitiable for
us.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 2 +-
drivers/gpu/drm/etnaviv/etnaviv_gem.c | 22 +++++++++++++++++++--
drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 9 ++++++++-
include/uapi/drm/etnaviv_drm.h | 11 ++++++-----
4 files changed, 35 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 7ff795c5cc79..3a86d1211ca5 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -275,7 +275,7 @@ static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data,
struct drm_etnaviv_gem_new *args = data;

if (args->flags & ~(ETNA_BO_CACHED | ETNA_BO_WC | ETNA_BO_UNCACHED |
- ETNA_BO_FORCE_MMU))
+ ETNA_BO_CACHED_COHERENT | ETNA_BO_FORCE_MMU))
return -EINVAL;

return etnaviv_gem_new_handle(dev, file, args->size,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index b5f73502e3dd..d8b559bd33d3 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -343,6 +343,7 @@ void *etnaviv_gem_vmap(struct drm_gem_object *obj)
static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj)
{
struct page **pages;
+ pgprot_t prot;

lockdep_assert_held(&obj->lock);

@@ -350,8 +351,20 @@ static void *etnaviv_gem_vmap_impl(struct etnaviv_gem_object *obj)
if (IS_ERR(pages))
return NULL;

- return vmap(pages, obj->base.size >> PAGE_SHIFT,
- VM_MAP, pgprot_writecombine(PAGE_KERNEL));
+ switch (obj->flags) {
+ case ETNA_BO_CACHED_COHERENT:
+ case ETNA_BO_CACHED:
+ prot = PAGE_KERNEL;
+ break;
+ case ETNA_BO_UNCACHED:
+ prot = pgprot_noncached(PAGE_KERNEL);
+ break;
+ case ETNA_BO_WC:
+ default:
+ prot = pgprot_writecombine(PAGE_KERNEL);
+ }
+
+ return vmap(pages, obj->base.size >> PAGE_SHIFT, VM_MAP, prot);
}

static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op)
@@ -545,6 +558,7 @@ static const struct drm_gem_object_funcs etnaviv_gem_object_funcs = {
static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj)
{
+ struct etnaviv_drm_private *priv = dev->dev_private;
struct etnaviv_gem_object *etnaviv_obj;
unsigned sz = sizeof(*etnaviv_obj);
bool valid = true;
@@ -555,6 +569,10 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags,
case ETNA_BO_CACHED:
case ETNA_BO_WC:
break;
+ case ETNA_BO_CACHED_COHERENT:
+ if (priv->has_cached_coherent)
+ break;
+ fallthrough;
default:
valid = false;
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index 3524b5811682..671d91d8f1c6 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -112,11 +112,18 @@ static const struct etnaviv_gem_ops etnaviv_gem_prime_ops = {
struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sgt)
{
+ struct etnaviv_drm_private *priv = dev->dev_private;
struct etnaviv_gem_object *etnaviv_obj;
size_t size = PAGE_ALIGN(attach->dmabuf->size);
+ u32 cache_flags;
int ret, npages;

- ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC,
+ if (priv->has_cached_coherent)
+ cache_flags = ETNA_BO_CACHED_COHERENT;
+ else
+ cache_flags = ETNA_BO_WC;
+
+ ret = etnaviv_gem_new_private(dev, size, cache_flags,
&etnaviv_gem_prime_ops, &etnaviv_obj);
if (ret < 0)
return ERR_PTR(ret);
diff --git a/include/uapi/drm/etnaviv_drm.h b/include/uapi/drm/etnaviv_drm.h
index af024d90453d..474b0db286de 100644
--- a/include/uapi/drm/etnaviv_drm.h
+++ b/include/uapi/drm/etnaviv_drm.h
@@ -90,13 +90,14 @@ struct drm_etnaviv_param {
* GEM buffers:
*/

-#define ETNA_BO_CACHE_MASK 0x000f0000
+#define ETNA_BO_CACHE_MASK 0x000f0000
/* cache modes */
-#define ETNA_BO_CACHED 0x00010000
-#define ETNA_BO_WC 0x00020000
-#define ETNA_BO_UNCACHED 0x00040000
+#define ETNA_BO_CACHED 0x00010000
+#define ETNA_BO_WC 0x00020000
+#define ETNA_BO_UNCACHED 0x00040000
+#define ETNA_BO_CACHED_COHERENT 0x00080000
/* map flags */
-#define ETNA_BO_FORCE_MMU 0x00100000
+#define ETNA_BO_FORCE_MMU 0x00100000

struct drm_etnaviv_gem_new {
__u64 size; /* in */
--
2.25.1


2023-05-29 17:38:48

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v5 3/6] drm/etnaviv: add dedicated functions to create and destroy platform devices

Also rename the virtual master platform device as etnaviv_platform_device,
for better reflection that it is a platform device, not a DRM device.

Another benefit is that we no longer need to call of_node_put() for three
different cases, Instead, we only need to call it once.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 56 +++++++++++++++++++--------
1 file changed, 39 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 31a7f59ccb49..0a9d90c18f2c 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -656,12 +656,44 @@ static struct platform_driver etnaviv_platform_driver = {
},
};

-static struct platform_device *etnaviv_drm;
+static struct platform_device *etnaviv_platform_device;

-static int __init etnaviv_init(void)
+static int etnaviv_create_platform_device(const char *name,
+ struct platform_device **ppdev)
{
struct platform_device *pdev;
int ret;
+
+ pdev = platform_device_alloc(name, PLATFORM_DEVID_NONE);
+ if (!pdev)
+ return -ENOMEM;
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ platform_device_put(pdev);
+ return ret;
+ }
+
+ *ppdev = pdev;
+
+ return 0;
+}
+
+static void etnaviv_destroy_platform_device(struct platform_device **ppdev)
+{
+ struct platform_device *pdev = *ppdev;
+
+ if (!pdev)
+ return;
+
+ *ppdev = NULL;
+
+ platform_device_unregister(pdev);
+}
+
+static int __init etnaviv_init(void)
+{
+ int ret;
struct device_node *np;

etnaviv_validate_init();
@@ -682,22 +714,12 @@ static int __init etnaviv_init(void)
if (!of_device_is_available(np))
continue;

- pdev = platform_device_alloc("etnaviv", PLATFORM_DEVID_NONE);
- if (!pdev) {
- ret = -ENOMEM;
- of_node_put(np);
- goto unregister_platform_driver;
- }
-
- ret = platform_device_add(pdev);
- if (ret) {
- platform_device_put(pdev);
- of_node_put(np);
+ ret = etnaviv_create_platform_device("etnaviv",
+ &etnaviv_platform_device);
+ of_node_put(np);
+ if (ret)
goto unregister_platform_driver;
- }

- etnaviv_drm = pdev;
- of_node_put(np);
break;
}

@@ -713,7 +735,7 @@ module_init(etnaviv_init);

static void __exit etnaviv_exit(void)
{
- platform_device_unregister(etnaviv_drm);
+ etnaviv_destroy_platform_device(&etnaviv_platform_device);
platform_driver_unregister(&etnaviv_platform_driver);
platform_driver_unregister(&etnaviv_gpu_driver);
}
--
2.25.1


2023-05-29 17:48:31

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v5 2/6] drm/etnaviv: add a dedicated function to get various clocks

Because it is also platform-dependent, there are environments where don't
have CLK subsystem support, for example, discreted PCI gpu. So don't rage
quit if there is no CLK subsystem.

For the GPU in LS7a1000 and LS2k2000, the working frequency of the GPU is
tuned by configuring the PLL register directly.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 62 ++++++++++++++++++---------
drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 1 +
2 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 636d3f39ddcb..4937580551a5 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1565,10 +1565,45 @@ static irqreturn_t irq_handler(int irq, void *data)
return ret;
}

+static int etnaviv_gpu_clk_get(struct etnaviv_gpu *gpu)
+{
+ struct device *dev = gpu->dev;
+
+ if (gpu->no_clk)
+ return 0;
+
+ gpu->clk_reg = devm_clk_get_optional(dev, "reg");
+ DBG("clk_reg: %p", gpu->clk_reg);
+ if (IS_ERR(gpu->clk_reg))
+ return PTR_ERR(gpu->clk_reg);
+
+ gpu->clk_bus = devm_clk_get_optional(dev, "bus");
+ DBG("clk_bus: %p", gpu->clk_bus);
+ if (IS_ERR(gpu->clk_bus))
+ return PTR_ERR(gpu->clk_bus);
+
+ gpu->clk_core = devm_clk_get(dev, "core");
+ DBG("clk_core: %p", gpu->clk_core);
+ if (IS_ERR(gpu->clk_core))
+ return PTR_ERR(gpu->clk_core);
+ gpu->base_rate_core = clk_get_rate(gpu->clk_core);
+
+ gpu->clk_shader = devm_clk_get_optional(dev, "shader");
+ DBG("clk_shader: %p", gpu->clk_shader);
+ if (IS_ERR(gpu->clk_shader))
+ return PTR_ERR(gpu->clk_shader);
+ gpu->base_rate_shader = clk_get_rate(gpu->clk_shader);
+
+ return 0;
+}
+
static int etnaviv_gpu_clk_enable(struct etnaviv_gpu *gpu)
{
int ret;

+ if (gpu->no_clk)
+ return 0;
+
ret = clk_prepare_enable(gpu->clk_reg);
if (ret)
return ret;
@@ -1599,6 +1634,9 @@ static int etnaviv_gpu_clk_enable(struct etnaviv_gpu *gpu)

static int etnaviv_gpu_clk_disable(struct etnaviv_gpu *gpu)
{
+ if (gpu->no_clk)
+ return 0;
+
clk_disable_unprepare(gpu->clk_shader);
clk_disable_unprepare(gpu->clk_core);
clk_disable_unprepare(gpu->clk_bus);
@@ -1865,27 +1903,9 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
return err;

/* Get Clocks: */
- gpu->clk_reg = devm_clk_get_optional(&pdev->dev, "reg");
- DBG("clk_reg: %p", gpu->clk_reg);
- if (IS_ERR(gpu->clk_reg))
- return PTR_ERR(gpu->clk_reg);
-
- gpu->clk_bus = devm_clk_get_optional(&pdev->dev, "bus");
- DBG("clk_bus: %p", gpu->clk_bus);
- if (IS_ERR(gpu->clk_bus))
- return PTR_ERR(gpu->clk_bus);
-
- gpu->clk_core = devm_clk_get(&pdev->dev, "core");
- DBG("clk_core: %p", gpu->clk_core);
- if (IS_ERR(gpu->clk_core))
- return PTR_ERR(gpu->clk_core);
- gpu->base_rate_core = clk_get_rate(gpu->clk_core);
-
- gpu->clk_shader = devm_clk_get_optional(&pdev->dev, "shader");
- DBG("clk_shader: %p", gpu->clk_shader);
- if (IS_ERR(gpu->clk_shader))
- return PTR_ERR(gpu->clk_shader);
- gpu->base_rate_shader = clk_get_rate(gpu->clk_shader);
+ err = etnaviv_gpu_clk_get(gpu);
+ if (err)
+ return err;

/* TODO: figure out max mapped size */
dev_set_drvdata(dev, gpu);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 98c6f9c320fc..6da5209a7d64 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -148,6 +148,7 @@ struct etnaviv_gpu {
struct clk *clk_reg;
struct clk *clk_core;
struct clk *clk_shader;
+ bool no_clk;

unsigned int freq_scale;
unsigned long base_rate_core;
--
2.25.1


2023-05-29 17:50:02

by Sui Jingfeng

[permalink] [raw]
Subject: [PATCH v5 5/6] drm/etnaviv: expand driver support for the PCI devices

This patch adds PCI driver support on top of what already have. Take the
GC1000 in LS7A1000/LS2K1000 as the first instance of the PCI device driver.
There is only one GPU core for the GC1000 in the LS7A1000 and LS2K1000.
Therefore, component frameworks can be avoided. Because we want to bind the
DRM driver service to the PCI driver manually.
    
We avoid using the component framework because the virtual master device
will not be used without a force override. X server and Mesa will try to
find the PCI device to use by default. Creating a virtual master device
for PCI GPUs cause unnecessary troubles.
    
Using the component framework with a PCI device is still possible; it is
just that the solo PCI device should be the master. A platform with a
single GPU core could also try the non-component code path.

Signed-off-by: Sui Jingfeng <[email protected]>
---
drivers/gpu/drm/etnaviv/Makefile | 1 +
drivers/gpu/drm/etnaviv/etnaviv_drv.c | 62 ++++++++++++---
drivers/gpu/drm/etnaviv/etnaviv_drv.h | 3 +
drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 97 ++++++++++++++++-------
drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 12 +++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c | 88 ++++++++++++++++++++
drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h | 10 +++
7 files changed, 232 insertions(+), 41 deletions(-)
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
create mode 100644 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h

diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile
index 46e5ffad69a6..3f8b99664a58 100644
--- a/drivers/gpu/drm/etnaviv/Makefile
+++ b/drivers/gpu/drm/etnaviv/Makefile
@@ -13,6 +13,7 @@ etnaviv-y := \
etnaviv_iommu_v2.o \
etnaviv_iommu.o \
etnaviv_mmu.o \
+ etnaviv_pci_drv.o \
etnaviv_perfmon.o \
etnaviv_sched.o

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 56c98711f8e1..7ff795c5cc79 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -7,6 +7,7 @@
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of_platform.h>
+#include <linux/pci.h>
#include <linux/uaccess.h>

#include <drm/drm_debugfs.h>
@@ -21,6 +22,7 @@
#include "etnaviv_gpu.h"
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
+#include "etnaviv_pci_drv.h"
#include "etnaviv_perfmon.h"

/*
@@ -525,6 +527,16 @@ static int etnaviv_alloc_private(struct device *dev,
return ret;
}

+ /*
+ * Loongson Mips and LoongArch CPU(ls3a5000, ls3c5000, ls2k1000la)
+ * maintain cache coherency by hardware
+ */
+ if (IS_ENABLED(CONFIG_CPU_LOONGSON64) || IS_ENABLED(CONFIG_LOONGARCH))
+ priv->has_cached_coherent = true;
+
+ dev_info(dev, "Cached coherent mode is %s\n",
+ priv->has_cached_coherent ? "support" : "not support");
+
*ppriv = priv;

return 0;
@@ -539,10 +551,9 @@ static void etnaviv_free_private(struct etnaviv_drm_private *priv)
kfree(priv);
}

-/*
- * Platform driver:
- */
-static int etnaviv_bind(struct device *dev)
+static struct etnaviv_drm_private *etna_private_s;
+
+int etnaviv_drm_bind(struct device *dev, bool component)
{
struct etnaviv_drm_private *priv;
struct drm_device *drm;
@@ -558,12 +569,15 @@ static int etnaviv_bind(struct device *dev)

priv->drm = drm;
drm->dev_private = priv;
+ etna_private_s = priv;

dma_set_max_seg_size(dev, SZ_2G);

- dev_set_drvdata(dev, drm);
+ if (component)
+ ret = component_bind_all(dev, drm);
+ else
+ ret = etnaviv_gpu_bind(dev, NULL, drm);

- ret = component_bind_all(dev, drm);
if (ret < 0)
goto out_free_priv;

@@ -585,14 +599,17 @@ static int etnaviv_bind(struct device *dev)
return ret;
}

-static void etnaviv_unbind(struct device *dev)
+void etnaviv_drm_unbind(struct device *dev, bool component)
{
- struct drm_device *drm = dev_get_drvdata(dev);
- struct etnaviv_drm_private *priv = drm->dev_private;
+ struct etnaviv_drm_private *priv = etna_private_s;
+ struct drm_device *drm = priv->drm;

drm_dev_unregister(drm);

- component_unbind_all(dev, drm);
+ if (component)
+ component_unbind_all(dev, drm);
+ else
+ etnaviv_gpu_unbind(dev, NULL, drm);

etnaviv_free_private(priv);

@@ -601,9 +618,22 @@ static void etnaviv_unbind(struct device *dev)
drm_dev_put(drm);
}

+/*
+ * Platform driver:
+ */
+static int etnaviv_master_bind(struct device *dev)
+{
+ return etnaviv_drm_bind(dev, true);
+}
+
+static void etnaviv_master_unbind(struct device *dev)
+{
+ return etnaviv_drm_unbind(dev, true);
+}
+
static const struct component_master_ops etnaviv_master_ops = {
- .bind = etnaviv_bind,
- .unbind = etnaviv_unbind,
+ .bind = etnaviv_master_bind,
+ .unbind = etnaviv_master_unbind,
};

static int etnaviv_pdev_probe(struct platform_device *pdev)
@@ -723,10 +753,14 @@ static int __init etnaviv_init(void)
if (ret != 0)
return ret;

- ret = platform_driver_register(&etnaviv_platform_driver);
+ ret = pci_register_driver(&etnaviv_pci_driver);
if (ret != 0)
goto unregister_gpu_driver;

+ ret = platform_driver_register(&etnaviv_platform_driver);
+ if (ret != 0)
+ goto unregister_pci_driver;
+
/*
* If the DT contains at least one available GPU device, instantiate
* the DRM platform device.
@@ -748,6 +782,8 @@ static int __init etnaviv_init(void)

unregister_platform_driver:
platform_driver_unregister(&etnaviv_platform_driver);
+unregister_pci_driver:
+ pci_unregister_driver(&etnaviv_pci_driver);
unregister_gpu_driver:
platform_driver_unregister(&etnaviv_gpu_driver);
return ret;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index 87fb52c03c5e..934fc3744389 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -86,6 +86,9 @@ bool etnaviv_cmd_validate_one(struct etnaviv_gpu *gpu,
u32 *stream, unsigned int size,
struct drm_etnaviv_gem_submit_reloc *relocs, unsigned int reloc_size);

+int etnaviv_drm_bind(struct device *dev, bool component);
+void etnaviv_drm_unbind(struct device *dev, bool component);
+
#ifdef CONFIG_DEBUG_FS
void etnaviv_gem_describe_objects(struct etnaviv_drm_private *priv,
struct seq_file *m);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 4937580551a5..700f2414b87d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1565,10 +1565,11 @@ static irqreturn_t irq_handler(int irq, void *data)
return ret;
}

-static int etnaviv_gpu_clk_get(struct etnaviv_gpu *gpu)
+static int etnaviv_gpu_clk_get(struct etnaviv_gpu *gpu, bool no_clk)
{
struct device *dev = gpu->dev;

+ gpu->no_clk = no_clk;
if (gpu->no_clk)
return 0;

@@ -1746,8 +1747,7 @@ static const struct thermal_cooling_device_ops cooling_ops = {
.set_cur_state = etnaviv_gpu_cooling_set_cur_state,
};

-static int etnaviv_gpu_bind(struct device *dev, struct device *master,
- void *data)
+int etnaviv_gpu_bind(struct device *dev, struct device *master, void *data)
{
struct drm_device *drm = data;
struct etnaviv_drm_private *priv = drm->dev_private;
@@ -1778,7 +1778,6 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
if (ret < 0)
goto out_sched;

-
gpu->drm = drm;
gpu->fence_context = dma_fence_context_alloc(1);
xa_init_flags(&gpu->user_fences, XA_FLAGS_ALLOC);
@@ -1807,8 +1806,7 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master,
return ret;
}

-static void etnaviv_gpu_unbind(struct device *dev, struct device *master,
- void *data)
+void etnaviv_gpu_unbind(struct device *dev, struct device *master, void *data)
{
struct etnaviv_gpu *gpu = dev_get_drvdata(dev);

@@ -1878,9 +1876,37 @@ static int etnaviv_gpu_register_irq(struct etnaviv_gpu *gpu, int irq)
return 0;
}

-static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
+static int etnaviv_gpu_plat_drv_init(struct etnaviv_gpu *gpu, bool component)
+{
+ struct device *dev = gpu->dev;
+ struct platform_device *pdev = to_platform_device(dev);
+ int err;
+
+ /* Map registers: */
+ gpu->mmio = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(gpu->mmio))
+ return PTR_ERR(gpu->mmio);
+
+ if (component) {
+ err = component_add(dev, &gpu_ops);
+ if (err < 0) {
+ dev_err(dev, "failed to register component: %d\n", err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static void etnaviv_gpu_plat_drv_fini(struct etnaviv_gpu *gpu, bool component)
+{
+ if (component)
+ component_del(gpu->dev, &gpu_ops);
+}
+
+int etnaviv_gpu_driver_create(struct device *dev, int irq, bool component,
+ bool no_clk, pfn_gpu_init_t gpu_post_init)
{
- struct device *dev = &pdev->dev;
struct etnaviv_gpu *gpu;
int err;

@@ -1888,22 +1914,16 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
if (!gpu)
return -ENOMEM;

- gpu->dev = &pdev->dev;
+ gpu->dev = dev;
mutex_init(&gpu->lock);
mutex_init(&gpu->sched_lock);

- /* Map registers: */
- gpu->mmio = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(gpu->mmio))
- return PTR_ERR(gpu->mmio);
-
/* Get Interrupt: */
- err = etnaviv_gpu_register_irq(gpu, platform_get_irq(pdev, 0));
+ err = etnaviv_gpu_register_irq(gpu, irq);
if (err)
return err;

- /* Get Clocks: */
- err = etnaviv_gpu_clk_get(gpu);
+ err = etnaviv_gpu_clk_get(gpu, no_clk);
if (err)
return err;

@@ -1915,23 +1935,44 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
* autosuspend delay is rather arbitary: no measurements have
* yet been performed to determine an appropriate value.
*/
- pm_runtime_use_autosuspend(gpu->dev);
- pm_runtime_set_autosuspend_delay(gpu->dev, 200);
- pm_runtime_enable(gpu->dev);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_autosuspend_delay(dev, 200);
+ pm_runtime_enable(dev);

- err = component_add(&pdev->dev, &gpu_ops);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to register component: %d\n", err);
- return err;
- }
+ gpu_post_init(gpu, component);

return 0;
}

+void etnaviv_gpu_driver_destroy(struct device *dev, bool component,
+ pfn_gpu_fini_t gpu_early_fini)
+{
+ struct etnaviv_gpu *gpu = dev_get_drvdata(dev);
+
+ if (!gpu) {
+ dev_err(dev, "device not initialized properly\n");
+ return;
+ }
+
+ gpu_early_fini(gpu, component);
+
+ pm_runtime_disable(dev);
+}
+
+static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int irq = platform_get_irq(pdev, 0);
+
+ return etnaviv_gpu_driver_create(dev, irq, true, false, etnaviv_gpu_plat_drv_init);
+}
+
static int etnaviv_gpu_platform_remove(struct platform_device *pdev)
{
- component_del(&pdev->dev, &gpu_ops);
- pm_runtime_disable(&pdev->dev);
+ struct device *dev = &pdev->dev;
+
+ etnaviv_gpu_driver_destroy(dev, true, etnaviv_gpu_plat_drv_fini);
+
return 0;
}

@@ -1978,7 +2019,7 @@ static int etnaviv_gpu_rpm_resume(struct device *dev)
return 0;
}

-static const struct dev_pm_ops etnaviv_gpu_pm_ops = {
+const struct dev_pm_ops etnaviv_gpu_pm_ops = {
RUNTIME_PM_OPS(etnaviv_gpu_rpm_suspend, etnaviv_gpu_rpm_resume, NULL)
};

diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 6da5209a7d64..cfcdc5dde9d9 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -207,6 +207,18 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu);
int etnaviv_gpu_wait_idle(struct etnaviv_gpu *gpu, unsigned int timeout_ms);
void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch);

+typedef int (*pfn_gpu_init_t)(struct etnaviv_gpu *gpu, bool component);
+typedef void (*pfn_gpu_fini_t)(struct etnaviv_gpu *gpu, bool component);
+
+int etnaviv_gpu_driver_create(struct device *dev, int irq, bool component,
+ bool no_clk, pfn_gpu_init_t post_init);
+void etnaviv_gpu_driver_destroy(struct device *dev, bool component,
+ pfn_gpu_fini_t early_fini);
+
+int etnaviv_gpu_bind(struct device *dev, struct device *master, void *data);
+void etnaviv_gpu_unbind(struct device *dev, struct device *master, void *data);
+
extern struct platform_driver etnaviv_gpu_driver;
+extern const struct dev_pm_ops etnaviv_gpu_pm_ops;

#endif /* __ETNAVIV_GPU_H__ */
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
new file mode 100644
index 000000000000..e64a03061d09
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/pci.h>
+
+#include "etnaviv_drv.h"
+#include "etnaviv_gpu.h"
+#include "etnaviv_pci_drv.h"
+
+enum etnaviv_pci_gpu_family {
+ GC1000_IN_LS7A1000 = 0,
+ GC1000_IN_LS2K1000 = 1,
+};
+
+static int etnaviv_gpu_pci_init(struct etnaviv_gpu *gpu, bool component)
+{
+ struct pci_dev *pdev = to_pci_dev(gpu->dev);
+
+ /* Map registers, assume the PCI bar 0 contain the registers */
+ gpu->mmio = pcim_iomap(pdev, 0, 0);
+ if (IS_ERR(gpu->mmio))
+ return PTR_ERR(gpu->mmio);
+
+ gpu->no_clk = true;
+
+ return 0;
+}
+
+static void etnaviv_gpu_pci_fini(struct etnaviv_gpu *gpu, bool component)
+{
+ struct pci_dev *pdev = to_pci_dev(gpu->dev);
+
+ pci_clear_master(pdev);
+
+ dev_dbg(gpu->dev, "component is %s\n",
+ component ? "enabled" : "disabled");
+}
+
+static int etnaviv_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *ent)
+{
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = pcim_enable_device(pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable\n");
+ return ret;
+ }
+
+ pci_set_master(pdev);
+
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ /* Create a GPU driver instance for the PCI device itself */
+ ret = etnaviv_gpu_driver_create(dev, pdev->irq, false, true,
+ etnaviv_gpu_pci_init);
+ if (ret)
+ return ret;
+
+ return etnaviv_drm_bind(dev, false);
+}
+
+static void etnaviv_pci_remove(struct pci_dev *pdev)
+{
+ struct device *dev = &pdev->dev;
+
+ etnaviv_drm_unbind(dev, false);
+
+ etnaviv_gpu_driver_destroy(dev, false, etnaviv_gpu_pci_fini);
+}
+
+static const struct pci_device_id etnaviv_pci_id_lists[] = {
+ {0x0014, 0x7a15, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GC1000_IN_LS7A1000},
+ {0x0014, 0x7a05, PCI_ANY_ID, PCI_ANY_ID, 0, 0, GC1000_IN_LS2K1000},
+ {0, 0, 0, 0, 0, 0, 0}
+};
+
+struct pci_driver etnaviv_pci_driver = {
+ .name = "etnaviv",
+ .id_table = etnaviv_pci_id_lists,
+ .probe = etnaviv_pci_probe,
+ .remove = etnaviv_pci_remove,
+ .driver.pm = pm_ptr(&etnaviv_gpu_pm_ops),
+};
+
+MODULE_DEVICE_TABLE(pci, etnaviv_pci_id_lists);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h
new file mode 100644
index 000000000000..6e50ec5f32b7
--- /dev/null
+++ b/drivers/gpu/drm/etnaviv/etnaviv_pci_drv.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ETNAVIV_PCI_DRV_H__
+#define __ETNAVIV_PCI_DRV_H__
+
+#include <linux/pci.h>
+
+extern struct pci_driver etnaviv_pci_driver;
+
+#endif
--
2.25.1


2023-05-30 09:13:20

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v5 5/6] drm/etnaviv: expand driver support for the PCI devices

Hi Sui,

kernel test robot noticed the following build errors:

[auto build test ERROR on drm-misc/drm-misc-next]
[also build test ERROR on drm/drm-next drm-intel/for-linux-next drm-intel/for-linux-next-fixes drm-tip/drm-tip linus/master v6.4-rc4 next-20230530]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url: https://github.com/intel-lab-lkp/linux/commits/Sui-Jingfeng/drm-etnaviv-add-a-dedicated-function-to-register-an-irq-handler/20230530-012547
base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
patch link: https://lore.kernel.org/r/20230529172452.2148819-6-suijingfeng%40loongson.cn
patch subject: [PATCH v5 5/6] drm/etnaviv: expand driver support for the PCI devices
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20230530/[email protected]/config)
compiler: m68k-linux-gcc (GCC) 12.3.0
reproduce (this is a W=1 build):
mkdir -p ~/bin
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/1d05a5fa048dd4b2a934ffbb07c330ddd9279287
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Sui-Jingfeng/drm-etnaviv-add-a-dedicated-function-to-register-an-irq-handler/20230530-012547
git checkout 1d05a5fa048dd4b2a934ffbb07c330ddd9279287
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.3.0 ~/bin/make.cross W=1 O=build_dir ARCH=m68k olddefconfig
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.3.0 ~/bin/make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/gpu/drm/etnaviv/

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/

All errors (new ones prefixed by >>):

drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c: In function 'etnaviv_gpu_pci_fini':
>> drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c:32:9: error: implicit declaration of function 'pci_clear_master'; did you mean 'pci_set_master'? [-Werror=implicit-function-declaration]
32 | pci_clear_master(pdev);
| ^~~~~~~~~~~~~~~~
| pci_set_master
cc1: some warnings being treated as errors


vim +32 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c

27
28 static void etnaviv_gpu_pci_fini(struct etnaviv_gpu *gpu, bool component)
29 {
30 struct pci_dev *pdev = to_pci_dev(gpu->dev);
31
> 32 pci_clear_master(pdev);
33
34 dev_dbg(gpu->dev, "component is %s\n",
35 component ? "enabled" : "disabled");
36 }
37

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

2023-05-30 13:17:46

by Sui Jingfeng

[permalink] [raw]
Subject: Re: [PATCH v5 5/6] drm/etnaviv: expand driver support for the PCI devices

Hi,


Previously, I don't realize some arch doesn't enable CONFIG_PCI by default.

This problem only happens on the arch which CONFIG_PCI isn't being enabled.

This problem also caused by the fact that pci_clear_master don't have a
dummy implement.

I have create a patch to fix that, see [1].


This problem is easy to fix,  with some #ifdef and #endif definition guard,

make the PCI driver support don't get compiled on the architecture which
don't have  CONFIG_PCI enable. Originally, I want it always built-in.


Should I fix this problem at driver side and respin this patch?


[1]
https://patchwork.kernel.org/project/linux-pci/patch/[email protected]/


On 2023/5/30 17:00, kernel test robot wrote:
> Hi Sui,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on drm-misc/drm-misc-next]
> [also build test ERROR on drm/drm-next drm-intel/for-linux-next drm-intel/for-linux-next-fixes drm-tip/drm-tip linus/master v6.4-rc4 next-20230530]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Sui-Jingfeng/drm-etnaviv-add-a-dedicated-function-to-register-an-irq-handler/20230530-012547
> base: git://anongit.freedesktop.org/drm/drm-misc drm-misc-next
> patch link: https://lore.kernel.org/r/20230529172452.2148819-6-suijingfeng%40loongson.cn
> patch subject: [PATCH v5 5/6] drm/etnaviv: expand driver support for the PCI devices
> config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20230530/[email protected]/config)
> compiler: m68k-linux-gcc (GCC) 12.3.0
> reproduce (this is a W=1 build):
> mkdir -p ~/bin
> wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # https://github.com/intel-lab-lkp/linux/commit/1d05a5fa048dd4b2a934ffbb07c330ddd9279287
> git remote add linux-review https://github.com/intel-lab-lkp/linux
> git fetch --no-tags linux-review Sui-Jingfeng/drm-etnaviv-add-a-dedicated-function-to-register-an-irq-handler/20230530-012547
> git checkout 1d05a5fa048dd4b2a934ffbb07c330ddd9279287
> # save the config file
> mkdir build_dir && cp config build_dir/.config
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.3.0 ~/bin/make.cross W=1 O=build_dir ARCH=m68k olddefconfig
> COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.3.0 ~/bin/make.cross W=1 O=build_dir ARCH=m68k SHELL=/bin/bash drivers/gpu/drm/etnaviv/
>
> If you fix the issue, kindly add following tag where applicable
> | Reported-by: kernel test robot <[email protected]>
> | Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
>
> All errors (new ones prefixed by >>):
>
> drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c: In function 'etnaviv_gpu_pci_fini':
>>> drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c:32:9: error: implicit declaration of function 'pci_clear_master'; did you mean 'pci_set_master'? [-Werror=implicit-function-declaration]
> 32 | pci_clear_master(pdev);
> | ^~~~~~~~~~~~~~~~
> | pci_set_master
> cc1: some warnings being treated as errors
>
>
> vim +32 drivers/gpu/drm/etnaviv/etnaviv_pci_drv.c
>
> 27
> 28 static void etnaviv_gpu_pci_fini(struct etnaviv_gpu *gpu, bool component)
> 29 {
> 30 struct pci_dev *pdev = to_pci_dev(gpu->dev);
> 31
> > 32 pci_clear_master(pdev);
> 33
> 34 dev_dbg(gpu->dev, "component is %s\n",
> 35 component ? "enabled" : "disabled");
> 36 }
> 37
>