From 8ed226fff6eb97f85939a5d9732c0bbc4a900575 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 6 Jan 2020 16:16:46 +0100 Subject: drm/etnaviv: update hardware headers from rnndb Update the state HI header from rnndb commit 7f1ce75 ("rnndb: document some GPU identity register") Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/state_hi.xml.h | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h index 41d8da2b6f4f..004d8ddacf6a 100644 --- a/drivers/gpu/drm/etnaviv/state_hi.xml.h +++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h @@ -8,17 +8,17 @@ http://0x04.net/cgit/index.cgi/rules-ng-ng git clone git://0x04.net/rules-ng-ng The rules-ng-ng source files this header was generated from are: -- state.xml ( 26087 bytes, from 2017-12-18 16:51:59) -- common.xml ( 35468 bytes, from 2018-01-22 13:48:54) -- common_3d.xml ( 14615 bytes, from 2017-12-18 16:51:59) -- state_hi.xml ( 30232 bytes, from 2018-02-15 15:48:01) -- copyright.xml ( 1597 bytes, from 2016-12-08 16:37:56) -- state_2d.xml ( 51552 bytes, from 2016-12-08 16:37:56) -- state_3d.xml ( 79992 bytes, from 2017-12-18 16:51:59) -- state_blt.xml ( 13405 bytes, from 2017-12-18 16:51:59) -- state_vg.xml ( 5975 bytes, from 2016-12-08 16:37:56) - -Copyright (C) 2012-2018 by the following authors: +- state.xml ( 26666 bytes, from 2019-12-20 21:20:35) +- common.xml ( 35468 bytes, from 2018-02-10 13:09:26) +- common_3d.xml ( 15058 bytes, from 2019-12-28 20:02:03) +- state_hi.xml ( 30552 bytes, from 2019-12-28 20:02:48) +- copyright.xml ( 1597 bytes, from 2018-02-10 13:09:26) +- state_2d.xml ( 51552 bytes, from 2018-02-10 13:09:26) +- state_3d.xml ( 83098 bytes, from 2019-12-28 20:02:03) +- state_blt.xml ( 14252 bytes, from 2019-10-20 19:59:15) +- state_vg.xml ( 5975 bytes, from 2018-02-10 13:09:26) + +Copyright (C) 2012-2019 by the following authors: - Wladimir J. van der Laan - Christian Gmeiner - Lucas Stach @@ -48,6 +48,9 @@ DEALINGS IN THE SOFTWARE. #define MMU_EXCEPTION_SLAVE_NOT_PRESENT 0x00000001 #define MMU_EXCEPTION_PAGE_NOT_PRESENT 0x00000002 #define MMU_EXCEPTION_WRITE_VIOLATION 0x00000003 +#define MMU_EXCEPTION_OUT_OF_BOUND 0x00000004 +#define MMU_EXCEPTION_READ_SECURITY_VIOLATION 0x00000005 +#define MMU_EXCEPTION_WRITE_SECURITY_VIOLATION 0x00000006 #define VIVS_HI 0x00000000 #define VIVS_HI_CLOCK_CONTROL 0x00000000 @@ -140,6 +143,8 @@ DEALINGS IN THE SOFTWARE. #define VIVS_HI_CHIP_TIME 0x0000002c +#define VIVS_HI_CHIP_CUSTOMER_ID 0x00000030 + #define VIVS_HI_CHIP_MINOR_FEATURE_0 0x00000034 #define VIVS_HI_CACHE_CONTROL 0x00000038 @@ -237,6 +242,8 @@ DEALINGS IN THE SOFTWARE. #define VIVS_HI_BLT_INTR 0x000000d4 +#define VIVS_HI_CHIP_ECO_ID 0x000000e8 + #define VIVS_HI_AUXBIT 0x000000ec #define VIVS_PM 0x00000000 -- cgit v1.2.3 From 815e45bbd4d3b00ddb2af017fbdab25110ed13a4 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 6 Jan 2020 16:16:47 +0100 Subject: drm/etnaviv: determine product, customer and eco id They will be used for extended HWDB support. Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 11 ++++++++++- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 6 +++--- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 799ec20b267d..56b80ef21bec 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -333,9 +333,13 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu->identity.revision = etnaviv_field(chipIdentity, VIVS_HI_CHIP_IDENTITY_REVISION); } else { + u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE); gpu->identity.model = gpu_read(gpu, VIVS_HI_CHIP_MODEL); gpu->identity.revision = gpu_read(gpu, VIVS_HI_CHIP_REV); + gpu->identity.product_id = gpu_read(gpu, VIVS_HI_CHIP_PRODUCT_ID); + gpu->identity.customer_id = gpu_read(gpu, VIVS_HI_CHIP_CUSTOMER_ID); + gpu->identity.eco_id = gpu_read(gpu, VIVS_HI_CHIP_ECO_ID); /* * !!!! HACK ALERT !!!! @@ -350,7 +354,6 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) /* Another special case */ if (etnaviv_is_model_rev(gpu, GC300, 0x2201)) { - u32 chipDate = gpu_read(gpu, VIVS_HI_CHIP_DATE); u32 chipTime = gpu_read(gpu, VIVS_HI_CHIP_TIME); if (chipDate == 0x20080814 && chipTime == 0x12051100) { @@ -373,6 +376,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu) gpu->identity.model = chipModel_GC3000; gpu->identity.revision &= 0xffff; } + + if (etnaviv_is_model_rev(gpu, GC1000, 0x5037) && (chipDate == 0x20120617)) + gpu->identity.eco_id = 1; + + if (etnaviv_is_model_rev(gpu, GC320, 0x5303) && (chipDate == 0x20140511)) + gpu->identity.eco_id = 1; } dev_info(gpu->dev, "model: GC%x, revision: %x\n", diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 97bb48042b4d..8ea48697d132 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -15,11 +15,11 @@ struct etnaviv_gem_submit; struct etnaviv_vram_mapping; struct etnaviv_chip_identity { - /* Chip model. */ u32 model; - - /* Revision value.*/ u32 revision; + u32 product_id; + u32 customer_id; + u32 eco_id; /* Supported feature fields. */ u32 features; -- cgit v1.2.3 From 000806631d2a0bc914ffcf2a72aeb6dd59c7fc11 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 6 Jan 2020 16:16:48 +0100 Subject: drm/etnaviv: show identity information in debugfs Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 56b80ef21bec..f7b2f3a36a86 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -860,6 +860,13 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) verify_dma(gpu, &debug); + seq_puts(m, "\tidentity\n"); + seq_printf(m, "\t model: 0x%x\n", gpu->identity.model); + seq_printf(m, "\t revision: 0x%x\n", gpu->identity.revision); + seq_printf(m, "\t product_id: 0x%x\n", gpu->identity.product_id); + seq_printf(m, "\t customer_id: 0x%x\n", gpu->identity.customer_id); + seq_printf(m, "\t eco_id: 0x%x\n", gpu->identity.eco_id); + seq_puts(m, "\tfeatures\n"); seq_printf(m, "\t major_features: 0x%08x\n", gpu->identity.features); -- cgit v1.2.3 From a51d1f37dfca484833a8e88f3302104b458a007b Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 6 Jan 2020 16:16:49 +0100 Subject: drm/etnaviv: update gc7000 chip identity entry Use ~0U as marker for 'I do not care'. I am not sure what GC7000 based devices are in the wild and I do not want to break them. In the near future we should extend the hwdb. Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_hwdb.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index 39b463db76c9..eb0f3eb87ced 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -9,6 +9,9 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { { .model = 0x7000, .revision = 0x6214, + .product_id = ~0U, + .customer_id = ~0U, + .eco_id = ~0U, .stream_count = 16, .register_max = 64, .thread_count = 1024, -- cgit v1.2.3 From 4078a1186dd35e0e5732450beeadc7175ddbb302 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 6 Jan 2020 16:16:50 +0100 Subject: drm/etnaviv: update hwdb selection logic Take product id, customer id and eco id into account. If that delivers no match try a search for model and revision. Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_hwdb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index eb0f3eb87ced..cf3bb26e2e43 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -46,7 +46,13 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu) for (i = 0; i < ARRAY_SIZE(etnaviv_chip_identities); i++) { if (etnaviv_chip_identities[i].model == ident->model && - etnaviv_chip_identities[i].revision == ident->revision) { + etnaviv_chip_identities[i].revision == ident->revision && + (etnaviv_chip_identities[i].product_id == ident->product_id || + etnaviv_chip_identities[i].product_id == ~0U) && + (etnaviv_chip_identities[i].customer_id == ident->customer_id || + etnaviv_chip_identities[i].customer_id == ~0U) && + (etnaviv_chip_identities[i].eco_id == ident->eco_id || + etnaviv_chip_identities[i].eco_id == ~0U)) { memcpy(ident, &etnaviv_chip_identities[i], sizeof(*ident)); return true; -- cgit v1.2.3 From f56f1579a094573104ffb0e81b623528d992b73c Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 6 Jan 2020 16:16:51 +0100 Subject: drm/etnaviv: add hwdb entry for gc400 found in STM32 The information was taken from STM32 glacore driver hw database. The entry is named as gc7000nano_0x4652. Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_hwdb.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c index cf3bb26e2e43..167971a09be7 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c @@ -6,6 +6,37 @@ #include "etnaviv_gpu.h" static const struct etnaviv_chip_identity etnaviv_chip_identities[] = { + { + .model = 0x400, + .revision = 0x4652, + .product_id = 0x70001, + .customer_id = 0x100, + .eco_id = 0, + .stream_count = 4, + .register_max = 64, + .thread_count = 128, + .shader_core_count = 1, + .vertex_cache_size = 8, + .vertex_output_buffer_size = 1024, + .pixel_pipes = 1, + .instruction_count = 256, + .num_constants = 320, + .buffer_size = 0, + .varyings_count = 8, + .features = 0xa0e9e004, + .minor_features0 = 0xe1299fff, + .minor_features1 = 0xbe13b219, + .minor_features2 = 0xce110010, + .minor_features3 = 0x8000001, + .minor_features4 = 0x20102, + .minor_features5 = 0x120000, + .minor_features6 = 0x0, + .minor_features7 = 0x0, + .minor_features8 = 0x0, + .minor_features9 = 0x0, + .minor_features10 = 0x0, + .minor_features11 = 0x0, + }, { .model = 0x7000, .revision = 0x6214, -- cgit v1.2.3 From ed1dd899baa32d47d9a93d98336472da50564346 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Fri, 28 Feb 2020 11:37:49 +0100 Subject: drm/etnaviv: rework perfmon query infrastructure Report the correct perfmon domains and signals depending on the supported feature flags. Reported-by: Dan Carpenter Fixes: 9e2c2e273012 ("drm/etnaviv: add infrastructure to query perf counter") Cc: stable@vger.kernel.org Signed-off-by: Christian Gmeiner Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_perfmon.c | 59 +++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 7 deletions(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c index 8adbf2861bff..e6795bafcbb9 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c @@ -32,6 +32,7 @@ struct etnaviv_pm_domain { }; struct etnaviv_pm_domain_meta { + unsigned int feature; const struct etnaviv_pm_domain *domains; u32 nr_domains; }; @@ -410,36 +411,78 @@ static const struct etnaviv_pm_domain doms_vg[] = { static const struct etnaviv_pm_domain_meta doms_meta[] = { { + .feature = chipFeatures_PIPE_3D, .nr_domains = ARRAY_SIZE(doms_3d), .domains = &doms_3d[0] }, { + .feature = chipFeatures_PIPE_2D, .nr_domains = ARRAY_SIZE(doms_2d), .domains = &doms_2d[0] }, { + .feature = chipFeatures_PIPE_VG, .nr_domains = ARRAY_SIZE(doms_vg), .domains = &doms_vg[0] } }; +static unsigned int num_pm_domains(const struct etnaviv_gpu *gpu) +{ + unsigned int num = 0, i; + + for (i = 0; i < ARRAY_SIZE(doms_meta); i++) { + const struct etnaviv_pm_domain_meta *meta = &doms_meta[i]; + + if (gpu->identity.features & meta->feature) + num += meta->nr_domains; + } + + return num; +} + +static const struct etnaviv_pm_domain *pm_domain(const struct etnaviv_gpu *gpu, + unsigned int index) +{ + const struct etnaviv_pm_domain *domain = NULL; + unsigned int offset = 0, i; + + for (i = 0; i < ARRAY_SIZE(doms_meta); i++) { + const struct etnaviv_pm_domain_meta *meta = &doms_meta[i]; + + if (!(gpu->identity.features & meta->feature)) + continue; + + if (meta->nr_domains < (index - offset)) { + offset += meta->nr_domains; + continue; + } + + domain = meta->domains + (index - offset); + } + + return domain; +} + int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, struct drm_etnaviv_pm_domain *domain) { - const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe]; + const unsigned int nr_domains = num_pm_domains(gpu); const struct etnaviv_pm_domain *dom; - if (domain->iter >= meta->nr_domains) + if (domain->iter >= nr_domains) return -EINVAL; - dom = meta->domains + domain->iter; + dom = pm_domain(gpu, domain->iter); + if (!dom) + return -EINVAL; domain->id = domain->iter; domain->nr_signals = dom->nr_signals; strncpy(domain->name, dom->name, sizeof(domain->name)); domain->iter++; - if (domain->iter == meta->nr_domains) + if (domain->iter == nr_domains) domain->iter = 0xff; return 0; @@ -448,14 +491,16 @@ int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu, struct drm_etnaviv_pm_signal *signal) { - const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe]; + const unsigned int nr_domains = num_pm_domains(gpu); const struct etnaviv_pm_domain *dom; const struct etnaviv_pm_signal *sig; - if (signal->domain >= meta->nr_domains) + if (signal->domain >= nr_domains) return -EINVAL; - dom = meta->domains + signal->domain; + dom = pm_domain(gpu, signal->domain); + if (!dom) + return -EINVAL; if (signal->iter >= dom->nr_signals) return -EINVAL; -- cgit v1.2.3 From ea4ed4a55f7363ad8db1863bd536548fb7e5c6aa Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Mon, 2 Mar 2020 20:13:32 +0100 Subject: drm/etnaviv: Fix typo in comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use 'is' instead of 'it' so it becomes a valid sentence and spell 'resetting' correctly. Signed-off-by: Guido Günther Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index f7b2f3a36a86..50112fd646a3 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -515,7 +515,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) /* read idle register. */ idle = gpu_read(gpu, VIVS_HI_IDLE_STATE); - /* try reseting again if FE it not idle */ + /* try resetting again if FE is not idle */ if ((idle & VIVS_HI_IDLE_STATE_FE) == 0) { dev_dbg(gpu->dev, "FE is not idle\n"); continue; -- cgit v1.2.3 From b9e352ed825844aa3b8c71b7b1ebb906b4800e6f Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Mon, 2 Mar 2020 20:13:33 +0100 Subject: drm/etnaviv: Update idle bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the state HI and common header from rnndb commit commit 19280a95a (rnndb: Update idle bits) Signed-off-by: Guido Günther Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/state_hi.xml.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/state_hi.xml.h b/drivers/gpu/drm/etnaviv/state_hi.xml.h index 004d8ddacf6a..deaaa99fa654 100644 --- a/drivers/gpu/drm/etnaviv/state_hi.xml.h +++ b/drivers/gpu/drm/etnaviv/state_hi.xml.h @@ -84,6 +84,13 @@ DEALINGS IN THE SOFTWARE. #define VIVS_HI_IDLE_STATE_IM 0x00000200 #define VIVS_HI_IDLE_STATE_FP 0x00000400 #define VIVS_HI_IDLE_STATE_TS 0x00000800 +#define VIVS_HI_IDLE_STATE_BL 0x00001000 +#define VIVS_HI_IDLE_STATE_ASYNCFE 0x00002000 +#define VIVS_HI_IDLE_STATE_MC 0x00004000 +#define VIVS_HI_IDLE_STATE_PPA 0x00008000 +#define VIVS_HI_IDLE_STATE_WD 0x00010000 +#define VIVS_HI_IDLE_STATE_NN 0x00020000 +#define VIVS_HI_IDLE_STATE_TP 0x00040000 #define VIVS_HI_IDLE_STATE_AXI_LP 0x80000000 #define VIVS_HI_AXI_CONFIG 0x00000008 -- cgit v1.2.3 From b170455120b6a465d2b424562cafaad4a7ac94c1 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Mon, 2 Mar 2020 20:13:34 +0100 Subject: drm/etnaviv: Consider all kwnown idle bits in debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were missing out on some bits the vendor kernel driver knows about. Signed-off-by: Guido Günther Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 50112fd646a3..52473bec330a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -946,6 +946,20 @@ int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m) seq_puts(m, "\t FP is not idle\n"); if ((idle & VIVS_HI_IDLE_STATE_TS) == 0) seq_puts(m, "\t TS is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_BL) == 0) + seq_puts(m, "\t BL is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_ASYNCFE) == 0) + seq_puts(m, "\t ASYNCFE is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_MC) == 0) + seq_puts(m, "\t MC is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_PPA) == 0) + seq_puts(m, "\t PPA is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_WD) == 0) + seq_puts(m, "\t WD is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_NN) == 0) + seq_puts(m, "\t NN is not idle\n"); + if ((idle & VIVS_HI_IDLE_STATE_TP) == 0) + seq_puts(m, "\t TP is not idle\n"); if (idle & VIVS_HI_IDLE_STATE_AXI_LP) seq_puts(m, "\t AXI low power mode\n"); -- cgit v1.2.3 From 1a910c11d35bfacb68a3e650fbc087491e92661f Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Mon, 2 Mar 2020 20:13:35 +0100 Subject: drm/etnaviv: Ignore MC when checking runtime suspend idleness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without that runtime suspend is often blocked due to etnaviv_gpu_rpm_suspend() returning -EBUSY since the FE seems to trigger the MC in its idle loop. Ignoring the MC bit makes the GPU suspend as expected. This was tested on GC7000. Signed-off-by: Guido Günther Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 52473bec330a..26fe34086a60 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -1835,8 +1835,9 @@ static int etnaviv_gpu_rpm_suspend(struct device *dev) if (atomic_read(&gpu->sched.hw_rq_count)) return -EBUSY; - /* Check whether the hardware (except FE) is idle */ - mask = gpu->idle_mask & ~VIVS_HI_IDLE_STATE_FE; + /* Check whether the hardware (except FE and MC) is idle */ + mask = gpu->idle_mask & ~(VIVS_HI_IDLE_STATE_FE | + VIVS_HI_IDLE_STATE_MC); idle = gpu_read(gpu, VIVS_HI_IDLE_STATE) & mask; if (idle != mask) return -EBUSY; -- cgit v1.2.3 From 78f2bfa3181cd7ee134274aa17177dd933c69dc1 Mon Sep 17 00:00:00 2001 From: Guido Günther Date: Mon, 2 Mar 2020 20:13:36 +0100 Subject: drm/etnaviv: Warn when GPU doesn't idle fast enough MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the GPU isn't idle after signalling pm_runtime_mark_last_busy() plus waiting for the autosuspend delay there's likely something wrong with the way we check idleness so warn about that. Signed-off-by: Guido Günther Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 26fe34086a60..169db7cc0ec6 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -1839,8 +1839,11 @@ static int etnaviv_gpu_rpm_suspend(struct device *dev) mask = gpu->idle_mask & ~(VIVS_HI_IDLE_STATE_FE | VIVS_HI_IDLE_STATE_MC); idle = gpu_read(gpu, VIVS_HI_IDLE_STATE) & mask; - if (idle != mask) + if (idle != mask) { + dev_warn_ratelimited(dev, "GPU not yet idle, mask: 0x%08x\n", + idle); return -EBUSY; + } return etnaviv_gpu_hw_suspend(gpu); } -- cgit v1.2.3 From 1442d81fef9955f362ed64b3da7a9d885cd09205 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 5 Mar 2020 04:51:37 -0600 Subject: drm/etnaviv: Replace zero-length array with flexible-array member The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99: struct foo { int stuff; struct boo array[]; }; By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on. Also, notice that, dynamic memory allocations won't be affected by this change: "Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1] This issue was found with the help of Coccinelle. [1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html [2] https://github.com/KSPP/linux/issues/21 [3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour") Signed-off-by: Gustavo A. R. Silva Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index 6b68fe16041b..98e60df882b6 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -105,7 +105,7 @@ struct etnaviv_gem_submit { unsigned int nr_pmrs; struct etnaviv_perfmon_request *pmrs; unsigned int nr_bos; - struct etnaviv_gem_submit_bo bos[0]; + struct etnaviv_gem_submit_bo bos[]; /* No new members here, the previous one is variable-length! */ }; -- cgit v1.2.3 From b72af445cd38a44553a5bcfcce5676155dcffcbb Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Thu, 27 Feb 2020 12:09:25 +0100 Subject: drm/etnaviv: request pages from DMA32 zone when needed Some Vivante GPUs are found in systems that have interconnects restricted to 32 address bits, but may have system memory mapped above the 4GB mark. As this region isn't accessible to the GPU via DMA any GPU memory allocated in the upper part needs to go through SWIOTLB bounce buffering. This kills performance if it happens too often, as well as overrunning the available bounce buffer space, as the GPU buffer may stay mapped for a long time. Avoid bounce buffering by checking the addressing restrictions. If the GPU is unable to access memory above the 4GB mark, request our SHM buffers to be located in the DMA32 zone. Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 1 + drivers/gpu/drm/etnaviv/etnaviv_drv.h | 1 + drivers/gpu/drm/etnaviv/etnaviv_gem.c | 4 ++-- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 8 ++++++++ 4 files changed, 12 insertions(+), 2 deletions(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 6b43c1c94e8f..a8685b2e1803 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -551,6 +551,7 @@ static int etnaviv_bind(struct device *dev) mutex_init(&priv->gem_lock); INIT_LIST_HEAD(&priv->gem_list); priv->num_gpus = 0; + priv->shm_gfp_mask = GFP_HIGHUSER | __GFP_RETRY_MAYFAIL | __GFP_NOWARN; priv->cmdbuf_suballoc = etnaviv_cmdbuf_suballoc_new(drm->dev); if (IS_ERR(priv->cmdbuf_suballoc)) { diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index efc656efeb0f..4d8dc9236e5f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -35,6 +35,7 @@ struct etnaviv_drm_private { int num_gpus; struct device_dma_parameters dma_parms; struct etnaviv_gpu *gpu[ETNA_MAX_PIPES]; + gfp_t shm_gfp_mask; struct etnaviv_cmdbuf_suballoc *cmdbuf_suballoc; struct etnaviv_iommu_global *mmu_global; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 6adea180d629..dc9ef302f517 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -602,6 +602,7 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags, int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, u32 size, u32 flags, u32 *handle) { + struct etnaviv_drm_private *priv = dev->dev_private; struct drm_gem_object *obj = NULL; int ret; @@ -624,8 +625,7 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, * above new_inode() why this is required _and_ expected if you're * going to pin these pages. */ - mapping_set_gfp_mask(obj->filp->f_mapping, GFP_HIGHUSER | - __GFP_RETRY_MAYFAIL | __GFP_NOWARN); + mapping_set_gfp_mask(obj->filp->f_mapping, priv->shm_gfp_mask); etnaviv_gem_obj_add(dev, obj); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index 169db7cc0ec6..a31eeff2b297 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -781,6 +781,14 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) gpu->identity.features &= ~chipFeatures_FAST_CLEAR; } + /* + * If the GPU is part of a system with DMA addressing limitations, + * request pages for our SHM backend buffers from the DMA32 zone to + * hopefully avoid performance killing SWIOTLB bounce buffering. + */ + if (dma_addressing_limited(gpu->dev)) + priv->shm_gfp_mask |= GFP_DMA32; + /* Create buffer: */ ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &gpu->buffer, PAGE_SIZE); -- cgit v1.2.3 From f232d9ec029ce3e2543b05213e2979e01e503408 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Wed, 26 Feb 2020 16:27:08 +0100 Subject: drm/etnaviv: fix TS cache flushing on GPUs with BLT engine As seen in the Vivante kernel driver, most GPUs with the BLT engine have a broken TS cache flush. The workaround is to temporarily set the BLT command to CLEAR_IMAGE, without actually executing the clear. Apparently this state change is enough to trigger the required TS cache flush. As the BLT engine is completely asychronous, we also need a few more stall states to synchronize the flush with the frontend. Root-caused-by: Jonathan Marek Signed-off-by: Lucas Stach --- drivers/gpu/drm/etnaviv/etnaviv_buffer.c | 60 +++++++++++++++++++++++++++++--- drivers/gpu/drm/etnaviv/state_blt.xml.h | 2 ++ 2 files changed, 57 insertions(+), 5 deletions(-) (limited to 'drivers/gpu/drm/etnaviv') diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index 32d9fac587f9..76d38561c910 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -12,6 +12,7 @@ #include "common.xml.h" #include "state.xml.h" +#include "state_blt.xml.h" #include "state_hi.xml.h" #include "state_3d.xml.h" #include "cmdstream.xml.h" @@ -233,6 +234,8 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) struct etnaviv_cmdbuf *buffer = &gpu->buffer; unsigned int waitlink_offset = buffer->user_size - 16; u32 link_target, flush = 0; + bool has_blt = !!(gpu->identity.minor_features5 & + chipMinorFeatures5_BLT_ENGINE); lockdep_assert_held(&gpu->lock); @@ -248,16 +251,38 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) if (flush) { unsigned int dwords = 7; + if (has_blt) + dwords += 10; + link_target = etnaviv_buffer_reserve(gpu, buffer, dwords); CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + if (has_blt) { + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1); + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0); + } CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, flush); - if (gpu->exec_state == ETNA_PIPE_3D) - CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, - VIVS_TS_FLUSH_CACHE_FLUSH); + if (gpu->exec_state == ETNA_PIPE_3D) { + if (has_blt) { + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1); + CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1); + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0); + } else { + CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, + VIVS_TS_FLUSH_CACHE_FLUSH); + } + } CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + if (has_blt) { + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1); + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0); + } CMD_END(buffer); etnaviv_buffer_replace_wait(buffer, waitlink_offset, @@ -323,6 +348,8 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, bool switch_mmu_context = gpu->mmu_context != mmu_context; unsigned int new_flush_seq = READ_ONCE(gpu->mmu_context->flush_seq); bool need_flush = switch_mmu_context || gpu->flush_seq != new_flush_seq; + bool has_blt = !!(gpu->identity.minor_features5 & + chipMinorFeatures5_BLT_ENGINE); lockdep_assert_held(&gpu->lock); @@ -433,6 +460,15 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, * 2 semaphore stall + 1 event + 1 wait + 1 link. */ return_dwords = 7; + + /* + * When the BLT engine is present we need 6 more dwords in the return + * target: 3 enable/flush/disable + 4 enable/semaphore stall/disable, + * but we don't need the normal TS flush state. + */ + if (has_blt) + return_dwords += 6; + return_target = etnaviv_buffer_reserve(gpu, buffer, return_dwords); CMD_LINK(cmdbuf, return_dwords, return_target); @@ -447,11 +483,25 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, u32 exec_state, CMD_LOAD_STATE(buffer, VIVS_GL_FLUSH_CACHE, VIVS_GL_FLUSH_CACHE_DEPTH | VIVS_GL_FLUSH_CACHE_COLOR); - CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, - VIVS_TS_FLUSH_CACHE_FLUSH); + if (has_blt) { + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1); + CMD_LOAD_STATE(buffer, VIVS_BLT_SET_COMMAND, 0x1); + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0); + } else { + CMD_LOAD_STATE(buffer, VIVS_TS_FLUSH_CACHE, + VIVS_TS_FLUSH_CACHE_FLUSH); + } } CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_PE); + + if (has_blt) { + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x1); + CMD_SEM(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); + CMD_STALL(buffer, SYNC_RECIPIENT_FE, SYNC_RECIPIENT_BLT); + CMD_LOAD_STATE(buffer, VIVS_BLT_ENABLE, 0x0); + } + CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | VIVS_GL_EVENT_FROM_PE); CMD_WAIT(buffer); diff --git a/drivers/gpu/drm/etnaviv/state_blt.xml.h b/drivers/gpu/drm/etnaviv/state_blt.xml.h index daae55995def..0e8bcf9dcc93 100644 --- a/drivers/gpu/drm/etnaviv/state_blt.xml.h +++ b/drivers/gpu/drm/etnaviv/state_blt.xml.h @@ -46,6 +46,8 @@ DEALINGS IN THE SOFTWARE. /* This is a cut-down version of the state_blt.xml.h file */ +#define VIVS_BLT_SET_COMMAND 0x000140ac + #define VIVS_BLT_ENABLE 0x000140b8 #define VIVS_BLT_ENABLE_ENABLE 0x00000001 -- cgit v1.2.3