Merge "disp: msm: sde: Validate transaction counts for LUTDMA abs writes"

This commit is contained in:
qctecmdr
2021-08-27 21:23:19 -07:00
committed by Gerrit - the friendly Code Review server
5 changed files with 43 additions and 3 deletions

View File

@@ -1353,6 +1353,7 @@ struct sde_reg_dma_blk_info {
* @broadcast_disabled flag indicating if broadcast usage should be avoided * @broadcast_disabled flag indicating if broadcast usage should be avoided
* @xin_id VBIF xin client-id for LUTDMA * @xin_id VBIF xin client-id for LUTDMA
* @vbif_idx VBIF id (RT/NRT) * @vbif_idx VBIF id (RT/NRT)
* @base_off Base offset of LUTDMA from the MDSS root
* @clk_ctrl VBIF xin client clk-ctrl * @clk_ctrl VBIF xin client clk-ctrl
*/ */
struct sde_reg_dma_cfg { struct sde_reg_dma_cfg {
@@ -1362,6 +1363,7 @@ struct sde_reg_dma_cfg {
u32 broadcast_disabled; u32 broadcast_disabled;
u32 xin_id; u32 xin_id;
u32 vbif_idx; u32 vbif_idx;
u32 base_off;
enum sde_clk_ctrl_type clk_ctrl; enum sde_clk_ctrl_type clk_ctrl;
}; };

View File

@@ -14,7 +14,7 @@
#define GUARD_BYTES (BIT(8) - 1) #define GUARD_BYTES (BIT(8) - 1)
#define ALIGNED_OFFSET (U32_MAX & ~(GUARD_BYTES)) #define ALIGNED_OFFSET (U32_MAX & ~(GUARD_BYTES))
#define ADDR_ALIGN BIT(8) #define ADDR_ALIGN BIT(8)
#define MAX_RELATIVE_OFF (BIT(20) - 1) #define MAX_RELATIVE_OFF (BIT(21) - 1)
#define ABSOLUTE_RANGE BIT(27) #define ABSOLUTE_RANGE BIT(27)
#define DECODE_SEL_OP (BIT(HW_BLK_SELECT)) #define DECODE_SEL_OP (BIT(HW_BLK_SELECT))
@@ -254,6 +254,9 @@ static int write_multi_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
cfg->dma_buf->next_op_allowed = REG_WRITE_OP | DECODE_SEL_OP; cfg->dma_buf->next_op_allowed = REG_WRITE_OP | DECODE_SEL_OP;
cfg->dma_buf->ops_completed |= REG_WRITE_OP; cfg->dma_buf->ops_completed |= REG_WRITE_OP;
if (cfg->blk == MDSS)
cfg->dma_buf->abs_write_cnt += SIZE_DWORD(cfg->data_size);
return 0; return 0;
} }
@@ -319,8 +322,10 @@ static int write_single_reg(struct sde_reg_dma_setup_ops_cfg *cfg)
cfg->dma_buf->index); cfg->dma_buf->index);
loc[0] = SINGLE_REG_WRITE_OPCODE; loc[0] = SINGLE_REG_WRITE_OPCODE;
loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF); loc[0] |= (cfg->blk_offset & MAX_RELATIVE_OFF);
if (cfg->blk == MDSS) if (cfg->blk == MDSS) {
loc[0] |= ABSOLUTE_RANGE; loc[0] |= ABSOLUTE_RANGE;
cfg->dma_buf->abs_write_cnt++;
}
loc[1] = *cfg->data; loc[1] = *cfg->data;
cfg->dma_buf->index += ops_mem_size[cfg->ops]; cfg->dma_buf->index += ops_mem_size[cfg->ops];
@@ -624,6 +629,32 @@ static int validate_kick_off_v1(struct sde_reg_dma_kickoff_cfg *cfg)
return -EINVAL; return -EINVAL;
} }
if ((cfg->dma_buf->abs_write_cnt % 2) != 0) {
/* Touch up buffer to avoid HW issues with odd number of abs writes */
u32 reg = 0;
struct sde_reg_dma_setup_ops_cfg dma_write_cfg;
dma_write_cfg.dma_buf = cfg->dma_buf;
dma_write_cfg.blk = MDSS;
dma_write_cfg.feature = REG_DMA_FEATURES_MAX;
dma_write_cfg.ops = HW_BLK_SELECT;
if (validate_write_decode_sel(&dma_write_cfg) || write_decode_sel(&dma_write_cfg)) {
DRM_ERROR("Failed setting MDSS decode select for LUTDMA touch up\n");
return -EINVAL;
}
/* Perform dummy write on LUTDMA RO version reg */
dma_write_cfg.ops = REG_SINGLE_WRITE;
dma_write_cfg.blk_offset = reg_dma->caps->base_off +
reg_dma->caps->reg_dma_blks[cfg->dma_type].base;
dma_write_cfg.data = ®
dma_write_cfg.data_size = sizeof(uint32_t);
if (validate_write_reg(&dma_write_cfg) || write_single_reg(&dma_write_cfg)) {
DRM_ERROR("Failed to add touch up write to LUTDMA buffer\n");
return -EINVAL;
}
}
return 0; return 0;
} }
@@ -1110,6 +1141,7 @@ static int reset_reg_dma_buffer_v1(struct sde_reg_dma_buffer *lut_buf)
lut_buf->index = 0; lut_buf->index = 0;
lut_buf->ops_completed = 0; lut_buf->ops_completed = 0;
lut_buf->next_op_allowed = DECODE_SEL_OP; lut_buf->next_op_allowed = DECODE_SEL_OP;
lut_buf->abs_write_cnt = 0;
return 0; return 0;
} }

View File

@@ -4557,7 +4557,9 @@ static int _sde_kms_hw_init_ioremap(struct sde_kms *sde_kms,
sde_kms->reg_dma = NULL; sde_kms->reg_dma = NULL;
SDE_DEBUG("REG_DMA is not defined"); SDE_DEBUG("REG_DMA is not defined");
} else { } else {
unsigned long mdp_addr = msm_get_phys_addr(platformdev, "mdp_phys");
sde_kms->reg_dma_len = msm_iomap_size(platformdev, "regdma_phys"); sde_kms->reg_dma_len = msm_iomap_size(platformdev, "regdma_phys");
sde_kms->reg_dma_off = msm_get_phys_addr(platformdev, "regdma_phys") - mdp_addr;
rc = sde_dbg_reg_register_base("reg_dma", sde_kms->reg_dma, rc = sde_dbg_reg_register_base("reg_dma", sde_kms->reg_dma,
sde_kms->reg_dma_len, sde_kms->reg_dma_len,
msm_get_phys_addr(platformdev, "regdma_phys"), msm_get_phys_addr(platformdev, "regdma_phys"),
@@ -4651,6 +4653,7 @@ static int _sde_kms_hw_init_blocks(struct sde_kms *sde_kms,
} }
/* Initialize reg dma block which is a singleton */ /* Initialize reg dma block which is a singleton */
sde_kms->catalog->dma_cfg.base_off = sde_kms->reg_dma_off;
rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog, rc = sde_reg_dma_init(sde_kms->reg_dma, sde_kms->catalog,
sde_kms->dev); sde_kms->dev);
if (rc) { if (rc) {

View File

@@ -262,6 +262,7 @@ struct sde_kms {
/* io/register spaces: */ /* io/register spaces: */
void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma, *sid; void __iomem *mmio, *vbif[VBIF_MAX], *reg_dma, *sid;
unsigned long mmio_len, vbif_len[VBIF_MAX], reg_dma_len, sid_len; unsigned long mmio_len, vbif_len[VBIF_MAX], reg_dma_len, sid_len;
unsigned long reg_dma_off;
struct regulator *vdd; struct regulator *vdd;
struct regulator *mmagic; struct regulator *mmagic;

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _SDE_REG_DMA_H #ifndef _SDE_REG_DMA_H
@@ -232,6 +232,7 @@ enum sde_reg_dma_last_cmd_mode {
* @vaddr: cpu address * @vaddr: cpu address
* @next_op_allowed: operation allowed on the buffer * @next_op_allowed: operation allowed on the buffer
* @ops_completed: operations completed on buffer * @ops_completed: operations completed on buffer
* @abs_write_cnt: count of mdss absolute addr writes in the current buffer
*/ */
struct sde_reg_dma_buffer { struct sde_reg_dma_buffer {
struct drm_gem_object *buf; struct drm_gem_object *buf;
@@ -242,6 +243,7 @@ struct sde_reg_dma_buffer {
void *vaddr; void *vaddr;
u32 next_op_allowed; u32 next_op_allowed;
u32 ops_completed; u32 ops_completed;
u32 abs_write_cnt;
}; };
/** /**