Merge tag 'drm-msm-fixes-2026-05-17' of https://gitlab.freedesktop.org/drm/msm into drm-fixes

Fixes for v7.1:

Core:
- Fixed bindings for SM8650, SM8750 and Eliza
- Don't use UTS_RELEASE directly
- Fix typo in clock-names property

DPU:
- Fixed CWB description on Kaanapali
- Fixed scanline strides for YUV UBWC formats
- Stopped DSI register dumping to access past the end of region

DSI:
- Fix dumping unaligned regions

GPU:
- Fix GMEM_BASE for a6xx gen3
- Fix userspace reachable crash on a2xx-a4xx
- Fix sysprof_active for counter collection with IFPC enabled GPUs
- Fix shrinker lockdep

Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Rob Clark <rob.clark@oss.qualcomm.com>
Link: https://patch.msgid.link/CACSVV02cTK7h=d0uqanRE-cj35THDqFjqsTB_2zQV1Mcw77aNw@mail.gmail.com
This commit is contained in:
Dave Airlie 2026-05-21 10:12:21 +10:00
commit 5b4a47dc54
17 changed files with 113 additions and 69 deletions

View File

@ -219,6 +219,7 @@ allOf:
- required:
- "#sound-dai-cells"
else:
$ref: /schemas/sound/dai-common.yaml#
properties:
aux-bus: false
required:
@ -243,7 +244,7 @@ allOf:
clocks:
minItems: 5
maxItems: 5
clocks-names:
clock-names:
minItems: 5
maxItems: 5
@ -264,7 +265,7 @@ allOf:
clocks:
minItems: 5
maxItems: 6
clocks-names:
clock-names:
minItems: 5
maxItems: 6
@ -277,7 +278,6 @@ allOf:
- qcom,sc8180x-dp
- qcom,sdm845-dp
- qcom,sm8350-dp
- qcom,sm8650-dp
then:
properties:
reg:
@ -286,6 +286,24 @@ allOf:
clocks:
minItems: 6
maxItems: 6
clock-names:
minItems: 6
maxItems: 6
- if:
properties:
compatible:
contains:
enum:
- qcom,sm8650-dp
then:
properties:
reg:
minItems: 5
maxItems: 9
clocks:
minItems: 6
maxItems: 6
clocks-names:
minItems: 6
maxItems: 6
@ -306,7 +324,7 @@ allOf:
clocks:
minItems: 6
maxItems: 8
clocks-names:
clock-names:
minItems: 6
maxItems: 8
@ -326,7 +344,7 @@ allOf:
clocks:
minItems: 5
maxItems: 6
clocks-names:
clock-names:
minItems: 5
maxItems: 6

View File

@ -119,7 +119,7 @@ examples:
mdss_mdp: display-controller@ae01000 {
compatible = "qcom,eliza-dpu";
reg = <0x0ae01000 0x93000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp",
"vbif";
@ -304,7 +304,7 @@ examples:
mdss_dsi0_phy: phy@ae95000 {
compatible = "qcom,eliza-dsi-phy-4nm", "qcom,sm8650-dsi-phy-4nm";
reg = <0x0ae95000 0x200>,
<0x0ae95200 0x280>,
<0x0ae95200 0x300>,
<0x0ae95500 0x400>;
reg-names = "dsi_phy",
"dsi_phy_lane",
@ -388,7 +388,7 @@ examples:
mdss_dsi1_phy: phy@ae97000 {
compatible = "qcom,eliza-dsi-phy-4nm", "qcom,sm8650-dsi-phy-4nm";
reg = <0x0ae97000 0x200>,
<0x0ae97200 0x280>,
<0x0ae97200 0x300>,
<0x0ae97500 0x400>;
reg-names = "dsi_phy",
"dsi_phy_lane",
@ -407,11 +407,15 @@ examples:
displayport-controller@af54000 {
compatible = "qcom,eliza-dp", "qcom,sm8650-dp";
reg = <0xaf54000 0x104>,
<0xaf54200 0xc0>,
<0xaf55000 0x770>,
<0xaf56000 0x9c>,
<0xaf57000 0x9c>;
reg = <0x0af54000 0x200>,
<0x0af54200 0x200>,
<0x0af55000 0xc00>,
<0x0af56000 0x400>,
<0x0af57000 0x400>,
<0x0af58000 0x400>,
<0x0af59000 0x400>,
<0x0af5a000 0x600>,
<0x0af5b000 0x600>;
interrupts-extended = <&mdss 12>;

View File

@ -70,7 +70,7 @@ examples:
display-controller@ae01000 {
compatible = "qcom,sm8650-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp", "vbif";
clocks = <&gcc_axi_clk>,

View File

@ -112,7 +112,7 @@ examples:
display-controller@ae01000 {
compatible = "qcom,sm8650-dpu";
reg = <0x0ae01000 0x8f000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp", "vbif";
clocks = <&gcc_axi_clk>,

View File

@ -117,7 +117,7 @@ examples:
display-controller@ae01000 {
compatible = "qcom,sm8750-dpu";
reg = <0x0ae01000 0x93000>,
<0x0aeb0000 0x2008>;
<0x0aeb0000 0x3000>;
reg-names = "mdp",
"vbif";
@ -389,11 +389,15 @@ examples:
displayport-controller@af54000 {
compatible = "qcom,sm8750-dp", "qcom,sm8650-dp";
reg = <0xaf54000 0x104>,
<0xaf54200 0xc0>,
<0xaf55000 0x770>,
<0xaf56000 0x9c>,
<0xaf57000 0x9c>;
reg = <0x0af54000 0x200>,
<0x0af54200 0x200>,
<0x0af55000 0xc00>,
<0x0af56000 0x400>,
<0x0af57000 0x400>,
<0x0af58000 0x400>,
<0x0af59000 0x400>,
<0x0af5a000 0x600>,
<0x0af5b000 0x600>;
interrupts-extended = <&mdss 12>;

View File

@ -2621,7 +2621,6 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
struct platform_device *pdev = priv->gpu_pdev;
struct adreno_platform_config *config = pdev->dev.platform_data;
const struct adreno_info *info = config->info;
struct device_node *node;
struct a6xx_gpu *a6xx_gpu;
struct adreno_gpu *adreno_gpu;
struct msm_gpu *gpu;
@ -2643,7 +2642,8 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
adreno_gpu->registers = NULL;
/* Check if there is a GMU phandle and set it up */
node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0);
struct device_node *node __free(device_node) =
of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0);
/* FIXME: How do we gracefully handle this? */
BUG_ON(!node);
@ -2690,7 +2690,6 @@ static struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
ret = a6xx_gmu_wrapper_init(a6xx_gpu, node);
else
ret = a6xx_gmu_init(a6xx_gpu, node);
of_node_put(node);
if (ret) {
a6xx_destroy(&(a6xx_gpu->base.base));
return ERR_PTR(ret);
@ -2740,6 +2739,7 @@ const struct adreno_gpu_funcs a6xx_gpu_funcs = {
.create_private_vm = a6xx_create_private_vm,
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
.sysprof_setup = a6xx_gmu_sysprof_setup,
},
.init = a6xx_gpu_init,
.get_timestamp = a6xx_gmu_get_timestamp,
@ -2808,6 +2808,7 @@ const struct adreno_gpu_funcs a7xx_gpu_funcs = {
.create_private_vm = a6xx_create_private_vm,
.get_rptr = a6xx_get_rptr,
.progress = a6xx_progress,
.sysprof_setup = a6xx_gmu_sysprof_setup,
},
.init = a6xx_gpu_init,
.get_timestamp = a6xx_gmu_get_timestamp,

View File

@ -289,6 +289,8 @@ static int a8xx_hfi_send_perf_table(struct a6xx_gmu *gmu)
(gmu->nr_gpu_freqs * num_gx_votes * sizeof(gmu->gx_arc_votes[0])) +
(gmu->nr_gmu_freqs * num_cx_votes * sizeof(gmu->cx_arc_votes[0]));
tbl = kzalloc(size, GFP_KERNEL);
if (!tbl)
return -ENOMEM;
tbl->type = HFI_TABLE_GPU_PERF;
/* First fill GX votes */

View File

@ -17,7 +17,7 @@ MODULE_PARM_DESC(snapshot_debugbus, "Include debugbus sections in GPU devcoredum
module_param_named(snapshot_debugbus, snapshot_debugbus, bool, 0600);
int enable_preemption = -1;
MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx only) (1=on , 0=disable, -1=auto (default))");
MODULE_PARM_DESC(enable_preemption, "Enable preemption (A7xx+ only) (1=on , 0=disable, -1=auto (default))");
module_param(enable_preemption, int, 0600);
bool disable_acd;

View File

@ -376,7 +376,7 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx,
*value = adreno_gpu->info->gmem;
return 0;
case MSM_PARAM_GMEM_BASE:
if (adreno_gpu->info->family >= ADRENO_6XX_GEN4)
if (adreno_gpu->info->family >= ADRENO_6XX_GEN3)
*value = 0;
else
*value = 0x100000;
@ -424,15 +424,21 @@ int adreno_get_param(struct msm_gpu *gpu, struct msm_context *ctx,
*value = vm->mm_range;
return 0;
case MSM_PARAM_HIGHEST_BANK_BIT:
if (!adreno_gpu->ubwc_config)
return UERR(ENOENT, drm, "no UBWC on this platform");
*value = adreno_gpu->ubwc_config->highest_bank_bit;
return 0;
case MSM_PARAM_RAYTRACING:
*value = adreno_gpu->has_ray_tracing;
return 0;
case MSM_PARAM_UBWC_SWIZZLE:
if (!adreno_gpu->ubwc_config)
return UERR(ENOENT, drm, "no UBWC on this platform");
*value = adreno_gpu->ubwc_config->ubwc_swizzle;
return 0;
case MSM_PARAM_MACROTILE_MODE:
if (!adreno_gpu->ubwc_config)
return UERR(ENOENT, drm, "no UBWC on this platform");
*value = adreno_gpu->ubwc_config->macrotile_mode;
return 0;
case MSM_PARAM_UCHE_TRAP_BASE:

View File

@ -480,7 +480,7 @@ const struct dpu_mdss_cfg dpu_kaanapali_cfg = {
.wb_count = ARRAY_SIZE(kaanapali_wb),
.wb = kaanapali_wb,
.cwb_count = ARRAY_SIZE(kaanapali_cwb),
.cwb = sm8650_cwb,
.cwb = kaanapali_cwb,
.intf_count = ARRAY_SIZE(kaanapali_intf),
.intf = kaanapali_intf,
.vbif = &sm8650_vbif,

View File

@ -61,7 +61,7 @@ static int _dpu_format_populate_plane_sizes_ubwc(
bool meta = MSM_FORMAT_IS_UBWC(fmt);
if (MSM_FORMAT_IS_YUV(fmt)) {
unsigned int stride, sclines;
unsigned int stride, y_sclines, uv_sclines;
unsigned int y_tile_width, y_tile_height;
unsigned int y_meta_stride, y_meta_scanlines;
unsigned int uv_meta_stride, uv_meta_scanlines;
@ -77,23 +77,25 @@ static int _dpu_format_populate_plane_sizes_ubwc(
y_tile_width = 32;
}
sclines = round_up(fb->height, 16);
y_sclines = round_up(fb->height, 16);
uv_sclines = round_up((fb->height+1)>>1, 16);
y_tile_height = 4;
} else {
stride = round_up(fb->width, 128);
y_tile_width = 32;
sclines = round_up(fb->height, 32);
y_sclines = round_up(fb->height, 32);
uv_sclines = round_up((fb->height+1)>>1, 32);
y_tile_height = 8;
}
layout->plane_pitch[0] = stride;
layout->plane_size[0] = round_up(layout->plane_pitch[0] *
sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
y_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
layout->plane_pitch[1] = stride;
layout->plane_size[1] = round_up(layout->plane_pitch[1] *
sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
uv_sclines, DPU_UBWC_PLANE_SIZE_ALIGNMENT);
if (!meta)
return 0;

View File

@ -5,6 +5,7 @@
#include <drm/drm_edid.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_managed.h>
#include "dpu_writeback.h"
@ -125,7 +126,7 @@ int dpu_writeback_init(struct drm_device *dev, struct drm_encoder *enc,
struct dpu_wb_connector *dpu_wb_conn;
int rc = 0;
dpu_wb_conn = devm_kzalloc(dev->dev, sizeof(*dpu_wb_conn), GFP_KERNEL);
dpu_wb_conn = drmm_kzalloc(dev, sizeof(*dpu_wb_conn), GFP_KERNEL);
if (!dpu_wb_conn)
return -ENOMEM;

View File

@ -5,11 +5,11 @@
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
#include <generated/utsrelease.h>
#include <linux/utsname.h>
#include "msm_disp_snapshot.h"
static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *base_addr)
static void msm_disp_state_dump_regs(u32 **reg, u32 len, void __iomem *base_addr)
{
u32 len_padded;
u32 num_rows;
@ -19,11 +19,11 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
void __iomem *end_addr;
int i;
len_padded = aligned_len * REG_DUMP_ALIGN;
num_rows = aligned_len / REG_DUMP_ALIGN;
len_padded = round_up(len, REG_DUMP_ALIGN);
num_rows = DIV_ROUND_UP(len, REG_DUMP_ALIGN);
addr = base_addr;
end_addr = base_addr + aligned_len;
end_addr = base_addr + len;
*reg = kvzalloc(len_padded, GFP_KERNEL);
if (!*reg)
@ -48,8 +48,8 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
void __iomem *base_addr, struct drm_printer *p)
{
void __iomem *addr, *end_addr;
int i;
void __iomem *addr;
u32 num_rows;
if (!dump_addr) {
@ -58,6 +58,7 @@ static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
}
addr = base_addr;
end_addr = base_addr + len;
num_rows = len / REG_DUMP_ALIGN;
for (i = 0; i < num_rows; i++) {
@ -67,6 +68,17 @@ static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
dump_addr[i * 4 + 2], dump_addr[i * 4 + 3]);
addr += REG_DUMP_ALIGN;
}
if (addr != end_addr) {
drm_printf(p, "0x%lx : %08x",
(unsigned long)(addr - base_addr),
dump_addr[i * 4]);
if (addr + 0x4 < end_addr)
drm_printf(p, " %08x", dump_addr[i * 4 + 1]);
if (addr + 0x8 < end_addr)
drm_printf(p, " %08x", dump_addr[i * 4 + 2]);
drm_printf(p, "\n");
}
}
void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p)
@ -79,7 +91,7 @@ void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p)
}
drm_printf(p, "---\n");
drm_printf(p, "kernel: " UTS_RELEASE "\n");
drm_printf(p, "kernel: %s\n", init_utsname()->release);
drm_printf(p, "module: " KBUILD_MODNAME "\n");
drm_printf(p, "dpu devcoredump\n");
drm_printf(p, "time: %ptSp\n", &state->time);
@ -185,7 +197,7 @@ void msm_disp_snapshot_add_block(struct msm_disp_state *disp_state, u32 len,
va_end(va);
INIT_LIST_HEAD(&new_blk->node);
new_blk->size = ALIGN(len, REG_DUMP_ALIGN);
new_blk->size = len;
new_blk->base_addr = base_addr;
msm_disp_state_dump_regs(&new_blk->state, new_blk->size, base_addr);

View File

@ -2033,6 +2033,7 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
/* fixup base address by io offset */
msm_host->ctrl_base += cfg->io_offset;
msm_host->ctrl_size -= cfg->io_offset;
ret = devm_regulator_bulk_get_const(&pdev->dev, cfg->num_regulators,
cfg->regulator_data,

View File

@ -43,8 +43,7 @@ msm_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
}
static bool
with_vm_locks(struct ww_acquire_ctx *ticket,
void (*fn)(struct drm_gem_object *obj),
with_vm_locks(void (*fn)(struct drm_gem_object *obj),
struct drm_gem_object *obj)
{
/*
@ -52,7 +51,7 @@ with_vm_locks(struct ww_acquire_ctx *ticket,
* success paths
*/
struct drm_gpuvm_bo *vm_bo, *last_locked = NULL;
int ret = 0;
bool locked = true;
drm_gem_for_each_gpuvm_bo (vm_bo, obj) {
struct dma_resv *resv = drm_gpuvm_resv(vm_bo->vm);
@ -60,23 +59,14 @@ with_vm_locks(struct ww_acquire_ctx *ticket,
if (resv == obj->resv)
continue;
ret = dma_resv_lock(resv, ticket);
/*
* Since we already skip the case when the VM and obj
* share a resv (ie. _NO_SHARE objs), we don't expect
* to hit a double-locking scenario... which the lock
* unwinding cannot really cope with.
* dma_resv_lock can't be used due to acquiring 'ticket' before the
* fs_reclaim lock, which is held in shrinker context
*/
WARN_ON(ret == -EALREADY);
/*
* Don't bother with slow-lock / backoff / retry sequence,
* if we can't get the lock just give up and move on to
* the next object.
*/
if (ret)
if (!dma_resv_trylock(resv)) {
locked = false;
goto out_unlock;
}
/*
* Hold a ref to prevent the vm_bo from being freed
@ -108,11 +98,11 @@ with_vm_locks(struct ww_acquire_ctx *ticket,
}
}
return ret == 0;
return locked;
}
static bool
purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
purge(struct drm_gem_object *obj, struct ww_acquire_ctx *)
{
if (!is_purgeable(to_msm_bo(obj)))
return false;
@ -120,11 +110,11 @@ purge(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
if (msm_gem_active(obj))
return false;
return with_vm_locks(ticket, msm_gem_purge, obj);
return with_vm_locks(msm_gem_purge, obj);
}
static bool
evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
evict(struct drm_gem_object *obj, struct ww_acquire_ctx *)
{
if (is_unevictable(to_msm_bo(obj)))
return false;
@ -132,7 +122,7 @@ evict(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket)
if (msm_gem_active(obj))
return false;
return with_vm_locks(ticket, msm_gem_evict, obj);
return with_vm_locks(msm_gem_evict, obj);
}
static bool
@ -164,7 +154,6 @@ static unsigned long
msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
{
struct msm_drm_private *priv = shrinker->private_data;
struct ww_acquire_ctx ticket;
struct {
struct drm_gem_lru *lru;
bool (*shrink)(struct drm_gem_object *obj, struct ww_acquire_ctx *ticket);
@ -185,11 +174,14 @@ msm_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
for (unsigned i = 0; (nr > 0) && (i < ARRAY_SIZE(stages)); i++) {
if (!stages[i].cond)
continue;
/*
* 'ticket' not needed on trylock paths
*/
stages[i].freed =
drm_gem_lru_scan(stages[i].lru, nr,
&stages[i].remaining,
stages[i].shrink,
&ticket);
NULL);
nr -= stages[i].freed;
freed += stages[i].freed;
remaining += stages[i].remaining;

View File

@ -13,11 +13,11 @@
#include "msm_gpu_trace.h"
//#include "adreno/adreno_gpu.h"
#include <generated/utsrelease.h>
#include <linux/string_helpers.h>
#include <linux/devcoredump.h>
#include <linux/sched/task.h>
#include <linux/sched/mm.h>
#include <linux/utsname.h>
/*
* Power Management:
@ -196,7 +196,7 @@ static ssize_t msm_gpu_devcoredump_read(char *buffer, loff_t offset,
p = drm_coredump_printer(&iter);
drm_printf(&p, "---\n");
drm_printf(&p, "kernel: " UTS_RELEASE "\n");
drm_printf(&p, "kernel: %s\n", init_utsname()->release);
drm_printf(&p, "module: " KBUILD_MODNAME "\n");
drm_printf(&p, "time: %ptSp\n", &state->time);
if (state->comm)

View File

@ -677,7 +677,7 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
int prot)
{
struct msm_iommu *iommu = to_msm_iommu(mmu);
size_t ret;
ssize_t ret;
WARN_ON(off != 0);
@ -686,7 +686,8 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova,
iova |= GENMASK_ULL(63, 49);
ret = iommu_map_sgtable(iommu->domain, iova, sgt, prot);
WARN_ON(!ret);
if (ret < 0)
return ret;
return (ret == len) ? 0 : -EINVAL;
}