summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/v3d
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-09-19 10:18:15 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2024-09-19 10:18:15 +0200
commitde848da12f752170c2ebe114804a985314fd5a6a (patch)
tree039a686b062cfb5c1188456f228a040e04b7cdd0 /drivers/gpu/drm/v3d
parent176000734ee2978121fde22a954eb1eabb204329 (diff)
parentae2c6d8b3b88c176dff92028941a4023f1b4cb91 (diff)
downloadlwn-de848da12f752170c2ebe114804a985314fd5a6a.tar.gz
lwn-de848da12f752170c2ebe114804a985314fd5a6a.zip
Merge tag 'drm-next-2024-09-19' of https://gitlab.freedesktop.org/drm/kernel
Pull drm updates from Dave Airlie: "This adds a couple of patches outside the drm core, all should be acked appropriately, the string and pstore ones are the main ones that come to mind. Otherwise it's the usual drivers, xe is getting enabled by default on some new hardware, we've changed the device number handling to allow more devices, and we added some optional rust code to create QR codes in the panic handler, an idea first suggested I think 10 years ago :-) string: - add mem_is_zero() core: - support more device numbers - use XArray for minor ids - add backlight constants - Split dma fence array creation into alloc and arm fbdev: - remove usage of old fbdev hooks kms: - Add might_fault() to drm_modeset_lock priming - Add dynamic per-crtc vblank configuration support dma-buf: - docs cleanup buddy: - Add start address support for trim function printk: - pass description to kmsg_dump scheduler: - Remove full_recover from drm_sched_start ttm: - Make LRU walk restartable after dropping locks - Allow direct reclaim to allocate local memory panic: - add display QR code (in rust) displayport: - mst: GUID improvements bridge: - Silence error message on -EPROBE_DEFER - analogix: Clean aup - bridge-connector: Fix double free - lt6505: Disable interrupt when powered off - tc358767: Make default DP port preemphasis configurable - lt9611uxc: require DRM_BRIDGE_ATTACH_NO_CONNECTOR - anx7625: simplify OF array handling - dw-hdmi: simplify clock handling - lontium-lt8912b: fix mode validation - nwl-dsi: fix mode vsync/hsync polarity xe: - Enable LunarLake and Battlemage support - Introducing Xe2 ccs modifiers for integrated and discrete graphics - rename xe perf to xe observation - use wb caching on DGFX for system memory - add fence timeouts - Lunar Lake graphics/media/display workarounds - Battlemage workarounds - Battlemage GSC support - GSC and HuC fw updates for LL/BM - use dma_fence_chain_free - refactor hw engine lookup and mmio access - enable priority mem read for Xe2 - Add first GuC BMG fw - fix dma-resv lock - Fix DGFX display suspend/resume - Use xe_managed for kernel BOs - Use reserved copy engine for user binds on faulting devices - Allow mixing dma-fence jobs and long-running faulting jobs - fix media TLB invalidation - fix rpm in TTM swapout path - track resources and VF state by PF i915: - Type-C programming fix for MTL+ - FBC cleanup - Calc vblank delay more accurately - On DP MST, Enable LT fallback for UHBR<->non-UHBR rates - Fix DP LTTPR detection - limit relocations to INT_MAX - fix long hangs in buddy allocator on DG2/A380 amdgpu: - Per-queue reset support - SDMA devcoredump support - DCN 4.0.1 updates - GFX12/VCN4/JPEG4 updates - Convert vbios embedded EDID to drm_edid - GFX9.3/9.4 devcoredump support - process isolation framework for GFX 9.4.3/4 - take IOMMU mappings into account for P2P DMA amdkfd: - CRIU fixes - HMM fix - Enable process isolation support for GFX 9.4.3/4 - Allow users to target recommended SDMA engines - KFD support for targetting queues on recommended SDMA engines radeon: - remove .load and drm_dev_alloc - Fix vbios embedded EDID size handling - Convert vbios embedded EDID to drm_edid - Use GEM references instead of TTM - r100 cp init cleanup - Fix potential overflows in evergreen CS offset tracking msm: - DPU: - implement DP/PHY mapping on SC8180X - Enable writeback on SM8150, SC8180X, SM6125, SM6350 - DP: - Enable widebus on all relevant chipsets - MSM8998 HDMI support - GPU: - A642L speedbin support - A615/A306/A621 support - A7xx devcoredump support ast: - astdp: Support AST2600 with VGA - Clean up HPD - Fix timeout loop for DP link training - reorganize output code by type (VGA, DP, etc) - convert to struct drm_edid - fix BMC handling for all outputs exynos: - drop stale MAINTAINERS pattern - constify struct loongson: - use GEM refcount over TTM mgag200: - Improve BMC handling - Support VBLANK intterupts - transparently support BMC outputs nouveau: - Refactor and clean up internals - Use GEM refcount over TTM's gm12u320: - convert to struct drm_edid gma500: - update i2c terms lcdif: - pixel clock fix host1x: - fix syncpoint IRQ during resume - use iommu_paging_domain_alloc() imx: - ipuv3: convert to struct drm_edid omapdrm: - improve error handling - use common helper for_each_endpoint_of_node() panel: - add support for BOE TV101WUM-LL2 plus DT bindings - novatek-nt35950: improve error handling - nv3051d: improve error handling - panel-edp: - add support for BOE NE140WUM-N6G - revert support for SDC ATNA45AF01 - visionox-vtdr6130: - improve error handling - use devm_regulator_bulk_get_const() - boe-th101mb31ig002: - Support for starry-er88577 MIPI-DSI panel plus DT - Fix porch parameter - edp: Support AOU B116XTN02.3, AUO B116XAN06.1, AOU B116XAT04.1, BOE NV140WUM-N41, BOE NV133WUM-N63, BOE NV116WHM-A4D, CMN N116BCA-EA2, CMN N116BCP-EA2, CSW MNB601LS1-4 - himax-hx8394: Support Microchip AC40T08A MIPI Display panel plus DT - ilitek-ili9806e: Support Densitron DMT028VGHMCMI-1D TFT plus DT - jd9365da: - Support Melfas lmfbx101117480 MIPI-DSI panel plus DT - Refactor for code sharing - panel-edp: fix name for HKC MB116AN01 - jd9365da: fix "exit sleep" commands - jdi-fhd-r63452: simplify error handling with DSI multi-style helpers - mantix-mlaf057we51: simplify error handling with DSI multi-style helpers - simple: - support Innolux G070ACE-LH3 plus DT bindings - support On Tat Industrial Company KD50G21-40NT-A1 plus DT bindings - st7701: - decouple DSI and DRM code - add SPI support - support Anbernic RG28XX plus DT bindings mediatek: - support alpha blending - remove cl in struct cmdq_pkt - ovl adaptor fix - add power domain binding for mediatek DPI controller renesas: - rz-du: add support for RZ/G2UL plus DT bindings rockchip: - Improve DP sink-capability reporting - dw_hdmi: Support 4k@60Hz - vop: - Support RGB display on Rockchip RK3066 - Support 4096px width sti: - convert to struct drm_edid stm: - Avoid UAF wih managed plane and CRTC helpers - Fix module owner - Fix error handling in probe - Depend on COMMON_CLK - ltdc: - Fix transparency after disabling plane - Remove unused interrupt tegra: - gr3d: improve PM domain handling - convert to struct drm_edid - Call drm_atomic_helper_shutdown() vc4: - fix PM during detect - replace DRM_ERROR() with drm_error() - v3d: simplify clock retrieval v3d: - Clean up perfmon virtio: - add DRM capset" * tag 'drm-next-2024-09-19' of https://gitlab.freedesktop.org/drm/kernel: (1326 commits) drm/xe: Fix missing conversion to xe_display_pm_runtime_resume drm/xe/xe2hpg: Add Wa_15016589081 drm/xe: Don't keep stale pointer to bo->ggtt_node drm/xe: fix missing 'xe_vm_put' drm/xe: fix build warning with CONFIG_PM=n drm/xe: Suppress missing outer rpm protection warning drm/xe: prevent potential UAF in pf_provision_vf_ggtt() drm/amd/display: Add all planes on CRTC to state for overlay cursor drm/i915/bios: fix printk format width drm/i915/display: Fix BMG CCS modifiers drm/amdgpu: get rid of bogus includes of fdtable.h drm/amdkfd: CRIU fixes drm/amdgpu: fix a race in kfd_mem_export_dmabuf() drm: new helper: drm_gem_prime_handle_to_dmabuf() drm/amdgpu/atomfirmware: Silence UBSAN warning drm/amdgpu: Fix kdoc entry in 'amdgpu_vm_cpu_prepare' drm/amd/amdgpu: apply command submission parser for JPEG v1 drm/amd/amdgpu: apply command submission parser for JPEG v2+ drm/amd/pm: fix the pp_dpm_pcie issue on smu v14.0.2/3 drm/amd/pm: update the features set on smu v14.0.2/3 ...
Diffstat (limited to 'drivers/gpu/drm/v3d')
-rw-r--r--drivers/gpu/drm/v3d/v3d_bo.c12
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c11
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.h12
-rw-r--r--drivers/gpu/drm/v3d/v3d_perfmon.c40
-rw-r--r--drivers/gpu/drm/v3d/v3d_performance_counters.h16
-rw-r--r--drivers/gpu/drm/v3d/v3d_sched.c79
-rw-r--r--drivers/gpu/drm/v3d/v3d_submit.c255
7 files changed, 223 insertions, 202 deletions
diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c
index 9eafe53a8f41..ebe52bef4ffb 100644
--- a/drivers/gpu/drm/v3d/v3d_bo.c
+++ b/drivers/gpu/drm/v3d/v3d_bo.c
@@ -26,6 +26,17 @@
#include "v3d_drv.h"
#include "uapi/drm/v3d_drm.h"
+static enum drm_gem_object_status v3d_gem_status(struct drm_gem_object *obj)
+{
+ struct v3d_bo *bo = to_v3d_bo(obj);
+ enum drm_gem_object_status res = 0;
+
+ if (bo->base.pages)
+ res |= DRM_GEM_OBJECT_RESIDENT;
+
+ return res;
+}
+
/* Called DRM core on the last userspace/kernel unreference of the
* BO.
*/
@@ -63,6 +74,7 @@ static const struct drm_gem_object_funcs v3d_gem_funcs = {
.vmap = drm_gem_shmem_object_vmap,
.vunmap = drm_gem_shmem_object_vunmap,
.mmap = drm_gem_shmem_object_mmap,
+ .status = v3d_gem_status,
.vm_ops = &drm_gem_shmem_vm_ops,
};
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index 5982941d933b..d7ff1f5fa481 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -95,7 +95,7 @@ static int v3d_get_param_ioctl(struct drm_device *dev, void *data,
args->value = 1;
return 0;
case DRM_V3D_PARAM_MAX_PERF_COUNTERS:
- args->value = v3d->max_counters;
+ args->value = v3d->perfmon_info.max_counters;
return 0;
default:
DRM_DEBUG("Unknown parameter %d\n", args->param);
@@ -184,6 +184,8 @@ static void v3d_show_fdinfo(struct drm_printer *p, struct drm_file *file)
drm_printf(p, "v3d-jobs-%s: \t%llu jobs\n",
v3d_queue_to_string(queue), jobs_completed);
}
+
+ drm_show_memory_stats(p, file);
}
static const struct file_operations v3d_drm_fops = {
@@ -301,12 +303,7 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
ident3 = V3D_READ(V3D_HUB_IDENT3);
v3d->rev = V3D_GET_FIELD(ident3, V3D_HUB_IDENT3_IPREV);
- if (v3d->ver >= 71)
- v3d->max_counters = V3D_V71_NUM_PERFCOUNTERS;
- else if (v3d->ver >= 42)
- v3d->max_counters = V3D_V42_NUM_PERFCOUNTERS;
- else
- v3d->max_counters = 0;
+ v3d_perfmon_init(v3d);
v3d->reset = devm_reset_control_get_exclusive(dev, NULL);
if (IS_ERR(v3d->reset)) {
diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h
index a0febdb6f214..cf4b23369dc4 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.h
+++ b/drivers/gpu/drm/v3d/v3d_drv.h
@@ -106,10 +106,7 @@ struct v3d_dev {
bool single_irq_line;
- /* Different revisions of V3D have different total number of performance
- * counters
- */
- unsigned int max_counters;
+ struct v3d_perfmon_info perfmon_info;
void __iomem *hub_regs;
void __iomem *core_regs[3];
@@ -353,13 +350,9 @@ struct v3d_timestamp_query {
struct drm_syncobj *syncobj;
};
-/* Number of perfmons required to handle all supported performance counters */
-#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \
- DRM_V3D_MAX_PERF_COUNTERS)
-
struct v3d_performance_query {
/* Performance monitor IDs for this query */
- u32 kperfmon_ids[V3D_MAX_PERFMONS];
+ u32 *kperfmon_ids;
/* Syncobj that indicates the query availability */
struct drm_syncobj *syncobj;
@@ -574,6 +567,7 @@ int v3d_sched_init(struct v3d_dev *v3d);
void v3d_sched_fini(struct v3d_dev *v3d);
/* v3d_perfmon.c */
+void v3d_perfmon_init(struct v3d_dev *v3d);
void v3d_perfmon_get(struct v3d_perfmon *perfmon);
void v3d_perfmon_put(struct v3d_perfmon *perfmon);
void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon);
diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c
index b7d0b02e1a95..cd7f1eedf17f 100644
--- a/drivers/gpu/drm/v3d/v3d_perfmon.c
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -195,6 +195,23 @@ static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = {
{"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"},
};
+void v3d_perfmon_init(struct v3d_dev *v3d)
+{
+ const struct v3d_perf_counter_desc *counters = NULL;
+ unsigned int max = 0;
+
+ if (v3d->ver >= 71) {
+ counters = v3d_v71_performance_counters;
+ max = ARRAY_SIZE(v3d_v71_performance_counters);
+ } else if (v3d->ver >= 42) {
+ counters = v3d_v42_performance_counters;
+ max = ARRAY_SIZE(v3d_v42_performance_counters);
+ }
+
+ v3d->perfmon_info.max_counters = max;
+ v3d->perfmon_info.counters = counters;
+}
+
void v3d_perfmon_get(struct v3d_perfmon *perfmon)
{
if (perfmon)
@@ -321,7 +338,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
/* Make sure all counters are valid. */
for (i = 0; i < req->ncounters; i++) {
- if (req->counters[i] >= v3d->max_counters)
+ if (req->counters[i] >= v3d->perfmon_info.max_counters)
return -EINVAL;
}
@@ -416,25 +433,14 @@ int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
+ if (!v3d->perfmon_info.max_counters)
+ return -EOPNOTSUPP;
+
/* Make sure that the counter ID is valid */
- if (req->counter >= v3d->max_counters)
+ if (req->counter >= v3d->perfmon_info.max_counters)
return -EINVAL;
- BUILD_BUG_ON(ARRAY_SIZE(v3d_v42_performance_counters) !=
- V3D_V42_NUM_PERFCOUNTERS);
- BUILD_BUG_ON(ARRAY_SIZE(v3d_v71_performance_counters) !=
- V3D_V71_NUM_PERFCOUNTERS);
- BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V42_NUM_PERFCOUNTERS);
- BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V71_NUM_PERFCOUNTERS);
- BUILD_BUG_ON((V3D_MAX_COUNTERS != V3D_V42_NUM_PERFCOUNTERS) &&
- (V3D_MAX_COUNTERS != V3D_V71_NUM_PERFCOUNTERS));
-
- if (v3d->ver >= 71)
- counter = &v3d_v71_performance_counters[req->counter];
- else if (v3d->ver >= 42)
- counter = &v3d_v42_performance_counters[req->counter];
- else
- return -EOPNOTSUPP;
+ counter = &v3d->perfmon_info.counters[req->counter];
strscpy(req->name, counter->name, sizeof(req->name));
strscpy(req->category, counter->category, sizeof(req->category));
diff --git a/drivers/gpu/drm/v3d/v3d_performance_counters.h b/drivers/gpu/drm/v3d/v3d_performance_counters.h
index 131b2909522a..d919a2fc9449 100644
--- a/drivers/gpu/drm/v3d/v3d_performance_counters.h
+++ b/drivers/gpu/drm/v3d/v3d_performance_counters.h
@@ -19,11 +19,17 @@ struct v3d_perf_counter_desc {
char description[256];
};
+struct v3d_perfmon_info {
+ /*
+ * Different revisions of V3D have different total number of
+ * performance counters.
+ */
+ unsigned int max_counters;
-#define V3D_V42_NUM_PERFCOUNTERS (87)
-#define V3D_V71_NUM_PERFCOUNTERS (93)
-
-/* Maximum number of performance counters supported by any version of V3D */
-#define V3D_MAX_COUNTERS (93)
+ /*
+ * Array of counters valid for the platform.
+ */
+ const struct v3d_perf_counter_desc *counters;
+};
#endif
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index ad1e6236ff6f..08d2a2739582 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -94,8 +94,10 @@ v3d_performance_query_info_free(struct v3d_performance_query_info *query_info,
if (query_info->queries) {
unsigned int i;
- for (i = 0; i < count; i++)
+ for (i = 0; i < count; i++) {
drm_syncobj_put(query_info->queries[i].syncobj);
+ kvfree(query_info->queries[i].kperfmon_ids);
+ }
kvfree(query_info->queries);
}
@@ -365,8 +367,7 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
struct v3d_bo *bo = to_v3d_bo(job->base.bo[0]);
struct v3d_bo *indirect = to_v3d_bo(indirect_csd->indirect);
struct drm_v3d_submit_csd *args = &indirect_csd->job->args;
- struct v3d_dev *v3d = job->base.v3d;
- u32 num_batches, *wg_counts;
+ u32 *wg_counts;
v3d_get_bo_vaddr(bo);
v3d_get_bo_vaddr(indirect);
@@ -379,17 +380,8 @@ v3d_rewrite_csd_job_wg_counts_from_indirect(struct v3d_cpu_job *job)
args->cfg[0] = wg_counts[0] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[1] = wg_counts[1] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
args->cfg[2] = wg_counts[2] << V3D_CSD_CFG012_WG_COUNT_SHIFT;
-
- num_batches = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
- (wg_counts[0] * wg_counts[1] * wg_counts[2]);
-
- /* V3D 7.1.6 and later don't subtract 1 from the number of batches */
- if (v3d->ver < 71 || (v3d->ver == 71 && v3d->rev < 6))
- args->cfg[4] = num_batches - 1;
- else
- args->cfg[4] = num_batches;
-
- WARN_ON(args->cfg[4] == ~0);
+ args->cfg[4] = DIV_ROUND_UP(indirect_csd->wg_size, 16) *
+ (wg_counts[0] * wg_counts[1] * wg_counts[2]) - 1;
for (int i = 0; i < 3; i++) {
/* 0xffffffff indicates that the uniform rewrite is not needed */
@@ -443,18 +435,23 @@ v3d_reset_timestamp_queries(struct v3d_cpu_job *job)
v3d_put_bo_vaddr(bo);
}
-static void
-write_to_buffer(void *dst, u32 idx, bool do_64bit, u64 value)
+static void write_to_buffer_32(u32 *dst, unsigned int idx, u32 value)
{
- if (do_64bit) {
- u64 *dst64 = (u64 *)dst;
+ dst[idx] = value;
+}
- dst64[idx] = value;
- } else {
- u32 *dst32 = (u32 *)dst;
+static void write_to_buffer_64(u64 *dst, unsigned int idx, u64 value)
+{
+ dst[idx] = value;
+}
- dst32[idx] = (u32)value;
- }
+static void
+write_to_buffer(void *dst, unsigned int idx, bool do_64bit, u64 value)
+{
+ if (do_64bit)
+ write_to_buffer_64(dst, idx, value);
+ else
+ write_to_buffer_32(dst, idx, value);
}
static void
@@ -527,18 +524,24 @@ v3d_reset_performance_queries(struct v3d_cpu_job *job)
}
static void
-v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 query)
+v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data,
+ unsigned int query)
{
- struct v3d_performance_query_info *performance_query = &job->performance_query;
- struct v3d_copy_query_results_info *copy = &job->copy;
+ struct v3d_performance_query_info *performance_query =
+ &job->performance_query;
struct v3d_file_priv *v3d_priv = job->base.file->driver_priv;
+ struct v3d_performance_query *perf_query =
+ &performance_query->queries[query];
struct v3d_dev *v3d = job->base.v3d;
- struct v3d_perfmon *perfmon;
- u64 counter_values[V3D_MAX_COUNTERS];
+ unsigned int i, j, offset;
+
+ for (i = 0, offset = 0;
+ i < performance_query->nperfmons;
+ i++, offset += DRM_V3D_MAX_PERF_COUNTERS) {
+ struct v3d_perfmon *perfmon;
- for (int i = 0; i < performance_query->nperfmons; i++) {
perfmon = v3d_perfmon_find(v3d_priv,
- performance_query->queries[query].kperfmon_ids[i]);
+ perf_query->kperfmon_ids[i]);
if (!perfmon) {
DRM_DEBUG("Failed to find perfmon.");
continue;
@@ -546,14 +549,18 @@ v3d_write_performance_query_result(struct v3d_cpu_job *job, void *data, u32 quer
v3d_perfmon_stop(v3d, perfmon, true);
- memcpy(&counter_values[i * DRM_V3D_MAX_PERF_COUNTERS], perfmon->values,
- perfmon->ncounters * sizeof(u64));
+ if (job->copy.do_64bit) {
+ for (j = 0; j < perfmon->ncounters; j++)
+ write_to_buffer_64(data, offset + j,
+ perfmon->values[j]);
+ } else {
+ for (j = 0; j < perfmon->ncounters; j++)
+ write_to_buffer_32(data, offset + j,
+ perfmon->values[j]);
+ }
v3d_perfmon_put(perfmon);
}
-
- for (int i = 0; i < performance_query->ncounters; i++)
- write_to_buffer(data, i, copy->do_64bit, counter_values[i]);
}
static void
@@ -660,7 +667,7 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
/* Unblock schedulers and restart their jobs. */
for (q = 0; q < V3D_MAX_QUEUES; q++) {
- drm_sched_start(&v3d->queue[q].sched, true);
+ drm_sched_start(&v3d->queue[q].sched);
}
mutex_unlock(&v3d->reset_lock);
diff --git a/drivers/gpu/drm/v3d/v3d_submit.c b/drivers/gpu/drm/v3d/v3d_submit.c
index 4cdfabbf4964..d607aa9c4ec2 100644
--- a/drivers/gpu/drm/v3d/v3d_submit.c
+++ b/drivers/gpu/drm/v3d/v3d_submit.c
@@ -452,6 +452,7 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv,
{
u32 __user *offsets, *syncs;
struct drm_v3d_timestamp_query timestamp;
+ struct v3d_timestamp_query_info *query_info = &job->timestamp_query;
unsigned int i;
int err;
@@ -473,10 +474,10 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv,
job->job_type = V3D_CPU_JOB_TYPE_TIMESTAMP_QUERY;
- job->timestamp_query.queries = kvmalloc_array(timestamp.count,
- sizeof(struct v3d_timestamp_query),
- GFP_KERNEL);
- if (!job->timestamp_query.queries)
+ query_info->queries = kvmalloc_array(timestamp.count,
+ sizeof(struct v3d_timestamp_query),
+ GFP_KERNEL);
+ if (!query_info->queries)
return -ENOMEM;
offsets = u64_to_user_ptr(timestamp.offsets);
@@ -485,25 +486,26 @@ v3d_get_cpu_timestamp_query_params(struct drm_file *file_priv,
for (i = 0; i < timestamp.count; i++) {
u32 offset, sync;
- if (copy_from_user(&offset, offsets++, sizeof(offset))) {
+ if (get_user(offset, offsets++)) {
err = -EFAULT;
goto error;
}
- job->timestamp_query.queries[i].offset = offset;
+ query_info->queries[i].offset = offset;
- if (copy_from_user(&sync, syncs++, sizeof(sync))) {
+ if (get_user(sync, syncs++)) {
err = -EFAULT;
goto error;
}
- job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync);
- if (!job->timestamp_query.queries[i].syncobj) {
+ query_info->queries[i].syncobj = drm_syncobj_find(file_priv,
+ sync);
+ if (!query_info->queries[i].syncobj) {
err = -ENOENT;
goto error;
}
}
- job->timestamp_query.count = timestamp.count;
+ query_info->count = timestamp.count;
return 0;
@@ -519,6 +521,7 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv,
{
u32 __user *syncs;
struct drm_v3d_reset_timestamp_query reset;
+ struct v3d_timestamp_query_info *query_info = &job->timestamp_query;
unsigned int i;
int err;
@@ -537,10 +540,10 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv,
job->job_type = V3D_CPU_JOB_TYPE_RESET_TIMESTAMP_QUERY;
- job->timestamp_query.queries = kvmalloc_array(reset.count,
- sizeof(struct v3d_timestamp_query),
- GFP_KERNEL);
- if (!job->timestamp_query.queries)
+ query_info->queries = kvmalloc_array(reset.count,
+ sizeof(struct v3d_timestamp_query),
+ GFP_KERNEL);
+ if (!query_info->queries)
return -ENOMEM;
syncs = u64_to_user_ptr(reset.syncs);
@@ -548,20 +551,21 @@ v3d_get_cpu_reset_timestamp_params(struct drm_file *file_priv,
for (i = 0; i < reset.count; i++) {
u32 sync;
- job->timestamp_query.queries[i].offset = reset.offset + 8 * i;
+ query_info->queries[i].offset = reset.offset + 8 * i;
- if (copy_from_user(&sync, syncs++, sizeof(sync))) {
+ if (get_user(sync, syncs++)) {
err = -EFAULT;
goto error;
}
- job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync);
- if (!job->timestamp_query.queries[i].syncobj) {
+ query_info->queries[i].syncobj = drm_syncobj_find(file_priv,
+ sync);
+ if (!query_info->queries[i].syncobj) {
err = -ENOENT;
goto error;
}
}
- job->timestamp_query.count = reset.count;
+ query_info->count = reset.count;
return 0;
@@ -578,6 +582,7 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv,
{
u32 __user *offsets, *syncs;
struct drm_v3d_copy_timestamp_query copy;
+ struct v3d_timestamp_query_info *query_info = &job->timestamp_query;
unsigned int i;
int err;
@@ -599,10 +604,10 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv,
job->job_type = V3D_CPU_JOB_TYPE_COPY_TIMESTAMP_QUERY;
- job->timestamp_query.queries = kvmalloc_array(copy.count,
- sizeof(struct v3d_timestamp_query),
- GFP_KERNEL);
- if (!job->timestamp_query.queries)
+ query_info->queries = kvmalloc_array(copy.count,
+ sizeof(struct v3d_timestamp_query),
+ GFP_KERNEL);
+ if (!query_info->queries)
return -ENOMEM;
offsets = u64_to_user_ptr(copy.offsets);
@@ -611,25 +616,26 @@ v3d_get_cpu_copy_query_results_params(struct drm_file *file_priv,
for (i = 0; i < copy.count; i++) {
u32 offset, sync;
- if (copy_from_user(&offset, offsets++, sizeof(offset))) {
+ if (get_user(offset, offsets++)) {
err = -EFAULT;
goto error;
}
- job->timestamp_query.queries[i].offset = offset;
+ query_info->queries[i].offset = offset;
- if (copy_from_user(&sync, syncs++, sizeof(sync))) {
+ if (get_user(sync, syncs++)) {
err = -EFAULT;
goto error;
}
- job->timestamp_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync);
- if (!job->timestamp_query.queries[i].syncobj) {
+ query_info->queries[i].syncobj = drm_syncobj_find(file_priv,
+ sync);
+ if (!query_info->queries[i].syncobj) {
err = -ENOENT;
goto error;
}
}
- job->timestamp_query.count = copy.count;
+ query_info->count = copy.count;
job->copy.do_64bit = copy.do_64bit;
job->copy.do_partial = copy.do_partial;
@@ -645,95 +651,121 @@ error:
}
static int
-v3d_get_cpu_reset_performance_params(struct drm_file *file_priv,
- struct drm_v3d_extension __user *ext,
- struct v3d_cpu_job *job)
+v3d_copy_query_info(struct v3d_performance_query_info *query_info,
+ unsigned int count,
+ unsigned int nperfmons,
+ u32 __user *syncs,
+ u64 __user *kperfmon_ids,
+ struct drm_file *file_priv)
{
- u32 __user *syncs;
- u64 __user *kperfmon_ids;
- struct drm_v3d_reset_performance_query reset;
unsigned int i, j;
int err;
- if (!job) {
- DRM_DEBUG("CPU job extension was attached to a GPU job.\n");
- return -EINVAL;
- }
-
- if (job->job_type) {
- DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n");
- return -EINVAL;
- }
-
- if (copy_from_user(&reset, ext, sizeof(reset)))
- return -EFAULT;
-
- if (reset.nperfmons > V3D_MAX_PERFMONS)
- return -EINVAL;
-
- job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY;
-
- job->performance_query.queries = kvmalloc_array(reset.count,
- sizeof(struct v3d_performance_query),
- GFP_KERNEL);
- if (!job->performance_query.queries)
- return -ENOMEM;
-
- syncs = u64_to_user_ptr(reset.syncs);
- kperfmon_ids = u64_to_user_ptr(reset.kperfmon_ids);
-
- for (i = 0; i < reset.count; i++) {
- u32 sync;
- u64 ids;
+ for (i = 0; i < count; i++) {
+ struct v3d_performance_query *query = &query_info->queries[i];
u32 __user *ids_pointer;
- u32 id;
+ u32 sync, id;
+ u64 ids;
- if (copy_from_user(&sync, syncs++, sizeof(sync))) {
+ if (get_user(sync, syncs++)) {
err = -EFAULT;
goto error;
}
- if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) {
+ if (get_user(ids, kperfmon_ids++)) {
err = -EFAULT;
goto error;
}
+ query->kperfmon_ids =
+ kvmalloc_array(nperfmons,
+ sizeof(struct v3d_performance_query *),
+ GFP_KERNEL);
+ if (!query->kperfmon_ids) {
+ err = -ENOMEM;
+ goto error;
+ }
+
ids_pointer = u64_to_user_ptr(ids);
- for (j = 0; j < reset.nperfmons; j++) {
- if (copy_from_user(&id, ids_pointer++, sizeof(id))) {
+ for (j = 0; j < nperfmons; j++) {
+ if (get_user(id, ids_pointer++)) {
+ kvfree(query->kperfmon_ids);
err = -EFAULT;
goto error;
}
- job->performance_query.queries[i].kperfmon_ids[j] = id;
+ query->kperfmon_ids[j] = id;
}
- job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync);
- if (!job->performance_query.queries[i].syncobj) {
+ query->syncobj = drm_syncobj_find(file_priv, sync);
+ if (!query->syncobj) {
+ kvfree(query->kperfmon_ids);
err = -ENOENT;
goto error;
}
}
- job->performance_query.count = reset.count;
- job->performance_query.nperfmons = reset.nperfmons;
return 0;
error:
- v3d_performance_query_info_free(&job->performance_query, i);
+ v3d_performance_query_info_free(query_info, i);
return err;
}
static int
+v3d_get_cpu_reset_performance_params(struct drm_file *file_priv,
+ struct drm_v3d_extension __user *ext,
+ struct v3d_cpu_job *job)
+{
+ struct v3d_performance_query_info *query_info = &job->performance_query;
+ struct drm_v3d_reset_performance_query reset;
+ int err;
+
+ if (!job) {
+ DRM_DEBUG("CPU job extension was attached to a GPU job.\n");
+ return -EINVAL;
+ }
+
+ if (job->job_type) {
+ DRM_DEBUG("Two CPU job extensions were added to the same CPU job.\n");
+ return -EINVAL;
+ }
+
+ if (copy_from_user(&reset, ext, sizeof(reset)))
+ return -EFAULT;
+
+ job->job_type = V3D_CPU_JOB_TYPE_RESET_PERFORMANCE_QUERY;
+
+ query_info->queries =
+ kvmalloc_array(reset.count,
+ sizeof(struct v3d_performance_query),
+ GFP_KERNEL);
+ if (!query_info->queries)
+ return -ENOMEM;
+
+ err = v3d_copy_query_info(query_info,
+ reset.count,
+ reset.nperfmons,
+ u64_to_user_ptr(reset.syncs),
+ u64_to_user_ptr(reset.kperfmon_ids),
+ file_priv);
+ if (err)
+ return err;
+
+ query_info->count = reset.count;
+ query_info->nperfmons = reset.nperfmons;
+
+ return 0;
+}
+
+static int
v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv,
struct drm_v3d_extension __user *ext,
struct v3d_cpu_job *job)
{
- u32 __user *syncs;
- u64 __user *kperfmon_ids;
+ struct v3d_performance_query_info *query_info = &job->performance_query;
struct drm_v3d_copy_performance_query copy;
- unsigned int i, j;
int err;
if (!job) {
@@ -752,56 +784,27 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv,
if (copy.pad)
return -EINVAL;
- if (copy.nperfmons > V3D_MAX_PERFMONS)
- return -EINVAL;
-
job->job_type = V3D_CPU_JOB_TYPE_COPY_PERFORMANCE_QUERY;
- job->performance_query.queries = kvmalloc_array(copy.count,
- sizeof(struct v3d_performance_query),
- GFP_KERNEL);
- if (!job->performance_query.queries)
+ query_info->queries =
+ kvmalloc_array(copy.count,
+ sizeof(struct v3d_performance_query),
+ GFP_KERNEL);
+ if (!query_info->queries)
return -ENOMEM;
- syncs = u64_to_user_ptr(copy.syncs);
- kperfmon_ids = u64_to_user_ptr(copy.kperfmon_ids);
+ err = v3d_copy_query_info(query_info,
+ copy.count,
+ copy.nperfmons,
+ u64_to_user_ptr(copy.syncs),
+ u64_to_user_ptr(copy.kperfmon_ids),
+ file_priv);
+ if (err)
+ return err;
- for (i = 0; i < copy.count; i++) {
- u32 sync;
- u64 ids;
- u32 __user *ids_pointer;
- u32 id;
-
- if (copy_from_user(&sync, syncs++, sizeof(sync))) {
- err = -EFAULT;
- goto error;
- }
-
- if (copy_from_user(&ids, kperfmon_ids++, sizeof(ids))) {
- err = -EFAULT;
- goto error;
- }
-
- ids_pointer = u64_to_user_ptr(ids);
-
- for (j = 0; j < copy.nperfmons; j++) {
- if (copy_from_user(&id, ids_pointer++, sizeof(id))) {
- err = -EFAULT;
- goto error;
- }
-
- job->performance_query.queries[i].kperfmon_ids[j] = id;
- }
-
- job->performance_query.queries[i].syncobj = drm_syncobj_find(file_priv, sync);
- if (!job->performance_query.queries[i].syncobj) {
- err = -ENOENT;
- goto error;
- }
- }
- job->performance_query.count = copy.count;
- job->performance_query.nperfmons = copy.nperfmons;
- job->performance_query.ncounters = copy.ncounters;
+ query_info->count = copy.count;
+ query_info->nperfmons = copy.nperfmons;
+ query_info->ncounters = copy.ncounters;
job->copy.do_64bit = copy.do_64bit;
job->copy.do_partial = copy.do_partial;
@@ -810,10 +813,6 @@ v3d_get_cpu_copy_performance_query_params(struct drm_file *file_priv,
job->copy.stride = copy.stride;
return 0;
-
-error:
- v3d_performance_query_info_free(&job->performance_query, i);
- return err;
}
/* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data