Skip to content

Commit

Permalink
drm: kirin9xx: fix the IOMMU domain phy add setting logic
Browse files Browse the repository at this point in the history
The DRM driver needs to get the base address of the IOMMU
mapped physical address, in order to set the overlay data
on its registers.

The previous approach were to export a private structure
from the hisi_smmu_lpae driver.

Instead, let's use the interface provided by iommu_iova_to_phys(),
adding a logic there which will allow to get the start of the
mapped block.

Without that, it would try to access an invalid value, causing
an OOPS:

[    2.720590] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048
[    2.729563] Mem abort info:
[    2.732354]   ESR = 0x96000004
[    2.735405]   EC = 0x25: DABT (current EL), IL = 32 bits
[    2.740713]   SET = 0, FnV = 0
[    2.743915]   EA = 0, S1PTW = 0
[    2.747054] Data abort info:
[    2.749925]   ISV = 0, ISS = 0x00000004
[    2.753757]   CM = 0, WnR = 0
[    2.756723] user pgtable: 4k pages, 48-bit VAs, pgdp=00000001ab8f8000
[    2.763191] [0000000000000048] pgd=0000000000000000
[    2.768070] Internal error: Oops: 96000004 [#1] PREEMPT SMP
[    2.773638] Modules linked in: wl18xx wlcore mac80211 libarc4 cfg80211 rfkill snd_soc_hdmi_codec wlcore_sdio adv7511 crct10dif_ce cec kirin9xx_drm kirin9xx_dw_drm_dsi drm_kms_helper kirin9xx_pwm drm ip_tables x_tables ipv6 nf_defrag_ipv6
[    2.794685] CPU: 4 PID: 470 Comm: Xorg Not tainted 5.7.0+ torvalds#49
[    2.800421] Hardware name: HiKey970 (DT)
[    2.804335] pstate: 60000005 (nZCv daif -PAN -UAO)
[    2.809126] pc : hisi_dss_smmu_on+0x15c/0x1b8 [kirin9xx_drm]
[    2.814779] lr : hisi_dss_smmu_on+0x14c/0x1b8 [kirin9xx_drm]
[    2.820428] sp : ffff8000123339a0
[    2.823732] x29: ffff8000123339a0 x28: ffff0001b103e400
[    2.829035] x27: 0000000000000028 x26: ffff0001b19b5c00
[    2.834338] x25: 0000000000000038 x24: 0000000000000038
[    2.839640] x23: ffff800008f79628 x22: ffff0001b19b5c00
[    2.844943] x21: ffff800012980000 x20: ffff0001b7fe27c0
[    2.850245] x19: ffff800012900000 x18: 0000000000000000
[    2.855547] x17: 0000000000000000 x16: 0000000000000000
[    2.860850] x15: ffff800011b01000 x14: ffff800011d0a07a
[    2.866152] x13: 0000000000000f00 x12: 0000580000004d00
[    2.871454] x11: 000000000000a180 x10: 000000000000a160
[    2.876756] x9 : 000000000000a140 x8 : 000000000000a120
[    2.882058] x7 : 000000000000a100 x6 : 000000000000a0e0
[    2.887360] x5 : 0000000000000000 x4 : 000000000000001c
[    2.892663] x3 : 0000000000000000 x2 : 0000000000000000
[    2.897965] x1 : ffff800008f7a7b8 x0 : 0000000000000001
[    2.903268] Call trace:
[    2.905711]  hisi_dss_smmu_on+0x15c/0x1b8 [kirin9xx_drm]
[    2.911016]  hisifb_dss_on+0x190/0x1d0 [kirin9xx_drm]
[    2.916059]  dpe_init+0x4c/0xa8 [kirin9xx_drm]

Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
  • Loading branch information
mchehab committed Aug 5, 2020
1 parent 23633fe commit 36da105
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 5 deletions.
14 changes: 9 additions & 5 deletions drivers/gpu/drm/hisilicon/kirin/kirin9xx_drm_overlay_utils.c
Expand Up @@ -1341,7 +1341,6 @@ static void hisi_dss_mif_on(struct dss_hw_ctx *ctx)
void hisi_dss_smmu_on(struct dss_hw_ctx *ctx)
{
void __iomem *smmu_base;
struct iommu_domain_data *domain_data = NULL;
uint32_t phy_pgd_base = 0;
uint64_t fama_phy_pgd_base;

Expand Down Expand Up @@ -1374,10 +1373,15 @@ void hisi_dss_smmu_on(struct dss_hw_ctx *ctx)
set_reg(smmu_base + SMMU_SMRx_NS + 38 * 0x4, 0x1, 32, 0); /*cmd sec stream id*/

/*TTBR0*/
domain_data = (struct iommu_domain_data *)(ctx->mmu_domain->priv);
fama_phy_pgd_base = domain_data->phy_pgd_base;
phy_pgd_base = (uint32_t)(domain_data->phy_pgd_base);
DRM_DEBUG("fama_phy_pgd_base = %llu, phy_pgd_base =0x%x \n", fama_phy_pgd_base, phy_pgd_base);
fama_phy_pgd_base = iommu_iova_to_phys(ctx->mmu_domain, 0);
phy_pgd_base = (uint32_t)fama_phy_pgd_base;

if (!phy_pgd_base) {
DRM_ERROR("phy_pdg_base is NULL! probably smmu_lpae is missing at DT\n");
WARN_ON(1);
return;
}

set_reg(smmu_base + SMMU_CB_TTBR0, phy_pgd_base, 32, 0);
}

Expand Down
9 changes: 9 additions & 0 deletions drivers/iommu/hisi_smmu_lpae.c
Expand Up @@ -476,6 +476,15 @@ static phys_addr_t hisi_smmu_iova_to_phys_lpae(struct iommu_domain *domain,
if (!pgdp)
return 0;

/*
* The DRM driver needs to know the physical address of the
* start of the memory-mapped region, in order to set it on some
* registers. Add support for it, by returning the base of the
* memory mapped domain, when iova is zero.
*/
if (!iova)
return virt_to_phys(hisi_smmu_dev->smmu_pgd);

pgd = *(pgdp + smmu_pgd_index(iova));
if (smmu_pgd_none_lpae(pgd))
return 0;
Expand Down

0 comments on commit 36da105

Please sign in to comment.