summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/xen-blkfront.c4
-rw-r--r--drivers/clocksource/timer-atmel-pit.c20
-rw-r--r--drivers/clocksource/timer-fttmr010.c18
-rw-r--r--drivers/clocksource/timer-ti-32k.c3
-rw-r--r--drivers/cpufreq/qcom-cpufreq-kryo.c4
-rw-r--r--drivers/dax/device.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h49
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c183
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c52
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c187
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c84
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c22
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/cik.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c321
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c219
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c42
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c57
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c53
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c24
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c40
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c149
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c37
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c46
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_hw_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_link.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_aux.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c60
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c34
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c45
-rw-r--r--drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/include/signal_types.h5
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_offset.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_offset.h3
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_sh_mask.h3
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h12
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h10
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h4
-rw-r--r--drivers/gpu/drm/amd/powerplay/amd_powerplay.c87
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c19
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c9
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c3
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c5
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c44
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h12
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c30
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c7
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c82
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c64
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c91
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c151
-rw-r--r--drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h11
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/hwmgr.h3
-rw-r--r--drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h6
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c2
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c12
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c25
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c31
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c55
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c55
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c11
-rw-r--r--drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c2
-rw-r--r--drivers/gpu/drm/arm/malidp_crtc.c28
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c131
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h8
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c83
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.h16
-rw-r--r--drivers/gpu/drm/arm/malidp_mw.c25
-rw-r--r--drivers/gpu/drm/arm/malidp_planes.c347
-rw-r--r--drivers/gpu/drm/arm/malidp_regs.h13
-rw-r--r--drivers/gpu/drm/drm_panel.c10
-rw-r--r--drivers/gpu/drm/drm_syncobj.c5
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c27
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c26
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c107
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c17
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.h10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c46
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_plane.c16
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_scaler.c137
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c56
-rw-r--r--drivers/gpu/drm/exynos/regs-mixer.h5
-rw-r--r--drivers/gpu/drm/mediatek/Makefile5
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c131
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi_regs.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp.c14
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c15
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.h2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_phy.c235
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_phy.h60
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c212
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c226
-rw-r--r--drivers/gpu/drm/msm/Makefile1
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h8
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h8
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h8
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx.xml.h8
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_debugfs.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c20
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_power.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_preempt.c12
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx.xml.h1413
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c144
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.h21
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h12
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c38
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.h3
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_hfi.c161
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h8
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c1
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h26
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c737
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h115
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c257
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h10
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h23
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c48
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c125
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c109
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h56
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c323
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h139
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c16
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c29
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c29
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h39
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c18
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h17
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c3
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h16
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c45
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c499
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h4
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c15
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h14
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c285
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h44
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h116
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c5
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c10
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c4
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c8
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c4
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c49
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h5
-rw-r--r--drivers/gpu/drm/msm/msm_rd.c6
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c40
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl5070.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c220
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c54
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h33
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h25
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c179
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c36
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c1
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c35
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_connector.c3
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_priv.h7
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_tiler.c201
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c6
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fb.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem.c4
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/omapdrm/tcm-sita.h93
-rw-r--r--drivers/gpu/drm/radeon/evergreen_cs.c2
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c3
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c14
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.h3
-rw-r--r--drivers/gpu/drm/ttm/Makefile4
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c25
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/Makefile4
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_lock.c (renamed from drivers/gpu/drm/ttm/ttm_lock.c)15
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_lock.h248
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_object.c (renamed from drivers/gpu/drm/ttm/ttm_object.c)97
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_object.h375
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.c50
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c3
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_context.c23
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h147
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c1288
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fence.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c199
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h24
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_prime.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource.c124
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c48
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_shader.c25
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c7
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_so.c11
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c31
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c20
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_validation.c770
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_validation.h227
-rw-r--r--drivers/hwtracing/intel_th/core.c16
-rw-r--r--drivers/hwtracing/intel_th/pci.c5
-rw-r--r--drivers/infiniband/core/cache.c68
-rw-r--r--drivers/infiniband/core/ucma.c2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c68
-rw-r--r--drivers/infiniband/core/uverbs_main.c1
-rw-r--r--drivers/infiniband/core/uverbs_uapi.c1
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c93
-rw-r--r--drivers/infiniband/hw/hfi1/chip.c6
-rw-r--r--drivers/infiniband/hw/hfi1/pio.c51
-rw-r--r--drivers/infiniband/hw/hfi1/pio.h2
-rw-r--r--drivers/infiniband/hw/hfi1/user_sdma.c2
-rw-r--r--drivers/infiniband/hw/hfi1/verbs.c8
-rw-r--r--drivers/infiniband/hw/mlx5/devx.c5
-rw-r--r--drivers/infiniband/ulp/srp/ib_srp.c6
-rw-r--r--drivers/input/keyboard/atakbd.c74
-rw-r--r--drivers/input/misc/uinput.c2
-rw-r--r--drivers/input/mouse/elantech.c2
-rw-r--r--drivers/input/touchscreen/egalax_ts.c6
-rw-r--r--drivers/iommu/amd_iommu.c6
-rw-r--r--drivers/iommu/intel-iommu.c6
-rw-r--r--drivers/iommu/intel-pasid.h2
-rw-r--r--drivers/iommu/rockchip-iommu.c6
-rw-r--r--drivers/md/bcache/bcache.h1
-rw-r--r--drivers/md/bcache/journal.c6
-rw-r--r--drivers/md/bcache/super.c8
-rw-r--r--drivers/media/i2c/mt9v111.c41
-rw-r--r--drivers/media/platform/Kconfig2
-rw-r--r--drivers/media/platform/qcom/camss/camss-csid.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy-2ph-1-0.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss-csiphy.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss-ispif.c5
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-1.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-4-7.c1
-rw-r--r--drivers/media/platform/qcom/camss/camss.c15
-rw-r--r--drivers/media/usb/dvb-usb-v2/af9035.c6
-rw-r--r--drivers/net/bonding/bond_main.c11
-rw-r--r--drivers/net/ethernet/apple/bmac.c4
-rw-r--r--drivers/net/ethernet/apple/mace.c4
-rw-r--r--drivers/net/ethernet/apple/macmace.c4
-rw-r--r--drivers/net/ethernet/aquantia/atlantic/aq_ring.c32
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c16
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c18
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c3
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c20
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_msg.h1
-rw-r--r--drivers/net/ethernet/cirrus/ep93xx_eth.c2
-rw-r--r--drivers/net/ethernet/cirrus/mac89x0.c4
-rw-r--r--drivers/net/ethernet/i825xx/ether1.c5
-rw-r--r--drivers/net/ethernet/i825xx/lib82596.c4
-rw-r--r--drivers/net/ethernet/i825xx/sun3_82586.c6
-rw-r--r--drivers/net/ethernet/ibm/emac/core.c15
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k.h3
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_netdev.c3
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pci.c22
-rw-r--r--drivers/net/ethernet/intel/i40evf/i40evf_main.c26
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c27
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c30
-rw-r--r--drivers/net/ethernet/intel/ixgb/ixgb_main.c25
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c25
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c21
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c13
-rw-r--r--drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/en_netdev.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/eq.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/transobj.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c4
-rw-r--r--drivers/net/ethernet/mscc/ocelot_board.c12
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c18
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dcbx.c45
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dcbx.h1
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_dev.c15
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_hsi.h4
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c24
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_reg_addr.h6
-rw-r--r--drivers/net/ethernet/realtek/r8169.c9
-rw-r--r--drivers/net/ethernet/renesas/ravb.h5
-rw-r--r--drivers/net/ethernet/renesas/ravb_main.c11
-rw-r--r--drivers/net/ethernet/renesas/ravb_ptp.c2
-rw-r--r--drivers/net/ethernet/seeq/ether3.c5
-rw-r--r--drivers/net/ethernet/seeq/sgiseeq.c3
-rw-r--r--drivers/net/ethernet/sgi/ioc3-eth.c4
-rw-r--r--drivers/net/ethernet/sgi/meth.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h4
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c238
-rw-r--r--drivers/net/ethernet/wiznet/w5100.c2
-rw-r--r--drivers/net/ethernet/wiznet/w5300.c2
-rw-r--r--drivers/net/phy/sfp-bus.c4
-rw-r--r--drivers/net/tun.c43
-rw-r--r--drivers/nvme/host/multipath.c6
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.c8
-rw-r--r--drivers/pci/controller/dwc/pcie-designware.h3
-rw-r--r--drivers/pci/controller/pci-hyperv.c4
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c11
-rw-r--r--drivers/pinctrl/intel/pinctrl-cannonlake.c33
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c32
-rw-r--r--drivers/pinctrl/pinctrl-amd.c33
-rw-r--r--drivers/regulator/bd71837-regulator.c19
-rw-r--r--drivers/regulator/core.c4
-rw-r--r--drivers/regulator/of_regulator.c2
-rw-r--r--drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c5
-rw-r--r--drivers/scsi/ipr.c106
-rw-r--r--drivers/scsi/ipr.h1
-rw-r--r--drivers/scsi/lpfc/lpfc_attr.c15
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c10
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c11
-rw-r--r--drivers/scsi/sd.c6
-rw-r--r--drivers/scsi/ufs/ufshcd.c7
-rw-r--r--drivers/soundwire/stream.c23
-rw-r--r--drivers/spi/spi-gpio.c4
-rw-r--r--drivers/spi/spi-rspi.c34
-rw-r--r--drivers/spi/spi-sh-msiof.c28
-rw-r--r--drivers/spi/spi-tegra20-slink.c31
-rw-r--r--drivers/staging/media/mt9t031/Kconfig6
-rw-r--r--drivers/target/iscsi/iscsi_target_auth.c45
-rw-r--r--drivers/tty/serial/cpm_uart/cpm_uart_core.c10
-rw-r--r--drivers/tty/serial/fsl_lpuart.c3
-rw-r--r--drivers/tty/serial/imx.c8
-rw-r--r--drivers/tty/serial/mvebu-uart.c1
-rw-r--r--drivers/tty/tty_io.c11
-rw-r--r--drivers/tty/vt/vt_ioctl.c4
-rw-r--r--drivers/usb/class/cdc-wdm.c2
-rw-r--r--drivers/usb/common/roles.c15
-rw-r--r--drivers/usb/core/devio.c24
-rw-r--r--drivers/usb/core/driver.c28
-rw-r--r--drivers/usb/core/quirks.c3
-rw-r--r--drivers/usb/core/usb.c2
-rw-r--r--drivers/usb/musb/musb_dsps.c12
-rw-r--r--drivers/usb/typec/mux.c17
388 files changed, 9377 insertions, 7604 deletions
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index a71d817e900d..429d20131c7e 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -2670,8 +2670,8 @@ static void purge_persistent_grants(struct blkfront_info *info)
list_del(&gnt_list_entry->node);
gnttab_end_foreign_access(gnt_list_entry->gref, 0, 0UL);
rinfo->persistent_gnts_c--;
- __free_page(gnt_list_entry->page);
- kfree(gnt_list_entry);
+ gnt_list_entry->gref = GRANT_INVALID_REF;
+ list_add_tail(&gnt_list_entry->node, &rinfo->grants);
}
spin_unlock_irqrestore(&rinfo->ring_lock, flags);
diff --git a/drivers/clocksource/timer-atmel-pit.c b/drivers/clocksource/timer-atmel-pit.c
index ec8a4376f74f..2fab18fae4fc 100644
--- a/drivers/clocksource/timer-atmel-pit.c
+++ b/drivers/clocksource/timer-atmel-pit.c
@@ -180,26 +180,29 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
data->base = of_iomap(node, 0);
if (!data->base) {
pr_err("Could not map PIT address\n");
- return -ENXIO;
+ ret = -ENXIO;
+ goto exit;
}
data->mck = of_clk_get(node, 0);
if (IS_ERR(data->mck)) {
pr_err("Unable to get mck clk\n");
- return PTR_ERR(data->mck);
+ ret = PTR_ERR(data->mck);
+ goto exit;
}
ret = clk_prepare_enable(data->mck);
if (ret) {
pr_err("Unable to enable mck\n");
- return ret;
+ goto exit;
}
/* Get the interrupts property */
data->irq = irq_of_parse_and_map(node, 0);
if (!data->irq) {
pr_err("Unable to get IRQ from DT\n");
- return -EINVAL;
+ ret = -EINVAL;
+ goto exit;
}
/*
@@ -227,7 +230,7 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
ret = clocksource_register_hz(&data->clksrc, pit_rate);
if (ret) {
pr_err("Failed to register clocksource\n");
- return ret;
+ goto exit;
}
/* Set up irq handler */
@@ -236,7 +239,8 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
"at91_tick", data);
if (ret) {
pr_err("Unable to setup IRQ\n");
- return ret;
+ clocksource_unregister(&data->clksrc);
+ goto exit;
}
/* Set up and register clockevents */
@@ -254,6 +258,10 @@ static int __init at91sam926x_pit_dt_init(struct device_node *node)
clockevents_register_device(&data->clkevt);
return 0;
+
+exit:
+ kfree(data);
+ return ret;
}
TIMER_OF_DECLARE(at91sam926x_pit, "atmel,at91sam9260-pit",
at91sam926x_pit_dt_init);
diff --git a/drivers/clocksource/timer-fttmr010.c b/drivers/clocksource/timer-fttmr010.c
index c020038ebfab..cf93f6419b51 100644
--- a/drivers/clocksource/timer-fttmr010.c
+++ b/drivers/clocksource/timer-fttmr010.c
@@ -130,13 +130,17 @@ static int fttmr010_timer_set_next_event(unsigned long cycles,
cr &= ~fttmr010->t1_enable_val;
writel(cr, fttmr010->base + TIMER_CR);
- /* Setup the match register forward/backward in time */
- cr = readl(fttmr010->base + TIMER1_COUNT);
- if (fttmr010->count_down)
- cr -= cycles;
- else
- cr += cycles;
- writel(cr, fttmr010->base + TIMER1_MATCH1);
+ if (fttmr010->count_down) {
+ /*
+ * ASPEED Timer Controller will load TIMER1_LOAD register
+ * into TIMER1_COUNT register when the timer is re-enabled.
+ */
+ writel(cycles, fttmr010->base + TIMER1_LOAD);
+ } else {
+ /* Setup the match register forward in time */
+ cr = readl(fttmr010->base + TIMER1_COUNT);
+ writel(cr + cycles, fttmr010->base + TIMER1_MATCH1);
+ }
/* Start */
cr = readl(fttmr010->base + TIMER_CR);
diff --git a/drivers/clocksource/timer-ti-32k.c b/drivers/clocksource/timer-ti-32k.c
index 29e2e1a78a43..6949a9113dbb 100644
--- a/drivers/clocksource/timer-ti-32k.c
+++ b/drivers/clocksource/timer-ti-32k.c
@@ -97,6 +97,9 @@ static int __init ti_32k_timer_init(struct device_node *np)
return -ENXIO;
}
+ if (!of_machine_is_compatible("ti,am43"))
+ ti_32k_timer.cs.flags |= CLOCK_SOURCE_SUSPEND_NONSTOP;
+
ti_32k_timer.counter = ti_32k_timer.base;
/*
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c
index a1830fa25fc5..2a3675c24032 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -44,7 +44,7 @@ enum _msm8996_version {
struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev;
-static enum _msm8996_version __init qcom_cpufreq_kryo_get_msm_id(void)
+static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void)
{
size_t len;
u32 *msm_id;
@@ -222,7 +222,7 @@ static int __init qcom_cpufreq_kryo_init(void)
}
module_init(qcom_cpufreq_kryo_init);
-static void __init qcom_cpufreq_kryo_exit(void)
+static void __exit qcom_cpufreq_kryo_exit(void)
{
platform_device_unregister(kryo_cpufreq_pdev);
platform_driver_unregister(&qcom_cpufreq_kryo_driver);
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index bbe4d72ca105..948806e57cee 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -535,6 +535,11 @@ static unsigned long dax_get_unmapped_area(struct file *filp,
return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
}
+static const struct address_space_operations dev_dax_aops = {
+ .set_page_dirty = noop_set_page_dirty,
+ .invalidatepage = noop_invalidatepage,
+};
+
static int dax_open(struct inode *inode, struct file *filp)
{
struct dax_device *dax_dev = inode_dax(inode);
@@ -544,6 +549,7 @@ static int dax_open(struct inode *inode, struct file *filp)
dev_dbg(&dev_dax->dev, "trace\n");
inode->i_mapping = __dax_inode->i_mapping;
inode->i_mapping->host = __dax_inode;
+ inode->i_mapping->a_ops = &dev_dax_aops;
filp->f_mapping = inode->i_mapping;
filp->f_wb_err = filemap_sample_wb_err(filp->f_mapping);
filp->private_data = dev_dax;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index c05b39438663..d0102cfc8efb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -81,6 +81,23 @@
#include "amdgpu_bo_list.h"
#include "amdgpu_gem.h"
+#define MAX_GPU_INSTANCE 16
+
+struct amdgpu_gpu_instance
+{
+ struct amdgpu_device *adev;
+ int mgpu_fan_enabled;
+};
+
+struct amdgpu_mgpu_info
+{
+ struct amdgpu_gpu_instance gpu_ins[MAX_GPU_INSTANCE];
+ struct mutex mutex;
+ uint32_t num_gpu;
+ uint32_t num_dgpu;
+ uint32_t num_apu;
+};
+
/*
* Modules parameters.
*/
@@ -134,6 +151,7 @@ extern int amdgpu_compute_multipipe;
extern int amdgpu_gpu_recovery;
extern int amdgpu_emu_mode;
extern uint amdgpu_smu_memory_pool_size;
+extern struct amdgpu_mgpu_info mgpu_info;
#ifdef CONFIG_DRM_AMDGPU_SI
extern int amdgpu_si_support;
@@ -598,31 +616,6 @@ void amdgpu_benchmark(struct amdgpu_device *adev, int test_number);
*/
void amdgpu_test_moves(struct amdgpu_device *adev);
-
-/*
- * amdgpu smumgr functions
- */
-struct amdgpu_smumgr_funcs {
- int (*check_fw_load_finish)(struct amdgpu_device *adev, uint32_t fwtype);
- int (*request_smu_load_fw)(struct amdgpu_device *adev);
- int (*request_smu_specific_fw)(struct amdgpu_device *adev, uint32_t fwtype);
-};
-
-/*
- * amdgpu smumgr
- */
-struct amdgpu_smumgr {
- struct amdgpu_bo *toc_buf;
- struct amdgpu_bo *smu_buf;
- /* asic priv smu data */
- void *priv;
- spinlock_t smu_lock;
- /* smumgr functions */
- const struct amdgpu_smumgr_funcs *smumgr_funcs;
- /* ucode loading complete flag */
- uint32_t fw_flags;
-};
-
/*
* ASIC specific register table accessible by UMD
*/
@@ -958,9 +951,6 @@ struct amdgpu_device {
u32 cg_flags;
u32 pg_flags;
- /* amdgpu smumgr */
- struct amdgpu_smumgr smu;
-
/* gfx */
struct amdgpu_gfx gfx;
@@ -1025,6 +1015,9 @@ struct amdgpu_device {
bool has_hw_reset;
u8 reset_magic[AMDGPU_RESET_MAGIC_NUM];
+ /* s3/s4 mask */
+ bool in_suspend;
+
/* record last mm index being written through WREG32*/
unsigned long last_mm_index;
bool in_gpu_reset;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index 6488e90ec948..7f0afc526419 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -359,7 +359,9 @@ out:
*
* Checks the acpi event and if it matches an atif event,
* handles it.
- * Returns NOTIFY code
+ *
+ * Returns:
+ * NOTIFY_BAD or NOTIFY_DONE, depending on the event.
*/
static int amdgpu_atif_handler(struct amdgpu_device *adev,
struct acpi_bus_event *event)
@@ -373,11 +375,16 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
if (strcmp(event->device_class, ACPI_VIDEO_CLASS) != 0)
return NOTIFY_DONE;
+ /* Is this actually our event? */
if (!atif ||
!atif->notification_cfg.enabled ||
- event->type != atif->notification_cfg.command_code)
- /* Not our event */
- return NOTIFY_DONE;
+ event->type != atif->notification_cfg.command_code) {
+ /* These events will generate keypresses otherwise */
+ if (event->type == ACPI_VIDEO_NOTIFY_PROBE)
+ return NOTIFY_BAD;
+ else
+ return NOTIFY_DONE;
+ }
if (atif->functions.sbios_requests) {
struct atif_sbios_requests req;
@@ -386,7 +393,7 @@ static int amdgpu_atif_handler(struct amdgpu_device *adev,
count = amdgpu_atif_get_sbios_requests(atif, &req);
if (count <= 0)
- return NOTIFY_DONE;
+ return NOTIFY_BAD;
DRM_DEBUG_DRIVER("ATIF: %d pending SBIOS requests\n", count);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index bd79d0a31942..1e4dd09a5072 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -1525,6 +1525,92 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev)
return 0;
}
+static int amdgpu_device_ip_hw_init_phase1(struct amdgpu_device *adev)
+{
+ int i, r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.sw)
+ continue;
+ if (adev->ip_blocks[i].status.hw)
+ continue;
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH) {
+ r = adev->ip_blocks[i].version->funcs->hw_init(adev);
+ if (r) {
+ DRM_ERROR("hw_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
+ return r;
+ }
+ adev->ip_blocks[i].status.hw = true;
+ }
+ }
+
+ return 0;
+}
+
+static int amdgpu_device_ip_hw_init_phase2(struct amdgpu_device *adev)
+{
+ int i, r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.sw)
+ continue;
+ if (adev->ip_blocks[i].status.hw)
+ continue;
+ r = adev->ip_blocks[i].version->funcs->hw_init(adev);
+ if (r) {
+ DRM_ERROR("hw_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
+ return r;
+ }
+ adev->ip_blocks[i].status.hw = true;
+ }
+
+ return 0;
+}
+
+static int amdgpu_device_fw_loading(struct amdgpu_device *adev)
+{
+ int r = 0;
+ int i;
+
+ if (adev->asic_type >= CHIP_VEGA10) {
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP) {
+ if (adev->in_gpu_reset || adev->in_suspend) {
+ if (amdgpu_sriov_vf(adev) && adev->in_gpu_reset)
+ break; /* sriov gpu reset, psp need to do hw_init before IH because of hw limit */
+ r = adev->ip_blocks[i].version->funcs->resume(adev);
+ if (r) {
+ DRM_ERROR("resume of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
+ return r;
+ }
+ } else {
+ r = adev->ip_blocks[i].version->funcs->hw_init(adev);
+ if (r) {
+ DRM_ERROR("hw_init of IP block <%s> failed %d\n",
+ adev->ip_blocks[i].version->funcs->name, r);
+ return r;
+ }
+ }
+ adev->ip_blocks[i].status.hw = true;
+ }
+ }
+ }
+
+ if (adev->powerplay.pp_funcs->load_firmware) {
+ r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle);
+ if (r) {
+ pr_err("firmware loading failed\n");
+ return r;
+ }
+ }
+
+ return 0;
+}
+
/**
* amdgpu_device_ip_init - run init for hardware IPs
*
@@ -1581,19 +1667,21 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
}
}
- for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.sw)
- continue;
- if (adev->ip_blocks[i].status.hw)
- continue;
- r = adev->ip_blocks[i].version->funcs->hw_init((void *)adev);
- if (r) {
- DRM_ERROR("hw_init of IP block <%s> failed %d\n",
- adev->ip_blocks[i].version->funcs->name, r);
- return r;
- }
- adev->ip_blocks[i].status.hw = true;
- }
+ r = amdgpu_ucode_create_bo(adev); /* create ucode bo when sw_init complete*/
+ if (r)
+ return r;
+
+ r = amdgpu_device_ip_hw_init_phase1(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_device_fw_loading(adev);
+ if (r)
+ return r;
+
+ r = amdgpu_device_ip_hw_init_phase2(adev);
+ if (r)
+ return r;
amdgpu_xgmi_add_device(adev);
amdgpu_amdkfd_device_init(adev);
@@ -1656,7 +1744,7 @@ static int amdgpu_device_set_cg_state(struct amdgpu_device *adev,
for (j = 0; j < adev->num_ip_blocks; j++) {
i = state == AMD_CG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
- if (!adev->ip_blocks[i].status.valid)
+ if (!adev->ip_blocks[i].status.late_initialized)
continue;
/* skip CG for VCE/UVD, it's handled specially */
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
@@ -1686,7 +1774,7 @@ static int amdgpu_device_set_pg_state(struct amdgpu_device *adev, enum amd_power
for (j = 0; j < adev->num_ip_blocks; j++) {
i = state == AMD_PG_STATE_GATE ? j : adev->num_ip_blocks - j - 1;
- if (!adev->ip_blocks[i].status.valid)
+ if (!adev->ip_blocks[i].status.late_initialized)
continue;
/* skip CG for VCE/UVD, it's handled specially */
if (adev->ip_blocks[i].version->type != AMD_IP_BLOCK_TYPE_UVD &&
@@ -1723,7 +1811,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
int i = 0, r;
for (i = 0; i < adev->num_ip_blocks; i++) {
- if (!adev->ip_blocks[i].status.valid)
+ if (!adev->ip_blocks[i].status.hw)
continue;
if (adev->ip_blocks[i].version->funcs->late_init) {
r = adev->ip_blocks[i].version->funcs->late_init((void *)adev);
@@ -1732,8 +1820,8 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
adev->ip_blocks[i].version->funcs->name, r);
return r;
}
- adev->ip_blocks[i].status.late_initialized = true;
}
+ adev->ip_blocks[i].status.late_initialized = true;
}
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
@@ -1803,6 +1891,7 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
continue;
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC) {
+ amdgpu_ucode_free_bo(adev);
amdgpu_free_static_csa(adev);
amdgpu_device_wb_fini(adev);
amdgpu_device_vram_scratch_fini(adev);
@@ -1833,6 +1922,43 @@ static int amdgpu_device_ip_fini(struct amdgpu_device *adev)
return 0;
}
+static int amdgpu_device_enable_mgpu_fan_boost(void)
+{
+ struct amdgpu_gpu_instance *gpu_ins;
+ struct amdgpu_device *adev;
+ int i, ret = 0;
+
+ mutex_lock(&mgpu_info.mutex);
+
+ /*
+ * MGPU fan boost feature should be enabled
+ * only when there are two or more dGPUs in
+ * the system
+ */
+ if (mgpu_info.num_dgpu < 2)
+ goto out;
+
+ for (i = 0; i < mgpu_info.num_dgpu; i++) {
+ gpu_ins = &(mgpu_info.gpu_ins[i]);
+ adev = gpu_ins->adev;
+ if (!(adev->flags & AMD_IS_APU) &&
+ !gpu_ins->mgpu_fan_enabled &&
+ adev->powerplay.pp_funcs &&
+ adev->powerplay.pp_funcs->enable_mgpu_fan_boost) {
+ ret = amdgpu_dpm_enable_mgpu_fan_boost(adev);
+ if (ret)
+ break;
+
+ gpu_ins->mgpu_fan_enabled = 1;
+ }
+ }
+
+out:
+ mutex_unlock(&mgpu_info.mutex);
+
+ return ret;
+}
+
/**
* amdgpu_device_ip_late_init_func_handler - work handler for ib test
*
@@ -1847,6 +1973,10 @@ static void amdgpu_device_ip_late_init_func_handler(struct work_struct *work)
r = amdgpu_ib_ring_tests(adev);
if (r)
DRM_ERROR("ib ring test failed (%d).\n", r);
+
+ r = amdgpu_device_enable_mgpu_fan_boost();
+ if (r)
+ DRM_ERROR("enable mgpu fan boost failed (%d).\n", r);
}
static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
@@ -2082,7 +2212,8 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
continue;
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
- adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH)
+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
continue;
r = adev->ip_blocks[i].version->funcs->resume(adev);
if (r) {
@@ -2114,6 +2245,11 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
r = amdgpu_device_ip_resume_phase1(adev);
if (r)
return r;
+
+ r = amdgpu_device_fw_loading(adev);
+ if (r)
+ return r;
+
r = amdgpu_device_ip_resume_phase2(adev);
return r;
@@ -2608,6 +2744,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
return 0;
+ adev->in_suspend = true;
drm_kms_helper_poll_disable(dev);
if (fbcon)
@@ -2793,6 +2930,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
#ifdef CONFIG_PM
dev->dev->power.disable_depth--;
#endif
+ adev->in_suspend = false;
+
return 0;
}
@@ -3061,6 +3200,10 @@ retry:
if (r)
goto out;
+ r = amdgpu_device_fw_loading(adev);
+ if (r)
+ return r;
+
r = amdgpu_device_ip_resume_phase2(adev);
if (r)
goto out;
@@ -3117,6 +3260,10 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
/* we need recover gart prior to run SMC/CP/SDMA resume */
amdgpu_gtt_mgr_recover(&adev->mman.bdev.man[TTM_PL_TT]);
+ r = amdgpu_device_fw_loading(adev);
+ if (r)
+ return r;
+
/* now we are okay to resume SMC/CP/SDMA */
r = amdgpu_device_ip_reinit_late_sriov(adev);
if (r)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index ff24e1cc5b65..f972cd156795 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -278,6 +278,9 @@ enum amdgpu_pcie_gen {
#define amdgpu_dpm_get_fan_speed_rpm(adev, s) \
((adev)->powerplay.pp_funcs->get_fan_speed_rpm)((adev)->powerplay.pp_handle, (s))
+#define amdgpu_dpm_set_fan_speed_rpm(adev, s) \
+ ((adev)->powerplay.pp_funcs->set_fan_speed_rpm)((adev)->powerplay.pp_handle, (s))
+
#define amdgpu_dpm_get_sclk(adev, l) \
((adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)))
@@ -357,6 +360,10 @@ enum amdgpu_pcie_gen {
((adev)->powerplay.pp_funcs->odn_edit_dpm_table(\
(adev)->powerplay.pp_handle, type, parameter, size))
+#define amdgpu_dpm_enable_mgpu_fan_boost(adev) \
+ ((adev)->powerplay.pp_funcs->enable_mgpu_fan_boost(\
+ (adev)->powerplay.pp_handle))
+
struct amdgpu_dpm {
struct amdgpu_ps *ps;
/* number of valid power states */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 723f0f7754bd..28781414d71c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -127,6 +127,9 @@ int amdgpu_compute_multipipe = -1;
int amdgpu_gpu_recovery = -1; /* auto */
int amdgpu_emu_mode = 0;
uint amdgpu_smu_memory_pool_size = 0;
+struct amdgpu_mgpu_info mgpu_info = {
+ .mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),
+};
/**
* DOC: vramlimit (int)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index f172e92c463c..b61b5c11aead 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -297,8 +297,7 @@ struct amdgpu_gfx {
/* reset mask */
uint32_t grbm_soft_reset;
uint32_t srbm_soft_reset;
- /* s3/s4 mask */
- bool in_suspend;
+
/* NGG */
struct amdgpu_ngg ngg;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 9a5b252784a1..d73367cab4f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -146,6 +146,8 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
{
const uint64_t four_gb = 0x100000000ULL;
u64 size_af, size_bf;
+ /*To avoid the hole, limit the max mc address to AMDGPU_GMC_HOLE_START*/
+ u64 max_mc_address = min(adev->gmc.mc_mask, AMDGPU_GMC_HOLE_START - 1);
mc->gart_size += adev->pm.smu_prv_buffer_size;
@@ -153,7 +155,7 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
* the GART base on a 4GB boundary as well.
*/
size_bf = mc->fb_start;
- size_af = adev->gmc.mc_mask + 1 - ALIGN(mc->fb_end + 1, four_gb);
+ size_af = max_mc_address + 1 - ALIGN(mc->fb_end + 1, four_gb);
if (mc->gart_size > max(size_bf, size_af)) {
dev_warn(adev->dev, "limiting GART\n");
@@ -164,7 +166,7 @@ void amdgpu_gmc_gart_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
(size_af < mc->gart_size))
mc->gart_start = 0;
else
- mc->gart_start = mc->mc_mask - mc->gart_size + 1;
+ mc->gart_start = max_mc_address - mc->gart_size + 1;
mc->gart_start &= ~(four_gb - 1);
mc->gart_end = mc->gart_start + mc->gart_size - 1;
@@ -200,16 +202,13 @@ void amdgpu_gmc_agp_location(struct amdgpu_device *adev, struct amdgpu_gmc *mc)
}
if (size_bf > size_af) {
- mc->agp_start = mc->fb_start > mc->gart_start ?
- mc->gart_end + 1 : 0;
+ mc->agp_start = (mc->fb_start - size_bf) & sixteen_gb_mask;
mc->agp_size = size_bf;
} else {
- mc->agp_start = (mc->fb_start > mc->gart_start ?
- mc->fb_end : mc->gart_end) + 1,
+ mc->agp_start = ALIGN(mc->fb_end + 1, sixteen_gb);
mc->agp_size = size_af;
}
- mc->agp_start = ALIGN(mc->agp_start, sixteen_gb);
mc->agp_end = mc->agp_start + mc->agp_size - 1;
dev_info(adev->dev, "AGP: %lluM 0x%016llX - 0x%016llX\n",
mc->agp_size >> 20, mc->agp_start, mc->agp_end);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 47817e00f54f..b8963b725dfa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -354,6 +354,14 @@ int amdgpu_ib_ring_tests(struct amdgpu_device *adev)
if (!ring || !ring->ready)
continue;
+ /* skip IB tests for KIQ in general for the below reasons:
+ * 1. We never submit IBs to the KIQ
+ * 2. KIQ doesn't use the EOP interrupts,
+ * we use some other CP interrupt.
+ */
+ if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ)
+ continue;
+
/* MM engine need more time */
if (ring->funcs->type == AMDGPU_RING_TYPE_UVD ||
ring->funcs->type == AMDGPU_RING_TYPE_VCE ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index a64056dadc58..81732a84c2ab 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -40,6 +40,30 @@
#include "amdgpu_gem.h"
#include "amdgpu_display.h"
+static void amdgpu_unregister_gpu_instance(struct amdgpu_device *adev)
+{
+ struct amdgpu_gpu_instance *gpu_instance;
+ int i;
+
+ mutex_lock(&mgpu_info.mutex);
+
+ for (i = 0; i < mgpu_info.num_gpu; i++) {
+ gpu_instance = &(mgpu_info.gpu_ins[i]);
+ if (gpu_instance->adev == adev) {
+ mgpu_info.gpu_ins[i] =
+ mgpu_info.gpu_ins[mgpu_info.num_gpu - 1];
+ mgpu_info.num_gpu--;
+ if (adev->flags & AMD_IS_APU)
+ mgpu_info.num_apu--;
+ else
+ mgpu_info.num_dgpu--;
+ break;
+ }
+ }
+
+ mutex_unlock(&mgpu_info.mutex);
+}
+
/**
* amdgpu_driver_unload_kms - Main unload function for KMS.
*
@@ -55,6 +79,8 @@ void amdgpu_driver_unload_kms(struct drm_device *dev)
if (adev == NULL)
return;
+ amdgpu_unregister_gpu_instance(adev);
+
if (adev->rmmio == NULL)
goto done_free;
@@ -75,6 +101,31 @@ done_free:
dev->dev_private = NULL;
}
+static void amdgpu_register_gpu_instance(struct amdgpu_device *adev)
+{
+ struct amdgpu_gpu_instance *gpu_instance;
+
+ mutex_lock(&mgpu_info.mutex);
+
+ if (mgpu_info.num_gpu >= MAX_GPU_INSTANCE) {
+ DRM_ERROR("Cannot register more gpu instance\n");
+ mutex_unlock(&mgpu_info.mutex);
+ return;
+ }
+
+ gpu_instance = &(mgpu_info.gpu_ins[mgpu_info.num_gpu]);
+ gpu_instance->adev = adev;
+ gpu_instance->mgpu_fan_enabled = 0;
+
+ mgpu_info.num_gpu++;
+ if (adev->flags & AMD_IS_APU)
+ mgpu_info.num_apu++;
+ else
+ mgpu_info.num_dgpu++;
+
+ mutex_unlock(&mgpu_info.mutex);
+}
+
/**
* amdgpu_driver_load_kms - Main load function for KMS.
*
@@ -169,6 +220,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
pm_runtime_put_autosuspend(dev->dev);
}
+ amdgpu_register_gpu_instance(adev);
out:
if (r) {
/* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
index 18d989e0e362..94055a485e01 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
@@ -1120,12 +1120,19 @@ static ssize_t amdgpu_hwmon_set_pwm1(struct device *dev,
struct amdgpu_device *adev = dev_get_drvdata(dev);
int err;
u32 value;
+ u32 pwm_mode;
/* Can't adjust fan when the card is off */
if ((adev->flags & AMD_IS_PX) &&
(adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON))
return -EINVAL;
+ pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
+ if (pwm_mode != AMD_FAN_CTRL_MANUAL) {
+ pr_info("manual fan speed control should be enabled first\n");
+ return -EINVAL;
+ }
+
err = kstrtou32(buf, 10, &value);
if (err)
return err;
@@ -1187,6 +1194,148 @@ static ssize_t amdgpu_hwmon_get_fan1_input(struct device *dev,
return sprintf(buf, "%i\n", speed);
}
+static ssize_t amdgpu_hwmon_get_fan1_min(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ u32 min_rpm = 0;
+ u32 size = sizeof(min_rpm);
+ int r;
+
+ if (!adev->powerplay.pp_funcs->read_sensor)
+ return -EINVAL;
+
+ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MIN_FAN_RPM,
+ (void *)&min_rpm, &size);
+ if (r)
+ return r;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", min_rpm);
+}
+
+static ssize_t amdgpu_hwmon_get_fan1_max(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ u32 max_rpm = 0;
+ u32 size = sizeof(max_rpm);
+ int r;
+
+ if (!adev->powerplay.pp_funcs->read_sensor)
+ return -EINVAL;
+
+ r = amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_MAX_FAN_RPM,
+ (void *)&max_rpm, &size);
+ if (r)
+ return r;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", max_rpm);
+}
+
+static ssize_t amdgpu_hwmon_get_fan1_target(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ int err;
+ u32 rpm = 0;
+
+ /* Can't adjust fan when the card is off */
+ if ((adev->flags & AMD_IS_PX) &&
+ (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+ return -EINVAL;
+
+ if (adev->powerplay.pp_funcs->get_fan_speed_rpm) {
+ err = amdgpu_dpm_get_fan_speed_rpm(adev, &rpm);
+ if (err)
+ return err;
+ }
+
+ return sprintf(buf, "%i\n", rpm);
+}
+
+static ssize_t amdgpu_hwmon_set_fan1_target(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ int err;
+ u32 value;
+ u32 pwm_mode;
+
+ pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
+ if (pwm_mode != AMD_FAN_CTRL_MANUAL)
+ return -ENODATA;
+
+ /* Can't adjust fan when the card is off */
+ if ((adev->flags & AMD_IS_PX) &&
+ (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+ return -EINVAL;
+
+ err = kstrtou32(buf, 10, &value);
+ if (err)
+ return err;
+
+ if (adev->powerplay.pp_funcs->set_fan_speed_rpm) {
+ err = amdgpu_dpm_set_fan_speed_rpm(adev, value);
+ if (err)
+ return err;
+ }
+
+ return count;
+}
+
+static ssize_t amdgpu_hwmon_get_fan1_enable(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ u32 pwm_mode = 0;
+
+ if (!adev->powerplay.pp_funcs->get_fan_control_mode)
+ return -EINVAL;
+
+ pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
+
+ return sprintf(buf, "%i\n", pwm_mode == AMD_FAN_CTRL_AUTO ? 0 : 1);
+}
+
+static ssize_t amdgpu_hwmon_set_fan1_enable(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ struct amdgpu_device *adev = dev_get_drvdata(dev);
+ int err;
+ int value;
+ u32 pwm_mode;
+
+ /* Can't adjust fan when the card is off */
+ if ((adev->flags & AMD_IS_PX) &&
+ (adev->ddev->switch_power_state != DRM_SWITCH_POWER_ON))
+ return -EINVAL;
+
+ if (!adev->powerplay.pp_funcs->set_fan_control_mode)
+ return -EINVAL;
+
+ err = kstrtoint(buf, 10, &value);
+ if (err)
+ return err;
+
+ if (value == 0)
+ pwm_mode = AMD_FAN_CTRL_AUTO;
+ else if (value == 1)
+ pwm_mode = AMD_FAN_CTRL_MANUAL;
+ else
+ return -EINVAL;
+
+ amdgpu_dpm_set_fan_control_mode(adev, pwm_mode);
+
+ return count;
+}
+
static ssize_t amdgpu_hwmon_show_vddgfx(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -1406,8 +1555,16 @@ static ssize_t amdgpu_hwmon_set_power_cap(struct device *dev,
*
* - pwm1_max: pulse width modulation fan control maximum level (255)
*
+ * - fan1_min: an minimum value Unit: revolution/min (RPM)
+ *
+ * - fan1_max: an maxmum value Unit: revolution/max (RPM)
+ *
* - fan1_input: fan speed in RPM
*
+ * - fan[1-*]_target: Desired fan speed Unit: revolution/min (RPM)
+ *
+ * - fan[1-*]_enable: Enable or disable the sensors.1: Enable 0: Disable
+ *
* You can use hwmon tools like sensors to view this information on your system.
*
*/
@@ -1420,6 +1577,10 @@ static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_pwm1_
static SENSOR_DEVICE_ATTR(pwm1_min, S_IRUGO, amdgpu_hwmon_get_pwm1_min, NULL, 0);
static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO, amdgpu_hwmon_get_pwm1_max, NULL, 0);
static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, amdgpu_hwmon_get_fan1_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, amdgpu_hwmon_get_fan1_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO, amdgpu_hwmon_get_fan1_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_target, amdgpu_hwmon_set_fan1_target, 0);
+static SENSOR_DEVICE_ATTR(fan1_enable, S_IRUGO | S_IWUSR, amdgpu_hwmon_get_fan1_enable, amdgpu_hwmon_set_fan1_enable, 0);
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, amdgpu_hwmon_show_vddgfx, NULL, 0);
static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, amdgpu_hwmon_show_vddgfx_label, NULL, 0);
static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, amdgpu_hwmon_show_vddnb, NULL, 0);
@@ -1438,6 +1599,10 @@ static struct attribute *hwmon_attributes[] = {
&sensor_dev_attr_pwm1_min.dev_attr.attr,
&sensor_dev_attr_pwm1_max.dev_attr.attr,
&sensor_dev_attr_fan1_input.dev_attr.attr,
+ &sensor_dev_attr_fan1_min.dev_attr.attr,
+ &sensor_dev_attr_fan1_max.dev_attr.attr,
+ &sensor_dev_attr_fan1_target.dev_attr.attr,
+ &sensor_dev_attr_fan1_enable.dev_attr.attr,
&sensor_dev_attr_in0_input.dev_attr.attr,
&sensor_dev_attr_in0_label.dev_attr.attr,
&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -1456,13 +1621,16 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
struct amdgpu_device *adev = dev_get_drvdata(dev);
umode_t effective_mode = attr->mode;
-
/* Skip fan attributes if fan is not present */
if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
attr == &sensor_dev_attr_pwm1_min.dev_attr.attr ||
- attr == &sensor_dev_attr_fan1_input.dev_attr.attr))
+ attr == &sensor_dev_attr_fan1_input.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_min.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_target.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_enable.dev_attr.attr))
return 0;
/* Skip limit attributes if DPM is not enabled */
@@ -1472,7 +1640,12 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
attr == &sensor_dev_attr_pwm1.dev_attr.attr ||
attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr ||
attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
- attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
+ attr == &sensor_dev_attr_pwm1_min.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_input.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_min.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_target.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_enable.dev_attr.attr))
return 0;
/* mask fan attributes if we have no bindings for this asic to expose */
@@ -1497,10 +1670,18 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
/* hide max/min values if we can't both query and manage the fan */
if ((!adev->powerplay.pp_funcs->set_fan_speed_percent &&
!adev->powerplay.pp_funcs->get_fan_speed_percent) &&
+ (!adev->powerplay.pp_funcs->set_fan_speed_rpm &&
+ !adev->powerplay.pp_funcs->get_fan_speed_rpm) &&
(attr == &sensor_dev_attr_pwm1_max.dev_attr.attr ||
attr == &sensor_dev_attr_pwm1_min.dev_attr.attr))
return 0;
+ if ((!adev->powerplay.pp_funcs->set_fan_speed_rpm &&
+ !adev->powerplay.pp_funcs->get_fan_speed_rpm) &&
+ (attr == &sensor_dev_attr_fan1_max.dev_attr.attr ||
+ attr == &sensor_dev_attr_fan1_min.dev_attr.attr))
+ return 0;
+
/* only APUs have vddnb */
if (!(adev->flags & AMD_IS_APU) &&
(attr == &sensor_dev_attr_in1_input.dev_attr.attr ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index bd397d2916fb..25d2f3e757f1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -452,8 +452,6 @@ static int psp_hw_fini(void *handle)
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
return 0;
- amdgpu_ucode_fini_bo(adev);
-
psp_ring_destroy(psp, PSP_RING_TYPE__KM);
amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
index d17503f0df8e..500113ec65ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.h
@@ -46,10 +46,6 @@ struct amdgpu_sdma_instance {
struct amdgpu_sdma {
struct amdgpu_sdma_instance instance[AMDGPU_MAX_SDMA_INSTANCES];
-#ifdef CONFIG_DRM_AMDGPU_SI
- //SI DMA has a difference trap irq number for the second engine
- struct amdgpu_irq_src trap_irq_1;
-#endif
struct amdgpu_irq_src trap_irq;
struct amdgpu_irq_src illegal_inst_irq;
int num_instances;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
index 1fa8bc337859..7b33867036e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
@@ -297,10 +297,7 @@ amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type)
case CHIP_POLARIS11:
case CHIP_POLARIS12:
case CHIP_VEGAM:
- if (!load_type)
- return AMDGPU_FW_LOAD_DIRECT;
- else
- return AMDGPU_FW_LOAD_SMU;
+ return AMDGPU_FW_LOAD_SMU;
case CHIP_VEGA10:
case CHIP_RAVEN:
case CHIP_VEGA12:
@@ -423,32 +420,41 @@ static int amdgpu_ucode_patch_jt(struct amdgpu_firmware_info *ucode,
return 0;
}
-int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
+int amdgpu_ucode_create_bo(struct amdgpu_device *adev)
{
- uint64_t fw_offset = 0;
- int i, err;
- struct amdgpu_firmware_info *ucode = NULL;
- const struct common_firmware_header *header = NULL;
-
- if (!adev->firmware.fw_size) {
- dev_warn(adev->dev, "No ip firmware need to load\n");
- return 0;
- }
-
- if (!adev->in_gpu_reset) {
- err = amdgpu_bo_create_kernel(adev, adev->firmware.fw_size, PAGE_SIZE,
- amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
- &adev->firmware.fw_buf,
- &adev->firmware.fw_buf_mc,
- &adev->firmware.fw_buf_ptr);
- if (err) {
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT) {
+ amdgpu_bo_create_kernel(adev, adev->firmware.fw_size, PAGE_SIZE,
+ amdgpu_sriov_vf(adev) ? AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
+ &adev->firmware.fw_buf,
+ &adev->firmware.fw_buf_mc,
+ &adev->firmware.fw_buf_ptr);
+ if (!adev->firmware.fw_buf) {
dev_err(adev->dev, "failed to create kernel buffer for firmware.fw_buf\n");
- goto failed;
+ return -ENOMEM;
+ } else if (amdgpu_sriov_vf(adev)) {
+ memset(adev->firmware.fw_buf_ptr, 0, adev->firmware.fw_size);
}
}
+ return 0;
+}
+
+void amdgpu_ucode_free_bo(struct amdgpu_device *adev)
+{
+ if (adev->firmware.load_type != AMDGPU_FW_LOAD_DIRECT)
+ amdgpu_bo_free_kernel(&adev->firmware.fw_buf,
+ &adev->firmware.fw_buf_mc,
+ &adev->firmware.fw_buf_ptr);
+}
- memset(adev->firmware.fw_buf_ptr, 0, adev->firmware.fw_size);
+int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
+{
+ uint64_t fw_offset = 0;
+ int i;
+ struct amdgpu_firmware_info *ucode = NULL;
+ /* for baremetal, the ucode is allocated in gtt, so don't need to fill the bo when reset/suspend */
+ if (!amdgpu_sriov_vf(adev) && (adev->in_gpu_reset || adev->in_suspend))
+ return 0;
/*
* if SMU loaded firmware, it needn't add SMC, UVD, and VCE
* ucode info here
@@ -465,7 +471,6 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
for (i = 0; i < adev->firmware.max_ucodes; i++) {
ucode = &adev->firmware.ucode[i];
if (ucode->fw) {
- header = (const struct common_firmware_header *)ucode->fw->data;
amdgpu_ucode_init_single_fw(adev, ucode, adev->firmware.fw_buf_mc + fw_offset,
adev->firmware.fw_buf_ptr + fw_offset);
if (i == AMDGPU_UCODE_ID_CP_MEC1 &&
@@ -480,33 +485,4 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
}
}
return 0;
-
-failed:
- if (err)
- adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT;
-
- return err;
-}
-
-int amdgpu_ucode_fini_bo(struct amdgpu_device *adev)
-{
- int i;
- struct amdgpu_firmware_info *ucode = NULL;
-
- if (!adev->firmware.fw_size)
- return 0;
-
- for (i = 0; i < adev->firmware.max_ucodes; i++) {
- ucode = &adev->firmware.ucode[i];
- if (ucode->fw) {
- ucode->mc_addr = 0;
- ucode->kaddr = NULL;
- }
- }
-
- amdgpu_bo_free_kernel(&adev->firmware.fw_buf,
- &adev->firmware.fw_buf_mc,
- &adev->firmware.fw_buf_ptr);
-
- return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 8f3f1117728c..aa6641b944a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -276,8 +276,10 @@ void amdgpu_ucode_print_gpu_info_hdr(const struct common_firmware_header *hdr);
int amdgpu_ucode_validate(const struct firmware *fw);
bool amdgpu_ucode_hdr_version(union amdgpu_firmware_header *hdr,
uint16_t hdr_major, uint16_t hdr_minor);
+
int amdgpu_ucode_init_bo(struct amdgpu_device *adev);
-int amdgpu_ucode_fini_bo(struct amdgpu_device *adev);
+int amdgpu_ucode_create_bo(struct amdgpu_device *adev);
+void amdgpu_ucode_free_bo(struct amdgpu_device *adev);
enum amdgpu_firmware_load_type
amdgpu_ucode_get_load_type(struct amdgpu_device *adev, int load_type);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 0cc5190f4f36..5f3f54073818 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -258,6 +258,8 @@ int amdgpu_vce_suspend(struct amdgpu_device *adev)
{
int i;
+ cancel_delayed_work_sync(&adev->vce.idle_work);
+
if (adev->vce.vcpu_bo == NULL)
return 0;
@@ -268,7 +270,6 @@ int amdgpu_vce_suspend(struct amdgpu_device *adev)
if (i == AMDGPU_MAX_VCE_HANDLES)
return 0;
- cancel_delayed_work_sync(&adev->vce.idle_work);
/* TODO: suspending running encoding sessions isn't supported */
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 2a2eb0143f48..27da13df2f11 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -121,8 +121,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev)
version_major, version_minor, family_id);
}
- bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_HEAP_SIZE
- + AMDGPU_VCN_SESSION_SIZE * 40;
+ bo_size = AMDGPU_VCN_STACK_SIZE + AMDGPU_VCN_CONTEXT_SIZE;
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
bo_size += AMDGPU_GPU_PAGE_ALIGN(le32_to_cpu(hdr->ucode_size_bytes) + 8);
r = amdgpu_bo_create_kernel(adev, bo_size, PAGE_SIZE,
@@ -163,11 +162,11 @@ int amdgpu_vcn_suspend(struct amdgpu_device *adev)
unsigned size;
void *ptr;
+ cancel_delayed_work_sync(&adev->vcn.idle_work);
+
if (adev->vcn.vcpu_bo == NULL)
return 0;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
-
size = amdgpu_bo_size(adev->vcn.vcpu_bo);
ptr = adev->vcn.cpu_addr;
@@ -263,7 +262,7 @@ static int amdgpu_vcn_pause_dpg_mode(struct amdgpu_device *adev,
ring = &adev->vcn.ring_dec;
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
- lower_32_bits(ring->wptr) | 0x80000000);
+ RREG32_SOC15(UVD, 0, mmUVD_SCRATCH2));
SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
@@ -309,18 +308,21 @@ static int amdgpu_vcn_pause_dpg_mode(struct amdgpu_device *adev,
/* Restore */
ring = &adev->vcn.ring_jpeg;
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
- WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, 0x00000001L | 0x00000002L);
+ WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL,
+ UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
+ UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW,
- lower_32_bits(ring->gpu_addr));
+ lower_32_bits(ring->gpu_addr));
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH,
- upper_32_bits(ring->gpu_addr));
+ upper_32_bits(ring->gpu_addr));
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR, ring->wptr);
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, ring->wptr);
- WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L);
+ WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL,
+ UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
ring = &adev->vcn.ring_dec;
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
- lower_32_bits(ring->wptr) | 0x80000000);
+ RREG32_SOC15(UVD, 0, mmUVD_SCRATCH2));
SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
UVD_PGFSM_CONFIG__UVDM_UVDU_PWR_ON,
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 0b88a4672da5..a0ad19af9080 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -24,9 +24,9 @@
#ifndef __AMDGPU_VCN_H__
#define __AMDGPU_VCN_H__
-#define AMDGPU_VCN_STACK_SIZE (200*1024)
-#define AMDGPU_VCN_HEAP_SIZE (256*1024)
-#define AMDGPU_VCN_SESSION_SIZE (50*1024)
+#define AMDGPU_VCN_STACK_SIZE (128*1024)
+#define AMDGPU_VCN_CONTEXT_SIZE (512*1024)
+
#define AMDGPU_VCN_FIRMWARE_OFFSET 256
#define AMDGPU_VCN_MAX_ENC_RINGS 3
diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c
index 78ab939ae5d8..f41f5f57e9f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/cik.c
+++ b/drivers/gpu/drm/amd/amdgpu/cik.c
@@ -2002,6 +2002,8 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v7_0_ip_block);
amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v7_2_ip_block);
+ amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
if (amdgpu_dpm == -1)
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
else
@@ -2014,8 +2016,6 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v8_2_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v7_2_ip_block);
- amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &uvd_v4_2_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v2_0_ip_block);
break;
@@ -2023,6 +2023,8 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v7_0_ip_block);
amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v7_3_ip_block);
+ amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
if (amdgpu_dpm == -1)
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
else
@@ -2035,8 +2037,6 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v8_5_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v7_3_ip_block);
- amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &uvd_v4_2_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v2_0_ip_block);
break;
@@ -2044,6 +2044,8 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v7_0_ip_block);
amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v7_1_ip_block);
+ amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -2053,8 +2055,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v8_1_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v7_1_ip_block);
- amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
+
amdgpu_device_ip_block_add(adev, &uvd_v4_2_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v2_0_ip_block);
break;
@@ -2063,6 +2064,8 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &cik_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v7_0_ip_block);
amdgpu_device_ip_block_add(adev, &cik_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v7_2_ip_block);
+ amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &kv_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -2072,8 +2075,6 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v8_3_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v7_2_ip_block);
- amdgpu_device_ip_block_add(adev, &cik_sdma_ip_block);
amdgpu_device_ip_block_add(adev, &uvd_v4_2_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v2_0_ip_block);
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 2aeef2bb93a4..3d0f277a6523 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -1173,64 +1173,61 @@ static int gfx_v8_0_init_microcode(struct amdgpu_device *adev)
}
}
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_PFP];
- info->ucode_id = AMDGPU_UCODE_ID_CP_PFP;
- info->fw = adev->gfx.pfp_fw;
- header = (const struct common_firmware_header *)info->fw->data;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
-
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_ME];
- info->ucode_id = AMDGPU_UCODE_ID_CP_ME;
- info->fw = adev->gfx.me_fw;
- header = (const struct common_firmware_header *)info->fw->data;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
-
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_CE];
- info->ucode_id = AMDGPU_UCODE_ID_CP_CE;
- info->fw = adev->gfx.ce_fw;
- header = (const struct common_firmware_header *)info->fw->data;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_PFP];
+ info->ucode_id = AMDGPU_UCODE_ID_CP_PFP;
+ info->fw = adev->gfx.pfp_fw;
+ header = (const struct common_firmware_header *)info->fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_ME];
+ info->ucode_id = AMDGPU_UCODE_ID_CP_ME;
+ info->fw = adev->gfx.me_fw;
+ header = (const struct common_firmware_header *)info->fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_CE];
+ info->ucode_id = AMDGPU_UCODE_ID_CP_CE;
+ info->fw = adev->gfx.ce_fw;
+ header = (const struct common_firmware_header *)info->fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
+ info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
+ info->fw = adev->gfx.rlc_fw;
+ header = (const struct common_firmware_header *)info->fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
+ info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1;
+ info->fw = adev->gfx.mec_fw;
+ header = (const struct common_firmware_header *)info->fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+
+ /* we need account JT in */
+ cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_RLC_G];
- info->ucode_id = AMDGPU_UCODE_ID_RLC_G;
- info->fw = adev->gfx.rlc_fw;
- header = (const struct common_firmware_header *)info->fw->data;
+ if (amdgpu_sriov_vf(adev)) {
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE];
+ info->ucode_id = AMDGPU_UCODE_ID_STORAGE;
+ info->fw = adev->gfx.mec_fw;
adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+ ALIGN(le32_to_cpu(64 * PAGE_SIZE), PAGE_SIZE);
+ }
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC1];
- info->ucode_id = AMDGPU_UCODE_ID_CP_MEC1;
- info->fw = adev->gfx.mec_fw;
+ if (adev->gfx.mec2_fw) {
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2];
+ info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
+ info->fw = adev->gfx.mec2_fw;
header = (const struct common_firmware_header *)info->fw->data;
adev->firmware.fw_size +=
ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
-
- /* we need account JT in */
- cp_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(cp_hdr->jt_size) << 2, PAGE_SIZE);
-
- if (amdgpu_sriov_vf(adev)) {
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_STORAGE];
- info->ucode_id = AMDGPU_UCODE_ID_STORAGE;
- info->fw = adev->gfx.mec_fw;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(64 * PAGE_SIZE), PAGE_SIZE);
- }
-
- if (adev->gfx.mec2_fw) {
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CP_MEC2];
- info->ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
- info->fw = adev->gfx.mec2_fw;
- header = (const struct common_firmware_header *)info->fw->data;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
- }
-
}
out:
@@ -2048,11 +2045,6 @@ static int gfx_v8_0_sw_init(void *handle)
adev->gfx.mec.num_pipe_per_mec = 4;
adev->gfx.mec.num_queue_per_pipe = 8;
- /* KIQ event */
- r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_CP_INT_IB2, &adev->gfx.kiq.irq);
- if (r)
- return r;
-
/* EOP Event */
r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, VISLANDS30_IV_SRCID_CP_END_OF_PIPE, &adev->gfx.eop_irq);
if (r)
@@ -4181,45 +4173,11 @@ static void gfx_v8_0_rlc_start(struct amdgpu_device *adev)
udelay(50);
}
-static int gfx_v8_0_rlc_load_microcode(struct amdgpu_device *adev)
-{
- const struct rlc_firmware_header_v2_0 *hdr;
- const __le32 *fw_data;
- unsigned i, fw_size;
-
- if (!adev->gfx.rlc_fw)
- return -EINVAL;
-
- hdr = (const struct rlc_firmware_header_v2_0 *)adev->gfx.rlc_fw->data;
- amdgpu_ucode_print_rlc_hdr(&hdr->header);
-
- fw_data = (const __le32 *)(adev->gfx.rlc_fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
-
- WREG32(mmRLC_GPM_UCODE_ADDR, 0);
- for (i = 0; i < fw_size; i++)
- WREG32(mmRLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
- WREG32(mmRLC_GPM_UCODE_ADDR, adev->gfx.rlc_fw_version);
-
- return 0;
-}
-
static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev)
{
- int r;
-
gfx_v8_0_rlc_stop(adev);
gfx_v8_0_rlc_reset(adev);
gfx_v8_0_init_pg(adev);
-
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
- /* legacy rlc firmware loading */
- r = gfx_v8_0_rlc_load_microcode(adev);
- if (r)
- return r;
- }
-
gfx_v8_0_rlc_start(adev);
return 0;
@@ -4245,63 +4203,6 @@ static void gfx_v8_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
udelay(50);
}
-static int gfx_v8_0_cp_gfx_load_microcode(struct amdgpu_device *adev)
-{
- const struct gfx_firmware_header_v1_0 *pfp_hdr;
- const struct gfx_firmware_header_v1_0 *ce_hdr;
- const struct gfx_firmware_header_v1_0 *me_hdr;
- const __le32 *fw_data;
- unsigned i, fw_size;
-
- if (!adev->gfx.me_fw || !adev->gfx.pfp_fw || !adev->gfx.ce_fw)
- return -EINVAL;
-
- pfp_hdr = (const struct gfx_firmware_header_v1_0 *)
- adev->gfx.pfp_fw->data;
- ce_hdr = (const struct gfx_firmware_header_v1_0 *)
- adev->gfx.ce_fw->data;
- me_hdr = (const struct gfx_firmware_header_v1_0 *)
- adev->gfx.me_fw->data;
-
- amdgpu_ucode_print_gfx_hdr(&pfp_hdr->header);
- amdgpu_ucode_print_gfx_hdr(&ce_hdr->header);
- amdgpu_ucode_print_gfx_hdr(&me_hdr->header);
-
- gfx_v8_0_cp_gfx_enable(adev, false);
-
- /* PFP */
- fw_data = (const __le32 *)
- (adev->gfx.pfp_fw->data +
- le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
- fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
- WREG32(mmCP_PFP_UCODE_ADDR, 0);
- for (i = 0; i < fw_size; i++)
- WREG32(mmCP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
- WREG32(mmCP_PFP_UCODE_ADDR, adev->gfx.pfp_fw_version);
-
- /* CE */
- fw_data = (const __le32 *)
- (adev->gfx.ce_fw->data +
- le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
- fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
- WREG32(mmCP_CE_UCODE_ADDR, 0);
- for (i = 0; i < fw_size; i++)
- WREG32(mmCP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
- WREG32(mmCP_CE_UCODE_ADDR, adev->gfx.ce_fw_version);
-
- /* ME */
- fw_data = (const __le32 *)
- (adev->gfx.me_fw->data +
- le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
- fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
- WREG32(mmCP_ME_RAM_WADDR, 0);
- for (i = 0; i < fw_size; i++)
- WREG32(mmCP_ME_RAM_DATA, le32_to_cpup(fw_data++));
- WREG32(mmCP_ME_RAM_WADDR, adev->gfx.me_fw_version);
-
- return 0;
-}
-
static u32 gfx_v8_0_get_csb_size(struct amdgpu_device *adev)
{
u32 count = 0;
@@ -4501,52 +4402,6 @@ static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
udelay(50);
}
-static int gfx_v8_0_cp_compute_load_microcode(struct amdgpu_device *adev)
-{
- const struct gfx_firmware_header_v1_0 *mec_hdr;
- const __le32 *fw_data;
- unsigned i, fw_size;
-
- if (!adev->gfx.mec_fw)
- return -EINVAL;
-
- gfx_v8_0_cp_compute_enable(adev, false);
-
- mec_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec_fw->data;
- amdgpu_ucode_print_gfx_hdr(&mec_hdr->header);
-
- fw_data = (const __le32 *)
- (adev->gfx.mec_fw->data +
- le32_to_cpu(mec_hdr->header.ucode_array_offset_bytes));
- fw_size = le32_to_cpu(mec_hdr->header.ucode_size_bytes) / 4;
-
- /* MEC1 */
- WREG32(mmCP_MEC_ME1_UCODE_ADDR, 0);
- for (i = 0; i < fw_size; i++)
- WREG32(mmCP_MEC_ME1_UCODE_DATA, le32_to_cpup(fw_data+i));
- WREG32(mmCP_MEC_ME1_UCODE_ADDR, adev->gfx.mec_fw_version);
-
- /* Loading MEC2 firmware is only necessary if MEC2 should run different microcode than MEC1. */
- if (adev->gfx.mec2_fw) {
- const struct gfx_firmware_header_v1_0 *mec2_hdr;
-
- mec2_hdr = (const struct gfx_firmware_header_v1_0 *)adev->gfx.mec2_fw->data;
- amdgpu_ucode_print_gfx_hdr(&mec2_hdr->header);
-
- fw_data = (const __le32 *)
- (adev->gfx.mec2_fw->data +
- le32_to_cpu(mec2_hdr->header.ucode_array_offset_bytes));
- fw_size = le32_to_cpu(mec2_hdr->header.ucode_size_bytes) / 4;
-
- WREG32(mmCP_MEC_ME2_UCODE_ADDR, 0);
- for (i = 0; i < fw_size; i++)
- WREG32(mmCP_MEC_ME2_UCODE_DATA, le32_to_cpup(fw_data+i));
- WREG32(mmCP_MEC_ME2_UCODE_ADDR, adev->gfx.mec2_fw_version);
- }
-
- return 0;
-}
-
/* KIQ functions */
static void gfx_v8_0_kiq_setting(struct amdgpu_ring *ring)
{
@@ -4872,7 +4727,7 @@ static int gfx_v8_0_kcq_init_queue(struct amdgpu_ring *ring)
struct vi_mqd *mqd = ring->mqd_ptr;
int mqd_idx = ring - &adev->gfx.compute_ring[0];
- if (!adev->in_gpu_reset && !adev->gfx.in_suspend) {
+ if (!adev->in_gpu_reset && !adev->in_suspend) {
memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation));
((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
@@ -4980,17 +4835,6 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
if (!(adev->flags & AMD_IS_APU))
gfx_v8_0_enable_gui_idle_interrupt(adev, false);
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
- /* legacy firmware loading */
- r = gfx_v8_0_cp_gfx_load_microcode(adev);
- if (r)
- return r;
-
- r = gfx_v8_0_cp_compute_load_microcode(adev);
- if (r)
- return r;
- }
-
r = gfx_v8_0_kiq_resume(adev);
if (r)
return r;
@@ -5142,19 +4986,12 @@ static int gfx_v8_0_hw_fini(void *handle)
static int gfx_v8_0_suspend(void *handle)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- adev->gfx.in_suspend = true;
- return gfx_v8_0_hw_fini(adev);
+ return gfx_v8_0_hw_fini(handle);
}
static int gfx_v8_0_resume(void *handle)
{
- int r;
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- r = gfx_v8_0_hw_init(adev);
- adev->gfx.in_suspend = false;
- return r;
+ return gfx_v8_0_hw_init(handle);
}
static bool gfx_v8_0_check_soft_reset(void *handle)
@@ -7025,52 +6862,6 @@ static int gfx_v8_0_sq_irq(struct amdgpu_device *adev,
return 0;
}
-static int gfx_v8_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
- struct amdgpu_irq_src *src,
- unsigned int type,
- enum amdgpu_interrupt_state state)
-{
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
-
- switch (type) {
- case AMDGPU_CP_KIQ_IRQ_DRIVER0:
- WREG32_FIELD(CPC_INT_CNTL, GENERIC2_INT_ENABLE,
- state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);
- if (ring->me == 1)
- WREG32_FIELD_OFFSET(CP_ME1_PIPE0_INT_CNTL,
- ring->pipe,
- GENERIC2_INT_ENABLE,
- state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);
- else
- WREG32_FIELD_OFFSET(CP_ME2_PIPE0_INT_CNTL,
- ring->pipe,
- GENERIC2_INT_ENABLE,
- state == AMDGPU_IRQ_STATE_DISABLE ? 0 : 1);
- break;
- default:
- BUG(); /* kiq only support GENERIC2_INT now */
- break;
- }
- return 0;
-}
-
-static int gfx_v8_0_kiq_irq(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- struct amdgpu_iv_entry *entry)
-{
- u8 me_id, pipe_id, queue_id;
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
-
- me_id = (entry->ring_id & 0x0c) >> 2;
- pipe_id = (entry->ring_id & 0x03) >> 0;
- queue_id = (entry->ring_id & 0x70) >> 4;
- DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d, queue:%d\n",
- me_id, pipe_id, queue_id);
-
- amdgpu_fence_process(ring);
- return 0;
-}
-
static const struct amd_ip_funcs gfx_v8_0_ip_funcs = {
.name = "gfx_v8_0",
.early_init = gfx_v8_0_early_init,
@@ -7221,11 +7012,6 @@ static const struct amdgpu_irq_src_funcs gfx_v8_0_priv_inst_irq_funcs = {
.process = gfx_v8_0_priv_inst_irq,
};
-static const struct amdgpu_irq_src_funcs gfx_v8_0_kiq_irq_funcs = {
- .set = gfx_v8_0_kiq_set_interrupt_state,
- .process = gfx_v8_0_kiq_irq,
-};
-
static const struct amdgpu_irq_src_funcs gfx_v8_0_cp_ecc_error_irq_funcs = {
.set = gfx_v8_0_set_cp_ecc_int_state,
.process = gfx_v8_0_cp_ecc_error_irq,
@@ -7247,9 +7033,6 @@ static void gfx_v8_0_set_irq_funcs(struct amdgpu_device *adev)
adev->gfx.priv_inst_irq.num_types = 1;
adev->gfx.priv_inst_irq.funcs = &gfx_v8_0_priv_inst_irq_funcs;
- adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
- adev->gfx.kiq.irq.funcs = &gfx_v8_0_kiq_irq_funcs;
-
adev->gfx.cp_ecc_error_irq.num_types = 1;
adev->gfx.cp_ecc_error_irq.funcs = &gfx_v8_0_cp_ecc_error_irq_funcs;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 261bb051b14d..e61f6a3ca241 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -133,7 +133,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
};
static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
@@ -173,7 +176,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_1[] =
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0x00003120),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000000ff),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
};
static const struct soc15_reg_golden golden_settings_gc_9_1_rv1[] =
@@ -247,7 +253,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_2_1_vg12[] =
SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0xffff03ff, 0x01000107),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x00000000),
SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0x76325410),
- SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x01bd9f33, 0x01000000)
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x01bd9f33, 0x01000000),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+ SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
};
static const u32 GFX_RLC_SRM_INDEX_CNTL_ADDR_OFFSETS[] =
@@ -908,6 +917,50 @@ static void gfx_v9_0_get_csb_buffer(struct amdgpu_device *adev,
buffer[count++] = cpu_to_le32(0);
}
+static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
+{
+ struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
+ uint32_t pg_always_on_cu_num = 2;
+ uint32_t always_on_cu_num;
+ uint32_t i, j, k;
+ uint32_t mask, cu_bitmap, counter;
+
+ if (adev->flags & AMD_IS_APU)
+ always_on_cu_num = 4;
+ else if (adev->asic_type == CHIP_VEGA12)
+ always_on_cu_num = 8;
+ else
+ always_on_cu_num = 12;
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
+ for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
+ mask = 1;
+ cu_bitmap = 0;
+ counter = 0;
+ gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff);
+
+ for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
+ if (cu_info->bitmap[i][j] & mask) {
+ if (counter == pg_always_on_cu_num)
+ WREG32_SOC15(GC, 0, mmRLC_PG_ALWAYS_ON_CU_MASK, cu_bitmap);
+ if (counter < always_on_cu_num)
+ cu_bitmap |= mask;
+ else
+ break;
+ counter++;
+ }
+ mask <<= 1;
+ }
+
+ WREG32_SOC15(GC, 0, mmRLC_LB_ALWAYS_ACTIVE_CU_MASK, cu_bitmap);
+ cu_info->ao_cu_bitmap[i][j] = cu_bitmap;
+ }
+ }
+ gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ mutex_unlock(&adev->grbm_idx_mutex);
+}
+
static void gfx_v9_0_init_lbpw(struct amdgpu_device *adev)
{
uint32_t data;
@@ -941,8 +994,10 @@ static void gfx_v9_0_init_lbpw(struct amdgpu_device *adev)
data |= 0x00C00000;
WREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_7, data);
- /* set RLC_LB_ALWAYS_ACTIVE_CU_MASK = 0xFFF */
- WREG32_SOC15(GC, 0, mmRLC_LB_ALWAYS_ACTIVE_CU_MASK, 0xFFF);
+ /*
+ * RLC_LB_ALWAYS_ACTIVE_CU_MASK = 0xF (4 CUs AON for Raven),
+ * programmed in gfx_v9_0_init_always_on_cu_mask()
+ */
/* set RLC_LB_CNTL = 0x8000_0095, 31 bit is reserved,
* but used for RLC_LB_CNTL configuration */
@@ -951,6 +1006,57 @@ static void gfx_v9_0_init_lbpw(struct amdgpu_device *adev)
data |= REG_SET_FIELD(data, RLC_LB_CNTL, RESERVED, 0x80000);
WREG32_SOC15(GC, 0, mmRLC_LB_CNTL, data);
mutex_unlock(&adev->grbm_idx_mutex);
+
+ gfx_v9_0_init_always_on_cu_mask(adev);
+}
+
+static void gfx_v9_4_init_lbpw(struct amdgpu_device *adev)
+{
+ uint32_t data;
+
+ /* set mmRLC_LB_THR_CONFIG_1/2/3/4 */
+ WREG32_SOC15(GC, 0, mmRLC_LB_THR_CONFIG_1, 0x0000007F);
+ WREG32_SOC15(GC, 0, mmRLC_LB_THR_CONFIG_2, 0x033388F8);
+ WREG32_SOC15(GC, 0, mmRLC_LB_THR_CONFIG_3, 0x00000077);
+ WREG32_SOC15(GC, 0, mmRLC_LB_THR_CONFIG_4, (0x10 | 0x27 << 8 | 0x02FA << 16));
+
+ /* set mmRLC_LB_CNTR_INIT = 0x0000_0000 */
+ WREG32_SOC15(GC, 0, mmRLC_LB_CNTR_INIT, 0x00000000);
+
+ /* set mmRLC_LB_CNTR_MAX = 0x0000_0500 */
+ WREG32_SOC15(GC, 0, mmRLC_LB_CNTR_MAX, 0x00000800);
+
+ mutex_lock(&adev->grbm_idx_mutex);
+ /* set mmRLC_LB_INIT_CU_MASK thru broadcast mode to enable all SE/SH*/
+ gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
+
+ /* set mmRLC_LB_PARAMS = 0x003F_1006 */
+ data = REG_SET_FIELD(0, RLC_LB_PARAMS, FIFO_SAMPLES, 0x0003);
+ data |= REG_SET_FIELD(data, RLC_LB_PARAMS, PG_IDLE_SAMPLES, 0x0010);
+ data |= REG_SET_FIELD(data, RLC_LB_PARAMS, PG_IDLE_SAMPLE_INTERVAL, 0x033F);
+ WREG32_SOC15(GC, 0, mmRLC_LB_PARAMS, data);
+
+ /* set mmRLC_GPM_GENERAL_7[31-16] = 0x00C0 */
+ data = RREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_7);
+ data &= 0x0000FFFF;
+ data |= 0x00C00000;
+ WREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_7, data);
+
+ /*
+ * RLC_LB_ALWAYS_ACTIVE_CU_MASK = 0xFFF (12 CUs AON),
+ * programmed in gfx_v9_0_init_always_on_cu_mask()
+ */
+
+ /* set RLC_LB_CNTL = 0x8000_0095, 31 bit is reserved,
+ * but used for RLC_LB_CNTL configuration */
+ data = RLC_LB_CNTL__LB_CNT_SPIM_ACTIVE_MASK;
+ data |= REG_SET_FIELD(data, RLC_LB_CNTL, CU_MASK_USED_OFF_HYST, 0x09);
+ data |= REG_SET_FIELD(data, RLC_LB_CNTL, RESERVED, 0x80000);
+ WREG32_SOC15(GC, 0, mmRLC_LB_CNTL, data);
+ mutex_unlock(&adev->grbm_idx_mutex);
+
+ gfx_v9_0_init_always_on_cu_mask(adev);
}
static void gfx_v9_0_enable_lbpw(struct amdgpu_device *adev, bool enable)
@@ -1084,8 +1190,17 @@ static int gfx_v9_0_rlc_init(struct amdgpu_device *adev)
rv_init_cp_jump_table(adev);
amdgpu_bo_kunmap(adev->gfx.rlc.cp_table_obj);
amdgpu_bo_unreserve(adev->gfx.rlc.cp_table_obj);
+ }
+ switch (adev->asic_type) {
+ case CHIP_RAVEN:
gfx_v9_0_init_lbpw(adev);
+ break;
+ case CHIP_VEGA20:
+ gfx_v9_4_init_lbpw(adev);
+ break;
+ default:
+ break;
}
return 0;
@@ -1605,11 +1720,6 @@ static int gfx_v9_0_sw_init(void *handle)
adev->gfx.mec.num_pipe_per_mec = 4;
adev->gfx.mec.num_queue_per_pipe = 8;
- /* KIQ event */
- r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_IB2_INTERRUPT_PKT, &adev->gfx.kiq.irq);
- if (r)
- return r;
-
/* EOP Event */
r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_GRBM_CP, GFX_9_0__SRCID__CP_EOP_INTERRUPT, &adev->gfx.eop_irq);
if (r)
@@ -2403,7 +2513,8 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev)
return r;
}
- if (adev->asic_type == CHIP_RAVEN) {
+ if (adev->asic_type == CHIP_RAVEN ||
+ adev->asic_type == CHIP_VEGA20) {
if (amdgpu_lbpw != 0)
gfx_v9_0_enable_lbpw(adev, true);
else
@@ -3091,7 +3202,7 @@ static int gfx_v9_0_kcq_init_queue(struct amdgpu_ring *ring)
struct v9_mqd *mqd = ring->mqd_ptr;
int mqd_idx = ring - &adev->gfx.compute_ring[0];
- if (!adev->in_gpu_reset && !adev->gfx.in_suspend) {
+ if (!adev->in_gpu_reset && !adev->in_suspend) {
memset((void *)mqd, 0, sizeof(struct v9_mqd_allocation));
((struct v9_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
((struct v9_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
@@ -3310,7 +3421,7 @@ static int gfx_v9_0_hw_fini(void *handle)
/* Use deinitialize sequence from CAIL when unbinding device from driver,
* otherwise KIQ is hanging when binding back
*/
- if (!adev->in_gpu_reset && !adev->gfx.in_suspend) {
+ if (!adev->in_gpu_reset && !adev->in_suspend) {
mutex_lock(&adev->srbm_mutex);
soc15_grbm_select(adev, adev->gfx.kiq.ring.me,
adev->gfx.kiq.ring.pipe,
@@ -3330,20 +3441,12 @@ static int gfx_v9_0_hw_fini(void *handle)
static int gfx_v9_0_suspend(void *handle)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-
- adev->gfx.in_suspend = true;
- return gfx_v9_0_hw_fini(adev);
+ return gfx_v9_0_hw_fini(handle);
}
static int gfx_v9_0_resume(void *handle)
{
- struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- int r;
-
- r = gfx_v9_0_hw_init(adev);
- adev->gfx.in_suspend = false;
- return r;
+ return gfx_v9_0_hw_init(handle);
}
static bool gfx_v9_0_is_idle(void *handle)
@@ -4609,68 +4712,6 @@ static int gfx_v9_0_priv_inst_irq(struct amdgpu_device *adev,
return 0;
}
-static int gfx_v9_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
- struct amdgpu_irq_src *src,
- unsigned int type,
- enum amdgpu_interrupt_state state)
-{
- uint32_t tmp, target;
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
-
- if (ring->me == 1)
- target = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
- else
- target = SOC15_REG_OFFSET(GC, 0, mmCP_ME2_PIPE0_INT_CNTL);
- target += ring->pipe;
-
- switch (type) {
- case AMDGPU_CP_KIQ_IRQ_DRIVER0:
- if (state == AMDGPU_IRQ_STATE_DISABLE) {
- tmp = RREG32_SOC15(GC, 0, mmCPC_INT_CNTL);
- tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
- GENERIC2_INT_ENABLE, 0);
- WREG32_SOC15(GC, 0, mmCPC_INT_CNTL, tmp);
-
- tmp = RREG32(target);
- tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
- GENERIC2_INT_ENABLE, 0);
- WREG32(target, tmp);
- } else {
- tmp = RREG32_SOC15(GC, 0, mmCPC_INT_CNTL);
- tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
- GENERIC2_INT_ENABLE, 1);
- WREG32_SOC15(GC, 0, mmCPC_INT_CNTL, tmp);
-
- tmp = RREG32(target);
- tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
- GENERIC2_INT_ENABLE, 1);
- WREG32(target, tmp);
- }
- break;
- default:
- BUG(); /* kiq only support GENERIC2_INT now */
- break;
- }
- return 0;
-}
-
-static int gfx_v9_0_kiq_irq(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- struct amdgpu_iv_entry *entry)
-{
- u8 me_id, pipe_id, queue_id;
- struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
-
- me_id = (entry->ring_id & 0x0c) >> 2;
- pipe_id = (entry->ring_id & 0x03) >> 0;
- queue_id = (entry->ring_id & 0x70) >> 4;
- DRM_DEBUG("IH: CPC GENERIC2_INT, me:%d, pipe:%d, queue:%d\n",
- me_id, pipe_id, queue_id);
-
- amdgpu_fence_process(ring);
- return 0;
-}
-
static const struct amd_ip_funcs gfx_v9_0_ip_funcs = {
.name = "gfx_v9_0",
.early_init = gfx_v9_0_early_init,
@@ -4819,11 +4860,6 @@ static void gfx_v9_0_set_ring_funcs(struct amdgpu_device *adev)
adev->gfx.compute_ring[i].funcs = &gfx_v9_0_ring_funcs_compute;
}
-static const struct amdgpu_irq_src_funcs gfx_v9_0_kiq_irq_funcs = {
- .set = gfx_v9_0_kiq_set_interrupt_state,
- .process = gfx_v9_0_kiq_irq,
-};
-
static const struct amdgpu_irq_src_funcs gfx_v9_0_eop_irq_funcs = {
.set = gfx_v9_0_set_eop_interrupt_state,
.process = gfx_v9_0_eop_irq,
@@ -4849,9 +4885,6 @@ static void gfx_v9_0_set_irq_funcs(struct amdgpu_device *adev)
adev->gfx.priv_inst_irq.num_types = 1;
adev->gfx.priv_inst_irq.funcs = &gfx_v9_0_priv_inst_irq_funcs;
-
- adev->gfx.kiq.irq.num_types = AMDGPU_CP_KIQ_IRQ_LAST;
- adev->gfx.kiq.irq.funcs = &gfx_v9_0_kiq_irq_funcs;
}
static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 9217af00bc8d..3f3fac2d50cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -306,11 +306,8 @@ static int psp_v11_0_ring_stop(struct psp_context *psp,
enum psp_ring_type ring_type)
{
int ret = 0;
- struct psp_ring *ring;
struct amdgpu_device *adev = psp->adev;
- ring = &psp->km_ring;
-
/* Write the ring destroy command to C2PMSG_64 */
WREG32_SOC15(MP0, 0, mmMP0_SMN_C2PMSG_64, GFX_CTRL_CMD_ID_DESTROY_RINGS);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
index cd781abc4953..2d4770e173dd 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c
@@ -504,41 +504,6 @@ static int sdma_v2_4_rlc_resume(struct amdgpu_device *adev)
return 0;
}
-/**
- * sdma_v2_4_load_microcode - load the sDMA ME ucode
- *
- * @adev: amdgpu_device pointer
- *
- * Loads the sDMA0/1 ucode.
- * Returns 0 for success, -EINVAL if the ucode is not available.
- */
-static int sdma_v2_4_load_microcode(struct amdgpu_device *adev)
-{
- const struct sdma_firmware_header_v1_0 *hdr;
- const __le32 *fw_data;
- u32 fw_size;
- int i, j;
-
- /* halt the MEs */
- sdma_v2_4_enable(adev, false);
-
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (!adev->sdma.instance[i].fw)
- return -EINVAL;
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
- amdgpu_ucode_print_sdma_hdr(&hdr->header);
- fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- fw_data = (const __le32 *)
- (adev->sdma.instance[i].fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
- for (j = 0; j < fw_size; j++)
- WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version);
- }
-
- return 0;
-}
/**
* sdma_v2_4_start - setup and start the async dma engines
@@ -552,13 +517,6 @@ static int sdma_v2_4_start(struct amdgpu_device *adev)
{
int r;
-
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
- r = sdma_v2_4_load_microcode(adev);
- if (r)
- return r;
- }
-
/* halt the engine before programing */
sdma_v2_4_enable(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 6d5c8ac64874..6fb3edaba0ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -318,14 +318,13 @@ static int sdma_v3_0_init_microcode(struct amdgpu_device *adev)
if (adev->sdma.instance[i].feature_version >= 20)
adev->sdma.instance[i].burst_nop = true;
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
- info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
- info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
- info->fw = adev->sdma.instance[i].fw;
- header = (const struct common_firmware_header *)info->fw->data;
- adev->firmware.fw_size +=
- ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
- }
+ info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
+ info->ucode_id = AMDGPU_UCODE_ID_SDMA0 + i;
+ info->fw = adev->sdma.instance[i].fw;
+ header = (const struct common_firmware_header *)info->fw->data;
+ adev->firmware.fw_size +=
+ ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
+
}
out:
if (err) {
@@ -778,42 +777,6 @@ static int sdma_v3_0_rlc_resume(struct amdgpu_device *adev)
}
/**
- * sdma_v3_0_load_microcode - load the sDMA ME ucode
- *
- * @adev: amdgpu_device pointer
- *
- * Loads the sDMA0/1 ucode.
- * Returns 0 for success, -EINVAL if the ucode is not available.
- */
-static int sdma_v3_0_load_microcode(struct amdgpu_device *adev)
-{
- const struct sdma_firmware_header_v1_0 *hdr;
- const __le32 *fw_data;
- u32 fw_size;
- int i, j;
-
- /* halt the MEs */
- sdma_v3_0_enable(adev, false);
-
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (!adev->sdma.instance[i].fw)
- return -EINVAL;
- hdr = (const struct sdma_firmware_header_v1_0 *)adev->sdma.instance[i].fw->data;
- amdgpu_ucode_print_sdma_hdr(&hdr->header);
- fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
- fw_data = (const __le32 *)
- (adev->sdma.instance[i].fw->data +
- le32_to_cpu(hdr->header.ucode_array_offset_bytes));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], 0);
- for (j = 0; j < fw_size; j++)
- WREG32(mmSDMA0_UCODE_DATA + sdma_offsets[i], le32_to_cpup(fw_data++));
- WREG32(mmSDMA0_UCODE_ADDR + sdma_offsets[i], adev->sdma.instance[i].fw_version);
- }
-
- return 0;
-}
-
-/**
* sdma_v3_0_start - setup and start the async dma engines
*
* @adev: amdgpu_device pointer
@@ -825,12 +788,6 @@ static int sdma_v3_0_start(struct amdgpu_device *adev)
{
int r;
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
- r = sdma_v3_0_load_microcode(adev);
- if (r)
- return r;
- }
-
/* disable sdma engine before programing it */
sdma_v3_0_ctx_switch_enable(adev, false);
sdma_v3_0_enable(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index a3e2ed15fff2..c20d413f277c 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -818,7 +818,7 @@ sdma_v4_1_update_power_gating(struct amdgpu_device *adev, bool enable)
uint32_t def, data;
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_SDMA)) {
- /* disable idle interrupt */
+ /* enable idle interrupt */
def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CNTL));
data |= SDMA0_CNTL__CTXEMPTY_INT_ENABLE_MASK;
@@ -1364,6 +1364,9 @@ static int sdma_v4_0_hw_init(void *handle)
int r;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs->set_powergating_by_smu)
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false);
+
sdma_v4_0_init_golden_registers(adev);
r = sdma_v4_0_start(adev);
@@ -1381,6 +1384,9 @@ static int sdma_v4_0_hw_fini(void *handle)
sdma_v4_0_ctx_switch_enable(adev, false);
sdma_v4_0_enable(adev, false);
+ if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs->set_powergating_by_smu)
+ amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c
index c364ef94cc36..f8408f88cd37 100644
--- a/drivers/gpu/drm/amd/amdgpu/si.c
+++ b/drivers/gpu/drm/amd/amdgpu/si.c
@@ -2057,13 +2057,13 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v6_0_ip_block);
amdgpu_device_ip_block_add(adev, &si_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v6_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
else
amdgpu_device_ip_block_add(adev, &dce_v6_0_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v6_0_ip_block);
- amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
/* amdgpu_device_ip_block_add(adev, &uvd_v3_1_ip_block); */
/* amdgpu_device_ip_block_add(adev, &vce_v1_0_ip_block); */
break;
@@ -2071,13 +2071,14 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v6_0_ip_block);
amdgpu_device_ip_block_add(adev, &si_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v6_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
else
amdgpu_device_ip_block_add(adev, &dce_v6_4_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v6_0_ip_block);
- amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
+
/* amdgpu_device_ip_block_add(adev, &uvd_v3_1_ip_block); */
/* amdgpu_device_ip_block_add(adev, &vce_v1_0_ip_block); */
break;
@@ -2085,11 +2086,11 @@ int si_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &si_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v6_0_ip_block);
amdgpu_device_ip_block_add(adev, &si_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v6_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
amdgpu_device_ip_block_add(adev, &si_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v6_0_ip_block);
- amdgpu_device_ip_block_add(adev, &si_dma_ip_block);
break;
default:
BUG();
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index d4ceaf440f26..adbaea6da0d7 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -502,12 +502,14 @@ static int si_dma_sw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* DMA0 trap event */
- r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 224, &adev->sdma.trap_irq);
+ r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 224,
+ &adev->sdma.trap_irq);
if (r)
return r;
/* DMA1 trap event */
- r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 244, &adev->sdma.trap_irq_1);
+ r = amdgpu_irq_add_id(adev, AMDGPU_IRQ_CLIENTID_LEGACY, 244,
+ &adev->sdma.trap_irq);
if (r)
return r;
@@ -649,17 +651,10 @@ static int si_dma_process_trap_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry)
{
- amdgpu_fence_process(&adev->sdma.instance[0].ring);
-
- return 0;
-}
-
-static int si_dma_process_trap_irq_1(struct amdgpu_device *adev,
- struct amdgpu_irq_src *source,
- struct amdgpu_iv_entry *entry)
-{
- amdgpu_fence_process(&adev->sdma.instance[1].ring);
-
+ if (entry->src_id == 224)
+ amdgpu_fence_process(&adev->sdma.instance[0].ring);
+ else
+ amdgpu_fence_process(&adev->sdma.instance[1].ring);
return 0;
}
@@ -786,11 +781,6 @@ static const struct amdgpu_irq_src_funcs si_dma_trap_irq_funcs = {
.process = si_dma_process_trap_irq,
};
-static const struct amdgpu_irq_src_funcs si_dma_trap_irq_funcs_1 = {
- .set = si_dma_set_trap_irq_state,
- .process = si_dma_process_trap_irq_1,
-};
-
static const struct amdgpu_irq_src_funcs si_dma_illegal_inst_irq_funcs = {
.process = si_dma_process_illegal_inst_irq,
};
@@ -799,7 +789,6 @@ static void si_dma_set_irq_funcs(struct amdgpu_device *adev)
{
adev->sdma.trap_irq.num_types = AMDGPU_SDMA_IRQ_LAST;
adev->sdma.trap_irq.funcs = &si_dma_trap_irq_funcs;
- adev->sdma.trap_irq_1.funcs = &si_dma_trap_irq_funcs_1;
adev->sdma.illegal_inst_irq.funcs = &si_dma_illegal_inst_irq_funcs;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index fb26039beeba..bf5e6a413dee 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -529,6 +529,8 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &psp_v11_0_ip_block);
else
amdgpu_device_ip_block_add(adev, &psp_v3_1_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
if (!amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
@@ -539,8 +541,6 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
#else
# warning "Enable CONFIG_DRM_AMD_DC for display support on SOC15."
#endif
- amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
if (!(adev->asic_type == CHIP_VEGA20 && amdgpu_sriov_vf(adev))) {
amdgpu_device_ip_block_add(adev, &uvd_v7_0_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v4_0_ip_block);
@@ -551,6 +551,8 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
amdgpu_device_ip_block_add(adev, &psp_v10_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -560,8 +562,6 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
#else
# warning "Enable CONFIG_DRM_AMD_DC for display support on SOC15."
#endif
- amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block);
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 8ef4a5392112..7a5b40275e8e 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -274,7 +274,7 @@ err:
*/
static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
uint32_t handle,
- bool direct, struct dma_fence **fence)
+ struct dma_fence **fence)
{
const unsigned ib_size_dw = 16;
struct amdgpu_job *job;
@@ -310,11 +310,7 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
for (i = ib->length_dw; i < ib_size_dw; ++i)
ib->ptr[i] = 0x0;
- if (direct)
- r = amdgpu_job_submit_direct(job, ring, &f);
- else
- r = amdgpu_job_submit(job, &ring->adev->vce.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &f);
+ r = amdgpu_job_submit_direct(job, ring, &f);
if (r)
goto err;
@@ -345,7 +341,7 @@ static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
goto error;
}
- r = uvd_v6_0_enc_get_destroy_msg(ring, 1, true, &fence);
+ r = uvd_v6_0_enc_get_destroy_msg(ring, 1, &fence);
if (r) {
DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r);
goto error;
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index a289f6a20b6b..58b39afcfb86 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -280,8 +280,8 @@ err:
*
* Close up a stream for HW test or if userspace failed to do so
*/
-int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
- bool direct, struct dma_fence **fence)
+static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
+ struct dma_fence **fence)
{
const unsigned ib_size_dw = 16;
struct amdgpu_job *job;
@@ -317,11 +317,7 @@ int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
for (i = ib->length_dw; i < ib_size_dw; ++i)
ib->ptr[i] = 0x0;
- if (direct)
- r = amdgpu_job_submit_direct(job, ring, &f);
- else
- r = amdgpu_job_submit(job, &ring->adev->vce.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &f);
+ r = amdgpu_job_submit_direct(job, ring, &f);
if (r)
goto err;
@@ -352,7 +348,7 @@ static int uvd_v7_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout)
goto error;
}
- r = uvd_v7_0_enc_get_destroy_msg(ring, 1, true, &fence);
+ r = uvd_v7_0_enc_get_destroy_msg(ring, 1, &fence);
if (r) {
DRM_ERROR("amdgpu: (%d)failed to get destroy ib (%ld).\n", ring->me, r);
goto error;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
index 63d7f97e81b7..e9282415c24f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
@@ -278,6 +278,7 @@ static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4);
uint32_t offset;
+ /* cache window 0: fw */
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo));
@@ -297,20 +298,21 @@ static void vcn_v1_0_mc_resume_spg_mode(struct amdgpu_device *adev)
WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size);
+ /* cache window 1: stack */
WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
lower_32_bits(adev->vcn.gpu_addr + offset));
WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
upper_32_bits(adev->vcn.gpu_addr + offset));
WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1, 0);
- WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_HEAP_SIZE);
+ WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE);
+ /* cache window 2: context */
WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
- lower_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_HEAP_SIZE));
+ lower_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
WREG32_SOC15(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
- upper_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_HEAP_SIZE));
+ upper_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_STACK_SIZE));
WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2, 0);
- WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE2,
- AMDGPU_VCN_STACK_SIZE + (AMDGPU_VCN_SESSION_SIZE * 40));
+ WREG32_SOC15(UVD, 0, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE);
WREG32_SOC15(UVD, 0, mmUVD_UDEC_ADDR_CONFIG,
adev->gfx.config.gb_addr_config);
@@ -325,6 +327,7 @@ static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
uint32_t size = AMDGPU_GPU_PAGE_ALIGN(adev->vcn.fw->size + 4);
uint32_t offset;
+ /* cache window 0: fw */
if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW,
(adev->firmware.ucode[AMDGPU_UCODE_ID_VCN].tmr_mc_addr_lo),
@@ -347,24 +350,25 @@ static void vcn_v1_0_mc_resume_dpg_mode(struct amdgpu_device *adev)
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_SIZE0, size, 0xFFFFFFFF, 0);
+ /* cache window 1: stack */
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW,
lower_32_bits(adev->vcn.gpu_addr + offset), 0xFFFFFFFF, 0);
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH,
upper_32_bits(adev->vcn.gpu_addr + offset), 0xFFFFFFFF, 0);
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1, 0,
0xFFFFFFFF, 0);
- WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_HEAP_SIZE,
+ WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_SIZE1, AMDGPU_VCN_STACK_SIZE,
0xFFFFFFFF, 0);
+ /* cache window 2: context */
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW,
- lower_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_HEAP_SIZE),
+ lower_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),
0xFFFFFFFF, 0);
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH,
- upper_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_HEAP_SIZE),
+ upper_32_bits(adev->vcn.gpu_addr + offset + AMDGPU_VCN_STACK_SIZE),
0xFFFFFFFF, 0);
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2, 0, 0xFFFFFFFF, 0);
- WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_SIZE2,
- AMDGPU_VCN_STACK_SIZE + (AMDGPU_VCN_SESSION_SIZE * 40),
+ WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_VCPU_CACHE_SIZE2, AMDGPU_VCN_CONTEXT_SIZE,
0xFFFFFFFF, 0);
WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_UDEC_ADDR_CONFIG,
@@ -601,8 +605,6 @@ static void vcn_v1_0_clock_gating_dpg_mode(struct amdgpu_device *adev, uint8_t s
reg_data = 0 << UVD_CGC_CTRL__DYN_CLOCK_MODE__SHIFT;
reg_data |= 1 << UVD_CGC_CTRL__CLK_GATE_DLY_TIMER__SHIFT;
reg_data |= 4 << UVD_CGC_CTRL__CLK_OFF_DELAY__SHIFT;
- WREG32_SOC15_DPG_MODE(UVD, 0, mmUVD_CGC_CTRL, reg_data, 0xFFFFFFFF, sram_sel);
-
reg_data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK |
UVD_CGC_CTRL__UDEC_CM_MODE_MASK |
UVD_CGC_CTRL__UDEC_IT_MODE_MASK |
@@ -812,12 +814,12 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
for (j = 0; j < 100; ++j) {
status = RREG32_SOC15(UVD, 0, mmUVD_STATUS);
- if (status & 2)
+ if (status & UVD_STATUS__IDLE)
break;
mdelay(10);
}
r = 0;
- if (status & 2)
+ if (status & UVD_STATUS__IDLE)
break;
DRM_ERROR("VCN decode not responding, trying to reset the VCPU!!!\n");
@@ -875,6 +877,8 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
/* Initialize the ring buffer's read and write pointers */
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR, 0);
+ WREG32_SOC15(UVD, 0, mmUVD_SCRATCH2, 0);
+
ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR);
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
lower_32_bits(ring->wptr));
@@ -898,12 +902,13 @@ static int vcn_v1_0_start_spg_mode(struct amdgpu_device *adev)
ring = &adev->vcn.ring_jpeg;
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_VMID, 0);
- WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, (0x00000001L | 0x00000002L));
+ WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_NO_FETCH_MASK |
+ UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_LOW, lower_32_bits(ring->gpu_addr));
WREG32_SOC15(UVD, 0, mmUVD_LMI_JRBC_RB_64BIT_BAR_HIGH, upper_32_bits(ring->gpu_addr));
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_RPTR, 0);
WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR, 0);
- WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, 0x00000002L);
+ WREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_CNTL, UVD_JRBC_RB_CNTL__RB_RPTR_WR_EN_MASK);
/* initialize wptr */
ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_JRBC_RB_WPTR);
@@ -1051,6 +1056,8 @@ static int vcn_v1_0_start_dpg_mode(struct amdgpu_device *adev)
/* Initialize the ring buffer's read and write pointers */
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR, 0);
+ WREG32_SOC15(UVD, 0, mmUVD_SCRATCH2, 0);
+
ring->wptr = RREG32_SOC15(UVD, 0, mmUVD_RBC_RB_RPTR);
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR,
lower_32_bits(ring->wptr));
@@ -1120,8 +1127,9 @@ static int vcn_v1_0_stop_dpg_mode(struct amdgpu_device *adev)
{
int ret_code;
- /* Wait for power status to be 1 */
- SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS, 0x1,
+ /* Wait for power status to be UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF */
+ SOC15_WAIT_ON_RREG(UVD, 0, mmUVD_POWER_STATUS,
+ UVD_POWER_STATUS__UVD_POWER_STATUS_TILES_OFF,
UVD_POWER_STATUS__UVD_POWER_STATUS_MASK, ret_code);
/* disable dynamic power gating mode */
@@ -1147,7 +1155,7 @@ static bool vcn_v1_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
- return (RREG32_SOC15(VCN, 0, mmUVD_STATUS) == 0x2);
+ return (RREG32_SOC15(VCN, 0, mmUVD_STATUS) == UVD_STATUS__IDLE);
}
static int vcn_v1_0_wait_for_idle(void *handle)
@@ -1155,7 +1163,8 @@ static int vcn_v1_0_wait_for_idle(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret = 0;
- SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_STATUS, 0x2, 0x2, ret);
+ SOC15_WAIT_ON_RREG(VCN, 0, mmUVD_STATUS, UVD_STATUS__IDLE,
+ UVD_STATUS__IDLE, ret);
return ret;
}
@@ -1217,6 +1226,10 @@ static void vcn_v1_0_dec_ring_set_wptr(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
+ if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
+ WREG32_SOC15(UVD, 0, mmUVD_SCRATCH2,
+ lower_32_bits(ring->wptr) | 0x80000000);
+
WREG32_SOC15(UVD, 0, mmUVD_RBC_RB_WPTR, lower_32_bits(ring->wptr));
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index 88b57a5e9489..07880d35e9de 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -1596,16 +1596,18 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v7_4_ip_block);
amdgpu_device_ip_block_add(adev, &iceland_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v2_4_ip_block);
break;
case CHIP_FIJI:
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v8_5_ip_block);
amdgpu_device_ip_block_add(adev, &tonga_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -1615,8 +1617,6 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v10_1_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
if (!amdgpu_sriov_vf(adev)) {
amdgpu_device_ip_block_add(adev, &uvd_v6_0_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v3_0_ip_block);
@@ -1626,6 +1626,8 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v8_0_ip_block);
amdgpu_device_ip_block_add(adev, &tonga_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -1635,8 +1637,6 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v10_0_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
if (!amdgpu_sriov_vf(adev)) {
amdgpu_device_ip_block_add(adev, &uvd_v5_0_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v3_0_ip_block);
@@ -1649,6 +1649,8 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v8_1_ip_block);
amdgpu_device_ip_block_add(adev, &tonga_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -1658,8 +1660,6 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v11_2_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v3_1_ip_block);
amdgpu_device_ip_block_add(adev, &uvd_v6_3_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v3_4_ip_block);
break;
@@ -1667,6 +1667,8 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v8_0_ip_block);
amdgpu_device_ip_block_add(adev, &cz_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -1676,8 +1678,6 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v11_0_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &uvd_v6_0_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v3_1_ip_block);
#if defined(CONFIG_DRM_AMD_ACP)
@@ -1688,6 +1688,8 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &vi_common_ip_block);
amdgpu_device_ip_block_add(adev, &gmc_v8_0_ip_block);
amdgpu_device_ip_block_add(adev, &cz_ih_ip_block);
+ amdgpu_device_ip_block_add(adev, &gfx_v8_1_ip_block);
+ amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
@@ -1697,8 +1699,6 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
#endif
else
amdgpu_device_ip_block_add(adev, &dce_v11_0_ip_block);
- amdgpu_device_ip_block_add(adev, &gfx_v8_1_ip_block);
- amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &uvd_v6_2_ip_block);
amdgpu_device_ip_block_add(adev, &vce_v3_4_ip_block);
#if defined(CONFIG_DRM_AMD_ACP)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index d6af31ccf0ee..a3b933967171 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -358,8 +358,8 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm,
struct queue *q,
struct qcm_process_device *qpd)
{
- int retval;
struct mqd_manager *mqd_mgr;
+ int retval;
mqd_mgr = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE);
if (!mqd_mgr)
@@ -387,8 +387,12 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm,
if (!q->properties.is_active)
return 0;
- retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, q->queue,
- &q->properties, q->process->mm);
+ if (WARN(q->process->mm != current->mm,
+ "should only run in user thread"))
+ retval = -EFAULT;
+ else
+ retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, q->queue,
+ &q->properties, current->mm);
if (retval)
goto out_uninit_mqd;
@@ -545,9 +549,15 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q)
retval = map_queues_cpsch(dqm);
else if (q->properties.is_active &&
(q->properties.type == KFD_QUEUE_TYPE_COMPUTE ||
- q->properties.type == KFD_QUEUE_TYPE_SDMA))
- retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe, q->queue,
- &q->properties, q->process->mm);
+ q->properties.type == KFD_QUEUE_TYPE_SDMA)) {
+ if (WARN(q->process->mm != current->mm,
+ "should only run in user thread"))
+ retval = -EFAULT;
+ else
+ retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd,
+ q->pipe, q->queue,
+ &q->properties, current->mm);
+ }
out_unlock:
dqm_unlock(dqm);
@@ -653,6 +663,7 @@ out:
static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
struct qcm_process_device *qpd)
{
+ struct mm_struct *mm = NULL;
struct queue *q;
struct mqd_manager *mqd_mgr;
struct kfd_process_device *pdd;
@@ -686,6 +697,15 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
kfd_flush_tlb(pdd);
}
+ /* Take a safe reference to the mm_struct, which may otherwise
+ * disappear even while the kfd_process is still referenced.
+ */
+ mm = get_task_mm(pdd->process->lead_thread);
+ if (!mm) {
+ retval = -EFAULT;
+ goto out;
+ }
+
/* activate all active queues on the qpd */
list_for_each_entry(q, &qpd->queues_list, list) {
if (!q->properties.is_evicted)
@@ -700,14 +720,15 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm,
q->properties.is_evicted = false;
q->properties.is_active = true;
retval = mqd_mgr->load_mqd(mqd_mgr, q->mqd, q->pipe,
- q->queue, &q->properties,
- q->process->mm);
+ q->queue, &q->properties, mm);
if (retval)
goto out;
dqm->queue_count++;
}
qpd->evicted = 0;
out:
+ if (mm)
+ mmput(mm);
dqm_unlock(dqm);
return retval;
}
@@ -1343,9 +1364,6 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm,
{
int retval;
struct mqd_manager *mqd_mgr;
- bool preempt_all_queues;
-
- preempt_all_queues = false;
retval = 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 715422bb30db..e224f23e2215 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -718,6 +718,87 @@ amdgpu_dm_find_first_crtc_matching_connector(struct drm_atomic_state *state,
return NULL;
}
+static void emulated_link_detect(struct dc_link *link)
+{
+ struct dc_sink_init_data sink_init_data = { 0 };
+ struct display_sink_capability sink_caps = { 0 };
+ enum dc_edid_status edid_status;
+ struct dc_context *dc_ctx = link->ctx;
+ struct dc_sink *sink = NULL;
+ struct dc_sink *prev_sink = NULL;
+
+ link->type = dc_connection_none;
+ prev_sink = link->local_sink;
+
+ if (prev_sink != NULL)
+ dc_sink_retain(prev_sink);
+
+ switch (link->connector_signal) {
+ case SIGNAL_TYPE_HDMI_TYPE_A: {
+ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+ sink_caps.signal = SIGNAL_TYPE_HDMI_TYPE_A;
+ break;
+ }
+
+ case SIGNAL_TYPE_DVI_SINGLE_LINK: {
+ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+ sink_caps.signal = SIGNAL_TYPE_DVI_SINGLE_LINK;
+ break;
+ }
+
+ case SIGNAL_TYPE_DVI_DUAL_LINK: {
+ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+ sink_caps.signal = SIGNAL_TYPE_DVI_DUAL_LINK;
+ break;
+ }
+
+ case SIGNAL_TYPE_LVDS: {
+ sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C;
+ sink_caps.signal = SIGNAL_TYPE_LVDS;
+ break;
+ }
+
+ case SIGNAL_TYPE_EDP: {
+ sink_caps.transaction_type =
+ DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+ sink_caps.signal = SIGNAL_TYPE_EDP;
+ break;
+ }
+
+ case SIGNAL_TYPE_DISPLAY_PORT: {
+ sink_caps.transaction_type =
+ DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
+ sink_caps.signal = SIGNAL_TYPE_VIRTUAL;
+ break;
+ }
+
+ default:
+ DC_ERROR("Invalid connector type! signal:%d\n",
+ link->connector_signal);
+ return;
+ }
+
+ sink_init_data.link = link;
+ sink_init_data.sink_signal = sink_caps.signal;
+
+ sink = dc_sink_create(&sink_init_data);
+ if (!sink) {
+ DC_ERROR("Failed to create sink!\n");
+ return;
+ }
+
+ link->local_sink = sink;
+
+ edid_status = dm_helpers_read_local_edid(
+ link->ctx,
+ link,
+ sink);
+
+ if (edid_status != EDID_OK)
+ DC_ERROR("Failed to read EDID");
+
+}
+
static int dm_resume(void *handle)
{
struct amdgpu_device *adev = handle;
@@ -731,6 +812,7 @@ static int dm_resume(void *handle)
struct drm_plane *plane;
struct drm_plane_state *new_plane_state;
struct dm_plane_state *dm_new_plane_state;
+ enum dc_connection_type new_connection_type = dc_connection_none;
int ret;
int i;
@@ -761,7 +843,13 @@ static int dm_resume(void *handle)
continue;
mutex_lock(&aconnector->hpd_lock);
- dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
+ if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
+ DRM_ERROR("KMS: Failed to detect connector\n");
+
+ if (aconnector->base.force && new_connection_type == dc_connection_none)
+ emulated_link_detect(aconnector->dc_link);
+ else
+ dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD);
if (aconnector->fake_enable && aconnector->dc_link->local_sink)
aconnector->fake_enable = false;
@@ -1010,6 +1098,7 @@ static void handle_hpd_irq(void *param)
struct amdgpu_dm_connector *aconnector = (struct amdgpu_dm_connector *)param;
struct drm_connector *connector = &aconnector->base;
struct drm_device *dev = connector->dev;
+ enum dc_connection_type new_connection_type = dc_connection_none;
/*
* In case of failure or MST no need to update connector status or notify the OS
@@ -1020,7 +1109,21 @@ static void handle_hpd_irq(void *param)
if (aconnector->fake_enable)
aconnector->fake_enable = false;
- if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
+ if (!dc_link_detect_sink(aconnector->dc_link, &new_connection_type))
+ DRM_ERROR("KMS: Failed to detect connector\n");
+
+ if (aconnector->base.force && new_connection_type == dc_connection_none) {
+ emulated_link_detect(aconnector->dc_link);
+
+
+ drm_modeset_lock_all(dev);
+ dm_restore_drm_connector_state(dev, connector);
+ drm_modeset_unlock_all(dev);
+
+ if (aconnector->base.force == DRM_FORCE_UNSPECIFIED)
+ drm_kms_helper_hotplug_event(dev);
+
+ } else if (dc_link_detect(aconnector->dc_link, DETECT_REASON_HPD)) {
amdgpu_dm_update_connector_after_detect(aconnector);
@@ -1120,6 +1223,7 @@ static void handle_hpd_rx_irq(void *param)
struct drm_device *dev = connector->dev;
struct dc_link *dc_link = aconnector->dc_link;
bool is_mst_root_connector = aconnector->mst_mgr.mst_state;
+ enum dc_connection_type new_connection_type = dc_connection_none;
/*
* TODO:Temporary add mutex to protect hpd interrupt not have a gpio
@@ -1132,7 +1236,24 @@ static void handle_hpd_rx_irq(void *param)
if (dc_link_handle_hpd_rx_irq(dc_link, NULL, NULL) &&
!is_mst_root_connector) {
/* Downstream Port status changed. */
- if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
+ if (!dc_link_detect_sink(dc_link, &new_connection_type))
+ DRM_ERROR("KMS: Failed to detect connector\n");
+
+ if (aconnector->base.force && new_connection_type == dc_connection_none) {
+ emulated_link_detect(dc_link);
+
+ if (aconnector->fake_enable)
+ aconnector->fake_enable = false;
+
+ amdgpu_dm_update_connector_after_detect(aconnector);
+
+
+ drm_modeset_lock_all(dev);
+ dm_restore_drm_connector_state(dev, connector);
+ drm_modeset_unlock_all(dev);
+
+ drm_kms_helper_hotplug_event(dev);
+ } else if (dc_link_detect(dc_link, DETECT_REASON_HPDRX)) {
if (aconnector->fake_enable)
aconnector->fake_enable = false;
@@ -1529,6 +1650,7 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
struct amdgpu_mode_info *mode_info = &adev->mode_info;
uint32_t link_cnt;
int32_t total_overlay_planes, total_primary_planes;
+ enum dc_connection_type new_connection_type = dc_connection_none;
link_cnt = dm->dc->caps.max_links;
if (amdgpu_dm_mode_config_init(dm->adev)) {
@@ -1595,7 +1717,14 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
link = dc_get_link_at_index(dm->dc, i);
- if (dc_link_detect(link, DETECT_REASON_BOOT)) {
+ if (!dc_link_detect_sink(link, &new_connection_type))
+ DRM_ERROR("KMS: Failed to detect connector\n");
+
+ if (aconnector->base.force && new_connection_type == dc_connection_none) {
+ emulated_link_detect(link);
+ amdgpu_dm_update_connector_after_detect(aconnector);
+
+ } else if (dc_link_detect(link, DETECT_REASON_BOOT)) {
amdgpu_dm_update_connector_after_detect(aconnector);
register_backlight_device(dm, link);
}
@@ -2638,7 +2767,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (dm_state && dm_state->freesync_capable)
stream->ignore_msa_timing_param = true;
finish:
- if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL)
+ if (sink && sink->sink_signal == SIGNAL_TYPE_VIRTUAL && aconnector->base.force != DRM_FORCE_ON)
dc_sink_release(sink);
return stream;
@@ -4611,12 +4740,18 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
}
spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
- /* Signal HW programming completion */
- drm_atomic_helper_commit_hw_done(state);
if (wait_for_vblank)
drm_atomic_helper_wait_for_flip_done(dev, state);
+ /*
+ * FIXME:
+ * Delay hw_done() until flip_done() is signaled. This is to block
+ * another commit from freeing the CRTC state while we're still
+ * waiting on flip_done.
+ */
+ drm_atomic_helper_commit_hw_done(state);
+
drm_atomic_helper_cleanup_planes(dev, state);
/*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
index a910f01838ab..a212178f2edc 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
@@ -36,17 +36,13 @@
* Private declarations.
*****************************************************************************/
-struct handler_common_data {
+struct amdgpu_dm_irq_handler_data {
struct list_head list;
interrupt_handler handler;
void *handler_arg;
/* DM which this handler belongs to */
struct amdgpu_display_manager *dm;
-};
-
-struct amdgpu_dm_irq_handler_data {
- struct handler_common_data hcd;
/* DAL irq source which registered for this interrupt. */
enum dc_irq_source irq_source;
};
@@ -61,7 +57,7 @@ struct amdgpu_dm_irq_handler_data {
* Private functions.
*****************************************************************************/
-static void init_handler_common_data(struct handler_common_data *hcd,
+static void init_handler_common_data(struct amdgpu_dm_irq_handler_data *hcd,
void (*ih)(void *),
void *args,
struct amdgpu_display_manager *dm)
@@ -85,11 +81,9 @@ static void dm_irq_work_func(struct work_struct *work)
struct amdgpu_dm_irq_handler_data *handler_data;
list_for_each(entry, handler_list) {
- handler_data =
- list_entry(
- entry,
- struct amdgpu_dm_irq_handler_data,
- hcd.list);
+ handler_data = list_entry(entry,
+ struct amdgpu_dm_irq_handler_data,
+ list);
DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n",
handler_data->irq_source);
@@ -97,7 +91,7 @@ static void dm_irq_work_func(struct work_struct *work)
DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n",
handler_data->irq_source);
- handler_data->hcd.handler(handler_data->hcd.handler_arg);
+ handler_data->handler(handler_data->handler_arg);
}
/* Call a DAL subcomponent which registered for interrupt notification
@@ -137,11 +131,11 @@ static struct list_head *remove_irq_handler(struct amdgpu_device *adev,
list_for_each_safe(entry, tmp, hnd_list) {
handler = list_entry(entry, struct amdgpu_dm_irq_handler_data,
- hcd.list);
+ list);
if (ih == handler) {
/* Found our handler. Remove it from the list. */
- list_del(&handler->hcd.list);
+ list_del(&handler->list);
handler_removed = true;
break;
}
@@ -230,8 +224,7 @@ void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev,
memset(handler_data, 0, sizeof(*handler_data));
- init_handler_common_data(&handler_data->hcd, ih, handler_args,
- &adev->dm);
+ init_handler_common_data(handler_data, ih, handler_args, &adev->dm);
irq_source = int_params->irq_source;
@@ -250,7 +243,7 @@ void *amdgpu_dm_irq_register_interrupt(struct amdgpu_device *adev,
break;
}
- list_add_tail(&handler_data->hcd.list, hnd_list);
+ list_add_tail(&handler_data->list, hnd_list);
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
@@ -462,15 +455,13 @@ static void amdgpu_dm_irq_immediate_work(struct amdgpu_device *adev,
entry,
&adev->dm.irq_handler_list_high_tab[irq_source]) {
- handler_data =
- list_entry(
- entry,
- struct amdgpu_dm_irq_handler_data,
- hcd.list);
+ handler_data = list_entry(entry,
+ struct amdgpu_dm_irq_handler_data,
+ list);
/* Call a subcomponent which registered for immediate
* interrupt notification */
- handler_data->hcd.handler(handler_data->hcd.handler_arg);
+ handler_data->handler(handler_data->handler_arg);
}
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 76fe5a9af3bf..7c491c91465f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -60,6 +60,7 @@
#define DC_LOGGER \
dc->ctx->logger
+const static char DC_BUILD_ID[] = "production-build";
/*******************************************************************************
* Private functions
@@ -758,6 +759,8 @@ struct dc *dc_create(const struct dc_init_data *init_params)
dc->config = init_params->flags;
+ dc->build_id = DC_BUILD_ID;
+
DC_LOG_DC("Display Core initialized\n");
@@ -1110,32 +1113,6 @@ static bool is_surface_in_context(
return false;
}
-static unsigned int pixel_format_to_bpp(enum surface_pixel_format format)
-{
- switch (format) {
- case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
- case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
- return 12;
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
- case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
- case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
- case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
- return 16;
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
- case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
- case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
- return 32;
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
- case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
- case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
- return 64;
- default:
- ASSERT_CRITICAL(false);
- return -1;
- }
-}
-
static enum surface_update_type get_plane_info_update_type(const struct dc_surface_update *u)
{
union surface_update_flags *update_flags = &u->surface->update_flags;
@@ -1169,8 +1146,8 @@ static enum surface_update_type get_plane_info_update_type(const struct dc_surfa
|| u->plane_info->dcc.grph.meta_pitch != u->surface->dcc.grph.meta_pitch)
update_flags->bits.dcc_change = 1;
- if (pixel_format_to_bpp(u->plane_info->format) !=
- pixel_format_to_bpp(u->surface->format))
+ if (resource_pixel_format_to_bpp(u->plane_info->format) !=
+ resource_pixel_format_to_bpp(u->surface->format))
/* different bytes per element will require full bandwidth
* and DML calculation
*/
@@ -1859,3 +1836,16 @@ void dc_link_remove_remote_sink(struct dc_link *link, struct dc_sink *sink)
}
}
}
+
+void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info)
+{
+ info->displayClock = (unsigned int)state->bw.dcn.clk.dispclk_khz;
+ info->engineClock = (unsigned int)state->bw.dcn.clk.dcfclk_khz;
+ info->memoryClock = (unsigned int)state->bw.dcn.clk.dramclk_khz;
+ info->maxSupportedDppClock = (unsigned int)state->bw.dcn.clk.max_supported_dppclk_khz;
+ info->dppClock = (unsigned int)state->bw.dcn.clk.dppclk_khz;
+ info->socClock = (unsigned int)state->bw.dcn.clk.socclk_khz;
+ info->dcfClockDeepSleep = (unsigned int)state->bw.dcn.clk.dcfclk_deep_sleep_khz;
+ info->fClock = (unsigned int)state->bw.dcn.clk.fclk_khz;
+ info->phyClock = (unsigned int)state->bw.dcn.clk.phyclk_khz;
+} \ No newline at end of file
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index 9f9503a9b9aa..fb04a4ad141f 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -198,7 +198,7 @@ static bool program_hpd_filter(
return result;
}
-static bool detect_sink(struct dc_link *link, enum dc_connection_type *type)
+bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type)
{
uint32_t is_hpd_high = 0;
struct gpio *hpd_pin;
@@ -612,7 +612,7 @@ bool dc_link_detect(struct dc_link *link, enum dc_detect_reason reason)
if (link->connector_signal == SIGNAL_TYPE_VIRTUAL)
return false;
- if (false == detect_sink(link, &new_connection_type)) {
+ if (false == dc_link_detect_sink(link, &new_connection_type)) {
BREAK_TO_DEBUGGER();
return false;
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 2d6a4300bfa4..b6fe29b9fb65 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1975,6 +1975,9 @@ static void calculate_phy_pix_clks(struct dc_stream_state *stream)
else
stream->phy_pix_clk =
stream->timing.pix_clk_khz;
+
+ if (stream->timing.timing_3d_format == TIMING_3D_FORMAT_HW_FRAME_PACKING)
+ stream->phy_pix_clk *= 2;
}
enum dc_status resource_map_pool_resources(
@@ -2096,6 +2099,14 @@ enum dc_status dc_validate_global_state(
if (pipe_ctx->stream != stream)
continue;
+ if (dc->res_pool->funcs->get_default_swizzle_mode &&
+ pipe_ctx->plane_state &&
+ pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
+ result = dc->res_pool->funcs->get_default_swizzle_mode(pipe_ctx->plane_state);
+ if (result != DC_OK)
+ return result;
+ }
+
/* Switch to dp clock source only if there is
* no non dp stream that shares the same timing
* with the dp stream.
@@ -2885,3 +2896,32 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla
return res;
}
+
+unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format)
+{
+ switch (format) {
+ case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
+ return 8;
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr:
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
+ return 12;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
+ case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
+ case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
+ return 16;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR8888:
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
+ return 32;
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
+ case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F:
+ case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
+ return 64;
+ default:
+ ASSERT_CRITICAL(false);
+ return -1;
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 11ea2a226952..199527171100 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -38,13 +38,12 @@
#include "inc/compressor.h"
#include "dml/display_mode_lib.h"
-#define DC_VER "3.1.67"
+#define DC_VER "3.1.68"
#define MAX_SURFACES 3
#define MAX_STREAMS 6
#define MAX_SINKS_PER_LINK 4
-
/*******************************************************************************
* Display Core Interfaces
******************************************************************************/
@@ -208,6 +207,7 @@ struct dc_clocks {
int dcfclk_deep_sleep_khz;
int fclk_khz;
int phyclk_khz;
+ int dramclk_khz;
};
struct dc_debug_options {
@@ -315,6 +315,8 @@ struct dc {
struct compressor *fbc_compressor;
struct dc_debug_data debug_data;
+
+ const char *build_id;
};
enum frame_buffer_mode {
@@ -599,6 +601,8 @@ struct dc_validation_set {
enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *plane_state);
+void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info);
+
enum dc_status dc_validate_global_state(
struct dc *dc,
struct dc_state *new_ctx);
diff --git a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
index 57f57cf0fe2a..7825e4b5e97c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_hw_types.h
@@ -289,7 +289,8 @@ enum swizzle_mode_values {
DC_SW_VAR_S_X = 29,
DC_SW_VAR_D_X = 30,
DC_SW_VAR_R_X = 31,
- DC_SW_MAX
+ DC_SW_MAX = 32,
+ DC_SW_UNKNOWN = DC_SW_MAX
};
union dc_tiling_info {
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
index 438fb35d87b8..3bfdccceb524 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -216,6 +216,7 @@ void dc_link_enable_hpd_filter(struct dc_link *link, bool enable);
bool dc_link_is_dp_sink_present(struct dc_link *link);
+bool dc_link_detect_sink(struct dc_link *link, enum dc_connection_type *type);
/*
* DPCD access interfaces
*/
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index 4fb62780a696..6e12d640d020 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -659,4 +659,16 @@ enum i2c_mot_mode {
I2C_MOT_FALSE
};
+struct AsicStateEx {
+ unsigned int memoryClock;
+ unsigned int displayClock;
+ unsigned int engineClock;
+ unsigned int maxSupportedDppClock;
+ unsigned int dppClock;
+ unsigned int socClock;
+ unsigned int dcfClockDeepSleep;
+ unsigned int fClock;
+ unsigned int phyClock;
+};
+
#endif /* DC_TYPES_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
index 3f5b2e6f7553..aaeb7faac0c4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
@@ -312,7 +312,7 @@ static void process_channel_reply(
/* in case HPD is LOW, exit AUX transaction */
if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
- reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
+ reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
index d42afa081452..d89a097ba936 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_clocks.c
@@ -664,6 +664,11 @@ static void dce_update_clocks(struct dccg *dccg,
bool safe_to_lower)
{
struct dm_pp_power_level_change_request level_change_req;
+ struct dce_dccg *clk_dce = TO_DCE_CLOCKS(dccg);
+
+ /* TODO: Investigate why this is needed to fix display corruption. */
+ if (!clk_dce->dfs_bypass_active)
+ new_clocks->dispclk_khz = new_clocks->dispclk_khz * 115 / 100;
level_change_req.power_level = dce_get_required_clocks_state(dccg, new_clocks);
/* get max clock state from PPLIB */
diff --git a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
index 4942590e8b9c..366bc8c2c643 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c
@@ -662,21 +662,10 @@ bool dce110_link_encoder_validate_dp_output(
const struct dce110_link_encoder *enc110,
const struct dc_crtc_timing *crtc_timing)
{
- /* default RGB only */
- if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
- return true;
-
- if (enc110->base.features.flags.bits.IS_YCBCR_CAPABLE)
- return true;
-
- /* for DCE 8.x or later DP Y-only feature,
- * we need ASIC cap + FeatureSupportDPYonly, not support 666 */
- if (crtc_timing->flags.Y_ONLY &&
- enc110->base.features.flags.bits.IS_YCBCR_CAPABLE &&
- crtc_timing->display_color_depth != COLOR_DEPTH_666)
- return true;
+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+ return false;
- return false;
+ return true;
}
void dce110_link_encoder_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
index b1cc38827f09..14754a87156c 100644
--- a/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce100/dce100_resource.c
@@ -551,8 +551,7 @@ static const struct encoder_feature_support link_enc_feature = {
.max_hdmi_deep_color = COLOR_DEPTH_121212,
.max_hdmi_pixel_clock = 300000,
.flags.bits.IS_HBR2_CAPABLE = true,
- .flags.bits.IS_TPS3_CAPABLE = true,
- .flags.bits.IS_YCBCR_CAPABLE = true
+ .flags.bits.IS_TPS3_CAPABLE = true
};
struct link_encoder *dce100_link_encoder_create(
@@ -690,7 +689,9 @@ static void destruct(struct dce110_resource_pool *pool)
kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
pool->base.timing_generators[i] = NULL;
}
+ }
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
if (pool->base.engines[i] != NULL)
dce110_engine_destroy(&pool->base.engines[i]);
if (pool->base.hw_i2cs[i] != NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
index 6b7cccc486d8..b75ede5f84f7 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
@@ -2537,7 +2537,7 @@ static void pplib_apply_display_requirements(
dc->prev_display_config = *pp_display_cfg;
}
-void dce110_set_bandwidth(
+static void dce110_set_bandwidth(
struct dc *dc,
struct dc_state *context,
bool decrease_allowed)
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
index e4c5db75c4c6..d6db3dbd9015 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.h
@@ -68,11 +68,6 @@ void dce110_fill_display_configs(
const struct dc_state *context,
struct dm_pp_display_configuration *pp_display_cfg);
-void dce110_set_bandwidth(
- struct dc *dc,
- struct dc_state *context,
- bool decrease_allowed);
-
uint32_t dce110_get_min_vblank_time_us(const struct dc_state *context);
void dp_receiver_power_ctrl(struct dc_link *link, bool on);
diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
index b44cc7042249..de190935f0a4 100644
--- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c
@@ -570,8 +570,7 @@ static const struct encoder_feature_support link_enc_feature = {
.max_hdmi_deep_color = COLOR_DEPTH_121212,
.max_hdmi_pixel_clock = 594000,
.flags.bits.IS_HBR2_CAPABLE = true,
- .flags.bits.IS_TPS3_CAPABLE = true,
- .flags.bits.IS_YCBCR_CAPABLE = true
+ .flags.bits.IS_TPS3_CAPABLE = true
};
static struct link_encoder *dce110_link_encoder_create(
@@ -720,7 +719,9 @@ static void destruct(struct dce110_resource_pool *pool)
kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
pool->base.timing_generators[i] = NULL;
}
+ }
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
if (pool->base.engines[i] != NULL)
dce110_engine_destroy(&pool->base.engines[i]);
if (pool->base.hw_i2cs[i] != NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
index 0f8332ea1160..3ce79c208ddf 100644
--- a/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce112/dce112_resource.c
@@ -555,8 +555,7 @@ static const struct encoder_feature_support link_enc_feature = {
.flags.bits.IS_HBR2_CAPABLE = true,
.flags.bits.IS_HBR3_CAPABLE = true,
.flags.bits.IS_TPS3_CAPABLE = true,
- .flags.bits.IS_TPS4_CAPABLE = true,
- .flags.bits.IS_YCBCR_CAPABLE = true
+ .flags.bits.IS_TPS4_CAPABLE = true
};
struct link_encoder *dce112_link_encoder_create(
@@ -694,9 +693,6 @@ static void destruct(struct dce110_resource_pool *pool)
if (pool->base.opps[i] != NULL)
dce110_opp_destroy(&pool->base.opps[i]);
- if (pool->base.engines[i] != NULL)
- dce110_engine_destroy(&pool->base.engines[i]);
-
if (pool->base.transforms[i] != NULL)
dce112_transform_destroy(&pool->base.transforms[i]);
@@ -712,6 +708,11 @@ static void destruct(struct dce110_resource_pool *pool)
kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
pool->base.timing_generators[i] = NULL;
}
+ }
+
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
+ if (pool->base.engines[i] != NULL)
+ dce110_engine_destroy(&pool->base.engines[i]);
if (pool->base.hw_i2cs[i] != NULL) {
kfree(pool->base.hw_i2cs[i]);
pool->base.hw_i2cs[i] = NULL;
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
index 5853522a6182..eb0f5f9a973b 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_hw_sequencer.c
@@ -244,17 +244,6 @@ static void dce120_update_dchub(
dh_data->dchub_info_valid = false;
}
-static void dce120_set_bandwidth(
- struct dc *dc,
- struct dc_state *context,
- bool decrease_allowed)
-{
- if (context->stream_count <= 0)
- return;
-
- dce110_set_bandwidth(dc, context, decrease_allowed);
-}
-
void dce120_hw_sequencer_construct(struct dc *dc)
{
/* All registers used by dce11.2 match those in dce11 in offset and
@@ -263,6 +252,5 @@ void dce120_hw_sequencer_construct(struct dc *dc)
dce110_hw_sequencer_construct(dc);
dc->hwss.enable_display_power_gating = dce120_enable_display_power_gating;
dc->hwss.update_dchub = dce120_update_dchub;
- dc->hwss.set_bandwidth = dce120_set_bandwidth;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
index 59055801af44..79ab5f9f9115 100644
--- a/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce120/dce120_resource.c
@@ -533,7 +533,9 @@ static void destruct(struct dce110_resource_pool *pool)
kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
pool->base.timing_generators[i] = NULL;
}
+ }
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
if (pool->base.engines[i] != NULL)
dce110_engine_destroy(&pool->base.engines[i]);
if (pool->base.hw_i2cs[i] != NULL) {
@@ -609,7 +611,6 @@ static const struct encoder_feature_support link_enc_feature = {
.flags.bits.IS_HBR3_CAPABLE = true,
.flags.bits.IS_TPS3_CAPABLE = true,
.flags.bits.IS_TPS4_CAPABLE = true,
- .flags.bits.IS_YCBCR_CAPABLE = true
};
static struct link_encoder *dce120_link_encoder_create(
diff --git a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
index 1dc590ccc5f9..d68f951f9869 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
@@ -650,8 +650,7 @@ static const struct encoder_feature_support link_enc_feature = {
.max_hdmi_deep_color = COLOR_DEPTH_121212,
.max_hdmi_pixel_clock = 297000,
.flags.bits.IS_HBR2_CAPABLE = true,
- .flags.bits.IS_TPS3_CAPABLE = true,
- .flags.bits.IS_YCBCR_CAPABLE = true
+ .flags.bits.IS_TPS3_CAPABLE = true
};
struct link_encoder *dce80_link_encoder_create(
@@ -739,7 +738,9 @@ static void destruct(struct dce110_resource_pool *pool)
kfree(DCE110TG_FROM_TG(pool->base.timing_generators[i]));
pool->base.timing_generators[i] = NULL;
}
+ }
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
if (pool->base.engines[i] != NULL)
dce110_engine_destroy(&pool->base.engines[i]);
if (pool->base.hw_i2cs[i] != NULL) {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
index 1ea91e153d3a..4254e7e1a509 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.c
@@ -87,6 +87,23 @@ void hubbub1_wm_read_state(struct hubbub *hubbub,
s->dram_clk_chanage = REG_READ(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D);
}
+void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub)
+{
+ REG_UPDATE(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+ DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, 0);
+}
+
+bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubbub)
+{
+ uint32_t enable = 0;
+
+ REG_GET(DCHUBBUB_ARB_DRAM_STATE_CNTL,
+ DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE, &enable);
+
+ return true ? false : enable;
+}
+
+
bool hubbub1_verify_allow_pstate_change_high(
struct hubbub *hubbub)
{
@@ -116,7 +133,43 @@ bool hubbub1_verify_allow_pstate_change_high(
forced_pstate_allow = false;
}
- /* RV1:
+ /* RV2:
+ * dchubbubdebugind, at: 0xB
+ * description
+ * 0: Pipe0 Plane0 Allow Pstate Change
+ * 1: Pipe0 Plane1 Allow Pstate Change
+ * 2: Pipe0 Cursor0 Allow Pstate Change
+ * 3: Pipe0 Cursor1 Allow Pstate Change
+ * 4: Pipe1 Plane0 Allow Pstate Change
+ * 5: Pipe1 Plane1 Allow Pstate Change
+ * 6: Pipe1 Cursor0 Allow Pstate Change
+ * 7: Pipe1 Cursor1 Allow Pstate Change
+ * 8: Pipe2 Plane0 Allow Pstate Change
+ * 9: Pipe2 Plane1 Allow Pstate Change
+ * 10: Pipe2 Cursor0 Allow Pstate Change
+ * 11: Pipe2 Cursor1 Allow Pstate Change
+ * 12: Pipe3 Plane0 Allow Pstate Change
+ * 13: Pipe3 Plane1 Allow Pstate Change
+ * 14: Pipe3 Cursor0 Allow Pstate Change
+ * 15: Pipe3 Cursor1 Allow Pstate Change
+ * 16: Pipe4 Plane0 Allow Pstate Change
+ * 17: Pipe4 Plane1 Allow Pstate Change
+ * 18: Pipe4 Cursor0 Allow Pstate Change
+ * 19: Pipe4 Cursor1 Allow Pstate Change
+ * 20: Pipe5 Plane0 Allow Pstate Change
+ * 21: Pipe5 Plane1 Allow Pstate Change
+ * 22: Pipe5 Cursor0 Allow Pstate Change
+ * 23: Pipe5 Cursor1 Allow Pstate Change
+ * 24: Pipe6 Plane0 Allow Pstate Change
+ * 25: Pipe6 Plane1 Allow Pstate Change
+ * 26: Pipe6 Cursor0 Allow Pstate Change
+ * 27: Pipe6 Cursor1 Allow Pstate Change
+ * 28: WB0 Allow Pstate Change
+ * 29: WB1 Allow Pstate Change
+ * 30: Arbiter's allow_pstate_change
+ * 31: SOC pstate change request"
+ *
+ * RV1:
* dchubbubdebugind, at: 0x7
* description "3-0: Pipe0 cursor0 QOS
* 7-4: Pipe1 cursor0 QOS
@@ -140,7 +193,6 @@ bool hubbub1_verify_allow_pstate_change_high(
* 31: SOC pstate change request
*/
-
REG_WRITE(DCHUBBUB_TEST_DEBUG_INDEX, hubbub->debug_test_index_pstate);
for (i = 0; i < pstate_wait_timeout_us; i++) {
@@ -802,5 +854,9 @@ void hubbub1_construct(struct hubbub *hubbub,
hubbub->masks = hubbub_mask;
hubbub->debug_test_index_pstate = 0x7;
+#if defined(CONFIG_DRM_AMD_DC_DCN1_01)
+ if (ctx->dce_version == DCN_VERSION_1_01)
+ hubbub->debug_test_index_pstate = 0xB;
+#endif
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index d6e596eef4c5..d0f03d152913 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -203,6 +203,10 @@ void hubbub1_program_watermarks(
unsigned int refclk_mhz,
bool safe_to_lower);
+void hubbub1_disable_allow_self_refresh(struct hubbub *hubbub);
+
+bool hububu1_is_allow_self_refresh_enabled(struct hubbub *hubub);
+
void hubbub1_toggle_watermark_change_req(
struct hubbub *hubbub);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
index a881ff5559ec..193184affefb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
@@ -997,7 +997,21 @@ static void dcn10_init_hw(struct dc *dc)
} else {
if (!dcb->funcs->is_accelerated_mode(dcb)) {
+ bool allow_self_fresh_force_enable =
+ hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub);
+
bios_golden_init(dc);
+
+ /* WA for making DF sleep when idle after resume from S0i3.
+ * DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE is set to 1 by
+ * command table, if DCHUBBUB_ARB_ALLOW_SELF_REFRESH_FORCE_ENABLE = 0
+ * before calling command table and it changed to 1 after,
+ * it should be set back to 0.
+ */
+ if (allow_self_fresh_force_enable == false &&
+ hububu1_is_allow_self_refresh_enabled(dc->res_pool->hubbub))
+ hubbub1_disable_allow_self_refresh(dc->res_pool->hubbub);
+
disable_vga(dc->hwseq);
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
index 6f675206a136..ba6a8686062f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_link_encoder.c
@@ -606,22 +606,10 @@ bool dcn10_link_encoder_validate_dp_output(
const struct dcn10_link_encoder *enc10,
const struct dc_crtc_timing *crtc_timing)
{
- /* default RGB only */
- if (crtc_timing->pixel_encoding == PIXEL_ENCODING_RGB)
- return true;
-
- if (enc10->base.features.flags.bits.IS_YCBCR_CAPABLE)
- return true;
-
- /* for DCE 8.x or later DP Y-only feature,
- * we need ASIC cap + FeatureSupportDPYonly, not support 666
- */
- if (crtc_timing->flags.Y_ONLY &&
- enc10->base.features.flags.bits.IS_YCBCR_CAPABLE &&
- crtc_timing->display_color_depth != COLOR_DEPTH_666)
- return true;
+ if (crtc_timing->pixel_encoding == PIXEL_ENCODING_YCBCR420)
+ return false;
- return false;
+ return true;
}
void dcn10_link_encoder_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
index 411f89218e01..54626682bab2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
@@ -98,7 +98,6 @@ static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_c
struct dc_crtc_timing patched_crtc_timing;
int vesa_sync_start;
int asic_blank_end;
- int interlace_factor;
int vertical_line_start;
patched_crtc_timing = *dc_crtc_timing;
@@ -112,16 +111,13 @@ static uint32_t get_start_vline(struct timing_generator *optc, const struct dc_c
vesa_sync_start -
patched_crtc_timing.h_border_left;
- interlace_factor = patched_crtc_timing.flags.INTERLACE ? 2 : 1;
-
vesa_sync_start = patched_crtc_timing.v_addressable +
patched_crtc_timing.v_border_bottom +
patched_crtc_timing.v_front_porch;
asic_blank_end = (patched_crtc_timing.v_total -
vesa_sync_start -
- patched_crtc_timing.v_border_top)
- * interlace_factor;
+ patched_crtc_timing.v_border_top);
vertical_line_start = asic_blank_end - optc->dlg_otg_param.vstartup_start + 1;
if (vertical_line_start < 0) {
@@ -154,7 +150,7 @@ void optc1_program_vline_interrupt(
req_delta_lines--;
if (req_delta_lines > vsync_line)
- start_line = dc_crtc_timing->v_total - (req_delta_lines - vsync_line) - 1;
+ start_line = dc_crtc_timing->v_total - (req_delta_lines - vsync_line) + 2;
else
start_line = vsync_line - req_delta_lines;
@@ -186,7 +182,6 @@ void optc1_program_timing(
uint32_t v_sync_end;
uint32_t v_init, v_fp2;
uint32_t h_sync_polarity, v_sync_polarity;
- uint32_t interlace_factor;
uint32_t start_point = 0;
uint32_t field_num = 0;
uint32_t h_div_2;
@@ -237,16 +232,8 @@ void optc1_program_timing(
REG_UPDATE(OTG_H_SYNC_A_CNTL,
OTG_H_SYNC_A_POL, h_sync_polarity);
- /* Load vertical timing */
+ v_total = patched_crtc_timing.v_total - 1;
- /* CRTC_V_TOTAL = v_total - 1 */
- if (patched_crtc_timing.flags.INTERLACE) {
- interlace_factor = 2;
- v_total = 2 * patched_crtc_timing.v_total;
- } else {
- interlace_factor = 1;
- v_total = patched_crtc_timing.v_total - 1;
- }
REG_SET(OTG_V_TOTAL, 0,
OTG_V_TOTAL, v_total);
@@ -259,7 +246,7 @@ void optc1_program_timing(
OTG_V_TOTAL_MIN, v_total);
/* v_sync_start = 0, v_sync_end = v_sync_width */
- v_sync_end = patched_crtc_timing.v_sync_width * interlace_factor;
+ v_sync_end = patched_crtc_timing.v_sync_width;
REG_UPDATE_2(OTG_V_SYNC_A,
OTG_V_SYNC_A_START, 0,
@@ -271,15 +258,13 @@ void optc1_program_timing(
asic_blank_end = (patched_crtc_timing.v_total -
vesa_sync_start -
- patched_crtc_timing.v_border_top)
- * interlace_factor;
+ patched_crtc_timing.v_border_top);
/* v_blank_start = v_blank_end + v_active */
asic_blank_start = asic_blank_end +
(patched_crtc_timing.v_border_top +
patched_crtc_timing.v_addressable +
- patched_crtc_timing.v_border_bottom)
- * interlace_factor;
+ patched_crtc_timing.v_border_bottom);
REG_UPDATE_2(OTG_V_BLANK_START_END,
OTG_V_BLANK_START, asic_blank_start,
@@ -301,7 +286,7 @@ void optc1_program_timing(
0 : 1;
REG_UPDATE(OTG_V_SYNC_A_CNTL,
- OTG_V_SYNC_A_POL, v_sync_polarity);
+ OTG_V_SYNC_A_POL, v_sync_polarity);
v_init = asic_blank_start;
if (optc->dlg_otg_param.signal == SIGNAL_TYPE_DISPLAY_PORT ||
@@ -532,7 +517,6 @@ bool optc1_validate_timing(
struct timing_generator *optc,
const struct dc_crtc_timing *timing)
{
- uint32_t interlace_factor;
uint32_t v_blank;
uint32_t h_blank;
uint32_t min_v_blank;
@@ -540,10 +524,8 @@ bool optc1_validate_timing(
ASSERT(timing != NULL);
- interlace_factor = timing->flags.INTERLACE ? 2 : 1;
v_blank = (timing->v_total - timing->v_addressable -
- timing->v_border_top - timing->v_border_bottom) *
- interlace_factor;
+ timing->v_border_top - timing->v_border_bottom);
h_blank = (timing->h_total - timing->h_addressable -
timing->h_border_right -
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
index cb1b134b8fcb..a71453a15ae3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -507,6 +507,18 @@ static const struct resource_caps res_cap = {
.num_ddc = 4,
};
+#if defined(CONFIG_DRM_AMD_DC_DCN1_01)
+static const struct resource_caps rv2_res_cap = {
+ .num_timing_generator = 3,
+ .num_opp = 3,
+ .num_video_plane = 3,
+ .num_audio = 3,
+ .num_stream_encoder = 3,
+ .num_pll = 3,
+ .num_ddc = 3,
+};
+#endif
+
static const struct dc_debug_options debug_defaults_drv = {
.sanity_checks = true,
.disable_dmcu = true,
@@ -711,8 +723,7 @@ static const struct encoder_feature_support link_enc_feature = {
.flags.bits.IS_HBR2_CAPABLE = true,
.flags.bits.IS_HBR3_CAPABLE = true,
.flags.bits.IS_TPS3_CAPABLE = true,
- .flags.bits.IS_TPS4_CAPABLE = true,
- .flags.bits.IS_YCBCR_CAPABLE = true
+ .flags.bits.IS_TPS4_CAPABLE = true
};
struct link_encoder *dcn10_link_encoder_create(
@@ -897,7 +908,9 @@ static void destruct(struct dcn10_resource_pool *pool)
kfree(DCN10TG_FROM_TG(pool->base.timing_generators[i]));
pool->base.timing_generators[i] = NULL;
}
+ }
+ for (i = 0; i < pool->base.res_cap->num_ddc; i++) {
if (pool->base.engines[i] != NULL)
pool->base.engines[i]->funcs->destroy_engine(&pool->base.engines[i]);
if (pool->base.hw_i2cs[i] != NULL) {
@@ -1119,6 +1132,24 @@ static enum dc_status dcn10_validate_plane(const struct dc_plane_state *plane_st
return DC_OK;
}
+static enum dc_status dcn10_get_default_swizzle_mode(struct dc_plane_state *plane_state)
+{
+ enum dc_status result = DC_OK;
+
+ enum surface_pixel_format surf_pix_format = plane_state->format;
+ unsigned int bpp = resource_pixel_format_to_bpp(surf_pix_format);
+
+ enum swizzle_mode_values swizzle = DC_SW_LINEAR;
+
+ if (bpp == 64)
+ swizzle = DC_SW_64KB_D;
+ else
+ swizzle = DC_SW_64KB_S;
+
+ plane_state->tiling_info.gfx9.swizzle = swizzle;
+ return result;
+}
+
static const struct dc_cap_funcs cap_funcs = {
.get_dcc_compression_cap = dcn10_get_dcc_compression_cap
};
@@ -1129,7 +1160,8 @@ static const struct resource_funcs dcn10_res_pool_funcs = {
.validate_bandwidth = dcn_validate_bandwidth,
.acquire_idle_pipe_for_layer = dcn10_acquire_idle_pipe_for_layer,
.validate_plane = dcn10_validate_plane,
- .add_stream_to_ctx = dcn10_add_stream_to_ctx
+ .add_stream_to_ctx = dcn10_add_stream_to_ctx,
+ .get_default_swizzle_mode = dcn10_get_default_swizzle_mode
};
static uint32_t read_pipe_fuses(struct dc_context *ctx)
@@ -1152,7 +1184,12 @@ static bool construct(
ctx->dc_bios->regs = &bios_regs;
- pool->base.res_cap = &res_cap;
+#if defined(CONFIG_DRM_AMD_DC_DCN1_01)
+ if (ctx->dce_version == DCN_VERSION_1_01)
+ pool->base.res_cap = &rv2_res_cap;
+ else
+#endif
+ pool->base.res_cap = &res_cap;
pool->base.funcs = &dcn10_res_pool_funcs;
/*
diff --git a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
index 8eee8ace1259..59c3ed43d609 100644
--- a/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
+++ b/drivers/gpu/drm/amd/display/dc/i2caux/dce110/aux_engine_dce110.c
@@ -346,7 +346,7 @@ static void process_channel_reply(
/* in case HPD is LOW, exit AUX transaction */
if ((sw_status & AUX_SW_STATUS__AUX_SW_HPD_DISCON_MASK)) {
- reply->status = AUX_CHANNEL_OPERATION_FAILED_HPD_DISCON;
+ reply->status = AUX_TRANSACTION_REPLY_HPD_DISCON;
return;
}
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 831a1bdf622c..c1976c175b57 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -120,6 +120,9 @@ struct resource_funcs {
struct dc *dc,
struct dc_state *new_ctx,
struct dc_stream_state *stream);
+ enum dc_status (*get_default_swizzle_mode)(
+ struct dc_plane_state *plane_state);
+
};
struct audio_support{
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
index 58818920ed41..e28e9770e0a3 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h
@@ -58,7 +58,6 @@ struct encoder_feature_support {
uint32_t IS_HBR3_CAPABLE:1;
uint32_t IS_TPS3_CAPABLE:1;
uint32_t IS_TPS4_CAPABLE:1;
- uint32_t IS_YCBCR_CAPABLE:1;
uint32_t HDMI_6GB_EN:1;
} bits;
uint32_t raw;
diff --git a/drivers/gpu/drm/amd/display/dc/inc/resource.h b/drivers/gpu/drm/amd/display/dc/inc/resource.h
index 76d00c6dbca9..33b99e3ab10d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/resource.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/resource.h
@@ -172,4 +172,7 @@ void update_audio_usage(
const struct resource_pool *pool,
struct audio *audio,
bool acquired);
+
+unsigned int resource_pixel_format_to_bpp(enum surface_pixel_format format);
+
#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_RESOURCE_H_ */
diff --git a/drivers/gpu/drm/amd/display/include/signal_types.h b/drivers/gpu/drm/amd/display/include/signal_types.h
index 03476b142d8e..f56d2891475f 100644
--- a/drivers/gpu/drm/amd/display/include/signal_types.h
+++ b/drivers/gpu/drm/amd/display/include/signal_types.h
@@ -102,4 +102,9 @@ static inline bool dc_is_audio_capable_signal(enum signal_type signal)
dc_is_hdmi_signal(signal));
}
+static inline bool dc_is_virtual_signal(enum signal_type signal)
+{
+ return (signal == SIGNAL_TYPE_VIRTUAL);
+}
+
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_offset.h
index 4ce090db7ef7..529b37db274c 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/gc/gc_9_0_offset.h
@@ -2449,6 +2449,8 @@
#define mmCP_ECC_FIRSTOCCURRENCE_RING2_BASE_IDX 0
#define mmGB_EDC_MODE 0x107e
#define mmGB_EDC_MODE_BASE_IDX 0
+#define mmCP_DEBUG 0x107f
+#define mmCP_DEBUG_BASE_IDX 0
#define mmCP_CPF_DEBUG 0x1080
#define mmCP_PQ_WPTR_POLL_CNTL 0x1083
#define mmCP_PQ_WPTR_POLL_CNTL_BASE_IDX 0
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_offset.h
index efd2704d0f8f..0d6891095f62 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_offset.h
@@ -175,4 +175,7 @@
#define mmSMUSVI0_PLANE0_CURRENTVID_BASE_IDX 0
#define mmSMUSVI0_PLANE0_CURRENTVID 0x0013
+#define mmSMUSVI0_TEL_PLANE0_BASE_IDX 0
+#define mmSMUSVI0_TEL_PLANE0 0x0004
+
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_sh_mask.h
index 2487ab9621e9..b1d9d8be1119 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/smuio/smuio_9_0_sh_mask.h
@@ -258,4 +258,7 @@
#define SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID__SHIFT 0x18
#define SMUSVI0_PLANE0_CURRENTVID__CURRENT_SVI0_PLANE0_VID_MASK 0xFF000000L
+#define SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT 0x10
+#define SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK 0x01FF0000L
+
#endif
diff --git a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
index 510ec3c70626..a9eb57a53e59 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_offset.h
@@ -26,6 +26,18 @@
#define mmCG_MULT_THERMAL_STATUS 0x005f
#define mmCG_MULT_THERMAL_STATUS_BASE_IDX 0
+#define mmCG_FDO_CTRL0 0x0067
+#define mmCG_FDO_CTRL0_BASE_IDX 0
+
+#define mmCG_FDO_CTRL1 0x0068
+#define mmCG_FDO_CTRL1_BASE_IDX 0
+
+#define mmCG_FDO_CTRL2 0x0069
+#define mmCG_FDO_CTRL2_BASE_IDX 0
+
+#define mmCG_TACH_CTRL 0x006a
+#define mmCG_TACH_CTRL_BASE_IDX 0
+
#define mmTHM_THERMAL_INT_ENA 0x000a
#define mmTHM_THERMAL_INT_ENA_BASE_IDX 0
#define mmTHM_THERMAL_INT_CTRL 0x000b
diff --git a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
index f69533fa6abf..d130d92aee19 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/thm/thm_11_0_2_sh_mask.h
@@ -28,6 +28,16 @@
#define CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT 0x9
#define CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP_MASK 0x000001FFL
#define CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK 0x0003FE00L
+#define CG_FDO_CTRL2__TMIN__SHIFT 0x0
+#define CG_FDO_CTRL2__TMIN_MASK 0x000000FFL
+#define CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT 0xb
+#define CG_FDO_CTRL2__FDO_PWM_MODE_MASK 0x00003800L
+#define CG_FDO_CTRL1__FMAX_DUTY100__SHIFT 0x0
+#define CG_FDO_CTRL1__FMAX_DUTY100_MASK 0x000000FFL
+#define CG_FDO_CTRL0__FDO_STATIC_DUTY__SHIFT 0x0
+#define CG_FDO_CTRL0__FDO_STATIC_DUTY_MASK 0x000000FFL
+#define CG_TACH_CTRL__TARGET_PERIOD__SHIFT 0x3
+#define CG_TACH_CTRL__TARGET_PERIOD_MASK 0xFFFFFFF8L
//THM_THERMAL_INT_ENA
#define THM_THERMAL_INT_ENA__THERM_INTH_SET__SHIFT 0x0
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index bd7404532029..980e696989b1 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -114,6 +114,8 @@ enum amd_pp_sensors {
AMDGPU_PP_SENSOR_STABLE_PSTATE_SCLK,
AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK,
AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK,
+ AMDGPU_PP_SENSOR_MIN_FAN_RPM,
+ AMDGPU_PP_SENSOR_MAX_FAN_RPM,
};
enum amd_pp_task {
@@ -228,6 +230,7 @@ struct amd_pm_funcs {
enum amd_dpm_forced_level (*get_performance_level)(void *handle);
enum amd_pm_state_type (*get_current_power_state)(void *handle);
int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm);
+ int (*set_fan_speed_rpm)(void *handle, uint32_t rpm);
int (*get_pp_num_states)(void *handle, struct pp_states_info *data);
int (*get_pp_table)(void *handle, char **table);
int (*set_pp_table)(void *handle, const char *buf, size_t size);
@@ -272,6 +275,7 @@ struct amd_pm_funcs {
int (*get_display_mode_validation_clocks)(void *handle,
struct amd_pp_simple_clock_info *clocks);
int (*notify_smu_enable_pwe)(void *handle);
+ int (*enable_mgpu_fan_boost)(void *handle);
};
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
index da4ebff5b74d..75b56ae032ce 100644
--- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c
@@ -109,11 +109,8 @@ static int pp_sw_fini(void *handle)
hwmgr_sw_fini(hwmgr);
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) {
- release_firmware(adev->pm.fw);
- adev->pm.fw = NULL;
- amdgpu_ucode_fini_bo(adev);
- }
+ release_firmware(adev->pm.fw);
+ adev->pm.fw = NULL;
return 0;
}
@@ -124,9 +121,6 @@ static int pp_hw_init(void *handle)
struct amdgpu_device *adev = handle;
struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
- if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU)
- amdgpu_ucode_init_bo(adev);
-
ret = hwmgr_hw_init(hwmgr);
if (ret)
@@ -273,8 +267,23 @@ const struct amdgpu_ip_block_version pp_smu_ip_block =
.funcs = &pp_ip_funcs,
};
+/* This interface only be supported On Vi,
+ * because only smu7/8 can help to load gfx/sdma fw,
+ * smu need to be enabled before load other ip's fw.
+ * so call start smu to load smu7 fw and other ip's fw
+ */
static int pp_dpm_load_fw(void *handle)
{
+ struct pp_hwmgr *hwmgr = handle;
+
+ if (!hwmgr || !hwmgr->smumgr_funcs || !hwmgr->smumgr_funcs->start_smu)
+ return -EINVAL;
+
+ if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {
+ pr_err("fw load failed\n");
+ return -EINVAL;
+ }
+
return 0;
}
@@ -576,6 +585,24 @@ static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm)
return ret;
}
+static int pp_dpm_set_fan_speed_rpm(void *handle, uint32_t rpm)
+{
+ struct pp_hwmgr *hwmgr = handle;
+ int ret = 0;
+
+ if (!hwmgr || !hwmgr->pm_en)
+ return -EINVAL;
+
+ if (hwmgr->hwmgr_func->set_fan_speed_rpm == NULL) {
+ pr_info("%s was not implemented.\n", __func__);
+ return 0;
+ }
+ mutex_lock(&hwmgr->smu_lock);
+ ret = hwmgr->hwmgr_func->set_fan_speed_rpm(hwmgr, rpm);
+ mutex_unlock(&hwmgr->smu_lock);
+ return ret;
+}
+
static int pp_dpm_get_pp_num_states(void *handle,
struct pp_states_info *data)
{
@@ -813,6 +840,12 @@ static int pp_dpm_read_sensor(void *handle, int idx,
case AMDGPU_PP_SENSOR_STABLE_PSTATE_MCLK:
*((uint32_t *)value) = hwmgr->pstate_mclk;
return 0;
+ case AMDGPU_PP_SENSOR_MIN_FAN_RPM:
+ *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMinRPM;
+ return 0;
+ case AMDGPU_PP_SENSOR_MAX_FAN_RPM:
+ *((uint32_t *)value) = hwmgr->thermal_controller.fanInfo.ulMaxRPM;
+ return 0;
default:
mutex_lock(&hwmgr->smu_lock);
ret = hwmgr->hwmgr_func->read_sensor(hwmgr, idx, value, size);
@@ -1196,6 +1229,21 @@ static void pp_dpm_powergate_acp(void *handle, bool gate)
hwmgr->hwmgr_func->powergate_acp(hwmgr, gate);
}
+static void pp_dpm_powergate_sdma(void *handle, bool gate)
+{
+ struct pp_hwmgr *hwmgr = handle;
+
+ if (!hwmgr)
+ return;
+
+ if (hwmgr->hwmgr_func->powergate_sdma == NULL) {
+ pr_info("%s was not implemented.\n", __func__);
+ return;
+ }
+
+ hwmgr->hwmgr_func->powergate_sdma(hwmgr, gate);
+}
+
static int pp_set_powergating_by_smu(void *handle,
uint32_t block_type, bool gate)
{
@@ -1218,6 +1266,9 @@ static int pp_set_powergating_by_smu(void *handle,
case AMD_IP_BLOCK_TYPE_ACP:
pp_dpm_powergate_acp(handle, gate);
break;
+ case AMD_IP_BLOCK_TYPE_SDMA:
+ pp_dpm_powergate_sdma(handle, gate);
+ break;
default:
break;
}
@@ -1243,6 +1294,24 @@ static int pp_notify_smu_enable_pwe(void *handle)
return 0;
}
+static int pp_enable_mgpu_fan_boost(void *handle)
+{
+ struct pp_hwmgr *hwmgr = handle;
+
+ if (!hwmgr || !hwmgr->pm_en)
+ return -EINVAL;
+
+ if (hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) {
+ return 0;
+ }
+
+ mutex_lock(&hwmgr->smu_lock);
+ hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr);
+ mutex_unlock(&hwmgr->smu_lock);
+
+ return 0;
+}
+
static const struct amd_pm_funcs pp_dpm_funcs = {
.load_firmware = pp_dpm_load_fw,
.wait_for_fw_loading_complete = pp_dpm_fw_loading_complete,
@@ -1255,6 +1324,7 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
.set_fan_speed_percent = pp_dpm_set_fan_speed_percent,
.get_fan_speed_percent = pp_dpm_get_fan_speed_percent,
.get_fan_speed_rpm = pp_dpm_get_fan_speed_rpm,
+ .set_fan_speed_rpm = pp_dpm_set_fan_speed_rpm,
.get_pp_num_states = pp_dpm_get_pp_num_states,
.get_pp_table = pp_dpm_get_pp_table,
.set_pp_table = pp_dpm_set_pp_table,
@@ -1287,4 +1357,5 @@ static const struct amd_pm_funcs pp_dpm_funcs = {
.display_clock_voltage_request = pp_display_clock_voltage_request,
.get_display_mode_validation_clocks = pp_get_display_mode_validation_clocks,
.notify_smu_enable_pwe = pp_notify_smu_enable_pwe,
+ .enable_mgpu_fan_boost = pp_enable_mgpu_fan_boost,
};
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
index 7500a3e61dba..47ac92369739 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c
@@ -89,7 +89,6 @@ int hwmgr_early_init(struct pp_hwmgr *hwmgr)
hwmgr_init_default_caps(hwmgr);
hwmgr_set_user_specify_caps(hwmgr);
hwmgr->fan_ctrl_is_in_default_mode = true;
- hwmgr->reload_fw = 1;
hwmgr_init_workload_prority(hwmgr);
switch (hwmgr->chip_family) {
@@ -209,17 +208,6 @@ int hwmgr_hw_init(struct pp_hwmgr *hwmgr)
{
int ret = 0;
- if (!hwmgr || !hwmgr->smumgr_funcs)
- return -EINVAL;
-
- if (hwmgr->smumgr_funcs->start_smu) {
- ret = hwmgr->smumgr_funcs->start_smu(hwmgr);
- if (ret) {
- pr_err("smc start failed\n");
- return -EINVAL;
- }
- }
-
if (!hwmgr->pm_en)
return 0;
@@ -320,13 +308,6 @@ int hwmgr_resume(struct pp_hwmgr *hwmgr)
if (!hwmgr)
return -EINVAL;
- if (hwmgr->smumgr_funcs && hwmgr->smumgr_funcs->start_smu) {
- if (hwmgr->smumgr_funcs->start_smu(hwmgr)) {
- pr_err("smc start failed\n");
- return -EINVAL;
- }
- }
-
if (!hwmgr->pm_en)
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
index 5d1dae25a466..dd18cb710391 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu10_hwmgr.c
@@ -1153,6 +1153,14 @@ static int smu10_powergate_mmhub(struct pp_hwmgr *hwmgr)
return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerGateMmHub);
}
+static int smu10_powergate_sdma(struct pp_hwmgr *hwmgr, bool gate)
+{
+ if (gate)
+ return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerDownSdma);
+ else
+ return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_PowerUpSdma);
+}
+
static void smu10_powergate_vcn(struct pp_hwmgr *hwmgr, bool bgate)
{
if (bgate) {
@@ -1208,6 +1216,7 @@ static const struct pp_hwmgr_func smu10_hwmgr_funcs = {
.smus_notify_pwe = smu10_smus_notify_pwe,
.display_clock_voltage_request = smu10_display_clock_voltage_request,
.powergate_gfx = smu10_gfx_off_control,
+ .powergate_sdma = smu10_powergate_sdma,
};
int smu10_init_function_pointers(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c
index 44527755e747..5bdc0df5a9f4 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c
@@ -260,6 +260,7 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
if (hwmgr->thermal_controller.fanInfo.bNoFan ||
(hwmgr->thermal_controller.fanInfo.
ucTachometerPulsesPerRevolution == 0) ||
+ speed == 0 ||
(speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
(speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
return 0;
@@ -272,7 +273,7 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
- CG_TACH_STATUS, TACH_PERIOD, tach_period);
+ CG_TACH_CTRL, TARGET_PERIOD, tach_period);
return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
}
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c
index 53cf787560f7..fef111ddb736 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu8_hwmgr.c
@@ -1228,14 +1228,17 @@ static int smu8_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
static int smu8_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr)
{
- if (PP_CAP(PHM_PlatformCaps_UVDPowerGating))
+ if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) {
+ smu8_nbdpm_pstate_enable_disable(hwmgr, true, true);
return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF);
+ }
return 0;
}
static int smu8_dpm_powerup_uvd(struct pp_hwmgr *hwmgr)
{
if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) {
+ smu8_nbdpm_pstate_enable_disable(hwmgr, false, true);
return smum_send_msg_to_smc_with_parameter(
hwmgr,
PPSMC_MSG_UVDPowerON,
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
index 8ad4e6960efd..4714b5b59825 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c
@@ -39,6 +39,50 @@ uint16_t convert_to_vddc(uint8_t vid)
return (uint16_t) ((6200 - (vid * 25)) / VOLTAGE_SCALE);
}
+int phm_copy_clock_limits_array(
+ struct pp_hwmgr *hwmgr,
+ uint32_t **pptable_info_array,
+ const uint32_t *pptable_array,
+ uint32_t power_saving_clock_count)
+{
+ uint32_t array_size, i;
+ uint32_t *table;
+
+ array_size = sizeof(uint32_t) * power_saving_clock_count;
+ table = kzalloc(array_size, GFP_KERNEL);
+ if (NULL == table)
+ return -ENOMEM;
+
+ for (i = 0; i < power_saving_clock_count; i++)
+ table[i] = le32_to_cpu(pptable_array[i]);
+
+ *pptable_info_array = table;
+
+ return 0;
+}
+
+int phm_copy_overdrive_settings_limits_array(
+ struct pp_hwmgr *hwmgr,
+ uint32_t **pptable_info_array,
+ const uint32_t *pptable_array,
+ uint32_t od_setting_count)
+{
+ uint32_t array_size, i;
+ uint32_t *table;
+
+ array_size = sizeof(uint32_t) * od_setting_count;
+ table = kzalloc(array_size, GFP_KERNEL);
+ if (NULL == table)
+ return -ENOMEM;
+
+ for (i = 0; i < od_setting_count; i++)
+ table[i] = le32_to_cpu(pptable_array[i]);
+
+ *pptable_info_array = table;
+
+ return 0;
+}
+
uint32_t phm_set_field_to_u32(u32 offset, u32 original_data, u32 field, u32 size)
{
u32 mask = 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h
index 5454289d5226..ad33983a8064 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.h
@@ -47,6 +47,18 @@ struct watermarks {
uint32_t padding[7];
};
+int phm_copy_clock_limits_array(
+ struct pp_hwmgr *hwmgr,
+ uint32_t **pptable_info_array,
+ const uint32_t *pptable_array,
+ uint32_t power_saving_clock_count);
+
+int phm_copy_overdrive_settings_limits_array(
+ struct pp_hwmgr *hwmgr,
+ uint32_t **pptable_info_array,
+ const uint32_t *pptable_array,
+ uint32_t od_setting_count);
+
extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr,
uint32_t index,
uint32_t value, uint32_t mask);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
index 16b1a9cf6cf0..b8747a5c9204 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
@@ -451,23 +451,23 @@ static int get_tdp_table(
le16_to_cpu(power_tune_table_v2->usLoadLineResistance);
} else {
power_tune_table_v3 = (ATOM_Vega10_PowerTune_Table_V3 *)table;
- tdp_table->usMaximumPowerDeliveryLimit = power_tune_table_v3->usSocketPowerLimit;
- tdp_table->usTDC = power_tune_table_v3->usTdcLimit;
- tdp_table->usEDCLimit = power_tune_table_v3->usEdcLimit;
- tdp_table->usSoftwareShutdownTemp = power_tune_table_v3->usSoftwareShutdownTemp;
- tdp_table->usTemperatureLimitTedge = power_tune_table_v3->usTemperatureLimitTedge;
- tdp_table->usTemperatureLimitHotspot = power_tune_table_v3->usTemperatureLimitHotSpot;
- tdp_table->usTemperatureLimitLiquid1 = power_tune_table_v3->usTemperatureLimitLiquid1;
- tdp_table->usTemperatureLimitLiquid2 = power_tune_table_v3->usTemperatureLimitLiquid2;
- tdp_table->usTemperatureLimitHBM = power_tune_table_v3->usTemperatureLimitHBM;
- tdp_table->usTemperatureLimitVrVddc = power_tune_table_v3->usTemperatureLimitVrSoc;
- tdp_table->usTemperatureLimitVrMvdd = power_tune_table_v3->usTemperatureLimitVrMem;
- tdp_table->usTemperatureLimitPlx = power_tune_table_v3->usTemperatureLimitPlx;
+ tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v3->usSocketPowerLimit);
+ tdp_table->usTDC = le16_to_cpu(power_tune_table_v3->usTdcLimit);
+ tdp_table->usEDCLimit = le16_to_cpu(power_tune_table_v3->usEdcLimit);
+ tdp_table->usSoftwareShutdownTemp = le16_to_cpu(power_tune_table_v3->usSoftwareShutdownTemp);
+ tdp_table->usTemperatureLimitTedge = le16_to_cpu(power_tune_table_v3->usTemperatureLimitTedge);
+ tdp_table->usTemperatureLimitHotspot = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHotSpot);
+ tdp_table->usTemperatureLimitLiquid1 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid1);
+ tdp_table->usTemperatureLimitLiquid2 = le16_to_cpu(power_tune_table_v3->usTemperatureLimitLiquid2);
+ tdp_table->usTemperatureLimitHBM = le16_to_cpu(power_tune_table_v3->usTemperatureLimitHBM);
+ tdp_table->usTemperatureLimitVrVddc = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrSoc);
+ tdp_table->usTemperatureLimitVrMvdd = le16_to_cpu(power_tune_table_v3->usTemperatureLimitVrMem);
+ tdp_table->usTemperatureLimitPlx = le16_to_cpu(power_tune_table_v3->usTemperatureLimitPlx);
tdp_table->ucLiquid1_I2C_address = power_tune_table_v3->ucLiquid1_I2C_address;
tdp_table->ucLiquid2_I2C_address = power_tune_table_v3->ucLiquid2_I2C_address;
- tdp_table->usBoostStartTemperature = power_tune_table_v3->usBoostStartTemperature;
- tdp_table->usBoostStopTemperature = power_tune_table_v3->usBoostStopTemperature;
- tdp_table->ulBoostClock = power_tune_table_v3->ulBoostClock;
+ tdp_table->usBoostStartTemperature = le16_to_cpu(power_tune_table_v3->usBoostStartTemperature);
+ tdp_table->usBoostStopTemperature = le16_to_cpu(power_tune_table_v3->usBoostStopTemperature);
+ tdp_table->ulBoostClock = le32_to_cpu(power_tune_table_v3->ulBoostClock);
get_scl_sda_value(power_tune_table_v3->ucLiquid_I2C_Line, &scl, &sda);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
index 407762b36901..3f807d6c95ce 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
@@ -312,6 +312,7 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
int result = 0;
if (hwmgr->thermal_controller.fanInfo.bNoFan ||
+ speed == 0 ||
(speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) ||
(speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM))
return -1;
@@ -322,9 +323,9 @@ int vega10_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
if (!result) {
crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
- WREG32_SOC15(THM, 0, mmCG_TACH_STATUS,
- REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_STATUS),
- CG_TACH_STATUS, TACH_PERIOD,
+ WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
+ CG_TACH_CTRL, TARGET_PERIOD,
tach_period));
}
return vega10_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c
index cb3a5b1737c8..9817f7a5ed29 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_processpptables.c
@@ -99,50 +99,6 @@ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
return 0;
}
-static int copy_clock_limits_array(
- struct pp_hwmgr *hwmgr,
- uint32_t **pptable_info_array,
- const uint32_t *pptable_array)
-{
- uint32_t array_size, i;
- uint32_t *table;
-
- array_size = sizeof(uint32_t) * ATOM_VEGA12_PPCLOCK_COUNT;
-
- table = kzalloc(array_size, GFP_KERNEL);
- if (NULL == table)
- return -ENOMEM;
-
- for (i = 0; i < ATOM_VEGA12_PPCLOCK_COUNT; i++)
- table[i] = pptable_array[i];
-
- *pptable_info_array = table;
-
- return 0;
-}
-
-static int copy_overdrive_settings_limits_array(
- struct pp_hwmgr *hwmgr,
- uint32_t **pptable_info_array,
- const uint32_t *pptable_array)
-{
- uint32_t array_size, i;
- uint32_t *table;
-
- array_size = sizeof(uint32_t) * ATOM_VEGA12_ODSETTING_COUNT;
-
- table = kzalloc(array_size, GFP_KERNEL);
- if (NULL == table)
- return -ENOMEM;
-
- for (i = 0; i < ATOM_VEGA12_ODSETTING_COUNT; i++)
- table[i] = pptable_array[i];
-
- *pptable_info_array = table;
-
- return 0;
-}
-
static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable)
{
struct pp_atomfwctrl_smc_dpm_parameters smc_dpm_table;
@@ -250,14 +206,22 @@ static int init_powerplay_table_information(
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
- if (powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX] > VEGA12_ENGINECLOCK_HARDMAX)
+ if (le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]) > VEGA12_ENGINECLOCK_HARDMAX)
hwmgr->platform_descriptor.overdriveLimit.engineClock = VEGA12_ENGINECLOCK_HARDMAX;
else
- hwmgr->platform_descriptor.overdriveLimit.engineClock = powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX];
- hwmgr->platform_descriptor.overdriveLimit.memoryClock = powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_UCLKFMAX];
-
- copy_overdrive_settings_limits_array(hwmgr, &pptable_information->od_settings_max, powerplay_table->ODSettingsMax);
- copy_overdrive_settings_limits_array(hwmgr, &pptable_information->od_settings_min, powerplay_table->ODSettingsMin);
+ hwmgr->platform_descriptor.overdriveLimit.engineClock =
+ le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_GFXCLKFMAX]);
+ hwmgr->platform_descriptor.overdriveLimit.memoryClock =
+ le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_UCLKFMAX]);
+
+ phm_copy_overdrive_settings_limits_array(hwmgr,
+ &pptable_information->od_settings_max,
+ powerplay_table->ODSettingsMax,
+ ATOM_VEGA12_ODSETTING_COUNT);
+ phm_copy_overdrive_settings_limits_array(hwmgr,
+ &pptable_information->od_settings_min,
+ powerplay_table->ODSettingsMin,
+ ATOM_VEGA12_ODSETTING_COUNT);
/* hwmgr->platformDescriptor.minOverdriveVDDC = 0;
hwmgr->platformDescriptor.maxOverdriveVDDC = 0;
@@ -267,15 +231,15 @@ static int init_powerplay_table_information(
&& hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0)
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ACOverdriveSupport);
- pptable_information->us_small_power_limit1 = powerplay_table->usSmallPowerLimit1;
- pptable_information->us_small_power_limit2 = powerplay_table->usSmallPowerLimit2;
- pptable_information->us_boost_power_limit = powerplay_table->usBoostPowerLimit;
- pptable_information->us_od_turbo_power_limit = powerplay_table->usODTurboPowerLimit;
- pptable_information->us_od_powersave_power_limit = powerplay_table->usODPowerSavePowerLimit;
+ pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1);
+ pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2);
+ pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit);
+ pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit);
+ pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit);
- pptable_information->us_software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
+ pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp);
- hwmgr->platform_descriptor.TDPODLimit = (uint16_t)powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_POWERPERCENTAGE];
+ hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->ODSettingsMax[ATOM_VEGA12_ODSETTING_POWERPERCENTAGE]);
disable_power_control = 0;
if (!disable_power_control) {
@@ -285,8 +249,8 @@ static int init_powerplay_table_information(
PHM_PlatformCaps_PowerControl);
}
- copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax);
- copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin);
+ phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_max, powerplay_table->PowerSavingClockMax, ATOM_VEGA12_PPCLOCK_COUNT);
+ phm_copy_clock_limits_array(hwmgr, &pptable_information->power_saving_clock_min, powerplay_table->PowerSavingClockMin, ATOM_VEGA12_PPCLOCK_COUNT);
pptable_information->smc_pptable = (PPTable_t *)kmalloc(sizeof(PPTable_t), GFP_KERNEL);
if (pptable_information->smc_pptable == NULL)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
index 2a554f9edcda..958af7b48827 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c
@@ -46,6 +46,9 @@
#include "ppinterrupt.h"
#include "pp_overdriver.h"
#include "pp_thermal.h"
+#include "soc15_common.h"
+#include "smuio/smuio_9_0_offset.h"
+#include "smuio/smuio_9_0_sh_mask.h"
static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)
{
@@ -1474,6 +1477,19 @@ static int vega20_init_max_sustainable_clocks(struct pp_hwmgr *hwmgr)
return 0;
}
+static int vega20_enable_mgpu_fan_boost(struct pp_hwmgr *hwmgr)
+{
+ int result;
+
+ result = smum_send_msg_to_smc(hwmgr,
+ PPSMC_MSG_SetMGpuFanBoostLimitRpm);
+ PP_ASSERT_WITH_CODE(!result,
+ "[EnableMgpuFan] Failed to enable mgpu fan boost!",
+ return result);
+
+ return 0;
+}
+
static void vega20_init_powergate_state(struct pp_hwmgr *hwmgr)
{
struct vega20_hwmgr *data =
@@ -1544,6 +1560,14 @@ static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
"[EnableDPMTasks] Failed to populate umdpstate clocks!",
return result);
+ result = smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_GetPptLimit,
+ POWER_SOURCE_AC << 16);
+ PP_ASSERT_WITH_CODE(!result,
+ "[GetPptLimit] get default PPT limit failed!",
+ return result);
+ hwmgr->power_limit =
+ hwmgr->default_power_limit = smum_get_argument(hwmgr);
+
return 0;
}
@@ -1907,6 +1931,8 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
void *value, int *size)
{
struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
+ struct amdgpu_device *adev = hwmgr->adev;
+ uint32_t val_vid;
int ret = 0;
switch (idx) {
@@ -1941,6 +1967,13 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,
*size = 16;
ret = vega20_get_gpu_power(hwmgr, (uint32_t *)value);
break;
+ case AMDGPU_PP_SENSOR_VDDGFX:
+ val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) &
+ SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >>
+ SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT;
+ *((uint32_t *)value) =
+ (uint32_t)convert_to_vddc((uint8_t)val_vid);
+ break;
case AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK:
ret = vega20_get_enabled_smc_features(hwmgr, (uint64_t *)value);
if (!ret)
@@ -2269,6 +2302,25 @@ static uint32_t vega20_get_fan_control_mode(struct pp_hwmgr *hwmgr)
return AMD_FAN_CTRL_AUTO;
}
+static void vega20_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+ switch (mode) {
+ case AMD_FAN_CTRL_NONE:
+ vega20_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+ break;
+ case AMD_FAN_CTRL_MANUAL:
+ if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
+ vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
+ break;
+ case AMD_FAN_CTRL_AUTO:
+ if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
+ vega20_fan_ctrl_start_smc_fan_control(hwmgr);
+ break;
+ default:
+ break;
+ }
+}
+
static int vega20_get_dal_power_level(struct pp_hwmgr *hwmgr,
struct amd_pp_simple_clock_info *info)
{
@@ -3165,7 +3217,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
"[GetPowerProfile] Failed to get activity monitor!",
return result);
- size += sprintf(buf + size, "%2d(%14s%s)\n",
+ size += sprintf(buf + size, "%2d %14s%s:\n",
i, profile_name[i], (i == hwmgr->power_profile_mode) ? "*" : " ");
size += sprintf(buf + size, "%19s %d(%13s) %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
@@ -3432,15 +3484,25 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = {
.disable_smc_firmware_ctf =
vega20_thermal_disable_alert,
/* fan control related */
+ .get_fan_speed_percent =
+ vega20_fan_ctrl_get_fan_speed_percent,
+ .set_fan_speed_percent =
+ vega20_fan_ctrl_set_fan_speed_percent,
.get_fan_speed_info =
vega20_fan_ctrl_get_fan_speed_info,
.get_fan_speed_rpm =
vega20_fan_ctrl_get_fan_speed_rpm,
+ .set_fan_speed_rpm =
+ vega20_fan_ctrl_set_fan_speed_rpm,
.get_fan_control_mode =
vega20_get_fan_control_mode,
+ .set_fan_control_mode =
+ vega20_set_fan_control_mode,
/* smu memory related */
.notify_cac_buffer_info =
vega20_notify_cac_buffer_info,
+ .enable_mgpu_fan_boost =
+ vega20_enable_mgpu_fan_boost,
};
int vega20_hwmgr_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c
index 5f1f7a32ac24..32fe38452094 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c
@@ -661,50 +661,6 @@ static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps)
return 0;
}
-static int copy_clock_limits_array(
- struct pp_hwmgr *hwmgr,
- uint32_t **pptable_info_array,
- const uint32_t *pptable_array,
- uint32_t power_saving_clock_count)
-{
- uint32_t array_size, i;
- uint32_t *table;
-
- array_size = sizeof(uint32_t) * power_saving_clock_count;
- table = kzalloc(array_size, GFP_KERNEL);
- if (NULL == table)
- return -ENOMEM;
-
- for (i = 0; i < power_saving_clock_count; i++)
- table[i] = pptable_array[i];
-
- *pptable_info_array = table;
-
- return 0;
-}
-
-static int copy_overdrive_settings_limits_array(
- struct pp_hwmgr *hwmgr,
- uint32_t **pptable_info_array,
- const uint32_t *pptable_array,
- uint32_t od_setting_count)
-{
- uint32_t array_size, i;
- uint32_t *table;
-
- array_size = sizeof(uint32_t) * od_setting_count;
- table = kzalloc(array_size, GFP_KERNEL);
- if (NULL == table)
- return -ENOMEM;
-
- for (i = 0; i < od_setting_count; i++)
- table[i] = pptable_array[i];
-
- *pptable_info_array = table;
-
- return 0;
-}
-
static int copy_overdrive_feature_capabilities_array(
struct pp_hwmgr *hwmgr,
uint8_t **pptable_info_array,
@@ -721,7 +677,7 @@ static int copy_overdrive_feature_capabilities_array(
return -ENOMEM;
for (i = 0; i < od_feature_count; i++) {
- table[i] = pptable_array[i];
+ table[i] = le32_to_cpu(pptable_array[i]);
if (table[i])
od_supported = true;
}
@@ -834,6 +790,8 @@ static int init_powerplay_table_information(
hwmgr->thermal_controller.ucType = powerplay_table->ucThermalControllerType;
pptable_information->uc_thermal_controller_type = powerplay_table->ucThermalControllerType;
+ hwmgr->thermal_controller.fanInfo.ulMinRPM = 0;
+ hwmgr->thermal_controller.fanInfo.ulMaxRPM = powerplay_table->smcPPTable.FanMaximumRpm;
set_hw_cap(hwmgr,
ATOM_VEGA20_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType,
@@ -842,34 +800,40 @@ static int init_powerplay_table_information(
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl);
if (powerplay_table->OverDrive8Table.ucODTableRevision == 1) {
- od_feature_count = (powerplay_table->OverDrive8Table.ODFeatureCount > ATOM_VEGA20_ODFEATURE_COUNT) ?
- ATOM_VEGA20_ODFEATURE_COUNT : powerplay_table->OverDrive8Table.ODFeatureCount;
- od_setting_count = (powerplay_table->OverDrive8Table.ODSettingCount > ATOM_VEGA20_ODSETTING_COUNT) ?
- ATOM_VEGA20_ODSETTING_COUNT : powerplay_table->OverDrive8Table.ODSettingCount;
+ od_feature_count =
+ (le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount) >
+ ATOM_VEGA20_ODFEATURE_COUNT) ?
+ ATOM_VEGA20_ODFEATURE_COUNT :
+ le32_to_cpu(powerplay_table->OverDrive8Table.ODFeatureCount);
+ od_setting_count =
+ (le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount) >
+ ATOM_VEGA20_ODSETTING_COUNT) ?
+ ATOM_VEGA20_ODSETTING_COUNT :
+ le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingCount);
copy_overdrive_feature_capabilities_array(hwmgr,
&pptable_information->od_feature_capabilities,
powerplay_table->OverDrive8Table.ODFeatureCapabilities,
od_feature_count);
- copy_overdrive_settings_limits_array(hwmgr,
+ phm_copy_overdrive_settings_limits_array(hwmgr,
&pptable_information->od_settings_max,
powerplay_table->OverDrive8Table.ODSettingsMax,
od_setting_count);
- copy_overdrive_settings_limits_array(hwmgr,
+ phm_copy_overdrive_settings_limits_array(hwmgr,
&pptable_information->od_settings_min,
powerplay_table->OverDrive8Table.ODSettingsMin,
od_setting_count);
}
- pptable_information->us_small_power_limit1 = powerplay_table->usSmallPowerLimit1;
- pptable_information->us_small_power_limit2 = powerplay_table->usSmallPowerLimit2;
- pptable_information->us_boost_power_limit = powerplay_table->usBoostPowerLimit;
- pptable_information->us_od_turbo_power_limit = powerplay_table->usODTurboPowerLimit;
- pptable_information->us_od_powersave_power_limit = powerplay_table->usODPowerSavePowerLimit;
+ pptable_information->us_small_power_limit1 = le16_to_cpu(powerplay_table->usSmallPowerLimit1);
+ pptable_information->us_small_power_limit2 = le16_to_cpu(powerplay_table->usSmallPowerLimit2);
+ pptable_information->us_boost_power_limit = le16_to_cpu(powerplay_table->usBoostPowerLimit);
+ pptable_information->us_od_turbo_power_limit = le16_to_cpu(powerplay_table->usODTurboPowerLimit);
+ pptable_information->us_od_powersave_power_limit = le16_to_cpu(powerplay_table->usODPowerSavePowerLimit);
- pptable_information->us_software_shutdown_temp = powerplay_table->usSoftwareShutdownTemp;
+ pptable_information->us_software_shutdown_temp = le16_to_cpu(powerplay_table->usSoftwareShutdownTemp);
- hwmgr->platform_descriptor.TDPODLimit = (uint16_t)powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE];
+ hwmgr->platform_descriptor.TDPODLimit = le32_to_cpu(powerplay_table->OverDrive8Table.ODSettingsMax[ATOM_VEGA20_ODSETTING_POWERPERCENTAGE]);
disable_power_control = 0;
if (!disable_power_control && hwmgr->platform_descriptor.TDPODLimit)
@@ -877,13 +841,16 @@ static int init_powerplay_table_information(
phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PowerControl);
if (powerplay_table->PowerSavingClockTable.ucTableRevision == 1) {
- power_saving_clock_count = (powerplay_table->PowerSavingClockTable.PowerSavingClockCount >= ATOM_VEGA20_PPCLOCK_COUNT) ?
- ATOM_VEGA20_PPCLOCK_COUNT : powerplay_table->PowerSavingClockTable.PowerSavingClockCount;
- copy_clock_limits_array(hwmgr,
+ power_saving_clock_count =
+ (le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount) >=
+ ATOM_VEGA20_PPCLOCK_COUNT) ?
+ ATOM_VEGA20_PPCLOCK_COUNT :
+ le32_to_cpu(powerplay_table->PowerSavingClockTable.PowerSavingClockCount);
+ phm_copy_clock_limits_array(hwmgr,
&pptable_information->power_saving_clock_max,
powerplay_table->PowerSavingClockTable.PowerSavingClockMax,
power_saving_clock_count);
- copy_clock_limits_array(hwmgr,
+ phm_copy_clock_limits_array(hwmgr,
&pptable_information->power_saving_clock_min,
powerplay_table->PowerSavingClockTable.PowerSavingClockMin,
power_saving_clock_count);
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c
index 1c951a5d827d..ede54e87e287 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.c
@@ -29,6 +29,78 @@
#include "soc15_common.h"
#include "pp_debug.h"
+static int vega20_disable_fan_control_feature(struct pp_hwmgr *hwmgr)
+{
+ struct vega20_hwmgr *data = hwmgr->backend;
+ int ret = 0;
+
+ if (data->smu_features[GNLD_FAN_CONTROL].supported) {
+ ret = vega20_enable_smc_features(
+ hwmgr, false,
+ data->smu_features[GNLD_FAN_CONTROL].
+ smu_feature_bitmap);
+ PP_ASSERT_WITH_CODE(!ret,
+ "Disable FAN CONTROL feature Failed!",
+ return ret);
+ data->smu_features[GNLD_FAN_CONTROL].enabled = false;
+ }
+
+ return ret;
+}
+
+int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+ struct vega20_hwmgr *data = hwmgr->backend;
+
+ if (data->smu_features[GNLD_FAN_CONTROL].supported)
+ return vega20_disable_fan_control_feature(hwmgr);
+
+ return 0;
+}
+
+static int vega20_enable_fan_control_feature(struct pp_hwmgr *hwmgr)
+{
+ struct vega20_hwmgr *data = hwmgr->backend;
+ int ret = 0;
+
+ if (data->smu_features[GNLD_FAN_CONTROL].supported) {
+ ret = vega20_enable_smc_features(
+ hwmgr, true,
+ data->smu_features[GNLD_FAN_CONTROL].
+ smu_feature_bitmap);
+ PP_ASSERT_WITH_CODE(!ret,
+ "Enable FAN CONTROL feature Failed!",
+ return ret);
+ data->smu_features[GNLD_FAN_CONTROL].enabled = true;
+ }
+
+ return ret;
+}
+
+int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
+{
+ struct vega20_hwmgr *data = hwmgr->backend;
+
+ if (data->smu_features[GNLD_FAN_CONTROL].supported)
+ return vega20_enable_fan_control_feature(hwmgr);
+
+ return 0;
+}
+
+static int vega20_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+
+ WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
+ CG_FDO_CTRL2, TMIN, 0));
+ WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
+ CG_FDO_CTRL2, FDO_PWM_MODE, mode));
+
+ return 0;
+}
+
static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
{
int ret = 0;
@@ -42,12 +114,62 @@ static int vega20_get_current_rpm(struct pp_hwmgr *hwmgr, uint32_t *current_rpm)
return 0;
}
+int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+ uint32_t *speed)
+{
+ struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend);
+ PPTable_t *pp_table = &(data->smc_state_table.pp_table);
+ uint32_t current_rpm, percent = 0;
+ int ret = 0;
+
+ ret = vega20_get_current_rpm(hwmgr, &current_rpm);
+ if (ret)
+ return ret;
+
+ percent = current_rpm * 100 / pp_table->FanMaximumRpm;
+
+ *speed = percent > 100 ? 100 : percent;
+
+ return 0;
+}
+
+int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+ uint32_t speed)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+ uint32_t duty100;
+ uint32_t duty;
+ uint64_t tmp64;
+
+ if (speed > 100)
+ speed = 100;
+
+ if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl))
+ vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
+
+ duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
+ CG_FDO_CTRL1, FMAX_DUTY100);
+
+ if (duty100 == 0)
+ return -EINVAL;
+
+ tmp64 = (uint64_t)speed * duty100;
+ do_div(tmp64, 100);
+ duty = (uint32_t)tmp64;
+
+ WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
+ CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
+
+ return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+}
+
int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info)
{
memset(fan_speed_info, 0, sizeof(*fan_speed_info));
- fan_speed_info->supports_percent_read = false;
- fan_speed_info->supports_percent_write = false;
+ fan_speed_info->supports_percent_read = true;
+ fan_speed_info->supports_percent_write = true;
fan_speed_info->supports_rpm_read = true;
fan_speed_info->supports_rpm_write = true;
@@ -61,6 +183,31 @@ int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
return vega20_get_current_rpm(hwmgr, speed);
}
+int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+ uint32_t tach_period, crystal_clock_freq;
+ int result = 0;
+
+ if (!speed)
+ return -EINVAL;
+
+ if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) {
+ result = vega20_fan_ctrl_stop_smc_fan_control(hwmgr);
+ if (result)
+ return result;
+ }
+
+ crystal_clock_freq = amdgpu_asic_get_xclk((struct amdgpu_device *)hwmgr->adev);
+ tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
+ WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
+ REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
+ CG_TACH_CTRL, TARGET_PERIOD,
+ tach_period));
+
+ return vega20_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
+}
+
/**
* Reads the remote temperature from the SIslands thermal controller.
*
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h
index 2a6d49fec4e0..2d1769bbd24e 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_thermal.h
@@ -50,15 +50,22 @@ struct vega20_temperature {
#define FDO_PWM_MODE_STATIC_RPM 5
extern int vega20_thermal_get_temperature(struct pp_hwmgr *hwmgr);
-extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
extern int vega20_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr,
struct phm_fan_speed_info *fan_speed_info);
-extern int vega20_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr);
extern int vega20_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr,
uint32_t *speed);
+extern int vega20_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr,
+ uint32_t speed);
+extern int vega20_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr,
+ uint32_t *speed);
+extern int vega20_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr,
+ uint32_t speed);
+extern int vega20_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
+extern int vega20_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
extern int vega20_thermal_disable_alert(struct pp_hwmgr *hwmgr);
extern int vega20_start_thermal_controller(struct pp_hwmgr *hwmgr,
struct PP_TemperatureRange *range);
+extern int vega20_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr);
#endif
diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
index a6d92128b19c..e5a60aa44b5d 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
@@ -328,6 +328,8 @@ struct pp_hwmgr_func {
int (*set_power_limit)(struct pp_hwmgr *hwmgr, uint32_t n);
int (*powergate_mmhub)(struct pp_hwmgr *hwmgr);
int (*smus_notify_pwe)(struct pp_hwmgr *hwmgr);
+ int (*powergate_sdma)(struct pp_hwmgr *hwmgr, bool bgate);
+ int (*enable_mgpu_fan_boost)(struct pp_hwmgr *hwmgr);
};
struct pp_table_func {
@@ -732,7 +734,6 @@ struct pp_hwmgr {
void *smu_backend;
const struct pp_smumgr_func *smumgr_funcs;
bool is_kicker;
- bool reload_fw;
enum PP_DAL_POWERLEVEL dal_power_level;
struct phm_dynamic_state_info dyn_state;
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h
index 71191deb4e76..a002021414ff 100644
--- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h
+++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h
@@ -269,6 +269,12 @@ typedef enum {
} PPCLK_e;
typedef enum {
+ POWER_SOURCE_AC,
+ POWER_SOURCE_DC,
+ POWER_SOURCE_COUNT,
+} POWER_SOURCE_e;
+
+typedef enum {
VOLTAGE_MODE_AVFS = 0,
VOLTAGE_MODE_AVFS_SS,
VOLTAGE_MODE_SS,
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
index 18643e06bc6f..669bd0c2a16c 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c
@@ -2269,11 +2269,13 @@ static uint32_t ci_get_offsetof(uint32_t type, uint32_t member)
case DRAM_LOG_BUFF_SIZE:
return offsetof(SMU7_SoftRegisters, DRAM_LOG_BUFF_SIZE);
}
+ break;
case SMU_Discrete_DpmTable:
switch (member) {
case LowSclkInterruptThreshold:
return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT);
}
+ break;
}
pr_debug("can't get the offset of type %x member %x\n", type, member);
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
index ec14798e87b6..bc8375cbf297 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c
@@ -302,16 +302,6 @@ static int fiji_start_smu(struct pp_hwmgr *hwmgr)
hwmgr->avfs_supported = false;
}
- /* To initialize all clock gating before RLC loaded and running.*/
- amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
- AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE);
- amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
- AMD_IP_BLOCK_TYPE_GMC, AMD_CG_STATE_GATE);
- amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
- AMD_IP_BLOCK_TYPE_SDMA, AMD_CG_STATE_GATE);
- amdgpu_device_ip_set_clockgating_state(hwmgr->adev,
- AMD_IP_BLOCK_TYPE_COMMON, AMD_CG_STATE_GATE);
-
/* Setup SoftRegsStart here for register lookup in case
* DummyBackEnd is used and ProcessFirmwareHeader is not executed
*/
@@ -2331,6 +2321,7 @@ static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member)
case DRAM_LOG_BUFF_SIZE:
return offsetof(SMU73_SoftRegisters, DRAM_LOG_BUFF_SIZE);
}
+ break;
case SMU_Discrete_DpmTable:
switch (member) {
case UvdBootLevel:
@@ -2340,6 +2331,7 @@ static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member)
case LowSclkInterruptThreshold:
return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold);
}
+ break;
}
pr_warn("can't get the offset of type %x member %x\n", type, member);
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c
index 73aa368a454e..375ccf6ff5f2 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c
@@ -232,26 +232,25 @@ static int iceland_request_smu_load_specific_fw(struct pp_hwmgr *hwmgr,
static int iceland_start_smu(struct pp_hwmgr *hwmgr)
{
+ struct iceland_smumgr *priv = hwmgr->smu_backend;
int result;
- result = iceland_smu_upload_firmware_image(hwmgr);
- if (result)
- return result;
- result = iceland_smu_start_smc(hwmgr);
- if (result)
- return result;
-
if (!smu7_is_smc_ram_running(hwmgr)) {
- pr_info("smu not running, upload firmware again \n");
result = iceland_smu_upload_firmware_image(hwmgr);
if (result)
return result;
- result = iceland_smu_start_smc(hwmgr);
- if (result)
- return result;
+ iceland_smu_start_smc(hwmgr);
}
+ /* Setup SoftRegsStart here to visit the register UcodeLoadStatus
+ * to check fw loading state
+ */
+ smu7_read_smc_sram_dword(hwmgr,
+ SMU71_FIRMWARE_HEADER_LOCATION +
+ offsetof(SMU71_Firmware_Header, SoftRegisters),
+ &(priv->smu7_data.soft_regs_start), 0x40000);
+
result = smu7_request_smu_load_fw(hwmgr);
return result;
@@ -2237,11 +2236,13 @@ static uint32_t iceland_get_offsetof(uint32_t type, uint32_t member)
case DRAM_LOG_BUFF_SIZE:
return offsetof(SMU71_SoftRegisters, DRAM_LOG_BUFF_SIZE);
}
+ break;
case SMU_Discrete_DpmTable:
switch (member) {
case LowSclkInterruptThreshold:
return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold);
}
+ break;
}
pr_warn("can't get the offset of type %x member %x\n", type, member);
return 0;
@@ -2662,7 +2663,7 @@ const struct pp_smumgr_func iceland_smu_funcs = {
.smu_fini = &smu7_smu_fini,
.start_smu = &iceland_start_smu,
.check_fw_load_finish = &smu7_check_fw_load_finish,
- .request_smu_load_fw = &smu7_reload_firmware,
+ .request_smu_load_fw = &smu7_request_smu_load_fw,
.request_smu_load_specific_fw = &iceland_request_smu_load_specific_fw,
.send_msg_to_smc = &smu7_send_msg_to_smc,
.send_msg_to_smc_with_parameter = &smu7_send_msg_to_smc_with_parameter,
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
index 6f961dec2088..d0eb8ab50148 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu10_smumgr.c
@@ -186,40 +186,12 @@ static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr)
return 0;
}
-/* sdma is disabled by default in vbios, need to re-enable in driver */
-static void smu10_smc_enable_sdma(struct pp_hwmgr *hwmgr)
-{
- smu10_send_msg_to_smc(hwmgr,
- PPSMC_MSG_PowerUpSdma);
-}
-
-static void smu10_smc_disable_sdma(struct pp_hwmgr *hwmgr)
-{
- smu10_send_msg_to_smc(hwmgr,
- PPSMC_MSG_PowerDownSdma);
-}
-
-/* vcn is disabled by default in vbios, need to re-enable in driver */
-static void smu10_smc_enable_vcn(struct pp_hwmgr *hwmgr)
-{
- smu10_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_PowerUpVcn, 0);
-}
-
-static void smu10_smc_disable_vcn(struct pp_hwmgr *hwmgr)
-{
- smu10_send_msg_to_smc_with_parameter(hwmgr,
- PPSMC_MSG_PowerDownVcn, 0);
-}
-
static int smu10_smu_fini(struct pp_hwmgr *hwmgr)
{
struct smu10_smumgr *priv =
(struct smu10_smumgr *)(hwmgr->smu_backend);
if (priv) {
- smu10_smc_disable_sdma(hwmgr);
- smu10_smc_disable_vcn(hwmgr);
amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle,
&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr,
&priv->smu_tables.entry[SMU10_WMTABLE].table);
@@ -243,8 +215,7 @@ static int smu10_start_smu(struct pp_hwmgr *hwmgr)
if (smu10_verify_smc_interface(hwmgr))
return -EINVAL;
- smu10_smc_enable_sdma(hwmgr);
- smu10_smc_enable_vcn(hwmgr);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
index 186dafc7f166..3f51d545e8ff 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c
@@ -302,44 +302,6 @@ int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_
return 0;
}
-/* Convert the firmware type to SMU type mask. For MEC, we need to check all MEC related type */
-
-static uint32_t smu7_get_mask_for_firmware_type(uint32_t fw_type)
-{
- uint32_t result = 0;
-
- switch (fw_type) {
- case UCODE_ID_SDMA0:
- result = UCODE_ID_SDMA0_MASK;
- break;
- case UCODE_ID_SDMA1:
- result = UCODE_ID_SDMA1_MASK;
- break;
- case UCODE_ID_CP_CE:
- result = UCODE_ID_CP_CE_MASK;
- break;
- case UCODE_ID_CP_PFP:
- result = UCODE_ID_CP_PFP_MASK;
- break;
- case UCODE_ID_CP_ME:
- result = UCODE_ID_CP_ME_MASK;
- break;
- case UCODE_ID_CP_MEC:
- case UCODE_ID_CP_MEC_JT1:
- case UCODE_ID_CP_MEC_JT2:
- result = UCODE_ID_CP_MEC_MASK;
- break;
- case UCODE_ID_RLC_G:
- result = UCODE_ID_RLC_G_MASK;
- break;
- default:
- pr_info("UCode type is out of range! \n");
- result = 0;
- }
-
- return result;
-}
-
static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr,
uint32_t fw_type,
struct SMU_Entry *entry)
@@ -381,10 +343,7 @@ int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
uint32_t fw_to_load;
int r = 0;
- if (!hwmgr->reload_fw) {
- pr_info("skip reloading...\n");
- return 0;
- }
+ amdgpu_ucode_init_bo(hwmgr->adev);
if (smu_data->soft_regs_start)
cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
@@ -467,10 +426,13 @@ int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, upper_32_bits(smu_data->header_buffer.mc_addr));
smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, lower_32_bits(smu_data->header_buffer.mc_addr));
- if (smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load))
- pr_err("Fail to Request SMU Load uCode");
+ smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load);
- return r;
+ r = smu7_check_fw_load_finish(hwmgr, fw_to_load);
+ if (!r)
+ return 0;
+
+ pr_err("SMU load firmware failed\n");
failed:
kfree(smu_data->toc);
@@ -482,13 +444,12 @@ failed:
int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type)
{
struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
- uint32_t fw_mask = smu7_get_mask_for_firmware_type(fw_type);
uint32_t ret;
ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11,
smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
SMU_SoftRegisters, UcodeLoadStatus),
- fw_mask, fw_mask);
+ fw_type, fw_type);
return ret;
}
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
index a74c5be1ec18..f836d30fdd44 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c
@@ -658,11 +658,10 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
{
struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
uint32_t smc_address;
+ uint32_t fw_to_check = 0;
+ int ret;
- if (!hwmgr->reload_fw) {
- pr_info("skip reloading...\n");
- return 0;
- }
+ amdgpu_ucode_init_bo(hwmgr->adev);
smu8_smu_populate_firmware_entries(hwmgr);
@@ -689,28 +688,9 @@ static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
smu8_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
smu8_smu->toc_entry_power_profiling_index);
- return smu8_send_msg_to_smc_with_parameter(hwmgr,
+ smu8_send_msg_to_smc_with_parameter(hwmgr,
PPSMC_MSG_ExecuteJob,
smu8_smu->toc_entry_initialize_index);
-}
-
-static int smu8_start_smu(struct pp_hwmgr *hwmgr)
-{
- int ret = 0;
- uint32_t fw_to_check = 0;
- struct amdgpu_device *adev = hwmgr->adev;
-
- uint32_t index = SMN_MP1_SRAM_START_ADDR +
- SMU8_FIRMWARE_HEADER_LOCATION +
- offsetof(struct SMU8_Firmware_Header, Version);
-
-
- if (hwmgr == NULL || hwmgr->device == NULL)
- return -EINVAL;
-
- cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
- hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
- adev->pm.fw_version = hwmgr->smu_version >> 8;
fw_to_check = UCODE_ID_RLC_G_MASK |
UCODE_ID_SDMA0_MASK |
@@ -724,8 +704,6 @@ static int smu8_start_smu(struct pp_hwmgr *hwmgr)
if (hwmgr->chip_id == CHIP_STONEY)
fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
- smu8_request_smu_load_fw(hwmgr);
-
ret = smu8_check_fw_load_finish(hwmgr, fw_to_check);
if (ret) {
pr_err("SMU firmware load failed\n");
@@ -733,10 +711,31 @@ static int smu8_start_smu(struct pp_hwmgr *hwmgr)
}
ret = smu8_load_mec_firmware(hwmgr);
- if (ret)
+ if (ret) {
pr_err("Mec Firmware load failed\n");
+ return ret;
+ }
- return ret;
+ return 0;
+}
+
+static int smu8_start_smu(struct pp_hwmgr *hwmgr)
+{
+ struct amdgpu_device *adev = hwmgr->adev;
+
+ uint32_t index = SMN_MP1_SRAM_START_ADDR +
+ SMU8_FIRMWARE_HEADER_LOCATION +
+ offsetof(struct SMU8_Firmware_Header, Version);
+
+
+ if (hwmgr == NULL || hwmgr->device == NULL)
+ return -EINVAL;
+
+ cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
+ hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
+ adev->pm.fw_version = hwmgr->smu_version >> 8;
+
+ return smu8_request_smu_load_fw(hwmgr);
}
static int smu8_smu_init(struct pp_hwmgr *hwmgr)
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
index ae8378ed32ee..3ed6c5f1e5cf 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c
@@ -192,6 +192,7 @@ static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr)
static int tonga_start_smu(struct pp_hwmgr *hwmgr)
{
+ struct tonga_smumgr *priv = hwmgr->smu_backend;
int result;
/* Only start SMC if SMC RAM is not running */
@@ -209,6 +210,14 @@ static int tonga_start_smu(struct pp_hwmgr *hwmgr)
}
}
+ /* Setup SoftRegsStart here to visit the register UcodeLoadStatus
+ * to check fw loading state
+ */
+ smu7_read_smc_sram_dword(hwmgr,
+ SMU72_FIRMWARE_HEADER_LOCATION +
+ offsetof(SMU72_Firmware_Header, SoftRegisters),
+ &(priv->smu7_data.soft_regs_start), 0x40000);
+
result = smu7_request_smu_load_fw(hwmgr);
return result;
@@ -2619,6 +2628,7 @@ static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member)
case DRAM_LOG_BUFF_SIZE:
return offsetof(SMU72_SoftRegisters, DRAM_LOG_BUFF_SIZE);
}
+ break;
case SMU_Discrete_DpmTable:
switch (member) {
case UvdBootLevel:
@@ -2628,6 +2638,7 @@ static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member)
case LowSclkInterruptThreshold:
return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold);
}
+ break;
}
pr_warn("can't get the offset of type %x member %x\n", type, member);
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c
index 3d415fabbd93..9f71512b2510 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c
@@ -2185,6 +2185,7 @@ static uint32_t vegam_get_offsetof(uint32_t type, uint32_t member)
case DRAM_LOG_BUFF_SIZE:
return offsetof(SMU75_SoftRegisters, DRAM_LOG_BUFF_SIZE);
}
+ break;
case SMU_Discrete_DpmTable:
switch (member) {
case UvdBootLevel:
@@ -2194,6 +2195,7 @@ static uint32_t vegam_get_offsetof(uint32_t type, uint32_t member)
case LowSclkInterruptThreshold:
return offsetof(SMU75_Discrete_DpmTable, LowSclkInterruptThreshold);
}
+ break;
}
pr_warn("can't get the offset of type %x member %x\n", type, member);
return 0;
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c
index ef44202fb43f..e1b72782848c 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -348,19 +348,20 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
/*
* check if there is enough rotation memory available for planes
- * that need 90° and 270° rotation. Each plane has set its required
- * memory size in the ->plane_check() callback, here we only make
- * sure that the sums are less that the total usable memory.
+ * that need 90° and 270° rotion or planes that are compressed.
+ * Each plane has set its required memory size in the ->plane_check()
+ * callback, here we only make sure that the sums are less that the
+ * total usable memory.
*
* The rotation memory allocation algorithm (for each plane):
- * a. If no more rotated planes exist, all remaining rotate
- * memory in the bank is available for use by the plane.
- * b. If other rotated planes exist, and plane's layer ID is
- * DE_VIDEO1, it can use all the memory from first bank if
- * secondary rotation memory bank is available, otherwise it can
+ * a. If no more rotated or compressed planes exist, all remaining
+ * rotate memory in the bank is available for use by the plane.
+ * b. If other rotated or compressed planes exist, and plane's
+ * layer ID is DE_VIDEO1, it can use all the memory from first bank
+ * if secondary rotation memory bank is available, otherwise it can
* use up to half the bank's memory.
- * c. If other rotated planes exist, and plane's layer ID is not
- * DE_VIDEO1, it can use half of the available memory
+ * c. If other rotated or compressed planes exist, and plane's layer ID
+ * is not DE_VIDEO1, it can use half of the available memory.
*
* Note: this algorithm assumes that the order in which the planes are
* checked always has DE_VIDEO1 plane first in the list if it is
@@ -372,7 +373,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
/* first count the number of rotated planes */
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
- if (pstate->rotation & MALIDP_ROTATED_MASK)
+ struct drm_framebuffer *fb = pstate->fb;
+
+ if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier)
rotated_planes++;
}
@@ -388,8 +391,9 @@ static int malidp_crtc_atomic_check(struct drm_crtc *crtc,
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) {
struct malidp_plane *mp = to_malidp_plane(plane);
struct malidp_plane_state *ms = to_malidp_plane_state(pstate);
+ struct drm_framebuffer *fb = pstate->fb;
- if (pstate->rotation & MALIDP_ROTATED_MASK) {
+ if ((pstate->rotation & MALIDP_ROTATED_MASK) || fb->modifier) {
/* process current plane */
rotated_planes--;
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 3171ffaadd77..505f316a192e 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -37,6 +37,8 @@
#include "malidp_hw.h"
#define MALIDP_CONF_VALID_TIMEOUT 250
+#define AFBC_HEADER_SIZE 16
+#define AFBC_SUPERBLK_ALIGNMENT 128
static void malidp_write_gamma_table(struct malidp_hw_device *hwdev,
u32 data[MALIDP_COEFFTAB_NUM_COEFFS])
@@ -258,8 +260,134 @@ static const struct drm_mode_config_helper_funcs malidp_mode_config_helpers = {
.atomic_commit_tail = malidp_atomic_commit_tail,
};
+static bool
+malidp_verify_afbc_framebuffer_caps(struct drm_device *dev,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ const struct drm_format_info *info;
+
+ if ((mode_cmd->modifier[0] >> 56) != DRM_FORMAT_MOD_VENDOR_ARM) {
+ DRM_DEBUG_KMS("Unknown modifier (not Arm)\n");
+ return false;
+ }
+
+ if (mode_cmd->modifier[0] &
+ ~DRM_FORMAT_MOD_ARM_AFBC(AFBC_MOD_VALID_BITS)) {
+ DRM_DEBUG_KMS("Unsupported modifiers\n");
+ return false;
+ }
+
+ info = drm_get_format_info(dev, mode_cmd);
+ if (!info) {
+ DRM_DEBUG_KMS("Unable to get the format information\n");
+ return false;
+ }
+
+ if (info->num_planes != 1) {
+ DRM_DEBUG_KMS("AFBC buffers expect one plane\n");
+ return false;
+ }
+
+ if (mode_cmd->offsets[0] != 0) {
+ DRM_DEBUG_KMS("AFBC buffers' plane offset should be 0\n");
+ return false;
+ }
+
+ switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
+ case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
+ if ((mode_cmd->width % 16) || (mode_cmd->height % 16)) {
+ DRM_DEBUG_KMS("AFBC buffers must be aligned to 16 pixels\n");
+ return false;
+ }
+ break;
+ default:
+ DRM_DEBUG_KMS("Unsupported AFBC block size\n");
+ return false;
+ }
+
+ return true;
+}
+
+static bool
+malidp_verify_afbc_framebuffer_size(struct drm_device *dev,
+ struct drm_file *file,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ int n_superblocks = 0;
+ const struct drm_format_info *info;
+ struct drm_gem_object *objs = NULL;
+ u32 afbc_superblock_size = 0, afbc_superblock_height = 0;
+ u32 afbc_superblock_width = 0, afbc_size = 0;
+
+ switch (mode_cmd->modifier[0] & AFBC_FORMAT_MOD_BLOCK_SIZE_MASK) {
+ case AFBC_FORMAT_MOD_BLOCK_SIZE_16x16:
+ afbc_superblock_height = 16;
+ afbc_superblock_width = 16;
+ break;
+ default:
+ DRM_DEBUG_KMS("AFBC superblock size is not supported\n");
+ return false;
+ }
+
+ info = drm_get_format_info(dev, mode_cmd);
+
+ n_superblocks = (mode_cmd->width / afbc_superblock_width) *
+ (mode_cmd->height / afbc_superblock_height);
+
+ afbc_superblock_size = info->cpp[0] * afbc_superblock_width *
+ afbc_superblock_height;
+
+ afbc_size = ALIGN(n_superblocks * AFBC_HEADER_SIZE, AFBC_SUPERBLK_ALIGNMENT);
+ afbc_size += n_superblocks * ALIGN(afbc_superblock_size, AFBC_SUPERBLK_ALIGNMENT);
+
+ if (mode_cmd->width * info->cpp[0] != mode_cmd->pitches[0]) {
+ DRM_DEBUG_KMS("Invalid value of pitch (=%u) should be same as width (=%u) * cpp (=%u)\n",
+ mode_cmd->pitches[0], mode_cmd->width, info->cpp[0]);
+ return false;
+ }
+
+ objs = drm_gem_object_lookup(file, mode_cmd->handles[0]);
+ if (!objs) {
+ DRM_DEBUG_KMS("Failed to lookup GEM object\n");
+ return false;
+ }
+
+ if (objs->size < afbc_size) {
+ DRM_DEBUG_KMS("buffer size (%zu) too small for AFBC buffer size = %u\n",
+ objs->size, afbc_size);
+ drm_gem_object_put_unlocked(objs);
+ return false;
+ }
+
+ drm_gem_object_put_unlocked(objs);
+
+ return true;
+}
+
+static bool
+malidp_verify_afbc_framebuffer(struct drm_device *dev, struct drm_file *file,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ if (malidp_verify_afbc_framebuffer_caps(dev, mode_cmd))
+ return malidp_verify_afbc_framebuffer_size(dev, file, mode_cmd);
+
+ return false;
+}
+
+struct drm_framebuffer *
+malidp_fb_create(struct drm_device *dev, struct drm_file *file,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ if (mode_cmd->modifier[0]) {
+ if (!malidp_verify_afbc_framebuffer(dev, file, mode_cmd))
+ return ERR_PTR(-EINVAL);
+ }
+
+ return drm_gem_fb_create(dev, file, mode_cmd);
+}
+
static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
- .fb_create = drm_gem_fb_create,
+ .fb_create = malidp_fb_create,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -752,6 +880,7 @@ static int malidp_bind(struct device *dev)
drm->irq_enabled = true;
ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
+ drm_crtc_vblank_reset(&malidp->crtc);
if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n");
goto vblank_fail;
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index e3eb0cb1f385..b76c86f18a56 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -55,6 +55,12 @@ struct malidp_plane {
const struct malidp_layer *layer;
};
+enum mmu_prefetch_mode {
+ MALIDP_PREFETCH_MODE_NONE,
+ MALIDP_PREFETCH_MODE_PARTIAL,
+ MALIDP_PREFETCH_MODE_FULL,
+};
+
struct malidp_plane_state {
struct drm_plane_state base;
@@ -63,6 +69,8 @@ struct malidp_plane_state {
/* internal format ID */
u8 format;
u8 n_planes;
+ enum mmu_prefetch_mode mmu_prefetch_mode;
+ u32 mmu_prefetch_pgsize;
};
#define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index c94a4422e0e9..7aad7dd80d8c 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -84,16 +84,48 @@ static const struct malidp_format_id malidp550_de_formats[] = {
};
static const struct malidp_layer malidp500_layers[] = {
- { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB },
- { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
- { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
+ /* id, base address, fb pointer address base, stride offset,
+ * yuv2rgb matrix offset, mmu control register offset, rotation_features
+ */
+ { DE_VIDEO1, MALIDP500_DE_LV_BASE, MALIDP500_DE_LV_PTR_BASE,
+ MALIDP_DE_LV_STRIDE0, MALIDP500_LV_YUV2RGB, 0, ROTATE_ANY },
+ { DE_GRAPHICS1, MALIDP500_DE_LG1_BASE, MALIDP500_DE_LG1_PTR_BASE,
+ MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
+ { DE_GRAPHICS2, MALIDP500_DE_LG2_BASE, MALIDP500_DE_LG2_PTR_BASE,
+ MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
};
static const struct malidp_layer malidp550_layers[] = {
- { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
- { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE, MALIDP_DE_LG_STRIDE, 0 },
- { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE, MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB },
- { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE, MALIDP550_DE_LS_R1_STRIDE, 0 },
+ /* id, base address, fb pointer address base, stride offset,
+ * yuv2rgb matrix offset, mmu control register offset, rotation_features
+ */
+ { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
+ MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
+ { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
+ MALIDP_DE_LG_STRIDE, 0, 0, ROTATE_ANY },
+ { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
+ MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB, 0, ROTATE_ANY },
+ { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
+ MALIDP550_DE_LS_R1_STRIDE, 0, 0, ROTATE_NONE },
+};
+
+static const struct malidp_layer malidp650_layers[] = {
+ /* id, base address, fb pointer address base, stride offset,
+ * yuv2rgb matrix offset, mmu control register offset,
+ * rotation_features
+ */
+ { DE_VIDEO1, MALIDP550_DE_LV1_BASE, MALIDP550_DE_LV1_PTR_BASE,
+ MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
+ MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
+ { DE_GRAPHICS1, MALIDP550_DE_LG_BASE, MALIDP550_DE_LG_PTR_BASE,
+ MALIDP_DE_LG_STRIDE, 0, MALIDP650_DE_LG_MMU_CTRL,
+ ROTATE_COMPRESSED },
+ { DE_VIDEO2, MALIDP550_DE_LV2_BASE, MALIDP550_DE_LV2_PTR_BASE,
+ MALIDP_DE_LV_STRIDE0, MALIDP550_LV_YUV2RGB,
+ MALIDP650_DE_LV_MMU_CTRL, ROTATE_ANY },
+ { DE_SMART, MALIDP550_DE_LS_BASE, MALIDP550_DE_LS_PTR_BASE,
+ MALIDP550_DE_LS_R1_STRIDE, 0, MALIDP650_DE_LS_MMU_CTRL,
+ ROTATE_NONE },
};
#define SE_N_SCALING_COEFFS 96
@@ -288,10 +320,6 @@ static void malidp500_modeset(struct malidp_hw_device *hwdev, struct videomode *
static int malidp500_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16 h, u32 fmt)
{
- /* RGB888 or BGR888 can't be rotated */
- if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
- return -EINVAL;
-
/*
* Each layer needs enough rotation memory to fit 8 lines
* worth of pixel data. Required size is then:
@@ -384,7 +412,8 @@ static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev,
static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
dma_addr_t *addrs, s32 *pitches,
- int num_planes, u16 w, u16 h, u32 fmt_id)
+ int num_planes, u16 w, u16 h, u32 fmt_id,
+ const s16 *rgb2yuv_coeffs)
{
u32 base = MALIDP500_SE_MEMWRITE_BASE;
u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
@@ -416,6 +445,16 @@ static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev,
malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h),
MALIDP500_SE_MEMWRITE_OUT_SIZE);
+
+ if (rgb2yuv_coeffs) {
+ int i;
+
+ for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
+ malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
+ MALIDP500_SE_RGB_YUV_COEFFS + i * 4);
+ }
+ }
+
malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL);
return 0;
@@ -568,10 +607,6 @@ static int malidp550_rotmem_required(struct malidp_hw_device *hwdev, u16 w, u16
{
u32 bytes_per_col;
- /* raw RGB888 or BGR888 can't be rotated */
- if ((fmt == DRM_FORMAT_RGB888) || (fmt == DRM_FORMAT_BGR888))
- return -EINVAL;
-
switch (fmt) {
/* 8 lines at 4 bytes per pixel */
case DRM_FORMAT_ARGB2101010:
@@ -658,7 +693,8 @@ static long malidp550_se_calc_mclk(struct malidp_hw_device *hwdev,
static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
dma_addr_t *addrs, s32 *pitches,
- int num_planes, u16 w, u16 h, u32 fmt_id)
+ int num_planes, u16 w, u16 h, u32 fmt_id,
+ const s16 *rgb2yuv_coeffs)
{
u32 base = MALIDP550_SE_MEMWRITE_BASE;
u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK);
@@ -689,6 +725,15 @@ static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev,
malidp_hw_setbits(hwdev, MALIDP550_SE_MEMWRITE_ONESHOT | MALIDP_SE_MEMWRITE_EN,
MALIDP550_SE_CONTROL);
+ if (rgb2yuv_coeffs) {
+ int i;
+
+ for (i = 0; i < MALIDP_COLORADJ_NUM_COEFFS; i++) {
+ malidp_hw_write(hwdev, rgb2yuv_coeffs[i],
+ MALIDP550_SE_RGB_YUV_COEFFS + i * 4);
+ }
+ }
+
return 0;
}
@@ -832,8 +877,8 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = {
.dc_base = MALIDP550_DC_BASE,
.out_depth_base = MALIDP550_DE_OUTPUT_DEPTH,
.features = MALIDP_REGMAP_HAS_CLEARIRQ,
- .n_layers = ARRAY_SIZE(malidp550_layers),
- .layers = malidp550_layers,
+ .n_layers = ARRAY_SIZE(malidp650_layers),
+ .layers = malidp650_layers,
.de_irq_map = {
.irq_mask = MALIDP_DE_IRQ_UNDERRUN |
MALIDP650_DE_IRQ_DRIFT |
diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h
index ad2e96915d44..40155e2ea9d9 100644
--- a/drivers/gpu/drm/arm/malidp_hw.h
+++ b/drivers/gpu/drm/arm/malidp_hw.h
@@ -36,6 +36,12 @@ enum {
SE_MEMWRITE = BIT(5),
};
+enum rotation_features {
+ ROTATE_NONE, /* does not support rotation at all */
+ ROTATE_ANY, /* supports rotation on any buffers */
+ ROTATE_COMPRESSED, /* supports rotation only on compressed buffers */
+};
+
struct malidp_format_id {
u32 format; /* DRM fourcc */
u8 layer; /* bitmask of layers supporting it */
@@ -62,6 +68,8 @@ struct malidp_layer {
u16 ptr; /* address offset for the pointer register */
u16 stride_offset; /* offset to the first stride register. */
s16 yuv2rgb_offset; /* offset to the YUV->RGB matrix entries */
+ u16 mmu_ctrl_offset; /* offset to the MMU control register */
+ enum rotation_features rot; /* type of rotation supported */
};
enum malidp_scaling_coeff_set {
@@ -191,7 +199,8 @@ struct malidp_hw {
* @param fmt_id - internal format ID of output buffer
*/
int (*enable_memwrite)(struct malidp_hw_device *hwdev, dma_addr_t *addrs,
- s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id);
+ s32 *pitches, int num_planes, u16 w, u16 h, u32 fmt_id,
+ const s16 *rgb2yuv_coeffs);
/*
* Disable the writing to memory of the next frame's content.
@@ -379,4 +388,9 @@ static inline void malidp_se_set_enh_coeffs(struct malidp_hw_device *hwdev)
#define MALIDP_GAMMA_LUT_SIZE 4096
+#define AFBC_MOD_VALID_BITS (AFBC_FORMAT_MOD_BLOCK_SIZE_MASK | \
+ AFBC_FORMAT_MOD_YTR | AFBC_FORMAT_MOD_SPLIT | \
+ AFBC_FORMAT_MOD_SPARSE | AFBC_FORMAT_MOD_CBR | \
+ AFBC_FORMAT_MOD_TILED | AFBC_FORMAT_MOD_SC)
+
#endif /* __MALIDP_HW_H__ */
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index ba6ae66387c9..91472e5e0c8b 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -26,6 +26,8 @@ struct malidp_mw_connector_state {
s32 pitches[2];
u8 format;
u8 n_planes;
+ bool rgb2yuv_initialized;
+ const s16 *rgb2yuv_coeffs;
};
static int malidp_mw_connector_get_modes(struct drm_connector *connector)
@@ -84,7 +86,7 @@ static void malidp_mw_connector_destroy(struct drm_connector *connector)
static struct drm_connector_state *
malidp_mw_connector_duplicate_state(struct drm_connector *connector)
{
- struct malidp_mw_connector_state *mw_state;
+ struct malidp_mw_connector_state *mw_state, *mw_current_state;
if (WARN_ON(!connector->state))
return NULL;
@@ -93,7 +95,10 @@ malidp_mw_connector_duplicate_state(struct drm_connector *connector)
if (!mw_state)
return NULL;
- /* No need to preserve any of our driver-local data */
+ mw_current_state = to_mw_state(connector->state);
+ mw_state->rgb2yuv_coeffs = mw_current_state->rgb2yuv_coeffs;
+ mw_state->rgb2yuv_initialized = mw_current_state->rgb2yuv_initialized;
+
__drm_atomic_helper_connector_duplicate_state(connector, &mw_state->base);
return &mw_state->base;
@@ -108,6 +113,13 @@ static const struct drm_connector_funcs malidp_mw_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
+static const s16 rgb2yuv_coeffs_bt709_limited[MALIDP_COLORADJ_NUM_COEFFS] = {
+ 47, 157, 16,
+ -26, -87, 112,
+ 112, -102, -10,
+ 16, 128, 128
+};
+
static int
malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
@@ -157,6 +169,9 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
}
mw_state->n_planes = n_planes;
+ if (fb->format->is_yuv)
+ mw_state->rgb2yuv_coeffs = rgb2yuv_coeffs_bt709_limited;
+
return 0;
}
@@ -239,10 +254,12 @@ void malidp_mw_atomic_commit(struct drm_device *drm,
drm_writeback_queue_job(mw_conn, conn_state->writeback_job);
conn_state->writeback_job = NULL;
-
hwdev->hw->enable_memwrite(hwdev, mw_state->addrs,
mw_state->pitches, mw_state->n_planes,
- fb->width, fb->height, mw_state->format);
+ fb->width, fb->height, mw_state->format,
+ !mw_state->rgb2yuv_initialized ?
+ mw_state->rgb2yuv_coeffs : NULL);
+ mw_state->rgb2yuv_initialized = !!mw_state->rgb2yuv_coeffs;
} else {
DRM_DEV_DEBUG_DRIVER(drm->dev, "Disable memwrite\n");
hwdev->hw->disable_memwrite(hwdev);
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 49c37f6dd63e..837a24d56675 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -10,11 +10,14 @@
* ARM Mali DP plane manipulation routines.
*/
+#include <linux/iommu.h>
+
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_print.h>
@@ -36,6 +39,7 @@
#define LAYER_COMP_MASK (0x3 << 12)
#define LAYER_COMP_PIXEL (0x3 << 12)
#define LAYER_COMP_PLANE (0x2 << 12)
+#define LAYER_PMUL_ENABLE (0x1 << 14)
#define LAYER_ALPHA_OFFSET (16)
#define LAYER_ALPHA_MASK (0xff)
#define LAYER_ALPHA(x) (((x) & LAYER_ALPHA_MASK) << LAYER_ALPHA_OFFSET)
@@ -56,6 +60,13 @@
*/
#define MALIDP_ALPHA_LUT 0xffaa5500
+/* page sizes the MMU prefetcher can support */
+#define MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES (SZ_4K | SZ_64K)
+#define MALIDP_MMU_PREFETCH_FULL_PGSIZES (SZ_1M | SZ_2M)
+
+/* readahead for partial-frame prefetch */
+#define MALIDP_MMU_PREFETCH_READAHEAD 8
+
static void malidp_de_plane_destroy(struct drm_plane *plane)
{
struct malidp_plane *mp = to_malidp_plane(plane);
@@ -100,6 +111,9 @@ drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
state->format = m_state->format;
state->n_planes = m_state->n_planes;
+ state->mmu_prefetch_mode = m_state->mmu_prefetch_mode;
+ state->mmu_prefetch_pgsize = m_state->mmu_prefetch_pgsize;
+
return &state->base;
}
@@ -112,6 +126,12 @@ static void malidp_destroy_plane_state(struct drm_plane *plane,
kfree(m_state);
}
+static const char * const prefetch_mode_names[] = {
+ [MALIDP_PREFETCH_MODE_NONE] = "MMU_PREFETCH_NONE",
+ [MALIDP_PREFETCH_MODE_PARTIAL] = "MMU_PREFETCH_PARTIAL",
+ [MALIDP_PREFETCH_MODE_FULL] = "MMU_PREFETCH_FULL",
+};
+
static void malidp_plane_atomic_print_state(struct drm_printer *p,
const struct drm_plane_state *state)
{
@@ -120,6 +140,9 @@ static void malidp_plane_atomic_print_state(struct drm_printer *p,
drm_printf(p, "\trotmem_size=%u\n", ms->rotmem_size);
drm_printf(p, "\tformat_id=%u\n", ms->format);
drm_printf(p, "\tn_planes=%u\n", ms->n_planes);
+ drm_printf(p, "\tmmu_prefetch_mode=%s\n",
+ prefetch_mode_names[ms->mmu_prefetch_mode]);
+ drm_printf(p, "\tmmu_prefetch_pgsize=%d\n", ms->mmu_prefetch_pgsize);
}
static const struct drm_plane_funcs malidp_de_plane_funcs = {
@@ -173,6 +196,199 @@ static int malidp_se_check_scaling(struct malidp_plane *mp,
return 0;
}
+static u32 malidp_get_pgsize_bitmap(struct malidp_plane *mp)
+{
+ u32 pgsize_bitmap = 0;
+
+ if (iommu_present(&platform_bus_type)) {
+ struct iommu_domain *mmu_dom =
+ iommu_get_domain_for_dev(mp->base.dev->dev);
+
+ if (mmu_dom)
+ pgsize_bitmap = mmu_dom->pgsize_bitmap;
+ }
+
+ return pgsize_bitmap;
+}
+
+/*
+ * Check if the framebuffer is entirely made up of pages at least pgsize in
+ * size. Only a heuristic: assumes that each scatterlist entry has been aligned
+ * to the largest page size smaller than its length and that the MMU maps to
+ * the largest page size possible.
+ */
+static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
+ u32 pgsize)
+{
+ int i;
+
+ for (i = 0; i < ms->n_planes; i++) {
+ struct drm_gem_object *obj;
+ struct drm_gem_cma_object *cma_obj;
+ struct sg_table *sgt;
+ struct scatterlist *sgl;
+
+ obj = drm_gem_fb_get_obj(ms->base.fb, i);
+ cma_obj = to_drm_gem_cma_obj(obj);
+
+ if (cma_obj->sgt)
+ sgt = cma_obj->sgt;
+ else
+ sgt = obj->dev->driver->gem_prime_get_sg_table(obj);
+
+ if (!sgt)
+ return false;
+
+ sgl = sgt->sgl;
+
+ while (sgl) {
+ if (sgl->length < pgsize) {
+ if (!cma_obj->sgt)
+ kfree(sgt);
+ return false;
+ }
+
+ sgl = sg_next(sgl);
+ }
+ if (!cma_obj->sgt)
+ kfree(sgt);
+ }
+
+ return true;
+}
+
+/*
+ * Check if it is possible to enable partial-frame MMU prefetch given the
+ * current format, AFBC state and rotation.
+ */
+static bool malidp_partial_prefetch_supported(u32 format, u64 modifier,
+ unsigned int rotation)
+{
+ bool afbc, sparse;
+
+ /* rotation and horizontal flip not supported for partial prefetch */
+ if (rotation & (DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
+ DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X))
+ return false;
+
+ afbc = modifier & DRM_FORMAT_MOD_ARM_AFBC(0);
+ sparse = modifier & AFBC_FORMAT_MOD_SPARSE;
+
+ switch (format) {
+ case DRM_FORMAT_ARGB2101010:
+ case DRM_FORMAT_RGBA1010102:
+ case DRM_FORMAT_BGRA1010102:
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_RGBA8888:
+ case DRM_FORMAT_BGRA8888:
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_XBGR8888:
+ case DRM_FORMAT_RGBX8888:
+ case DRM_FORMAT_BGRX8888:
+ case DRM_FORMAT_RGB888:
+ case DRM_FORMAT_RGBA5551:
+ case DRM_FORMAT_RGB565:
+ /* always supported */
+ return true;
+
+ case DRM_FORMAT_ABGR2101010:
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_ABGR1555:
+ case DRM_FORMAT_BGR565:
+ /* supported, but if AFBC then must be sparse mode */
+ return (!afbc) || (afbc && sparse);
+
+ case DRM_FORMAT_BGR888:
+ /* supported, but not for AFBC */
+ return !afbc;
+
+ case DRM_FORMAT_YUYV:
+ case DRM_FORMAT_UYVY:
+ case DRM_FORMAT_NV12:
+ case DRM_FORMAT_YUV420:
+ /* not supported */
+ return false;
+
+ default:
+ return false;
+ }
+}
+
+/*
+ * Select the preferred MMU prefetch mode. Full-frame prefetch is preferred as
+ * long as the framebuffer is all large pages. Otherwise partial-frame prefetch
+ * is selected as long as it is supported for the current format. The selected
+ * page size for prefetch is returned in pgsize_bitmap.
+ */
+static enum mmu_prefetch_mode malidp_mmu_prefetch_select_mode
+ (struct malidp_plane_state *ms, u32 *pgsize_bitmap)
+{
+ u32 pgsizes;
+
+ /* get the full-frame prefetch page size(s) supported by the MMU */
+ pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_FULL_PGSIZES;
+
+ while (pgsizes) {
+ u32 largest_pgsize = 1 << __fls(pgsizes);
+
+ if (malidp_check_pages_threshold(ms, largest_pgsize)) {
+ *pgsize_bitmap = largest_pgsize;
+ return MALIDP_PREFETCH_MODE_FULL;
+ }
+
+ pgsizes -= largest_pgsize;
+ }
+
+ /* get the partial-frame prefetch page size(s) supported by the MMU */
+ pgsizes = *pgsize_bitmap & MALIDP_MMU_PREFETCH_PARTIAL_PGSIZES;
+
+ if (malidp_partial_prefetch_supported(ms->base.fb->format->format,
+ ms->base.fb->modifier,
+ ms->base.rotation)) {
+ /* partial prefetch using the smallest page size */
+ *pgsize_bitmap = 1 << __ffs(pgsizes);
+ return MALIDP_PREFETCH_MODE_PARTIAL;
+ }
+ *pgsize_bitmap = 0;
+ return MALIDP_PREFETCH_MODE_NONE;
+}
+
+static u32 malidp_calc_mmu_control_value(enum mmu_prefetch_mode mode,
+ u8 readahead, u8 n_planes, u32 pgsize)
+{
+ u32 mmu_ctrl = 0;
+
+ if (mode != MALIDP_PREFETCH_MODE_NONE) {
+ mmu_ctrl |= MALIDP_MMU_CTRL_EN;
+
+ if (mode == MALIDP_PREFETCH_MODE_PARTIAL) {
+ mmu_ctrl |= MALIDP_MMU_CTRL_MODE;
+ mmu_ctrl |= MALIDP_MMU_CTRL_PP_NUM_REQ(readahead);
+ }
+
+ if (pgsize == SZ_64K || pgsize == SZ_2M) {
+ int i;
+
+ for (i = 0; i < n_planes; i++)
+ mmu_ctrl |= MALIDP_MMU_CTRL_PX_PS(i);
+ }
+ }
+
+ return mmu_ctrl;
+}
+
+static void malidp_de_prefetch_settings(struct malidp_plane *mp,
+ struct malidp_plane_state *ms)
+{
+ if (!mp->layer->mmu_ctrl_offset)
+ return;
+
+ /* get the page sizes supported by the MMU */
+ ms->mmu_prefetch_pgsize = malidp_get_pgsize_bitmap(mp);
+ ms->mmu_prefetch_mode =
+ malidp_mmu_prefetch_select_mode(ms, &ms->mmu_prefetch_pgsize);
+}
+
static int malidp_de_plane_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
@@ -180,6 +396,7 @@ static int malidp_de_plane_check(struct drm_plane *plane,
struct malidp_plane_state *ms = to_malidp_plane_state(state);
bool rotated = state->rotation & MALIDP_ROTATED_MASK;
struct drm_framebuffer *fb;
+ u16 pixel_alpha = state->pixel_blend_mode;
int i, ret;
if (!state->crtc || !state->fb)
@@ -223,11 +440,20 @@ static int malidp_de_plane_check(struct drm_plane *plane,
if (ret)
return ret;
- /* packed RGB888 / BGR888 can't be rotated or flipped */
- if (state->rotation != DRM_MODE_ROTATE_0 &&
- (fb->format->format == DRM_FORMAT_RGB888 ||
- fb->format->format == DRM_FORMAT_BGR888))
- return -EINVAL;
+ /* validate the rotation constraints for each layer */
+ if (state->rotation != DRM_MODE_ROTATE_0) {
+ if (mp->layer->rot == ROTATE_NONE)
+ return -EINVAL;
+ if ((mp->layer->rot == ROTATE_COMPRESSED) && !(fb->modifier))
+ return -EINVAL;
+ /*
+ * packed RGB888 / BGR888 can't be rotated or flipped
+ * unless they are stored in a compressed way
+ */
+ if ((fb->format->format == DRM_FORMAT_RGB888 ||
+ fb->format->format == DRM_FORMAT_BGR888) && !(fb->modifier))
+ return -EINVAL;
+ }
ms->rotmem_size = 0;
if (state->rotation & MALIDP_ROTATED_MASK) {
@@ -242,6 +468,14 @@ static int malidp_de_plane_check(struct drm_plane *plane,
ms->rotmem_size = val;
}
+ /* HW can't support plane + pixel blending */
+ if ((state->alpha != DRM_BLEND_ALPHA_OPAQUE) &&
+ (pixel_alpha != DRM_MODE_BLEND_PIXEL_NONE) &&
+ fb->format->has_alpha)
+ return -EINVAL;
+
+ malidp_de_prefetch_settings(mp, ms);
+
return 0;
}
@@ -318,22 +552,42 @@ static void malidp_de_set_color_encoding(struct malidp_plane *plane,
}
}
+static void malidp_de_set_mmu_control(struct malidp_plane *mp,
+ struct malidp_plane_state *ms)
+{
+ u32 mmu_ctrl;
+
+ /* check hardware supports MMU prefetch */
+ if (!mp->layer->mmu_ctrl_offset)
+ return;
+
+ mmu_ctrl = malidp_calc_mmu_control_value(ms->mmu_prefetch_mode,
+ MALIDP_MMU_PREFETCH_READAHEAD,
+ ms->n_planes,
+ ms->mmu_prefetch_pgsize);
+
+ malidp_hw_write(mp->hwdev, mmu_ctrl,
+ mp->layer->base + mp->layer->mmu_ctrl_offset);
+}
+
static void malidp_de_plane_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct malidp_plane *mp;
struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
+ struct drm_plane_state *state = plane->state;
+ u16 pixel_alpha = state->pixel_blend_mode;
+ u8 plane_alpha = state->alpha >> 8;
u32 src_w, src_h, dest_w, dest_h, val;
int i;
- bool format_has_alpha = plane->state->fb->format->has_alpha;
mp = to_malidp_plane(plane);
/* convert src values from Q16 fixed point to integer */
- src_w = plane->state->src_w >> 16;
- src_h = plane->state->src_h >> 16;
- dest_w = plane->state->crtc_w;
- dest_h = plane->state->crtc_h;
+ src_w = state->src_w >> 16;
+ src_h = state->src_h >> 16;
+ dest_w = state->crtc_w;
+ dest_h = state->crtc_h;
val = malidp_hw_read(mp->hwdev, mp->layer->base);
val = (val & ~LAYER_FORMAT_MASK) | ms->format;
@@ -342,14 +596,17 @@ static void malidp_de_plane_update(struct drm_plane *plane,
for (i = 0; i < ms->n_planes; i++) {
/* calculate the offset for the layer's plane registers */
u16 ptr = mp->layer->ptr + (i << 4);
- dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(plane->state->fb,
- plane->state, i);
+ dma_addr_t fb_addr = drm_fb_cma_get_gem_addr(state->fb,
+ state, i);
malidp_hw_write(mp->hwdev, lower_32_bits(fb_addr), ptr);
malidp_hw_write(mp->hwdev, upper_32_bits(fb_addr), ptr + 4);
}
+
+ malidp_de_set_mmu_control(mp, ms);
+
malidp_de_set_plane_pitches(mp, ms->n_planes,
- plane->state->fb->pitches);
+ state->fb->pitches);
if ((plane->state->color_encoding != old_state->color_encoding) ||
(plane->state->color_range != old_state->color_range))
@@ -362,52 +619,56 @@ static void malidp_de_plane_update(struct drm_plane *plane,
malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
mp->layer->base + MALIDP_LAYER_COMP_SIZE);
- malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) |
- LAYER_V_VAL(plane->state->crtc_y),
+ malidp_hw_write(mp->hwdev, LAYER_H_VAL(state->crtc_x) |
+ LAYER_V_VAL(state->crtc_y),
mp->layer->base + MALIDP_LAYER_OFFSET);
- if (mp->layer->id == DE_SMART)
+ if (mp->layer->id == DE_SMART) {
+ /*
+ * Enable the first rectangle in the SMART layer to be
+ * able to use it as a drm plane.
+ */
+ malidp_hw_write(mp->hwdev, 1,
+ mp->layer->base + MALIDP550_LS_ENABLE);
malidp_hw_write(mp->hwdev,
LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
mp->layer->base + MALIDP550_LS_R1_IN_SIZE);
+ }
/* first clear the rotation bits */
val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
val &= ~LAYER_ROT_MASK;
/* setup the rotation and axis flip bits */
- if (plane->state->rotation & DRM_MODE_ROTATE_MASK)
+ if (state->rotation & DRM_MODE_ROTATE_MASK)
val |= ilog2(plane->state->rotation & DRM_MODE_ROTATE_MASK) <<
LAYER_ROT_OFFSET;
- if (plane->state->rotation & DRM_MODE_REFLECT_X)
+ if (state->rotation & DRM_MODE_REFLECT_X)
val |= LAYER_H_FLIP;
- if (plane->state->rotation & DRM_MODE_REFLECT_Y)
+ if (state->rotation & DRM_MODE_REFLECT_Y)
val |= LAYER_V_FLIP;
- val &= ~LAYER_COMP_MASK;
- if (format_has_alpha) {
-
- /*
- * always enable pixel alpha blending until we have a way
- * to change blend modes
- */
- val |= LAYER_COMP_PIXEL;
- } else {
+ val &= ~(LAYER_COMP_MASK | LAYER_PMUL_ENABLE | LAYER_ALPHA(0xff));
- /*
- * do not enable pixel alpha blending as the color channel
- * does not have any alpha information
- */
+ if (state->alpha != DRM_BLEND_ALPHA_OPAQUE) {
val |= LAYER_COMP_PLANE;
-
- /* Set layer alpha coefficient to 0xff ie fully opaque */
- val |= LAYER_ALPHA(0xff);
+ } else if (state->fb->format->has_alpha) {
+ /* We only care about blend mode if the format has alpha */
+ switch (pixel_alpha) {
+ case DRM_MODE_BLEND_PREMULTI:
+ val |= LAYER_COMP_PIXEL | LAYER_PMUL_ENABLE;
+ break;
+ case DRM_MODE_BLEND_COVERAGE:
+ val |= LAYER_COMP_PIXEL;
+ break;
+ }
}
+ val |= LAYER_ALPHA(plane_alpha);
val &= ~LAYER_FLOWCFG(LAYER_FLOWCFG_MASK);
- if (plane->state->crtc) {
+ if (state->crtc) {
struct malidp_crtc_state *m =
- to_malidp_crtc_state(plane->state->crtc->state);
+ to_malidp_crtc_state(state->crtc->state);
if (m->scaler_config.scale_enable &&
m->scaler_config.plane_src_id == mp->layer->id)
@@ -446,6 +707,9 @@ int malidp_de_planes_init(struct drm_device *drm)
unsigned long crtcs = 1 << drm->mode_config.num_crtc;
unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 |
DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y;
+ unsigned int blend_caps = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE);
u32 *formats;
int ret, i, j, n;
@@ -483,13 +747,10 @@ int malidp_de_planes_init(struct drm_device *drm)
plane->hwdev = malidp->dev;
plane->layer = &map->layers[i];
+ drm_plane_create_alpha_property(&plane->base);
+ drm_plane_create_blend_mode_property(&plane->base, blend_caps);
+
if (id == DE_SMART) {
- /*
- * Enable the first rectangle in the SMART layer to be
- * able to use it as a drm plane.
- */
- malidp_hw_write(malidp->dev, 1,
- plane->layer->base + MALIDP550_LS_ENABLE);
/* Skip the features which the SMART layer doesn't have. */
continue;
}
diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h
index 3579d36b2a71..7ce3e141464d 100644
--- a/drivers/gpu/drm/arm/malidp_regs.h
+++ b/drivers/gpu/drm/arm/malidp_regs.h
@@ -205,6 +205,7 @@
#define MALIDP500_SE_BASE 0x00c00
#define MALIDP500_SE_CONTROL 0x00c0c
#define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c
+#define MALIDP500_SE_RGB_YUV_COEFFS 0x00C74
#define MALIDP500_SE_MEMWRITE_BASE 0x00e00
#define MALIDP500_DC_IRQ_BASE 0x00f00
#define MALIDP500_CONFIG_VALID 0x00f00
@@ -238,6 +239,7 @@
#define MALIDP550_SE_CONTROL 0x08010
#define MALIDP550_SE_MEMWRITE_ONESHOT (1 << 7)
#define MALIDP550_SE_MEMWRITE_OUT_SIZE 0x08030
+#define MALIDP550_SE_RGB_YUV_COEFFS 0x08078
#define MALIDP550_SE_MEMWRITE_BASE 0x08100
#define MALIDP550_DC_BASE 0x0c000
#define MALIDP550_DC_CONTROL 0x0c010
@@ -245,6 +247,17 @@
#define MALIDP550_CONFIG_VALID 0x0c014
#define MALIDP550_CONFIG_ID 0x0ffd4
+/* register offsets specific to DP650 */
+#define MALIDP650_DE_LV_MMU_CTRL 0x000D0
+#define MALIDP650_DE_LG_MMU_CTRL 0x00048
+#define MALIDP650_DE_LS_MMU_CTRL 0x00078
+
+/* bit masks to set the MMU control register */
+#define MALIDP_MMU_CTRL_EN (1 << 0)
+#define MALIDP_MMU_CTRL_MODE (1 << 4)
+#define MALIDP_MMU_CTRL_PX_PS(x) (1 << (8 + (x)))
+#define MALIDP_MMU_CTRL_PP_NUM_REQ(x) (((x) & 0x7f) << 12)
+
/*
* Starting with DP550 the register map blocks has been standardised to the
* following layout:
diff --git a/drivers/gpu/drm/drm_panel.c b/drivers/gpu/drm/drm_panel.c
index 0db486d10d1c..c33f95e08e1b 100644
--- a/drivers/gpu/drm/drm_panel.c
+++ b/drivers/gpu/drm/drm_panel.c
@@ -24,7 +24,6 @@
#include <linux/err.h>
#include <linux/module.h>
-#include <drm/drm_device.h>
#include <drm/drm_crtc.h>
#include <drm/drm_panel.h>
@@ -105,13 +104,6 @@ int drm_panel_attach(struct drm_panel *panel, struct drm_connector *connector)
if (panel->connector)
return -EBUSY;
- panel->link = device_link_add(connector->dev->dev, panel->dev, 0);
- if (!panel->link) {
- dev_err(panel->dev, "failed to link panel to %s\n",
- dev_name(connector->dev->dev));
- return -EINVAL;
- }
-
panel->connector = connector;
panel->drm = connector->dev;
@@ -133,8 +125,6 @@ EXPORT_SYMBOL(drm_panel_attach);
*/
int drm_panel_detach(struct drm_panel *panel)
{
- device_link_del(panel->link);
-
panel->connector = NULL;
panel->drm = NULL;
diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 5bcb3ef9b256..5c2091dbd230 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -113,6 +113,8 @@ static int drm_syncobj_fence_get_or_add_callback(struct drm_syncobj *syncobj,
{
int ret;
+ WARN_ON(*fence);
+
*fence = drm_syncobj_fence_get(syncobj);
if (*fence)
return 1;
@@ -717,6 +719,9 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs,
if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) {
for (i = 0; i < count; ++i) {
+ if (entries[i].fence)
+ continue;
+
drm_syncobj_fence_get_or_add_callback(syncobjs[i],
&entries[i].fence,
&entries[i].syncobj_cb,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 9b2720b41571..83c1f46670bf 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -592,8 +592,6 @@ static int etnaviv_pdev_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct component_match *match = NULL;
- dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
-
if (!dev->platform_data) {
struct device_node *core_node;
@@ -655,13 +653,30 @@ static int __init etnaviv_init(void)
for_each_compatible_node(np, NULL, "vivante,gc") {
if (!of_device_is_available(np))
continue;
- pdev = platform_device_register_simple("etnaviv", -1,
- NULL, 0);
- if (IS_ERR(pdev)) {
- ret = PTR_ERR(pdev);
+
+ pdev = platform_device_alloc("etnaviv", -1);
+ if (!pdev) {
+ ret = -ENOMEM;
+ of_node_put(np);
+ goto unregister_platform_driver;
+ }
+ pdev->dev.coherent_dma_mask = DMA_BIT_MASK(40);
+ pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+
+ /*
+ * Apply the same DMA configuration to the virtual etnaviv
+ * device as the GPU we found. This assumes that all Vivante
+ * GPUs in the system share the same DMA constraints.
+ */
+ of_dma_configure(&pdev->dev, np, true);
+
+ ret = platform_device_add(pdev);
+ if (ret) {
+ platform_device_put(pdev);
of_node_put(np);
goto unregister_platform_driver;
}
+
etnaviv_drm = pdev;
of_node_put(np);
break;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index b599f74692e5..6f76baf4550a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -149,37 +149,15 @@ static struct drm_driver exynos_drm_driver = {
static int exynos_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct exynos_drm_private *private;
-
- if (!drm_dev)
- return 0;
-
- private = drm_dev->dev_private;
-
- drm_kms_helper_poll_disable(drm_dev);
- exynos_drm_fbdev_suspend(drm_dev);
- private->suspend_state = drm_atomic_helper_suspend(drm_dev);
- if (IS_ERR(private->suspend_state)) {
- exynos_drm_fbdev_resume(drm_dev);
- drm_kms_helper_poll_enable(drm_dev);
- return PTR_ERR(private->suspend_state);
- }
- return 0;
+ return drm_mode_config_helper_suspend(drm_dev);
}
static void exynos_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct exynos_drm_private *private;
-
- if (!drm_dev)
- return;
- private = drm_dev->dev_private;
- drm_atomic_helper_resume(drm_dev, private->suspend_state);
- exynos_drm_fbdev_resume(drm_dev);
- drm_kms_helper_poll_enable(drm_dev);
+ drm_mode_config_helper_resume(drm_dev);
}
static const struct dev_pm_ops exynos_drm_pm_ops = {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index c737c4bd2c19..ec9604f1272b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -92,6 +92,8 @@ struct exynos_drm_plane {
#define EXYNOS_DRM_PLANE_CAP_SCALE (1 << 1)
#define EXYNOS_DRM_PLANE_CAP_ZPOS (1 << 2)
#define EXYNOS_DRM_PLANE_CAP_TILE (1 << 3)
+#define EXYNOS_DRM_PLANE_CAP_PIX_BLEND (1 << 4)
+#define EXYNOS_DRM_PLANE_CAP_WIN_BLEND (1 << 5)
/*
* Exynos DRM plane configuration structure.
@@ -195,7 +197,6 @@ struct drm_exynos_file_private {
*/
struct exynos_drm_private {
struct drm_fb_helper *fb_helper;
- struct drm_atomic_state *suspend_state;
struct device *g2d_dev;
struct device *dma_dev;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 781b82c2c579..07af7758066d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -255,6 +255,7 @@ struct exynos_dsi {
struct mipi_dsi_host dsi_host;
struct drm_connector connector;
struct drm_panel *panel;
+ struct drm_bridge *out_bridge;
struct device *dev;
void __iomem *reg_base;
@@ -279,7 +280,7 @@ struct exynos_dsi {
struct list_head transfer_list;
const struct exynos_dsi_driver_data *driver_data;
- struct device_node *bridge_node;
+ struct device_node *in_bridge_node;
};
#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
@@ -1382,29 +1383,37 @@ static void exynos_dsi_enable(struct drm_encoder *encoder)
return;
pm_runtime_get_sync(dsi->dev);
-
dsi->state |= DSIM_STATE_ENABLED;
- ret = drm_panel_prepare(dsi->panel);
- if (ret < 0) {
- dsi->state &= ~DSIM_STATE_ENABLED;
- pm_runtime_put_sync(dsi->dev);
- return;
+ if (dsi->panel) {
+ ret = drm_panel_prepare(dsi->panel);
+ if (ret < 0)
+ goto err_put_sync;
+ } else {
+ drm_bridge_pre_enable(dsi->out_bridge);
}
exynos_dsi_set_display_mode(dsi);
exynos_dsi_set_display_enable(dsi, true);
- ret = drm_panel_enable(dsi->panel);
- if (ret < 0) {
- dsi->state &= ~DSIM_STATE_ENABLED;
- exynos_dsi_set_display_enable(dsi, false);
- drm_panel_unprepare(dsi->panel);
- pm_runtime_put_sync(dsi->dev);
- return;
+ if (dsi->panel) {
+ ret = drm_panel_enable(dsi->panel);
+ if (ret < 0)
+ goto err_display_disable;
+ } else {
+ drm_bridge_enable(dsi->out_bridge);
}
dsi->state |= DSIM_STATE_VIDOUT_AVAILABLE;
+ return;
+
+err_display_disable:
+ exynos_dsi_set_display_enable(dsi, false);
+ drm_panel_unprepare(dsi->panel);
+
+err_put_sync:
+ dsi->state &= ~DSIM_STATE_ENABLED;
+ pm_runtime_put(dsi->dev);
}
static void exynos_dsi_disable(struct drm_encoder *encoder)
@@ -1417,11 +1426,11 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
dsi->state &= ~DSIM_STATE_VIDOUT_AVAILABLE;
drm_panel_disable(dsi->panel);
+ drm_bridge_disable(dsi->out_bridge);
exynos_dsi_set_display_enable(dsi, false);
drm_panel_unprepare(dsi->panel);
-
+ drm_bridge_post_disable(dsi->out_bridge);
dsi->state &= ~DSIM_STATE_ENABLED;
-
pm_runtime_put_sync(dsi->dev);
}
@@ -1499,7 +1508,30 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct exynos_dsi *dsi = host_to_dsi(host);
- struct drm_device *drm = dsi->connector.dev;
+ struct drm_encoder *encoder = &dsi->encoder;
+ struct drm_device *drm = encoder->dev;
+ struct drm_bridge *out_bridge;
+
+ out_bridge = of_drm_find_bridge(device->dev.of_node);
+ if (out_bridge) {
+ drm_bridge_attach(encoder, out_bridge, NULL);
+ dsi->out_bridge = out_bridge;
+ encoder->bridge = NULL;
+ } else {
+ int ret = exynos_dsi_create_connector(encoder);
+
+ if (ret) {
+ DRM_ERROR("failed to create connector ret = %d\n", ret);
+ drm_encoder_cleanup(encoder);
+ return ret;
+ }
+
+ dsi->panel = of_drm_find_panel(device->dev.of_node);
+ if (dsi->panel) {
+ drm_panel_attach(dsi->panel, &dsi->connector);
+ dsi->connector.status = connector_status_connected;
+ }
+ }
/*
* This is a temporary solution and should be made by more generic way.
@@ -1518,14 +1550,6 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
dsi->lanes = device->lanes;
dsi->format = device->format;
dsi->mode_flags = device->mode_flags;
- dsi->panel = of_drm_find_panel(device->dev.of_node);
- if (IS_ERR(dsi->panel))
- dsi->panel = NULL;
-
- if (dsi->panel) {
- drm_panel_attach(dsi->panel, &dsi->connector);
- dsi->connector.status = connector_status_connected;
- }
exynos_drm_crtc_get_by_type(drm, EXYNOS_DISPLAY_TYPE_LCD)->i80_mode =
!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO);
@@ -1541,19 +1565,21 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
struct mipi_dsi_device *device)
{
struct exynos_dsi *dsi = host_to_dsi(host);
- struct drm_device *drm = dsi->connector.dev;
-
- mutex_lock(&drm->mode_config.mutex);
+ struct drm_device *drm = dsi->encoder.dev;
if (dsi->panel) {
+ mutex_lock(&drm->mode_config.mutex);
exynos_dsi_disable(&dsi->encoder);
drm_panel_detach(dsi->panel);
dsi->panel = NULL;
dsi->connector.status = connector_status_disconnected;
+ mutex_unlock(&drm->mode_config.mutex);
+ } else {
+ if (dsi->out_bridge->funcs->detach)
+ dsi->out_bridge->funcs->detach(dsi->out_bridge);
+ dsi->out_bridge = NULL;
}
- mutex_unlock(&drm->mode_config.mutex);
-
if (drm->mode_config.poll_enabled)
drm_kms_helper_hotplug_event(drm);
@@ -1634,7 +1660,7 @@ static int exynos_dsi_parse_dt(struct exynos_dsi *dsi)
if (ret < 0)
return ret;
- dsi->bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0);
+ dsi->in_bridge_node = of_graph_get_remote_node(node, DSI_PORT_IN, 0);
return 0;
}
@@ -1645,7 +1671,7 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
struct drm_encoder *encoder = dev_get_drvdata(dev);
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
struct drm_device *drm_dev = data;
- struct drm_bridge *bridge;
+ struct drm_bridge *in_bridge;
int ret;
drm_encoder_init(drm_dev, encoder, &exynos_dsi_encoder_funcs,
@@ -1657,17 +1683,10 @@ static int exynos_dsi_bind(struct device *dev, struct device *master,
if (ret < 0)
return ret;
- ret = exynos_dsi_create_connector(encoder);
- if (ret) {
- DRM_ERROR("failed to create connector ret = %d\n", ret);
- drm_encoder_cleanup(encoder);
- return ret;
- }
-
- if (dsi->bridge_node) {
- bridge = of_drm_find_bridge(dsi->bridge_node);
- if (bridge)
- drm_bridge_attach(encoder, bridge, NULL);
+ if (dsi->in_bridge_node) {
+ in_bridge = of_drm_find_bridge(dsi->in_bridge_node);
+ if (in_bridge)
+ drm_bridge_attach(encoder, in_bridge, NULL);
}
return mipi_dsi_host_register(&dsi->dsi_host);
@@ -1786,7 +1805,7 @@ static int exynos_dsi_remove(struct platform_device *pdev)
{
struct exynos_dsi *dsi = platform_get_drvdata(pdev);
- of_node_put(dsi->bridge_node);
+ of_node_put(dsi->in_bridge_node);
pm_runtime_disable(&pdev->dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 132dd52d0ac7..918dd2c82209 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -270,20 +270,3 @@ void exynos_drm_fbdev_fini(struct drm_device *dev)
private->fb_helper = NULL;
}
-void exynos_drm_fbdev_suspend(struct drm_device *dev)
-{
- struct exynos_drm_private *private = dev->dev_private;
-
- console_lock();
- drm_fb_helper_set_suspend(private->fb_helper, 1);
- console_unlock();
-}
-
-void exynos_drm_fbdev_resume(struct drm_device *dev)
-{
- struct exynos_drm_private *private = dev->dev_private;
-
- console_lock();
- drm_fb_helper_set_suspend(private->fb_helper, 0);
- console_unlock();
-}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
index b33847223a85..6840b6aadbc0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.h
@@ -19,8 +19,6 @@
int exynos_drm_fbdev_init(struct drm_device *dev);
void exynos_drm_fbdev_fini(struct drm_device *dev);
-void exynos_drm_fbdev_suspend(struct drm_device *drm);
-void exynos_drm_fbdev_resume(struct drm_device *drm);
#else
@@ -39,14 +37,6 @@ static inline void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
#define exynos_drm_output_poll_changed (NULL)
-static inline void exynos_drm_fbdev_suspend(struct drm_device *drm)
-{
-}
-
-static inline void exynos_drm_fbdev_resume(struct drm_device *drm)
-{
-}
-
#endif
#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 7ba414b52faa..ce15d46bfce8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -448,7 +448,7 @@ static void gsc_handle_irq(struct gsc_context *ctx, bool enable,
}
-static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt)
+static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt, bool tiled)
{
u32 cfg;
@@ -514,6 +514,9 @@ static void gsc_src_set_fmt(struct gsc_context *ctx, u32 fmt)
break;
}
+ if (tiled)
+ cfg |= (GSC_IN_TILE_C_16x8 | GSC_IN_TILE_MODE);
+
gsc_write(cfg, GSC_IN_CON);
}
@@ -632,7 +635,7 @@ static void gsc_src_set_addr(struct gsc_context *ctx, u32 buf_id,
gsc_src_set_buf_seq(ctx, buf_id, true);
}
-static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt)
+static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt, bool tiled)
{
u32 cfg;
@@ -698,6 +701,9 @@ static void gsc_dst_set_fmt(struct gsc_context *ctx, u32 fmt)
break;
}
+ if (tiled)
+ cfg |= (GSC_IN_TILE_C_16x8 | GSC_OUT_TILE_MODE);
+
gsc_write(cfg, GSC_OUT_CON);
}
@@ -1122,11 +1128,11 @@ static int gsc_commit(struct exynos_drm_ipp *ipp,
return ret;
}
- gsc_src_set_fmt(ctx, task->src.buf.fourcc);
+ gsc_src_set_fmt(ctx, task->src.buf.fourcc, task->src.buf.modifier);
gsc_src_set_transf(ctx, task->transform.rotation);
gsc_src_set_size(ctx, &task->src);
gsc_src_set_addr(ctx, 0, &task->src);
- gsc_dst_set_fmt(ctx, task->dst.buf.fourcc);
+ gsc_dst_set_fmt(ctx, task->dst.buf.fourcc, task->dst.buf.modifier);
gsc_dst_set_size(ctx, &task->dst);
gsc_dst_set_addr(ctx, 0, &task->dst);
gsc_set_prescaler(ctx, &ctx->sc, &task->src.rect, &task->dst.rect);
@@ -1200,6 +1206,10 @@ static const unsigned int gsc_formats[] = {
DRM_FORMAT_YUV420, DRM_FORMAT_YVU420, DRM_FORMAT_YUV422,
};
+static const unsigned int gsc_tiled_formats[] = {
+ DRM_FORMAT_NV12, DRM_FORMAT_NV21,
+};
+
static int gsc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1207,23 +1217,24 @@ static int gsc_probe(struct platform_device *pdev)
struct exynos_drm_ipp_formats *formats;
struct gsc_context *ctx;
struct resource *res;
- int ret, i;
+ int num_formats, ret, i, j;
ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
- formats = devm_kcalloc(dev,
- ARRAY_SIZE(gsc_formats), sizeof(*formats),
- GFP_KERNEL);
- if (!formats)
- return -ENOMEM;
-
driver_data = (struct gsc_driverdata *)of_device_get_match_data(dev);
ctx->dev = dev;
ctx->num_clocks = driver_data->num_clocks;
ctx->clk_names = driver_data->clk_names;
+ /* construct formats/limits array */
+ num_formats = ARRAY_SIZE(gsc_formats) + ARRAY_SIZE(gsc_tiled_formats);
+ formats = devm_kcalloc(dev, num_formats, sizeof(*formats), GFP_KERNEL);
+ if (!formats)
+ return -ENOMEM;
+
+ /* linear formats */
for (i = 0; i < ARRAY_SIZE(gsc_formats); i++) {
formats[i].fourcc = gsc_formats[i];
formats[i].type = DRM_EXYNOS_IPP_FORMAT_SOURCE |
@@ -1231,8 +1242,19 @@ static int gsc_probe(struct platform_device *pdev)
formats[i].limits = driver_data->limits;
formats[i].num_limits = driver_data->num_limits;
}
+
+ /* tiled formats */
+ for (j = i, i = 0; i < ARRAY_SIZE(gsc_tiled_formats); j++, i++) {
+ formats[j].fourcc = gsc_tiled_formats[i];
+ formats[j].modifier = DRM_FORMAT_MOD_SAMSUNG_16_16_TILE;
+ formats[j].type = DRM_EXYNOS_IPP_FORMAT_SOURCE |
+ DRM_EXYNOS_IPP_FORMAT_DESTINATION;
+ formats[j].limits = driver_data->limits;
+ formats[j].num_limits = driver_data->num_limits;
+ }
+
ctx->formats = formats;
- ctx->num_formats = ARRAY_SIZE(gsc_formats);
+ ctx->num_formats = num_formats;
/* clock control */
for (i = 0; i < ctx->num_clocks; i++) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index dba29aec59b4..df0508e0e49e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -131,16 +131,14 @@ static void exynos_drm_plane_reset(struct drm_plane *plane)
if (plane->state) {
exynos_state = to_exynos_plane_state(plane->state);
- if (exynos_state->base.fb)
- drm_framebuffer_put(exynos_state->base.fb);
+ __drm_atomic_helper_plane_destroy_state(plane->state);
kfree(exynos_state);
plane->state = NULL;
}
exynos_state = kzalloc(sizeof(*exynos_state), GFP_KERNEL);
if (exynos_state) {
- plane->state = &exynos_state->base;
- plane->state->plane = plane;
+ __drm_atomic_helper_plane_reset(plane, &exynos_state->base);
plane->state->zpos = exynos_plane->config->zpos;
}
}
@@ -300,6 +298,10 @@ int exynos_plane_init(struct drm_device *dev,
const struct exynos_drm_plane_config *config)
{
int err;
+ unsigned int supported_modes = BIT(DRM_MODE_BLEND_PIXEL_NONE) |
+ BIT(DRM_MODE_BLEND_PREMULTI) |
+ BIT(DRM_MODE_BLEND_COVERAGE);
+ struct drm_plane *plane = &exynos_plane->base;
err = drm_universal_plane_init(dev, &exynos_plane->base,
1 << dev->mode_config.num_crtc,
@@ -320,5 +322,11 @@ int exynos_plane_init(struct drm_device *dev,
exynos_plane_attach_zpos_property(&exynos_plane->base, config->zpos,
!(config->capabilities & EXYNOS_DRM_PLANE_CAP_ZPOS));
+ if (config->capabilities & EXYNOS_DRM_PLANE_CAP_PIX_BLEND)
+ drm_plane_create_blend_mode_property(plane, supported_modes);
+
+ if (config->capabilities & EXYNOS_DRM_PLANE_CAP_WIN_BLEND)
+ drm_plane_create_alpha_property(plane);
+
return 0;
}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index 0ddb6eec7b11..cd66774e817d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -49,56 +49,46 @@ struct scaler_context {
const struct scaler_data *scaler_data;
};
-static u32 scaler_get_format(u32 drm_fmt)
+struct scaler_format {
+ u32 drm_fmt;
+ u32 internal_fmt;
+ u32 chroma_tile_w;
+ u32 chroma_tile_h;
+};
+
+static const struct scaler_format scaler_formats[] = {
+ { DRM_FORMAT_NV12, SCALER_YUV420_2P_UV, 8, 8 },
+ { DRM_FORMAT_NV21, SCALER_YUV420_2P_VU, 8, 8 },
+ { DRM_FORMAT_YUV420, SCALER_YUV420_3P, 8, 8 },
+ { DRM_FORMAT_YUYV, SCALER_YUV422_1P_YUYV, 16, 16 },
+ { DRM_FORMAT_UYVY, SCALER_YUV422_1P_UYVY, 16, 16 },
+ { DRM_FORMAT_YVYU, SCALER_YUV422_1P_YVYU, 16, 16 },
+ { DRM_FORMAT_NV16, SCALER_YUV422_2P_UV, 8, 16 },
+ { DRM_FORMAT_NV61, SCALER_YUV422_2P_VU, 8, 16 },
+ { DRM_FORMAT_YUV422, SCALER_YUV422_3P, 8, 16 },
+ { DRM_FORMAT_NV24, SCALER_YUV444_2P_UV, 16, 16 },
+ { DRM_FORMAT_NV42, SCALER_YUV444_2P_VU, 16, 16 },
+ { DRM_FORMAT_YUV444, SCALER_YUV444_3P, 16, 16 },
+ { DRM_FORMAT_RGB565, SCALER_RGB_565, 0, 0 },
+ { DRM_FORMAT_XRGB1555, SCALER_ARGB1555, 0, 0 },
+ { DRM_FORMAT_ARGB1555, SCALER_ARGB1555, 0, 0 },
+ { DRM_FORMAT_XRGB4444, SCALER_ARGB4444, 0, 0 },
+ { DRM_FORMAT_ARGB4444, SCALER_ARGB4444, 0, 0 },
+ { DRM_FORMAT_XRGB8888, SCALER_ARGB8888, 0, 0 },
+ { DRM_FORMAT_ARGB8888, SCALER_ARGB8888, 0, 0 },
+ { DRM_FORMAT_RGBX8888, SCALER_RGBA8888, 0, 0 },
+ { DRM_FORMAT_RGBA8888, SCALER_RGBA8888, 0, 0 },
+};
+
+static const struct scaler_format *scaler_get_format(u32 drm_fmt)
{
- switch (drm_fmt) {
- case DRM_FORMAT_NV12:
- return SCALER_YUV420_2P_UV;
- case DRM_FORMAT_NV21:
- return SCALER_YUV420_2P_VU;
- case DRM_FORMAT_YUV420:
- return SCALER_YUV420_3P;
- case DRM_FORMAT_YUYV:
- return SCALER_YUV422_1P_YUYV;
- case DRM_FORMAT_UYVY:
- return SCALER_YUV422_1P_UYVY;
- case DRM_FORMAT_YVYU:
- return SCALER_YUV422_1P_YVYU;
- case DRM_FORMAT_NV16:
- return SCALER_YUV422_2P_UV;
- case DRM_FORMAT_NV61:
- return SCALER_YUV422_2P_VU;
- case DRM_FORMAT_YUV422:
- return SCALER_YUV422_3P;
- case DRM_FORMAT_NV24:
- return SCALER_YUV444_2P_UV;
- case DRM_FORMAT_NV42:
- return SCALER_YUV444_2P_VU;
- case DRM_FORMAT_YUV444:
- return SCALER_YUV444_3P;
- case DRM_FORMAT_RGB565:
- return SCALER_RGB_565;
- case DRM_FORMAT_XRGB1555:
- return SCALER_ARGB1555;
- case DRM_FORMAT_ARGB1555:
- return SCALER_ARGB1555;
- case DRM_FORMAT_XRGB4444:
- return SCALER_ARGB4444;
- case DRM_FORMAT_ARGB4444:
- return SCALER_ARGB4444;
- case DRM_FORMAT_XRGB8888:
- return SCALER_ARGB8888;
- case DRM_FORMAT_ARGB8888:
- return SCALER_ARGB8888;
- case DRM_FORMAT_RGBX8888:
- return SCALER_RGBA8888;
- case DRM_FORMAT_RGBA8888:
- return SCALER_RGBA8888;
- default:
- break;
- }
+ int i;
- return 0;
+ for (i = 0; i < ARRAY_SIZE(scaler_formats); i++)
+ if (scaler_formats[i].drm_fmt == drm_fmt)
+ return &scaler_formats[i];
+
+ return NULL;
}
static inline int scaler_reset(struct scaler_context *scaler)
@@ -152,11 +142,11 @@ static inline void scaler_enable_int(struct scaler_context *scaler)
}
static inline void scaler_set_src_fmt(struct scaler_context *scaler,
- u32 src_fmt)
+ u32 src_fmt, u32 tile)
{
u32 val;
- val = SCALER_SRC_CFG_SET_COLOR_FORMAT(src_fmt);
+ val = SCALER_SRC_CFG_SET_COLOR_FORMAT(src_fmt) | (tile << 10);
scaler_write(val, SCALER_SRC_CFG);
}
@@ -188,15 +178,20 @@ static inline void scaler_set_src_span(struct scaler_context *scaler,
scaler_write(val, SCALER_SRC_SPAN);
}
-static inline void scaler_set_src_luma_pos(struct scaler_context *scaler,
- struct drm_exynos_ipp_task_rect *src_pos)
+static inline void scaler_set_src_luma_chroma_pos(struct scaler_context *scaler,
+ struct drm_exynos_ipp_task_rect *src_pos,
+ const struct scaler_format *fmt)
{
u32 val;
val = SCALER_SRC_Y_POS_SET_YH_POS(src_pos->x << 2);
val |= SCALER_SRC_Y_POS_SET_YV_POS(src_pos->y << 2);
scaler_write(val, SCALER_SRC_Y_POS);
- scaler_write(val, SCALER_SRC_C_POS); /* ATTENTION! */
+ val = SCALER_SRC_C_POS_SET_CH_POS(
+ (src_pos->x * fmt->chroma_tile_w / 16) << 2);
+ val |= SCALER_SRC_C_POS_SET_CV_POS(
+ (src_pos->y * fmt->chroma_tile_h / 16) << 2);
+ scaler_write(val, SCALER_SRC_C_POS);
}
static inline void scaler_set_src_wh(struct scaler_context *scaler,
@@ -366,11 +361,12 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
struct scaler_context *scaler =
container_of(ipp, struct scaler_context, ipp);
- u32 src_fmt = scaler_get_format(task->src.buf.fourcc);
struct drm_exynos_ipp_task_rect *src_pos = &task->src.rect;
-
- u32 dst_fmt = scaler_get_format(task->dst.buf.fourcc);
struct drm_exynos_ipp_task_rect *dst_pos = &task->dst.rect;
+ const struct scaler_format *src_fmt, *dst_fmt;
+
+ src_fmt = scaler_get_format(task->src.buf.fourcc);
+ dst_fmt = scaler_get_format(task->dst.buf.fourcc);
pm_runtime_get_sync(scaler->dev);
if (scaler_reset(scaler)) {
@@ -380,13 +376,14 @@ static int scaler_commit(struct exynos_drm_ipp *ipp,
scaler->task = task;
- scaler_set_src_fmt(scaler, src_fmt);
+ scaler_set_src_fmt(
+ scaler, src_fmt->internal_fmt, task->src.buf.modifier != 0);
scaler_set_src_base(scaler, &task->src);
scaler_set_src_span(scaler, &task->src);
- scaler_set_src_luma_pos(scaler, src_pos);
+ scaler_set_src_luma_chroma_pos(scaler, src_pos, src_fmt);
scaler_set_src_wh(scaler, src_pos);
- scaler_set_dst_fmt(scaler, dst_fmt);
+ scaler_set_dst_fmt(scaler, dst_fmt->internal_fmt);
scaler_set_dst_base(scaler, &task->dst);
scaler_set_dst_span(scaler, &task->dst);
scaler_set_dst_luma_pos(scaler, dst_pos);
@@ -617,6 +614,16 @@ static const struct drm_exynos_ipp_limit scaler_5420_one_pixel_limits[] = {
.v = { 65536 * 1 / 4, 65536 * 16 }) },
};
+static const struct drm_exynos_ipp_limit scaler_5420_tile_limits[] = {
+ { IPP_SIZE_LIMIT(BUFFER, .h = { 16, SZ_8K }, .v = { 16, SZ_8K })},
+ { IPP_SIZE_LIMIT(AREA, .h.align = 16, .v.align = 16) },
+ { IPP_SCALE_LIMIT(.h = {1, 1}, .v = {1, 1})},
+ { }
+};
+
+#define IPP_SRCDST_TILE_FORMAT(f, l) \
+ IPP_SRCDST_MFORMAT(f, DRM_FORMAT_MOD_SAMSUNG_16_16_TILE, (l))
+
static const struct exynos_drm_ipp_formats exynos5420_formats[] = {
/* SCALER_YUV420_2P_UV */
{ IPP_SRCDST_FORMAT(NV21, scaler_5420_two_pixel_hv_limits) },
@@ -680,6 +687,18 @@ static const struct exynos_drm_ipp_formats exynos5420_formats[] = {
/* SCALER_RGBA8888 */
{ IPP_SRCDST_FORMAT(RGBA8888, scaler_5420_one_pixel_limits) },
+
+ /* SCALER_YUV420_2P_UV TILE */
+ { IPP_SRCDST_TILE_FORMAT(NV21, scaler_5420_tile_limits) },
+
+ /* SCALER_YUV420_2P_VU TILE */
+ { IPP_SRCDST_TILE_FORMAT(NV12, scaler_5420_tile_limits) },
+
+ /* SCALER_YUV420_3P TILE */
+ { IPP_SRCDST_TILE_FORMAT(YUV420, scaler_5420_tile_limits) },
+
+ /* SCALER_YUV422_1P_YUYV TILE */
+ { IPP_SRCDST_TILE_FORMAT(YUYV, scaler_5420_tile_limits) },
};
static const struct scaler_data exynos5420_data = {
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index ffbf4a950f69..e3a4ecbc503b 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -131,14 +131,18 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
.pixel_formats = mixer_formats,
.num_pixel_formats = ARRAY_SIZE(mixer_formats),
.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
- EXYNOS_DRM_PLANE_CAP_ZPOS,
+ EXYNOS_DRM_PLANE_CAP_ZPOS |
+ EXYNOS_DRM_PLANE_CAP_PIX_BLEND |
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
}, {
.zpos = 1,
.type = DRM_PLANE_TYPE_CURSOR,
.pixel_formats = mixer_formats,
.num_pixel_formats = ARRAY_SIZE(mixer_formats),
.capabilities = EXYNOS_DRM_PLANE_CAP_DOUBLE |
- EXYNOS_DRM_PLANE_CAP_ZPOS,
+ EXYNOS_DRM_PLANE_CAP_ZPOS |
+ EXYNOS_DRM_PLANE_CAP_PIX_BLEND |
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
}, {
.zpos = 2,
.type = DRM_PLANE_TYPE_OVERLAY,
@@ -146,7 +150,8 @@ static const struct exynos_drm_plane_config plane_configs[MIXER_WIN_NR] = {
.num_pixel_formats = ARRAY_SIZE(vp_formats),
.capabilities = EXYNOS_DRM_PLANE_CAP_SCALE |
EXYNOS_DRM_PLANE_CAP_ZPOS |
- EXYNOS_DRM_PLANE_CAP_TILE,
+ EXYNOS_DRM_PLANE_CAP_TILE |
+ EXYNOS_DRM_PLANE_CAP_WIN_BLEND,
},
};
@@ -309,31 +314,42 @@ static void vp_default_filter(struct mixer_context *ctx)
}
static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win,
- bool alpha)
+ unsigned int pixel_alpha, unsigned int alpha)
{
+ u32 win_alpha = alpha >> 8;
u32 val;
val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
- if (alpha) {
- /* blending based on pixel alpha */
+ switch (pixel_alpha) {
+ case DRM_MODE_BLEND_PIXEL_NONE:
+ break;
+ case DRM_MODE_BLEND_COVERAGE:
+ val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
+ break;
+ case DRM_MODE_BLEND_PREMULTI:
+ default:
val |= MXR_GRP_CFG_BLEND_PRE_MUL;
val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
+ break;
+ }
+
+ if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
+ val |= MXR_GRP_CFG_WIN_BLEND_EN;
+ val |= win_alpha;
}
mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win),
val, MXR_GRP_CFG_MISC_MASK);
}
-static void mixer_cfg_vp_blend(struct mixer_context *ctx)
+static void mixer_cfg_vp_blend(struct mixer_context *ctx, unsigned int alpha)
{
- u32 val;
+ u32 win_alpha = alpha >> 8;
+ u32 val = 0;
- /*
- * No blending at the moment since the NV12/NV21 pixelformats don't
- * have an alpha channel. However the mixer supports a global alpha
- * value for a layer. Once this functionality is exposed, we can
- * support blending of the video layer through this.
- */
- val = 0;
+ if (alpha != DRM_BLEND_ALPHA_OPAQUE) {
+ val |= MXR_VID_CFG_BLEND_EN;
+ val |= win_alpha;
+ }
mixer_reg_write(ctx, MXR_VIDEO_CFG, val);
}
@@ -529,7 +545,7 @@ static void vp_video_buffer(struct mixer_context *ctx,
vp_reg_write(ctx, VP_BOT_C_PTR, chroma_addr[1]);
mixer_cfg_layer(ctx, plane->index, priority, true);
- mixer_cfg_vp_blend(ctx);
+ mixer_cfg_vp_blend(ctx, state->base.alpha);
spin_unlock_irqrestore(&ctx->reg_slock, flags);
@@ -553,10 +569,16 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
unsigned int win = plane->index;
unsigned int x_ratio = 0, y_ratio = 0;
unsigned int dst_x_offset, dst_y_offset;
+ unsigned int pixel_alpha;
dma_addr_t dma_addr;
unsigned int fmt;
u32 val;
+ if (fb->format->has_alpha)
+ pixel_alpha = state->base.pixel_blend_mode;
+ else
+ pixel_alpha = DRM_MODE_BLEND_PIXEL_NONE;
+
switch (fb->format->format) {
case DRM_FORMAT_XRGB4444:
case DRM_FORMAT_ARGB4444:
@@ -616,7 +638,7 @@ static void mixer_graph_buffer(struct mixer_context *ctx,
mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr);
mixer_cfg_layer(ctx, win, priority, true);
- mixer_cfg_gfx_blend(ctx, win, fb->format->has_alpha);
+ mixer_cfg_gfx_blend(ctx, win, pixel_alpha, state->base.alpha);
/* layer update mandatory for mixer 16.0.33.0 */
if (ctx->mxr_ver == MXR_VER_16_0_33_0 ||
diff --git a/drivers/gpu/drm/exynos/regs-mixer.h b/drivers/gpu/drm/exynos/regs-mixer.h
index 189cfa2470a8..d2b8194a07bf 100644
--- a/drivers/gpu/drm/exynos/regs-mixer.h
+++ b/drivers/gpu/drm/exynos/regs-mixer.h
@@ -109,12 +109,15 @@
#define MXR_CFG_SCAN_HD (1 << 0)
#define MXR_CFG_SCAN_MASK 0x47
+/* bits for MXR_VIDEO_CFG */
+#define MXR_VID_CFG_BLEND_EN (1 << 16)
+
/* bits for MXR_GRAPHICn_CFG */
#define MXR_GRP_CFG_COLOR_KEY_DISABLE (1 << 21)
#define MXR_GRP_CFG_BLEND_PRE_MUL (1 << 20)
#define MXR_GRP_CFG_WIN_BLEND_EN (1 << 17)
#define MXR_GRP_CFG_PIXEL_BLEND_EN (1 << 16)
-#define MXR_GRP_CFG_MISC_MASK ((3 << 16) | (3 << 20))
+#define MXR_GRP_CFG_MISC_MASK ((3 << 16) | (3 << 20) | 0xff)
#define MXR_GRP_CFG_FORMAT_VAL(x) MXR_MASK_VAL(x, 11, 8)
#define MXR_GRP_CFG_FORMAT_MASK MXR_GRP_CFG_FORMAT_VAL(~0)
#define MXR_GRP_CFG_ALPHA_VAL(x) MXR_MASK_VAL(x, 7, 0)
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index ce83c396a742..82ae49c64221 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
+
mediatek-drm-y := mtk_disp_color.o \
mtk_disp_ovl.o \
mtk_disp_rdma.o \
@@ -18,6 +19,8 @@ obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
mediatek-drm-hdmi-objs := mtk_cec.o \
mtk_hdmi.o \
mtk_hdmi_ddc.o \
- mtk_mt8173_hdmi_phy.o
+ mtk_mt2701_hdmi_phy.o \
+ mtk_mt8173_hdmi_phy.o \
+ mtk_hdmi_phy.o
obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 6c0ea39d5739..62a9d47df948 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -14,10 +14,12 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_of.h>
#include <linux/kernel.h>
#include <linux/component.h>
#include <linux/platform_device.h>
#include <linux/of.h>
+#include <linux/of_device.h>
#include <linux/of_graph.h>
#include <linux/interrupt.h>
#include <linux/types.h>
@@ -72,12 +74,12 @@ struct mtk_dpi {
struct clk *tvd_clk;
int irq;
struct drm_display_mode mode;
+ const struct mtk_dpi_conf *conf;
enum mtk_dpi_out_color_format color_format;
enum mtk_dpi_out_yc_map yc_map;
enum mtk_dpi_out_bit_num bit_num;
enum mtk_dpi_out_channel_swap channel_swap;
- bool power_sta;
- u8 power_ctl;
+ int refcount;
};
static inline struct mtk_dpi *mtk_dpi_from_encoder(struct drm_encoder *e)
@@ -90,11 +92,6 @@ enum mtk_dpi_polarity {
MTK_DPI_POLARITY_FALLING,
};
-enum mtk_dpi_power_ctl {
- DPI_POWER_START = BIT(0),
- DPI_POWER_ENABLE = BIT(1),
-};
-
struct mtk_dpi_polarities {
enum mtk_dpi_polarity de_pol;
enum mtk_dpi_polarity ck_pol;
@@ -116,6 +113,12 @@ struct mtk_dpi_yc_limit {
u16 c_bottom;
};
+struct mtk_dpi_conf {
+ unsigned int (*cal_factor)(int clock);
+ u32 reg_h_fre_con;
+ bool edge_sel_en;
+};
+
static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask)
{
u32 tmp = readl(dpi->regs + offset) & ~mask;
@@ -341,7 +344,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable)
static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi)
{
- mtk_dpi_mask(dpi, DPI_H_FRE_CON, H_FRE_2N, H_FRE_2N);
+ mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N);
+}
+
+static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi)
+{
+ if (dpi->conf->edge_sel_en)
+ mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN);
}
static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
@@ -367,40 +376,30 @@ static void mtk_dpi_config_color_format(struct mtk_dpi *dpi,
}
}
-static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
+static void mtk_dpi_power_off(struct mtk_dpi *dpi)
{
- dpi->power_ctl &= ~pctl;
-
- if ((dpi->power_ctl & DPI_POWER_START) ||
- (dpi->power_ctl & DPI_POWER_ENABLE))
+ if (WARN_ON(dpi->refcount == 0))
return;
- if (!dpi->power_sta)
+ if (--dpi->refcount != 0)
return;
mtk_dpi_disable(dpi);
clk_disable_unprepare(dpi->pixel_clk);
clk_disable_unprepare(dpi->engine_clk);
- dpi->power_sta = false;
}
-static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
+static int mtk_dpi_power_on(struct mtk_dpi *dpi)
{
int ret;
- dpi->power_ctl |= pctl;
-
- if (!(dpi->power_ctl & DPI_POWER_START) &&
- !(dpi->power_ctl & DPI_POWER_ENABLE))
- return 0;
-
- if (dpi->power_sta)
+ if (++dpi->refcount != 1)
return 0;
ret = clk_prepare_enable(dpi->engine_clk);
if (ret) {
dev_err(dpi->dev, "Failed to enable engine clock: %d\n", ret);
- goto err_eng;
+ goto err_refcount;
}
ret = clk_prepare_enable(dpi->pixel_clk);
@@ -410,13 +409,12 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl)
}
mtk_dpi_enable(dpi);
- dpi->power_sta = true;
return 0;
err_pixel:
clk_disable_unprepare(dpi->engine_clk);
-err_eng:
- dpi->power_ctl &= ~pctl;
+err_refcount:
+ dpi->refcount--;
return ret;
}
@@ -435,15 +433,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
unsigned int factor;
/* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */
-
- if (mode->clock <= 27000)
- factor = 3 << 4;
- else if (mode->clock <= 84000)
- factor = 3 << 3;
- else if (mode->clock <= 167000)
- factor = 3 << 2;
- else
- factor = 3 << 1;
+ factor = dpi->conf->cal_factor(mode->clock);
drm_display_mode_to_videomode(mode, &vm);
pll_rate = vm.pixelclock * factor;
@@ -518,6 +508,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi,
mtk_dpi_config_yc_map(dpi, dpi->yc_map);
mtk_dpi_config_color_format(dpi, dpi->color_format);
mtk_dpi_config_2n_h_fre(dpi);
+ mtk_dpi_config_disable_edge(dpi);
mtk_dpi_sw_reset(dpi, false);
return 0;
@@ -552,14 +543,14 @@ static void mtk_dpi_encoder_disable(struct drm_encoder *encoder)
{
struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
- mtk_dpi_power_off(dpi, DPI_POWER_ENABLE);
+ mtk_dpi_power_off(dpi);
}
static void mtk_dpi_encoder_enable(struct drm_encoder *encoder)
{
struct mtk_dpi *dpi = mtk_dpi_from_encoder(encoder);
- mtk_dpi_power_on(dpi, DPI_POWER_ENABLE);
+ mtk_dpi_power_on(dpi);
mtk_dpi_set_display_mode(dpi, &dpi->mode);
}
@@ -582,14 +573,14 @@ static void mtk_dpi_start(struct mtk_ddp_comp *comp)
{
struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
- mtk_dpi_power_on(dpi, DPI_POWER_START);
+ mtk_dpi_power_on(dpi);
}
static void mtk_dpi_stop(struct mtk_ddp_comp *comp)
{
struct mtk_dpi *dpi = container_of(comp, struct mtk_dpi, ddp_comp);
- mtk_dpi_power_off(dpi, DPI_POWER_START);
+ mtk_dpi_power_off(dpi);
}
static const struct mtk_ddp_comp_funcs mtk_dpi_funcs = {
@@ -656,12 +647,46 @@ static const struct component_ops mtk_dpi_component_ops = {
.unbind = mtk_dpi_unbind,
};
+static unsigned int mt8173_calculate_factor(int clock)
+{
+ if (clock <= 27000)
+ return 3 << 4;
+ else if (clock <= 84000)
+ return 3 << 3;
+ else if (clock <= 167000)
+ return 3 << 2;
+ else
+ return 3 << 1;
+}
+
+static unsigned int mt2701_calculate_factor(int clock)
+{
+ if (clock <= 64000)
+ return 16;
+ else if (clock <= 128000)
+ return 8;
+ else if (clock <= 256000)
+ return 4;
+ else
+ return 2;
+}
+
+static const struct mtk_dpi_conf mt8173_conf = {
+ .cal_factor = mt8173_calculate_factor,
+ .reg_h_fre_con = 0xe0,
+};
+
+static const struct mtk_dpi_conf mt2701_conf = {
+ .cal_factor = mt2701_calculate_factor,
+ .reg_h_fre_con = 0xb0,
+ .edge_sel_en = true,
+};
+
static int mtk_dpi_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct mtk_dpi *dpi;
struct resource *mem;
- struct device_node *bridge_node;
int comp_id;
int ret;
@@ -670,6 +695,7 @@ static int mtk_dpi_probe(struct platform_device *pdev)
return -ENOMEM;
dpi->dev = dev;
+ dpi->conf = (struct mtk_dpi_conf *)of_device_get_match_data(dev);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
dpi->regs = devm_ioremap_resource(dev, mem);
@@ -706,16 +732,12 @@ static int mtk_dpi_probe(struct platform_device *pdev)
return -EINVAL;
}
- bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0);
- if (!bridge_node)
- return -ENODEV;
-
- dev_info(dev, "Found bridge node: %pOF\n", bridge_node);
+ ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0,
+ NULL, &dpi->bridge);
+ if (ret)
+ return ret;
- dpi->bridge = of_drm_find_bridge(bridge_node);
- of_node_put(bridge_node);
- if (!dpi->bridge)
- return -EPROBE_DEFER;
+ dev_info(dev, "Found bridge node: %pOF\n", dpi->bridge->of_node);
comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI);
if (comp_id < 0) {
@@ -749,8 +771,13 @@ static int mtk_dpi_remove(struct platform_device *pdev)
}
static const struct of_device_id mtk_dpi_of_ids[] = {
- { .compatible = "mediatek,mt8173-dpi", },
- {}
+ { .compatible = "mediatek,mt2701-dpi",
+ .data = &mt2701_conf,
+ },
+ { .compatible = "mediatek,mt8173-dpi",
+ .data = &mt8173_conf,
+ },
+ { },
};
struct platform_driver mtk_dpi_driver = {
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
index 4b6ad4751a31..d9db8c4cacd7 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
+++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h
@@ -223,6 +223,6 @@
#define ESAV_CODE2 (0xFFF << 0)
#define ESAV_CODE3_MSB BIT(16)
-#define DPI_H_FRE_CON 0xE0
+#define EDGE_SEL_EN BIT(5)
#define H_FRE_2N BIT(25)
#endif /* __MTK_DPI_REGS_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
index 546b3e3b300b..579ce28d801d 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c
@@ -39,6 +39,7 @@
#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030
#define DISP_REG_CONFIG_OUT_SEL 0x04c
#define DISP_REG_CONFIG_DSI_SEL 0x050
+#define DISP_REG_CONFIG_DPI_SEL 0x064
#define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n))
#define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n))
@@ -136,7 +137,10 @@
#define OVL_MOUT_EN_RDMA 0x1
#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8
+#define BLS_TO_DPI_RDMA1_TO_DSI 0x2
#define DSI_SEL_IN_BLS 0x0
+#define DPI_SEL_IN_BLS 0x0
+#define DSI_SEL_IN_RDMA 0x1
struct mtk_disp_mutex {
int id;
@@ -339,9 +343,17 @@ static void mtk_ddp_sout_sel(void __iomem *config_regs,
enum mtk_ddp_comp_id cur,
enum mtk_ddp_comp_id next)
{
- if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0)
+ if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) {
writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1,
config_regs + DISP_REG_CONFIG_OUT_SEL);
+ } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DPI0) {
+ writel_relaxed(BLS_TO_DPI_RDMA1_TO_DSI,
+ config_regs + DISP_REG_CONFIG_OUT_SEL);
+ writel_relaxed(DSI_SEL_IN_RDMA,
+ config_regs + DISP_REG_CONFIG_DSI_SEL);
+ writel_relaxed(DPI_SEL_IN_BLS,
+ config_regs + DISP_REG_CONFIG_DPI_SEL);
+ }
}
void mtk_ddp_add_comp_to_path(void __iomem *config_regs,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
index ff974d82a4a6..54ca794db3e9 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
@@ -294,7 +294,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node,
comp->irq = of_irq_get(node, 0);
comp->clk = of_clk_get(node, 0);
if (IS_ERR(comp->clk))
- comp->clk = NULL;
+ return PTR_ERR(comp->clk);
/* Only DMA capable components need the LARB property */
comp->larb_dev = NULL;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 47ec604289b7..6422e99952fe 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -424,6 +424,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DSI },
{ .compatible = "mediatek,mt8173-dsi",
.data = (void *)MTK_DSI },
+ { .compatible = "mediatek,mt2701-dpi",
+ .data = (void *)MTK_DPI },
{ .compatible = "mediatek,mt8173-dpi",
.data = (void *)MTK_DPI },
{ .compatible = "mediatek,mt2701-disp-mutex",
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 2d45d1dd9554..11e3644da79a 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -233,6 +233,7 @@ static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black)
static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
{
struct arm_smccc_res res;
+ struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(hdmi->phy);
/*
* MT8173 HDMI hardware has an output control bit to enable/disable HDMI
@@ -240,8 +241,13 @@ static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
* The ARM trusted firmware provides an API for the HDMI driver to set
* this control bit to enable HDMI output in supervisor mode.
*/
- arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x80000000,
- 0, 0, 0, 0, 0, &res);
+ if (hdmi_phy->conf && hdmi_phy->conf->tz_disabled)
+ regmap_update_bits(hdmi->sys_regmap,
+ hdmi->sys_offset + HDMI_SYS_CFG20,
+ 0x80008005, enable ? 0x80000005 : 0x8000);
+ else
+ arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904,
+ 0x80000000, 0, 0, 0, 0, 0, &res);
regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0);
@@ -1575,6 +1581,11 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data,
hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
break;
+ case HDMI_SPDIF:
+ hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
+ hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
+ hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF;
+ break;
default:
dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__,
daifmt->fmt);
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h
index 6371b3de1ff6..3e9fb8d19802 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.h
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h
@@ -13,11 +13,11 @@
*/
#ifndef _MTK_HDMI_CTRL_H
#define _MTK_HDMI_CTRL_H
+#include "mtk_hdmi_phy.h"
struct platform_driver;
extern struct platform_driver mtk_cec_driver;
extern struct platform_driver mtk_hdmi_ddc_driver;
-extern struct platform_driver mtk_hdmi_phy_driver;
#endif /* _MTK_HDMI_CTRL_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
new file mode 100644
index 000000000000..4ef9c57ffd44
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Jie Qiu <jie.qiu@mediatek.com>
+ */
+
+#include "mtk_hdmi_phy.h"
+
+static int mtk_hdmi_phy_power_on(struct phy *phy);
+static int mtk_hdmi_phy_power_off(struct phy *phy);
+
+static const struct phy_ops mtk_hdmi_phy_dev_ops = {
+ .power_on = mtk_hdmi_phy_power_on,
+ .power_off = mtk_hdmi_phy_power_off,
+ .owner = THIS_MODULE,
+};
+
+long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+ hdmi_phy->pll_rate = rate;
+ if (rate <= 74250000)
+ *parent_rate = rate;
+ else
+ *parent_rate = rate / 2;
+
+ return rate;
+}
+
+unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+ return hdmi_phy->pll_rate;
+}
+
+void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+ u32 bits)
+{
+ void __iomem *reg = hdmi_phy->regs + offset;
+ u32 tmp;
+
+ tmp = readl(reg);
+ tmp &= ~bits;
+ writel(tmp, reg);
+}
+
+void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+ u32 bits)
+{
+ void __iomem *reg = hdmi_phy->regs + offset;
+ u32 tmp;
+
+ tmp = readl(reg);
+ tmp |= bits;
+ writel(tmp, reg);
+}
+
+void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+ u32 val, u32 mask)
+{
+ void __iomem *reg = hdmi_phy->regs + offset;
+ u32 tmp;
+
+ tmp = readl(reg);
+ tmp = (tmp & ~mask) | (val & mask);
+ writel(tmp, reg);
+}
+
+inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_hdmi_phy, pll_hw);
+}
+
+static int mtk_hdmi_phy_power_on(struct phy *phy)
+{
+ struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
+ int ret;
+
+ ret = clk_prepare_enable(hdmi_phy->pll);
+ if (ret < 0)
+ return ret;
+
+ hdmi_phy->conf->hdmi_phy_enable_tmds(hdmi_phy);
+ return 0;
+}
+
+static int mtk_hdmi_phy_power_off(struct phy *phy)
+{
+ struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
+
+ hdmi_phy->conf->hdmi_phy_disable_tmds(hdmi_phy);
+ clk_disable_unprepare(hdmi_phy->pll);
+
+ return 0;
+}
+
+static const struct phy_ops *
+mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy)
+{
+ if (hdmi_phy && hdmi_phy->conf &&
+ hdmi_phy->conf->hdmi_phy_enable_tmds &&
+ hdmi_phy->conf->hdmi_phy_disable_tmds)
+ return &mtk_hdmi_phy_dev_ops;
+
+ dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n");
+ return NULL;
+}
+
+static void mtk_hdmi_phy_clk_get_ops(struct mtk_hdmi_phy *hdmi_phy,
+ const struct clk_ops **ops)
+{
+ if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_clk_ops)
+ *ops = hdmi_phy->conf->hdmi_phy_clk_ops;
+ else
+ dev_err(hdmi_phy->dev, "Failed to get clk ops of phy\n");
+}
+
+static int mtk_hdmi_phy_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mtk_hdmi_phy *hdmi_phy;
+ struct resource *mem;
+ struct clk *ref_clk;
+ const char *ref_clk_name;
+ struct clk_init_data clk_init = {
+ .num_parents = 1,
+ .parent_names = (const char * const *)&ref_clk_name,
+ .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
+ };
+
+ struct phy *phy;
+ struct phy_provider *phy_provider;
+ int ret;
+
+ hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
+ if (!hdmi_phy)
+ return -ENOMEM;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ hdmi_phy->regs = devm_ioremap_resource(dev, mem);
+ if (IS_ERR(hdmi_phy->regs)) {
+ ret = PTR_ERR(hdmi_phy->regs);
+ dev_err(dev, "Failed to get memory resource: %d\n", ret);
+ return ret;
+ }
+
+ ref_clk = devm_clk_get(dev, "pll_ref");
+ if (IS_ERR(ref_clk)) {
+ ret = PTR_ERR(ref_clk);
+ dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
+ ret);
+ return ret;
+ }
+ ref_clk_name = __clk_get_name(ref_clk);
+
+ ret = of_property_read_string(dev->of_node, "clock-output-names",
+ &clk_init.name);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
+ return ret;
+ }
+
+ hdmi_phy->dev = dev;
+ hdmi_phy->conf =
+ (struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev);
+ mtk_hdmi_phy_clk_get_ops(hdmi_phy, &clk_init.ops);
+ hdmi_phy->pll_hw.init = &clk_init;
+ hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
+ if (IS_ERR(hdmi_phy->pll)) {
+ ret = PTR_ERR(hdmi_phy->pll);
+ dev_err(dev, "Failed to register PLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
+ &hdmi_phy->ibias);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
+ &hdmi_phy->ibias_up);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
+ return ret;
+ }
+
+ dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
+ hdmi_phy->drv_imp_clk = 0x30;
+ hdmi_phy->drv_imp_d2 = 0x30;
+ hdmi_phy->drv_imp_d1 = 0x30;
+ hdmi_phy->drv_imp_d0 = 0x30;
+
+ phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy));
+ if (IS_ERR(phy)) {
+ dev_err(dev, "Failed to create HDMI PHY\n");
+ return PTR_ERR(phy);
+ }
+ phy_set_drvdata(phy, hdmi_phy);
+
+ phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+ if (IS_ERR(phy_provider)) {
+ dev_err(dev, "Failed to register HDMI PHY\n");
+ return PTR_ERR(phy_provider);
+ }
+
+ return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
+ hdmi_phy->pll);
+}
+
+static const struct of_device_id mtk_hdmi_phy_match[] = {
+ { .compatible = "mediatek,mt2701-hdmi-phy",
+ .data = &mtk_hdmi_phy_2701_conf,
+ },
+ { .compatible = "mediatek,mt8173-hdmi-phy",
+ .data = &mtk_hdmi_phy_8173_conf,
+ },
+ {},
+};
+
+struct platform_driver mtk_hdmi_phy_driver = {
+ .probe = mtk_hdmi_phy_probe,
+ .driver = {
+ .name = "mediatek-hdmi-phy",
+ .of_match_table = mtk_hdmi_phy_match,
+ },
+};
+
+MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h
new file mode 100644
index 000000000000..f39b1fc66612
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Chunhui Dai <chunhui.dai@mediatek.com>
+ */
+
+#ifndef _MTK_HDMI_PHY_H
+#define _MTK_HDMI_PHY_H
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+struct mtk_hdmi_phy;
+
+struct mtk_hdmi_phy_conf {
+ bool tz_disabled;
+ const struct clk_ops *hdmi_phy_clk_ops;
+ void (*hdmi_phy_enable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
+ void (*hdmi_phy_disable_tmds)(struct mtk_hdmi_phy *hdmi_phy);
+};
+
+struct mtk_hdmi_phy {
+ void __iomem *regs;
+ struct device *dev;
+ struct mtk_hdmi_phy_conf *conf;
+ struct clk *pll;
+ struct clk_hw pll_hw;
+ unsigned long pll_rate;
+ unsigned char drv_imp_clk;
+ unsigned char drv_imp_d2;
+ unsigned char drv_imp_d1;
+ unsigned char drv_imp_d0;
+ unsigned int ibias;
+ unsigned int ibias_up;
+};
+
+void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+ u32 bits);
+void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+ u32 bits);
+void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
+ u32 val, u32 mask);
+struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw);
+long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate);
+unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate);
+
+extern struct platform_driver mtk_hdmi_phy_driver;
+extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf;
+extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf;
+
+#endif /* _MTK_HDMI_PHY_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
new file mode 100644
index 000000000000..fcc42dc6ea7f
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c
@@ -0,0 +1,212 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ * Author: Chunhui Dai <chunhui.dai@mediatek.com>
+ */
+
+#include "mtk_hdmi_phy.h"
+
+#define HDMI_CON0 0x00
+#define RG_HDMITX_DRV_IBIAS 0
+#define RG_HDMITX_DRV_IBIAS_MASK (0x3f << 0)
+#define RG_HDMITX_EN_SER 12
+#define RG_HDMITX_EN_SER_MASK (0x0f << 12)
+#define RG_HDMITX_EN_SLDO 16
+#define RG_HDMITX_EN_SLDO_MASK (0x0f << 16)
+#define RG_HDMITX_EN_PRED 20
+#define RG_HDMITX_EN_PRED_MASK (0x0f << 20)
+#define RG_HDMITX_EN_IMP 24
+#define RG_HDMITX_EN_IMP_MASK (0x0f << 24)
+#define RG_HDMITX_EN_DRV 28
+#define RG_HDMITX_EN_DRV_MASK (0x0f << 28)
+
+#define HDMI_CON1 0x04
+#define RG_HDMITX_PRED_IBIAS 18
+#define RG_HDMITX_PRED_IBIAS_MASK (0x0f << 18)
+#define RG_HDMITX_PRED_IMP (0x01 << 22)
+#define RG_HDMITX_DRV_IMP 26
+#define RG_HDMITX_DRV_IMP_MASK (0x3f << 26)
+
+#define HDMI_CON2 0x08
+#define RG_HDMITX_EN_TX_CKLDO (0x01 << 0)
+#define RG_HDMITX_EN_TX_POSDIV (0x01 << 1)
+#define RG_HDMITX_TX_POSDIV 3
+#define RG_HDMITX_TX_POSDIV_MASK (0x03 << 3)
+#define RG_HDMITX_EN_MBIAS (0x01 << 6)
+#define RG_HDMITX_MBIAS_LPF_EN (0x01 << 7)
+
+#define HDMI_CON4 0x10
+#define RG_HDMITX_RESERVE_MASK (0xffffffff << 0)
+
+#define HDMI_CON6 0x18
+#define RG_HTPLL_BR 0
+#define RG_HTPLL_BR_MASK (0x03 << 0)
+#define RG_HTPLL_BC 2
+#define RG_HTPLL_BC_MASK (0x03 << 2)
+#define RG_HTPLL_BP 4
+#define RG_HTPLL_BP_MASK (0x0f << 4)
+#define RG_HTPLL_IR 8
+#define RG_HTPLL_IR_MASK (0x0f << 8)
+#define RG_HTPLL_IC 12
+#define RG_HTPLL_IC_MASK (0x0f << 12)
+#define RG_HTPLL_POSDIV 16
+#define RG_HTPLL_POSDIV_MASK (0x03 << 16)
+#define RG_HTPLL_PREDIV 18
+#define RG_HTPLL_PREDIV_MASK (0x03 << 18)
+#define RG_HTPLL_FBKSEL 20
+#define RG_HTPLL_FBKSEL_MASK (0x03 << 20)
+#define RG_HTPLL_RLH_EN (0x01 << 22)
+#define RG_HTPLL_FBKDIV 24
+#define RG_HTPLL_FBKDIV_MASK (0x7f << 24)
+#define RG_HTPLL_EN (0x01 << 31)
+
+#define HDMI_CON7 0x1c
+#define RG_HTPLL_AUTOK_EN (0x01 << 23)
+#define RG_HTPLL_DIVEN 28
+#define RG_HTPLL_DIVEN_MASK (0x07 << 28)
+
+static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
+{
+ struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+ usleep_range(80, 100);
+ return 0;
+}
+
+static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
+{
+ struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+ usleep_range(80, 100);
+}
+
+static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
+ u32 pos_div;
+
+ if (rate <= 64000000)
+ pos_div = 3;
+ else if (rate <= 12800000)
+ pos_div = 1;
+ else
+ pos_div = 1;
+
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_PREDIV_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC),
+ RG_HTPLL_IC_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR),
+ RG_HTPLL_IR_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV),
+ RG_HDMITX_TX_POSDIV_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL),
+ RG_HTPLL_FBKSEL_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV),
+ RG_HTPLL_FBKDIV_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN),
+ RG_HTPLL_DIVEN_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP),
+ RG_HTPLL_BP_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC),
+ RG_HTPLL_BC_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR),
+ RG_HTPLL_BR_MASK);
+
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PRED_IMP);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS),
+ RG_HDMITX_PRED_IBIAS_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_IMP_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP),
+ RG_HDMITX_DRV_IMP_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK);
+ mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS),
+ RG_HDMITX_DRV_IBIAS_MASK);
+ return 0;
+}
+
+static const struct clk_ops mtk_hdmi_phy_pll_ops = {
+ .prepare = mtk_hdmi_pll_prepare,
+ .unprepare = mtk_hdmi_pll_unprepare,
+ .set_rate = mtk_hdmi_pll_set_rate,
+ .round_rate = mtk_hdmi_pll_round_rate,
+ .recalc_rate = mtk_hdmi_pll_recalc_rate,
+};
+
+static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
+{
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+ mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+ usleep_range(80, 100);
+}
+
+static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
+{
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_DRV_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_PRED_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SER_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_EN_SLDO_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_EN);
+ usleep_range(80, 100);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_POSDIV_MASK);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON6, RG_HTPLL_RLH_EN);
+ mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN);
+ usleep_range(80, 100);
+}
+
+struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = {
+ .tz_disabled = true,
+ .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
+ .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
+ .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
+};
+
+MODULE_AUTHOR("Chunhui Dai <chunhui.dai@mediatek.com>");
+MODULE_DESCRIPTION("MediaTek HDMI PHY Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
index 51cb9cfb6646..ed5916b27658 100644
--- a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
+++ b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
@@ -12,15 +12,7 @@
* GNU General Public License for more details.
*/
-#include <linux/clk.h>
-#include <linux/clk-provider.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/mfd/syscon.h>
-#include <linux/module.h>
-#include <linux/phy/phy.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
+#include "mtk_hdmi_phy.h"
#define HDMI_CON0 0x00
#define RG_HDMITX_PLL_EN BIT(31)
@@ -123,20 +115,6 @@
#define RGS_HDMITX_5T1_EDG (0xf << 4)
#define RGS_HDMITX_PLUG_TST BIT(0)
-struct mtk_hdmi_phy {
- void __iomem *regs;
- struct device *dev;
- struct clk *pll;
- struct clk_hw pll_hw;
- unsigned long pll_rate;
- u8 drv_imp_clk;
- u8 drv_imp_d2;
- u8 drv_imp_d1;
- u8 drv_imp_d0;
- u32 ibias;
- u32 ibias_up;
-};
-
static const u8 PREDIV[3][4] = {
{0x0, 0x0, 0x0, 0x0}, /* 27Mhz */
{0x1, 0x1, 0x1, 0x1}, /* 74Mhz */
@@ -185,44 +163,6 @@ static const u8 HTPLLBR[3][4] = {
{0x1, 0x2, 0x2, 0x1} /* 148Mhz */
};
-static void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
- u32 bits)
-{
- void __iomem *reg = hdmi_phy->regs + offset;
- u32 tmp;
-
- tmp = readl(reg);
- tmp &= ~bits;
- writel(tmp, reg);
-}
-
-static void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
- u32 bits)
-{
- void __iomem *reg = hdmi_phy->regs + offset;
- u32 tmp;
-
- tmp = readl(reg);
- tmp |= bits;
- writel(tmp, reg);
-}
-
-static void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
- u32 val, u32 mask)
-{
- void __iomem *reg = hdmi_phy->regs + offset;
- u32 tmp;
-
- tmp = readl(reg);
- tmp = (tmp & ~mask) | (val & mask);
- writel(tmp, reg);
-}
-
-static inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
-{
- return container_of(hw, struct mtk_hdmi_phy, pll_hw);
-}
-
static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
{
struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
@@ -345,29 +285,7 @@ static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
-{
- struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
- hdmi_phy->pll_rate = rate;
- if (rate <= 74250000)
- *parent_rate = rate;
- else
- *parent_rate = rate / 2;
-
- return rate;
-}
-
-static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
-{
- struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
-
- return hdmi_phy->pll_rate;
-}
-
-static const struct clk_ops mtk_hdmi_pll_ops = {
+static const struct clk_ops mtk_hdmi_phy_pll_ops = {
.prepare = mtk_hdmi_pll_prepare,
.unprepare = mtk_hdmi_pll_unprepare,
.set_rate = mtk_hdmi_pll_set_rate,
@@ -390,142 +308,10 @@ static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
RG_HDMITX_SER_EN);
}
-static int mtk_hdmi_phy_power_on(struct phy *phy)
-{
- struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
- int ret;
-
- ret = clk_prepare_enable(hdmi_phy->pll);
- if (ret < 0)
- return ret;
-
- mtk_hdmi_phy_enable_tmds(hdmi_phy);
-
- return 0;
-}
-
-static int mtk_hdmi_phy_power_off(struct phy *phy)
-{
- struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
-
- mtk_hdmi_phy_disable_tmds(hdmi_phy);
- clk_disable_unprepare(hdmi_phy->pll);
-
- return 0;
-}
-
-static const struct phy_ops mtk_hdmi_phy_ops = {
- .power_on = mtk_hdmi_phy_power_on,
- .power_off = mtk_hdmi_phy_power_off,
- .owner = THIS_MODULE,
-};
-
-static int mtk_hdmi_phy_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct mtk_hdmi_phy *hdmi_phy;
- struct resource *mem;
- struct clk *ref_clk;
- const char *ref_clk_name;
- struct clk_init_data clk_init = {
- .ops = &mtk_hdmi_pll_ops,
- .num_parents = 1,
- .parent_names = (const char * const *)&ref_clk_name,
- .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
- };
- struct phy *phy;
- struct phy_provider *phy_provider;
- int ret;
-
- hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
- if (!hdmi_phy)
- return -ENOMEM;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- hdmi_phy->regs = devm_ioremap_resource(dev, mem);
- if (IS_ERR(hdmi_phy->regs)) {
- ret = PTR_ERR(hdmi_phy->regs);
- dev_err(dev, "Failed to get memory resource: %d\n", ret);
- return ret;
- }
-
- ref_clk = devm_clk_get(dev, "pll_ref");
- if (IS_ERR(ref_clk)) {
- ret = PTR_ERR(ref_clk);
- dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
- ret);
- return ret;
- }
- ref_clk_name = __clk_get_name(ref_clk);
-
- ret = of_property_read_string(dev->of_node, "clock-output-names",
- &clk_init.name);
- if (ret < 0) {
- dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
- return ret;
- }
-
- hdmi_phy->pll_hw.init = &clk_init;
- hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
- if (IS_ERR(hdmi_phy->pll)) {
- ret = PTR_ERR(hdmi_phy->pll);
- dev_err(dev, "Failed to register PLL: %d\n", ret);
- return ret;
- }
-
- ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
- &hdmi_phy->ibias);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
- return ret;
- }
-
- ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
- &hdmi_phy->ibias_up);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
- return ret;
- }
-
- dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
- hdmi_phy->drv_imp_clk = 0x30;
- hdmi_phy->drv_imp_d2 = 0x30;
- hdmi_phy->drv_imp_d1 = 0x30;
- hdmi_phy->drv_imp_d0 = 0x30;
-
- phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops);
- if (IS_ERR(phy)) {
- dev_err(dev, "Failed to create HDMI PHY\n");
- return PTR_ERR(phy);
- }
- phy_set_drvdata(phy, hdmi_phy);
-
- phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
- if (IS_ERR(phy_provider))
- return PTR_ERR(phy_provider);
-
- hdmi_phy->dev = dev;
- return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
- hdmi_phy->pll);
-}
-
-static int mtk_hdmi_phy_remove(struct platform_device *pdev)
-{
- return 0;
-}
-
-static const struct of_device_id mtk_hdmi_phy_match[] = {
- { .compatible = "mediatek,mt8173-hdmi-phy", },
- {},
-};
-
-struct platform_driver mtk_hdmi_phy_driver = {
- .probe = mtk_hdmi_phy_probe,
- .remove = mtk_hdmi_phy_remove,
- .driver = {
- .name = "mediatek-hdmi-phy",
- .of_match_table = mtk_hdmi_phy_match,
- },
+struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = {
+ .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops,
+ .hdmi_phy_enable_tmds = mtk_hdmi_phy_enable_tmds,
+ .hdmi_phy_disable_tmds = mtk_hdmi_phy_disable_tmds,
};
MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 261fa79d456d..19ab521d4c3a 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -58,7 +58,6 @@ msm-y := \
disp/dpu1/dpu_formats.o \
disp/dpu1/dpu_hw_blk.o \
disp/dpu1/dpu_hw_catalog.o \
- disp/dpu1/dpu_hw_cdm.o \
disp/dpu1/dpu_hw_ctl.o \
disp/dpu1/dpu_hw_interrupts.o \
disp/dpu1/dpu_hw_intf.o \
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index 4bff0a740c7d..12b0ba270b5e 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index 645a19aef399..a89f7bb8b5cc 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index 19565e87aa7b..858690f52854 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
diff --git a/drivers/gpu/drm/msm/adreno/a5xx.xml.h b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
index 182d37ff3794..b4944cc0e62f 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a5xx.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
index 059ec7d394d0..d2127b1c4ece 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_debugfs.c
@@ -132,14 +132,14 @@ reset_set(void *data, u64 val)
if (a5xx_gpu->pm4_bo) {
if (a5xx_gpu->pm4_iova)
msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace);
- drm_gem_object_unreference(a5xx_gpu->pm4_bo);
+ drm_gem_object_put(a5xx_gpu->pm4_bo);
a5xx_gpu->pm4_bo = NULL;
}
if (a5xx_gpu->pfp_bo) {
if (a5xx_gpu->pfp_iova)
msm_gem_put_iova(a5xx_gpu->pfp_bo, gpu->aspace);
- drm_gem_object_unreference(a5xx_gpu->pfp_bo);
+ drm_gem_object_put(a5xx_gpu->pfp_bo);
a5xx_gpu->pfp_bo = NULL;
}
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index ab1d9308c311..48b5304f460c 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -1234,7 +1234,7 @@ static void a5xx_crashdumper_free(struct msm_gpu *gpu,
msm_gem_put_iova(dumper->bo, gpu->aspace);
msm_gem_put_vaddr(dumper->bo);
- drm_gem_object_unreference(dumper->bo);
+ drm_gem_object_put(dumper->bo);
}
static int a5xx_crashdumper_run(struct msm_gpu *gpu,
@@ -1436,12 +1436,22 @@ static struct msm_ringbuffer *a5xx_active_ring(struct msm_gpu *gpu)
return a5xx_gpu->cur_ring;
}
-static int a5xx_gpu_busy(struct msm_gpu *gpu, uint64_t *value)
+static unsigned long a5xx_gpu_busy(struct msm_gpu *gpu)
{
- *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
- REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
+ u64 busy_cycles, busy_time;
- return 0;
+ busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
+ REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
+
+ busy_time = busy_cycles - gpu->devfreq.busy_cycles;
+ do_div(busy_time, clk_get_rate(gpu->core_clk) / 1000000);
+
+ gpu->devfreq.busy_cycles = busy_cycles;
+
+ if (WARN_ON(busy_time > ~0LU))
+ return ~0LU;
+
+ return (unsigned long)busy_time;
}
static const struct adreno_gpu_funcs funcs = {
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c
index e9c0e56dbec0..7a41e1c147e4 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_power.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c
@@ -323,7 +323,7 @@ err:
if (a5xx_gpu->gpmu_iova)
msm_gem_put_iova(a5xx_gpu->gpmu_bo, gpu->aspace);
if (a5xx_gpu->gpmu_bo)
- drm_gem_object_unreference(a5xx_gpu->gpmu_bo);
+ drm_gem_object_put(a5xx_gpu->gpmu_bo);
a5xx_gpu->gpmu_bo = NULL;
a5xx_gpu->gpmu_iova = 0;
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
index 970c7963ae29..4c357ead1be6 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
@@ -208,6 +208,13 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)
struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
int i;
+ /* Always come up on rb 0 */
+ a5xx_gpu->cur_ring = gpu->rb[0];
+
+ /* No preemption if we only have one ring */
+ if (gpu->nr_rings == 1)
+ return;
+
for (i = 0; i < gpu->nr_rings; i++) {
a5xx_gpu->preempt[i]->wptr = 0;
a5xx_gpu->preempt[i]->rptr = 0;
@@ -220,9 +227,6 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)
/* Reset the preemption state */
set_preempt_state(a5xx_gpu, PREEMPT_NONE);
-
- /* Always come up on rb 0 */
- a5xx_gpu->cur_ring = gpu->rb[0];
}
static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu,
@@ -272,7 +276,7 @@ void a5xx_preempt_fini(struct msm_gpu *gpu)
if (a5xx_gpu->preempt_iova[i])
msm_gem_put_iova(a5xx_gpu->preempt_bo[i], gpu->aspace);
- drm_gem_object_unreference(a5xx_gpu->preempt_bo[i]);
+ drm_gem_object_put(a5xx_gpu->preempt_bo[i]);
a5xx_gpu->preempt_bo[i] = NULL;
}
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx.xml.h b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
index 87eab51f7000..a6f7c40454a6 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
@@ -268,8 +268,687 @@ enum a6xx_depth_format {
DEPTH6_32 = 4,
};
+enum a6xx_shader_id {
+ A6XX_TP0_TMO_DATA = 9,
+ A6XX_TP0_SMO_DATA = 10,
+ A6XX_TP0_MIPMAP_BASE_DATA = 11,
+ A6XX_TP1_TMO_DATA = 25,
+ A6XX_TP1_SMO_DATA = 26,
+ A6XX_TP1_MIPMAP_BASE_DATA = 27,
+ A6XX_SP_INST_DATA = 41,
+ A6XX_SP_LB_0_DATA = 42,
+ A6XX_SP_LB_1_DATA = 43,
+ A6XX_SP_LB_2_DATA = 44,
+ A6XX_SP_LB_3_DATA = 45,
+ A6XX_SP_LB_4_DATA = 46,
+ A6XX_SP_LB_5_DATA = 47,
+ A6XX_SP_CB_BINDLESS_DATA = 48,
+ A6XX_SP_CB_LEGACY_DATA = 49,
+ A6XX_SP_UAV_DATA = 50,
+ A6XX_SP_INST_TAG = 51,
+ A6XX_SP_CB_BINDLESS_TAG = 52,
+ A6XX_SP_TMO_UMO_TAG = 53,
+ A6XX_SP_SMO_TAG = 54,
+ A6XX_SP_STATE_DATA = 55,
+ A6XX_HLSQ_CHUNK_CVS_RAM = 73,
+ A6XX_HLSQ_CHUNK_CPS_RAM = 74,
+ A6XX_HLSQ_CHUNK_CVS_RAM_TAG = 75,
+ A6XX_HLSQ_CHUNK_CPS_RAM_TAG = 76,
+ A6XX_HLSQ_ICB_CVS_CB_BASE_TAG = 77,
+ A6XX_HLSQ_ICB_CPS_CB_BASE_TAG = 78,
+ A6XX_HLSQ_CVS_MISC_RAM = 80,
+ A6XX_HLSQ_CPS_MISC_RAM = 81,
+ A6XX_HLSQ_INST_RAM = 82,
+ A6XX_HLSQ_GFX_CVS_CONST_RAM = 83,
+ A6XX_HLSQ_GFX_CPS_CONST_RAM = 84,
+ A6XX_HLSQ_CVS_MISC_RAM_TAG = 85,
+ A6XX_HLSQ_CPS_MISC_RAM_TAG = 86,
+ A6XX_HLSQ_INST_RAM_TAG = 87,
+ A6XX_HLSQ_GFX_CVS_CONST_RAM_TAG = 88,
+ A6XX_HLSQ_GFX_CPS_CONST_RAM_TAG = 89,
+ A6XX_HLSQ_PWR_REST_RAM = 90,
+ A6XX_HLSQ_PWR_REST_TAG = 91,
+ A6XX_HLSQ_DATAPATH_META = 96,
+ A6XX_HLSQ_FRONTEND_META = 97,
+ A6XX_HLSQ_INDIRECT_META = 98,
+ A6XX_HLSQ_BACKEND_META = 99,
+};
+
+enum a6xx_debugbus_id {
+ A6XX_DBGBUS_CP = 1,
+ A6XX_DBGBUS_RBBM = 2,
+ A6XX_DBGBUS_VBIF = 3,
+ A6XX_DBGBUS_HLSQ = 4,
+ A6XX_DBGBUS_UCHE = 5,
+ A6XX_DBGBUS_DPM = 6,
+ A6XX_DBGBUS_TESS = 7,
+ A6XX_DBGBUS_PC = 8,
+ A6XX_DBGBUS_VFDP = 9,
+ A6XX_DBGBUS_VPC = 10,
+ A6XX_DBGBUS_TSE = 11,
+ A6XX_DBGBUS_RAS = 12,
+ A6XX_DBGBUS_VSC = 13,
+ A6XX_DBGBUS_COM = 14,
+ A6XX_DBGBUS_LRZ = 16,
+ A6XX_DBGBUS_A2D = 17,
+ A6XX_DBGBUS_CCUFCHE = 18,
+ A6XX_DBGBUS_GMU_CX = 19,
+ A6XX_DBGBUS_RBP = 20,
+ A6XX_DBGBUS_DCS = 21,
+ A6XX_DBGBUS_DBGC = 22,
+ A6XX_DBGBUS_CX = 23,
+ A6XX_DBGBUS_GMU_GX = 24,
+ A6XX_DBGBUS_TPFCHE = 25,
+ A6XX_DBGBUS_GBIF_GX = 26,
+ A6XX_DBGBUS_GPC = 29,
+ A6XX_DBGBUS_LARC = 30,
+ A6XX_DBGBUS_HLSQ_SPTP = 31,
+ A6XX_DBGBUS_RB_0 = 32,
+ A6XX_DBGBUS_RB_1 = 33,
+ A6XX_DBGBUS_UCHE_WRAPPER = 36,
+ A6XX_DBGBUS_CCU_0 = 40,
+ A6XX_DBGBUS_CCU_1 = 41,
+ A6XX_DBGBUS_VFD_0 = 56,
+ A6XX_DBGBUS_VFD_1 = 57,
+ A6XX_DBGBUS_VFD_2 = 58,
+ A6XX_DBGBUS_VFD_3 = 59,
+ A6XX_DBGBUS_SP_0 = 64,
+ A6XX_DBGBUS_SP_1 = 65,
+ A6XX_DBGBUS_TPL1_0 = 72,
+ A6XX_DBGBUS_TPL1_1 = 73,
+ A6XX_DBGBUS_TPL1_2 = 74,
+ A6XX_DBGBUS_TPL1_3 = 75,
+};
+
enum a6xx_cp_perfcounter_select {
PERF_CP_ALWAYS_COUNT = 0,
+ PERF_CP_BUSY_GFX_CORE_IDLE = 1,
+ PERF_CP_BUSY_CYCLES = 2,
+ PERF_CP_NUM_PREEMPTIONS = 3,
+ PERF_CP_PREEMPTION_REACTION_DELAY = 4,
+ PERF_CP_PREEMPTION_SWITCH_OUT_TIME = 5,
+ PERF_CP_PREEMPTION_SWITCH_IN_TIME = 6,
+ PERF_CP_DEAD_DRAWS_IN_BIN_RENDER = 7,
+ PERF_CP_PREDICATED_DRAWS_KILLED = 8,
+ PERF_CP_MODE_SWITCH = 9,
+ PERF_CP_ZPASS_DONE = 10,
+ PERF_CP_CONTEXT_DONE = 11,
+ PERF_CP_CACHE_FLUSH = 12,
+ PERF_CP_LONG_PREEMPTIONS = 13,
+ PERF_CP_SQE_I_CACHE_STARVE = 14,
+ PERF_CP_SQE_IDLE = 15,
+ PERF_CP_SQE_PM4_STARVE_RB_IB = 16,
+ PERF_CP_SQE_PM4_STARVE_SDS = 17,
+ PERF_CP_SQE_MRB_STARVE = 18,
+ PERF_CP_SQE_RRB_STARVE = 19,
+ PERF_CP_SQE_VSD_STARVE = 20,
+ PERF_CP_VSD_DECODE_STARVE = 21,
+ PERF_CP_SQE_PIPE_OUT_STALL = 22,
+ PERF_CP_SQE_SYNC_STALL = 23,
+ PERF_CP_SQE_PM4_WFI_STALL = 24,
+ PERF_CP_SQE_SYS_WFI_STALL = 25,
+ PERF_CP_SQE_T4_EXEC = 26,
+ PERF_CP_SQE_LOAD_STATE_EXEC = 27,
+ PERF_CP_SQE_SAVE_SDS_STATE = 28,
+ PERF_CP_SQE_DRAW_EXEC = 29,
+ PERF_CP_SQE_CTXT_REG_BUNCH_EXEC = 30,
+ PERF_CP_SQE_EXEC_PROFILED = 31,
+ PERF_CP_MEMORY_POOL_EMPTY = 32,
+ PERF_CP_MEMORY_POOL_SYNC_STALL = 33,
+ PERF_CP_MEMORY_POOL_ABOVE_THRESH = 34,
+ PERF_CP_AHB_WR_STALL_PRE_DRAWS = 35,
+ PERF_CP_AHB_STALL_SQE_GMU = 36,
+ PERF_CP_AHB_STALL_SQE_WR_OTHER = 37,
+ PERF_CP_AHB_STALL_SQE_RD_OTHER = 38,
+ PERF_CP_CLUSTER0_EMPTY = 39,
+ PERF_CP_CLUSTER1_EMPTY = 40,
+ PERF_CP_CLUSTER2_EMPTY = 41,
+ PERF_CP_CLUSTER3_EMPTY = 42,
+ PERF_CP_CLUSTER4_EMPTY = 43,
+ PERF_CP_CLUSTER5_EMPTY = 44,
+ PERF_CP_PM4_DATA = 45,
+ PERF_CP_PM4_HEADERS = 46,
+ PERF_CP_VBIF_READ_BEATS = 47,
+ PERF_CP_VBIF_WRITE_BEATS = 48,
+ PERF_CP_SQE_INSTR_COUNTER = 49,
+};
+
+enum a6xx_rbbm_perfcounter_select {
+ PERF_RBBM_ALWAYS_COUNT = 0,
+ PERF_RBBM_ALWAYS_ON = 1,
+ PERF_RBBM_TSE_BUSY = 2,
+ PERF_RBBM_RAS_BUSY = 3,
+ PERF_RBBM_PC_DCALL_BUSY = 4,
+ PERF_RBBM_PC_VSD_BUSY = 5,
+ PERF_RBBM_STATUS_MASKED = 6,
+ PERF_RBBM_COM_BUSY = 7,
+ PERF_RBBM_DCOM_BUSY = 8,
+ PERF_RBBM_VBIF_BUSY = 9,
+ PERF_RBBM_VSC_BUSY = 10,
+ PERF_RBBM_TESS_BUSY = 11,
+ PERF_RBBM_UCHE_BUSY = 12,
+ PERF_RBBM_HLSQ_BUSY = 13,
+};
+
+enum a6xx_pc_perfcounter_select {
+ PERF_PC_BUSY_CYCLES = 0,
+ PERF_PC_WORKING_CYCLES = 1,
+ PERF_PC_STALL_CYCLES_VFD = 2,
+ PERF_PC_STALL_CYCLES_TSE = 3,
+ PERF_PC_STALL_CYCLES_VPC = 4,
+ PERF_PC_STALL_CYCLES_UCHE = 5,
+ PERF_PC_STALL_CYCLES_TESS = 6,
+ PERF_PC_STALL_CYCLES_TSE_ONLY = 7,
+ PERF_PC_STALL_CYCLES_VPC_ONLY = 8,
+ PERF_PC_PASS1_TF_STALL_CYCLES = 9,
+ PERF_PC_STARVE_CYCLES_FOR_INDEX = 10,
+ PERF_PC_STARVE_CYCLES_FOR_TESS_FACTOR = 11,
+ PERF_PC_STARVE_CYCLES_FOR_VIZ_STREAM = 12,
+ PERF_PC_STARVE_CYCLES_FOR_POSITION = 13,
+ PERF_PC_STARVE_CYCLES_DI = 14,
+ PERF_PC_VIS_STREAMS_LOADED = 15,
+ PERF_PC_INSTANCES = 16,
+ PERF_PC_VPC_PRIMITIVES = 17,
+ PERF_PC_DEAD_PRIM = 18,
+ PERF_PC_LIVE_PRIM = 19,
+ PERF_PC_VERTEX_HITS = 20,
+ PERF_PC_IA_VERTICES = 21,
+ PERF_PC_IA_PRIMITIVES = 22,
+ PERF_PC_GS_PRIMITIVES = 23,
+ PERF_PC_HS_INVOCATIONS = 24,
+ PERF_PC_DS_INVOCATIONS = 25,
+ PERF_PC_VS_INVOCATIONS = 26,
+ PERF_PC_GS_INVOCATIONS = 27,
+ PERF_PC_DS_PRIMITIVES = 28,
+ PERF_PC_VPC_POS_DATA_TRANSACTION = 29,
+ PERF_PC_3D_DRAWCALLS = 30,
+ PERF_PC_2D_DRAWCALLS = 31,
+ PERF_PC_NON_DRAWCALL_GLOBAL_EVENTS = 32,
+ PERF_TESS_BUSY_CYCLES = 33,
+ PERF_TESS_WORKING_CYCLES = 34,
+ PERF_TESS_STALL_CYCLES_PC = 35,
+ PERF_TESS_STARVE_CYCLES_PC = 36,
+ PERF_PC_TSE_TRANSACTION = 37,
+ PERF_PC_TSE_VERTEX = 38,
+ PERF_PC_TESS_PC_UV_TRANS = 39,
+ PERF_PC_TESS_PC_UV_PATCHES = 40,
+ PERF_PC_TESS_FACTOR_TRANS = 41,
+};
+
+enum a6xx_vfd_perfcounter_select {
+ PERF_VFD_BUSY_CYCLES = 0,
+ PERF_VFD_STALL_CYCLES_UCHE = 1,
+ PERF_VFD_STALL_CYCLES_VPC_ALLOC = 2,
+ PERF_VFD_STALL_CYCLES_SP_INFO = 3,
+ PERF_VFD_STALL_CYCLES_SP_ATTR = 4,
+ PERF_VFD_STARVE_CYCLES_UCHE = 5,
+ PERF_VFD_RBUFFER_FULL = 6,
+ PERF_VFD_ATTR_INFO_FIFO_FULL = 7,
+ PERF_VFD_DECODED_ATTRIBUTE_BYTES = 8,
+ PERF_VFD_NUM_ATTRIBUTES = 9,
+ PERF_VFD_UPPER_SHADER_FIBERS = 10,
+ PERF_VFD_LOWER_SHADER_FIBERS = 11,
+ PERF_VFD_MODE_0_FIBERS = 12,
+ PERF_VFD_MODE_1_FIBERS = 13,
+ PERF_VFD_MODE_2_FIBERS = 14,
+ PERF_VFD_MODE_3_FIBERS = 15,
+ PERF_VFD_MODE_4_FIBERS = 16,
+ PERF_VFD_TOTAL_VERTICES = 17,
+ PERF_VFDP_STALL_CYCLES_VFD = 18,
+ PERF_VFDP_STALL_CYCLES_VFD_INDEX = 19,
+ PERF_VFDP_STALL_CYCLES_VFD_PROG = 20,
+ PERF_VFDP_STARVE_CYCLES_PC = 21,
+ PERF_VFDP_VS_STAGE_WAVES = 22,
+};
+
+enum a6xx_hslq_perfcounter_select {
+ PERF_HLSQ_BUSY_CYCLES = 0,
+ PERF_HLSQ_STALL_CYCLES_UCHE = 1,
+ PERF_HLSQ_STALL_CYCLES_SP_STATE = 2,
+ PERF_HLSQ_STALL_CYCLES_SP_FS_STAGE = 3,
+ PERF_HLSQ_UCHE_LATENCY_CYCLES = 4,
+ PERF_HLSQ_UCHE_LATENCY_COUNT = 5,
+ PERF_HLSQ_FS_STAGE_1X_WAVES = 6,
+ PERF_HLSQ_FS_STAGE_2X_WAVES = 7,
+ PERF_HLSQ_QUADS = 8,
+ PERF_HLSQ_CS_INVOCATIONS = 9,
+ PERF_HLSQ_COMPUTE_DRAWCALLS = 10,
+ PERF_HLSQ_FS_DATA_WAIT_PROGRAMMING = 11,
+ PERF_HLSQ_DUAL_FS_PROG_ACTIVE = 12,
+ PERF_HLSQ_DUAL_VS_PROG_ACTIVE = 13,
+ PERF_HLSQ_FS_BATCH_COUNT_ZERO = 14,
+ PERF_HLSQ_VS_BATCH_COUNT_ZERO = 15,
+ PERF_HLSQ_WAVE_PENDING_NO_QUAD = 16,
+ PERF_HLSQ_WAVE_PENDING_NO_PRIM_BASE = 17,
+ PERF_HLSQ_STALL_CYCLES_VPC = 18,
+ PERF_HLSQ_PIXELS = 19,
+ PERF_HLSQ_DRAW_MODE_SWITCH_VSFS_SYNC = 20,
+};
+
+enum a6xx_vpc_perfcounter_select {
+ PERF_VPC_BUSY_CYCLES = 0,
+ PERF_VPC_WORKING_CYCLES = 1,
+ PERF_VPC_STALL_CYCLES_UCHE = 2,
+ PERF_VPC_STALL_CYCLES_VFD_WACK = 3,
+ PERF_VPC_STALL_CYCLES_HLSQ_PRIM_ALLOC = 4,
+ PERF_VPC_STALL_CYCLES_PC = 5,
+ PERF_VPC_STALL_CYCLES_SP_LM = 6,
+ PERF_VPC_STARVE_CYCLES_SP = 7,
+ PERF_VPC_STARVE_CYCLES_LRZ = 8,
+ PERF_VPC_PC_PRIMITIVES = 9,
+ PERF_VPC_SP_COMPONENTS = 10,
+ PERF_VPC_STALL_CYCLES_VPCRAM_POS = 11,
+ PERF_VPC_LRZ_ASSIGN_PRIMITIVES = 12,
+ PERF_VPC_RB_VISIBLE_PRIMITIVES = 13,
+ PERF_VPC_LM_TRANSACTION = 14,
+ PERF_VPC_STREAMOUT_TRANSACTION = 15,
+ PERF_VPC_VS_BUSY_CYCLES = 16,
+ PERF_VPC_PS_BUSY_CYCLES = 17,
+ PERF_VPC_VS_WORKING_CYCLES = 18,
+ PERF_VPC_PS_WORKING_CYCLES = 19,
+ PERF_VPC_STARVE_CYCLES_RB = 20,
+ PERF_VPC_NUM_VPCRAM_READ_POS = 21,
+ PERF_VPC_WIT_FULL_CYCLES = 22,
+ PERF_VPC_VPCRAM_FULL_CYCLES = 23,
+ PERF_VPC_LM_FULL_WAIT_FOR_INTP_END = 24,
+ PERF_VPC_NUM_VPCRAM_WRITE = 25,
+ PERF_VPC_NUM_VPCRAM_READ_SO = 26,
+ PERF_VPC_NUM_ATTR_REQ_LM = 27,
+};
+
+enum a6xx_tse_perfcounter_select {
+ PERF_TSE_BUSY_CYCLES = 0,
+ PERF_TSE_CLIPPING_CYCLES = 1,
+ PERF_TSE_STALL_CYCLES_RAS = 2,
+ PERF_TSE_STALL_CYCLES_LRZ_BARYPLANE = 3,
+ PERF_TSE_STALL_CYCLES_LRZ_ZPLANE = 4,
+ PERF_TSE_STARVE_CYCLES_PC = 5,
+ PERF_TSE_INPUT_PRIM = 6,
+ PERF_TSE_INPUT_NULL_PRIM = 7,
+ PERF_TSE_TRIVAL_REJ_PRIM = 8,
+ PERF_TSE_CLIPPED_PRIM = 9,
+ PERF_TSE_ZERO_AREA_PRIM = 10,
+ PERF_TSE_FACENESS_CULLED_PRIM = 11,
+ PERF_TSE_ZERO_PIXEL_PRIM = 12,
+ PERF_TSE_OUTPUT_NULL_PRIM = 13,
+ PERF_TSE_OUTPUT_VISIBLE_PRIM = 14,
+ PERF_TSE_CINVOCATION = 15,
+ PERF_TSE_CPRIMITIVES = 16,
+ PERF_TSE_2D_INPUT_PRIM = 17,
+ PERF_TSE_2D_ALIVE_CYCLES = 18,
+ PERF_TSE_CLIP_PLANES = 19,
+};
+
+enum a6xx_ras_perfcounter_select {
+ PERF_RAS_BUSY_CYCLES = 0,
+ PERF_RAS_SUPERTILE_ACTIVE_CYCLES = 1,
+ PERF_RAS_STALL_CYCLES_LRZ = 2,
+ PERF_RAS_STARVE_CYCLES_TSE = 3,
+ PERF_RAS_SUPER_TILES = 4,
+ PERF_RAS_8X4_TILES = 5,
+ PERF_RAS_MASKGEN_ACTIVE = 6,
+ PERF_RAS_FULLY_COVERED_SUPER_TILES = 7,
+ PERF_RAS_FULLY_COVERED_8X4_TILES = 8,
+ PERF_RAS_PRIM_KILLED_INVISILBE = 9,
+ PERF_RAS_SUPERTILE_GEN_ACTIVE_CYCLES = 10,
+ PERF_RAS_LRZ_INTF_WORKING_CYCLES = 11,
+ PERF_RAS_BLOCKS = 12,
+};
+
+enum a6xx_uche_perfcounter_select {
+ PERF_UCHE_BUSY_CYCLES = 0,
+ PERF_UCHE_STALL_CYCLES_ARBITER = 1,
+ PERF_UCHE_VBIF_LATENCY_CYCLES = 2,
+ PERF_UCHE_VBIF_LATENCY_SAMPLES = 3,
+ PERF_UCHE_VBIF_READ_BEATS_TP = 4,
+ PERF_UCHE_VBIF_READ_BEATS_VFD = 5,
+ PERF_UCHE_VBIF_READ_BEATS_HLSQ = 6,
+ PERF_UCHE_VBIF_READ_BEATS_LRZ = 7,
+ PERF_UCHE_VBIF_READ_BEATS_SP = 8,
+ PERF_UCHE_READ_REQUESTS_TP = 9,
+ PERF_UCHE_READ_REQUESTS_VFD = 10,
+ PERF_UCHE_READ_REQUESTS_HLSQ = 11,
+ PERF_UCHE_READ_REQUESTS_LRZ = 12,
+ PERF_UCHE_READ_REQUESTS_SP = 13,
+ PERF_UCHE_WRITE_REQUESTS_LRZ = 14,
+ PERF_UCHE_WRITE_REQUESTS_SP = 15,
+ PERF_UCHE_WRITE_REQUESTS_VPC = 16,
+ PERF_UCHE_WRITE_REQUESTS_VSC = 17,
+ PERF_UCHE_EVICTS = 18,
+ PERF_UCHE_BANK_REQ0 = 19,
+ PERF_UCHE_BANK_REQ1 = 20,
+ PERF_UCHE_BANK_REQ2 = 21,
+ PERF_UCHE_BANK_REQ3 = 22,
+ PERF_UCHE_BANK_REQ4 = 23,
+ PERF_UCHE_BANK_REQ5 = 24,
+ PERF_UCHE_BANK_REQ6 = 25,
+ PERF_UCHE_BANK_REQ7 = 26,
+ PERF_UCHE_VBIF_READ_BEATS_CH0 = 27,
+ PERF_UCHE_VBIF_READ_BEATS_CH1 = 28,
+ PERF_UCHE_GMEM_READ_BEATS = 29,
+ PERF_UCHE_TPH_REF_FULL = 30,
+ PERF_UCHE_TPH_VICTIM_FULL = 31,
+ PERF_UCHE_TPH_EXT_FULL = 32,
+ PERF_UCHE_VBIF_STALL_WRITE_DATA = 33,
+ PERF_UCHE_DCMP_LATENCY_SAMPLES = 34,
+ PERF_UCHE_DCMP_LATENCY_CYCLES = 35,
+ PERF_UCHE_VBIF_READ_BEATS_PC = 36,
+ PERF_UCHE_READ_REQUESTS_PC = 37,
+ PERF_UCHE_RAM_READ_REQ = 38,
+ PERF_UCHE_RAM_WRITE_REQ = 39,
+};
+
+enum a6xx_tp_perfcounter_select {
+ PERF_TP_BUSY_CYCLES = 0,
+ PERF_TP_STALL_CYCLES_UCHE = 1,
+ PERF_TP_LATENCY_CYCLES = 2,
+ PERF_TP_LATENCY_TRANS = 3,
+ PERF_TP_FLAG_CACHE_REQUEST_SAMPLES = 4,
+ PERF_TP_FLAG_CACHE_REQUEST_LATENCY = 5,
+ PERF_TP_L1_CACHELINE_REQUESTS = 6,
+ PERF_TP_L1_CACHELINE_MISSES = 7,
+ PERF_TP_SP_TP_TRANS = 8,
+ PERF_TP_TP_SP_TRANS = 9,
+ PERF_TP_OUTPUT_PIXELS = 10,
+ PERF_TP_FILTER_WORKLOAD_16BIT = 11,
+ PERF_TP_FILTER_WORKLOAD_32BIT = 12,
+ PERF_TP_QUADS_RECEIVED = 13,
+ PERF_TP_QUADS_OFFSET = 14,
+ PERF_TP_QUADS_SHADOW = 15,
+ PERF_TP_QUADS_ARRAY = 16,
+ PERF_TP_QUADS_GRADIENT = 17,
+ PERF_TP_QUADS_1D = 18,
+ PERF_TP_QUADS_2D = 19,
+ PERF_TP_QUADS_BUFFER = 20,
+ PERF_TP_QUADS_3D = 21,
+ PERF_TP_QUADS_CUBE = 22,
+ PERF_TP_DIVERGENT_QUADS_RECEIVED = 23,
+ PERF_TP_PRT_NON_RESIDENT_EVENTS = 24,
+ PERF_TP_OUTPUT_PIXELS_POINT = 25,
+ PERF_TP_OUTPUT_PIXELS_BILINEAR = 26,
+ PERF_TP_OUTPUT_PIXELS_MIP = 27,
+ PERF_TP_OUTPUT_PIXELS_ANISO = 28,
+ PERF_TP_OUTPUT_PIXELS_ZERO_LOD = 29,
+ PERF_TP_FLAG_CACHE_REQUESTS = 30,
+ PERF_TP_FLAG_CACHE_MISSES = 31,
+ PERF_TP_L1_5_L2_REQUESTS = 32,
+ PERF_TP_2D_OUTPUT_PIXELS = 33,
+ PERF_TP_2D_OUTPUT_PIXELS_POINT = 34,
+ PERF_TP_2D_OUTPUT_PIXELS_BILINEAR = 35,
+ PERF_TP_2D_FILTER_WORKLOAD_16BIT = 36,
+ PERF_TP_2D_FILTER_WORKLOAD_32BIT = 37,
+ PERF_TP_TPA2TPC_TRANS = 38,
+ PERF_TP_L1_MISSES_ASTC_1TILE = 39,
+ PERF_TP_L1_MISSES_ASTC_2TILE = 40,
+ PERF_TP_L1_MISSES_ASTC_4TILE = 41,
+ PERF_TP_L1_5_L2_COMPRESS_REQS = 42,
+ PERF_TP_L1_5_L2_COMPRESS_MISS = 43,
+ PERF_TP_L1_BANK_CONFLICT = 44,
+ PERF_TP_L1_5_MISS_LATENCY_CYCLES = 45,
+ PERF_TP_L1_5_MISS_LATENCY_TRANS = 46,
+ PERF_TP_QUADS_CONSTANT_MULTIPLIED = 47,
+ PERF_TP_FRONTEND_WORKING_CYCLES = 48,
+ PERF_TP_L1_TAG_WORKING_CYCLES = 49,
+ PERF_TP_L1_DATA_WRITE_WORKING_CYCLES = 50,
+ PERF_TP_PRE_L1_DECOM_WORKING_CYCLES = 51,
+ PERF_TP_BACKEND_WORKING_CYCLES = 52,
+ PERF_TP_FLAG_CACHE_WORKING_CYCLES = 53,
+ PERF_TP_L1_5_CACHE_WORKING_CYCLES = 54,
+ PERF_TP_STARVE_CYCLES_SP = 55,
+ PERF_TP_STARVE_CYCLES_UCHE = 56,
+};
+
+enum a6xx_sp_perfcounter_select {
+ PERF_SP_BUSY_CYCLES = 0,
+ PERF_SP_ALU_WORKING_CYCLES = 1,
+ PERF_SP_EFU_WORKING_CYCLES = 2,
+ PERF_SP_STALL_CYCLES_VPC = 3,
+ PERF_SP_STALL_CYCLES_TP = 4,
+ PERF_SP_STALL_CYCLES_UCHE = 5,
+ PERF_SP_STALL_CYCLES_RB = 6,
+ PERF_SP_NON_EXECUTION_CYCLES = 7,
+ PERF_SP_WAVE_CONTEXTS = 8,
+ PERF_SP_WAVE_CONTEXT_CYCLES = 9,
+ PERF_SP_FS_STAGE_WAVE_CYCLES = 10,
+ PERF_SP_FS_STAGE_WAVE_SAMPLES = 11,
+ PERF_SP_VS_STAGE_WAVE_CYCLES = 12,
+ PERF_SP_VS_STAGE_WAVE_SAMPLES = 13,
+ PERF_SP_FS_STAGE_DURATION_CYCLES = 14,
+ PERF_SP_VS_STAGE_DURATION_CYCLES = 15,
+ PERF_SP_WAVE_CTRL_CYCLES = 16,
+ PERF_SP_WAVE_LOAD_CYCLES = 17,
+ PERF_SP_WAVE_EMIT_CYCLES = 18,
+ PERF_SP_WAVE_NOP_CYCLES = 19,
+ PERF_SP_WAVE_WAIT_CYCLES = 20,
+ PERF_SP_WAVE_FETCH_CYCLES = 21,
+ PERF_SP_WAVE_IDLE_CYCLES = 22,
+ PERF_SP_WAVE_END_CYCLES = 23,
+ PERF_SP_WAVE_LONG_SYNC_CYCLES = 24,
+ PERF_SP_WAVE_SHORT_SYNC_CYCLES = 25,
+ PERF_SP_WAVE_JOIN_CYCLES = 26,
+ PERF_SP_LM_LOAD_INSTRUCTIONS = 27,
+ PERF_SP_LM_STORE_INSTRUCTIONS = 28,
+ PERF_SP_LM_ATOMICS = 29,
+ PERF_SP_GM_LOAD_INSTRUCTIONS = 30,
+ PERF_SP_GM_STORE_INSTRUCTIONS = 31,
+ PERF_SP_GM_ATOMICS = 32,
+ PERF_SP_VS_STAGE_TEX_INSTRUCTIONS = 33,
+ PERF_SP_VS_STAGE_EFU_INSTRUCTIONS = 34,
+ PERF_SP_VS_STAGE_FULL_ALU_INSTRUCTIONS = 35,
+ PERF_SP_VS_STAGE_HALF_ALU_INSTRUCTIONS = 36,
+ PERF_SP_FS_STAGE_TEX_INSTRUCTIONS = 37,
+ PERF_SP_FS_STAGE_CFLOW_INSTRUCTIONS = 38,
+ PERF_SP_FS_STAGE_EFU_INSTRUCTIONS = 39,
+ PERF_SP_FS_STAGE_FULL_ALU_INSTRUCTIONS = 40,
+ PERF_SP_FS_STAGE_HALF_ALU_INSTRUCTIONS = 41,
+ PERF_SP_FS_STAGE_BARY_INSTRUCTIONS = 42,
+ PERF_SP_VS_INSTRUCTIONS = 43,
+ PERF_SP_FS_INSTRUCTIONS = 44,
+ PERF_SP_ADDR_LOCK_COUNT = 45,
+ PERF_SP_UCHE_READ_TRANS = 46,
+ PERF_SP_UCHE_WRITE_TRANS = 47,
+ PERF_SP_EXPORT_VPC_TRANS = 48,
+ PERF_SP_EXPORT_RB_TRANS = 49,
+ PERF_SP_PIXELS_KILLED = 50,
+ PERF_SP_ICL1_REQUESTS = 51,
+ PERF_SP_ICL1_MISSES = 52,
+ PERF_SP_HS_INSTRUCTIONS = 53,
+ PERF_SP_DS_INSTRUCTIONS = 54,
+ PERF_SP_GS_INSTRUCTIONS = 55,
+ PERF_SP_CS_INSTRUCTIONS = 56,
+ PERF_SP_GPR_READ = 57,
+ PERF_SP_GPR_WRITE = 58,
+ PERF_SP_FS_STAGE_HALF_EFU_INSTRUCTIONS = 59,
+ PERF_SP_VS_STAGE_HALF_EFU_INSTRUCTIONS = 60,
+ PERF_SP_LM_BANK_CONFLICTS = 61,
+ PERF_SP_TEX_CONTROL_WORKING_CYCLES = 62,
+ PERF_SP_LOAD_CONTROL_WORKING_CYCLES = 63,
+ PERF_SP_FLOW_CONTROL_WORKING_CYCLES = 64,
+ PERF_SP_LM_WORKING_CYCLES = 65,
+ PERF_SP_DISPATCHER_WORKING_CYCLES = 66,
+ PERF_SP_SEQUENCER_WORKING_CYCLES = 67,
+ PERF_SP_LOW_EFFICIENCY_STARVED_BY_TP = 68,
+ PERF_SP_STARVE_CYCLES_HLSQ = 69,
+ PERF_SP_NON_EXECUTION_LS_CYCLES = 70,
+ PERF_SP_WORKING_EU = 71,
+ PERF_SP_ANY_EU_WORKING = 72,
+ PERF_SP_WORKING_EU_FS_STAGE = 73,
+ PERF_SP_ANY_EU_WORKING_FS_STAGE = 74,
+ PERF_SP_WORKING_EU_VS_STAGE = 75,
+ PERF_SP_ANY_EU_WORKING_VS_STAGE = 76,
+ PERF_SP_WORKING_EU_CS_STAGE = 77,
+ PERF_SP_ANY_EU_WORKING_CS_STAGE = 78,
+ PERF_SP_GPR_READ_PREFETCH = 79,
+ PERF_SP_GPR_READ_CONFLICT = 80,
+ PERF_SP_GPR_WRITE_CONFLICT = 81,
+ PERF_SP_GM_LOAD_LATENCY_CYCLES = 82,
+ PERF_SP_GM_LOAD_LATENCY_SAMPLES = 83,
+ PERF_SP_EXECUTABLE_WAVES = 84,
+};
+
+enum a6xx_rb_perfcounter_select {
+ PERF_RB_BUSY_CYCLES = 0,
+ PERF_RB_STALL_CYCLES_HLSQ = 1,
+ PERF_RB_STALL_CYCLES_FIFO0_FULL = 2,
+ PERF_RB_STALL_CYCLES_FIFO1_FULL = 3,
+ PERF_RB_STALL_CYCLES_FIFO2_FULL = 4,
+ PERF_RB_STARVE_CYCLES_SP = 5,
+ PERF_RB_STARVE_CYCLES_LRZ_TILE = 6,
+ PERF_RB_STARVE_CYCLES_CCU = 7,
+ PERF_RB_STARVE_CYCLES_Z_PLANE = 8,
+ PERF_RB_STARVE_CYCLES_BARY_PLANE = 9,
+ PERF_RB_Z_WORKLOAD = 10,
+ PERF_RB_HLSQ_ACTIVE = 11,
+ PERF_RB_Z_READ = 12,
+ PERF_RB_Z_WRITE = 13,
+ PERF_RB_C_READ = 14,
+ PERF_RB_C_WRITE = 15,
+ PERF_RB_TOTAL_PASS = 16,
+ PERF_RB_Z_PASS = 17,
+ PERF_RB_Z_FAIL = 18,
+ PERF_RB_S_FAIL = 19,
+ PERF_RB_BLENDED_FXP_COMPONENTS = 20,
+ PERF_RB_BLENDED_FP16_COMPONENTS = 21,
+ PERF_RB_PS_INVOCATIONS = 22,
+ PERF_RB_2D_ALIVE_CYCLES = 23,
+ PERF_RB_2D_STALL_CYCLES_A2D = 24,
+ PERF_RB_2D_STARVE_CYCLES_SRC = 25,
+ PERF_RB_2D_STARVE_CYCLES_SP = 26,
+ PERF_RB_2D_STARVE_CYCLES_DST = 27,
+ PERF_RB_2D_VALID_PIXELS = 28,
+ PERF_RB_3D_PIXELS = 29,
+ PERF_RB_BLENDER_WORKING_CYCLES = 30,
+ PERF_RB_ZPROC_WORKING_CYCLES = 31,
+ PERF_RB_CPROC_WORKING_CYCLES = 32,
+ PERF_RB_SAMPLER_WORKING_CYCLES = 33,
+ PERF_RB_STALL_CYCLES_CCU_COLOR_READ = 34,
+ PERF_RB_STALL_CYCLES_CCU_COLOR_WRITE = 35,
+ PERF_RB_STALL_CYCLES_CCU_DEPTH_READ = 36,
+ PERF_RB_STALL_CYCLES_CCU_DEPTH_WRITE = 37,
+ PERF_RB_STALL_CYCLES_VPC = 38,
+ PERF_RB_2D_INPUT_TRANS = 39,
+ PERF_RB_2D_OUTPUT_RB_DST_TRANS = 40,
+ PERF_RB_2D_OUTPUT_RB_SRC_TRANS = 41,
+ PERF_RB_BLENDED_FP32_COMPONENTS = 42,
+ PERF_RB_COLOR_PIX_TILES = 43,
+ PERF_RB_STALL_CYCLES_CCU = 44,
+ PERF_RB_EARLY_Z_ARB3_GRANT = 45,
+ PERF_RB_LATE_Z_ARB3_GRANT = 46,
+ PERF_RB_EARLY_Z_SKIP_GRANT = 47,
+};
+
+enum a6xx_vsc_perfcounter_select {
+ PERF_VSC_BUSY_CYCLES = 0,
+ PERF_VSC_WORKING_CYCLES = 1,
+ PERF_VSC_STALL_CYCLES_UCHE = 2,
+ PERF_VSC_EOT_NUM = 3,
+ PERF_VSC_INPUT_TILES = 4,
+};
+
+enum a6xx_ccu_perfcounter_select {
+ PERF_CCU_BUSY_CYCLES = 0,
+ PERF_CCU_STALL_CYCLES_RB_DEPTH_RETURN = 1,
+ PERF_CCU_STALL_CYCLES_RB_COLOR_RETURN = 2,
+ PERF_CCU_STARVE_CYCLES_FLAG_RETURN = 3,
+ PERF_CCU_DEPTH_BLOCKS = 4,
+ PERF_CCU_COLOR_BLOCKS = 5,
+ PERF_CCU_DEPTH_BLOCK_HIT = 6,
+ PERF_CCU_COLOR_BLOCK_HIT = 7,
+ PERF_CCU_PARTIAL_BLOCK_READ = 8,
+ PERF_CCU_GMEM_READ = 9,
+ PERF_CCU_GMEM_WRITE = 10,
+ PERF_CCU_DEPTH_READ_FLAG0_COUNT = 11,
+ PERF_CCU_DEPTH_READ_FLAG1_COUNT = 12,
+ PERF_CCU_DEPTH_READ_FLAG2_COUNT = 13,
+ PERF_CCU_DEPTH_READ_FLAG3_COUNT = 14,
+ PERF_CCU_DEPTH_READ_FLAG4_COUNT = 15,
+ PERF_CCU_DEPTH_READ_FLAG5_COUNT = 16,
+ PERF_CCU_DEPTH_READ_FLAG6_COUNT = 17,
+ PERF_CCU_DEPTH_READ_FLAG8_COUNT = 18,
+ PERF_CCU_COLOR_READ_FLAG0_COUNT = 19,
+ PERF_CCU_COLOR_READ_FLAG1_COUNT = 20,
+ PERF_CCU_COLOR_READ_FLAG2_COUNT = 21,
+ PERF_CCU_COLOR_READ_FLAG3_COUNT = 22,
+ PERF_CCU_COLOR_READ_FLAG4_COUNT = 23,
+ PERF_CCU_COLOR_READ_FLAG5_COUNT = 24,
+ PERF_CCU_COLOR_READ_FLAG6_COUNT = 25,
+ PERF_CCU_COLOR_READ_FLAG8_COUNT = 26,
+ PERF_CCU_2D_RD_REQ = 27,
+ PERF_CCU_2D_WR_REQ = 28,
+};
+
+enum a6xx_lrz_perfcounter_select {
+ PERF_LRZ_BUSY_CYCLES = 0,
+ PERF_LRZ_STARVE_CYCLES_RAS = 1,
+ PERF_LRZ_STALL_CYCLES_RB = 2,
+ PERF_LRZ_STALL_CYCLES_VSC = 3,
+ PERF_LRZ_STALL_CYCLES_VPC = 4,
+ PERF_LRZ_STALL_CYCLES_FLAG_PREFETCH = 5,
+ PERF_LRZ_STALL_CYCLES_UCHE = 6,
+ PERF_LRZ_LRZ_READ = 7,
+ PERF_LRZ_LRZ_WRITE = 8,
+ PERF_LRZ_READ_LATENCY = 9,
+ PERF_LRZ_MERGE_CACHE_UPDATING = 10,
+ PERF_LRZ_PRIM_KILLED_BY_MASKGEN = 11,
+ PERF_LRZ_PRIM_KILLED_BY_LRZ = 12,
+ PERF_LRZ_VISIBLE_PRIM_AFTER_LRZ = 13,
+ PERF_LRZ_FULL_8X8_TILES = 14,
+ PERF_LRZ_PARTIAL_8X8_TILES = 15,
+ PERF_LRZ_TILE_KILLED = 16,
+ PERF_LRZ_TOTAL_PIXEL = 17,
+ PERF_LRZ_VISIBLE_PIXEL_AFTER_LRZ = 18,
+ PERF_LRZ_FULLY_COVERED_TILES = 19,
+ PERF_LRZ_PARTIAL_COVERED_TILES = 20,
+ PERF_LRZ_FEEDBACK_ACCEPT = 21,
+ PERF_LRZ_FEEDBACK_DISCARD = 22,
+ PERF_LRZ_FEEDBACK_STALL = 23,
+ PERF_LRZ_STALL_CYCLES_RB_ZPLANE = 24,
+ PERF_LRZ_STALL_CYCLES_RB_BPLANE = 25,
+ PERF_LRZ_STALL_CYCLES_VC = 26,
+ PERF_LRZ_RAS_MASK_TRANS = 27,
+};
+
+enum a6xx_cmp_perfcounter_select {
+ PERF_CMPDECMP_STALL_CYCLES_ARB = 0,
+ PERF_CMPDECMP_VBIF_LATENCY_CYCLES = 1,
+ PERF_CMPDECMP_VBIF_LATENCY_SAMPLES = 2,
+ PERF_CMPDECMP_VBIF_READ_DATA_CCU = 3,
+ PERF_CMPDECMP_VBIF_WRITE_DATA_CCU = 4,
+ PERF_CMPDECMP_VBIF_READ_REQUEST = 5,
+ PERF_CMPDECMP_VBIF_WRITE_REQUEST = 6,
+ PERF_CMPDECMP_VBIF_READ_DATA = 7,
+ PERF_CMPDECMP_VBIF_WRITE_DATA = 8,
+ PERF_CMPDECMP_FLAG_FETCH_CYCLES = 9,
+ PERF_CMPDECMP_FLAG_FETCH_SAMPLES = 10,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG1_COUNT = 11,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG2_COUNT = 12,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG3_COUNT = 13,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG4_COUNT = 14,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG5_COUNT = 15,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG6_COUNT = 16,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG8_COUNT = 17,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG1_COUNT = 18,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG2_COUNT = 19,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG3_COUNT = 20,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG4_COUNT = 21,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG5_COUNT = 22,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG6_COUNT = 23,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG8_COUNT = 24,
+ PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_REQ = 25,
+ PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_WR = 26,
+ PERF_CMPDECMP_2D_STALL_CYCLES_VBIF_RETURN = 27,
+ PERF_CMPDECMP_2D_RD_DATA = 28,
+ PERF_CMPDECMP_2D_WR_DATA = 29,
+ PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH0 = 30,
+ PERF_CMPDECMP_VBIF_READ_DATA_UCHE_CH1 = 31,
+ PERF_CMPDECMP_2D_OUTPUT_TRANS = 32,
+ PERF_CMPDECMP_VBIF_WRITE_DATA_UCHE = 33,
+ PERF_CMPDECMP_DEPTH_WRITE_FLAG0_COUNT = 34,
+ PERF_CMPDECMP_COLOR_WRITE_FLAG0_COUNT = 35,
+ PERF_CMPDECMP_COLOR_WRITE_FLAGALPHA_COUNT = 36,
+ PERF_CMPDECMP_2D_BUSY_CYCLES = 37,
+ PERF_CMPDECMP_2D_REORDER_STARVE_CYCLES = 38,
+ PERF_CMPDECMP_2D_PIXELS = 39,
};
enum a6xx_tex_filter {
@@ -1765,12 +2444,39 @@ static inline uint32_t A6XX_UCHE_CLIENT_PF_PERFSEL(uint32_t val)
#define REG_A6XX_VBIF_VERSION 0x00003000
+#define REG_A6XX_VBIF_CLKON 0x00003001
+#define A6XX_VBIF_CLKON_FORCE_ON_TESTBUS 0x00000002
+
#define REG_A6XX_VBIF_GATE_OFF_WRREQ_EN 0x0000302a
#define REG_A6XX_VBIF_XIN_HALT_CTRL0 0x00003080
#define REG_A6XX_VBIF_XIN_HALT_CTRL1 0x00003081
+#define REG_A6XX_VBIF_TEST_BUS_OUT_CTRL 0x00003084
+
+#define REG_A6XX_VBIF_TEST_BUS1_CTRL0 0x00003085
+
+#define REG_A6XX_VBIF_TEST_BUS1_CTRL1 0x00003086
+#define A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL__MASK 0x0000000f
+#define A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL__SHIFT 0
+static inline uint32_t A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL(uint32_t val)
+{
+ return ((val) << A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL__SHIFT) & A6XX_VBIF_TEST_BUS1_CTRL1_DATA_SEL__MASK;
+}
+
+#define REG_A6XX_VBIF_TEST_BUS2_CTRL0 0x00003087
+
+#define REG_A6XX_VBIF_TEST_BUS2_CTRL1 0x00003088
+#define A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL__MASK 0x000001ff
+#define A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL__SHIFT 0
+static inline uint32_t A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL(uint32_t val)
+{
+ return ((val) << A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL__SHIFT) & A6XX_VBIF_TEST_BUS2_CTRL1_DATA_SEL__MASK;
+}
+
+#define REG_A6XX_VBIF_TEST_BUS_OUT 0x0000308c
+
#define REG_A6XX_VBIF_PERF_CNT_SEL0 0x000030d0
#define REG_A6XX_VBIF_PERF_CNT_SEL1 0x000030d1
@@ -1813,313 +2519,79 @@ static inline uint32_t A6XX_UCHE_CLIENT_PF_PERFSEL(uint32_t val)
#define REG_A6XX_VBIF_PERF_PWR_CNT_HIGH2 0x0000311a
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_A 0x00018400
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_B 0x00018401
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_C 0x00018402
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_D 0x00018403
-#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX__MASK 0x000000ff
-#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX__SHIFT 0
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_INDEX__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL__MASK 0x0000ff00
-#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL__SHIFT 8
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_SEL_D_PING_BLK_SEL__MASK;
-}
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLT 0x00018404
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__MASK 0x0000003f
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__SHIFT 0
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__MASK 0x00007000
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__SHIFT 12
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__MASK 0xf0000000
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__SHIFT 28
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__MASK;
-}
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLM 0x00018405
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__MASK 0x0f000000
-#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__SHIFT 24
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__MASK;
-}
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_0 0x00018408
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_1 0x00018409
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_2 0x0001840a
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_3 0x0001840b
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_0 0x0001840c
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_1 0x0001840d
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_2 0x0001840e
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_3 0x0001840f
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0 0x00018410
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__MASK 0x0000000f
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__SHIFT 0
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__MASK 0x000000f0
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__SHIFT 4
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__MASK 0x00000f00
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__SHIFT 8
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__MASK 0x0000f000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__SHIFT 12
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__MASK 0x000f0000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__SHIFT 16
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__MASK 0x00f00000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__SHIFT 20
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__MASK 0x0f000000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__SHIFT 24
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__MASK 0xf0000000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__SHIFT 28
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__MASK;
-}
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1 0x00018411
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__MASK 0x0000000f
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__SHIFT 0
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__MASK 0x000000f0
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__SHIFT 4
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__MASK 0x00000f00
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__SHIFT 8
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__MASK 0x0000f000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__SHIFT 12
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__MASK 0x000f0000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__SHIFT 16
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__MASK 0x00f00000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__SHIFT 20
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__MASK 0x0f000000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__SHIFT 24
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__MASK;
-}
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__MASK 0xf0000000
-#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__SHIFT 28
-static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15(uint32_t val)
-{
- return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__MASK;
-}
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF1 0x0001842f
-
-#define REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2 0x00018430
-
-#define REG_A6XX_PDC_GPU_ENABLE_PDC 0x00021140
-
-#define REG_A6XX_PDC_GPU_SEQ_START_ADDR 0x00021148
-
-#define REG_A6XX_PDC_GPU_TCS0_CONTROL 0x00021540
-
-#define REG_A6XX_PDC_GPU_TCS0_CMD_ENABLE_BANK 0x00021541
-
-#define REG_A6XX_PDC_GPU_TCS0_CMD_WAIT_FOR_CMPL_BANK 0x00021542
-
-#define REG_A6XX_PDC_GPU_TCS0_CMD0_MSGID 0x00021543
-
-#define REG_A6XX_PDC_GPU_TCS0_CMD0_ADDR 0x00021544
-
-#define REG_A6XX_PDC_GPU_TCS0_CMD0_DATA 0x00021545
-
-#define REG_A6XX_PDC_GPU_TCS1_CONTROL 0x00021572
-
-#define REG_A6XX_PDC_GPU_TCS1_CMD_ENABLE_BANK 0x00021573
-
-#define REG_A6XX_PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK 0x00021574
-
-#define REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID 0x00021575
-
-#define REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR 0x00021576
-
-#define REG_A6XX_PDC_GPU_TCS1_CMD0_DATA 0x00021577
-
-#define REG_A6XX_PDC_GPU_TCS2_CONTROL 0x000215a4
-
-#define REG_A6XX_PDC_GPU_TCS2_CMD_ENABLE_BANK 0x000215a5
-
-#define REG_A6XX_PDC_GPU_TCS2_CMD_WAIT_FOR_CMPL_BANK 0x000215a6
-
-#define REG_A6XX_PDC_GPU_TCS2_CMD0_MSGID 0x000215a7
-
-#define REG_A6XX_PDC_GPU_TCS2_CMD0_ADDR 0x000215a8
-
-#define REG_A6XX_PDC_GPU_TCS2_CMD0_DATA 0x000215a9
-
-#define REG_A6XX_PDC_GPU_TCS3_CONTROL 0x000215d6
-
-#define REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK 0x000215d7
-
-#define REG_A6XX_PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK 0x000215d8
-
-#define REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID 0x000215d9
-
-#define REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR 0x000215da
-
-#define REG_A6XX_PDC_GPU_TCS3_CMD0_DATA 0x000215db
-
-#define REG_A6XX_PDC_GPU_SEQ_MEM_0 0x000a0000
-
-#define REG_A6XX_X1_WINDOW_OFFSET 0x000088d4
-#define A6XX_X1_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
-#define A6XX_X1_WINDOW_OFFSET_X__MASK 0x00007fff
-#define A6XX_X1_WINDOW_OFFSET_X__SHIFT 0
-static inline uint32_t A6XX_X1_WINDOW_OFFSET_X(uint32_t val)
-{
- return ((val) << A6XX_X1_WINDOW_OFFSET_X__SHIFT) & A6XX_X1_WINDOW_OFFSET_X__MASK;
-}
-#define A6XX_X1_WINDOW_OFFSET_Y__MASK 0x7fff0000
-#define A6XX_X1_WINDOW_OFFSET_Y__SHIFT 16
-static inline uint32_t A6XX_X1_WINDOW_OFFSET_Y(uint32_t val)
-{
- return ((val) << A6XX_X1_WINDOW_OFFSET_Y__SHIFT) & A6XX_X1_WINDOW_OFFSET_Y__MASK;
-}
-
-#define REG_A6XX_X2_WINDOW_OFFSET 0x0000b4d1
-#define A6XX_X2_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
-#define A6XX_X2_WINDOW_OFFSET_X__MASK 0x00007fff
-#define A6XX_X2_WINDOW_OFFSET_X__SHIFT 0
-static inline uint32_t A6XX_X2_WINDOW_OFFSET_X(uint32_t val)
+#define REG_A6XX_RB_WINDOW_OFFSET2 0x000088d4
+#define A6XX_RB_WINDOW_OFFSET2_WINDOW_OFFSET_DISABLE 0x80000000
+#define A6XX_RB_WINDOW_OFFSET2_X__MASK 0x00007fff
+#define A6XX_RB_WINDOW_OFFSET2_X__SHIFT 0
+static inline uint32_t A6XX_RB_WINDOW_OFFSET2_X(uint32_t val)
{
- return ((val) << A6XX_X2_WINDOW_OFFSET_X__SHIFT) & A6XX_X2_WINDOW_OFFSET_X__MASK;
+ return ((val) << A6XX_RB_WINDOW_OFFSET2_X__SHIFT) & A6XX_RB_WINDOW_OFFSET2_X__MASK;
}
-#define A6XX_X2_WINDOW_OFFSET_Y__MASK 0x7fff0000
-#define A6XX_X2_WINDOW_OFFSET_Y__SHIFT 16
-static inline uint32_t A6XX_X2_WINDOW_OFFSET_Y(uint32_t val)
+#define A6XX_RB_WINDOW_OFFSET2_Y__MASK 0x7fff0000
+#define A6XX_RB_WINDOW_OFFSET2_Y__SHIFT 16
+static inline uint32_t A6XX_RB_WINDOW_OFFSET2_Y(uint32_t val)
{
- return ((val) << A6XX_X2_WINDOW_OFFSET_Y__SHIFT) & A6XX_X2_WINDOW_OFFSET_Y__MASK;
+ return ((val) << A6XX_RB_WINDOW_OFFSET2_Y__SHIFT) & A6XX_RB_WINDOW_OFFSET2_Y__MASK;
}
-#define REG_A6XX_X3_WINDOW_OFFSET 0x0000b307
-#define A6XX_X3_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
-#define A6XX_X3_WINDOW_OFFSET_X__MASK 0x00007fff
-#define A6XX_X3_WINDOW_OFFSET_X__SHIFT 0
-static inline uint32_t A6XX_X3_WINDOW_OFFSET_X(uint32_t val)
+#define REG_A6XX_SP_WINDOW_OFFSET 0x0000b4d1
+#define A6XX_SP_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
+#define A6XX_SP_WINDOW_OFFSET_X__MASK 0x00007fff
+#define A6XX_SP_WINDOW_OFFSET_X__SHIFT 0
+static inline uint32_t A6XX_SP_WINDOW_OFFSET_X(uint32_t val)
{
- return ((val) << A6XX_X3_WINDOW_OFFSET_X__SHIFT) & A6XX_X3_WINDOW_OFFSET_X__MASK;
+ return ((val) << A6XX_SP_WINDOW_OFFSET_X__SHIFT) & A6XX_SP_WINDOW_OFFSET_X__MASK;
}
-#define A6XX_X3_WINDOW_OFFSET_Y__MASK 0x7fff0000
-#define A6XX_X3_WINDOW_OFFSET_Y__SHIFT 16
-static inline uint32_t A6XX_X3_WINDOW_OFFSET_Y(uint32_t val)
+#define A6XX_SP_WINDOW_OFFSET_Y__MASK 0x7fff0000
+#define A6XX_SP_WINDOW_OFFSET_Y__SHIFT 16
+static inline uint32_t A6XX_SP_WINDOW_OFFSET_Y(uint32_t val)
{
- return ((val) << A6XX_X3_WINDOW_OFFSET_Y__SHIFT) & A6XX_X3_WINDOW_OFFSET_Y__MASK;
+ return ((val) << A6XX_SP_WINDOW_OFFSET_Y__SHIFT) & A6XX_SP_WINDOW_OFFSET_Y__MASK;
}
-#define REG_A6XX_X1_BIN_SIZE 0x000080a1
-#define A6XX_X1_BIN_SIZE_WIDTH__MASK 0x000000ff
-#define A6XX_X1_BIN_SIZE_WIDTH__SHIFT 0
-static inline uint32_t A6XX_X1_BIN_SIZE_WIDTH(uint32_t val)
+#define REG_A6XX_SP_TP_WINDOW_OFFSET 0x0000b307
+#define A6XX_SP_TP_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
+#define A6XX_SP_TP_WINDOW_OFFSET_X__MASK 0x00007fff
+#define A6XX_SP_TP_WINDOW_OFFSET_X__SHIFT 0
+static inline uint32_t A6XX_SP_TP_WINDOW_OFFSET_X(uint32_t val)
{
- return ((val >> 5) << A6XX_X1_BIN_SIZE_WIDTH__SHIFT) & A6XX_X1_BIN_SIZE_WIDTH__MASK;
+ return ((val) << A6XX_SP_TP_WINDOW_OFFSET_X__SHIFT) & A6XX_SP_TP_WINDOW_OFFSET_X__MASK;
}
-#define A6XX_X1_BIN_SIZE_HEIGHT__MASK 0x0001ff00
-#define A6XX_X1_BIN_SIZE_HEIGHT__SHIFT 8
-static inline uint32_t A6XX_X1_BIN_SIZE_HEIGHT(uint32_t val)
+#define A6XX_SP_TP_WINDOW_OFFSET_Y__MASK 0x7fff0000
+#define A6XX_SP_TP_WINDOW_OFFSET_Y__SHIFT 16
+static inline uint32_t A6XX_SP_TP_WINDOW_OFFSET_Y(uint32_t val)
{
- return ((val >> 4) << A6XX_X1_BIN_SIZE_HEIGHT__SHIFT) & A6XX_X1_BIN_SIZE_HEIGHT__MASK;
+ return ((val) << A6XX_SP_TP_WINDOW_OFFSET_Y__SHIFT) & A6XX_SP_TP_WINDOW_OFFSET_Y__MASK;
}
-#define REG_A6XX_X2_BIN_SIZE 0x00008800
-#define A6XX_X2_BIN_SIZE_WIDTH__MASK 0x000000ff
-#define A6XX_X2_BIN_SIZE_WIDTH__SHIFT 0
-static inline uint32_t A6XX_X2_BIN_SIZE_WIDTH(uint32_t val)
+#define REG_A6XX_GRAS_BIN_CONTROL 0x000080a1
+#define A6XX_GRAS_BIN_CONTROL_BINW__MASK 0x000000ff
+#define A6XX_GRAS_BIN_CONTROL_BINW__SHIFT 0
+static inline uint32_t A6XX_GRAS_BIN_CONTROL_BINW(uint32_t val)
{
- return ((val >> 5) << A6XX_X2_BIN_SIZE_WIDTH__SHIFT) & A6XX_X2_BIN_SIZE_WIDTH__MASK;
+ return ((val >> 5) << A6XX_GRAS_BIN_CONTROL_BINW__SHIFT) & A6XX_GRAS_BIN_CONTROL_BINW__MASK;
}
-#define A6XX_X2_BIN_SIZE_HEIGHT__MASK 0x0001ff00
-#define A6XX_X2_BIN_SIZE_HEIGHT__SHIFT 8
-static inline uint32_t A6XX_X2_BIN_SIZE_HEIGHT(uint32_t val)
+#define A6XX_GRAS_BIN_CONTROL_BINH__MASK 0x0001ff00
+#define A6XX_GRAS_BIN_CONTROL_BINH__SHIFT 8
+static inline uint32_t A6XX_GRAS_BIN_CONTROL_BINH(uint32_t val)
{
- return ((val >> 4) << A6XX_X2_BIN_SIZE_HEIGHT__SHIFT) & A6XX_X2_BIN_SIZE_HEIGHT__MASK;
+ return ((val >> 4) << A6XX_GRAS_BIN_CONTROL_BINH__SHIFT) & A6XX_GRAS_BIN_CONTROL_BINH__MASK;
}
+#define A6XX_GRAS_BIN_CONTROL_BINNING_PASS 0x00040000
+#define A6XX_GRAS_BIN_CONTROL_USE_VIZ 0x00200000
-#define REG_A6XX_X3_BIN_SIZE 0x000088d3
-#define A6XX_X3_BIN_SIZE_WIDTH__MASK 0x000000ff
-#define A6XX_X3_BIN_SIZE_WIDTH__SHIFT 0
-static inline uint32_t A6XX_X3_BIN_SIZE_WIDTH(uint32_t val)
+#define REG_A6XX_RB_BIN_CONTROL2 0x000088d3
+#define A6XX_RB_BIN_CONTROL2_BINW__MASK 0x000000ff
+#define A6XX_RB_BIN_CONTROL2_BINW__SHIFT 0
+static inline uint32_t A6XX_RB_BIN_CONTROL2_BINW(uint32_t val)
{
- return ((val >> 5) << A6XX_X3_BIN_SIZE_WIDTH__SHIFT) & A6XX_X3_BIN_SIZE_WIDTH__MASK;
+ return ((val >> 5) << A6XX_RB_BIN_CONTROL2_BINW__SHIFT) & A6XX_RB_BIN_CONTROL2_BINW__MASK;
}
-#define A6XX_X3_BIN_SIZE_HEIGHT__MASK 0x0001ff00
-#define A6XX_X3_BIN_SIZE_HEIGHT__SHIFT 8
-static inline uint32_t A6XX_X3_BIN_SIZE_HEIGHT(uint32_t val)
+#define A6XX_RB_BIN_CONTROL2_BINH__MASK 0x0001ff00
+#define A6XX_RB_BIN_CONTROL2_BINH__SHIFT 8
+static inline uint32_t A6XX_RB_BIN_CONTROL2_BINH(uint32_t val)
{
- return ((val >> 4) << A6XX_X3_BIN_SIZE_HEIGHT__SHIFT) & A6XX_X3_BIN_SIZE_HEIGHT__MASK;
+ return ((val >> 4) << A6XX_RB_BIN_CONTROL2_BINH__SHIFT) & A6XX_RB_BIN_CONTROL2_BINH__MASK;
}
#define REG_A6XX_VSC_BIN_SIZE 0x00000c02
@@ -2182,11 +2654,19 @@ static inline uint32_t A6XX_VSC_PIPE_CONFIG_REG_H(uint32_t val)
return ((val) << A6XX_VSC_PIPE_CONFIG_REG_H__SHIFT) & A6XX_VSC_PIPE_CONFIG_REG_H__MASK;
}
-#define REG_A6XX_VSC_XXX_ADDRESS_LO 0x00000c30
+#define REG_A6XX_VSC_PIPE_DATA2_ADDRESS_LO 0x00000c30
-#define REG_A6XX_VSC_XXX_ADDRESS_HI 0x00000c31
+#define REG_A6XX_VSC_PIPE_DATA2_ADDRESS_HI 0x00000c31
-#define REG_A6XX_VSC_XXX_PITCH 0x00000c32
+#define REG_A6XX_VSC_PIPE_DATA2_PITCH 0x00000c32
+
+#define REG_A6XX_VSC_PIPE_DATA2_ARRAY_PITCH 0x00000c33
+#define A6XX_VSC_PIPE_DATA2_ARRAY_PITCH__MASK 0xffffffff
+#define A6XX_VSC_PIPE_DATA2_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A6XX_VSC_PIPE_DATA2_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 4) << A6XX_VSC_PIPE_DATA2_ARRAY_PITCH__SHIFT) & A6XX_VSC_PIPE_DATA2_ARRAY_PITCH__MASK;
+}
#define REG_A6XX_VSC_PIPE_DATA_ADDRESS_LO 0x00000c34
@@ -2194,18 +2674,29 @@ static inline uint32_t A6XX_VSC_PIPE_CONFIG_REG_H(uint32_t val)
#define REG_A6XX_VSC_PIPE_DATA_PITCH 0x00000c36
+#define REG_A6XX_VSC_PIPE_DATA_ARRAY_PITCH 0x00000c37
+#define A6XX_VSC_PIPE_DATA_ARRAY_PITCH__MASK 0xffffffff
+#define A6XX_VSC_PIPE_DATA_ARRAY_PITCH__SHIFT 0
+static inline uint32_t A6XX_VSC_PIPE_DATA_ARRAY_PITCH(uint32_t val)
+{
+ return ((val >> 4) << A6XX_VSC_PIPE_DATA_ARRAY_PITCH__SHIFT) & A6XX_VSC_PIPE_DATA_ARRAY_PITCH__MASK;
+}
+
static inline uint32_t REG_A6XX_VSC_SIZE(uint32_t i0) { return 0x00000c78 + 0x1*i0; }
static inline uint32_t REG_A6XX_VSC_SIZE_REG(uint32_t i0) { return 0x00000c78 + 0x1*i0; }
#define REG_A6XX_UCHE_UNKNOWN_0E12 0x00000e12
+#define REG_A6XX_GRAS_UNKNOWN_8000 0x00008000
+
#define REG_A6XX_GRAS_UNKNOWN_8001 0x00008001
#define REG_A6XX_GRAS_UNKNOWN_8004 0x00008004
#define REG_A6XX_GRAS_CNTL 0x00008005
#define A6XX_GRAS_CNTL_VARYING 0x00000001
+#define A6XX_GRAS_CNTL_UNK3 0x00000008
#define A6XX_GRAS_CNTL_XCOORD 0x00000040
#define A6XX_GRAS_CNTL_YCOORD 0x00000080
#define A6XX_GRAS_CNTL_ZCOORD 0x00000100
@@ -2308,6 +2799,9 @@ static inline uint32_t A6XX_GRAS_SU_POINT_SIZE(float val)
return ((((int32_t)(val * 16.0))) << A6XX_GRAS_SU_POINT_SIZE__SHIFT) & A6XX_GRAS_SU_POINT_SIZE__MASK;
}
+#define REG_A6XX_GRAS_SU_DEPTH_PLANE_CNTL 0x00008094
+#define A6XX_GRAS_SU_DEPTH_PLANE_CNTL_FRAG_WRITES_Z 0x00000001
+
#define REG_A6XX_GRAS_SU_POLY_OFFSET_SCALE 0x00008095
#define A6XX_GRAS_SU_POLY_OFFSET_SCALE__MASK 0xffffffff
#define A6XX_GRAS_SU_POLY_OFFSET_SCALE__SHIFT 0
@@ -2344,6 +2838,8 @@ static inline uint32_t A6XX_GRAS_SU_DEPTH_BUFFER_INFO_DEPTH_FORMAT(enum a6xx_dep
#define REG_A6XX_GRAS_UNKNOWN_809B 0x0000809b
+#define REG_A6XX_GRAS_UNKNOWN_80A0 0x000080a0
+
#define REG_A6XX_GRAS_RAS_MSAA_CNTL 0x000080a2
#define A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES__MASK 0x00000003
#define A6XX_GRAS_RAS_MSAA_CNTL_SAMPLES__SHIFT 0
@@ -2464,6 +2960,8 @@ static inline uint32_t A6XX_GRAS_SC_WINDOW_SCISSOR_BR_Y(uint32_t val)
#define A6XX_GRAS_LRZ_CNTL_LRZ_WRITE 0x00000002
#define A6XX_GRAS_LRZ_CNTL_GREATER 0x00000004
+#define REG_A6XX_GRAS_UNKNOWN_8101 0x00008101
+
#define REG_A6XX_GRAS_2D_BLIT_INFO 0x00008102
#define A6XX_GRAS_2D_BLIT_INFO_COLOR_FORMAT__MASK 0x000000ff
#define A6XX_GRAS_2D_BLIT_INFO_COLOR_FORMAT__SHIFT 0
@@ -2494,6 +2992,10 @@ static inline uint32_t A6XX_GRAS_LRZ_BUFFER_PITCH_ARRAY_PITCH(uint32_t val)
#define REG_A6XX_GRAS_LRZ_FAST_CLEAR_BUFFER_BASE_HI 0x00008107
+#define REG_A6XX_GRAS_UNKNOWN_8109 0x00008109
+
+#define REG_A6XX_GRAS_UNKNOWN_8110 0x00008110
+
#define REG_A6XX_GRAS_2D_BLIT_CNTL 0x00008400
#define REG_A6XX_GRAS_2D_SRC_TL_X 0x00008401
@@ -2590,6 +3092,33 @@ static inline uint32_t A6XX_GRAS_RESOLVE_CNTL_2_Y(uint32_t val)
#define REG_A6XX_GRAS_UNKNOWN_8600 0x00008600
+#define REG_A6XX_RB_BIN_CONTROL 0x00008800
+#define A6XX_RB_BIN_CONTROL_BINW__MASK 0x000000ff
+#define A6XX_RB_BIN_CONTROL_BINW__SHIFT 0
+static inline uint32_t A6XX_RB_BIN_CONTROL_BINW(uint32_t val)
+{
+ return ((val >> 5) << A6XX_RB_BIN_CONTROL_BINW__SHIFT) & A6XX_RB_BIN_CONTROL_BINW__MASK;
+}
+#define A6XX_RB_BIN_CONTROL_BINH__MASK 0x0001ff00
+#define A6XX_RB_BIN_CONTROL_BINH__SHIFT 8
+static inline uint32_t A6XX_RB_BIN_CONTROL_BINH(uint32_t val)
+{
+ return ((val >> 4) << A6XX_RB_BIN_CONTROL_BINH__SHIFT) & A6XX_RB_BIN_CONTROL_BINH__MASK;
+}
+#define A6XX_RB_BIN_CONTROL_BINNING_PASS 0x00040000
+#define A6XX_RB_BIN_CONTROL_USE_VIZ 0x00200000
+
+#define REG_A6XX_RB_RENDER_CNTL 0x00008801
+#define A6XX_RB_RENDER_CNTL_UNK4 0x00000010
+#define A6XX_RB_RENDER_CNTL_BINNING 0x00000080
+#define A6XX_RB_RENDER_CNTL_FLAG_DEPTH 0x00004000
+#define A6XX_RB_RENDER_CNTL_FLAG_MRTS__MASK 0x00ff0000
+#define A6XX_RB_RENDER_CNTL_FLAG_MRTS__SHIFT 16
+static inline uint32_t A6XX_RB_RENDER_CNTL_FLAG_MRTS(uint32_t val)
+{
+ return ((val) << A6XX_RB_RENDER_CNTL_FLAG_MRTS__SHIFT) & A6XX_RB_RENDER_CNTL_FLAG_MRTS__MASK;
+}
+
#define REG_A6XX_RB_RAS_MSAA_CNTL 0x00008802
#define A6XX_RB_RAS_MSAA_CNTL_SAMPLES__MASK 0x00000003
#define A6XX_RB_RAS_MSAA_CNTL_SAMPLES__SHIFT 0
@@ -2615,6 +3144,7 @@ static inline uint32_t A6XX_RB_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples val
#define REG_A6XX_RB_RENDER_CONTROL0 0x00008809
#define A6XX_RB_RENDER_CONTROL0_VARYING 0x00000001
+#define A6XX_RB_RENDER_CONTROL0_UNK3 0x00000008
#define A6XX_RB_RENDER_CONTROL0_XCOORD 0x00000040
#define A6XX_RB_RENDER_CONTROL0_YCOORD 0x00000080
#define A6XX_RB_RENDER_CONTROL0_ZCOORD 0x00000100
@@ -2747,6 +3277,10 @@ static inline uint32_t A6XX_RB_DITHER_CNTL_DITHER_MODE_MRT7(enum adreno_rb_dithe
#define A6XX_RB_SRGB_CNTL_SRGB_MRT6 0x00000040
#define A6XX_RB_SRGB_CNTL_SRGB_MRT7 0x00000080
+#define REG_A6XX_RB_UNKNOWN_8810 0x00008810
+
+#define REG_A6XX_RB_UNKNOWN_8811 0x00008811
+
#define REG_A6XX_RB_UNKNOWN_8818 0x00008818
#define REG_A6XX_RB_UNKNOWN_8819 0x00008819
@@ -2837,7 +3371,6 @@ static inline uint32_t A6XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
{
return ((val) << A6XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A6XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
}
-#define A6XX_RB_MRT_BUF_INFO_COLOR_SRGB 0x00008000
static inline uint32_t REG_A6XX_RB_MRT_PITCH(uint32_t i0) { return 0x00008823 + 0x8*i0; }
#define A6XX_RB_MRT_PITCH__MASK 0xffffffff
@@ -2923,6 +3456,9 @@ static inline uint32_t A6XX_RB_BLEND_CNTL_SAMPLE_MASK(uint32_t val)
return ((val) << A6XX_RB_BLEND_CNTL_SAMPLE_MASK__SHIFT) & A6XX_RB_BLEND_CNTL_SAMPLE_MASK__MASK;
}
+#define REG_A6XX_RB_DEPTH_PLANE_CNTL 0x00008870
+#define A6XX_RB_DEPTH_PLANE_CNTL_FRAG_WRITES_Z 0x00000001
+
#define REG_A6XX_RB_DEPTH_CNTL 0x00008871
#define A6XX_RB_DEPTH_CNTL_Z_ENABLE 0x00000001
#define A6XX_RB_DEPTH_CNTL_Z_WRITE_ENABLE 0x00000002
@@ -3053,6 +3589,12 @@ static inline uint32_t A6XX_RB_STENCILREF_REF(uint32_t val)
{
return ((val) << A6XX_RB_STENCILREF_REF__SHIFT) & A6XX_RB_STENCILREF_REF__MASK;
}
+#define A6XX_RB_STENCILREF_BFREF__MASK 0x0000ff00
+#define A6XX_RB_STENCILREF_BFREF__SHIFT 8
+static inline uint32_t A6XX_RB_STENCILREF_BFREF(uint32_t val)
+{
+ return ((val) << A6XX_RB_STENCILREF_BFREF__SHIFT) & A6XX_RB_STENCILREF_BFREF__MASK;
+}
#define REG_A6XX_RB_STENCILMASK 0x00008888
#define A6XX_RB_STENCILMASK_MASK__MASK 0x000000ff
@@ -3061,6 +3603,12 @@ static inline uint32_t A6XX_RB_STENCILMASK_MASK(uint32_t val)
{
return ((val) << A6XX_RB_STENCILMASK_MASK__SHIFT) & A6XX_RB_STENCILMASK_MASK__MASK;
}
+#define A6XX_RB_STENCILMASK_BFMASK__MASK 0x0000ff00
+#define A6XX_RB_STENCILMASK_BFMASK__SHIFT 8
+static inline uint32_t A6XX_RB_STENCILMASK_BFMASK(uint32_t val)
+{
+ return ((val) << A6XX_RB_STENCILMASK_BFMASK__SHIFT) & A6XX_RB_STENCILMASK_BFMASK__MASK;
+}
#define REG_A6XX_RB_STENCILWRMASK 0x00008889
#define A6XX_RB_STENCILWRMASK_WRMASK__MASK 0x000000ff
@@ -3069,6 +3617,12 @@ static inline uint32_t A6XX_RB_STENCILWRMASK_WRMASK(uint32_t val)
{
return ((val) << A6XX_RB_STENCILWRMASK_WRMASK__SHIFT) & A6XX_RB_STENCILWRMASK_WRMASK__MASK;
}
+#define A6XX_RB_STENCILWRMASK_BFWRMASK__MASK 0x0000ff00
+#define A6XX_RB_STENCILWRMASK_BFWRMASK__SHIFT 8
+static inline uint32_t A6XX_RB_STENCILWRMASK_BFWRMASK(uint32_t val)
+{
+ return ((val) << A6XX_RB_STENCILWRMASK_BFWRMASK__SHIFT) & A6XX_RB_STENCILWRMASK_BFWRMASK__MASK;
+}
#define REG_A6XX_RB_WINDOW_OFFSET 0x00008890
#define A6XX_RB_WINDOW_OFFSET_WINDOW_OFFSET_DISABLE 0x80000000
@@ -3177,14 +3731,14 @@ static inline uint32_t A6XX_RB_BLIT_DST_ARRAY_PITCH(uint32_t val)
#define REG_A6XX_RB_BLIT_INFO 0x000088e3
#define A6XX_RB_BLIT_INFO_UNK0 0x00000001
-#define A6XX_RB_BLIT_INFO_FAST_CLEAR 0x00000002
+#define A6XX_RB_BLIT_INFO_GMEM 0x00000002
#define A6XX_RB_BLIT_INFO_INTEGER 0x00000004
-#define A6XX_RB_BLIT_INFO_UNK3 0x00000008
-#define A6XX_RB_BLIT_INFO_MASK__MASK 0x000000f0
-#define A6XX_RB_BLIT_INFO_MASK__SHIFT 4
-static inline uint32_t A6XX_RB_BLIT_INFO_MASK(uint32_t val)
+#define A6XX_RB_BLIT_INFO_DEPTH 0x00000008
+#define A6XX_RB_BLIT_INFO_CLEAR_MASK__MASK 0x000000f0
+#define A6XX_RB_BLIT_INFO_CLEAR_MASK__SHIFT 4
+static inline uint32_t A6XX_RB_BLIT_INFO_CLEAR_MASK(uint32_t val)
{
- return ((val) << A6XX_RB_BLIT_INFO_MASK__SHIFT) & A6XX_RB_BLIT_INFO_MASK__MASK;
+ return ((val) << A6XX_RB_BLIT_INFO_CLEAR_MASK__SHIFT) & A6XX_RB_BLIT_INFO_CLEAR_MASK__MASK;
}
#define REG_A6XX_RB_UNKNOWN_88F0 0x000088f0
@@ -3274,12 +3828,16 @@ static inline uint32_t A6XX_RB_2D_DST_SIZE_PITCH(uint32_t val)
#define REG_A6XX_RB_UNKNOWN_8E01 0x00008e01
+#define REG_A6XX_RB_UNKNOWN_8E04 0x00008e04
+
#define REG_A6XX_RB_CCU_CNTL 0x00008e07
#define REG_A6XX_VPC_UNKNOWN_9101 0x00009101
#define REG_A6XX_VPC_GS_SIV_CNTL 0x00009104
+#define REG_A6XX_VPC_UNKNOWN_9107 0x00009107
+
#define REG_A6XX_VPC_UNKNOWN_9108 0x00009108
static inline uint32_t REG_A6XX_VPC_VARYING_INTERP(uint32_t i0) { return 0x00009200 + 0x1*i0; }
@@ -3385,6 +3943,9 @@ static inline uint32_t A6XX_VPC_CNTL_0_NUMNONPOSVAR(uint32_t val)
#define A6XX_VPC_SO_BUF_CNTL_BUF3 0x00000200
#define A6XX_VPC_SO_BUF_CNTL_ENABLE 0x00008000
+#define REG_A6XX_VPC_SO_OVERRIDE 0x00009306
+#define A6XX_VPC_SO_OVERRIDE_SO_DISABLE 0x00000001
+
#define REG_A6XX_VPC_UNKNOWN_9600 0x00009600
#define REG_A6XX_VPC_UNKNOWN_9602 0x00009602
@@ -3397,8 +3958,14 @@ static inline uint32_t A6XX_VPC_CNTL_0_NUMNONPOSVAR(uint32_t val)
#define REG_A6XX_PC_UNKNOWN_9805 0x00009805
+#define REG_A6XX_PC_UNKNOWN_9806 0x00009806
+
+#define REG_A6XX_PC_UNKNOWN_9980 0x00009980
+
#define REG_A6XX_PC_UNKNOWN_9981 0x00009981
+#define REG_A6XX_PC_UNKNOWN_9990 0x00009990
+
#define REG_A6XX_PC_PRIMITIVE_CNTL_0 0x00009b00
#define A6XX_PC_PRIMITIVE_CNTL_0_PRIMITIVE_RESTART 0x00000001
#define A6XX_PC_PRIMITIVE_CNTL_0_PROVOKING_VTX_LAST 0x00000002
@@ -3410,6 +3977,7 @@ static inline uint32_t A6XX_PC_PRIMITIVE_CNTL_1_STRIDE_IN_VPC(uint32_t val)
{
return ((val) << A6XX_PC_PRIMITIVE_CNTL_1_STRIDE_IN_VPC__SHIFT) & A6XX_PC_PRIMITIVE_CNTL_1_STRIDE_IN_VPC__MASK;
}
+#define A6XX_PC_PRIMITIVE_CNTL_1_PSIZE 0x00000100
#define REG_A6XX_PC_UNKNOWN_9B06 0x00009b06
@@ -3488,6 +4056,8 @@ static inline uint32_t A6XX_VFD_CONTROL_3_REGID_TESSY(uint32_t val)
#define REG_A6XX_VFD_UNKNOWN_A008 0x0000a008
+#define REG_A6XX_VFD_UNKNOWN_A009 0x0000a009
+
#define REG_A6XX_VFD_INDEX_OFFSET 0x0000a00e
#define REG_A6XX_VFD_INSTANCE_START_OFFSET 0x0000a00f
@@ -3640,6 +4210,8 @@ static inline uint32_t A6XX_SP_VS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
#define A6XX_SP_VS_CTRL_REG0_PIXLODENABLE 0x04000000
#define A6XX_SP_VS_CTRL_REG0_MERGEDREGS 0x80000000
+#define REG_A6XX_SP_UNKNOWN_A81B 0x0000a81b
+
#define REG_A6XX_SP_VS_OBJ_START_LO 0x0000a81c
#define REG_A6XX_SP_VS_OBJ_START_HI 0x0000a81d
@@ -3884,6 +4456,8 @@ static inline uint32_t A6XX_SP_FS_CTRL_REG0_THREADSIZE(enum a3xx_threadsize val)
#define A6XX_SP_FS_CTRL_REG0_PIXLODENABLE 0x04000000
#define A6XX_SP_FS_CTRL_REG0_MERGEDREGS 0x80000000
+#define REG_A6XX_SP_UNKNOWN_A982 0x0000a982
+
#define REG_A6XX_SP_FS_OBJ_START_LO 0x0000a983
#define REG_A6XX_SP_FS_OBJ_START_HI 0x0000a984
@@ -3979,7 +4553,8 @@ static inline uint32_t A6XX_SP_FS_MRT_REG_COLOR_FORMAT(enum a6xx_color_fmt val)
}
#define A6XX_SP_FS_MRT_REG_COLOR_SINT 0x00000100
#define A6XX_SP_FS_MRT_REG_COLOR_UINT 0x00000200
-#define A6XX_SP_FS_MRT_REG_COLOR_SRGB 0x00000400
+
+#define REG_A6XX_SP_UNKNOWN_A99E 0x0000a99e
#define REG_A6XX_SP_FS_TEX_COUNT 0x0000a9a7
@@ -4066,14 +4641,20 @@ static inline uint32_t A6XX_SP_FS_CONFIG_NSAMP(uint32_t val)
#define REG_A6XX_SP_FS_INSTRLEN 0x0000ab05
+#define REG_A6XX_SP_UNKNOWN_AB20 0x0000ab20
+
#define REG_A6XX_SP_UNKNOWN_AE00 0x0000ae00
+#define REG_A6XX_SP_UNKNOWN_AE03 0x0000ae03
+
#define REG_A6XX_SP_UNKNOWN_AE04 0x0000ae04
#define REG_A6XX_SP_UNKNOWN_AE0F 0x0000ae0f
#define REG_A6XX_SP_UNKNOWN_B182 0x0000b182
+#define REG_A6XX_SP_UNKNOWN_B183 0x0000b183
+
#define REG_A6XX_SP_TP_RAS_MSAA_CNTL 0x0000b300
#define A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES__MASK 0x00000003
#define A6XX_SP_TP_RAS_MSAA_CNTL_SAMPLES__SHIFT 0
@@ -4097,6 +4678,8 @@ static inline uint32_t A6XX_SP_TP_DEST_MSAA_CNTL_SAMPLES(enum a3xx_msaa_samples
#define REG_A6XX_SP_TP_UNKNOWN_B304 0x0000b304
+#define REG_A6XX_SP_TP_UNKNOWN_B309 0x0000b309
+
#define REG_A6XX_SP_PS_2D_SRC_INFO 0x0000b4c0
#define A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT__MASK 0x000000ff
#define A6XX_SP_PS_2D_SRC_INFO_COLOR_FORMAT__SHIFT 0
@@ -4162,6 +4745,8 @@ static inline uint32_t A6XX_HLSQ_GS_CNTL_CONSTLEN(uint32_t val)
return ((val >> 2) << A6XX_HLSQ_GS_CNTL_CONSTLEN__SHIFT) & A6XX_HLSQ_GS_CNTL_CONSTLEN__MASK;
}
+#define REG_A6XX_HLSQ_UNKNOWN_B980 0x0000b980
+
#define REG_A6XX_HLSQ_CONTROL_1_REG 0x0000b982
#define REG_A6XX_HLSQ_CONTROL_2_REG 0x0000b983
@@ -4537,11 +5122,11 @@ static inline uint32_t A6XX_TEX_CONST_7_FLAG_LO(uint32_t val)
}
#define REG_A6XX_TEX_CONST_8 0x00000008
-#define A6XX_TEX_CONST_8_BASE_HI__MASK 0x0001ffff
-#define A6XX_TEX_CONST_8_BASE_HI__SHIFT 0
-static inline uint32_t A6XX_TEX_CONST_8_BASE_HI(uint32_t val)
+#define A6XX_TEX_CONST_8_FLAG_HI__MASK 0x0001ffff
+#define A6XX_TEX_CONST_8_FLAG_HI__SHIFT 0
+static inline uint32_t A6XX_TEX_CONST_8_FLAG_HI(uint32_t val)
{
- return ((val) << A6XX_TEX_CONST_8_BASE_HI__SHIFT) & A6XX_TEX_CONST_8_BASE_HI__MASK;
+ return ((val) << A6XX_TEX_CONST_8_FLAG_HI__SHIFT) & A6XX_TEX_CONST_8_FLAG_HI__MASK;
}
#define REG_A6XX_TEX_CONST_9 0x00000009
@@ -4558,5 +5143,227 @@ static inline uint32_t A6XX_TEX_CONST_8_BASE_HI(uint32_t val)
#define REG_A6XX_TEX_CONST_15 0x0000000f
+#define REG_A6XX_PDC_GPU_ENABLE_PDC 0x00001140
+
+#define REG_A6XX_PDC_GPU_SEQ_START_ADDR 0x00001148
+
+#define REG_A6XX_PDC_GPU_TCS0_CONTROL 0x00001540
+
+#define REG_A6XX_PDC_GPU_TCS0_CMD_ENABLE_BANK 0x00001541
+
+#define REG_A6XX_PDC_GPU_TCS0_CMD_WAIT_FOR_CMPL_BANK 0x00001542
+
+#define REG_A6XX_PDC_GPU_TCS0_CMD0_MSGID 0x00001543
+
+#define REG_A6XX_PDC_GPU_TCS0_CMD0_ADDR 0x00001544
+
+#define REG_A6XX_PDC_GPU_TCS0_CMD0_DATA 0x00001545
+
+#define REG_A6XX_PDC_GPU_TCS1_CONTROL 0x00001572
+
+#define REG_A6XX_PDC_GPU_TCS1_CMD_ENABLE_BANK 0x00001573
+
+#define REG_A6XX_PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK 0x00001574
+
+#define REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID 0x00001575
+
+#define REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR 0x00001576
+
+#define REG_A6XX_PDC_GPU_TCS1_CMD0_DATA 0x00001577
+
+#define REG_A6XX_PDC_GPU_TCS2_CONTROL 0x000015a4
+
+#define REG_A6XX_PDC_GPU_TCS2_CMD_ENABLE_BANK 0x000015a5
+
+#define REG_A6XX_PDC_GPU_TCS2_CMD_WAIT_FOR_CMPL_BANK 0x000015a6
+
+#define REG_A6XX_PDC_GPU_TCS2_CMD0_MSGID 0x000015a7
+
+#define REG_A6XX_PDC_GPU_TCS2_CMD0_ADDR 0x000015a8
+
+#define REG_A6XX_PDC_GPU_TCS2_CMD0_DATA 0x000015a9
+
+#define REG_A6XX_PDC_GPU_TCS3_CONTROL 0x000015d6
+
+#define REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK 0x000015d7
+
+#define REG_A6XX_PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK 0x000015d8
+
+#define REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID 0x000015d9
+
+#define REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR 0x000015da
+
+#define REG_A6XX_PDC_GPU_TCS3_CMD0_DATA 0x000015db
+
+#define REG_A6XX_PDC_GPU_SEQ_MEM_0 0x00000000
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_A 0x00000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX__MASK 0x000000ff
+#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX__SHIFT 0
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_INDEX__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL__MASK 0x0000ff00
+#define A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL__SHIFT 8
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_SEL_A_PING_BLK_SEL__MASK;
+}
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_B 0x00000001
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_C 0x00000002
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_SEL_D 0x00000003
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLT 0x00000004
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__MASK 0x0000003f
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__SHIFT 0
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_TRACEEN__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__MASK 0x00007000
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__SHIFT 12
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_GRANU__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__MASK 0xf0000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__SHIFT 28
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLT_SEGT__MASK;
+}
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_CNTLM 0x00000005
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__MASK 0x0f000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__SHIFT 24
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_CNTLM_ENABLE__MASK;
+}
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_0 0x00000008
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_1 0x00000009
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_2 0x0000000a
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_IVTL_3 0x0000000b
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_0 0x0000000c
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_1 0x0000000d
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_2 0x0000000e
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_MASKL_3 0x0000000f
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0 0x00000010
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__MASK 0x0000000f
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__SHIFT 0
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL0__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__MASK 0x000000f0
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__SHIFT 4
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL1__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__MASK 0x00000f00
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__SHIFT 8
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL2__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__MASK 0x0000f000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__SHIFT 12
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL3__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__MASK 0x000f0000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__SHIFT 16
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL4__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__MASK 0x00f00000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__SHIFT 20
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL5__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__MASK 0x0f000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__SHIFT 24
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL6__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__MASK 0xf0000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__SHIFT 28
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_0_BYTEL7__MASK;
+}
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1 0x00000011
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__MASK 0x0000000f
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__SHIFT 0
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL8__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__MASK 0x000000f0
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__SHIFT 4
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL9__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__MASK 0x00000f00
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__SHIFT 8
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL10__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__MASK 0x0000f000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__SHIFT 12
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL11__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__MASK 0x000f0000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__SHIFT 16
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL12__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__MASK 0x00f00000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__SHIFT 20
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL13__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__MASK 0x0f000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__SHIFT 24
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL14__MASK;
+}
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__MASK 0xf0000000
+#define A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__SHIFT 28
+static inline uint32_t A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15(uint32_t val)
+{
+ return ((val) << A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__SHIFT) & A6XX_CX_DBGC_CFG_DBGBUS_BYTEL_1_BYTEL15__MASK;
+}
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF1 0x0000002f
+
+#define REG_A6XX_CX_DBGC_CFG_DBGBUS_TRACE_BUF2 0x00000030
+
#endif /* A6XX_XML */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index bbb8126ec5c5..d4e98e5876bc 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -2,7 +2,6 @@
/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. */
#include <linux/clk.h>
-#include <linux/iopoll.h>
#include <linux/pm_opp.h>
#include <soc/qcom/cmd-db.h>
@@ -42,9 +41,6 @@ static irqreturn_t a6xx_hfi_irq(int irq, void *data)
status = gmu_read(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO);
gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR, status);
- if (status & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ)
- tasklet_schedule(&gmu->hfi_tasklet);
-
if (status & A6XX_GMU_GMU2HOST_INTR_INFO_CM3_FAULT) {
dev_err_ratelimited(gmu->dev, "GMU firmware fault\n");
@@ -65,12 +61,14 @@ static bool a6xx_gmu_gx_is_on(struct a6xx_gmu *gmu)
A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_CLK_OFF));
}
-static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
+static void __a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
{
+ int ret;
+
gmu_write(gmu, REG_A6XX_GMU_DCVS_ACK_OPTION, 0);
gmu_write(gmu, REG_A6XX_GMU_DCVS_PERF_SETTING,
- ((index << 24) & 0xff) | (3 & 0xf));
+ ((3 & 0xf) << 28) | index);
/*
* Send an invalid index as a vote for the bus bandwidth and let the
@@ -82,7 +80,37 @@ static int a6xx_gmu_set_freq(struct a6xx_gmu *gmu, int index)
a6xx_gmu_set_oob(gmu, GMU_OOB_DCVS_SET);
a6xx_gmu_clear_oob(gmu, GMU_OOB_DCVS_SET);
- return gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN);
+ ret = gmu_read(gmu, REG_A6XX_GMU_DCVS_RETURN);
+ if (ret)
+ dev_err(gmu->dev, "GMU set GPU frequency error: %d\n", ret);
+
+ gmu->freq = gmu->gpu_freqs[index];
+}
+
+void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+ u32 perf_index = 0;
+
+ if (freq == gmu->freq)
+ return;
+
+ for (perf_index = 0; perf_index < gmu->nr_gpu_freqs - 1; perf_index++)
+ if (freq == gmu->gpu_freqs[perf_index])
+ break;
+
+ __a6xx_gmu_set_freq(gmu, perf_index);
+}
+
+unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ struct a6xx_gmu *gmu = &a6xx_gpu->gmu;
+
+ return gmu->freq;
}
static bool a6xx_gmu_check_idle_level(struct a6xx_gmu *gmu)
@@ -135,9 +163,6 @@ static int a6xx_gmu_hfi_start(struct a6xx_gmu *gmu)
u32 val;
int ret;
- gmu_rmw(gmu, REG_A6XX_GMU_GMU2HOST_INTR_MASK,
- A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 0);
-
gmu_write(gmu, REG_A6XX_GMU_HFI_CTRL_INIT, 1);
ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_HFI_CTRL_STATUS, val,
@@ -348,8 +373,23 @@ static void a6xx_rpmh_stop(struct a6xx_gmu *gmu)
gmu_write(gmu, REG_A6XX_GMU_RSCC_CONTROL_REQ, 0);
}
+static inline void pdc_write(void __iomem *ptr, u32 offset, u32 value)
+{
+ return msm_writel(value, ptr + (offset << 2));
+}
+
+static void __iomem *a6xx_gmu_get_mmio(struct platform_device *pdev,
+ const char *name);
+
static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
{
+ struct platform_device *pdev = to_platform_device(gmu->dev);
+ void __iomem *pdcptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc");
+ void __iomem *seqptr = a6xx_gmu_get_mmio(pdev, "gmu_pdc_seq");
+
+ if (!pdcptr || !seqptr)
+ goto err;
+
/* Disable SDE clock gating */
gmu_write(gmu, REG_A6XX_GPU_RSCC_RSC_STATUS0_DRV0, BIT(24));
@@ -374,44 +414,48 @@ static void a6xx_gmu_rpmh_init(struct a6xx_gmu *gmu)
gmu_write(gmu, REG_A6XX_RSCC_SEQ_MEM_0_DRV0 + 4, 0x0020e8a8);
/* Load PDC sequencer uCode for power up and power down sequence */
- pdc_write(gmu, REG_A6XX_PDC_GPU_SEQ_MEM_0, 0xfebea1e1);
- pdc_write(gmu, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 1, 0xa5a4a3a2);
- pdc_write(gmu, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 2, 0x8382a6e0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 3, 0xbce3e284);
- pdc_write(gmu, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 4, 0x002081fc);
+ pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0, 0xfebea1e1);
+ pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 1, 0xa5a4a3a2);
+ pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 2, 0x8382a6e0);
+ pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 3, 0xbce3e284);
+ pdc_write(seqptr, REG_A6XX_PDC_GPU_SEQ_MEM_0 + 4, 0x002081fc);
/* Set TCS commands used by PDC sequence for low power modes */
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD_ENABLE_BANK, 7);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK, 0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CONTROL, 0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID, 0x10108);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR, 0x30010);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA, 1);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 4, 0x10108);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 4, 0x30000);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30080);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK, 0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CONTROL, 0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID, 0x10108);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR, 0x30010);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA, 2);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30080);
- pdc_write(gmu, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD_ENABLE_BANK, 7);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD_WAIT_FOR_CMPL_BANK, 0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CONTROL, 0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID, 0x10108);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR, 0x30010);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA, 1);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 4, 0x10108);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 4, 0x30000);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 4, 0x0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_MSGID + 8, 0x10108);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_ADDR + 8, 0x30080);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS1_CMD0_DATA + 8, 0x0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_ENABLE_BANK, 7);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD_WAIT_FOR_CMPL_BANK, 0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CONTROL, 0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID, 0x10108);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR, 0x30010);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA, 2);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 4, 0x10108);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 4, 0x30000);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 4, 0x3);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_MSGID + 8, 0x10108);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_ADDR + 8, 0x30080);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_TCS3_CMD0_DATA + 8, 0x3);
/* Setup GPU PDC */
- pdc_write(gmu, REG_A6XX_PDC_GPU_SEQ_START_ADDR, 0);
- pdc_write(gmu, REG_A6XX_PDC_GPU_ENABLE_PDC, 0x80000001);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_SEQ_START_ADDR, 0);
+ pdc_write(pdcptr, REG_A6XX_PDC_GPU_ENABLE_PDC, 0x80000001);
/* ensure no writes happen before the uCode is fully written */
wmb();
+
+err:
+ devm_iounmap(gmu->dev, pdcptr);
+ devm_iounmap(gmu->dev, seqptr);
}
/*
@@ -547,8 +591,7 @@ static int a6xx_gmu_fw_start(struct a6xx_gmu *gmu, unsigned int state)
}
#define A6XX_HFI_IRQ_MASK \
- (A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ | \
- A6XX_GMU_GMU2HOST_INTR_INFO_CM3_FAULT)
+ (A6XX_GMU_GMU2HOST_INTR_INFO_CM3_FAULT)
#define A6XX_GMU_IRQ_MASK \
(A6XX_GMU_AO_HOST_INTERRUPT_STATUS_WDOG_BITE | \
@@ -626,7 +669,7 @@ int a6xx_gmu_reset(struct a6xx_gpu *a6xx_gpu)
ret = a6xx_hfi_start(gmu, GMU_COLD_BOOT);
/* Set the GPU back to the highest power frequency */
- a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
+ __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
out:
if (ret)
@@ -665,7 +708,7 @@ int a6xx_gmu_resume(struct a6xx_gpu *a6xx_gpu)
ret = a6xx_hfi_start(gmu, status);
/* Set the GPU to the highest power frequency */
- a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
+ __a6xx_gmu_set_freq(gmu, gmu->nr_gpu_freqs - 1);
out:
/* Make sure to turn off the boot OOB request on error */
@@ -1140,7 +1183,7 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
gmu->dev = &pdev->dev;
- of_dma_configure(gmu->dev, node, false);
+ of_dma_configure(gmu->dev, node, true);
/* Fow now, don't do anything fancy until we get our feet under us */
gmu->idle_level = GMU_IDLE_STATE_ACTIVE;
@@ -1170,11 +1213,7 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
/* Map the GMU registers */
gmu->mmio = a6xx_gmu_get_mmio(pdev, "gmu");
-
- /* Map the GPU power domain controller registers */
- gmu->pdc_mmio = a6xx_gmu_get_mmio(pdev, "gmu_pdc");
-
- if (IS_ERR(gmu->mmio) || IS_ERR(gmu->pdc_mmio))
+ if (IS_ERR(gmu->mmio))
goto err;
/* Get the HFI and GMU interrupts */
@@ -1184,9 +1223,6 @@ int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node)
if (gmu->hfi_irq < 0 || gmu->gmu_irq < 0)
goto err;
- /* Set up a tasklet to handle GMU HFI responses */
- tasklet_init(&gmu->hfi_tasklet, a6xx_hfi_task, (unsigned long) gmu);
-
/* Get the power levels for the GMU and GPU */
a6xx_gmu_pwrlevels_probe(gmu);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
index d9a386c18799..35f765afae45 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h
@@ -4,6 +4,7 @@
#ifndef _A6XX_GMU_H_
#define _A6XX_GMU_H_
+#include <linux/iopoll.h>
#include <linux/interrupt.h>
#include "msm_drv.h"
#include "a6xx_hfi.h"
@@ -47,7 +48,6 @@ struct a6xx_gmu {
struct device *dev;
void * __iomem mmio;
- void * __iomem pdc_mmio;
int hfi_irq;
int gmu_irq;
@@ -74,6 +74,8 @@ struct a6xx_gmu {
unsigned long gmu_freqs[4];
u32 cx_arc_votes[4];
+ unsigned long freq;
+
struct a6xx_hfi_queue queues[2];
struct tasklet_struct hfi_tasklet;
@@ -89,11 +91,6 @@ static inline void gmu_write(struct a6xx_gmu *gmu, u32 offset, u32 value)
return msm_writel(value, gmu->mmio + (offset << 2));
}
-static inline void pdc_write(struct a6xx_gmu *gmu, u32 offset, u32 value)
-{
- return msm_writel(value, gmu->pdc_mmio + (offset << 2));
-}
-
static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or)
{
u32 val = gmu_read(gmu, reg);
@@ -103,6 +100,16 @@ static inline void gmu_rmw(struct a6xx_gmu *gmu, u32 reg, u32 mask, u32 or)
gmu_write(gmu, reg, val | or);
}
+static inline u64 gmu_read64(struct a6xx_gmu *gmu, u32 lo, u32 hi)
+{
+ u64 val;
+
+ val = (u64) msm_readl(gmu->mmio + (lo << 2));
+ val |= ((u64) msm_readl(gmu->mmio + (hi << 2)) << 32);
+
+ return val;
+}
+
#define gmu_poll_timeout(gmu, addr, val, cond, interval, timeout) \
readl_poll_timeout((gmu)->mmio + ((addr) << 2), val, cond, \
interval, timeout)
@@ -157,6 +164,4 @@ void a6xx_hfi_init(struct a6xx_gmu *gmu);
int a6xx_hfi_start(struct a6xx_gmu *gmu, int boot_state);
void a6xx_hfi_stop(struct a6xx_gmu *gmu);
-void a6xx_hfi_task(unsigned long data);
-
#endif
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
index ef68098d2adc..db56f263ed77 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
@@ -167,8 +167,8 @@ static inline uint32_t A6XX_GMU_PWR_COL_INTER_FRAME_CTRL_MIN_PASS_LENGTH(uint32_
#define REG_A6XX_GMU_SPTPRAC_PWR_CLK_STATUS 0x000050d0
#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWERING_OFF 0x00000001
#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWERING_ON 0x00000002
-#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_ON 0x00000004
-#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_OFF 0x00000008
+#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_OFF 0x00000004
+#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SPTPRAC_GDSC_POWER_ON 0x00000008
#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_SP_CLOCK_OFF 0x00000010
#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GMU_UP_POWER_STATE 0x00000020
#define A6XX_GMU_SPTPRAC_PWR_CLK_STATUS_GX_HM_GDSC_POWER_OFF 0x00000040
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index c629f742a1d1..631257c297fd 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -7,6 +7,8 @@
#include "a6xx_gpu.h"
#include "a6xx_gmu.xml.h"
+#include <linux/devfreq.h>
+
static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -438,10 +440,8 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A6XX_CP_PROTECT(22), A6XX_PROTECT_RW(0x900, 0x4d));
gpu_write(gpu, REG_A6XX_CP_PROTECT(23), A6XX_PROTECT_RW(0x98d, 0x76));
gpu_write(gpu, REG_A6XX_CP_PROTECT(24),
- A6XX_PROTECT_RDONLY(0x8d0, 0x23));
- gpu_write(gpu, REG_A6XX_CP_PROTECT(25),
A6XX_PROTECT_RDONLY(0x980, 0x4));
- gpu_write(gpu, REG_A6XX_CP_PROTECT(26), A6XX_PROTECT_RW(0xa630, 0x0));
+ gpu_write(gpu, REG_A6XX_CP_PROTECT(25), A6XX_PROTECT_RW(0xa630, 0x0));
/* Enable interrupts */
gpu_write(gpu, REG_A6XX_RBBM_INT_0_MASK, A6XX_INT_MASK);
@@ -682,6 +682,8 @@ static int a6xx_pm_resume(struct msm_gpu *gpu)
gpu->needs_hw_init = true;
+ msm_gpu_resume_devfreq(gpu);
+
return ret;
}
@@ -690,6 +692,8 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu)
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ devfreq_suspend_device(gpu->devfreq.devfreq);
+
/*
* Make sure the GMU is idle before continuing (because some transitions
* may use VBIF
@@ -744,7 +748,7 @@ static void a6xx_destroy(struct msm_gpu *gpu)
if (a6xx_gpu->sqe_bo) {
if (a6xx_gpu->sqe_iova)
msm_gem_put_iova(a6xx_gpu->sqe_bo, gpu->aspace);
- drm_gem_object_unreference_unlocked(a6xx_gpu->sqe_bo);
+ drm_gem_object_put_unlocked(a6xx_gpu->sqe_bo);
}
a6xx_gmu_remove(a6xx_gpu);
@@ -753,6 +757,27 @@ static void a6xx_destroy(struct msm_gpu *gpu)
kfree(a6xx_gpu);
}
+static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
+ u64 busy_cycles, busy_time;
+
+ busy_cycles = gmu_read64(&a6xx_gpu->gmu,
+ REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_L,
+ REG_A6XX_GMU_CX_GMU_POWER_COUNTER_XOCLK_0_H);
+
+ busy_time = (busy_cycles - gpu->devfreq.busy_cycles) * 10;
+ do_div(busy_time, 192);
+
+ gpu->devfreq.busy_cycles = busy_cycles;
+
+ if (WARN_ON(busy_time > ~0LU))
+ return ~0LU;
+
+ return (unsigned long)busy_time;
+}
+
static const struct adreno_gpu_funcs funcs = {
.base = {
.get_param = adreno_get_param,
@@ -768,6 +793,9 @@ static const struct adreno_gpu_funcs funcs = {
#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
.show = a6xx_show,
#endif
+ .gpu_busy = a6xx_gpu_busy,
+ .gpu_get_freq = a6xx_gmu_get_freq,
+ .gpu_set_freq = a6xx_gmu_set_freq,
},
.get_timestamp = a6xx_get_timestamp,
};
@@ -799,7 +827,7 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
}
/* Check if there is a GMU phandle and set it up */
- node = of_parse_phandle(pdev->dev.of_node, "gmu", 0);
+ node = of_parse_phandle(pdev->dev.of_node, "qcom,gmu", 0);
/* FIXME: How do we gracefully handle this? */
BUG_ON(!node);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
index dd69e5b0e692..4127dcebc202 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.h
@@ -56,5 +56,6 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state);
int a6xx_gmu_probe(struct a6xx_gpu *a6xx_gpu, struct device_node *node);
void a6xx_gmu_remove(struct a6xx_gpu *a6xx_gpu);
-
+void a6xx_gmu_set_freq(struct msm_gpu *gpu, unsigned long freq);
+unsigned long a6xx_gmu_get_freq(struct msm_gpu *gpu);
#endif /* __A6XX_GPU_H__ */
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
index f19ef4cb6ea4..6ff9baec2658 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_hfi.c
@@ -79,83 +79,72 @@ static int a6xx_hfi_queue_write(struct a6xx_gmu *gmu,
return 0;
}
-struct a6xx_hfi_response {
- u32 id;
- u32 seqnum;
- struct list_head node;
- struct completion complete;
-
- u32 error;
- u32 payload[16];
-};
+static int a6xx_hfi_wait_for_ack(struct a6xx_gmu *gmu, u32 id, u32 seqnum,
+ u32 *payload, u32 payload_size)
+{
+ struct a6xx_hfi_queue *queue = &gmu->queues[HFI_RESPONSE_QUEUE];
+ u32 val;
+ int ret;
-/*
- * Incoming HFI ack messages can come in out of order so we need to store all
- * the pending messages on a list until they are handled.
- */
-static spinlock_t hfi_ack_lock = __SPIN_LOCK_UNLOCKED(message_lock);
-static LIST_HEAD(hfi_ack_list);
+ /* Wait for a response */
+ ret = gmu_poll_timeout(gmu, REG_A6XX_GMU_GMU2HOST_INTR_INFO, val,
+ val & A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ, 100, 5000);
-static void a6xx_hfi_handle_ack(struct a6xx_gmu *gmu,
- struct a6xx_hfi_msg_response *msg)
-{
- struct a6xx_hfi_response *resp;
- u32 id, seqnum;
-
- /* msg->ret_header contains the header of the message being acked */
- id = HFI_HEADER_ID(msg->ret_header);
- seqnum = HFI_HEADER_SEQNUM(msg->ret_header);
-
- spin_lock(&hfi_ack_lock);
- list_for_each_entry(resp, &hfi_ack_list, node) {
- if (resp->id == id && resp->seqnum == seqnum) {
- resp->error = msg->error;
- memcpy(resp->payload, msg->payload,
- sizeof(resp->payload));
-
- complete(&resp->complete);
- spin_unlock(&hfi_ack_lock);
- return;
- }
+ if (ret) {
+ dev_err(gmu->dev,
+ "Message %s id %d timed out waiting for response\n",
+ a6xx_hfi_msg_id[id], seqnum);
+ return -ETIMEDOUT;
}
- spin_unlock(&hfi_ack_lock);
- dev_err(gmu->dev, "Nobody was waiting for HFI message %d\n", seqnum);
-}
+ /* Clear the interrupt */
+ gmu_write(gmu, REG_A6XX_GMU_GMU2HOST_INTR_CLR,
+ A6XX_GMU_GMU2HOST_INTR_INFO_MSGQ);
-static void a6xx_hfi_handle_error(struct a6xx_gmu *gmu,
- struct a6xx_hfi_msg_response *msg)
-{
- struct a6xx_hfi_msg_error *error = (struct a6xx_hfi_msg_error *) msg;
+ for (;;) {
+ struct a6xx_hfi_msg_response resp;
- dev_err(gmu->dev, "GMU firmware error %d\n", error->code);
-}
+ /* Get the next packet */
+ ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,
+ sizeof(resp) >> 2);
-void a6xx_hfi_task(unsigned long data)
-{
- struct a6xx_gmu *gmu = (struct a6xx_gmu *) data;
- struct a6xx_hfi_queue *queue = &gmu->queues[HFI_RESPONSE_QUEUE];
- struct a6xx_hfi_msg_response resp;
+ /* If the queue is empty our response never made it */
+ if (!ret) {
+ dev_err(gmu->dev,
+ "The HFI response queue is unexpectedly empty\n");
- for (;;) {
- u32 id;
- int ret = a6xx_hfi_queue_read(queue, (u32 *) &resp,
- sizeof(resp) >> 2);
+ return -ENOENT;
+ }
+
+ if (HFI_HEADER_ID(resp.header) == HFI_F2H_MSG_ERROR) {
+ struct a6xx_hfi_msg_error *error =
+ (struct a6xx_hfi_msg_error *) &resp;
- /* Returns the number of bytes copied or negative on error */
- if (ret <= 0) {
- if (ret < 0)
- dev_err(gmu->dev,
- "Unable to read the HFI message queue\n");
- break;
+ dev_err(gmu->dev, "GMU firmware error %d\n",
+ error->code);
+ continue;
+ }
+
+ if (seqnum != HFI_HEADER_SEQNUM(resp.ret_header)) {
+ dev_err(gmu->dev,
+ "Unexpected message id %d on the response queue\n",
+ HFI_HEADER_SEQNUM(resp.ret_header));
+ continue;
+ }
+
+ if (resp.error) {
+ dev_err(gmu->dev,
+ "Message %s id %d returned error %d\n",
+ a6xx_hfi_msg_id[id], seqnum, resp.error);
+ return -EINVAL;
}
- id = HFI_HEADER_ID(resp.header);
+ /* All is well, copy over the buffer */
+ if (payload && payload_size)
+ memcpy(payload, resp.payload,
+ min_t(u32, payload_size, sizeof(resp.payload)));
- if (id == HFI_F2H_MSG_ACK)
- a6xx_hfi_handle_ack(gmu, &resp);
- else if (id == HFI_F2H_MSG_ERROR)
- a6xx_hfi_handle_error(gmu, &resp);
+ return 0;
}
}
@@ -163,7 +152,6 @@ static int a6xx_hfi_send_msg(struct a6xx_gmu *gmu, int id,
void *data, u32 size, u32 *payload, u32 payload_size)
{
struct a6xx_hfi_queue *queue = &gmu->queues[HFI_COMMAND_QUEUE];
- struct a6xx_hfi_response resp = { 0 };
int ret, dwords = size >> 2;
u32 seqnum;
@@ -173,53 +161,14 @@ static int a6xx_hfi_send_msg(struct a6xx_gmu *gmu, int id,
*((u32 *) data) = (seqnum << 20) | (HFI_MSG_CMD << 16) |
(dwords << 8) | id;
- init_completion(&resp.complete);
- resp.id = id;
- resp.seqnum = seqnum;
-
- spin_lock_bh(&hfi_ack_lock);
- list_add_tail(&resp.node, &hfi_ack_list);
- spin_unlock_bh(&hfi_ack_lock);
-
ret = a6xx_hfi_queue_write(gmu, queue, data, dwords);
if (ret) {
dev_err(gmu->dev, "Unable to send message %s id %d\n",
a6xx_hfi_msg_id[id], seqnum);
- goto out;
- }
-
- /* Wait up to 5 seconds for the response */
- ret = wait_for_completion_timeout(&resp.complete,
- msecs_to_jiffies(5000));
- if (!ret) {
- dev_err(gmu->dev,
- "Message %s id %d timed out waiting for response\n",
- a6xx_hfi_msg_id[id], seqnum);
- ret = -ETIMEDOUT;
- } else
- ret = 0;
-
-out:
- spin_lock_bh(&hfi_ack_lock);
- list_del(&resp.node);
- spin_unlock_bh(&hfi_ack_lock);
-
- if (ret)
return ret;
-
- if (resp.error) {
- dev_err(gmu->dev, "Message %s id %d returned error %d\n",
- a6xx_hfi_msg_id[id], seqnum, resp.error);
- return -EINVAL;
}
- if (payload && payload_size) {
- int copy = min_t(u32, payload_size, sizeof(resp.payload));
-
- memcpy(payload, resp.payload, copy);
- }
-
- return 0;
+ return a6xx_hfi_wait_for_ack(gmu, id, seqnum, payload, payload_size);
}
static int a6xx_hfi_send_gmu_init(struct a6xx_gmu *gmu, int boot_state)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index 5dace1350810..1318959d504d 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 7d3e9a129ac7..86abdb2b3a9c 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -120,6 +120,7 @@ static const struct adreno_info gpulist[] = {
[ADRENO_FW_GMU] = "a630_gmu.bin",
},
.gmem = SZ_1M,
+ .inactive_period = DRM_MSM_INACTIVE_PERIOD,
.init = a6xx_gpu_init,
},
};
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 03a91e10b310..15eb03bed984 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -12,12 +12,12 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/envytools/rnndb/freedreno_copyright.xml ( 1572 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a2xx.xml ( 36805 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/adreno_common.xml ( 13634 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42393 bytes, from 2018-08-06 18:45:45)
+- /home/robclark/src/envytools/rnndb/adreno/adreno_pm4.xml ( 42585 bytes, from 2018-10-04 19:06:37)
- /home/robclark/src/envytools/rnndb/adreno/a3xx.xml ( 83840 bytes, from 2018-07-03 19:37:13)
- /home/robclark/src/envytools/rnndb/adreno/a4xx.xml ( 112086 bytes, from 2018-07-03 19:37:13)
-- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 101627 bytes, from 2018-08-06 18:45:45)
-- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-07-03 19:37:13)
+- /home/robclark/src/envytools/rnndb/adreno/a5xx.xml ( 147240 bytes, from 2018-10-04 19:06:37)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx.xml ( 139581 bytes, from 2018-10-04 19:06:42)
+- /home/robclark/src/envytools/rnndb/adreno/a6xx_gmu.xml ( 10431 bytes, from 2018-09-14 13:03:07)
- /home/robclark/src/envytools/rnndb/adreno/ocmem.xml ( 1773 bytes, from 2018-07-03 19:37:13)
Copyright (C) 2013-2018 by the following authors:
@@ -237,7 +237,7 @@ enum adreno_pm4_type3_packets {
CP_UNK_A6XX_14 = 20,
CP_UNK_A6XX_36 = 54,
CP_UNK_A6XX_55 = 85,
- UNK_A6XX_6D = 109,
+ CP_REG_WRITE = 109,
};
enum adreno_state_block {
@@ -968,19 +968,19 @@ static inline uint32_t CP_SET_BIN_DATA5_4_BIN_SIZE_ADDRESS_HI(uint32_t val)
}
#define REG_CP_SET_BIN_DATA5_5 0x00000005
-#define CP_SET_BIN_DATA5_5_XXX_ADDRESS_LO__MASK 0xffffffff
-#define CP_SET_BIN_DATA5_5_XXX_ADDRESS_LO__SHIFT 0
-static inline uint32_t CP_SET_BIN_DATA5_5_XXX_ADDRESS_LO(uint32_t val)
+#define CP_SET_BIN_DATA5_5_BIN_DATA_ADDR2_LO__MASK 0xffffffff
+#define CP_SET_BIN_DATA5_5_BIN_DATA_ADDR2_LO__SHIFT 0
+static inline uint32_t CP_SET_BIN_DATA5_5_BIN_DATA_ADDR2_LO(uint32_t val)
{
- return ((val) << CP_SET_BIN_DATA5_5_XXX_ADDRESS_LO__SHIFT) & CP_SET_BIN_DATA5_5_XXX_ADDRESS_LO__MASK;
+ return ((val) << CP_SET_BIN_DATA5_5_BIN_DATA_ADDR2_LO__SHIFT) & CP_SET_BIN_DATA5_5_BIN_DATA_ADDR2_LO__MASK;
}
#define REG_CP_SET_BIN_DATA5_6 0x00000006
-#define CP_SET_BIN_DATA5_6_XXX_ADDRESS_HI__MASK 0xffffffff
-#define CP_SET_BIN_DATA5_6_XXX_ADDRESS_HI__SHIFT 0
-static inline uint32_t CP_SET_BIN_DATA5_6_XXX_ADDRESS_HI(uint32_t val)
+#define CP_SET_BIN_DATA5_6_BIN_DATA_ADDR2_LO__MASK 0xffffffff
+#define CP_SET_BIN_DATA5_6_BIN_DATA_ADDR2_LO__SHIFT 0
+static inline uint32_t CP_SET_BIN_DATA5_6_BIN_DATA_ADDR2_LO(uint32_t val)
{
- return ((val) << CP_SET_BIN_DATA5_6_XXX_ADDRESS_HI__SHIFT) & CP_SET_BIN_DATA5_6_XXX_ADDRESS_HI__MASK;
+ return ((val) << CP_SET_BIN_DATA5_6_BIN_DATA_ADDR2_LO__SHIFT) & CP_SET_BIN_DATA5_6_BIN_DATA_ADDR2_LO__MASK;
}
#define REG_CP_REG_TO_MEM_0 0x00000000
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 80cbf75bc2ff..d4530d60767b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -47,237 +47,17 @@
#define LEFT_MIXER 0
#define RIGHT_MIXER 1
-#define MISR_BUFF_SIZE 256
-
-static inline struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
-{
- struct msm_drm_private *priv;
-
- if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
- DPU_ERROR("invalid crtc\n");
- return NULL;
- }
- priv = crtc->dev->dev_private;
- if (!priv || !priv->kms) {
- DPU_ERROR("invalid kms\n");
- return NULL;
- }
-
- return to_dpu_kms(priv->kms);
-}
-
-static inline int _dpu_crtc_power_enable(struct dpu_crtc *dpu_crtc, bool enable)
-{
- struct drm_crtc *crtc;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
-
- if (!dpu_crtc) {
- DPU_ERROR("invalid dpu crtc\n");
- return -EINVAL;
- }
-
- crtc = &dpu_crtc->base;
- if (!crtc->dev || !crtc->dev->dev_private) {
- DPU_ERROR("invalid drm device\n");
- return -EINVAL;
- }
-
- priv = crtc->dev->dev_private;
- if (!priv->kms) {
- DPU_ERROR("invalid kms\n");
- return -EINVAL;
- }
-
- dpu_kms = to_dpu_kms(priv->kms);
-
- if (enable)
- pm_runtime_get_sync(&dpu_kms->pdev->dev);
- else
- pm_runtime_put_sync(&dpu_kms->pdev->dev);
-
- return 0;
-}
-
-/**
- * _dpu_crtc_rp_to_crtc - get crtc from resource pool object
- * @rp: Pointer to resource pool
- * return: Pointer to drm crtc if success; null otherwise
- */
-static struct drm_crtc *_dpu_crtc_rp_to_crtc(struct dpu_crtc_respool *rp)
-{
- if (!rp)
- return NULL;
-
- return container_of(rp, struct dpu_crtc_state, rp)->base.crtc;
-}
-
-/**
- * _dpu_crtc_rp_reclaim - reclaim unused, or all if forced, resources in pool
- * @rp: Pointer to resource pool
- * @force: True to reclaim all resources; otherwise, reclaim only unused ones
- * return: None
- */
-static void _dpu_crtc_rp_reclaim(struct dpu_crtc_respool *rp, bool force)
+static inline int _dpu_crtc_get_mixer_width(struct dpu_crtc_state *cstate,
+ struct drm_display_mode *mode)
{
- struct dpu_crtc_res *res, *next;
- struct drm_crtc *crtc;
-
- crtc = _dpu_crtc_rp_to_crtc(rp);
- if (!crtc) {
- DPU_ERROR("invalid crtc\n");
- return;
- }
-
- DPU_DEBUG("crtc%d.%u %s\n", crtc->base.id, rp->sequence_id,
- force ? "destroy" : "free_unused");
-
- list_for_each_entry_safe(res, next, &rp->res_list, list) {
- if (!force && !(res->flags & DPU_CRTC_RES_FLAG_FREE))
- continue;
- DPU_DEBUG("crtc%d.%u reclaim res:0x%x/0x%llx/%pK/%d\n",
- crtc->base.id, rp->sequence_id,
- res->type, res->tag, res->val,
- atomic_read(&res->refcount));
- list_del(&res->list);
- if (res->ops.put)
- res->ops.put(res->val);
- kfree(res);
- }
+ return mode->hdisplay / cstate->num_mixers;
}
-/**
- * _dpu_crtc_rp_free_unused - free unused resource in pool
- * @rp: Pointer to resource pool
- * return: none
- */
-static void _dpu_crtc_rp_free_unused(struct dpu_crtc_respool *rp)
-{
- mutex_lock(rp->rp_lock);
- _dpu_crtc_rp_reclaim(rp, false);
- mutex_unlock(rp->rp_lock);
-}
-
-/**
- * _dpu_crtc_rp_destroy - destroy resource pool
- * @rp: Pointer to resource pool
- * return: None
- */
-static void _dpu_crtc_rp_destroy(struct dpu_crtc_respool *rp)
-{
- mutex_lock(rp->rp_lock);
- list_del_init(&rp->rp_list);
- _dpu_crtc_rp_reclaim(rp, true);
- mutex_unlock(rp->rp_lock);
-}
-
-/**
- * _dpu_crtc_hw_blk_get - get callback for hardware block
- * @val: Resource handle
- * @type: Resource type
- * @tag: Search tag for given resource
- * return: Resource handle
- */
-static void *_dpu_crtc_hw_blk_get(void *val, u32 type, u64 tag)
-{
- DPU_DEBUG("res:%d/0x%llx/%pK\n", type, tag, val);
- return dpu_hw_blk_get(val, type, tag);
-}
-
-/**
- * _dpu_crtc_hw_blk_put - put callback for hardware block
- * @val: Resource handle
- * return: None
- */
-static void _dpu_crtc_hw_blk_put(void *val)
-{
- DPU_DEBUG("res://%pK\n", val);
- dpu_hw_blk_put(val);
-}
-
-/**
- * _dpu_crtc_rp_duplicate - duplicate resource pool and reset reference count
- * @rp: Pointer to original resource pool
- * @dup_rp: Pointer to duplicated resource pool
- * return: None
- */
-static void _dpu_crtc_rp_duplicate(struct dpu_crtc_respool *rp,
- struct dpu_crtc_respool *dup_rp)
-{
- struct dpu_crtc_res *res, *dup_res;
- struct drm_crtc *crtc;
-
- if (!rp || !dup_rp || !rp->rp_head) {
- DPU_ERROR("invalid resource pool\n");
- return;
- }
-
- crtc = _dpu_crtc_rp_to_crtc(rp);
- if (!crtc) {
- DPU_ERROR("invalid crtc\n");
- return;
- }
-
- DPU_DEBUG("crtc%d.%u duplicate\n", crtc->base.id, rp->sequence_id);
-
- mutex_lock(rp->rp_lock);
- dup_rp->sequence_id = rp->sequence_id + 1;
- INIT_LIST_HEAD(&dup_rp->res_list);
- dup_rp->ops = rp->ops;
- list_for_each_entry(res, &rp->res_list, list) {
- dup_res = kzalloc(sizeof(struct dpu_crtc_res), GFP_KERNEL);
- if (!dup_res) {
- mutex_unlock(rp->rp_lock);
- return;
- }
- INIT_LIST_HEAD(&dup_res->list);
- atomic_set(&dup_res->refcount, 0);
- dup_res->type = res->type;
- dup_res->tag = res->tag;
- dup_res->val = res->val;
- dup_res->ops = res->ops;
- dup_res->flags = DPU_CRTC_RES_FLAG_FREE;
- DPU_DEBUG("crtc%d.%u dup res:0x%x/0x%llx/%pK/%d\n",
- crtc->base.id, dup_rp->sequence_id,
- dup_res->type, dup_res->tag, dup_res->val,
- atomic_read(&dup_res->refcount));
- list_add_tail(&dup_res->list, &dup_rp->res_list);
- if (dup_res->ops.get)
- dup_res->ops.get(dup_res->val, 0, -1);
- }
-
- dup_rp->rp_lock = rp->rp_lock;
- dup_rp->rp_head = rp->rp_head;
- INIT_LIST_HEAD(&dup_rp->rp_list);
- list_add_tail(&dup_rp->rp_list, rp->rp_head);
- mutex_unlock(rp->rp_lock);
-}
-
-/**
- * _dpu_crtc_rp_reset - reset resource pool after allocation
- * @rp: Pointer to original resource pool
- * @rp_lock: Pointer to serialization resource pool lock
- * @rp_head: Pointer to crtc resource pool head
- * return: None
- */
-static void _dpu_crtc_rp_reset(struct dpu_crtc_respool *rp,
- struct mutex *rp_lock, struct list_head *rp_head)
+static inline struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
{
- if (!rp || !rp_lock || !rp_head) {
- DPU_ERROR("invalid resource pool\n");
- return;
- }
+ struct msm_drm_private *priv = crtc->dev->dev_private;
- mutex_lock(rp_lock);
- rp->rp_lock = rp_lock;
- rp->rp_head = rp_head;
- INIT_LIST_HEAD(&rp->rp_list);
- rp->sequence_id = 0;
- INIT_LIST_HEAD(&rp->res_list);
- rp->ops.get = _dpu_crtc_hw_blk_get;
- rp->ops.put = _dpu_crtc_hw_blk_put;
- list_add_tail(&rp->rp_list, rp->rp_head);
- mutex_unlock(rp_lock);
+ return to_dpu_kms(priv->kms);
}
static void dpu_crtc_destroy(struct drm_crtc *crtc)
@@ -297,14 +77,29 @@ static void dpu_crtc_destroy(struct drm_crtc *crtc)
}
static void _dpu_crtc_setup_blend_cfg(struct dpu_crtc_mixer *mixer,
- struct dpu_plane_state *pstate)
+ struct dpu_plane_state *pstate, struct dpu_format *format)
{
struct dpu_hw_mixer *lm = mixer->hw_lm;
+ uint32_t blend_op;
+ struct drm_format_name_buf format_name;
/* default to opaque blending */
- lm->ops.setup_blend_config(lm, pstate->stage, 0XFF, 0,
- DPU_BLEND_FG_ALPHA_FG_CONST |
- DPU_BLEND_BG_ALPHA_BG_CONST);
+ blend_op = DPU_BLEND_FG_ALPHA_FG_CONST |
+ DPU_BLEND_BG_ALPHA_BG_CONST;
+
+ if (format->alpha_enable) {
+ /* coverage blending */
+ blend_op = DPU_BLEND_FG_ALPHA_FG_PIXEL |
+ DPU_BLEND_BG_ALPHA_FG_PIXEL |
+ DPU_BLEND_BG_INV_ALPHA;
+ }
+
+ lm->ops.setup_blend_config(lm, pstate->stage,
+ 0xFF, 0, blend_op);
+
+ DPU_DEBUG("format:%s, alpha_en:%u blend_op:0x%x\n",
+ drm_get_format_name(format->base.pixel_format, &format_name),
+ format->alpha_enable, blend_op);
}
static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
@@ -317,9 +112,9 @@ static void _dpu_crtc_program_lm_output_roi(struct drm_crtc *crtc)
crtc_state = to_dpu_crtc_state(crtc->state);
lm_horiz_position = 0;
- for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) {
+ for (lm_idx = 0; lm_idx < crtc_state->num_mixers; lm_idx++) {
const struct drm_rect *lm_roi = &crtc_state->lm_bounds[lm_idx];
- struct dpu_hw_mixer *hw_lm = dpu_crtc->mixers[lm_idx].hw_lm;
+ struct dpu_hw_mixer *hw_lm = crtc_state->mixers[lm_idx].hw_lm;
struct dpu_hw_mixer_cfg cfg;
if (!lm_roi || !drm_rect_visible(lm_roi))
@@ -339,28 +134,17 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
struct drm_plane *plane;
struct drm_framebuffer *fb;
struct drm_plane_state *state;
- struct dpu_crtc_state *cstate;
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
struct dpu_plane_state *pstate = NULL;
struct dpu_format *format;
- struct dpu_hw_ctl *ctl;
- struct dpu_hw_mixer *lm;
- struct dpu_hw_stage_cfg *stage_cfg;
+ struct dpu_hw_ctl *ctl = mixer->lm_ctl;
+ struct dpu_hw_stage_cfg *stage_cfg = &dpu_crtc->stage_cfg;
u32 flush_mask;
uint32_t stage_idx, lm_idx;
int zpos_cnt[DPU_STAGE_MAX + 1] = { 0 };
bool bg_alpha_enable = false;
- if (!dpu_crtc || !mixer) {
- DPU_ERROR("invalid dpu_crtc or mixer\n");
- return;
- }
-
- ctl = mixer->hw_ctl;
- lm = mixer->hw_lm;
- stage_cfg = &dpu_crtc->stage_cfg;
- cstate = to_dpu_crtc_state(crtc->state);
-
drm_atomic_crtc_for_each_plane(plane, crtc) {
state = plane->state;
if (!state)
@@ -379,10 +163,6 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
state->fb ? state->fb->base.id : -1);
format = to_dpu_format(msm_framebuffer_format(pstate->base.fb));
- if (!format) {
- DPU_ERROR("invalid format\n");
- return;
- }
if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable)
bg_alpha_enable = true;
@@ -400,8 +180,9 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
fb ? fb->modifier : 0);
/* blend config update */
- for (lm_idx = 0; lm_idx < dpu_crtc->num_mixers; lm_idx++) {
- _dpu_crtc_setup_blend_cfg(mixer + lm_idx, pstate);
+ for (lm_idx = 0; lm_idx < cstate->num_mixers; lm_idx++) {
+ _dpu_crtc_setup_blend_cfg(mixer + lm_idx,
+ pstate, format);
mixer[lm_idx].flush_mask |= flush_mask;
@@ -422,38 +203,25 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
*/
static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
{
- struct dpu_crtc *dpu_crtc;
- struct dpu_crtc_state *dpu_crtc_state;
- struct dpu_crtc_mixer *mixer;
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
+ struct dpu_crtc_mixer *mixer = cstate->mixers;
struct dpu_hw_ctl *ctl;
struct dpu_hw_mixer *lm;
-
int i;
- if (!crtc)
- return;
-
- dpu_crtc = to_dpu_crtc(crtc);
- dpu_crtc_state = to_dpu_crtc_state(crtc->state);
- mixer = dpu_crtc->mixers;
-
DPU_DEBUG("%s\n", dpu_crtc->name);
- if (dpu_crtc->num_mixers > CRTC_DUAL_MIXERS) {
- DPU_ERROR("invalid number mixers: %d\n", dpu_crtc->num_mixers);
- return;
- }
-
- for (i = 0; i < dpu_crtc->num_mixers; i++) {
- if (!mixer[i].hw_lm || !mixer[i].hw_ctl) {
+ for (i = 0; i < cstate->num_mixers; i++) {
+ if (!mixer[i].hw_lm || !mixer[i].lm_ctl) {
DPU_ERROR("invalid lm or ctl assigned to mixer\n");
return;
}
mixer[i].mixer_op_mode = 0;
mixer[i].flush_mask = 0;
- if (mixer[i].hw_ctl->ops.clear_all_blendstages)
- mixer[i].hw_ctl->ops.clear_all_blendstages(
- mixer[i].hw_ctl);
+ if (mixer[i].lm_ctl->ops.clear_all_blendstages)
+ mixer[i].lm_ctl->ops.clear_all_blendstages(
+ mixer[i].lm_ctl);
}
/* initialize stage cfg */
@@ -461,8 +229,8 @@ static void _dpu_crtc_blend_setup(struct drm_crtc *crtc)
_dpu_crtc_blend_setup_mixer(crtc, dpu_crtc, mixer);
- for (i = 0; i < dpu_crtc->num_mixers; i++) {
- ctl = mixer[i].hw_ctl;
+ for (i = 0; i < cstate->num_mixers; i++) {
+ ctl = mixer[i].lm_ctl;
lm = mixer[i].hw_lm;
lm->ops.setup_alpha_out(lm, mixer[i].mixer_op_mode);
@@ -543,34 +311,13 @@ static void dpu_crtc_vblank_cb(void *data)
static void dpu_crtc_frame_event_work(struct kthread_work *work)
{
- struct msm_drm_private *priv;
- struct dpu_crtc_frame_event *fevent;
- struct drm_crtc *crtc;
- struct dpu_crtc *dpu_crtc;
- struct dpu_kms *dpu_kms;
+ struct dpu_crtc_frame_event *fevent = container_of(work,
+ struct dpu_crtc_frame_event, work);
+ struct drm_crtc *crtc = fevent->crtc;
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
unsigned long flags;
bool frame_done = false;
- if (!work) {
- DPU_ERROR("invalid work handle\n");
- return;
- }
-
- fevent = container_of(work, struct dpu_crtc_frame_event, work);
- if (!fevent->crtc || !fevent->crtc->state) {
- DPU_ERROR("invalid crtc\n");
- return;
- }
-
- crtc = fevent->crtc;
- dpu_crtc = to_dpu_crtc(crtc);
-
- dpu_kms = _dpu_crtc_get_kms(crtc);
- if (!dpu_kms) {
- DPU_ERROR("invalid kms handle\n");
- return;
- }
- priv = dpu_kms->dev->dev_private;
DPU_ATRACE_BEGIN("crtc_frame_event");
DRM_DEBUG_KMS("crtc%d event:%u ts:%lld\n", crtc->base.id, fevent->event,
@@ -636,11 +383,6 @@ static void dpu_crtc_frame_event_cb(void *data, u32 event)
unsigned long flags;
u32 crtc_id;
- if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
- DPU_ERROR("invalid parameters\n");
- return;
- }
-
/* Nothing to do on idle event */
if (event & DPU_ENCODER_FRAME_EVENT_IDLE)
return;
@@ -683,7 +425,7 @@ static void _dpu_crtc_setup_mixer_for_encoder(
struct drm_crtc *crtc,
struct drm_encoder *enc)
{
- struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
struct dpu_rm *rm = &dpu_kms->rm;
struct dpu_crtc_mixer *mixer;
@@ -695,8 +437,8 @@ static void _dpu_crtc_setup_mixer_for_encoder(
dpu_rm_init_hw_iter(&ctl_iter, enc->base.id, DPU_HW_BLK_CTL);
/* Set up all the mixers and ctls reserved by this encoder */
- for (i = dpu_crtc->num_mixers; i < ARRAY_SIZE(dpu_crtc->mixers); i++) {
- mixer = &dpu_crtc->mixers[i];
+ for (i = cstate->num_mixers; i < ARRAY_SIZE(cstate->mixers); i++) {
+ mixer = &cstate->mixers[i];
if (!dpu_rm_get_hw(rm, &lm_iter))
break;
@@ -706,14 +448,14 @@ static void _dpu_crtc_setup_mixer_for_encoder(
if (!dpu_rm_get_hw(rm, &ctl_iter)) {
DPU_DEBUG("no ctl assigned to lm %d, using previous\n",
mixer->hw_lm->idx - LM_0);
- mixer->hw_ctl = last_valid_ctl;
+ mixer->lm_ctl = last_valid_ctl;
} else {
- mixer->hw_ctl = (struct dpu_hw_ctl *)ctl_iter.hw;
- last_valid_ctl = mixer->hw_ctl;
+ mixer->lm_ctl = (struct dpu_hw_ctl *)ctl_iter.hw;
+ last_valid_ctl = mixer->lm_ctl;
}
/* Shouldn't happen, mixers are always >= ctls */
- if (!mixer->hw_ctl) {
+ if (!mixer->lm_ctl) {
DPU_ERROR("no valid ctls found for lm %d\n",
mixer->hw_lm->idx - LM_0);
return;
@@ -721,11 +463,11 @@ static void _dpu_crtc_setup_mixer_for_encoder(
mixer->encoder = enc;
- dpu_crtc->num_mixers++;
+ cstate->num_mixers++;
DPU_DEBUG("setup mixer %d: lm %d\n",
i, mixer->hw_lm->idx - LM_0);
DPU_DEBUG("setup mixer %d: ctl %d\n",
- i, mixer->hw_ctl->idx - CTL_0);
+ i, mixer->lm_ctl->idx - CTL_0);
}
}
@@ -734,10 +476,6 @@ static void _dpu_crtc_setup_mixers(struct drm_crtc *crtc)
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct drm_encoder *enc;
- dpu_crtc->num_mixers = 0;
- dpu_crtc->mixers_swapped = false;
- memset(dpu_crtc->mixers, 0, sizeof(dpu_crtc->mixers));
-
mutex_lock(&dpu_crtc->crtc_lock);
/* Check for mixers on all encoders attached to this crtc */
list_for_each_entry(enc, &crtc->dev->mode_config.encoder_list, head) {
@@ -753,24 +491,13 @@ static void _dpu_crtc_setup_mixers(struct drm_crtc *crtc)
static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
- struct dpu_crtc *dpu_crtc;
- struct dpu_crtc_state *cstate;
- struct drm_display_mode *adj_mode;
- u32 crtc_split_width;
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
+ struct drm_display_mode *adj_mode = &state->adjusted_mode;
+ u32 crtc_split_width = _dpu_crtc_get_mixer_width(cstate, adj_mode);
int i;
- if (!crtc || !state) {
- DPU_ERROR("invalid args\n");
- return;
- }
-
- dpu_crtc = to_dpu_crtc(crtc);
- cstate = to_dpu_crtc_state(state);
-
- adj_mode = &state->adjusted_mode;
- crtc_split_width = dpu_crtc_get_mixer_width(dpu_crtc, cstate, adj_mode);
-
- for (i = 0; i < dpu_crtc->num_mixers; i++) {
+ for (i = 0; i < cstate->num_mixers; i++) {
struct drm_rect *r = &cstate->lm_bounds[i];
r->x1 = crtc_split_width * i;
r->y1 = 0;
@@ -787,6 +514,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
struct dpu_crtc *dpu_crtc;
+ struct dpu_crtc_state *cstate;
struct drm_encoder *encoder;
struct drm_device *dev;
unsigned long flags;
@@ -806,10 +534,11 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
DPU_DEBUG("crtc%d\n", crtc->base.id);
dpu_crtc = to_dpu_crtc(crtc);
+ cstate = to_dpu_crtc_state(crtc->state);
dev = crtc->dev;
smmu_state = &dpu_crtc->smmu_state;
- if (!dpu_crtc->num_mixers) {
+ if (!cstate->num_mixers) {
_dpu_crtc_setup_mixers(crtc);
_dpu_crtc_setup_lm_bounds(crtc, crtc->state);
}
@@ -836,7 +565,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
* it means we are trying to flush a CRTC whose state is disabled:
* nothing else needs to be done.
*/
- if (unlikely(!dpu_crtc->num_mixers))
+ if (unlikely(!cstate->num_mixers))
return;
_dpu_crtc_blend_setup(crtc);
@@ -861,11 +590,6 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
unsigned long flags;
struct dpu_crtc_state *cstate;
- if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
- DPU_ERROR("invalid crtc\n");
- return;
- }
-
if (!crtc->state->enable) {
DPU_DEBUG("crtc%d -> enable %d, skip atomic_flush\n",
crtc->base.id, crtc->state->enable);
@@ -900,7 +624,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
* it means we are trying to flush a CRTC whose state is disabled:
* nothing else needs to be done.
*/
- if (unlikely(!dpu_crtc->num_mixers))
+ if (unlikely(!cstate->num_mixers))
return;
/*
@@ -951,8 +675,6 @@ static void dpu_crtc_destroy_state(struct drm_crtc *crtc,
DPU_DEBUG("crtc%d\n", crtc->base.id);
- _dpu_crtc_rp_destroy(&cstate->rp);
-
__drm_atomic_helper_crtc_destroy_state(state);
kfree(cstate);
@@ -960,15 +682,9 @@ static void dpu_crtc_destroy_state(struct drm_crtc *crtc,
static int _dpu_crtc_wait_for_frame_done(struct drm_crtc *crtc)
{
- struct dpu_crtc *dpu_crtc;
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
int ret, rc = 0;
- if (!crtc) {
- DPU_ERROR("invalid argument\n");
- return -EINVAL;
- }
- dpu_crtc = to_dpu_crtc(crtc);
-
if (!atomic_read(&dpu_crtc->frame_pending)) {
DPU_DEBUG("no frames pending\n");
return 0;
@@ -989,35 +705,18 @@ static int _dpu_crtc_wait_for_frame_done(struct drm_crtc *crtc)
void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
- struct drm_device *dev;
- struct dpu_crtc *dpu_crtc;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
- struct dpu_crtc_state *cstate;
+ struct drm_device *dev = crtc->dev;
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
+ struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
int ret;
- if (!crtc) {
- DPU_ERROR("invalid argument\n");
- return;
- }
- dev = crtc->dev;
- dpu_crtc = to_dpu_crtc(crtc);
- dpu_kms = _dpu_crtc_get_kms(crtc);
-
- if (!dpu_kms || !dpu_kms->dev || !dpu_kms->dev->dev_private) {
- DPU_ERROR("invalid argument\n");
- return;
- }
-
- priv = dpu_kms->dev->dev_private;
- cstate = to_dpu_crtc_state(crtc->state);
-
/*
* If no mixers has been allocated in dpu_crtc_atomic_check(),
* it means we are trying to start a CRTC whose state is disabled:
* nothing else needs to be done.
*/
- if (unlikely(!dpu_crtc->num_mixers))
+ if (unlikely(!cstate->num_mixers))
return;
DPU_ATRACE_BEGIN("crtc_commit");
@@ -1072,33 +771,19 @@ end:
* _dpu_crtc_vblank_enable_no_lock - update power resource and vblank request
* @dpu_crtc: Pointer to dpu crtc structure
* @enable: Whether to enable/disable vblanks
- *
- * @Return: error code
*/
-static int _dpu_crtc_vblank_enable_no_lock(
+static void _dpu_crtc_vblank_enable_no_lock(
struct dpu_crtc *dpu_crtc, bool enable)
{
- struct drm_device *dev;
- struct drm_crtc *crtc;
+ struct drm_crtc *crtc = &dpu_crtc->base;
+ struct drm_device *dev = crtc->dev;
struct drm_encoder *enc;
- if (!dpu_crtc) {
- DPU_ERROR("invalid crtc\n");
- return -EINVAL;
- }
-
- crtc = &dpu_crtc->base;
- dev = crtc->dev;
-
if (enable) {
- int ret;
-
/* drop lock since power crtc cb may try to re-acquire lock */
mutex_unlock(&dpu_crtc->crtc_lock);
- ret = _dpu_crtc_power_enable(dpu_crtc, true);
+ pm_runtime_get_sync(dev->dev);
mutex_lock(&dpu_crtc->crtc_lock);
- if (ret)
- return ret;
list_for_each_entry(enc, &dev->mode_config.encoder_list, head) {
if (enc->crtc != crtc)
@@ -1125,11 +810,9 @@ static int _dpu_crtc_vblank_enable_no_lock(
/* drop lock since power crtc cb may try to re-acquire lock */
mutex_unlock(&dpu_crtc->crtc_lock);
- _dpu_crtc_power_enable(dpu_crtc, false);
+ pm_runtime_put_sync(dev->dev);
mutex_lock(&dpu_crtc->crtc_lock);
}
-
- return 0;
}
/**
@@ -1139,23 +822,7 @@ static int _dpu_crtc_vblank_enable_no_lock(
*/
static void _dpu_crtc_set_suspend(struct drm_crtc *crtc, bool enable)
{
- struct dpu_crtc *dpu_crtc;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
- int ret = 0;
-
- if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
- DPU_ERROR("invalid crtc\n");
- return;
- }
- dpu_crtc = to_dpu_crtc(crtc);
- priv = crtc->dev->dev_private;
-
- if (!priv->kms) {
- DPU_ERROR("invalid crtc kms\n");
- return;
- }
- dpu_kms = to_dpu_kms(priv->kms);
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
DRM_DEBUG_KMS("crtc%d suspend = %d\n", crtc->base.id, enable);
@@ -1170,10 +837,7 @@ static void _dpu_crtc_set_suspend(struct drm_crtc *crtc, bool enable)
DPU_DEBUG("crtc%d suspend already set to %d, ignoring update\n",
crtc->base.id, enable);
else if (dpu_crtc->enabled && dpu_crtc->vblank_requested) {
- ret = _dpu_crtc_vblank_enable_no_lock(dpu_crtc, !enable);
- if (ret)
- DPU_ERROR("%s vblank enable failed: %d\n",
- dpu_crtc->name, ret);
+ _dpu_crtc_vblank_enable_no_lock(dpu_crtc, !enable);
}
dpu_crtc->suspend = enable;
@@ -1206,8 +870,6 @@ static struct drm_crtc_state *dpu_crtc_duplicate_state(struct drm_crtc *crtc)
/* duplicate base helper */
__drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);
- _dpu_crtc_rp_duplicate(&old_cstate->rp, &cstate->rp);
-
return &cstate->base;
}
@@ -1244,9 +906,6 @@ static void dpu_crtc_reset(struct drm_crtc *crtc)
return;
}
- _dpu_crtc_rp_reset(&cstate->rp, &dpu_crtc->rp_lock,
- &dpu_crtc->rp_head);
-
cstate->base.crtc = crtc;
crtc->state = &cstate->base;
}
@@ -1254,62 +913,19 @@ static void dpu_crtc_reset(struct drm_crtc *crtc)
static void dpu_crtc_handle_power_event(u32 event_type, void *arg)
{
struct drm_crtc *crtc = arg;
- struct dpu_crtc *dpu_crtc;
+ struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct drm_encoder *encoder;
- struct dpu_crtc_mixer *m;
- u32 i, misr_status;
-
- if (!crtc) {
- DPU_ERROR("invalid crtc\n");
- return;
- }
- dpu_crtc = to_dpu_crtc(crtc);
mutex_lock(&dpu_crtc->crtc_lock);
trace_dpu_crtc_handle_power_event(DRMID(crtc), event_type);
- switch (event_type) {
- case DPU_POWER_EVENT_POST_ENABLE:
- /* restore encoder; crtc will be programmed during commit */
- drm_for_each_encoder(encoder, crtc->dev) {
- if (encoder->crtc != crtc)
- continue;
-
- dpu_encoder_virt_restore(encoder);
- }
-
- for (i = 0; i < dpu_crtc->num_mixers; ++i) {
- m = &dpu_crtc->mixers[i];
- if (!m->hw_lm || !m->hw_lm->ops.setup_misr ||
- !dpu_crtc->misr_enable)
- continue;
-
- m->hw_lm->ops.setup_misr(m->hw_lm, true,
- dpu_crtc->misr_frame_count);
- }
- break;
- case DPU_POWER_EVENT_PRE_DISABLE:
- for (i = 0; i < dpu_crtc->num_mixers; ++i) {
- m = &dpu_crtc->mixers[i];
- if (!m->hw_lm || !m->hw_lm->ops.collect_misr ||
- !dpu_crtc->misr_enable)
- continue;
+ /* restore encoder; crtc will be programmed during commit */
+ drm_for_each_encoder(encoder, crtc->dev) {
+ if (encoder->crtc != crtc)
+ continue;
- misr_status = m->hw_lm->ops.collect_misr(m->hw_lm);
- dpu_crtc->misr_data[i] = misr_status ? misr_status :
- dpu_crtc->misr_data[i];
- }
- break;
- case DPU_POWER_EVENT_POST_DISABLE:
- /**
- * Nothing to do. All the planes on the CRTC will be
- * programmed for every frame
- */
- break;
- default:
- DPU_DEBUG("event:%d not handled\n", event_type);
- break;
+ dpu_encoder_virt_restore(encoder);
}
mutex_unlock(&dpu_crtc->crtc_lock);
@@ -1322,7 +938,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
struct drm_display_mode *mode;
struct drm_encoder *encoder;
struct msm_drm_private *priv;
- int ret;
unsigned long flags;
if (!crtc || !crtc->dev || !crtc->dev->dev_private || !crtc->state) {
@@ -1353,10 +968,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
trace_dpu_crtc_disable(DRMID(crtc), false, dpu_crtc);
if (dpu_crtc->enabled && !dpu_crtc->suspend &&
dpu_crtc->vblank_requested) {
- ret = _dpu_crtc_vblank_enable_no_lock(dpu_crtc, false);
- if (ret)
- DPU_ERROR("%s vblank enable failed: %d\n",
- dpu_crtc->name, ret);
+ _dpu_crtc_vblank_enable_no_lock(dpu_crtc, false);
}
dpu_crtc->enabled = false;
@@ -1379,9 +991,8 @@ static void dpu_crtc_disable(struct drm_crtc *crtc)
dpu_power_handle_unregister_event(dpu_crtc->phandle,
dpu_crtc->power_event);
- memset(dpu_crtc->mixers, 0, sizeof(dpu_crtc->mixers));
- dpu_crtc->num_mixers = 0;
- dpu_crtc->mixers_swapped = false;
+ memset(cstate->mixers, 0, sizeof(cstate->mixers));
+ cstate->num_mixers = 0;
/* disable clk & bw control until clk & bw properties are set */
cstate->bw_control = false;
@@ -1403,7 +1014,6 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
struct dpu_crtc *dpu_crtc;
struct drm_encoder *encoder;
struct msm_drm_private *priv;
- int ret;
if (!crtc || !crtc->dev || !crtc->dev->dev_private) {
DPU_ERROR("invalid crtc\n");
@@ -1425,10 +1035,7 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
trace_dpu_crtc_enable(DRMID(crtc), true, dpu_crtc);
if (!dpu_crtc->enabled && !dpu_crtc->suspend &&
dpu_crtc->vblank_requested) {
- ret = _dpu_crtc_vblank_enable_no_lock(dpu_crtc, true);
- if (ret)
- DPU_ERROR("%s vblank enable failed: %d\n",
- dpu_crtc->name, ret);
+ _dpu_crtc_vblank_enable_no_lock(dpu_crtc, true);
}
dpu_crtc->enabled = true;
@@ -1438,9 +1045,7 @@ static void dpu_crtc_enable(struct drm_crtc *crtc,
drm_crtc_vblank_on(crtc);
dpu_crtc->power_event = dpu_power_handle_register_event(
- dpu_crtc->phandle,
- DPU_POWER_EVENT_POST_ENABLE | DPU_POWER_EVENT_POST_DISABLE |
- DPU_POWER_EVENT_PRE_DISABLE,
+ dpu_crtc->phandle, DPU_POWER_EVENT_ENABLE,
dpu_crtc_handle_power_event, crtc, dpu_crtc->name);
}
@@ -1496,7 +1101,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
memset(pipe_staged, 0, sizeof(pipe_staged));
- mixer_width = dpu_crtc_get_mixer_width(dpu_crtc, cstate, mode);
+ mixer_width = _dpu_crtc_get_mixer_width(cstate, mode);
_dpu_crtc_setup_lm_bounds(crtc, state);
@@ -1535,8 +1140,7 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
cnt++;
dst = drm_plane_state_dest(pstate);
- if (!drm_rect_intersect(&clip, &dst) ||
- !drm_rect_equals(&clip, &dst)) {
+ if (!drm_rect_intersect(&clip, &dst)) {
DPU_ERROR("invalid vertical/horizontal destination\n");
DPU_ERROR("display: " DRM_RECT_FMT " plane: "
DRM_RECT_FMT "\n", DRM_RECT_ARG(&crtc_rect),
@@ -1679,7 +1283,6 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
}
end:
- _dpu_crtc_rp_free_unused(&cstate->rp);
kfree(pstates);
return rc;
}
@@ -1687,7 +1290,6 @@ end:
int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
{
struct dpu_crtc *dpu_crtc;
- int ret;
if (!crtc) {
DPU_ERROR("invalid crtc\n");
@@ -1698,10 +1300,7 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en)
mutex_lock(&dpu_crtc->crtc_lock);
trace_dpu_crtc_vblank(DRMID(&dpu_crtc->base), en, dpu_crtc);
if (dpu_crtc->enabled && !dpu_crtc->suspend) {
- ret = _dpu_crtc_vblank_enable_no_lock(dpu_crtc, en);
- if (ret)
- DPU_ERROR("%s vblank enable failed: %d\n",
- dpu_crtc->name, ret);
+ _dpu_crtc_vblank_enable_no_lock(dpu_crtc, en);
}
dpu_crtc->vblank_requested = en;
mutex_unlock(&dpu_crtc->crtc_lock);
@@ -1730,26 +1329,28 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
dpu_crtc = s->private;
crtc = &dpu_crtc->base;
+
+ drm_modeset_lock_all(crtc->dev);
cstate = to_dpu_crtc_state(crtc->state);
mutex_lock(&dpu_crtc->crtc_lock);
mode = &crtc->state->adjusted_mode;
- out_width = dpu_crtc_get_mixer_width(dpu_crtc, cstate, mode);
+ out_width = _dpu_crtc_get_mixer_width(cstate, mode);
seq_printf(s, "crtc:%d width:%d height:%d\n", crtc->base.id,
mode->hdisplay, mode->vdisplay);
seq_puts(s, "\n");
- for (i = 0; i < dpu_crtc->num_mixers; ++i) {
- m = &dpu_crtc->mixers[i];
+ for (i = 0; i < cstate->num_mixers; ++i) {
+ m = &cstate->mixers[i];
if (!m->hw_lm)
seq_printf(s, "\tmixer[%d] has no lm\n", i);
- else if (!m->hw_ctl)
+ else if (!m->lm_ctl)
seq_printf(s, "\tmixer[%d] has no ctl\n", i);
else
seq_printf(s, "\tmixer:%d ctl:%d width:%d height:%d\n",
- m->hw_lm->idx - LM_0, m->hw_ctl->idx - CTL_0,
+ m->hw_lm->idx - LM_0, m->lm_ctl->idx - CTL_0,
out_width, mode->vdisplay);
}
@@ -1822,6 +1423,7 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
seq_printf(s, "vblank_enable:%d\n", dpu_crtc->vblank_requested);
mutex_unlock(&dpu_crtc->crtc_lock);
+ drm_modeset_unlock_all(crtc->dev);
return 0;
}
@@ -1831,113 +1433,6 @@ static int _dpu_debugfs_status_open(struct inode *inode, struct file *file)
return single_open(file, _dpu_debugfs_status_show, inode->i_private);
}
-static ssize_t _dpu_crtc_misr_setup(struct file *file,
- const char __user *user_buf, size_t count, loff_t *ppos)
-{
- struct dpu_crtc *dpu_crtc;
- struct dpu_crtc_mixer *m;
- int i = 0, rc;
- char buf[MISR_BUFF_SIZE + 1];
- u32 frame_count, enable;
- size_t buff_copy;
-
- if (!file || !file->private_data)
- return -EINVAL;
-
- dpu_crtc = file->private_data;
- buff_copy = min_t(size_t, count, MISR_BUFF_SIZE);
- if (copy_from_user(buf, user_buf, buff_copy)) {
- DPU_ERROR("buffer copy failed\n");
- return -EINVAL;
- }
-
- buf[buff_copy] = 0; /* end of string */
-
- if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
- return -EINVAL;
-
- rc = _dpu_crtc_power_enable(dpu_crtc, true);
- if (rc)
- return rc;
-
- mutex_lock(&dpu_crtc->crtc_lock);
- dpu_crtc->misr_enable = enable;
- dpu_crtc->misr_frame_count = frame_count;
- for (i = 0; i < dpu_crtc->num_mixers; ++i) {
- dpu_crtc->misr_data[i] = 0;
- m = &dpu_crtc->mixers[i];
- if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
- continue;
-
- m->hw_lm->ops.setup_misr(m->hw_lm, enable, frame_count);
- }
- mutex_unlock(&dpu_crtc->crtc_lock);
- _dpu_crtc_power_enable(dpu_crtc, false);
-
- return count;
-}
-
-static ssize_t _dpu_crtc_misr_read(struct file *file,
- char __user *user_buff, size_t count, loff_t *ppos)
-{
- struct dpu_crtc *dpu_crtc;
- struct dpu_crtc_mixer *m;
- int i = 0, rc;
- u32 misr_status;
- ssize_t len = 0;
- char buf[MISR_BUFF_SIZE + 1] = {'\0'};
-
- if (*ppos)
- return 0;
-
- if (!file || !file->private_data)
- return -EINVAL;
-
- dpu_crtc = file->private_data;
- rc = _dpu_crtc_power_enable(dpu_crtc, true);
- if (rc)
- return rc;
-
- mutex_lock(&dpu_crtc->crtc_lock);
- if (!dpu_crtc->misr_enable) {
- len += snprintf(buf + len, MISR_BUFF_SIZE - len,
- "disabled\n");
- goto buff_check;
- }
-
- for (i = 0; i < dpu_crtc->num_mixers; ++i) {
- m = &dpu_crtc->mixers[i];
- if (!m->hw_lm || !m->hw_lm->ops.collect_misr)
- continue;
-
- misr_status = m->hw_lm->ops.collect_misr(m->hw_lm);
- dpu_crtc->misr_data[i] = misr_status ? misr_status :
- dpu_crtc->misr_data[i];
- len += snprintf(buf + len, MISR_BUFF_SIZE - len, "lm idx:%d\n",
- m->hw_lm->idx - LM_0);
- len += snprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n",
- dpu_crtc->misr_data[i]);
- }
-
-buff_check:
- if (count <= len) {
- len = 0;
- goto end;
- }
-
- if (copy_to_user(user_buff, buf, len)) {
- len = -EFAULT;
- goto end;
- }
-
- *ppos += len; /* increase offset */
-
-end:
- mutex_unlock(&dpu_crtc->crtc_lock);
- _dpu_crtc_power_enable(dpu_crtc, false);
- return len;
-}
-
#define DEFINE_DPU_DEBUGFS_SEQ_FOPS(__prefix) \
static int __prefix ## _open(struct inode *inode, struct file *file) \
{ \
@@ -1955,8 +1450,6 @@ static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v)
{
struct drm_crtc *crtc = (struct drm_crtc *) s->private;
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
- struct dpu_crtc_res *res;
- struct dpu_crtc_respool *rp;
int i;
seq_printf(s, "client type: %d\n", dpu_crtc_get_client_type(crtc));
@@ -1973,17 +1466,6 @@ static int dpu_crtc_debugfs_state_show(struct seq_file *s, void *v)
dpu_crtc->cur_perf.max_per_pipe_ib[i]);
}
- mutex_lock(&dpu_crtc->rp_lock);
- list_for_each_entry(rp, &dpu_crtc->rp_head, rp_list) {
- seq_printf(s, "rp.%d: ", rp->sequence_id);
- list_for_each_entry(res, &rp->res_list, list)
- seq_printf(s, "0x%x/0x%llx/%pK/%d ",
- res->type, res->tag, res->val,
- atomic_read(&res->refcount));
- seq_puts(s, "\n");
- }
- mutex_unlock(&dpu_crtc->rp_lock);
-
return 0;
}
DEFINE_DPU_DEBUGFS_SEQ_FOPS(dpu_crtc_debugfs_state);
@@ -1999,19 +1481,12 @@ static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc)
.llseek = seq_lseek,
.release = single_release,
};
- static const struct file_operations debugfs_misr_fops = {
- .open = simple_open,
- .read = _dpu_crtc_misr_read,
- .write = _dpu_crtc_misr_setup,
- };
if (!crtc)
return -EINVAL;
dpu_crtc = to_dpu_crtc(crtc);
dpu_kms = _dpu_crtc_get_kms(crtc);
- if (!dpu_kms)
- return -EINVAL;
dpu_crtc->debugfs_root = debugfs_create_dir(dpu_crtc->name,
crtc->dev->primary->debugfs_root);
@@ -2026,8 +1501,6 @@ static int _dpu_crtc_init_debugfs(struct drm_crtc *crtc)
dpu_crtc->debugfs_root,
&dpu_crtc->base,
&dpu_crtc_debugfs_state_fops);
- debugfs_create_file("misr_data", 0600, dpu_crtc->debugfs_root,
- dpu_crtc, &debugfs_misr_fops);
return 0;
}
@@ -2082,7 +1555,8 @@ static const struct drm_crtc_helper_funcs dpu_crtc_helper_funcs = {
};
/* initialize crtc */
-struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane)
+struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
+ struct drm_plane *cursor)
{
struct drm_crtc *crtc = NULL;
struct dpu_crtc *dpu_crtc = NULL;
@@ -2104,9 +1578,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane)
spin_lock_init(&dpu_crtc->spin_lock);
atomic_set(&dpu_crtc->frame_pending, 0);
- mutex_init(&dpu_crtc->rp_lock);
- INIT_LIST_HEAD(&dpu_crtc->rp_head);
-
init_completion(&dpu_crtc->frame_done_comp);
INIT_LIST_HEAD(&dpu_crtc->frame_event_list);
@@ -2119,7 +1590,7 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane)
dpu_crtc_frame_event_work);
}
- drm_crtc_init_with_planes(dev, crtc, plane, NULL, &dpu_crtc_funcs,
+ drm_crtc_init_with_planes(dev, crtc, plane, cursor, &dpu_crtc_funcs,
NULL);
drm_crtc_helper_add(crtc, &dpu_crtc_helper_funcs);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index e87109e608e9..3723b4830335 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -83,14 +83,14 @@ struct dpu_crtc_smmu_state_data {
/**
* struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
* @hw_lm: LM HW Driver context
- * @hw_ctl: CTL Path HW driver context
+ * @lm_ctl: CTL Path HW driver context
* @encoder: Encoder attached to this lm & ctl
* @mixer_op_mode: mixer blending operation mode
* @flush_mask: mixer flush mask for ctl, mixer and pipe
*/
struct dpu_crtc_mixer {
struct dpu_hw_mixer *hw_lm;
- struct dpu_hw_ctl *hw_ctl;
+ struct dpu_hw_ctl *lm_ctl;
struct drm_encoder *encoder;
u32 mixer_op_mode;
u32 flush_mask;
@@ -121,11 +121,6 @@ struct dpu_crtc_frame_event {
* struct dpu_crtc - virtualized CRTC data structure
* @base : Base drm crtc structure
* @name : ASCII description of this crtc
- * @num_ctls : Number of ctl paths in use
- * @num_mixers : Number of mixers in use
- * @mixers_swapped: Whether the mixers have been swapped for left/right update
- * especially in the case of DSC Merge.
- * @mixers : List of active mixers
* @event : Pointer to last received drm vblank event. If there is a
* pending vblank event, this will be non-null.
* @vsync_count : Running count of received vsync events
@@ -156,27 +151,14 @@ struct dpu_crtc_frame_event {
* @event_thread : Pointer to event handler thread
* @event_worker : Event worker queue
* @event_lock : Spinlock around event handling code
- * @misr_enable : boolean entry indicates misr enable/disable status.
- * @misr_frame_count : misr frame count provided by client
- * @misr_data : store misr data before turning off the clocks.
* @phandle: Pointer to power handler
* @power_event : registered power event handle
* @cur_perf : current performance committed to clock/bandwidth driver
- * @rp_lock : serialization lock for resource pool
- * @rp_head : list of active resource pool
- * @scl3_cfg_lut : qseed3 lut config
*/
struct dpu_crtc {
struct drm_crtc base;
char name[DPU_CRTC_NAME_SIZE];
- /* HW Resources reserved for the crtc */
- u32 num_ctls;
- u32 num_mixers;
- bool mixers_swapped;
- struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS];
- struct dpu_hw_scaler3_lut_cfg *scl3_lut_cfg;
-
struct drm_pending_vblank_event *event;
u32 vsync_count;
@@ -206,77 +188,20 @@ struct dpu_crtc {
/* for handling internal event thread */
spinlock_t event_lock;
- bool misr_enable;
- u32 misr_frame_count;
- u32 misr_data[CRTC_DUAL_MIXERS];
struct dpu_power_handle *phandle;
struct dpu_power_event *power_event;
struct dpu_core_perf_params cur_perf;
- struct mutex rp_lock;
- struct list_head rp_head;
-
struct dpu_crtc_smmu_state_data smmu_state;
};
#define to_dpu_crtc(x) container_of(x, struct dpu_crtc, base)
/**
- * struct dpu_crtc_res_ops - common operations for crtc resources
- * @get: get given resource
- * @put: put given resource
- */
-struct dpu_crtc_res_ops {
- void *(*get)(void *val, u32 type, u64 tag);
- void (*put)(void *val);
-};
-
-#define DPU_CRTC_RES_FLAG_FREE BIT(0)
-
-/**
- * struct dpu_crtc_res - definition of crtc resources
- * @list: list of crtc resource
- * @type: crtc resource type
- * @tag: unique identifier per type
- * @refcount: reference/usage count
- * @ops: callback operations
- * @val: resource handle associated with type/tag
- * @flags: customization flags
- */
-struct dpu_crtc_res {
- struct list_head list;
- u32 type;
- u64 tag;
- atomic_t refcount;
- struct dpu_crtc_res_ops ops;
- void *val;
- u32 flags;
-};
-
-/**
- * dpu_crtc_respool - crtc resource pool
- * @rp_lock: pointer to serialization lock
- * @rp_head: pointer to head of active resource pools of this crtc
- * @rp_list: list of crtc resource pool
- * @sequence_id: sequence identifier, incremented per state duplication
- * @res_list: list of resource managed by this resource pool
- * @ops: resource operations for parent resource pool
- */
-struct dpu_crtc_respool {
- struct mutex *rp_lock;
- struct list_head *rp_head;
- struct list_head rp_list;
- u32 sequence_id;
- struct list_head res_list;
- struct dpu_crtc_res_ops ops;
-};
-
-/**
* struct dpu_crtc_state - dpu container for atomic crtc state
* @base: Base drm crtc state structure
- * @is_ppsplit : Whether current topology requires PPSplit special handling
* @bw_control : true if bw/clk controlled by core bw/clk properties
* @bw_split_vote : true if bw controlled by llcc/dram bw properties
* @lm_bounds : LM boundaries based on current mode full resolution, no ROI.
@@ -285,41 +210,41 @@ struct dpu_crtc_respool {
* @property_values: Current crtc property values
* @input_fence_timeout_ns : Cached input fence timeout, in ns
* @new_perf: new performance state being requested
+ * @num_mixers : Number of mixers in use
+ * @mixers : List of active mixers
+ * @num_ctls : Number of ctl paths in use
+ * @hw_ctls : List of active ctl paths
*/
struct dpu_crtc_state {
struct drm_crtc_state base;
bool bw_control;
bool bw_split_vote;
-
- bool is_ppsplit;
struct drm_rect lm_bounds[CRTC_DUAL_MIXERS];
uint64_t input_fence_timeout_ns;
struct dpu_core_perf_params new_perf;
- struct dpu_crtc_respool rp;
+
+ /* HW Resources reserved for the crtc */
+ u32 num_mixers;
+ struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS];
+
+ u32 num_ctls;
+ struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS];
};
#define to_dpu_crtc_state(x) \
container_of(x, struct dpu_crtc_state, base)
/**
- * dpu_crtc_get_mixer_width - get the mixer width
- * Mixer width will be same as panel width(/2 for split)
+ * dpu_crtc_state_is_stereo - Is crtc virtualized with two mixers?
+ * @cstate: Pointer to dpu crtc state
+ * @Return: true - has two mixers, false - has one mixer
*/
-static inline int dpu_crtc_get_mixer_width(struct dpu_crtc *dpu_crtc,
- struct dpu_crtc_state *cstate, struct drm_display_mode *mode)
+static inline bool dpu_crtc_state_is_stereo(struct dpu_crtc_state *cstate)
{
- u32 mixer_width;
-
- if (!dpu_crtc || !cstate || !mode)
- return 0;
-
- mixer_width = (dpu_crtc->num_mixers == CRTC_DUAL_MIXERS ?
- mode->hdisplay / CRTC_DUAL_MIXERS : mode->hdisplay);
-
- return mixer_width;
+ return cstate->num_mixers == CRTC_DUAL_MIXERS;
}
/**
@@ -375,9 +300,11 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc,
* dpu_crtc_init - create a new crtc object
* @dev: dpu device
* @plane: base plane
+ * @cursor: cursor plane
* @Return: new crtc object or error
*/
-struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane);
+struct drm_crtc *dpu_crtc_init(struct drm_device *dev, struct drm_plane *plane,
+ struct drm_plane *cursor);
/**
* dpu_crtc_register_custom_event - api for enabling/disabling crtc event
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 1b4de3486ef9..96cdf06e7da2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -65,8 +65,6 @@
#define MAX_CHANNELS_PER_ENC 2
-#define MISR_BUFF_SIZE 256
-
#define IDLE_SHORT_TIMEOUT 1
#define MAX_VDISPLAY_SPLIT 1080
@@ -161,8 +159,6 @@ enum dpu_enc_rc_states {
* @frame_done_timer: watchdog timer for frame done event
* @vsync_event_timer: vsync timer
* @disp_info: local copy of msm_display_info struct
- * @misr_enable: misr enable/disable status
- * @misr_frame_count: misr frame count before start capturing the data
* @idle_pc_supported: indicate if idle power collaps is supported
* @rc_lock: resource control mutex lock to protect
* virt encoder over various state changes
@@ -179,11 +175,10 @@ struct dpu_encoder_virt {
spinlock_t enc_spinlock;
uint32_t bus_scaling_client;
- uint32_t display_num_of_h_tiles;
-
unsigned int num_phys_encs;
struct dpu_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
struct dpu_encoder_phys *cur_master;
+ struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
bool intfs_swapped;
@@ -202,8 +197,6 @@ struct dpu_encoder_virt {
struct timer_list vsync_event_timer;
struct msm_display_info disp_info;
- bool misr_enable;
- u32 misr_frame_count;
bool idle_pc_supported;
struct mutex rc_lock;
@@ -443,30 +436,22 @@ int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc,
}
void dpu_encoder_get_hw_resources(struct drm_encoder *drm_enc,
- struct dpu_encoder_hw_resources *hw_res,
- struct drm_connector_state *conn_state)
+ struct dpu_encoder_hw_resources *hw_res)
{
struct dpu_encoder_virt *dpu_enc = NULL;
int i = 0;
- if (!hw_res || !drm_enc || !conn_state) {
- DPU_ERROR("invalid argument(s), drm_enc %d, res %d, state %d\n",
- drm_enc != 0, hw_res != 0, conn_state != 0);
- return;
- }
-
dpu_enc = to_dpu_encoder_virt(drm_enc);
DPU_DEBUG_ENC(dpu_enc, "\n");
/* Query resources used by phys encs, expected to be without overlap */
memset(hw_res, 0, sizeof(*hw_res));
- hw_res->display_num_of_h_tiles = dpu_enc->display_num_of_h_tiles;
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
if (phys && phys->ops.get_hw_resources)
- phys->ops.get_hw_resources(phys, hw_res, conn_state);
+ phys->ops.get_hw_resources(phys, hw_res);
}
}
@@ -525,7 +510,7 @@ void dpu_encoder_helper_split_config(
hw_mdptop = phys_enc->hw_mdptop;
disp_info = &dpu_enc->disp_info;
- if (disp_info->intf_type != DRM_MODE_CONNECTOR_DSI)
+ if (disp_info->intf_type != DRM_MODE_ENCODER_DSI)
return;
/**
@@ -660,7 +645,7 @@ static int dpu_encoder_virt_atomic_check(
if (drm_atomic_crtc_needs_modeset(crtc_state)
&& dpu_enc->mode_set_complete) {
ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, crtc_state,
- conn_state, topology, true);
+ topology, true);
dpu_enc->mode_set_complete = false;
}
}
@@ -1016,9 +1001,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct dpu_kms *dpu_kms;
struct list_head *connector_list;
struct drm_connector *conn = NULL, *conn_iter;
- struct dpu_rm_hw_iter pp_iter;
+ struct dpu_rm_hw_iter pp_iter, ctl_iter;
struct msm_display_topology topology;
- enum dpu_rm_topology_name topology_name;
+ struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
int i = 0, ret;
if (!drm_enc) {
@@ -1051,7 +1036,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
ret = dpu_rm_reserve(&dpu_kms->rm, drm_enc, drm_enc->crtc->state,
- conn->state, topology, false);
+ topology, false);
if (ret) {
DPU_ERROR_ENC(dpu_enc,
"failed to reserve hw resources, %d\n", ret);
@@ -1066,19 +1051,33 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc,
dpu_enc->hw_pp[i] = (struct dpu_hw_pingpong *) pp_iter.hw;
}
- topology_name = dpu_rm_get_topology_name(topology);
+ dpu_rm_init_hw_iter(&ctl_iter, drm_enc->base.id, DPU_HW_BLK_CTL);
+ for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+ if (!dpu_rm_get_hw(&dpu_kms->rm, &ctl_iter))
+ break;
+ hw_ctl[i] = (struct dpu_hw_ctl *)ctl_iter.hw;
+ }
+
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
if (phys) {
if (!dpu_enc->hw_pp[i]) {
- DPU_ERROR_ENC(dpu_enc,
- "invalid pingpong block for the encoder\n");
+ DPU_ERROR_ENC(dpu_enc, "no pp block assigned"
+ "at idx: %d\n", i);
return;
}
+
+ if (!hw_ctl[i]) {
+ DPU_ERROR_ENC(dpu_enc, "no ctl block assigned"
+ "at idx: %d\n", i);
+ return;
+ }
+
phys->hw_pp = dpu_enc->hw_pp[i];
+ phys->hw_ctl = hw_ctl[i];
+
phys->connector = conn->state->connector;
- phys->topology_name = topology_name;
if (phys->ops.mode_set)
phys->ops.mode_set(phys, mode, adj_mode);
}
@@ -1111,12 +1110,6 @@ static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
return;
}
- if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DisplayPort &&
- dpu_enc->cur_master->hw_mdptop &&
- dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select)
- dpu_enc->cur_master->hw_mdptop->ops.intf_audio_select(
- dpu_enc->cur_master->hw_mdptop);
-
if (dpu_enc->cur_master->hw_mdptop &&
dpu_enc->cur_master->hw_mdptop->ops.reset_ubwc)
dpu_enc->cur_master->hw_mdptop->ops.reset_ubwc(
@@ -1153,7 +1146,7 @@ void dpu_encoder_virt_restore(struct drm_encoder *drm_enc)
static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc = NULL;
- int i, ret = 0;
+ int ret = 0;
struct drm_display_mode *cur_mode = NULL;
if (!drm_enc) {
@@ -1166,21 +1159,12 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
trace_dpu_enc_enable(DRMID(drm_enc), cur_mode->hdisplay,
cur_mode->vdisplay);
- dpu_enc->cur_master = NULL;
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
+ /* always enable slave encoder before master */
+ if (dpu_enc->cur_slave && dpu_enc->cur_slave->ops.enable)
+ dpu_enc->cur_slave->ops.enable(dpu_enc->cur_slave);
- if (phys && phys->ops.is_master && phys->ops.is_master(phys)) {
- DPU_DEBUG_ENC(dpu_enc, "master is now idx %d\n", i);
- dpu_enc->cur_master = phys;
- break;
- }
- }
-
- if (!dpu_enc->cur_master) {
- DPU_ERROR("virt encoder has no master! num_phys %d\n", i);
- return;
- }
+ if (dpu_enc->cur_master && dpu_enc->cur_master->ops.enable)
+ dpu_enc->cur_master->ops.enable(dpu_enc->cur_master);
ret = dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_KICKOFF);
if (ret) {
@@ -1189,26 +1173,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc)
return;
}
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
-
- if (!phys)
- continue;
-
- if (phys != dpu_enc->cur_master) {
- if (phys->ops.enable)
- phys->ops.enable(phys);
- }
-
- if (dpu_enc->misr_enable && (dpu_enc->disp_info.capabilities &
- MSM_DISPLAY_CAP_VID_MODE) && phys->ops.setup_misr)
- phys->ops.setup_misr(phys, true,
- dpu_enc->misr_frame_count);
- }
-
- if (dpu_enc->cur_master->ops.enable)
- dpu_enc->cur_master->ops.enable(dpu_enc->cur_master);
-
_dpu_encoder_virt_enable_helper(drm_enc);
}
@@ -1266,8 +1230,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc)
dpu_enc->phys_encs[i]->connector = NULL;
}
- dpu_enc->cur_master = NULL;
-
DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
dpu_rm_release(&dpu_kms->rm, drm_enc);
@@ -1397,9 +1359,9 @@ static void dpu_encoder_frame_done_callback(
/* One of the physical encoders has become idle */
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
if (dpu_enc->phys_encs[i] == ready_phys) {
- clear_bit(i, dpu_enc->frame_busy_mask);
trace_dpu_enc_frame_done_cb(DRMID(drm_enc), i,
dpu_enc->frame_busy_mask[0]);
+ clear_bit(i, dpu_enc->frame_busy_mask);
}
}
@@ -1480,7 +1442,8 @@ static inline void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
ret = ctl->ops.get_pending_flush(ctl);
trace_dpu_enc_trigger_flush(DRMID(drm_enc), phys->intf_idx,
- pending_kickoff_cnt, ctl->idx, ret);
+ pending_kickoff_cnt, ctl->idx,
+ extra_flush_bits, ret);
}
/**
@@ -1879,7 +1842,7 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
phys->ops.handle_post_kickoff(phys);
}
- if (dpu_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DSI &&
+ if (dpu_enc->disp_info.intf_type == DRM_MODE_ENCODER_DSI &&
!_dpu_encoder_wakeup_time(drm_enc, &wakeup_time)) {
trace_dpu_enc_early_kickoff(DRMID(drm_enc),
ktime_to_ms(wakeup_time));
@@ -1955,113 +1918,6 @@ static int _dpu_encoder_debugfs_status_open(struct inode *inode,
return single_open(file, _dpu_encoder_status_show, inode->i_private);
}
-static ssize_t _dpu_encoder_misr_setup(struct file *file,
- const char __user *user_buf, size_t count, loff_t *ppos)
-{
- struct dpu_encoder_virt *dpu_enc;
- int i = 0, rc;
- char buf[MISR_BUFF_SIZE + 1];
- size_t buff_copy;
- u32 frame_count, enable;
-
- if (!file || !file->private_data)
- return -EINVAL;
-
- dpu_enc = file->private_data;
-
- buff_copy = min_t(size_t, count, MISR_BUFF_SIZE);
- if (copy_from_user(buf, user_buf, buff_copy))
- return -EINVAL;
-
- buf[buff_copy] = 0; /* end of string */
-
- if (sscanf(buf, "%u %u", &enable, &frame_count) != 2)
- return -EINVAL;
-
- rc = _dpu_encoder_power_enable(dpu_enc, true);
- if (rc)
- return rc;
-
- mutex_lock(&dpu_enc->enc_lock);
- dpu_enc->misr_enable = enable;
- dpu_enc->misr_frame_count = frame_count;
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
-
- if (!phys || !phys->ops.setup_misr)
- continue;
-
- phys->ops.setup_misr(phys, enable, frame_count);
- }
- mutex_unlock(&dpu_enc->enc_lock);
- _dpu_encoder_power_enable(dpu_enc, false);
-
- return count;
-}
-
-static ssize_t _dpu_encoder_misr_read(struct file *file,
- char __user *user_buff, size_t count, loff_t *ppos)
-{
- struct dpu_encoder_virt *dpu_enc;
- int i = 0, len = 0;
- char buf[MISR_BUFF_SIZE + 1] = {'\0'};
- int rc;
-
- if (*ppos)
- return 0;
-
- if (!file || !file->private_data)
- return -EINVAL;
-
- dpu_enc = file->private_data;
-
- rc = _dpu_encoder_power_enable(dpu_enc, true);
- if (rc)
- return rc;
-
- mutex_lock(&dpu_enc->enc_lock);
- if (!dpu_enc->misr_enable) {
- len += snprintf(buf + len, MISR_BUFF_SIZE - len,
- "disabled\n");
- goto buff_check;
- } else if (dpu_enc->disp_info.capabilities &
- ~MSM_DISPLAY_CAP_VID_MODE) {
- len += snprintf(buf + len, MISR_BUFF_SIZE - len,
- "unsupported\n");
- goto buff_check;
- }
-
- for (i = 0; i < dpu_enc->num_phys_encs; i++) {
- struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
-
- if (!phys || !phys->ops.collect_misr)
- continue;
-
- len += snprintf(buf + len, MISR_BUFF_SIZE - len,
- "Intf idx:%d\n", phys->intf_idx - INTF_0);
- len += snprintf(buf + len, MISR_BUFF_SIZE - len, "0x%x\n",
- phys->ops.collect_misr(phys));
- }
-
-buff_check:
- if (count <= len) {
- len = 0;
- goto end;
- }
-
- if (copy_to_user(user_buff, buf, len)) {
- len = -EFAULT;
- goto end;
- }
-
- *ppos += len; /* increase offset */
-
-end:
- mutex_unlock(&dpu_enc->enc_lock);
- _dpu_encoder_power_enable(dpu_enc, false);
- return len;
-}
-
static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
@@ -2076,12 +1932,6 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
.release = single_release,
};
- static const struct file_operations debugfs_misr_fops = {
- .open = simple_open,
- .read = _dpu_encoder_misr_read,
- .write = _dpu_encoder_misr_setup,
- };
-
char name[DPU_NAME_SIZE];
if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private) {
@@ -2105,9 +1955,6 @@ static int _dpu_encoder_init_debugfs(struct drm_encoder *drm_enc)
debugfs_create_file("status", 0600,
dpu_enc->debugfs_root, dpu_enc, &debugfs_status_fops);
- debugfs_create_file("misr_data", 0600,
- dpu_enc->debugfs_root, dpu_enc, &debugfs_misr_fops);
-
for (i = 0; i < dpu_enc->num_phys_encs; i++)
if (dpu_enc->phys_encs[i] &&
dpu_enc->phys_encs[i]->ops.late_register)
@@ -2195,6 +2042,11 @@ static int dpu_encoder_virt_add_phys_encs(
++dpu_enc->num_phys_encs;
}
+ if (params->split_role == ENC_ROLE_SLAVE)
+ dpu_enc->cur_slave = enc;
+ else
+ dpu_enc->cur_master = enc;
+
return 0;
}
@@ -2206,8 +2058,7 @@ static const struct dpu_encoder_virt_ops dpu_encoder_parent_ops = {
static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
- struct msm_display_info *disp_info,
- int *drm_enc_mode)
+ struct msm_display_info *disp_info)
{
int ret = 0;
int i = 0;
@@ -2220,6 +2071,8 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
return -EINVAL;
}
+ dpu_enc->cur_master = NULL;
+
memset(&phys_params, 0, sizeof(phys_params));
phys_params.dpu_kms = dpu_kms;
phys_params.parent = &dpu_enc->base;
@@ -2228,24 +2081,17 @@ static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
DPU_DEBUG("\n");
- if (disp_info->intf_type == DRM_MODE_CONNECTOR_DSI) {
- *drm_enc_mode = DRM_MODE_ENCODER_DSI;
+ switch (disp_info->intf_type) {
+ case DRM_MODE_ENCODER_DSI:
intf_type = INTF_DSI;
- } else if (disp_info->intf_type == DRM_MODE_CONNECTOR_HDMIA) {
- *drm_enc_mode = DRM_MODE_ENCODER_TMDS;
- intf_type = INTF_HDMI;
- } else if (disp_info->intf_type == DRM_MODE_CONNECTOR_DisplayPort) {
- *drm_enc_mode = DRM_MODE_ENCODER_TMDS;
- intf_type = INTF_DP;
- } else {
+ break;
+ default:
DPU_ERROR_ENC(dpu_enc, "unsupported display interface type\n");
return -EINVAL;
}
WARN_ON(disp_info->num_of_h_tiles < 1);
- dpu_enc->display_num_of_h_tiles = disp_info->num_of_h_tiles;
-
DPU_DEBUG("dsi_info->num_of_h_tiles %d\n", disp_info->num_of_h_tiles);
if ((disp_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE) ||
@@ -2358,25 +2204,22 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc,
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
struct drm_encoder *drm_enc = NULL;
struct dpu_encoder_virt *dpu_enc = NULL;
- int drm_enc_mode = DRM_MODE_ENCODER_NONE;
int ret = 0;
dpu_enc = to_dpu_encoder_virt(enc);
mutex_init(&dpu_enc->enc_lock);
- ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info,
- &drm_enc_mode);
+ ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info);
if (ret)
goto fail;
- dpu_enc->cur_master = NULL;
spin_lock_init(&dpu_enc->enc_spinlock);
atomic_set(&dpu_enc->frame_done_timeout, 0);
timer_setup(&dpu_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
- if (disp_info->intf_type == DRM_MODE_CONNECTOR_DSI)
+ if (disp_info->intf_type == DRM_MODE_ENCODER_DSI)
timer_setup(&dpu_enc->vsync_event_timer,
dpu_encoder_vsync_event_handler,
0);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 60f809fc7c13..9dbf38f446d9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -32,15 +32,9 @@
/**
* Encoder functions and data types
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
- * @needs_cdm: Encoder requests a CDM based on pixel format conversion needs
- * @display_num_of_h_tiles: Number of horizontal tiles in case of split
- * interface
- * @topology: Topology of the display
*/
struct dpu_encoder_hw_resources {
enum dpu_intf_mode intfs[INTF_MAX];
- bool needs_cdm;
- u32 display_num_of_h_tiles;
};
/**
@@ -56,11 +50,9 @@ struct dpu_encoder_kickoff_params {
* dpu_encoder_get_hw_resources - Populate table of required hardware resources
* @encoder: encoder pointer
* @hw_res: resource table to populate with encoder required resources
- * @conn_state: report hw reqs based on this proposed connector state
*/
void dpu_encoder_get_hw_resources(struct drm_encoder *encoder,
- struct dpu_encoder_hw_resources *hw_res,
- struct drm_connector_state *conn_state);
+ struct dpu_encoder_hw_resources *hw_res);
/**
* dpu_encoder_register_vblank_callback - provide callback to encoder that
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index c7df8aad6613..964efcc757a4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -22,8 +22,8 @@
#include "dpu_hw_pingpong.h"
#include "dpu_hw_ctl.h"
#include "dpu_hw_top.h"
-#include "dpu_hw_cdm.h"
#include "dpu_encoder.h"
+#include "dpu_crtc.h"
#define DPU_ENCODER_NAME_MAX 16
@@ -114,8 +114,6 @@ struct dpu_encoder_virt_ops {
* @handle_post_kickoff: Do any work necessary post-kickoff work
* @trigger_start: Process start event on physical encoder
* @needs_single_flush: Whether encoder slaves need to be flushed
- * @setup_misr: Sets up MISR, enable and disables based on sysfs
- * @collect_misr: Collects MISR data on frame update
* @hw_reset: Issue HW recovery such as CTL reset and clear
* DPU_ENC_ERR_NEEDS_HW_RESET state
* @irq_control: Handler to enable/disable all the encoder IRQs
@@ -143,8 +141,7 @@ struct dpu_encoder_phys_ops {
struct drm_connector_state *conn_state);
void (*destroy)(struct dpu_encoder_phys *encoder);
void (*get_hw_resources)(struct dpu_encoder_phys *encoder,
- struct dpu_encoder_hw_resources *hw_res,
- struct drm_connector_state *conn_state);
+ struct dpu_encoder_hw_resources *hw_res);
int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable);
int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc);
int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc);
@@ -154,10 +151,6 @@ struct dpu_encoder_phys_ops {
void (*handle_post_kickoff)(struct dpu_encoder_phys *phys_enc);
void (*trigger_start)(struct dpu_encoder_phys *phys_enc);
bool (*needs_single_flush)(struct dpu_encoder_phys *phys_enc);
-
- void (*setup_misr)(struct dpu_encoder_phys *phys_encs,
- bool enable, u32 frame_count);
- u32 (*collect_misr)(struct dpu_encoder_phys *phys_enc);
void (*hw_reset)(struct dpu_encoder_phys *phys_enc);
void (*irq_control)(struct dpu_encoder_phys *phys, bool enable);
void (*prepare_idle_pc)(struct dpu_encoder_phys *phys_enc);
@@ -210,8 +203,6 @@ struct dpu_encoder_irq {
* @parent_ops: Callbacks exposed by the parent to the phys_enc
* @hw_mdptop: Hardware interface to the top registers
* @hw_ctl: Hardware interface to the ctl registers
- * @hw_cdm: Hardware interface to the cdm registers
- * @cdm_cfg: Chroma-down hardware configuration
* @hw_pp: Hardware interface to the ping pong registers
* @dpu_kms: Pointer to the dpu_kms top level
* @cached_mode: DRM mode cached at mode_set time, acted on in enable
@@ -219,7 +210,6 @@ struct dpu_encoder_irq {
* @split_role: Role to play in a split-panel configuration
* @intf_mode: Interface mode
* @intf_idx: Interface index on dpu hardware
- * @topology_name: topology selected for the display
* @enc_spinlock: Virtual-Encoder-Wide Spin Lock for IRQ purposes
* @enable_state: Enable state tracking
* @vblank_refcount: Reference count of vblank request
@@ -241,15 +231,12 @@ struct dpu_encoder_phys {
const struct dpu_encoder_virt_ops *parent_ops;
struct dpu_hw_mdp *hw_mdptop;
struct dpu_hw_ctl *hw_ctl;
- struct dpu_hw_cdm *hw_cdm;
- struct dpu_hw_cdm_cfg cdm_cfg;
struct dpu_hw_pingpong *hw_pp;
struct dpu_kms *dpu_kms;
struct drm_display_mode cached_mode;
enum dpu_enc_split_role split_role;
enum dpu_intf_mode intf_mode;
enum dpu_intf intf_idx;
- enum dpu_rm_topology_name topology_name;
spinlock_t *enc_spinlock;
enum dpu_enc_enable_state enable_state;
atomic_t vblank_refcount;
@@ -367,11 +354,15 @@ void dpu_encoder_helper_hw_reset(struct dpu_encoder_phys *phys_enc);
static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
struct dpu_encoder_phys *phys_enc)
{
+ struct dpu_crtc_state *dpu_cstate;
+
if (!phys_enc || phys_enc->enable_state == DPU_ENC_DISABLING)
return BLEND_3D_NONE;
+ dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
+
if (phys_enc->split_role == ENC_ROLE_SOLO &&
- phys_enc->topology_name == DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE)
+ dpu_crtc_state_is_stereo(dpu_cstate))
return BLEND_3D_H_ROW_INT;
return BLEND_3D_NONE;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index 3084675ed425..b2d7f0ded24c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -196,9 +196,6 @@ static void dpu_encoder_phys_cmd_mode_set(
{
struct dpu_encoder_phys_cmd *cmd_enc =
to_dpu_encoder_phys_cmd(phys_enc);
- struct dpu_rm *rm = &phys_enc->dpu_kms->rm;
- struct dpu_rm_hw_iter iter;
- int i, instance;
if (!phys_enc || !mode || !adj_mode) {
DPU_ERROR("invalid args\n");
@@ -208,22 +205,6 @@ static void dpu_encoder_phys_cmd_mode_set(
DPU_DEBUG_CMDENC(cmd_enc, "caching mode:\n");
drm_mode_debug_printmodeline(adj_mode);
- instance = phys_enc->split_role == ENC_ROLE_SLAVE ? 1 : 0;
-
- /* Retrieve previously allocated HW Resources. Shouldn't fail */
- dpu_rm_init_hw_iter(&iter, phys_enc->parent->base.id, DPU_HW_BLK_CTL);
- for (i = 0; i <= instance; i++) {
- if (dpu_rm_get_hw(rm, &iter))
- phys_enc->hw_ctl = (struct dpu_hw_ctl *)iter.hw;
- }
-
- if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {
- DPU_ERROR_CMDENC(cmd_enc, "failed to init ctl: %ld\n",
- PTR_ERR(phys_enc->hw_ctl));
- phys_enc->hw_ctl = NULL;
- return;
- }
-
_dpu_encoder_phys_cmd_setup_irq_hw_idx(phys_enc);
}
@@ -618,23 +599,8 @@ static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc)
static void dpu_encoder_phys_cmd_get_hw_resources(
struct dpu_encoder_phys *phys_enc,
- struct dpu_encoder_hw_resources *hw_res,
- struct drm_connector_state *conn_state)
+ struct dpu_encoder_hw_resources *hw_res)
{
- struct dpu_encoder_phys_cmd *cmd_enc =
- to_dpu_encoder_phys_cmd(phys_enc);
-
- if (!phys_enc) {
- DPU_ERROR("invalid encoder\n");
- return;
- }
-
- if ((phys_enc->intf_idx - INTF_0) >= INTF_MAX) {
- DPU_ERROR("invalid intf idx:%d\n", phys_enc->intf_idx);
- return;
- }
-
- DPU_DEBUG_CMDENC(cmd_enc, "\n");
hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_CMD;
}
@@ -823,7 +789,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
{
struct dpu_encoder_phys *phys_enc = NULL;
struct dpu_encoder_phys_cmd *cmd_enc = NULL;
- struct dpu_hw_mdp *hw_mdp;
struct dpu_encoder_irq *irq;
int i, ret = 0;
@@ -836,14 +801,7 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
goto fail;
}
phys_enc = &cmd_enc->base;
-
- hw_mdp = dpu_rm_get_mdp(&p->dpu_kms->rm);
- if (IS_ERR_OR_NULL(hw_mdp)) {
- ret = PTR_ERR(hw_mdp);
- DPU_ERROR("failed to get mdptop\n");
- goto fail_mdp_init;
- }
- phys_enc->hw_mdptop = hw_mdp;
+ phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
phys_enc->intf_idx = p->intf_idx;
dpu_encoder_phys_cmd_init_ops(&phys_enc->ops);
@@ -898,8 +856,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
return phys_enc;
-fail_mdp_init:
- kfree(cmd_enc);
fail:
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 14fc7c2a6bb7..84de385a9f62 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -355,13 +355,14 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg, int irq_idx)
static bool _dpu_encoder_phys_is_dual_ctl(struct dpu_encoder_phys *phys_enc)
{
+ struct dpu_crtc_state *dpu_cstate;
+
if (!phys_enc)
return false;
- if (phys_enc->topology_name == DPU_RM_TOPOLOGY_DUALPIPE)
- return true;
+ dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
- return false;
+ return dpu_cstate->num_ctls > 1;
}
static bool dpu_encoder_phys_vid_needs_single_flush(
@@ -395,9 +396,6 @@ static void dpu_encoder_phys_vid_mode_set(
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
{
- struct dpu_rm *rm;
- struct dpu_rm_hw_iter iter;
- int i, instance;
struct dpu_encoder_phys_vid *vid_enc;
if (!phys_enc || !phys_enc->dpu_kms) {
@@ -405,7 +403,6 @@ static void dpu_encoder_phys_vid_mode_set(
return;
}
- rm = &phys_enc->dpu_kms->rm;
vid_enc = to_dpu_encoder_phys_vid(phys_enc);
if (adj_mode) {
@@ -414,21 +411,6 @@ static void dpu_encoder_phys_vid_mode_set(
DPU_DEBUG_VIDENC(vid_enc, "caching mode:\n");
}
- instance = phys_enc->split_role == ENC_ROLE_SLAVE ? 1 : 0;
-
- /* Retrieve previously allocated HW Resources. Shouldn't fail */
- dpu_rm_init_hw_iter(&iter, phys_enc->parent->base.id, DPU_HW_BLK_CTL);
- for (i = 0; i <= instance; i++) {
- if (dpu_rm_get_hw(rm, &iter))
- phys_enc->hw_ctl = (struct dpu_hw_ctl *)iter.hw;
- }
- if (IS_ERR_OR_NULL(phys_enc->hw_ctl)) {
- DPU_ERROR_VIDENC(vid_enc, "failed to init ctl, %ld\n",
- PTR_ERR(phys_enc->hw_ctl));
- phys_enc->hw_ctl = NULL;
- return;
- }
-
_dpu_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
}
@@ -481,7 +463,7 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
{
struct msm_drm_private *priv;
struct dpu_encoder_phys_vid *vid_enc;
- struct dpu_hw_intf *intf;
+ struct dpu_rm_hw_iter iter;
struct dpu_hw_ctl *ctl;
u32 flush_mask = 0;
@@ -493,11 +475,20 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
priv = phys_enc->parent->dev->dev_private;
vid_enc = to_dpu_encoder_phys_vid(phys_enc);
- intf = vid_enc->hw_intf;
ctl = phys_enc->hw_ctl;
- if (!vid_enc->hw_intf || !phys_enc->hw_ctl) {
- DPU_ERROR("invalid hw_intf %d hw_ctl %d\n",
- vid_enc->hw_intf != 0, phys_enc->hw_ctl != 0);
+
+ dpu_rm_init_hw_iter(&iter, phys_enc->parent->base.id, DPU_HW_BLK_INTF);
+ while (dpu_rm_get_hw(&phys_enc->dpu_kms->rm, &iter)) {
+ struct dpu_hw_intf *hw_intf = (struct dpu_hw_intf *)iter.hw;
+
+ if (hw_intf->idx == phys_enc->intf_idx) {
+ vid_enc->hw_intf = hw_intf;
+ break;
+ }
+ }
+
+ if (!vid_enc->hw_intf) {
+ DPU_ERROR("hw_intf not assigned\n");
return;
}
@@ -519,7 +510,7 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
!dpu_encoder_phys_vid_is_master(phys_enc))
goto skip_flush;
- ctl->ops.get_bitmask_intf(ctl, &flush_mask, intf->idx);
+ ctl->ops.get_bitmask_intf(ctl, &flush_mask, vid_enc->hw_intf->idx);
ctl->ops.update_pending_flush(ctl, flush_mask);
skip_flush:
@@ -547,25 +538,9 @@ static void dpu_encoder_phys_vid_destroy(struct dpu_encoder_phys *phys_enc)
static void dpu_encoder_phys_vid_get_hw_resources(
struct dpu_encoder_phys *phys_enc,
- struct dpu_encoder_hw_resources *hw_res,
- struct drm_connector_state *conn_state)
+ struct dpu_encoder_hw_resources *hw_res)
{
- struct dpu_encoder_phys_vid *vid_enc;
-
- if (!phys_enc || !hw_res) {
- DPU_ERROR("invalid arg(s), enc %d hw_res %d conn_state %d\n",
- phys_enc != 0, hw_res != 0, conn_state != 0);
- return;
- }
-
- vid_enc = to_dpu_encoder_phys_vid(phys_enc);
- if (!vid_enc->hw_intf) {
- DPU_ERROR("invalid arg(s), hw_intf\n");
- return;
- }
-
- DPU_DEBUG_VIDENC(vid_enc, "\n");
- hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO;
+ hw_res->intfs[phys_enc->intf_idx - INTF_0] = INTF_MODE_VIDEO;
}
static int _dpu_encoder_phys_vid_wait_for_vblank(
@@ -756,32 +731,6 @@ static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc,
}
}
-static void dpu_encoder_phys_vid_setup_misr(struct dpu_encoder_phys *phys_enc,
- bool enable, u32 frame_count)
-{
- struct dpu_encoder_phys_vid *vid_enc;
-
- if (!phys_enc)
- return;
- vid_enc = to_dpu_encoder_phys_vid(phys_enc);
-
- if (vid_enc->hw_intf && vid_enc->hw_intf->ops.setup_misr)
- vid_enc->hw_intf->ops.setup_misr(vid_enc->hw_intf,
- enable, frame_count);
-}
-
-static u32 dpu_encoder_phys_vid_collect_misr(struct dpu_encoder_phys *phys_enc)
-{
- struct dpu_encoder_phys_vid *vid_enc;
-
- if (!phys_enc)
- return 0;
- vid_enc = to_dpu_encoder_phys_vid(phys_enc);
-
- return vid_enc->hw_intf && vid_enc->hw_intf->ops.collect_misr ?
- vid_enc->hw_intf->ops.collect_misr(vid_enc->hw_intf) : 0;
-}
-
static int dpu_encoder_phys_vid_get_line_count(
struct dpu_encoder_phys *phys_enc)
{
@@ -817,8 +766,6 @@ static void dpu_encoder_phys_vid_init_ops(struct dpu_encoder_phys_ops *ops)
ops->prepare_for_kickoff = dpu_encoder_phys_vid_prepare_for_kickoff;
ops->handle_post_kickoff = dpu_encoder_phys_vid_handle_post_kickoff;
ops->needs_single_flush = dpu_encoder_phys_vid_needs_single_flush;
- ops->setup_misr = dpu_encoder_phys_vid_setup_misr;
- ops->collect_misr = dpu_encoder_phys_vid_collect_misr;
ops->hw_reset = dpu_encoder_helper_hw_reset;
ops->get_line_count = dpu_encoder_phys_vid_get_line_count;
}
@@ -828,8 +775,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
{
struct dpu_encoder_phys *phys_enc = NULL;
struct dpu_encoder_phys_vid *vid_enc = NULL;
- struct dpu_rm_hw_iter iter;
- struct dpu_hw_mdp *hw_mdp;
struct dpu_encoder_irq *irq;
int i, ret = 0;
@@ -846,35 +791,9 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
phys_enc = &vid_enc->base;
- hw_mdp = dpu_rm_get_mdp(&p->dpu_kms->rm);
- if (IS_ERR_OR_NULL(hw_mdp)) {
- ret = PTR_ERR(hw_mdp);
- DPU_ERROR("failed to get mdptop\n");
- goto fail;
- }
- phys_enc->hw_mdptop = hw_mdp;
+ phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
phys_enc->intf_idx = p->intf_idx;
- /**
- * hw_intf resource permanently assigned to this encoder
- * Other resources allocated at atomic commit time by use case
- */
- dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_INTF);
- while (dpu_rm_get_hw(&p->dpu_kms->rm, &iter)) {
- struct dpu_hw_intf *hw_intf = (struct dpu_hw_intf *)iter.hw;
-
- if (hw_intf->idx == p->intf_idx) {
- vid_enc->hw_intf = hw_intf;
- break;
- }
- }
-
- if (!vid_enc->hw_intf) {
- ret = -EINVAL;
- DPU_ERROR("failed to get hw_intf\n");
- goto fail;
- }
-
DPU_DEBUG_VIDENC(vid_enc, "\n");
dpu_encoder_phys_vid_init_ops(&phys_enc->ops);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 44ee06398b1d..512ac0834d2b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -29,6 +29,9 @@
BIT(DPU_SSPP_TS_PREFILL) | BIT(DPU_SSPP_TS_PREFILL_REC1) |\
BIT(DPU_SSPP_CDP) | BIT(DPU_SSPP_EXCL_RECT))
+#define DMA_CURSOR_SDM845_MASK \
+ (DMA_SDM845_MASK | BIT(DPU_SSPP_CURSOR))
+
#define MIXER_SDM845_MASK \
(BIT(DPU_MIXER_SOURCESPLIT) | BIT(DPU_DIM_LAYER))
@@ -71,7 +74,6 @@ static struct dpu_mdp_cfg sdm845_mdp[] = {
.base = 0x0, .len = 0x45C,
.features = 0,
.highest_bank_bit = 0x2,
- .has_dest_scaler = true,
.clk_ctrls[DPU_CLK_CTRL_VIG0] = {
.reg_off = 0x2AC, .bit_off = 0},
.clk_ctrls[DPU_CLK_CTRL_VIG1] = {
@@ -174,45 +176,35 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK("9", 2);
static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK("10", 3);
static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4);
-#define SSPP_VIG_BLK(_name, _id, _base, _sblk, _xinid, _clkctrl) \
- { \
- .name = _name, .id = _id, \
- .base = _base, .len = 0x1c8, \
- .features = VIG_SDM845_MASK, \
- .sblk = &_sblk, \
- .xin_id = _xinid, \
- .type = SSPP_TYPE_VIG, \
- .clk_ctrl = _clkctrl \
- }
-
-#define SSPP_DMA_BLK(_name, _id, _base, _sblk, _xinid, _clkctrl) \
+#define SSPP_BLK(_name, _id, _base, _features, \
+ _sblk, _xinid, _type, _clkctrl) \
{ \
.name = _name, .id = _id, \
.base = _base, .len = 0x1c8, \
- .features = DMA_SDM845_MASK, \
+ .features = _features, \
.sblk = &_sblk, \
.xin_id = _xinid, \
- .type = SSPP_TYPE_DMA, \
+ .type = _type, \
.clk_ctrl = _clkctrl \
}
static struct dpu_sspp_cfg sdm845_sspp[] = {
- SSPP_VIG_BLK("sspp_0", SSPP_VIG0, 0x4000,
- sdm845_vig_sblk_0, 0, DPU_CLK_CTRL_VIG0),
- SSPP_VIG_BLK("sspp_1", SSPP_VIG1, 0x6000,
- sdm845_vig_sblk_1, 4, DPU_CLK_CTRL_VIG1),
- SSPP_VIG_BLK("sspp_2", SSPP_VIG2, 0x8000,
- sdm845_vig_sblk_2, 8, DPU_CLK_CTRL_VIG2),
- SSPP_VIG_BLK("sspp_3", SSPP_VIG3, 0xa000,
- sdm845_vig_sblk_3, 12, DPU_CLK_CTRL_VIG3),
- SSPP_DMA_BLK("sspp_8", SSPP_DMA0, 0x24000,
- sdm845_dma_sblk_0, 1, DPU_CLK_CTRL_DMA0),
- SSPP_DMA_BLK("sspp_9", SSPP_DMA1, 0x26000,
- sdm845_dma_sblk_1, 5, DPU_CLK_CTRL_DMA1),
- SSPP_DMA_BLK("sspp_10", SSPP_DMA2, 0x28000,
- sdm845_dma_sblk_2, 9, DPU_CLK_CTRL_CURSOR0),
- SSPP_DMA_BLK("sspp_11", SSPP_DMA3, 0x2a000,
- sdm845_dma_sblk_3, 13, DPU_CLK_CTRL_CURSOR1),
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SDM845_MASK,
+ sdm845_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_1", SSPP_VIG1, 0x6000, VIG_SDM845_MASK,
+ sdm845_vig_sblk_1, 4, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG1),
+ SSPP_BLK("sspp_2", SSPP_VIG2, 0x8000, VIG_SDM845_MASK,
+ sdm845_vig_sblk_2, 8, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG2),
+ SSPP_BLK("sspp_3", SSPP_VIG3, 0xa000, VIG_SDM845_MASK,
+ sdm845_vig_sblk_3, 12, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG3),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
+ sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
+ SSPP_BLK("sspp_9", SSPP_DMA1, 0x26000, DMA_SDM845_MASK,
+ sdm845_dma_sblk_1, 5, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA1),
+ SSPP_BLK("sspp_10", SSPP_DMA2, 0x28000, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR0),
+ SSPP_BLK("sspp_11", SSPP_DMA3, 0x2a000, DMA_CURSOR_SDM845_MASK,
+ sdm845_dma_sblk_3, 13, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
};
/*************************************************************
@@ -227,48 +219,23 @@ static const struct dpu_lm_sub_blks sdm845_lm_sblk = {
},
};
-#define LM_BLK(_name, _id, _base, _ds, _pp, _lmpair) \
+#define LM_BLK(_name, _id, _base, _pp, _lmpair) \
{ \
.name = _name, .id = _id, \
.base = _base, .len = 0x320, \
.features = MIXER_SDM845_MASK, \
.sblk = &sdm845_lm_sblk, \
- .ds = _ds, \
.pingpong = _pp, \
.lm_pair_mask = (1 << _lmpair) \
}
static struct dpu_lm_cfg sdm845_lm[] = {
- LM_BLK("lm_0", LM_0, 0x44000, DS_0, PINGPONG_0, LM_1),
- LM_BLK("lm_1", LM_1, 0x45000, DS_1, PINGPONG_1, LM_0),
- LM_BLK("lm_2", LM_2, 0x46000, DS_MAX, PINGPONG_2, LM_5),
- LM_BLK("lm_3", LM_3, 0x0, DS_MAX, PINGPONG_MAX, 0),
- LM_BLK("lm_4", LM_4, 0x0, DS_MAX, PINGPONG_MAX, 0),
- LM_BLK("lm_5", LM_5, 0x49000, DS_MAX, PINGPONG_3, LM_2),
-};
-
-/*************************************************************
- * DS sub blocks config
- *************************************************************/
-static const struct dpu_ds_top_cfg sdm845_ds_top = {
- .name = "ds_top_0", .id = DS_TOP,
- .base = 0x60000, .len = 0xc,
- .maxinputwidth = DEFAULT_DPU_LINE_WIDTH,
- .maxoutputwidth = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
- .maxupscale = MAX_UPSCALE_RATIO,
-};
-
-#define DS_BLK(_name, _id, _base) \
- {\
- .name = _name, .id = _id, \
- .base = _base, .len = 0x800, \
- .features = DPU_SSPP_SCALER_QSEED3, \
- .top = &sdm845_ds_top \
- }
-
-static struct dpu_ds_cfg sdm845_ds[] = {
- DS_BLK("ds_0", DS_0, 0x800),
- DS_BLK("ds_1", DS_1, 0x1000),
+ LM_BLK("lm_0", LM_0, 0x44000, PINGPONG_0, LM_1),
+ LM_BLK("lm_1", LM_1, 0x45000, PINGPONG_1, LM_0),
+ LM_BLK("lm_2", LM_2, 0x46000, PINGPONG_2, LM_5),
+ LM_BLK("lm_3", LM_3, 0x0, PINGPONG_MAX, 0),
+ LM_BLK("lm_4", LM_4, 0x0, PINGPONG_MAX, 0),
+ LM_BLK("lm_5", LM_5, 0x49000, PINGPONG_3, LM_2),
};
/*************************************************************
@@ -328,18 +295,6 @@ static struct dpu_intf_cfg sdm845_intf[] = {
};
/*************************************************************
- * CDM sub blocks config
- *************************************************************/
-static struct dpu_cdm_cfg sdm845_cdm[] = {
- {
- .name = "cdm_0", .id = CDM_0,
- .base = 0x79200, .len = 0x224,
- .features = 0,
- .intf_connect = BIT(INTF_3),
- },
-};
-
-/*************************************************************
* VBIF sub blocks config
*************************************************************/
/* VBIF QOS remap */
@@ -461,12 +416,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.sspp = sdm845_sspp,
.mixer_count = ARRAY_SIZE(sdm845_lm),
.mixer = sdm845_lm,
- .ds_count = ARRAY_SIZE(sdm845_ds),
- .ds = sdm845_ds,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
- .cdm_count = ARRAY_SIZE(sdm845_cdm),
- .cdm = sdm845_cdm,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index f0cb0d4fc80e..dc060e7358e4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -428,7 +428,6 @@ struct dpu_clk_ctrl_reg {
* @highest_bank_bit: UBWC parameter
* @ubwc_static: ubwc static configuration
* @ubwc_swizzle: ubwc default swizzle setting
- * @has_dest_scaler: indicates support of destination scaler
* @clk_ctrls clock control register definition
*/
struct dpu_mdp_cfg {
@@ -436,7 +435,6 @@ struct dpu_mdp_cfg {
u32 highest_bank_bit;
u32 ubwc_static;
u32 ubwc_swizzle;
- bool has_dest_scaler;
struct dpu_clk_ctrl_reg clk_ctrls[DPU_CLK_CTRL_MAX];
};
@@ -474,50 +472,16 @@ struct dpu_sspp_cfg {
* @features bit mask identifying sub-blocks/features
* @sblk: LM Sub-blocks information
* @pingpong: ID of connected PingPong, PINGPONG_MAX if unsupported
- * @ds: ID of connected DS, DS_MAX if unsupported
* @lm_pair_mask: Bitmask of LMs that can be controlled by same CTL
*/
struct dpu_lm_cfg {
DPU_HW_BLK_INFO;
const struct dpu_lm_sub_blks *sblk;
u32 pingpong;
- u32 ds;
unsigned long lm_pair_mask;
};
/**
- * struct dpu_ds_top_cfg - information of dest scaler top
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying features
- * @version hw version of dest scaler
- * @maxinputwidth maximum input line width
- * @maxoutputwidth maximum output line width
- * @maxupscale maximum upscale ratio
- */
-struct dpu_ds_top_cfg {
- DPU_HW_BLK_INFO;
- u32 version;
- u32 maxinputwidth;
- u32 maxoutputwidth;
- u32 maxupscale;
-};
-
-/**
- * struct dpu_ds_cfg - information of dest scaler blocks
- * @id enum identifying this block
- * @base register offset wrt DS top offset
- * @features bit mask identifying features
- * @version hw version of the qseed block
- * @top DS top information
- */
-struct dpu_ds_cfg {
- DPU_HW_BLK_INFO;
- u32 version;
- const struct dpu_ds_top_cfg *top;
-};
-
-/**
* struct dpu_pingpong_cfg - information of PING-PONG blocks
* @id enum identifying this block
* @base register offset of this block
@@ -530,18 +494,6 @@ struct dpu_pingpong_cfg {
};
/**
- * struct dpu_cdm_cfg - information of chroma down blocks
- * @id enum identifying this block
- * @base register offset of this block
- * @features bit mask identifying sub-blocks/features
- * @intf_connect Bitmask of INTF IDs this CDM can connect to
- */
-struct dpu_cdm_cfg {
- DPU_HW_BLK_INFO;
- unsigned long intf_connect;
-};
-
-/**
* struct dpu_intf_cfg - information of timing engine blocks
* @id enum identifying this block
* @base register offset of this block
@@ -728,15 +680,9 @@ struct dpu_mdss_cfg {
u32 mixer_count;
struct dpu_lm_cfg *mixer;
- u32 ds_count;
- struct dpu_ds_cfg *ds;
-
u32 pingpong_count;
struct dpu_pingpong_cfg *pingpong;
- u32 cdm_count;
- struct dpu_cdm_cfg *cdm;
-
u32 intf_count;
struct dpu_intf_cfg *intf;
@@ -771,9 +717,7 @@ struct dpu_mdss_hw_cfg_handler {
#define BLK_DMA(s) ((s)->dma)
#define BLK_CURSOR(s) ((s)->cursor)
#define BLK_MIXER(s) ((s)->mixer)
-#define BLK_DS(s) ((s)->ds)
#define BLK_PINGPONG(s) ((s)->pingpong)
-#define BLK_CDM(s) ((s)->cdm)
#define BLK_INTF(s) ((s)->intf)
#define BLK_AD(s) ((s)->ad)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
deleted file mode 100644
index 554874ba0c3b..000000000000
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#include "dpu_hw_mdss.h"
-#include "dpu_hwio.h"
-#include "dpu_hw_catalog.h"
-#include "dpu_hw_cdm.h"
-#include "dpu_dbg.h"
-#include "dpu_kms.h"
-
-#define CDM_CSC_10_OPMODE 0x000
-#define CDM_CSC_10_BASE 0x004
-
-#define CDM_CDWN2_OP_MODE 0x100
-#define CDM_CDWN2_CLAMP_OUT 0x104
-#define CDM_CDWN2_PARAMS_3D_0 0x108
-#define CDM_CDWN2_PARAMS_3D_1 0x10C
-#define CDM_CDWN2_COEFF_COSITE_H_0 0x110
-#define CDM_CDWN2_COEFF_COSITE_H_1 0x114
-#define CDM_CDWN2_COEFF_COSITE_H_2 0x118
-#define CDM_CDWN2_COEFF_OFFSITE_H_0 0x11C
-#define CDM_CDWN2_COEFF_OFFSITE_H_1 0x120
-#define CDM_CDWN2_COEFF_OFFSITE_H_2 0x124
-#define CDM_CDWN2_COEFF_COSITE_V 0x128
-#define CDM_CDWN2_COEFF_OFFSITE_V 0x12C
-#define CDM_CDWN2_OUT_SIZE 0x130
-
-#define CDM_HDMI_PACK_OP_MODE 0x200
-#define CDM_CSC_10_MATRIX_COEFF_0 0x004
-
-/**
- * Horizontal coefficients for cosite chroma downscale
- * s13 representation of coefficients
- */
-static u32 cosite_h_coeff[] = {0x00000016, 0x000001cc, 0x0100009e};
-
-/**
- * Horizontal coefficients for offsite chroma downscale
- */
-static u32 offsite_h_coeff[] = {0x000b0005, 0x01db01eb, 0x00e40046};
-
-/**
- * Vertical coefficients for cosite chroma downscale
- */
-static u32 cosite_v_coeff[] = {0x00080004};
-/**
- * Vertical coefficients for offsite chroma downscale
- */
-static u32 offsite_v_coeff[] = {0x00060002};
-
-/* Limited Range rgb2yuv coeff with clamp and bias values for CSC 10 module */
-static struct dpu_csc_cfg rgb2yuv_cfg = {
- {
- 0x0083, 0x0102, 0x0032,
- 0x1fb5, 0x1f6c, 0x00e1,
- 0x00e1, 0x1f45, 0x1fdc
- },
- { 0x00, 0x00, 0x00 },
- { 0x0040, 0x0200, 0x0200 },
- { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff },
- { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 },
-};
-
-static struct dpu_cdm_cfg *_cdm_offset(enum dpu_cdm cdm,
- struct dpu_mdss_cfg *m,
- void __iomem *addr,
- struct dpu_hw_blk_reg_map *b)
-{
- int i;
-
- for (i = 0; i < m->cdm_count; i++) {
- if (cdm == m->cdm[i].id) {
- b->base_off = addr;
- b->blk_off = m->cdm[i].base;
- b->length = m->cdm[i].len;
- b->hwversion = m->hwversion;
- b->log_mask = DPU_DBG_MASK_CDM;
- return &m->cdm[i];
- }
- }
-
- return ERR_PTR(-EINVAL);
-}
-
-static int dpu_hw_cdm_setup_csc_10bit(struct dpu_hw_cdm *ctx,
- struct dpu_csc_cfg *data)
-{
- dpu_hw_csc_setup(&ctx->hw, CDM_CSC_10_MATRIX_COEFF_0, data, true);
-
- return 0;
-}
-
-static int dpu_hw_cdm_setup_cdwn(struct dpu_hw_cdm *ctx,
- struct dpu_hw_cdm_cfg *cfg)
-{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
- u32 opmode = 0;
- u32 out_size = 0;
-
- if (cfg->output_bit_depth == CDM_CDWN_OUTPUT_10BIT)
- opmode &= ~BIT(7);
- else
- opmode |= BIT(7);
-
- /* ENABLE DWNS_H bit */
- opmode |= BIT(1);
-
- switch (cfg->h_cdwn_type) {
- case CDM_CDWN_DISABLE:
- /* CLEAR METHOD_H field */
- opmode &= ~(0x18);
- /* CLEAR DWNS_H bit */
- opmode &= ~BIT(1);
- break;
- case CDM_CDWN_PIXEL_DROP:
- /* Clear METHOD_H field (pixel drop is 0) */
- opmode &= ~(0x18);
- break;
- case CDM_CDWN_AVG:
- /* Clear METHOD_H field (Average is 0x1) */
- opmode &= ~(0x18);
- opmode |= (0x1 << 0x3);
- break;
- case CDM_CDWN_COSITE:
- /* Clear METHOD_H field (Average is 0x2) */
- opmode &= ~(0x18);
- opmode |= (0x2 << 0x3);
- /* Co-site horizontal coefficients */
- DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_0,
- cosite_h_coeff[0]);
- DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_1,
- cosite_h_coeff[1]);
- DPU_REG_WRITE(c, CDM_CDWN2_COEFF_COSITE_H_2,
- cosite_h_coeff[2]);
- break;
- case CDM_CDWN_OFFSITE:
- /* Clear METHOD_H field (Average is 0x3) */
- opmode &= ~(0x18);
- opmode |= (0x3 << 0x3);
-
- /* Off-site horizontal coefficients */
- DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_0,
- offsite_h_coeff[0]);
- DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_1,
- offsite_h_coeff[1]);
- DPU_REG_WRITE(c, CDM_CDWN2_COEFF_OFFSITE_H_2,
- offsite_h_coeff[2]);
- break;
- default:
- pr_err("%s invalid horz down sampling type\n", __func__);
- return -EINVAL;
- }
-
- /* ENABLE DWNS_V bit */
- opmode |= BIT(2);
-
- switch (cfg->v_cdwn_type) {
- case CDM_CDWN_DISABLE:
- /* CLEAR METHOD_V field */
- opmode &= ~(0x60);
- /* CLEAR DWNS_V bit */
- opmode &= ~BIT(2);
- break;
- case CDM_CDWN_PIXEL_DROP:
- /* Clear METHOD_V field (pixel drop is 0) */
- opmode &= ~(0x60);
- break;
- case CDM_CDWN_AVG:
- /* Clear METHOD_V field (Average is 0x1) */
- opmode &= ~(0x60);
- opmode |= (0x1 << 0x5);
- break;
- case CDM_CDWN_COSITE:
- /* Clear METHOD_V field (Average is 0x2) */
- opmode &= ~(0x60);
- opmode |= (0x2 << 0x5);
- /* Co-site vertical coefficients */
- DPU_REG_WRITE(c,
- CDM_CDWN2_COEFF_COSITE_V,
- cosite_v_coeff[0]);
- break;
- case CDM_CDWN_OFFSITE:
- /* Clear METHOD_V field (Average is 0x3) */
- opmode &= ~(0x60);
- opmode |= (0x3 << 0x5);
-
- /* Off-site vertical coefficients */
- DPU_REG_WRITE(c,
- CDM_CDWN2_COEFF_OFFSITE_V,
- offsite_v_coeff[0]);
- break;
- default:
- return -EINVAL;
- }
-
- if (cfg->v_cdwn_type || cfg->h_cdwn_type)
- opmode |= BIT(0); /* EN CDWN module */
- else
- opmode &= ~BIT(0);
-
- out_size = (cfg->output_width & 0xFFFF) |
- ((cfg->output_height & 0xFFFF) << 16);
- DPU_REG_WRITE(c, CDM_CDWN2_OUT_SIZE, out_size);
- DPU_REG_WRITE(c, CDM_CDWN2_OP_MODE, opmode);
- DPU_REG_WRITE(c, CDM_CDWN2_CLAMP_OUT,
- ((0x3FF << 16) | 0x0));
-
- return 0;
-}
-
-static int dpu_hw_cdm_enable(struct dpu_hw_cdm *ctx,
- struct dpu_hw_cdm_cfg *cdm)
-{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
- const struct dpu_format *fmt = cdm->output_fmt;
- struct cdm_output_cfg cdm_cfg = { 0 };
- u32 opmode = 0;
- u32 csc = 0;
-
- if (!DPU_FORMAT_IS_YUV(fmt))
- return -EINVAL;
-
- if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) {
- if (fmt->chroma_sample != DPU_CHROMA_H1V2)
- return -EINVAL; /*unsupported format */
- opmode = BIT(0);
- opmode |= (fmt->chroma_sample << 1);
- cdm_cfg.intf_en = true;
- }
-
- csc |= BIT(2);
- csc &= ~BIT(1);
- csc |= BIT(0);
-
- if (ctx->hw_mdp && ctx->hw_mdp->ops.setup_cdm_output)
- ctx->hw_mdp->ops.setup_cdm_output(ctx->hw_mdp, &cdm_cfg);
-
- DPU_REG_WRITE(c, CDM_CSC_10_OPMODE, csc);
- DPU_REG_WRITE(c, CDM_HDMI_PACK_OP_MODE, opmode);
- return 0;
-}
-
-static void dpu_hw_cdm_disable(struct dpu_hw_cdm *ctx)
-{
- struct cdm_output_cfg cdm_cfg = { 0 };
-
- if (ctx->hw_mdp && ctx->hw_mdp->ops.setup_cdm_output)
- ctx->hw_mdp->ops.setup_cdm_output(ctx->hw_mdp, &cdm_cfg);
-}
-
-static void _setup_cdm_ops(struct dpu_hw_cdm_ops *ops,
- unsigned long features)
-{
- ops->setup_csc_data = dpu_hw_cdm_setup_csc_10bit;
- ops->setup_cdwn = dpu_hw_cdm_setup_cdwn;
- ops->enable = dpu_hw_cdm_enable;
- ops->disable = dpu_hw_cdm_disable;
-}
-
-static struct dpu_hw_blk_ops dpu_hw_ops = {
- .start = NULL,
- .stop = NULL,
-};
-
-struct dpu_hw_cdm *dpu_hw_cdm_init(enum dpu_cdm idx,
- void __iomem *addr,
- struct dpu_mdss_cfg *m,
- struct dpu_hw_mdp *hw_mdp)
-{
- struct dpu_hw_cdm *c;
- struct dpu_cdm_cfg *cfg;
- int rc;
-
- c = kzalloc(sizeof(*c), GFP_KERNEL);
- if (!c)
- return ERR_PTR(-ENOMEM);
-
- cfg = _cdm_offset(idx, m, addr, &c->hw);
- if (IS_ERR_OR_NULL(cfg)) {
- kfree(c);
- return ERR_PTR(-EINVAL);
- }
-
- c->idx = idx;
- c->caps = cfg;
- _setup_cdm_ops(&c->ops, c->caps->features);
- c->hw_mdp = hw_mdp;
-
- rc = dpu_hw_blk_init(&c->base, DPU_HW_BLK_CDM, idx, &dpu_hw_ops);
- if (rc) {
- DPU_ERROR("failed to init hw blk %d\n", rc);
- goto blk_init_error;
- }
-
- /*
- * Perform any default initialization for the chroma down module
- * @setup default csc coefficients
- */
- dpu_hw_cdm_setup_csc_10bit(c, &rgb2yuv_cfg);
-
- return c;
-
-blk_init_error:
- kzfree(c);
-
- return ERR_PTR(rc);
-}
-
-void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm)
-{
- if (cdm)
- dpu_hw_blk_destroy(&cdm->base);
- kfree(cdm);
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
deleted file mode 100644
index 5cceb1ecb8e0..000000000000
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cdm.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
-
-#ifndef _DPU_HW_CDM_H
-#define _DPU_HW_CDM_H
-
-#include "dpu_hw_mdss.h"
-#include "dpu_hw_top.h"
-#include "dpu_hw_blk.h"
-
-struct dpu_hw_cdm;
-
-struct dpu_hw_cdm_cfg {
- u32 output_width;
- u32 output_height;
- u32 output_bit_depth;
- u32 h_cdwn_type;
- u32 v_cdwn_type;
- const struct dpu_format *output_fmt;
- u32 output_type;
- int flags;
-};
-
-enum dpu_hw_cdwn_type {
- CDM_CDWN_DISABLE,
- CDM_CDWN_PIXEL_DROP,
- CDM_CDWN_AVG,
- CDM_CDWN_COSITE,
- CDM_CDWN_OFFSITE,
-};
-
-enum dpu_hw_cdwn_output_type {
- CDM_CDWN_OUTPUT_HDMI,
- CDM_CDWN_OUTPUT_WB,
-};
-
-enum dpu_hw_cdwn_output_bit_depth {
- CDM_CDWN_OUTPUT_8BIT,
- CDM_CDWN_OUTPUT_10BIT,
-};
-
-/**
- * struct dpu_hw_cdm_ops : Interface to the chroma down Hw driver functions
- * Assumption is these functions will be called after
- * clocks are enabled
- * @setup_csc: Programs the csc matrix
- * @setup_cdwn: Sets up the chroma down sub module
- * @enable: Enables the output to interface and programs the
- * output packer
- * @disable: Puts the cdm in bypass mode
- */
-struct dpu_hw_cdm_ops {
- /**
- * Programs the CSC matrix for conversion from RGB space to YUV space,
- * it is optional to call this function as this matrix is automatically
- * set during initialization, user should call this if it wants
- * to program a different matrix than default matrix.
- * @cdm: Pointer to the chroma down context structure
- * @data Pointer to CSC configuration data
- * return: 0 if success; error code otherwise
- */
- int (*setup_csc_data)(struct dpu_hw_cdm *cdm,
- struct dpu_csc_cfg *data);
-
- /**
- * Programs the Chroma downsample part.
- * @cdm Pointer to chroma down context
- */
- int (*setup_cdwn)(struct dpu_hw_cdm *cdm,
- struct dpu_hw_cdm_cfg *cfg);
-
- /**
- * Enable the CDM module
- * @cdm Pointer to chroma down context
- */
- int (*enable)(struct dpu_hw_cdm *cdm,
- struct dpu_hw_cdm_cfg *cfg);
-
- /**
- * Disable the CDM module
- * @cdm Pointer to chroma down context
- */
- void (*disable)(struct dpu_hw_cdm *cdm);
-};
-
-struct dpu_hw_cdm {
- struct dpu_hw_blk base;
- struct dpu_hw_blk_reg_map hw;
-
- /* chroma down */
- const struct dpu_cdm_cfg *caps;
- enum dpu_cdm idx;
-
- /* mdp top hw driver */
- struct dpu_hw_mdp *hw_mdp;
-
- /* ops */
- struct dpu_hw_cdm_ops ops;
-};
-
-/**
- * dpu_hw_cdm - convert base object dpu_hw_base to container
- * @hw: Pointer to base hardware block
- * return: Pointer to hardware block container
- */
-static inline struct dpu_hw_cdm *to_dpu_hw_cdm(struct dpu_hw_blk *hw)
-{
- return container_of(hw, struct dpu_hw_cdm, base);
-}
-
-/**
- * dpu_hw_cdm_init - initializes the cdm hw driver object.
- * should be called once before accessing every cdm.
- * @idx: cdm index for which driver object is required
- * @addr: mapped register io address of MDP
- * @m : pointer to mdss catalog data
- * @hw_mdp: pointer to mdp top hw driver object
- */
-struct dpu_hw_cdm *dpu_hw_cdm_init(enum dpu_cdm idx,
- void __iomem *addr,
- struct dpu_mdss_cfg *m,
- struct dpu_hw_mdp *hw_mdp);
-
-/**
- * dpu_hw_cdm_destroy - destroys CDM driver context
- * @cdm: pointer to CDM driver context
- */
-void dpu_hw_cdm_destroy(struct dpu_hw_cdm *cdm);
-
-#endif /*_DPU_HW_CDM_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 06be7cf7ce50..eec1051f2afc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -224,19 +224,6 @@ static inline int dpu_hw_ctl_get_bitmask_intf(struct dpu_hw_ctl *ctx,
return 0;
}
-static inline int dpu_hw_ctl_get_bitmask_cdm(struct dpu_hw_ctl *ctx,
- u32 *flushbits, enum dpu_cdm cdm)
-{
- switch (cdm) {
- case CDM_0:
- *flushbits |= BIT(26);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
static u32 dpu_hw_ctl_poll_reset_status(struct dpu_hw_ctl *ctx, u32 timeout_us)
{
struct dpu_hw_blk_reg_map *c = &ctx->hw;
@@ -310,7 +297,7 @@ static void dpu_hw_ctl_setup_blendstage(struct dpu_hw_ctl *ctx,
u32 mixercfg = 0, mixercfg_ext = 0, mix, ext;
u32 mixercfg_ext2 = 0, mixercfg_ext3 = 0;
int i, j;
- u8 stages;
+ int stages;
int pipes_per_stage;
stages = _mixer_stages(ctx->mixer_hw_caps, ctx->mixer_count, lm);
@@ -485,7 +472,6 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->get_bitmask_sspp = dpu_hw_ctl_get_bitmask_sspp;
ops->get_bitmask_mixer = dpu_hw_ctl_get_bitmask_mixer;
ops->get_bitmask_intf = dpu_hw_ctl_get_bitmask_intf;
- ops->get_bitmask_cdm = dpu_hw_ctl_get_bitmask_cdm;
};
static struct dpu_hw_blk_ops dpu_hw_ops = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index c66a71f8b839..6f313faca43e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -142,10 +142,6 @@ struct dpu_hw_ctl_ops {
u32 *flushbits,
enum dpu_intf blk);
- int (*get_bitmask_cdm)(struct dpu_hw_ctl *ctx,
- u32 *flushbits,
- enum dpu_cdm blk);
-
/**
* Set all blend stages to disabled
* @ctx : ctl path ctx pointer
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index d280df5613c9..9c6bba0ac7c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -65,9 +65,6 @@
#define INTF_FRAME_COUNT 0x0AC
#define INTF_LINE_COUNT 0x0B0
-#define INTF_MISR_CTRL 0x180
-#define INTF_MISR_SIGNATURE 0x184
-
static struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf,
struct dpu_mdss_cfg *m,
void __iomem *addr,
@@ -246,30 +243,6 @@ static void dpu_hw_intf_get_status(
}
}
-static void dpu_hw_intf_setup_misr(struct dpu_hw_intf *intf,
- bool enable, u32 frame_count)
-{
- struct dpu_hw_blk_reg_map *c = &intf->hw;
- u32 config = 0;
-
- DPU_REG_WRITE(c, INTF_MISR_CTRL, MISR_CTRL_STATUS_CLEAR);
- /* clear misr data */
- wmb();
-
- if (enable)
- config = (frame_count & MISR_FRAME_COUNT_MASK) |
- MISR_CTRL_ENABLE | INTF_MISR_CTRL_FREE_RUN_MASK;
-
- DPU_REG_WRITE(c, INTF_MISR_CTRL, config);
-}
-
-static u32 dpu_hw_intf_collect_misr(struct dpu_hw_intf *intf)
-{
- struct dpu_hw_blk_reg_map *c = &intf->hw;
-
- return DPU_REG_READ(c, INTF_MISR_SIGNATURE);
-}
-
static u32 dpu_hw_intf_get_line_count(struct dpu_hw_intf *intf)
{
struct dpu_hw_blk_reg_map *c;
@@ -289,8 +262,6 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
ops->setup_prg_fetch = dpu_hw_intf_setup_prg_fetch;
ops->get_status = dpu_hw_intf_get_status;
ops->enable_timing = dpu_hw_intf_enable_timing_engine;
- ops->setup_misr = dpu_hw_intf_setup_misr;
- ops->collect_misr = dpu_hw_intf_collect_misr;
ops->get_line_count = dpu_hw_intf_get_line_count;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index a79d735da68d..3b77df460dea 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -59,8 +59,6 @@ struct intf_status {
* @ setup_prog_fetch : enables/disables the programmable fetch logic
* @ enable_timing: enable/disable timing engine
* @ get_status: returns if timing engine is enabled or not
- * @ setup_misr: enables/disables MISR in HW register
- * @ collect_misr: reads and stores MISR data from HW register
* @ get_line_count: reads current vertical line counter
*/
struct dpu_hw_intf_ops {
@@ -77,11 +75,6 @@ struct dpu_hw_intf_ops {
void (*get_status)(struct dpu_hw_intf *intf,
struct intf_status *status);
- void (*setup_misr)(struct dpu_hw_intf *intf,
- bool enable, u32 frame_count);
-
- u32 (*collect_misr)(struct dpu_hw_intf *intf);
-
u32 (*get_line_count)(struct dpu_hw_intf *intf);
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
index 4ab72b0f07a5..acb8dc8acaa5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c
@@ -34,9 +34,6 @@
#define LM_BLEND0_FG_ALPHA 0x04
#define LM_BLEND0_BG_ALPHA 0x08
-#define LM_MISR_CTRL 0x310
-#define LM_MISR_SIGNATURE 0x314
-
static struct dpu_lm_cfg *_lm_offset(enum dpu_lm mixer,
struct dpu_mdss_cfg *m,
void __iomem *addr,
@@ -171,30 +168,6 @@ static void dpu_hw_lm_gc(struct dpu_hw_mixer *mixer,
{
}
-static void dpu_hw_lm_setup_misr(struct dpu_hw_mixer *ctx,
- bool enable, u32 frame_count)
-{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
- u32 config = 0;
-
- DPU_REG_WRITE(c, LM_MISR_CTRL, MISR_CTRL_STATUS_CLEAR);
- /* clear misr data */
- wmb();
-
- if (enable)
- config = (frame_count & MISR_FRAME_COUNT_MASK) |
- MISR_CTRL_ENABLE | INTF_MISR_CTRL_FREE_RUN_MASK;
-
- DPU_REG_WRITE(c, LM_MISR_CTRL, config);
-}
-
-static u32 dpu_hw_lm_collect_misr(struct dpu_hw_mixer *ctx)
-{
- struct dpu_hw_blk_reg_map *c = &ctx->hw;
-
- return DPU_REG_READ(c, LM_MISR_SIGNATURE);
-}
-
static void _setup_mixer_ops(struct dpu_mdss_cfg *m,
struct dpu_hw_lm_ops *ops,
unsigned long features)
@@ -207,8 +180,6 @@ static void _setup_mixer_ops(struct dpu_mdss_cfg *m,
ops->setup_alpha_out = dpu_hw_lm_setup_color3;
ops->setup_border_color = dpu_hw_lm_setup_border_color;
ops->setup_gc = dpu_hw_lm_gc;
- ops->setup_misr = dpu_hw_lm_setup_misr;
- ops->collect_misr = dpu_hw_lm_collect_misr;
};
static struct dpu_hw_blk_ops dpu_hw_ops = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
index e29e5dab31bf..5b036aca8340 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h
@@ -66,13 +66,6 @@ struct dpu_hw_lm_ops {
*/
void (*setup_gc)(struct dpu_hw_mixer *mixer,
void *cfg);
-
- /* setup_misr: enables/disables MISR in HW register */
- void (*setup_misr)(struct dpu_hw_mixer *ctx,
- bool enable, u32 frame_count);
-
- /* collect_misr: reads and stores MISR data from HW register */
- u32 (*collect_misr)(struct dpu_hw_mixer *ctx);
};
struct dpu_hw_mixer {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index 35e6bf930924..68c54d2c9677 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -100,7 +100,6 @@ enum dpu_hw_blk_type {
DPU_HW_BLK_SSPP,
DPU_HW_BLK_LM,
DPU_HW_BLK_CTL,
- DPU_HW_BLK_CDM,
DPU_HW_BLK_PINGPONG,
DPU_HW_BLK_INTF,
DPU_HW_BLK_WB,
@@ -173,13 +172,6 @@ enum dpu_dspp {
DSPP_MAX
};
-enum dpu_ds {
- DS_TOP,
- DS_0,
- DS_1,
- DS_MAX
-};
-
enum dpu_ctl {
CTL_0 = 1,
CTL_1,
@@ -189,12 +181,6 @@ enum dpu_ctl {
CTL_MAX
};
-enum dpu_cdm {
- CDM_0 = 1,
- CDM_1,
- CDM_MAX
-};
-
enum dpu_pingpong {
PINGPONG_0 = 1,
PINGPONG_1,
@@ -246,12 +232,6 @@ enum dpu_wb {
WB_MAX
};
-enum dpu_ad {
- AD_0 = 0x1,
- AD_1,
- AD_MAX
-};
-
enum dpu_cwb {
CWB_0 = 0x1,
CWB_1,
@@ -451,15 +431,14 @@ struct dpu_mdss_color {
* Define bit masks for h/w logging.
*/
#define DPU_DBG_MASK_NONE (1 << 0)
-#define DPU_DBG_MASK_CDM (1 << 1)
-#define DPU_DBG_MASK_INTF (1 << 2)
-#define DPU_DBG_MASK_LM (1 << 3)
-#define DPU_DBG_MASK_CTL (1 << 4)
-#define DPU_DBG_MASK_PINGPONG (1 << 5)
-#define DPU_DBG_MASK_SSPP (1 << 6)
-#define DPU_DBG_MASK_WB (1 << 7)
-#define DPU_DBG_MASK_TOP (1 << 8)
-#define DPU_DBG_MASK_VBIF (1 << 9)
-#define DPU_DBG_MASK_ROT (1 << 10)
+#define DPU_DBG_MASK_INTF (1 << 1)
+#define DPU_DBG_MASK_LM (1 << 2)
+#define DPU_DBG_MASK_CTL (1 << 3)
+#define DPU_DBG_MASK_PINGPONG (1 << 4)
+#define DPU_DBG_MASK_SSPP (1 << 5)
+#define DPU_DBG_MASK_WB (1 << 6)
+#define DPU_DBG_MASK_TOP (1 << 7)
+#define DPU_DBG_MASK_VBIF (1 << 8)
+#define DPU_DBG_MASK_ROT (1 << 9)
#endif /* _DPU_HW_MDSS_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index db2798e862fc..b8781256e21b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -98,23 +98,6 @@ static void dpu_hw_setup_split_pipe(struct dpu_hw_mdp *mdp,
DPU_REG_WRITE(c, SPLIT_DISPLAY_EN, cfg->en & 0x1);
}
-static void dpu_hw_setup_cdm_output(struct dpu_hw_mdp *mdp,
- struct cdm_output_cfg *cfg)
-{
- struct dpu_hw_blk_reg_map *c;
- u32 out_ctl = 0;
-
- if (!mdp || !cfg)
- return;
-
- c = &mdp->hw;
-
- if (cfg->intf_en)
- out_ctl |= BIT(19);
-
- DPU_REG_WRITE(c, MDP_OUT_CTL_0, out_ctl);
-}
-
static bool dpu_hw_setup_clk_force_ctrl(struct dpu_hw_mdp *mdp,
enum dpu_clk_ctrl_type clk_ctrl, bool enable)
{
@@ -307,7 +290,6 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
unsigned long cap)
{
ops->setup_split_pipe = dpu_hw_setup_split_pipe;
- ops->setup_cdm_output = dpu_hw_setup_cdm_output;
ops->setup_clk_force_ctrl = dpu_hw_setup_clk_force_ctrl;
ops->get_danger_status = dpu_hw_get_danger_status;
ops->setup_vsync_source = dpu_hw_setup_vsync_source;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 899925aaa6d7..192e338f20bb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -52,14 +52,6 @@ struct split_pipe_cfg {
};
/**
- * struct cdm_output_cfg: output configuration for cdm
- * @intf_en : enable/disable interface output
- */
-struct cdm_output_cfg {
- bool intf_en;
-};
-
-/**
* struct dpu_danger_safe_status: danger and safe status signals
* @mdp: top level status
* @sspp: source pipe status
@@ -89,7 +81,6 @@ struct dpu_vsync_source_cfg {
* Assumption is these functions will be called after clocks are enabled.
* @setup_split_pipe : Programs the pipe control registers
* @setup_pp_split : Programs the pp split control registers
- * @setup_cdm_output : programs cdm control
* @setup_traffic_shaper : programs traffic shaper control
*/
struct dpu_hw_mdp_ops {
@@ -102,14 +93,6 @@ struct dpu_hw_mdp_ops {
struct split_pipe_cfg *p);
/**
- * setup_cdm_output() : Setup selection control of the cdm data path
- * @mdp : mdp top context driver
- * @cfg : cdm output configuration
- */
- void (*setup_cdm_output)(struct dpu_hw_mdp *mdp,
- struct cdm_output_cfg *cfg);
-
- /**
* setup_traffic_shaper() : Setup traffic shaper control
* @mdp : mdp top context driver
* @cfg : traffic shaper configuration
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
index 4cabae480a7b..cb5c0170374b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c
@@ -50,9 +50,6 @@ static u32 dpu_hw_util_log_mask = DPU_DBG_MASK_NONE;
#define QSEED3_CLK_CTRL0 0x54
#define QSEED3_CLK_CTRL1 0x58
#define QSEED3_CLK_STATUS 0x5C
-#define QSEED3_MISR_CTRL 0x70
-#define QSEED3_MISR_SIGNATURE_0 0x74
-#define QSEED3_MISR_SIGNATURE_1 0x78
#define QSEED3_PHASE_INIT_Y_H 0x90
#define QSEED3_PHASE_INIT_Y_V 0x94
#define QSEED3_PHASE_INIT_UV_H 0x98
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
index 1240f505ca53..321fc64ddd0e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h
@@ -148,16 +148,6 @@ struct dpu_hw_scaler3_cfg {
struct dpu_hw_scaler3_de_cfg de;
};
-struct dpu_hw_scaler3_lut_cfg {
- bool is_configured;
- u32 *dir_lut;
- size_t dir_len;
- u32 *cir_lut;
- size_t cir_len;
- u32 *sep_lut;
- size_t sep_len;
-};
-
/**
* struct dpu_drm_pix_ext_v1 - version 1 of pixel ext structure
* @num_ext_pxls_lr: Number of total horizontal pixels
@@ -325,12 +315,6 @@ int dpu_reg_read(struct dpu_hw_blk_reg_map *c, u32 reg_off);
#define DPU_REG_WRITE(c, off, val) dpu_reg_write(c, off, val, #off)
#define DPU_REG_READ(c, off) dpu_reg_read(c, off)
-#define MISR_FRAME_COUNT_MASK 0xFF
-#define MISR_CTRL_ENABLE BIT(8)
-#define MISR_CTRL_STATUS BIT(9)
-#define MISR_CTRL_STATUS_CLEAR BIT(10)
-#define INTF_MISR_CTRL_FREE_RUN_MASK BIT(31)
-
void *dpu_hw_util_get_dir(void);
void dpu_hw_setup_scaler3(struct dpu_hw_blk_reg_map *c,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 7dd6bd2d6d37..0a683e65a9f3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -450,7 +450,7 @@ static void _dpu_kms_initialize_dsi(struct drm_device *dev,
int i, rc;
/*TODO: Support two independent DSI connectors */
- encoder = dpu_encoder_init(dev, DRM_MODE_CONNECTOR_DSI);
+ encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
if (IS_ERR_OR_NULL(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
return;
@@ -531,12 +531,13 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
{
struct drm_device *dev;
struct drm_plane *primary_planes[MAX_PLANES], *plane;
+ struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
struct drm_crtc *crtc;
struct msm_drm_private *priv;
struct dpu_mdss_cfg *catalog;
- int primary_planes_idx = 0, i, ret;
+ int primary_planes_idx = 0, cursor_planes_idx = 0, i, ret;
int max_crtc_count;
if (!dpu_kms || !dpu_kms->dev || !dpu_kms->dev->dev) {
@@ -556,16 +557,24 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
max_crtc_count = min(catalog->mixer_count, priv->num_encoders);
- /* Create the planes */
+ /* Create the planes, keeping track of one primary/cursor per crtc */
for (i = 0; i < catalog->sspp_count; i++) {
- bool primary = true;
-
- if (catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR)
- || primary_planes_idx >= max_crtc_count)
- primary = false;
-
- plane = dpu_plane_init(dev, catalog->sspp[i].id, primary,
- (1UL << max_crtc_count) - 1, 0);
+ enum drm_plane_type type;
+
+ if ((catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR))
+ && cursor_planes_idx < max_crtc_count)
+ type = DRM_PLANE_TYPE_CURSOR;
+ else if (primary_planes_idx < max_crtc_count)
+ type = DRM_PLANE_TYPE_PRIMARY;
+ else
+ type = DRM_PLANE_TYPE_OVERLAY;
+
+ DPU_DEBUG("Create plane type %d with features %lx (cur %lx)\n",
+ type, catalog->sspp[i].features,
+ catalog->sspp[i].features & BIT(DPU_SSPP_CURSOR));
+
+ plane = dpu_plane_init(dev, catalog->sspp[i].id, type,
+ (1UL << max_crtc_count) - 1, 0);
if (IS_ERR(plane)) {
DPU_ERROR("dpu_plane_init failed\n");
ret = PTR_ERR(plane);
@@ -573,7 +582,9 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
}
priv->planes[priv->num_planes++] = plane;
- if (primary)
+ if (type == DRM_PLANE_TYPE_CURSOR)
+ cursor_planes[cursor_planes_idx++] = plane;
+ else if (type == DRM_PLANE_TYPE_PRIMARY)
primary_planes[primary_planes_idx++] = plane;
}
@@ -581,7 +592,7 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
/* Create one CRTC per encoder */
for (i = 0; i < max_crtc_count; i++) {
- crtc = dpu_crtc_init(dev, primary_planes[i]);
+ crtc = dpu_crtc_init(dev, primary_planes[i], cursor_planes[i]);
if (IS_ERR(crtc)) {
ret = PTR_ERR(crtc);
goto fail;
@@ -956,8 +967,7 @@ static void dpu_kms_handle_power_event(u32 event_type, void *usr)
if (!dpu_kms)
return;
- if (event_type == DPU_POWER_EVENT_POST_ENABLE)
- dpu_vbif_init_memtypes(dpu_kms);
+ dpu_vbif_init_memtypes(dpu_kms);
}
static int dpu_kms_hw_init(struct msm_kms *kms)
@@ -1144,10 +1154,9 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
/*
* Handle (re)initializations during power enable
*/
- dpu_kms_handle_power_event(DPU_POWER_EVENT_POST_ENABLE, dpu_kms);
+ dpu_kms_handle_power_event(DPU_POWER_EVENT_ENABLE, dpu_kms);
dpu_kms->power_event = dpu_power_handle_register_event(
- &dpu_kms->phandle,
- DPU_POWER_EVENT_POST_ENABLE,
+ &dpu_kms->phandle, DPU_POWER_EVENT_ENABLE,
dpu_kms_handle_power_event, dpu_kms, "kms");
pm_runtime_put_sync(&dpu_kms->pdev->dev);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
index 9e533b86682c..2235ef8129f4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c
@@ -158,6 +158,8 @@ static void dpu_mdss_destroy(struct drm_device *dev)
_dpu_mdss_irq_domain_fini(dpu_mdss);
+ free_irq(platform_get_irq(pdev, 0), dpu_mdss);
+
msm_dss_put_clk(mp->clk_config, mp->num_clk);
devm_kfree(&pdev->dev, mp->clk_config);
@@ -215,7 +217,7 @@ int dpu_mdss_init(struct drm_device *dev)
if (ret)
goto irq_domain_error;
- ret = devm_request_irq(dev->dev, platform_get_irq(pdev, 0),
+ ret = request_irq(platform_get_irq(pdev, 0),
dpu_mdss_irq, 0, "dpu_mdss_isr", dpu_mdss);
if (ret) {
DPU_ERROR("failed to init irq: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 015341e2dd4c..f549daf30fe6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -125,26 +125,11 @@ struct dpu_plane {
static struct dpu_kms *_dpu_plane_get_kms(struct drm_plane *plane)
{
- struct msm_drm_private *priv;
+ struct msm_drm_private *priv = plane->dev->dev_private;
- if (!plane || !plane->dev)
- return NULL;
- priv = plane->dev->dev_private;
- if (!priv)
- return NULL;
return to_dpu_kms(priv->kms);
}
-static bool dpu_plane_enabled(struct drm_plane_state *state)
-{
- return state && state->fb && state->crtc;
-}
-
-static bool dpu_plane_sspp_enabled(struct drm_plane_state *state)
-{
- return state && state->crtc;
-}
-
/**
* _dpu_plane_calc_fill_level - calculate fill level of the given source format
* @plane: Pointer to drm plane
@@ -160,7 +145,7 @@ static inline int _dpu_plane_calc_fill_level(struct drm_plane *plane,
u32 fixed_buff_size;
u32 total_fl;
- if (!plane || !fmt || !plane->state || !src_width || !fmt->bpp) {
+ if (!fmt || !plane->state || !src_width || !fmt->bpp) {
DPU_ERROR("invalid arguments\n");
return 0;
}
@@ -170,7 +155,7 @@ static inline int _dpu_plane_calc_fill_level(struct drm_plane *plane,
fixed_buff_size = pdpu->pipe_sblk->common->pixel_ram_size;
list_for_each_entry(tmp, &pdpu->mplane_list, mplane_list) {
- if (!dpu_plane_enabled(tmp->base.state))
+ if (!tmp->base.state->visible)
continue;
DPU_DEBUG("plane%d/%d src_width:%d/%d\n",
pdpu->base.base.id, tmp->base.base.id,
@@ -241,26 +226,11 @@ static u64 _dpu_plane_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
struct drm_framebuffer *fb)
{
- struct dpu_plane *pdpu;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
const struct dpu_format *fmt = NULL;
u64 qos_lut;
u32 total_fl = 0, lut_usage;
- if (!plane || !fb) {
- DPU_ERROR("invalid arguments plane %d fb %d\n",
- plane != 0, fb != 0);
- return;
- }
-
- pdpu = to_dpu_plane(plane);
-
- if (!pdpu->pipe_hw || !pdpu->pipe_sblk || !pdpu->catalog) {
- DPU_ERROR("invalid arguments\n");
- return;
- } else if (!pdpu->pipe_hw->ops.setup_creq_lut) {
- return;
- }
-
if (!pdpu->is_rt_pipe) {
lut_usage = DPU_QOS_LUT_USAGE_NRT;
} else {
@@ -302,24 +272,10 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
struct drm_framebuffer *fb)
{
- struct dpu_plane *pdpu;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
const struct dpu_format *fmt = NULL;
u32 danger_lut, safe_lut;
- if (!plane || !fb) {
- DPU_ERROR("invalid arguments\n");
- return;
- }
-
- pdpu = to_dpu_plane(plane);
-
- if (!pdpu->pipe_hw || !pdpu->pipe_sblk || !pdpu->catalog) {
- DPU_ERROR("invalid arguments\n");
- return;
- } else if (!pdpu->pipe_hw->ops.setup_danger_safe_lut) {
- return;
- }
-
if (!pdpu->is_rt_pipe) {
danger_lut = pdpu->catalog->perf.danger_lut_tbl
[DPU_QOS_LUT_USAGE_NRT];
@@ -373,21 +329,7 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
bool enable, u32 flags)
{
- struct dpu_plane *pdpu;
-
- if (!plane) {
- DPU_ERROR("invalid arguments\n");
- return;
- }
-
- pdpu = to_dpu_plane(plane);
-
- if (!pdpu->pipe_hw || !pdpu->pipe_sblk) {
- DPU_ERROR("invalid arguments\n");
- return;
- } else if (!pdpu->pipe_hw->ops.setup_qos_ctrl) {
- return;
- }
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
if (flags & DPU_PLANE_QOS_VBLANK_CTRL) {
pdpu->pipe_qos_cfg.creq_vblank = pdpu->pipe_sblk->creq_vblank;
@@ -423,35 +365,17 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
&pdpu->pipe_qos_cfg);
}
-int dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
+static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
{
- struct dpu_plane *pdpu;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
-
- if (!plane || !plane->dev) {
- DPU_ERROR("invalid arguments\n");
- return -EINVAL;
- }
-
- priv = plane->dev->dev_private;
- if (!priv || !priv->kms) {
- DPU_ERROR("invalid KMS reference\n");
- return -EINVAL;
- }
-
- dpu_kms = to_dpu_kms(priv->kms);
- pdpu = to_dpu_plane(plane);
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
if (!pdpu->is_rt_pipe)
- goto end;
+ return;
pm_runtime_get_sync(&dpu_kms->pdev->dev);
_dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
pm_runtime_put_sync(&dpu_kms->pdev->dev);
-
-end:
- return 0;
}
/**
@@ -462,29 +386,9 @@ end:
static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
struct drm_crtc *crtc)
{
- struct dpu_plane *pdpu;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_vbif_set_ot_params ot_params;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
-
- if (!plane || !plane->dev || !crtc) {
- DPU_ERROR("invalid arguments plane %d crtc %d\n",
- plane != 0, crtc != 0);
- return;
- }
-
- priv = plane->dev->dev_private;
- if (!priv || !priv->kms) {
- DPU_ERROR("invalid KMS reference\n");
- return;
- }
-
- dpu_kms = to_dpu_kms(priv->kms);
- pdpu = to_dpu_plane(plane);
- if (!pdpu->pipe_hw) {
- DPU_ERROR("invalid pipe reference\n");
- return;
- }
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
memset(&ot_params, 0, sizeof(ot_params));
ot_params.xin_id = pdpu->pipe_hw->cap->xin_id;
@@ -506,28 +410,9 @@ static void _dpu_plane_set_ot_limit(struct drm_plane *plane,
*/
static void _dpu_plane_set_qos_remap(struct drm_plane *plane)
{
- struct dpu_plane *pdpu;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_vbif_set_qos_params qos_params;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
-
- if (!plane || !plane->dev) {
- DPU_ERROR("invalid arguments\n");
- return;
- }
-
- priv = plane->dev->dev_private;
- if (!priv || !priv->kms) {
- DPU_ERROR("invalid KMS reference\n");
- return;
- }
-
- dpu_kms = to_dpu_kms(priv->kms);
- pdpu = to_dpu_plane(plane);
- if (!pdpu->pipe_hw) {
- DPU_ERROR("invalid pipe reference\n");
- return;
- }
+ struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
memset(&qos_params, 0, sizeof(qos_params));
qos_params.vbif_idx = VBIF_RT;
@@ -548,27 +433,12 @@ static void _dpu_plane_set_qos_remap(struct drm_plane *plane)
/**
* _dpu_plane_get_aspace: gets the address space
*/
-static int _dpu_plane_get_aspace(
- struct dpu_plane *pdpu,
- struct dpu_plane_state *pstate,
- struct msm_gem_address_space **aspace)
+static inline struct msm_gem_address_space *_dpu_plane_get_aspace(
+ struct dpu_plane *pdpu)
{
- struct dpu_kms *kms;
+ struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
- if (!pdpu || !pstate || !aspace) {
- DPU_ERROR("invalid parameters\n");
- return -EINVAL;
- }
-
- kms = _dpu_plane_get_kms(&pdpu->base);
- if (!kms) {
- DPU_ERROR("invalid kms\n");
- return -EINVAL;
- }
-
- *aspace = kms->base.aspace;
-
- return 0;
+ return kms->base.aspace;
}
static inline void _dpu_plane_set_scanout(struct drm_plane *plane,
@@ -576,29 +446,10 @@ static inline void _dpu_plane_set_scanout(struct drm_plane *plane,
struct dpu_hw_pipe_cfg *pipe_cfg,
struct drm_framebuffer *fb)
{
- struct dpu_plane *pdpu;
- struct msm_gem_address_space *aspace = NULL;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct msm_gem_address_space *aspace = _dpu_plane_get_aspace(pdpu);
int ret;
- if (!plane || !pstate || !pipe_cfg || !fb) {
- DPU_ERROR(
- "invalid arg(s), plane %d state %d cfg %d fb %d\n",
- plane != 0, pstate != 0, pipe_cfg != 0, fb != 0);
- return;
- }
-
- pdpu = to_dpu_plane(plane);
- if (!pdpu->pipe_hw) {
- DPU_ERROR_PLANE(pdpu, "invalid pipe_hw\n");
- return;
- }
-
- ret = _dpu_plane_get_aspace(pdpu, pstate, &aspace);
- if (ret) {
- DPU_ERROR_PLANE(pdpu, "Failed to get aspace %d\n", ret);
- return;
- }
-
ret = dpu_format_populate_layout(aspace, fb, &pipe_cfg->layout);
if (ret == -EAGAIN)
DPU_DEBUG_PLANE(pdpu, "not updating same src addrs\n");
@@ -622,15 +473,6 @@ static void _dpu_plane_setup_scaler3(struct dpu_plane *pdpu,
{
uint32_t i;
- if (!pdpu || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
- !chroma_subsmpl_v) {
- DPU_ERROR(
- "pdpu %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
- !!pdpu, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
- chroma_subsmpl_v);
- return;
- }
-
memset(scale_cfg, 0, sizeof(*scale_cfg));
memset(&pstate->pixel_ext, 0, sizeof(struct dpu_hw_pixel_ext));
@@ -734,17 +576,8 @@ static void _dpu_plane_setup_scaler(struct dpu_plane *pdpu,
struct dpu_plane_state *pstate,
const struct dpu_format *fmt, bool color_fill)
{
- struct dpu_hw_pixel_ext *pe;
uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
- if (!pdpu || !fmt || !pstate) {
- DPU_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
- pdpu != 0, fmt != 0, pstate != 0);
- return;
- }
-
- pe = &pstate->pixel_ext;
-
/* don't chroma subsample if decimating */
chroma_subsmpl_h =
drm_format_horz_chroma_subsampling(fmt->base.pixel_format);
@@ -772,21 +605,8 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
uint32_t color, uint32_t alpha)
{
const struct dpu_format *fmt;
- const struct drm_plane *plane;
- struct dpu_plane_state *pstate;
-
- if (!pdpu || !pdpu->base.state) {
- DPU_ERROR("invalid plane\n");
- return -EINVAL;
- }
-
- if (!pdpu->pipe_hw) {
- DPU_ERROR_PLANE(pdpu, "invalid plane h/w pointer\n");
- return -EINVAL;
- }
-
- plane = &pdpu->base;
- pstate = to_dpu_plane_state(plane->state);
+ const struct drm_plane *plane = &pdpu->base;
+ struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state);
DPU_DEBUG_PLANE(pdpu, "\n");
@@ -837,12 +657,7 @@ static int _dpu_plane_color_fill(struct dpu_plane *pdpu,
void dpu_plane_clear_multirect(const struct drm_plane_state *drm_state)
{
- struct dpu_plane_state *pstate;
-
- if (!drm_state)
- return;
-
- pstate = to_dpu_plane_state(drm_state);
+ struct dpu_plane_state *pstate = to_dpu_plane_state(drm_state);
pstate->multirect_index = DPU_SSPP_RECT_SOLO;
pstate->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
@@ -973,15 +788,6 @@ done:
void dpu_plane_get_ctl_flush(struct drm_plane *plane, struct dpu_hw_ctl *ctl,
u32 *flush_sspp)
{
- struct dpu_plane_state *pstate;
-
- if (!plane || !flush_sspp) {
- DPU_ERROR("invalid parameters\n");
- return;
- }
-
- pstate = to_dpu_plane_state(plane->state);
-
*flush_sspp = ctl->ops.get_bitmask_sspp(ctl, dpu_plane_pipe(plane));
}
@@ -995,7 +801,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
struct drm_gem_object *obj;
struct msm_gem_object *msm_obj;
struct dma_fence *fence;
- struct msm_gem_address_space *aspace;
+ struct msm_gem_address_space *aspace = _dpu_plane_get_aspace(pdpu);
int ret;
if (!new_state->fb)
@@ -1003,12 +809,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane,
DPU_DEBUG_PLANE(pdpu, "FB[%u]\n", fb->base.id);
- ret = _dpu_plane_get_aspace(pdpu, pstate, &aspace);
- if (ret) {
- DPU_ERROR_PLANE(pdpu, "Failed to get aspace\n");
- return ret;
- }
-
/* cache aspace */
pstate->aspace = aspace;
@@ -1078,33 +878,30 @@ static bool dpu_plane_validate_src(struct drm_rect *src,
drm_rect_equals(fb_rect, src);
}
-static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
- struct drm_plane_state *state)
+static int dpu_plane_atomic_check(struct drm_plane *plane,
+ struct drm_plane_state *state)
{
- int ret = 0;
- struct dpu_plane *pdpu;
- struct dpu_plane_state *pstate;
+ int ret = 0, min_scale;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ const struct drm_crtc_state *crtc_state = NULL;
const struct dpu_format *fmt;
struct drm_rect src, dst, fb_rect = { 0 };
- uint32_t max_upscale = 1, max_downscale = 1;
uint32_t min_src_size, max_linewidth;
- int hscale = 1, vscale = 1;
- if (!plane || !state) {
- DPU_ERROR("invalid arg(s), plane %d state %d\n",
- plane != 0, state != 0);
- ret = -EINVAL;
- goto exit;
- }
-
- pdpu = to_dpu_plane(plane);
- pstate = to_dpu_plane_state(state);
+ if (state->crtc)
+ crtc_state = drm_atomic_get_new_crtc_state(state->state,
+ state->crtc);
- if (!pdpu->pipe_sblk) {
- DPU_ERROR_PLANE(pdpu, "invalid catalog\n");
- ret = -EINVAL;
- goto exit;
+ min_scale = FRAC_16_16(1, pdpu->pipe_sblk->maxdwnscale);
+ ret = drm_atomic_helper_check_plane_state(state, crtc_state, min_scale,
+ pdpu->pipe_sblk->maxupscale << 16,
+ true, true);
+ if (ret) {
+ DPU_ERROR_PLANE(pdpu, "Check plane state failed (%d)\n", ret);
+ return ret;
}
+ if (!state->visible)
+ return 0;
src.x1 = state->src_x >> 16;
src.y1 = state->src_y >> 16;
@@ -1118,25 +915,6 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
max_linewidth = pdpu->pipe_sblk->common->maxlinewidth;
- if (pdpu->features & DPU_SSPP_SCALER) {
- max_downscale = pdpu->pipe_sblk->maxdwnscale;
- max_upscale = pdpu->pipe_sblk->maxupscale;
- }
- if (drm_rect_width(&src) < drm_rect_width(&dst))
- hscale = drm_rect_calc_hscale(&src, &dst, 1, max_upscale);
- else
- hscale = drm_rect_calc_hscale(&dst, &src, 1, max_downscale);
- if (drm_rect_height(&src) < drm_rect_height(&dst))
- vscale = drm_rect_calc_vscale(&src, &dst, 1, max_upscale);
- else
- vscale = drm_rect_calc_vscale(&dst, &src, 1, max_downscale);
-
- DPU_DEBUG_PLANE(pdpu, "check %d -> %d\n",
- dpu_plane_enabled(plane->state), dpu_plane_enabled(state));
-
- if (!dpu_plane_enabled(state))
- goto exit;
-
fmt = to_dpu_format(msm_framebuffer_format(state->fb));
min_src_size = DPU_FORMAT_IS_YUV(fmt) ? 2 : 1;
@@ -1147,13 +925,13 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
| BIT(DPU_SSPP_CSC_10BIT))))) {
DPU_ERROR_PLANE(pdpu,
"plane doesn't have scaler/csc for yuv\n");
- ret = -EINVAL;
+ return -EINVAL;
/* check src bounds */
} else if (!dpu_plane_validate_src(&src, &fb_rect, min_src_size)) {
DPU_ERROR_PLANE(pdpu, "invalid source " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&src));
- ret = -E2BIG;
+ return -E2BIG;
/* valid yuv image */
} else if (DPU_FORMAT_IS_YUV(fmt) &&
@@ -1162,41 +940,22 @@ static int dpu_plane_sspp_atomic_check(struct drm_plane *plane,
drm_rect_height(&src) & 0x1)) {
DPU_ERROR_PLANE(pdpu, "invalid yuv source " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&src));
- ret = -EINVAL;
+ return -EINVAL;
/* min dst support */
} else if (drm_rect_width(&dst) < 0x1 || drm_rect_height(&dst) < 0x1) {
DPU_ERROR_PLANE(pdpu, "invalid dest rect " DRM_RECT_FMT "\n",
DRM_RECT_ARG(&dst));
- ret = -EINVAL;
+ return -EINVAL;
/* check decimated source width */
} else if (drm_rect_width(&src) > max_linewidth) {
DPU_ERROR_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n",
DRM_RECT_ARG(&src), max_linewidth);
- ret = -E2BIG;
-
- /* check scaler capability */
- } else if (hscale < 0 || vscale < 0) {
- DPU_ERROR_PLANE(pdpu, "invalid scaling requested src="
- DRM_RECT_FMT " dst=" DRM_RECT_FMT "\n",
- DRM_RECT_ARG(&src), DRM_RECT_ARG(&dst));
- ret = -E2BIG;
+ return -E2BIG;
}
-exit:
- return ret;
-}
-
-static int dpu_plane_atomic_check(struct drm_plane *plane,
- struct drm_plane_state *state)
-{
- if (!state->fb)
- return 0;
-
- DPU_DEBUG_PLANE(to_dpu_plane(plane), "\n");
-
- return dpu_plane_sspp_atomic_check(plane, state);
+ return 0;
}
void dpu_plane_flush(struct drm_plane *plane)
@@ -1245,46 +1004,16 @@ void dpu_plane_set_error(struct drm_plane *plane, bool error)
pdpu->is_error = error;
}
-static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+static void dpu_plane_sspp_atomic_update(struct drm_plane *plane)
{
- uint32_t nplanes, src_flags;
- struct dpu_plane *pdpu;
- struct drm_plane_state *state;
- struct dpu_plane_state *pstate;
- struct dpu_plane_state *old_pstate;
- const struct dpu_format *fmt;
- struct drm_crtc *crtc;
- struct drm_framebuffer *fb;
- struct drm_rect src, dst;
-
- if (!plane) {
- DPU_ERROR("invalid plane\n");
- return -EINVAL;
- } else if (!plane->state) {
- DPU_ERROR("invalid plane state\n");
- return -EINVAL;
- } else if (!old_state) {
- DPU_ERROR("invalid old state\n");
- return -EINVAL;
- }
-
- pdpu = to_dpu_plane(plane);
- state = plane->state;
-
- pstate = to_dpu_plane_state(state);
-
- old_pstate = to_dpu_plane_state(old_state);
-
- crtc = state->crtc;
- fb = state->fb;
- if (!crtc || !fb) {
- DPU_ERROR_PLANE(pdpu, "invalid crtc %d or fb %d\n",
- crtc != 0, fb != 0);
- return -EINVAL;
- }
- fmt = to_dpu_format(msm_framebuffer_format(fb));
- nplanes = fmt->num_planes;
+ uint32_t src_flags;
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct drm_plane_state *state = plane->state;
+ struct dpu_plane_state *pstate = to_dpu_plane_state(state);
+ struct drm_crtc *crtc = state->crtc;
+ struct drm_framebuffer *fb = state->fb;
+ const struct dpu_format *fmt =
+ to_dpu_format(msm_framebuffer_format(fb));
memset(&(pdpu->pipe_cfg), 0, sizeof(struct dpu_hw_pipe_cfg));
@@ -1295,28 +1024,27 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
pdpu->is_rt_pipe = (dpu_crtc_get_client_type(crtc) != NRT_CLIENT);
_dpu_plane_set_qos_ctrl(plane, false, DPU_PLANE_QOS_PANIC_CTRL);
- src.x1 = state->src_x >> 16;
- src.y1 = state->src_y >> 16;
- src.x2 = src.x1 + (state->src_w >> 16);
- src.y2 = src.y1 + (state->src_h >> 16);
+ DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FP_FMT "->crtc%u " DRM_RECT_FMT
+ ", %4.4s ubwc %d\n", fb->base.id, DRM_RECT_FP_ARG(&state->src),
+ crtc->base.id, DRM_RECT_ARG(&state->dst),
+ (char *)&fmt->base.pixel_format, DPU_FORMAT_IS_UBWC(fmt));
- dst = drm_plane_state_dest(state);
+ pdpu->pipe_cfg.src_rect = state->src;
- DPU_DEBUG_PLANE(pdpu, "FB[%u] " DRM_RECT_FMT "->crtc%u " DRM_RECT_FMT
- ", %4.4s ubwc %d\n", fb->base.id, DRM_RECT_ARG(&src),
- crtc->base.id, DRM_RECT_ARG(&dst),
- (char *)&fmt->base.pixel_format,
- DPU_FORMAT_IS_UBWC(fmt));
+ /* state->src is 16.16, src_rect is not */
+ pdpu->pipe_cfg.src_rect.x1 >>= 16;
+ pdpu->pipe_cfg.src_rect.x2 >>= 16;
+ pdpu->pipe_cfg.src_rect.y1 >>= 16;
+ pdpu->pipe_cfg.src_rect.y2 >>= 16;
- pdpu->pipe_cfg.src_rect = src;
- pdpu->pipe_cfg.dst_rect = dst;
+ pdpu->pipe_cfg.dst_rect = state->dst;
_dpu_plane_setup_scaler(pdpu, pstate, fmt, false);
/* override for color fill */
if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
/* skip remaining processing on color fill */
- return 0;
+ return;
}
if (pdpu->pipe_hw->ops.setup_rects) {
@@ -1387,30 +1115,13 @@ static int dpu_plane_sspp_atomic_update(struct drm_plane *plane,
}
_dpu_plane_set_qos_remap(plane);
- return 0;
}
-static void _dpu_plane_atomic_disable(struct drm_plane *plane,
- struct drm_plane_state *old_state)
+static void _dpu_plane_atomic_disable(struct drm_plane *plane)
{
- struct dpu_plane *pdpu;
- struct drm_plane_state *state;
- struct dpu_plane_state *pstate;
-
- if (!plane) {
- DPU_ERROR("invalid plane\n");
- return;
- } else if (!plane->state) {
- DPU_ERROR("invalid plane state\n");
- return;
- } else if (!old_state) {
- DPU_ERROR("invalid old state\n");
- return;
- }
-
- pdpu = to_dpu_plane(plane);
- state = plane->state;
- pstate = to_dpu_plane_state(state);
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct drm_plane_state *state = plane->state;
+ struct dpu_plane_state *pstate = to_dpu_plane_state(state);
trace_dpu_plane_disable(DRMID(plane), is_dpu_plane_virtual(plane),
pstate->multirect_mode);
@@ -1426,31 +1137,17 @@ static void _dpu_plane_atomic_disable(struct drm_plane *plane,
static void dpu_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
- struct dpu_plane *pdpu;
- struct drm_plane_state *state;
-
- if (!plane) {
- DPU_ERROR("invalid plane\n");
- return;
- } else if (!plane->state) {
- DPU_ERROR("invalid plane state\n");
- return;
- }
+ struct dpu_plane *pdpu = to_dpu_plane(plane);
+ struct drm_plane_state *state = plane->state;
- pdpu = to_dpu_plane(plane);
pdpu->is_error = false;
- state = plane->state;
DPU_DEBUG_PLANE(pdpu, "\n");
- if (!dpu_plane_sspp_enabled(state)) {
- _dpu_plane_atomic_disable(plane, old_state);
+ if (!state->visible) {
+ _dpu_plane_atomic_disable(plane);
} else {
- int ret;
-
- ret = dpu_plane_sspp_atomic_update(plane, old_state);
- /* atomic_check should have ensured that this doesn't fail */
- WARN_ON(ret < 0);
+ dpu_plane_sspp_atomic_update(plane);
}
}
@@ -1487,8 +1184,7 @@ static void dpu_plane_destroy(struct drm_plane *plane)
/* this will destroy the states as well */
drm_plane_cleanup(plane);
- if (pdpu->pipe_hw)
- dpu_hw_sspp_destroy(pdpu->pipe_hw);
+ dpu_hw_sspp_destroy(pdpu->pipe_hw);
kfree(pdpu);
}
@@ -1507,9 +1203,7 @@ static void dpu_plane_destroy_state(struct drm_plane *plane,
pstate = to_dpu_plane_state(state);
- /* remove ref count for frame buffers */
- if (state->fb)
- drm_framebuffer_put(state->fb);
+ __drm_atomic_helper_plane_destroy_state(state);
kfree(pstate);
}
@@ -1829,40 +1523,17 @@ bool is_dpu_plane_virtual(struct drm_plane *plane)
/* initialize plane */
struct drm_plane *dpu_plane_init(struct drm_device *dev,
- uint32_t pipe, bool primary_plane,
+ uint32_t pipe, enum drm_plane_type type,
unsigned long possible_crtcs, u32 master_plane_id)
{
struct drm_plane *plane = NULL, *master_plane = NULL;
const struct dpu_format_extended *format_list;
struct dpu_plane *pdpu;
- struct msm_drm_private *priv;
- struct dpu_kms *kms;
- enum drm_plane_type type;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct dpu_kms *kms = to_dpu_kms(priv->kms);
int zpos_max = DPU_ZPOS_MAX;
int ret = -EINVAL;
- if (!dev) {
- DPU_ERROR("[%u]device is NULL\n", pipe);
- goto exit;
- }
-
- priv = dev->dev_private;
- if (!priv) {
- DPU_ERROR("[%u]private data is NULL\n", pipe);
- goto exit;
- }
-
- if (!priv->kms) {
- DPU_ERROR("[%u]invalid KMS reference\n", pipe);
- goto exit;
- }
- kms = to_dpu_kms(priv->kms);
-
- if (!kms->catalog) {
- DPU_ERROR("[%u]invalid catalog reference\n", pipe);
- goto exit;
- }
-
/* create and zero local structure */
pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL);
if (!pdpu) {
@@ -1918,12 +1589,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
goto clean_sspp;
}
- if (pdpu->features & BIT(DPU_SSPP_CURSOR))
- type = DRM_PLANE_TYPE_CURSOR;
- else if (primary_plane)
- type = DRM_PLANE_TYPE_PRIMARY;
- else
- type = DRM_PLANE_TYPE_OVERLAY;
ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs,
pdpu->formats, pdpu->nformats,
NULL, type, NULL);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
index f6fe6ddc7a3a..7fed0b627708 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.h
@@ -122,7 +122,7 @@ void dpu_plane_set_error(struct drm_plane *plane, bool error);
* dpu_plane_init - create new dpu plane for the given pipe
* @dev: Pointer to DRM device
* @pipe: dpu hardware pipe identifier
- * @primary_plane: true if this pipe is primary plane for crtc
+ * @type: Plane type - PRIMARY/OVERLAY/CURSOR
* @possible_crtcs: bitmask of crtc that can be attached to the given pipe
* @master_plane_id: primary plane id of a multirect pipe. 0 value passed for
* a regular plane initialization. A non-zero primary plane
@@ -130,7 +130,7 @@ void dpu_plane_set_error(struct drm_plane *plane, bool error);
*
*/
struct drm_plane *dpu_plane_init(struct drm_device *dev,
- uint32_t pipe, bool primary_plane,
+ uint32_t pipe, enum drm_plane_type type,
unsigned long possible_crtcs, u32 master_plane_id);
/**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c
index a75eebca2f37..fc14116789f2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.c
@@ -145,6 +145,7 @@ int dpu_power_resource_enable(struct dpu_power_handle *phandle,
bool changed = false;
u32 max_usecase_ndx = VOTE_INDEX_DISABLE, prev_usecase_ndx;
struct dpu_power_client *client;
+ u32 event_type;
if (!phandle || !pclient) {
pr_err("invalid input argument\n");
@@ -181,19 +182,9 @@ int dpu_power_resource_enable(struct dpu_power_handle *phandle,
if (!changed)
goto end;
- if (enable) {
- dpu_power_event_trigger_locked(phandle,
- DPU_POWER_EVENT_PRE_ENABLE);
- dpu_power_event_trigger_locked(phandle,
- DPU_POWER_EVENT_POST_ENABLE);
-
- } else {
- dpu_power_event_trigger_locked(phandle,
- DPU_POWER_EVENT_PRE_DISABLE);
- dpu_power_event_trigger_locked(phandle,
- DPU_POWER_EVENT_POST_DISABLE);
- }
+ event_type = enable ? DPU_POWER_EVENT_ENABLE : DPU_POWER_EVENT_DISABLE;
+ dpu_power_event_trigger_locked(phandle, event_type);
end:
mutex_unlock(&phandle->phandle_lock);
return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h
index 344f74464eca..a65b7a297f21 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_power_handle.h
@@ -23,17 +23,9 @@
#include "dpu_io_util.h"
-/* event will be triggered before power handler disable */
-#define DPU_POWER_EVENT_PRE_DISABLE 0x1
-
-/* event will be triggered after power handler disable */
-#define DPU_POWER_EVENT_POST_DISABLE 0x2
-
-/* event will be triggered before power handler enable */
-#define DPU_POWER_EVENT_PRE_ENABLE 0x4
-
-/* event will be triggered after power handler enable */
-#define DPU_POWER_EVENT_POST_ENABLE 0x8
+/* events will be triggered on power handler enable/disable */
+#define DPU_POWER_EVENT_DISABLE BIT(0)
+#define DPU_POWER_EVENT_ENABLE BIT(1)
/**
* mdss_bus_vote_type: register bus vote type
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 13c0a36d4ef9..bdb117709674 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -16,7 +16,6 @@
#include "dpu_kms.h"
#include "dpu_hw_lm.h"
#include "dpu_hw_ctl.h"
-#include "dpu_hw_cdm.h"
#include "dpu_hw_pingpong.h"
#include "dpu_hw_intf.h"
#include "dpu_encoder.h"
@@ -25,38 +24,13 @@
#define RESERVED_BY_OTHER(h, r) \
((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id))
-#define RM_RQ_LOCK(r) ((r)->top_ctrl & BIT(DPU_RM_TOPCTL_RESERVE_LOCK))
-#define RM_RQ_CLEAR(r) ((r)->top_ctrl & BIT(DPU_RM_TOPCTL_RESERVE_CLEAR))
-#define RM_RQ_DS(r) ((r)->top_ctrl & BIT(DPU_RM_TOPCTL_DS))
-#define RM_IS_TOPOLOGY_MATCH(t, r) ((t).num_lm == (r).num_lm && \
- (t).num_comp_enc == (r).num_enc && \
- (t).num_intf == (r).num_intf)
-
-struct dpu_rm_topology_def {
- enum dpu_rm_topology_name top_name;
- int num_lm;
- int num_comp_enc;
- int num_intf;
- int num_ctl;
- int needs_split_display;
-};
-
-static const struct dpu_rm_topology_def g_top_table[] = {
- { DPU_RM_TOPOLOGY_NONE, 0, 0, 0, 0, false },
- { DPU_RM_TOPOLOGY_SINGLEPIPE, 1, 0, 1, 1, false },
- { DPU_RM_TOPOLOGY_DUALPIPE, 2, 0, 2, 2, true },
- { DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE, 2, 0, 1, 1, false },
-};
-
/**
* struct dpu_rm_requirements - Reservation requirements parameter bundle
- * @top_ctrl: topology control preference from kernel client
- * @top: selected topology for the display
+ * @topology: selected topology for the display
* @hw_res: Hardware resources required as reported by the encoders
*/
struct dpu_rm_requirements {
- uint64_t top_ctrl;
- const struct dpu_rm_topology_def *topology;
+ struct msm_display_topology topology;
struct dpu_encoder_hw_resources hw_res;
};
@@ -72,13 +46,11 @@ struct dpu_rm_requirements {
* @enc_id: Reservations are tracked by Encoder DRM object ID.
* CRTCs may be connected to multiple Encoders.
* An encoder or connector id identifies the display path.
- * @topology DRM<->HW topology use case
*/
struct dpu_rm_rsvp {
struct list_head list;
uint32_t seq;
uint32_t enc_id;
- enum dpu_rm_topology_name topology;
};
/**
@@ -122,8 +94,8 @@ static void _dpu_rm_print_rsvps(
DPU_DEBUG("%d\n", stage);
list_for_each_entry(rsvp, &rm->rsvps, list) {
- DRM_DEBUG_KMS("%d rsvp[s%ue%u] topology %d\n", stage, rsvp->seq,
- rsvp->enc_id, rsvp->topology);
+ DRM_DEBUG_KMS("%d rsvp[s%ue%u]\n", stage, rsvp->seq,
+ rsvp->enc_id);
}
for (type = 0; type < DPU_HW_BLK_MAX; type++) {
@@ -146,18 +118,6 @@ struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm)
return rm->hw_mdp;
}
-enum dpu_rm_topology_name
-dpu_rm_get_topology_name(struct msm_display_topology topology)
-{
- int i;
-
- for (i = 0; i < DPU_RM_TOPOLOGY_MAX; i++)
- if (RM_IS_TOPOLOGY_MATCH(g_top_table[i], topology))
- return g_top_table[i].top_name;
-
- return DPU_RM_TOPOLOGY_NONE;
-}
-
void dpu_rm_init_hw_iter(
struct dpu_rm_hw_iter *iter,
uint32_t enc_id,
@@ -229,9 +189,6 @@ static void _dpu_rm_hw_destroy(enum dpu_hw_blk_type type, void *hw)
case DPU_HW_BLK_CTL:
dpu_hw_ctl_destroy(hw);
break;
- case DPU_HW_BLK_CDM:
- dpu_hw_cdm_destroy(hw);
- break;
case DPU_HW_BLK_PINGPONG:
dpu_hw_pingpong_destroy(hw);
break;
@@ -305,9 +262,6 @@ static int _dpu_rm_hw_blk_create(
case DPU_HW_BLK_CTL:
hw = dpu_hw_ctl_init(id, mmio, cat);
break;
- case DPU_HW_BLK_CDM:
- hw = dpu_hw_cdm_init(id, mmio, cat, hw_mdp);
- break;
case DPU_HW_BLK_PINGPONG:
hw = dpu_hw_pingpong_init(id, mmio, cat);
break;
@@ -438,15 +392,6 @@ int dpu_rm_init(struct dpu_rm *rm,
}
}
- for (i = 0; i < cat->cdm_count; i++) {
- rc = _dpu_rm_hw_blk_create(rm, cat, mmio, DPU_HW_BLK_CDM,
- cat->cdm[i].id, &cat->cdm[i]);
- if (rc) {
- DPU_ERROR("failed: cdm hw not available\n");
- goto fail;
- }
- }
-
return 0;
fail:
@@ -455,6 +400,11 @@ fail:
return rc;
}
+static bool _dpu_rm_needs_split_display(const struct msm_display_topology *top)
+{
+ return top->num_intf > 1;
+}
+
/**
* _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
* proposed use case requirements, incl. hardwired dependent blocks like
@@ -538,14 +488,14 @@ static int _dpu_rm_reserve_lms(
int lm_count = 0;
int i, rc = 0;
- if (!reqs->topology->num_lm) {
- DPU_ERROR("invalid number of lm: %d\n", reqs->topology->num_lm);
+ if (!reqs->topology.num_lm) {
+ DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
return -EINVAL;
}
/* Find a primary mixer */
dpu_rm_init_hw_iter(&iter_i, 0, DPU_HW_BLK_LM);
- while (lm_count != reqs->topology->num_lm &&
+ while (lm_count != reqs->topology.num_lm &&
_dpu_rm_get_hw_locked(rm, &iter_i)) {
memset(&lm, 0, sizeof(lm));
memset(&pp, 0, sizeof(pp));
@@ -563,7 +513,7 @@ static int _dpu_rm_reserve_lms(
/* Valid primary mixer found, find matching peers */
dpu_rm_init_hw_iter(&iter_j, 0, DPU_HW_BLK_LM);
- while (lm_count != reqs->topology->num_lm &&
+ while (lm_count != reqs->topology.num_lm &&
_dpu_rm_get_hw_locked(rm, &iter_j)) {
if (iter_i.blk == iter_j.blk)
continue;
@@ -578,7 +528,7 @@ static int _dpu_rm_reserve_lms(
}
}
- if (lm_count != reqs->topology->num_lm) {
+ if (lm_count != reqs->topology.num_lm) {
DPU_DEBUG("unable to find appropriate mixers\n");
return -ENAVAIL;
}
@@ -600,14 +550,20 @@ static int _dpu_rm_reserve_lms(
static int _dpu_rm_reserve_ctls(
struct dpu_rm *rm,
struct dpu_rm_rsvp *rsvp,
- const struct dpu_rm_topology_def *top)
+ const struct msm_display_topology *top)
{
struct dpu_rm_hw_blk *ctls[MAX_BLOCKS];
struct dpu_rm_hw_iter iter;
- int i = 0;
+ int i = 0, num_ctls = 0;
+ bool needs_split_display = false;
memset(&ctls, 0, sizeof(ctls));
+ /* each hw_intf needs its own hw_ctrl to program its control path */
+ num_ctls = top->num_intf;
+
+ needs_split_display = _dpu_rm_needs_split_display(top);
+
dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_CTL);
while (_dpu_rm_get_hw_locked(rm, &iter)) {
const struct dpu_hw_ctl *ctl = to_dpu_hw_ctl(iter.blk->hw);
@@ -621,20 +577,20 @@ static int _dpu_rm_reserve_ctls(
DPU_DEBUG("ctl %d caps 0x%lX\n", iter.blk->id, features);
- if (top->needs_split_display != has_split_display)
+ if (needs_split_display != has_split_display)
continue;
ctls[i] = iter.blk;
DPU_DEBUG("ctl %d match\n", iter.blk->id);
- if (++i == top->num_ctl)
+ if (++i == num_ctls)
break;
}
- if (i != top->num_ctl)
+ if (i != num_ctls)
return -ENAVAIL;
- for (i = 0; i < ARRAY_SIZE(ctls) && i < top->num_ctl; i++) {
+ for (i = 0; i < ARRAY_SIZE(ctls) && i < num_ctls; i++) {
ctls[i]->rsvp_nxt = rsvp;
trace_dpu_rm_reserve_ctls(ctls[i]->id, ctls[i]->type,
rsvp->enc_id);
@@ -643,55 +599,11 @@ static int _dpu_rm_reserve_ctls(
return 0;
}
-static int _dpu_rm_reserve_cdm(
- struct dpu_rm *rm,
- struct dpu_rm_rsvp *rsvp,
- uint32_t id,
- enum dpu_hw_blk_type type)
-{
- struct dpu_rm_hw_iter iter;
-
- DRM_DEBUG_KMS("type %d id %d\n", type, id);
-
- dpu_rm_init_hw_iter(&iter, 0, DPU_HW_BLK_CDM);
- while (_dpu_rm_get_hw_locked(rm, &iter)) {
- const struct dpu_hw_cdm *cdm = to_dpu_hw_cdm(iter.blk->hw);
- const struct dpu_cdm_cfg *caps = cdm->caps;
- bool match = false;
-
- if (RESERVED_BY_OTHER(iter.blk, rsvp))
- continue;
-
- if (type == DPU_HW_BLK_INTF && id != INTF_MAX)
- match = test_bit(id, &caps->intf_connect);
-
- DRM_DEBUG_KMS("iter: type:%d id:%d enc:%d cdm:%lu match:%d\n",
- iter.blk->type, iter.blk->id, rsvp->enc_id,
- caps->intf_connect, match);
-
- if (!match)
- continue;
-
- trace_dpu_rm_reserve_cdm(iter.blk->id, iter.blk->type,
- rsvp->enc_id);
- iter.blk->rsvp_nxt = rsvp;
- break;
- }
-
- if (!iter.hw) {
- DPU_ERROR("couldn't reserve cdm for type %d id %d\n", type, id);
- return -ENAVAIL;
- }
-
- return 0;
-}
-
static int _dpu_rm_reserve_intf(
struct dpu_rm *rm,
struct dpu_rm_rsvp *rsvp,
uint32_t id,
- enum dpu_hw_blk_type type,
- bool needs_cdm)
+ enum dpu_hw_blk_type type)
{
struct dpu_rm_hw_iter iter;
int ret = 0;
@@ -719,9 +631,6 @@ static int _dpu_rm_reserve_intf(
return -EINVAL;
}
- if (needs_cdm)
- ret = _dpu_rm_reserve_cdm(rm, rsvp, id, type);
-
return ret;
}
@@ -738,7 +647,7 @@ static int _dpu_rm_reserve_intf_related_hw(
continue;
id = i + INTF_0;
ret = _dpu_rm_reserve_intf(rm, rsvp, id,
- DPU_HW_BLK_INTF, hw_res->needs_cdm);
+ DPU_HW_BLK_INTF);
if (ret)
return ret;
}
@@ -750,17 +659,14 @@ static int _dpu_rm_make_next_rsvp(
struct dpu_rm *rm,
struct drm_encoder *enc,
struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state,
struct dpu_rm_rsvp *rsvp,
struct dpu_rm_requirements *reqs)
{
int ret;
- struct dpu_rm_topology_def topology;
/* Create reservation info, tag reserved blocks with it as we go */
rsvp->seq = ++rm->rsvp_next_seq;
rsvp->enc_id = enc->base.id;
- rsvp->topology = reqs->topology->top_name;
list_add_tail(&rsvp->list, &rm->rsvps);
ret = _dpu_rm_reserve_lms(rm, rsvp, reqs);
@@ -769,23 +675,12 @@ static int _dpu_rm_make_next_rsvp(
return ret;
}
- /*
- * Do assignment preferring to give away low-resource CTLs first:
- * - Check mixers without Split Display
- * - Only then allow to grab from CTLs with split display capability
- */
- _dpu_rm_reserve_ctls(rm, rsvp, reqs->topology);
- if (ret && !reqs->topology->needs_split_display) {
- memcpy(&topology, reqs->topology, sizeof(topology));
- topology.needs_split_display = true;
- _dpu_rm_reserve_ctls(rm, rsvp, &topology);
- }
+ ret = _dpu_rm_reserve_ctls(rm, rsvp, &reqs->topology);
if (ret) {
DPU_ERROR("unable to find appropriate CTL\n");
return ret;
}
- /* Assign INTFs and blks whose usage is tied to them: CTL & CDM */
ret = _dpu_rm_reserve_intf_related_hw(rm, rsvp, &reqs->hw_res);
if (ret)
return ret;
@@ -797,44 +692,16 @@ static int _dpu_rm_populate_requirements(
struct dpu_rm *rm,
struct drm_encoder *enc,
struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state,
struct dpu_rm_requirements *reqs,
struct msm_display_topology req_topology)
{
- int i;
+ dpu_encoder_get_hw_resources(enc, &reqs->hw_res);
- memset(reqs, 0, sizeof(*reqs));
+ reqs->topology = req_topology;
- dpu_encoder_get_hw_resources(enc, &reqs->hw_res, conn_state);
-
- for (i = 0; i < DPU_RM_TOPOLOGY_MAX; i++) {
- if (RM_IS_TOPOLOGY_MATCH(g_top_table[i],
- req_topology)) {
- reqs->topology = &g_top_table[i];
- break;
- }
- }
-
- if (!reqs->topology) {
- DPU_ERROR("invalid topology for the display\n");
- return -EINVAL;
- }
-
- /**
- * Set the requirement based on caps if not set from user space
- * This will ensure to select LM tied with DS blocks
- * Currently, DS blocks are tied with LM 0 and LM 1 (primary display)
- */
- if (!RM_RQ_DS(reqs) && rm->hw_mdp->caps->has_dest_scaler &&
- conn_state->connector->connector_type == DRM_MODE_CONNECTOR_DSI)
- reqs->top_ctrl |= BIT(DPU_RM_TOPCTL_DS);
-
- DRM_DEBUG_KMS("top_ctrl: 0x%llX num_h_tiles: %d\n", reqs->top_ctrl,
- reqs->hw_res.display_num_of_h_tiles);
- DRM_DEBUG_KMS("num_lm: %d num_ctl: %d topology: %d split_display: %d\n",
- reqs->topology->num_lm, reqs->topology->num_ctl,
- reqs->topology->top_name,
- reqs->topology->needs_split_display);
+ DRM_DEBUG_KMS("num_lm: %d num_enc: %d num_intf: %d\n",
+ reqs->topology.num_lm, reqs->topology.num_enc,
+ reqs->topology.num_intf);
return 0;
}
@@ -860,29 +727,12 @@ static struct dpu_rm_rsvp *_dpu_rm_get_rsvp(
return NULL;
}
-static struct drm_connector *_dpu_rm_get_connector(
- struct drm_encoder *enc)
-{
- struct drm_connector *conn = NULL;
- struct list_head *connector_list =
- &enc->dev->mode_config.connector_list;
-
- list_for_each_entry(conn, connector_list, head)
- if (conn->encoder == enc)
- return conn;
-
- return NULL;
-}
-
/**
* _dpu_rm_release_rsvp - release resources and release a reservation
* @rm: KMS handle
* @rsvp: RSVP pointer to release and release resources for
*/
-static void _dpu_rm_release_rsvp(
- struct dpu_rm *rm,
- struct dpu_rm_rsvp *rsvp,
- struct drm_connector *conn)
+static void _dpu_rm_release_rsvp(struct dpu_rm *rm, struct dpu_rm_rsvp *rsvp)
{
struct dpu_rm_rsvp *rsvp_c, *rsvp_n;
struct dpu_rm_hw_blk *blk;
@@ -923,7 +773,6 @@ static void _dpu_rm_release_rsvp(
void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc)
{
struct dpu_rm_rsvp *rsvp;
- struct drm_connector *conn;
if (!rm || !enc) {
DPU_ERROR("invalid params\n");
@@ -938,25 +787,15 @@ void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc)
goto end;
}
- conn = _dpu_rm_get_connector(enc);
- if (!conn) {
- DPU_ERROR("failed to get connector for enc %d\n", enc->base.id);
- goto end;
- }
-
- _dpu_rm_release_rsvp(rm, rsvp, conn);
+ _dpu_rm_release_rsvp(rm, rsvp);
end:
mutex_unlock(&rm->rm_lock);
}
-static int _dpu_rm_commit_rsvp(
- struct dpu_rm *rm,
- struct dpu_rm_rsvp *rsvp,
- struct drm_connector_state *conn_state)
+static void _dpu_rm_commit_rsvp(struct dpu_rm *rm, struct dpu_rm_rsvp *rsvp)
{
struct dpu_rm_hw_blk *blk;
enum dpu_hw_blk_type type;
- int ret = 0;
/* Swap next rsvp to be the active */
for (type = 0; type < DPU_HW_BLK_MAX; type++) {
@@ -967,19 +806,12 @@ static int _dpu_rm_commit_rsvp(
}
}
}
-
- if (!ret)
- DRM_DEBUG_KMS("rsrv enc %d topology %d\n", rsvp->enc_id,
- rsvp->topology);
-
- return ret;
}
int dpu_rm_reserve(
struct dpu_rm *rm,
struct drm_encoder *enc,
struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state,
struct msm_display_topology topology,
bool test_only)
{
@@ -987,25 +819,19 @@ int dpu_rm_reserve(
struct dpu_rm_requirements reqs;
int ret;
- if (!rm || !enc || !crtc_state || !conn_state) {
- DPU_ERROR("invalid arguments\n");
- return -EINVAL;
- }
-
/* Check if this is just a page-flip */
if (!drm_atomic_crtc_needs_modeset(crtc_state))
return 0;
- DRM_DEBUG_KMS("reserving hw for conn %d enc %d crtc %d test_only %d\n",
- conn_state->connector->base.id, enc->base.id,
- crtc_state->crtc->base.id, test_only);
+ DRM_DEBUG_KMS("reserving hw for enc %d crtc %d test_only %d\n",
+ enc->base.id, crtc_state->crtc->base.id, test_only);
mutex_lock(&rm->rm_lock);
_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_BEGIN);
- ret = _dpu_rm_populate_requirements(rm, enc, crtc_state,
- conn_state, &reqs, topology);
+ ret = _dpu_rm_populate_requirements(rm, enc, crtc_state, &reqs,
+ topology);
if (ret) {
DPU_ERROR("failed to populate hw requirements\n");
goto end;
@@ -1030,28 +856,15 @@ int dpu_rm_reserve(
rsvp_cur = _dpu_rm_get_rsvp(rm, enc);
- /*
- * User can request that we clear out any reservation during the
- * atomic_check phase by using this CLEAR bit
- */
- if (rsvp_cur && test_only && RM_RQ_CLEAR(&reqs)) {
- DPU_DEBUG("test_only & CLEAR: clear rsvp[s%de%d]\n",
- rsvp_cur->seq, rsvp_cur->enc_id);
- _dpu_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
- rsvp_cur = NULL;
- _dpu_rm_print_rsvps(rm, DPU_RM_STAGE_AFTER_CLEAR);
- }
-
/* Check the proposed reservation, store it in hw's "next" field */
- ret = _dpu_rm_make_next_rsvp(rm, enc, crtc_state, conn_state,
- rsvp_nxt, &reqs);
+ ret = _dpu_rm_make_next_rsvp(rm, enc, crtc_state, rsvp_nxt, &reqs);
_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_AFTER_RSVPNEXT);
if (ret) {
DPU_ERROR("failed to reserve hw resources: %d\n", ret);
- _dpu_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
- } else if (test_only && !RM_RQ_LOCK(&reqs)) {
+ _dpu_rm_release_rsvp(rm, rsvp_nxt);
+ } else if (test_only) {
/*
* Normally, if test_only, test the reservation and then undo
* However, if the user requests LOCK, then keep the reservation
@@ -1059,15 +872,11 @@ int dpu_rm_reserve(
*/
DPU_DEBUG("test_only: discard test rsvp[s%de%d]\n",
rsvp_nxt->seq, rsvp_nxt->enc_id);
- _dpu_rm_release_rsvp(rm, rsvp_nxt, conn_state->connector);
+ _dpu_rm_release_rsvp(rm, rsvp_nxt);
} else {
- if (test_only && RM_RQ_LOCK(&reqs))
- DPU_DEBUG("test_only & LOCK: lock rsvp[s%de%d]\n",
- rsvp_nxt->seq, rsvp_nxt->enc_id);
-
- _dpu_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
+ _dpu_rm_release_rsvp(rm, rsvp_cur);
- ret = _dpu_rm_commit_rsvp(rm, rsvp_nxt, conn_state);
+ _dpu_rm_commit_rsvp(rm, rsvp_nxt);
}
_dpu_rm_print_rsvps(rm, DPU_RM_STAGE_FINAL);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index ffd1841a6067..b8273bd23801 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -21,39 +21,6 @@
#include "dpu_hw_top.h"
/**
- * enum dpu_rm_topology_name - HW resource use case in use by connector
- * @DPU_RM_TOPOLOGY_NONE: No topology in use currently
- * @DPU_RM_TOPOLOGY_SINGLEPIPE: 1 LM, 1 PP, 1 INTF/WB
- * @DPU_RM_TOPOLOGY_DUALPIPE: 2 LM, 2 PP, 2 INTF/WB
- * @DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE: 2 LM, 2 PP, 3DMux, 1 INTF/WB
- */
-enum dpu_rm_topology_name {
- DPU_RM_TOPOLOGY_NONE = 0,
- DPU_RM_TOPOLOGY_SINGLEPIPE,
- DPU_RM_TOPOLOGY_DUALPIPE,
- DPU_RM_TOPOLOGY_DUALPIPE_3DMERGE,
- DPU_RM_TOPOLOGY_MAX,
-};
-
-/**
- * enum dpu_rm_topology_control - HW resource use case in use by connector
- * @DPU_RM_TOPCTL_RESERVE_LOCK: If set, in AtomicTest phase, after a successful
- * test, reserve the resources for this display.
- * Normal behavior would not impact the reservation
- * list during the AtomicTest phase.
- * @DPU_RM_TOPCTL_RESERVE_CLEAR: If set, in AtomicTest phase, before testing,
- * release any reservation held by this display.
- * Normal behavior would not impact the
- * reservation list during the AtomicTest phase.
- * @DPU_RM_TOPCTL_DS : Require layer mixers with DS capabilities
- */
-enum dpu_rm_topology_control {
- DPU_RM_TOPCTL_RESERVE_LOCK,
- DPU_RM_TOPCTL_RESERVE_CLEAR,
- DPU_RM_TOPCTL_DS,
-};
-
-/**
* struct dpu_rm - DPU dynamic hardware resource manager
* @dev: device handle for event logging purposes
* @rsvps: list of hardware reservations by each crtc->encoder->connector
@@ -125,7 +92,6 @@ int dpu_rm_destroy(struct dpu_rm *rm);
* @rm: DPU Resource Manager handle
* @drm_enc: DRM Encoder handle
* @crtc_state: Proposed Atomic DRM CRTC State handle
- * @conn_state: Proposed Atomic DRM Connector State handle
* @topology: Pointer to topology info for the display
* @test_only: Atomic-Test phase, discard results (unless property overrides)
* @Return: 0 on Success otherwise -ERROR
@@ -133,7 +99,6 @@ int dpu_rm_destroy(struct dpu_rm *rm);
int dpu_rm_reserve(struct dpu_rm *rm,
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state,
struct msm_display_topology topology,
bool test_only);
@@ -187,13 +152,4 @@ bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *iter);
*/
int dpu_rm_check_property_topctl(uint64_t val);
-/**
- * dpu_rm_get_topology_name - returns the name of the the given topology
- * definition
- * @topology: topology definition
- * @Return: name of the topology
- */
-enum dpu_rm_topology_name
-dpu_rm_get_topology_name(struct msm_display_topology topology);
-
#endif /* __DPU_RM_H__ */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index ae0ca5076238..e12c4cefb742 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -468,14 +468,16 @@ TRACE_EVENT(dpu_enc_frame_done_cb,
TRACE_EVENT(dpu_enc_trigger_flush,
TP_PROTO(uint32_t drm_id, enum dpu_intf intf_idx,
- int pending_kickoff_cnt, int ctl_idx, u32 pending_flush_ret),
+ int pending_kickoff_cnt, int ctl_idx, u32 extra_flush_bits,
+ u32 pending_flush_ret),
TP_ARGS(drm_id, intf_idx, pending_kickoff_cnt, ctl_idx,
- pending_flush_ret),
+ extra_flush_bits, pending_flush_ret),
TP_STRUCT__entry(
__field( uint32_t, drm_id )
__field( enum dpu_intf, intf_idx )
__field( int, pending_kickoff_cnt )
__field( int, ctl_idx )
+ __field( u32, extra_flush_bits )
__field( u32, pending_flush_ret )
),
TP_fast_assign(
@@ -483,12 +485,14 @@ TRACE_EVENT(dpu_enc_trigger_flush,
__entry->intf_idx = intf_idx;
__entry->pending_kickoff_cnt = pending_kickoff_cnt;
__entry->ctl_idx = ctl_idx;
+ __entry->extra_flush_bits = extra_flush_bits;
__entry->pending_flush_ret = pending_flush_ret;
),
TP_printk("id=%u, intf_idx=%d, pending_kickoff_cnt=%d ctl_idx=%d "
- "pending_flush_ret=%u", __entry->drm_id,
- __entry->intf_idx, __entry->pending_kickoff_cnt,
- __entry->ctl_idx, __entry->pending_flush_ret)
+ "extra_flush_bits=0x%x pending_flush_ret=0x%x",
+ __entry->drm_id, __entry->intf_idx,
+ __entry->pending_kickoff_cnt, __entry->ctl_idx,
+ __entry->extra_flush_bits, __entry->pending_flush_ret)
);
DECLARE_EVENT_CLASS(dpu_enc_ktime_template,
@@ -682,37 +686,41 @@ TRACE_EVENT(dpu_crtc_setup_mixer,
TP_STRUCT__entry(
__field( uint32_t, crtc_id )
__field( uint32_t, plane_id )
- __field( struct drm_plane_state*,state )
- __field( struct dpu_plane_state*,pstate )
+ __field( uint32_t, fb_id )
+ __field_struct( struct drm_rect, src_rect )
+ __field_struct( struct drm_rect, dst_rect )
__field( uint32_t, stage_idx )
+ __field( enum dpu_stage, stage )
__field( enum dpu_sspp, sspp )
+ __field( uint32_t, multirect_idx )
+ __field( uint32_t, multirect_mode )
__field( uint32_t, pixel_format )
__field( uint64_t, modifier )
),
TP_fast_assign(
__entry->crtc_id = crtc_id;
__entry->plane_id = plane_id;
- __entry->state = state;
- __entry->pstate = pstate;
+ __entry->fb_id = state ? state->fb->base.id : 0;
+ __entry->src_rect = drm_plane_state_src(state);
+ __entry->dst_rect = drm_plane_state_dest(state);
__entry->stage_idx = stage_idx;
+ __entry->stage = pstate->stage;
__entry->sspp = sspp;
+ __entry->multirect_idx = pstate->multirect_index;
+ __entry->multirect_mode = pstate->multirect_mode;
__entry->pixel_format = pixel_format;
__entry->modifier = modifier;
),
- TP_printk("crtc_id:%u plane_id:%u fb_id:%u src:{%ux%u+%ux%u} "
- "dst:{%ux%u+%ux%u} stage_idx:%u stage:%d, sspp:%d "
+ TP_printk("crtc_id:%u plane_id:%u fb_id:%u src:" DRM_RECT_FP_FMT
+ " dst:" DRM_RECT_FMT " stage_idx:%u stage:%d, sspp:%d "
"multirect_index:%d multirect_mode:%u pix_format:%u "
"modifier:%llu",
- __entry->crtc_id, __entry->plane_id,
- __entry->state->fb ? __entry->state->fb->base.id : -1,
- __entry->state->src_w >> 16, __entry->state->src_h >> 16,
- __entry->state->src_x >> 16, __entry->state->src_y >> 16,
- __entry->state->crtc_w, __entry->state->crtc_h,
- __entry->state->crtc_x, __entry->state->crtc_y,
- __entry->stage_idx, __entry->pstate->stage, __entry->sspp,
- __entry->pstate->multirect_index,
- __entry->pstate->multirect_mode, __entry->pixel_format,
- __entry->modifier)
+ __entry->crtc_id, __entry->plane_id, __entry->fb_id,
+ DRM_RECT_FP_ARG(&__entry->src_rect),
+ DRM_RECT_ARG(&__entry->dst_rect),
+ __entry->stage_idx, __entry->stage, __entry->sspp,
+ __entry->multirect_idx, __entry->multirect_mode,
+ __entry->pixel_format, __entry->modifier)
);
TRACE_EVENT(dpu_crtc_setup_lm_bounds,
@@ -721,15 +729,15 @@ TRACE_EVENT(dpu_crtc_setup_lm_bounds,
TP_STRUCT__entry(
__field( uint32_t, drm_id )
__field( int, mixer )
- __field( struct drm_rect *, bounds )
+ __field_struct( struct drm_rect, bounds )
),
TP_fast_assign(
__entry->drm_id = drm_id;
__entry->mixer = mixer;
- __entry->bounds = bounds;
+ __entry->bounds = *bounds;
),
TP_printk("id:%u mixer:%d bounds:" DRM_RECT_FMT, __entry->drm_id,
- __entry->mixer, DRM_RECT_ARG(__entry->bounds))
+ __entry->mixer, DRM_RECT_ARG(&__entry->bounds))
);
TRACE_EVENT(dpu_crtc_vblank_enable,
@@ -740,21 +748,25 @@ TRACE_EVENT(dpu_crtc_vblank_enable,
__field( uint32_t, drm_id )
__field( uint32_t, enc_id )
__field( bool, enable )
- __field( struct dpu_crtc *, crtc )
+ __field( bool, enabled )
+ __field( bool, suspend )
+ __field( bool, vblank_requested )
),
TP_fast_assign(
__entry->drm_id = drm_id;
__entry->enc_id = enc_id;
__entry->enable = enable;
- __entry->crtc = crtc;
+ __entry->enabled = crtc->enabled;
+ __entry->suspend = crtc->suspend;
+ __entry->vblank_requested = crtc->vblank_requested;
),
TP_printk("id:%u encoder:%u enable:%s state{enabled:%s suspend:%s "
"vblank_req:%s}",
__entry->drm_id, __entry->enc_id,
__entry->enable ? "true" : "false",
- __entry->crtc->enabled ? "true" : "false",
- __entry->crtc->suspend ? "true" : "false",
- __entry->crtc->vblank_requested ? "true" : "false")
+ __entry->enabled ? "true" : "false",
+ __entry->suspend ? "true" : "false",
+ __entry->vblank_requested ? "true" : "false")
);
DECLARE_EVENT_CLASS(dpu_crtc_enable_template,
@@ -763,18 +775,22 @@ DECLARE_EVENT_CLASS(dpu_crtc_enable_template,
TP_STRUCT__entry(
__field( uint32_t, drm_id )
__field( bool, enable )
- __field( struct dpu_crtc *, crtc )
+ __field( bool, enabled )
+ __field( bool, suspend )
+ __field( bool, vblank_requested )
),
TP_fast_assign(
__entry->drm_id = drm_id;
__entry->enable = enable;
- __entry->crtc = crtc;
+ __entry->enabled = crtc->enabled;
+ __entry->suspend = crtc->suspend;
+ __entry->vblank_requested = crtc->vblank_requested;
),
TP_printk("id:%u enable:%s state{enabled:%s suspend:%s vblank_req:%s}",
__entry->drm_id, __entry->enable ? "true" : "false",
- __entry->crtc->enabled ? "true" : "false",
- __entry->crtc->suspend ? "true" : "false",
- __entry->crtc->vblank_requested ? "true" : "false")
+ __entry->enabled ? "true" : "false",
+ __entry->suspend ? "true" : "false",
+ __entry->vblank_requested ? "true" : "false")
);
DEFINE_EVENT(dpu_crtc_enable_template, dpu_crtc_set_suspend,
TP_PROTO(uint32_t drm_id, bool enable, struct dpu_crtc *crtc),
@@ -814,24 +830,24 @@ TRACE_EVENT(dpu_plane_set_scanout,
TP_ARGS(index, layout, multirect_index),
TP_STRUCT__entry(
__field( enum dpu_sspp, index )
- __field( struct dpu_hw_fmt_layout*, layout )
+ __field_struct( struct dpu_hw_fmt_layout, layout )
__field( enum dpu_sspp_multirect_index, multirect_index)
),
TP_fast_assign(
__entry->index = index;
- __entry->layout = layout;
+ __entry->layout = *layout;
__entry->multirect_index = multirect_index;
),
TP_printk("index:%d layout:{%ux%u @ [%u/%u, %u/%u, %u/%u, %u/%u]} "
- "multirect_index:%d", __entry->index, __entry->layout->width,
- __entry->layout->height, __entry->layout->plane_addr[0],
- __entry->layout->plane_size[0],
- __entry->layout->plane_addr[1],
- __entry->layout->plane_size[1],
- __entry->layout->plane_addr[2],
- __entry->layout->plane_size[2],
- __entry->layout->plane_addr[3],
- __entry->layout->plane_size[3], __entry->multirect_index)
+ "multirect_index:%d", __entry->index, __entry->layout.width,
+ __entry->layout.height, __entry->layout.plane_addr[0],
+ __entry->layout.plane_size[0],
+ __entry->layout.plane_addr[1],
+ __entry->layout.plane_size[1],
+ __entry->layout.plane_addr[2],
+ __entry->layout.plane_size[2],
+ __entry->layout.plane_addr[3],
+ __entry->layout.plane_size[3], __entry->multirect_index)
);
TRACE_EVENT(dpu_plane_disable,
@@ -868,10 +884,6 @@ DECLARE_EVENT_CLASS(dpu_rm_iter_template,
TP_printk("id:%d type:%d enc_id:%u", __entry->id, __entry->type,
__entry->enc_id)
);
-DEFINE_EVENT(dpu_rm_iter_template, dpu_rm_reserve_cdm,
- TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id),
- TP_ARGS(id, type, enc_id)
-);
DEFINE_EVENT(dpu_rm_iter_template, dpu_rm_reserve_intf,
TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id),
TP_ARGS(id, type, enc_id)
@@ -979,16 +991,16 @@ TRACE_EVENT(dpu_core_perf_update_clk,
TP_PROTO(struct drm_device *dev, bool stop_req, u64 clk_rate),
TP_ARGS(dev, stop_req, clk_rate),
TP_STRUCT__entry(
- __field( struct drm_device *, dev )
+ __string( dev_name, dev->unique )
__field( bool, stop_req )
__field( u64, clk_rate )
),
TP_fast_assign(
- __entry->dev = dev;
+ __assign_str(dev_name, dev->unique);
__entry->stop_req = stop_req;
__entry->clk_rate = clk_rate;
),
- TP_printk("dev:%s stop_req:%s clk_rate:%llu", __entry->dev->unique,
+ TP_printk("dev:%s stop_req:%s clk_rate:%llu", __get_str(dev_name),
__entry->stop_req ? "true" : "false", __entry->clk_rate)
);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index 7d306c5acd09..7f42c3e68a53 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -185,7 +185,7 @@ static void mdp5_plane_reset(struct drm_plane *plane)
struct mdp5_plane_state *mdp5_state;
if (plane->state && plane->state->fb)
- drm_framebuffer_unreference(plane->state->fb);
+ drm_framebuffer_put(plane->state->fb);
kfree(to_mdp5_plane_state(plane->state));
mdp5_state = kzalloc(sizeof(*mdp5_state), GFP_KERNEL);
@@ -228,7 +228,7 @@ static void mdp5_plane_destroy_state(struct drm_plane *plane,
struct mdp5_plane_state *pstate = to_mdp5_plane_state(state);
if (state->fb)
- drm_framebuffer_unreference(state->fb);
+ drm_framebuffer_put(state->fb);
kfree(pstate);
}
@@ -259,7 +259,6 @@ static void mdp5_plane_cleanup_fb(struct drm_plane *plane,
msm_framebuffer_cleanup(fb, kms->aspace);
}
-#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state,
struct drm_plane_state *state)
{
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ff8164cc6738..a9768f823290 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -83,6 +83,7 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
return ERR_PTR(-ENOMEM);
DBG("dsi probed=%p", msm_dsi);
+ msm_dsi->id = -1;
msm_dsi->pdev = pdev;
platform_set_drvdata(pdev, msm_dsi);
@@ -117,8 +118,13 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
DBG("");
msm_dsi = dsi_init(pdev);
- if (IS_ERR(msm_dsi))
- return PTR_ERR(msm_dsi);
+ if (IS_ERR(msm_dsi)) {
+ /* Don't fail the bind if the dsi port is not connected */
+ if (PTR_ERR(msm_dsi) == -ENODEV)
+ return 0;
+ else
+ return PTR_ERR(msm_dsi);
+ }
priv->dsi[msm_dsi->id] = msm_dsi;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 96fb5f635314..9c6c523eacdc 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -1750,6 +1750,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
if (ret) {
dev_err(dev, "%s: invalid lane configuration %d\n",
__func__, ret);
+ ret = -EINVAL;
goto err;
}
@@ -1757,6 +1758,7 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
device_node = of_graph_get_remote_node(np, 1, 0);
if (!device_node) {
dev_dbg(dev, "%s: no valid device\n", __func__);
+ ret = -ENODEV;
goto err;
}
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 5224010d90e4..80aa6344185e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -839,6 +839,8 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi)
if (msm_dsi->host)
msm_dsi_host_unregister(msm_dsi->host);
- msm_dsim->dsi[msm_dsi->id] = NULL;
+
+ if (msm_dsi->id >= 0)
+ msm_dsim->dsi[msm_dsi->id] = NULL;
}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c1abad8a8612..4904d0d41409 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -337,7 +337,7 @@ static int msm_drm_uninit(struct device *dev)
mdss->funcs->destroy(ddev);
ddev->dev_private = NULL;
- drm_dev_unref(ddev);
+ drm_dev_put(ddev);
kfree(priv);
@@ -452,7 +452,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv)
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv) {
ret = -ENOMEM;
- goto err_unref_drm_dev;
+ goto err_put_drm_dev;
}
ddev->dev_private = priv;
@@ -653,8 +653,8 @@ err_destroy_mdss:
mdss->funcs->destroy(ddev);
err_free_priv:
kfree(priv);
-err_unref_drm_dev:
- drm_dev_unref(ddev);
+err_put_drm_dev:
+ drm_dev_put(ddev);
return ret;
}
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 8e510d5c758a..9d11f321f5a9 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -62,6 +62,8 @@ struct msm_gem_vma;
#define MAX_BRIDGES 8
#define MAX_CONNECTORS 8
+#define FRAC_16_16(mult, div) (((mult) << 16) / (div))
+
struct msm_file_private {
rwlock_t queuelock;
struct list_head submitqueues;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 7bd83e0afa97..7a7923e6220d 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -144,7 +144,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
goto out_unlock;
}
- drm_gem_object_reference(obj);
+ drm_gem_object_get(obj);
submit->bos[i].obj = msm_obj;
@@ -396,7 +396,7 @@ static void submit_cleanup(struct msm_gem_submit *submit)
struct msm_gem_object *msm_obj = submit->bos[i].obj;
submit_unlock_unpin_bo(submit, i, false);
list_del_init(&msm_obj->submit_entry);
- drm_gem_object_unreference(&msm_obj->base);
+ drm_gem_object_put(&msm_obj->base);
}
ww_acquire_fini(&submit->ticket);
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 5e808cfec345..11aac8337066 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -41,7 +41,11 @@ static int msm_devfreq_target(struct device *dev, unsigned long *freq,
if (IS_ERR(opp))
return PTR_ERR(opp);
- clk_set_rate(gpu->core_clk, *freq);
+ if (gpu->funcs->gpu_set_freq)
+ gpu->funcs->gpu_set_freq(gpu, (u64)*freq);
+ else
+ clk_set_rate(gpu->core_clk, *freq);
+
dev_pm_opp_put(opp);
return 0;
@@ -51,16 +55,14 @@ static int msm_devfreq_get_dev_status(struct device *dev,
struct devfreq_dev_status *status)
{
struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
- u64 cycles;
- u32 freq = ((u32) status->current_frequency) / 1000000;
ktime_t time;
- status->current_frequency = (unsigned long) clk_get_rate(gpu->core_clk);
- gpu->funcs->gpu_busy(gpu, &cycles);
-
- status->busy_time = ((u32) (cycles - gpu->devfreq.busy_cycles)) / freq;
+ if (gpu->funcs->gpu_get_freq)
+ status->current_frequency = gpu->funcs->gpu_get_freq(gpu);
+ else
+ status->current_frequency = clk_get_rate(gpu->core_clk);
- gpu->devfreq.busy_cycles = cycles;
+ status->busy_time = gpu->funcs->gpu_busy(gpu);
time = ktime_get();
status->total_time = ktime_us_delta(time, gpu->devfreq.time);
@@ -73,7 +75,10 @@ static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
{
struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
- *freq = (unsigned long) clk_get_rate(gpu->core_clk);
+ if (gpu->funcs->gpu_get_freq)
+ *freq = gpu->funcs->gpu_get_freq(gpu);
+ else
+ *freq = clk_get_rate(gpu->core_clk);
return 0;
}
@@ -88,7 +93,7 @@ static struct devfreq_dev_profile msm_devfreq_profile = {
static void msm_devfreq_init(struct msm_gpu *gpu)
{
/* We need target support to do devfreq */
- if (!gpu->funcs->gpu_busy || !gpu->core_clk)
+ if (!gpu->funcs->gpu_busy)
return;
msm_devfreq_profile.initial_freq = gpu->fast_rate;
@@ -105,6 +110,8 @@ static void msm_devfreq_init(struct msm_gpu *gpu)
dev_err(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n");
gpu->devfreq.devfreq = NULL;
}
+
+ devfreq_suspend_device(gpu->devfreq.devfreq);
}
static int enable_pwrrail(struct msm_gpu *gpu)
@@ -184,6 +191,14 @@ static int disable_axi(struct msm_gpu *gpu)
return 0;
}
+void msm_gpu_resume_devfreq(struct msm_gpu *gpu)
+{
+ gpu->devfreq.busy_cycles = 0;
+ gpu->devfreq.time = ktime_get();
+
+ devfreq_resume_device(gpu->devfreq.devfreq);
+}
+
int msm_gpu_pm_resume(struct msm_gpu *gpu)
{
int ret;
@@ -202,12 +217,7 @@ int msm_gpu_pm_resume(struct msm_gpu *gpu)
if (ret)
return ret;
- if (gpu->devfreq.devfreq) {
- gpu->devfreq.busy_cycles = 0;
- gpu->devfreq.time = ktime_get();
-
- devfreq_resume_device(gpu->devfreq.devfreq);
- }
+ msm_gpu_resume_devfreq(gpu);
gpu->needs_hw_init = true;
@@ -220,8 +230,7 @@ int msm_gpu_pm_suspend(struct msm_gpu *gpu)
DBG("%s", gpu->name);
- if (gpu->devfreq.devfreq)
- devfreq_suspend_device(gpu->devfreq.devfreq);
+ devfreq_suspend_device(gpu->devfreq.devfreq);
ret = disable_axi(gpu);
if (ret)
@@ -367,8 +376,8 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
msm_gpu_devcoredump_read, msm_gpu_devcoredump_free);
}
#else
-static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, char *comm,
- char *cmd)
+static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
+ struct msm_gem_submit *submit, char *comm, char *cmd)
{
}
#endif
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 9122ee6e55e4..f82bac086666 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -70,9 +70,11 @@ struct msm_gpu_funcs {
/* for generation specific debugfs: */
int (*debugfs_init)(struct msm_gpu *gpu, struct drm_minor *minor);
#endif
- int (*gpu_busy)(struct msm_gpu *gpu, uint64_t *value);
+ unsigned long (*gpu_busy)(struct msm_gpu *gpu);
struct msm_gpu_state *(*gpu_state_get)(struct msm_gpu *gpu);
int (*gpu_state_put)(struct msm_gpu_state *state);
+ unsigned long (*gpu_get_freq)(struct msm_gpu *gpu);
+ void (*gpu_set_freq)(struct msm_gpu *gpu, unsigned long freq);
};
struct msm_gpu {
@@ -264,6 +266,7 @@ static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
int msm_gpu_pm_suspend(struct msm_gpu *gpu);
int msm_gpu_pm_resume(struct msm_gpu *gpu);
+void msm_gpu_resume_devfreq(struct msm_gpu *gpu);
int msm_gpu_hw_init(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c
index 3aa8a8576abe..cca933458439 100644
--- a/drivers/gpu/drm/msm/msm_rd.c
+++ b/drivers/gpu/drm/msm/msm_rd.c
@@ -366,7 +366,7 @@ void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
va_list args;
va_start(args, fmt);
- n = vsnprintf(msg, sizeof(msg), fmt, args);
+ n = vscnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4));
@@ -375,11 +375,11 @@ void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
rcu_read_lock();
task = pid_task(submit->pid, PIDTYPE_PID);
if (task) {
- n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
+ n = scnprintf(msg, sizeof(msg), "%.*s/%d: fence=%u",
TASK_COMM_LEN, task->comm,
pid_nr(submit->pid), submit->seqno);
} else {
- n = snprintf(msg, sizeof(msg), "???/%d: fence=%u",
+ n = scnprintf(msg, sizeof(msg), "???/%d: fence=%u",
pid_nr(submit->pid), submit->seqno);
}
rcu_read_unlock();
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 1dbd1dcdcf15..5f163a025e89 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -36,6 +36,7 @@
#include <drm/drm_dp_helper.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_plane_helper.h>
+#include <drm/drm_scdc_helper.h>
#include <drm/drm_edid.h>
#include <nvif/class.h>
@@ -531,6 +532,7 @@ nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
static void
nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
{
+ struct nouveau_drm *drm = nouveau_drm(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
struct nouveau_crtc *nv_crtc = nouveau_crtc(encoder->crtc);
struct nv50_disp *disp = nv50_disp(encoder->dev);
@@ -548,9 +550,12 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
.pwr.rekey = 56, /* binary driver, and tegra, constant */
};
struct nouveau_connector *nv_connector;
+ struct drm_hdmi_info *hdmi;
u32 max_ac_packet;
union hdmi_infoframe avi_frame;
union hdmi_infoframe vendor_frame;
+ bool scdc_supported, high_tmds_clock_ratio = false, scrambling = false;
+ u8 config;
int ret;
int size;
@@ -558,8 +563,11 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
if (!drm_detect_hdmi_monitor(nv_connector->edid))
return;
+ hdmi = &nv_connector->base.display_info.hdmi;
+ scdc_supported = hdmi->scdc.supported;
+
ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi, mode,
- false);
+ scdc_supported);
if (!ret) {
/* We have an AVI InfoFrame, populate it to the display */
args.pwr.avi_infoframe_length
@@ -582,12 +590,42 @@ nv50_hdmi_enable(struct drm_encoder *encoder, struct drm_display_mode *mode)
max_ac_packet -= 18; /* constant from tegra */
args.pwr.max_ac_packet = max_ac_packet / 32;
+ if (hdmi->scdc.scrambling.supported) {
+ high_tmds_clock_ratio = mode->clock > 340000;
+ scrambling = high_tmds_clock_ratio ||
+ hdmi->scdc.scrambling.low_rates;
+ }
+
+ args.pwr.scdc =
+ NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE * scrambling |
+ NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 * high_tmds_clock_ratio;
+
size = sizeof(args.base)
+ sizeof(args.pwr)
+ args.pwr.avi_infoframe_length
+ args.pwr.vendor_infoframe_length;
nvif_mthd(&disp->disp->object, 0, &args, size);
+
nv50_audio_enable(encoder, mode);
+
+ /* If SCDC is supported by the downstream monitor, update
+ * divider / scrambling settings to what we programmed above.
+ */
+ if (!hdmi->scdc.scrambling.supported)
+ return;
+
+ ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config);
+ if (ret < 0) {
+ NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret);
+ return;
+ }
+ config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
+ config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 * high_tmds_clock_ratio;
+ config |= SCDC_SCRAMBLING_ENABLE * scrambling;
+ ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config);
+ if (ret < 0)
+ NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n",
+ config, ret);
}
/******************************************************************************
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
index 7cdf53615d7b..bced81987269 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
@@ -69,7 +69,10 @@ struct nv50_disp_sor_hdmi_pwr_v0 {
__u8 rekey;
__u8 avi_infoframe_length;
__u8 vendor_infoframe_length;
- __u8 pad06[2];
+#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE (1 << 0)
+#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 (1 << 1)
+ __u8 scdc;
+ __u8 pad07[1];
};
struct nv50_disp_sor_lvds_script_v0 {
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index 408b955e5c39..5f5be6368aed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -37,18 +37,19 @@
#include "nouveau_drv.h"
#include "nouveau_reg.h"
#include "nouveau_encoder.h"
+#include "nouveau_connector.h"
static struct ida bl_ida;
#define BL_NAME_SIZE 15 // 12 for name + 2 for digits + 1 for '\0'
-struct backlight_connector {
- struct list_head head;
+struct nouveau_backlight {
+ struct backlight_device *dev;
int id;
};
static bool
-nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_connector
- *connector)
+nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE],
+ struct nouveau_backlight *bl)
{
const int nb = ida_simple_get(&bl_ida, 0, 0, GFP_KERNEL);
if (nb < 0 || nb >= 100)
@@ -57,17 +58,18 @@ nouveau_get_backlight_name(char backlight_name[BL_NAME_SIZE], struct backlight_c
snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight%d", nb);
else
snprintf(backlight_name, BL_NAME_SIZE, "nv_backlight");
- connector->id = nb;
+ bl->id = nb;
return true;
}
static int
nv40_get_intensity(struct backlight_device *bd)
{
- struct nouveau_drm *drm = bl_get_data(bd);
+ struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+ struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nvif_object *device = &drm->client.device.object;
int val = (nvif_rd32(device, NV40_PMC_BACKLIGHT) &
- NV40_PMC_BACKLIGHT_MASK) >> 16;
+ NV40_PMC_BACKLIGHT_MASK) >> 16;
return val;
}
@@ -75,13 +77,14 @@ nv40_get_intensity(struct backlight_device *bd)
static int
nv40_set_intensity(struct backlight_device *bd)
{
- struct nouveau_drm *drm = bl_get_data(bd);
+ struct nouveau_encoder *nv_encoder = bl_get_data(bd);
+ struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nvif_object *device = &drm->client.device.object;
int val = bd->props.brightness;
int reg = nvif_rd32(device, NV40_PMC_BACKLIGHT);
nvif_wr32(device, NV40_PMC_BACKLIGHT,
- (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
+ (val << 16) | (reg & ~NV40_PMC_BACKLIGHT_MASK));
return 0;
}
@@ -93,38 +96,19 @@ static const struct backlight_ops nv40_bl_ops = {
};
static int
-nv40_backlight_init(struct drm_connector *connector)
+nv40_backlight_init(struct nouveau_encoder *encoder,
+ struct backlight_properties *props,
+ const struct backlight_ops **ops)
{
- struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ struct nouveau_drm *drm = nouveau_drm(encoder->base.base.dev);
struct nvif_object *device = &drm->client.device.object;
- struct backlight_properties props;
- struct backlight_device *bd;
- struct backlight_connector bl_connector;
- char backlight_name[BL_NAME_SIZE];
if (!(nvif_rd32(device, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
- return 0;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.type = BACKLIGHT_RAW;
- props.max_brightness = 31;
- if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
- NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
- return 0;
- }
- bd = backlight_device_register(backlight_name , connector->kdev, drm,
- &nv40_bl_ops, &props);
-
- if (IS_ERR(bd)) {
- if (bl_connector.id > 0)
- ida_simple_remove(&bl_ida, bl_connector.id);
- return PTR_ERR(bd);
- }
- list_add(&bl_connector.head, &drm->bl_connectors);
- drm->backlight = bd;
- bd->props.brightness = nv40_get_intensity(bd);
- backlight_update_status(bd);
+ return -ENODEV;
+ props->type = BACKLIGHT_RAW;
+ props->max_brightness = 31;
+ *ops = &nv40_bl_ops;
return 0;
}
@@ -154,7 +138,7 @@ nv50_set_intensity(struct backlight_device *bd)
u32 val = (bd->props.brightness * div) / 100;
nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
- NV50_PDISP_SOR_PWM_CTL_NEW | val);
+ NV50_PDISP_SOR_PWM_CTL_NEW | val);
return 0;
}
@@ -194,9 +178,10 @@ nva3_set_intensity(struct backlight_device *bd)
div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
val = (bd->props.brightness * div) / 100;
if (div) {
- nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or), val |
- NV50_PDISP_SOR_PWM_CTL_NEW |
- NVA3_PDISP_SOR_PWM_CTL_UNK);
+ nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
+ val |
+ NV50_PDISP_SOR_PWM_CTL_NEW |
+ NVA3_PDISP_SOR_PWM_CTL_UNK);
return 0;
}
@@ -210,110 +195,119 @@ static const struct backlight_ops nva3_bl_ops = {
};
static int
-nv50_backlight_init(struct drm_connector *connector)
+nv50_backlight_init(struct nouveau_encoder *nv_encoder,
+ struct backlight_properties *props,
+ const struct backlight_ops **ops)
{
- struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
struct nvif_object *device = &drm->client.device.object;
- struct nouveau_encoder *nv_encoder;
- struct backlight_properties props;
- struct backlight_device *bd;
- const struct backlight_ops *ops;
- struct backlight_connector bl_connector;
- char backlight_name[BL_NAME_SIZE];
-
- nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
- if (!nv_encoder) {
- nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
- if (!nv_encoder)
- return -ENODEV;
- }
if (!nvif_rd32(device, NV50_PDISP_SOR_PWM_CTL(ffs(nv_encoder->dcb->or) - 1)))
- return 0;
+ return -ENODEV;
if (drm->client.device.info.chipset <= 0xa0 ||
drm->client.device.info.chipset == 0xaa ||
drm->client.device.info.chipset == 0xac)
- ops = &nv50_bl_ops;
+ *ops = &nv50_bl_ops;
else
- ops = &nva3_bl_ops;
-
- memset(&props, 0, sizeof(struct backlight_properties));
- props.type = BACKLIGHT_RAW;
- props.max_brightness = 100;
- if (!nouveau_get_backlight_name(backlight_name, &bl_connector)) {
- NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
- return 0;
- }
- bd = backlight_device_register(backlight_name , connector->kdev,
- nv_encoder, ops, &props);
+ *ops = &nva3_bl_ops;
- if (IS_ERR(bd)) {
- if (bl_connector.id > 0)
- ida_simple_remove(&bl_ida, bl_connector.id);
- return PTR_ERR(bd);
- }
+ props->type = BACKLIGHT_RAW;
+ props->max_brightness = 100;
- list_add(&bl_connector.head, &drm->bl_connectors);
- drm->backlight = bd;
- bd->props.brightness = bd->ops->get_brightness(bd);
- backlight_update_status(bd);
return 0;
}
int
-nouveau_backlight_init(struct drm_device *dev)
+nouveau_backlight_init(struct drm_connector *connector)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
+ struct nouveau_drm *drm = nouveau_drm(connector->dev);
+ struct nouveau_backlight *bl;
+ struct nouveau_encoder *nv_encoder = NULL;
struct nvif_device *device = &drm->client.device;
- struct drm_connector *connector;
- struct drm_connector_list_iter conn_iter;
-
- INIT_LIST_HEAD(&drm->bl_connectors);
+ char backlight_name[BL_NAME_SIZE];
+ struct backlight_properties props = {0};
+ const struct backlight_ops *ops;
+ int ret;
if (apple_gmux_present()) {
- NV_INFO(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
+ NV_INFO_ONCE(drm, "Apple GMUX detected: not registering Nouveau backlight interface\n");
return 0;
}
- drm_connector_list_iter_begin(dev, &conn_iter);
- drm_for_each_connector_iter(connector, &conn_iter) {
- if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS &&
- connector->connector_type != DRM_MODE_CONNECTOR_eDP)
- continue;
-
- switch (device->info.family) {
- case NV_DEVICE_INFO_V0_CURIE:
- return nv40_backlight_init(connector);
- case NV_DEVICE_INFO_V0_TESLA:
- case NV_DEVICE_INFO_V0_FERMI:
- case NV_DEVICE_INFO_V0_KEPLER:
- case NV_DEVICE_INFO_V0_MAXWELL:
- return nv50_backlight_init(connector);
- default:
- break;
- }
+ if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+ nv_encoder = find_encoder(connector, DCB_OUTPUT_LVDS);
+ else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+ nv_encoder = find_encoder(connector, DCB_OUTPUT_DP);
+ else
+ return 0;
+
+ if (!nv_encoder)
+ return 0;
+
+ switch (device->info.family) {
+ case NV_DEVICE_INFO_V0_CURIE:
+ ret = nv40_backlight_init(nv_encoder, &props, &ops);
+ break;
+ case NV_DEVICE_INFO_V0_TESLA:
+ case NV_DEVICE_INFO_V0_FERMI:
+ case NV_DEVICE_INFO_V0_KEPLER:
+ case NV_DEVICE_INFO_V0_MAXWELL:
+ ret = nv50_backlight_init(nv_encoder, &props, &ops);
+ break;
+ default:
+ return 0;
}
- drm_connector_list_iter_end(&conn_iter);
+
+ if (ret == -ENODEV)
+ return 0;
+ else if (ret)
+ return ret;
+
+ bl = kzalloc(sizeof(*bl), GFP_KERNEL);
+ if (!bl)
+ return -ENOMEM;
+
+ if (!nouveau_get_backlight_name(backlight_name, bl)) {
+ NV_ERROR(drm, "Failed to retrieve a unique name for the backlight interface\n");
+ goto fail_alloc;
+ }
+
+ bl->dev = backlight_device_register(backlight_name, connector->kdev,
+ nv_encoder, ops, &props);
+ if (IS_ERR(bl->dev)) {
+ if (bl->id >= 0)
+ ida_simple_remove(&bl_ida, bl->id);
+ ret = PTR_ERR(bl->dev);
+ goto fail_alloc;
+ }
+
+ nouveau_connector(connector)->backlight = bl;
+ bl->dev->props.brightness = bl->dev->ops->get_brightness(bl->dev);
+ backlight_update_status(bl->dev);
return 0;
+
+fail_alloc:
+ kfree(bl);
+ return ret;
}
void
-nouveau_backlight_exit(struct drm_device *dev)
+nouveau_backlight_fini(struct drm_connector *connector)
{
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct backlight_connector *connector;
+ struct nouveau_connector *nv_conn = nouveau_connector(connector);
+ struct nouveau_backlight *bl = nv_conn->backlight;
- list_for_each_entry(connector, &drm->bl_connectors, head) {
- if (connector->id >= 0)
- ida_simple_remove(&bl_ida, connector->id);
- }
+ if (!bl)
+ return;
- if (drm->backlight) {
- backlight_device_unregister(drm->backlight);
- drm->backlight = NULL;
- }
+ if (bl->id >= 0)
+ ida_simple_remove(&bl_ida, bl->id);
+
+ backlight_device_unregister(bl->dev);
+ nv_conn->backlight = NULL;
+ kfree(bl);
}
void
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index dde8724aa8f5..fd80661dff92 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -886,6 +886,22 @@ nouveau_connector_detect_depth(struct drm_connector *connector)
}
static int
+nouveau_connector_late_register(struct drm_connector *connector)
+{
+ int ret;
+
+ ret = nouveau_backlight_init(connector);
+
+ return ret;
+}
+
+static void
+nouveau_connector_early_unregister(struct drm_connector *connector)
+{
+ nouveau_backlight_fini(connector);
+}
+
+static int
nouveau_connector_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
@@ -953,18 +969,33 @@ nouveau_connector_get_modes(struct drm_connector *connector)
}
static unsigned
-get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
+get_tmds_link_bandwidth(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
+ struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
struct nouveau_drm *drm = nouveau_drm(connector->dev);
struct dcb_output *dcb = nv_connector->detected_encoder->dcb;
+ struct drm_display_info *info = NULL;
+ const unsigned duallink_scale =
+ nouveau_duallink && nv_encoder->dcb->duallink_possible ? 2 : 1;
+
+ if (drm_detect_hdmi_monitor(nv_connector->edid))
+ info = &nv_connector->base.display_info;
- if (hdmi) {
+ if (info) {
if (nouveau_hdmimhz > 0)
return nouveau_hdmimhz * 1000;
/* Note: these limits are conservative, some Fermi's
* can do 297 MHz. Unclear how this can be determined.
*/
+ if (drm->client.device.info.chipset >= 0x120) {
+ const int max_tmds_clock =
+ info->hdmi.scdc.scrambling.supported ?
+ 594000 : 340000;
+ return info->max_tmds_clock ?
+ min(info->max_tmds_clock, max_tmds_clock) :
+ max_tmds_clock;
+ }
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_KEPLER)
return 297000;
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI)
@@ -972,13 +1003,13 @@ get_tmds_link_bandwidth(struct drm_connector *connector, bool hdmi)
}
if (dcb->location != DCB_LOC_ON_CHIP ||
drm->client.device.info.chipset >= 0x46)
- return 165000;
+ return 165000 * duallink_scale;
else if (drm->client.device.info.chipset >= 0x40)
- return 155000;
+ return 155000 * duallink_scale;
else if (drm->client.device.info.chipset >= 0x18)
- return 135000;
+ return 135000 * duallink_scale;
else
- return 112000;
+ return 112000 * duallink_scale;
}
static enum drm_mode_status
@@ -990,7 +1021,6 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
unsigned min_clock = 25000, max_clock = min_clock;
unsigned clock = mode->clock;
- bool hdmi;
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_LVDS:
@@ -1003,11 +1033,7 @@ nouveau_connector_mode_valid(struct drm_connector *connector,
max_clock = 400000;
break;
case DCB_OUTPUT_TMDS:
- hdmi = drm_detect_hdmi_monitor(nv_connector->edid);
- max_clock = get_tmds_link_bandwidth(connector, hdmi);
- if (!hdmi && nouveau_duallink &&
- nv_encoder->dcb->duallink_possible)
- max_clock *= 2;
+ max_clock = get_tmds_link_bandwidth(connector);
break;
case DCB_OUTPUT_ANALOG:
max_clock = nv_encoder->dcb->crtconf.maxfreq;
@@ -1069,6 +1095,8 @@ nouveau_connector_funcs = {
.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
.atomic_set_property = nouveau_conn_atomic_set_property,
.atomic_get_property = nouveau_conn_atomic_get_property,
+ .late_register = nouveau_connector_late_register,
+ .early_unregister = nouveau_connector_early_unregister,
};
static const struct drm_connector_funcs
@@ -1084,6 +1112,8 @@ nouveau_connector_funcs_lvds = {
.atomic_destroy_state = nouveau_conn_atomic_destroy_state,
.atomic_set_property = nouveau_conn_atomic_set_property,
.atomic_get_property = nouveau_conn_atomic_get_property,
+ .late_register = nouveau_connector_late_register,
+ .early_unregister = nouveau_connector_early_unregister,
};
static int
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index 0acc07555bcd..f57ef35b1e5e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -39,6 +39,10 @@
struct nvkm_i2c_port;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+struct nouveau_backlight;
+#endif
+
struct nouveau_connector {
struct drm_connector base;
enum dcb_connector_type type;
@@ -55,6 +59,9 @@ struct nouveau_connector {
struct nouveau_encoder *detected_encoder;
struct edid *edid;
struct drm_display_mode *native_mode;
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+ struct nouveau_backlight *backlight;
+#endif
};
static inline struct nouveau_connector *nouveau_connector(
@@ -181,4 +188,30 @@ int nouveau_conn_atomic_get_property(struct drm_connector *,
const struct drm_connector_state *,
struct drm_property *, u64 *);
struct drm_display_mode *nouveau_conn_native_mode(struct drm_connector *);
+
+#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_fini(struct drm_connector *);
+extern void nouveau_backlight_ctor(void);
+extern void nouveau_backlight_dtor(void);
+#else
+static inline int
+nouveau_backlight_init(struct drm_connector *connector)
+{
+ return 0;
+}
+
+static inline void
+nouveau_backlight_fini(struct drm_connector *connector) {
+}
+
+static inline void
+nouveau_backlight_ctor(void) {
+}
+
+static inline void
+nouveau_backlight_dtor(void) {
+}
+#endif
+
#endif /* __NOUVEAU_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 540c0cbbfcee..f326ffd86766 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -582,7 +582,6 @@ nouveau_display_create(struct drm_device *dev)
goto vblank_err;
}
- nouveau_backlight_init(dev);
INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
#ifdef CONFIG_ACPI
drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
@@ -607,7 +606,6 @@ nouveau_display_destroy(struct drm_device *dev)
#ifdef CONFIG_ACPI
unregister_acpi_notifier(&nouveau_drm(dev)->acpi_nb);
#endif
- nouveau_backlight_exit(dev);
nouveau_display_vblank_fini(dev);
drm_kms_helper_poll_fini(dev);
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index ff92b54ce448..eb77e41c2d4e 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -85,31 +85,6 @@ int nouveau_display_dumb_map_offset(struct drm_file *, struct drm_device *,
void nouveau_hdmi_mode_set(struct drm_encoder *, struct drm_display_mode *);
-#ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
-extern void nouveau_backlight_ctor(void);
-extern void nouveau_backlight_dtor(void);
-#else
-static inline int
-nouveau_backlight_init(struct drm_device *dev)
-{
- return 0;
-}
-
-static inline void
-nouveau_backlight_exit(struct drm_device *dev) {
-}
-
-static inline void
-nouveau_backlight_ctor(void) {
-}
-
-static inline void
-nouveau_backlight_dtor(void) {
-}
-#endif
-
struct drm_framebuffer *
nouveau_user_framebuffer_create(struct drm_device *, struct drm_file *,
const struct drm_mode_fb_cmd2 *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 74d2283f2c28..2b2baf6e0e0d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -458,75 +458,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
nouveau_bo_move_init(drm);
}
-static int nouveau_drm_probe(struct pci_dev *pdev,
- const struct pci_device_id *pent)
-{
- struct nvkm_device *device;
- struct apertures_struct *aper;
- bool boot = false;
- int ret;
-
- if (vga_switcheroo_client_probe_defer(pdev))
- return -EPROBE_DEFER;
-
- /* We need to check that the chipset is supported before booting
- * fbdev off the hardware, as there's no way to put it back.
- */
- ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
- if (ret)
- return ret;
-
- nvkm_device_del(&device);
-
- /* Remove conflicting drivers (vesafb, efifb etc). */
- aper = alloc_apertures(3);
- if (!aper)
- return -ENOMEM;
-
- aper->ranges[0].base = pci_resource_start(pdev, 1);
- aper->ranges[0].size = pci_resource_len(pdev, 1);
- aper->count = 1;
-
- if (pci_resource_len(pdev, 2)) {
- aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
- aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
- aper->count++;
- }
-
- if (pci_resource_len(pdev, 3)) {
- aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
- aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
- aper->count++;
- }
-
-#ifdef CONFIG_X86
- boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
-#endif
- if (nouveau_modeset != 2)
- drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot);
- kfree(aper);
-
- ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
- true, true, ~0ULL, &device);
- if (ret)
- return ret;
-
- pci_set_master(pdev);
-
- if (nouveau_atomic)
- driver_pci.driver_features |= DRIVER_ATOMIC;
-
- ret = drm_get_pci_dev(pdev, pent, &driver_pci);
- if (ret) {
- nvkm_device_del(&device);
- return ret;
- }
-
- return 0;
-}
-
static int
-nouveau_drm_load(struct drm_device *dev, unsigned long flags)
+nouveau_drm_device_init(struct drm_device *dev)
{
struct nouveau_drm *drm;
int ret;
@@ -538,11 +471,11 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
ret = nouveau_cli_init(drm, "DRM-master", &drm->master);
if (ret)
- return ret;
+ goto fail_alloc;
ret = nouveau_cli_init(drm, "DRM", &drm->client);
if (ret)
- return ret;
+ goto fail_master;
dev->irq_enabled = true;
@@ -605,13 +538,15 @@ fail_bios:
fail_ttm:
nouveau_vga_fini(drm);
nouveau_cli_fini(&drm->client);
+fail_master:
nouveau_cli_fini(&drm->master);
+fail_alloc:
kfree(drm);
return ret;
}
static void
-nouveau_drm_unload(struct drm_device *dev)
+nouveau_drm_device_fini(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
@@ -640,18 +575,116 @@ nouveau_drm_unload(struct drm_device *dev)
kfree(drm);
}
+static int nouveau_drm_probe(struct pci_dev *pdev,
+ const struct pci_device_id *pent)
+{
+ struct nvkm_device *device;
+ struct drm_device *drm_dev;
+ struct apertures_struct *aper;
+ bool boot = false;
+ int ret;
+
+ if (vga_switcheroo_client_probe_defer(pdev))
+ return -EPROBE_DEFER;
+
+ /* We need to check that the chipset is supported before booting
+ * fbdev off the hardware, as there's no way to put it back.
+ */
+ ret = nvkm_device_pci_new(pdev, NULL, "error", true, false, 0, &device);
+ if (ret)
+ return ret;
+
+ nvkm_device_del(&device);
+
+ /* Remove conflicting drivers (vesafb, efifb etc). */
+ aper = alloc_apertures(3);
+ if (!aper)
+ return -ENOMEM;
+
+ aper->ranges[0].base = pci_resource_start(pdev, 1);
+ aper->ranges[0].size = pci_resource_len(pdev, 1);
+ aper->count = 1;
+
+ if (pci_resource_len(pdev, 2)) {
+ aper->ranges[aper->count].base = pci_resource_start(pdev, 2);
+ aper->ranges[aper->count].size = pci_resource_len(pdev, 2);
+ aper->count++;
+ }
+
+ if (pci_resource_len(pdev, 3)) {
+ aper->ranges[aper->count].base = pci_resource_start(pdev, 3);
+ aper->ranges[aper->count].size = pci_resource_len(pdev, 3);
+ aper->count++;
+ }
+
+#ifdef CONFIG_X86
+ boot = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
+#endif
+ if (nouveau_modeset != 2)
+ drm_fb_helper_remove_conflicting_framebuffers(aper, "nouveaufb", boot);
+ kfree(aper);
+
+ ret = nvkm_device_pci_new(pdev, nouveau_config, nouveau_debug,
+ true, true, ~0ULL, &device);
+ if (ret)
+ return ret;
+
+ pci_set_master(pdev);
+
+ if (nouveau_atomic)
+ driver_pci.driver_features |= DRIVER_ATOMIC;
+
+ drm_dev = drm_dev_alloc(&driver_pci, &pdev->dev);
+ if (IS_ERR(drm_dev)) {
+ ret = PTR_ERR(drm_dev);
+ goto fail_nvkm;
+ }
+
+ ret = pci_enable_device(pdev);
+ if (ret)
+ goto fail_drm;
+
+ drm_dev->pdev = pdev;
+ pci_set_drvdata(pdev, drm_dev);
+
+ ret = nouveau_drm_device_init(drm_dev);
+ if (ret)
+ goto fail_pci;
+
+ ret = drm_dev_register(drm_dev, pent->driver_data);
+ if (ret)
+ goto fail_drm_dev_init;
+
+ return 0;
+
+fail_drm_dev_init:
+ nouveau_drm_device_fini(drm_dev);
+fail_pci:
+ pci_disable_device(pdev);
+fail_drm:
+ drm_dev_put(drm_dev);
+fail_nvkm:
+ nvkm_device_del(&device);
+ return ret;
+}
+
void
nouveau_drm_device_remove(struct drm_device *dev)
{
+ struct pci_dev *pdev = dev->pdev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nvkm_client *client;
struct nvkm_device *device;
+ drm_dev_unregister(dev);
+
dev->irq_enabled = false;
client = nvxx_client(&drm->client.base);
device = nvkm_device_find(client->device);
- drm_put_dev(dev);
+ nouveau_drm_device_fini(dev);
+ pci_disable_device(pdev);
+ drm_dev_put(dev);
nvkm_device_del(&device);
}
@@ -1018,8 +1051,6 @@ driver_stub = {
DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER |
DRIVER_KMS_LEGACY_CONTEXT,
- .load = nouveau_drm_load,
- .unload = nouveau_drm_unload,
.open = nouveau_drm_open,
.postclose = nouveau_drm_postclose,
.lastclose = nouveau_vga_lastclose,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 6e1acaec3400..0b2191fa96f7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -194,8 +194,6 @@ struct nouveau_drm {
/* modesetting */
struct nvbios vbios;
struct nouveau_display *display;
- struct backlight_device *backlight;
- struct list_head bl_connectors;
struct work_struct hpd_work;
struct work_struct fbcon_work;
int fbcon_new_state;
@@ -244,10 +242,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
struct nouveau_cli *_cli = (c); \
dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \
} while(0)
+
#define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a)
#define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a)
#define NV_WARN(drm,f,a...) NV_PRINTK(warn, &(drm)->client, f, ##a)
#define NV_INFO(drm,f,a...) NV_PRINTK(info, &(drm)->client, f, ##a)
+
#define NV_DEBUG(drm,f,a...) do { \
if (unlikely(drm_debug & DRM_UT_DRIVER)) \
NV_PRINTK(info, &(drm)->client, f, ##a); \
@@ -257,6 +257,12 @@ void nouveau_drm_device_remove(struct drm_device *dev);
NV_PRINTK(info, &(drm)->client, f, ##a); \
} while(0)
+#define NV_PRINTK_ONCE(l,c,f,a...) NV_PRINTK(l##_once,c,f, ##a)
+
+#define NV_ERROR_ONCE(drm,f,a...) NV_PRINTK_ONCE(err, &(drm)->client, f, ##a)
+#define NV_WARN_ONCE(drm,f,a...) NV_PRINTK_ONCE(warn, &(drm)->client, f, ##a)
+#define NV_INFO_ONCE(drm,f,a...) NV_PRINTK_ONCE(info, &(drm)->client, f, ##a)
+
extern int nouveau_modeset;
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
index 3d485dbf310a..8089ac9a12e2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -50,6 +50,7 @@ nvkm-y += nvkm/engine/disp/hdmig84.o
nvkm-y += nvkm/engine/disp/hdmigt215.o
nvkm-y += nvkm/engine/disp/hdmigf119.o
nvkm-y += nvkm/engine/disp/hdmigk104.o
+nvkm-y += nvkm/engine/disp/hdmigm200.o
nvkm-y += nvkm/engine/disp/hdmigv100.o
nvkm-y += nvkm/engine/disp/conn.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
new file mode 100644
index 000000000000..9b16a08eb4d9
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2018 Ilia Mirkin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ilia Mirkin
+ */
+#include "hdmi.h"
+
+void
+gm200_hdmi_scdc(struct nvkm_ior *ior, int head, u8 scdc)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ const u32 hoff = head * 0x800;
+ const u32 ctrl = scdc & 0x3;
+
+ nvkm_mask(device, 0x61c5bc + hoff, 0x00000003, ctrl);
+
+ ior->tmds.high_speed = !!(scdc & 0x2);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index 19911211a12a..0f0c86c32ec3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -41,6 +41,11 @@ struct nvkm_ior {
u8 nr;
u8 bw;
} dp;
+
+ /* Armed TMDS state. */
+ struct {
+ bool high_speed;
+ } tmds;
};
struct nvkm_ior_func {
@@ -61,6 +66,7 @@ struct nvkm_ior_func {
void (*ctrl)(struct nvkm_ior *, int head, bool enable,
u8 max_ac_packet, u8 rekey, u8 *avi, u8 avi_size,
u8 *vendor, u8 vendor_size);
+ void (*scdc)(struct nvkm_ior *, int head, u8 scdc);
} hdmi;
struct {
@@ -144,6 +150,8 @@ void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+void gm200_hdmi_scdc(struct nvkm_ior *, int, u8);
+
void gt215_hda_hpd(struct nvkm_ior *, int, bool);
void gt215_hda_eld(struct nvkm_ior *, u8 *, u8);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
index 3aa5a2879239..5f758948d6e1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
@@ -176,9 +176,10 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
- "max_ac_packet %d rekey %d\n",
+ "max_ac_packet %d rekey %d scdc %d\n",
args->v0.version, args->v0.state,
- args->v0.max_ac_packet, args->v0.rekey);
+ args->v0.max_ac_packet, args->v0.rekey,
+ args->v0.scdc);
if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
return -EINVAL;
if ((args->v0.avi_infoframe_length
@@ -202,6 +203,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
args->v0.max_ac_packet,
args->v0.rekey, avi, avi_size,
vendor, vendor_size);
+
+ if (outp->ior->func->hdmi.scdc)
+ outp->ior->func->hdmi.scdc(
+ outp->ior, hidx, args->v0.scdc);
+
return 0;
}
break;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
index e6e6dfbb1283..456a5a143522 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c
@@ -120,13 +120,16 @@ void
gf119_sor_clock(struct nvkm_ior *sor)
{
struct nvkm_device *device = sor->disp->engine.subdev.device;
- const int div = sor->asy.link == 3;
const u32 soff = nv50_ior_base(sor);
+ u32 div1 = sor->asy.link == 3;
+ u32 div2 = sor->asy.link == 3;
if (sor->asy.proto == TMDS) {
- /* NFI why, but this sets DP_LINK_BW_2_7 when using TMDS. */
- nvkm_mask(device, 0x612300 + soff, 0x007c0000, 0x0a << 18);
+ const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a;
+ nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18);
+ if (sor->tmds.high_speed)
+ div2 = 1;
}
- nvkm_mask(device, 0x612300 + soff, 0x00000707, (div << 8) | div);
+ nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1);
}
void
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
index d892bdf04034..384f82652bec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c
@@ -99,6 +99,7 @@ gm200_sor = {
.clock = gf119_sor_clock,
.hdmi = {
.ctrl = gk104_hdmi_ctrl,
+ .scdc = gm200_hdmi_scdc,
},
.dp = {
.lanes = { 0, 1, 2, 3 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
index 040db8a338de..8ba881a729ee 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c
@@ -88,6 +88,7 @@ gv100_sor = {
.clock = gf119_sor_clock,
.hdmi = {
.ctrl = gv100_hdmi_ctrl,
+ .scdc = gm200_hdmi_scdc,
},
.dp = {
.lanes = { 0, 1, 2, 3 },
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
index d02e183717dc..5c14d6ac855d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r352.c
@@ -801,6 +801,7 @@ acr_r352_load(struct nvkm_acr *_acr, struct nvkm_falcon *falcon,
bl = acr->hsbl_unload_blob;
} else {
nvkm_error(_acr->subdev, "invalid secure boot blob!\n");
+ kfree(bl_desc);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index e61a9592a650..ba82d916719c 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -1140,18 +1140,6 @@ static void dispc_ovl_set_color_mode(struct dispc_device *dispc,
REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), m, 4, 1);
}
-static bool format_is_yuv(u32 fourcc)
-{
- switch (fourcc) {
- case DRM_FORMAT_YUYV:
- case DRM_FORMAT_UYVY:
- case DRM_FORMAT_NV12:
- return true;
- default:
- return false;
- }
-}
-
static void dispc_ovl_configure_burst_type(struct dispc_device *dispc,
enum omap_plane_id plane,
enum omap_dss_rotation_type rotation)
@@ -1910,11 +1898,14 @@ static void dispc_ovl_set_scaling_uv(struct dispc_device *dispc,
int scale_x = out_width != orig_width;
int scale_y = out_height != orig_height;
bool chroma_upscale = plane != OMAP_DSS_WB;
+ const struct drm_format_info *info;
+
+ info = drm_format_info(fourcc);
if (!dispc_has_feature(dispc, FEAT_HANDLE_UV_SEPARATE))
return;
- if (!format_is_yuv(fourcc)) {
+ if (!info->is_yuv) {
/* reset chroma resampling for RGB formats */
if (plane != OMAP_DSS_WB)
REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane),
@@ -2624,7 +2615,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
unsigned int offset0, offset1;
s32 row_inc;
s32 pix_inc;
- u16 frame_width, frame_height;
+ u16 frame_width;
unsigned int field_offset = 0;
u16 in_height = height;
u16 in_width = width;
@@ -2632,6 +2623,9 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
bool ilace = !!(vm->flags & DISPLAY_FLAGS_INTERLACED);
unsigned long pclk = dispc_plane_pclk_rate(dispc, plane);
unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
+ const struct drm_format_info *info;
+
+ info = drm_format_info(fourcc);
/* when setting up WB, dispc_plane_pclk_rate() returns 0 */
if (plane == OMAP_DSS_WB)
@@ -2640,7 +2634,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER)
return -EINVAL;
- if (format_is_yuv(fourcc) && (in_width & 1)) {
+ if (info->is_yuv && (in_width & 1)) {
DSSERR("input width %d is not even for YUV format\n", in_width);
return -EINVAL;
}
@@ -2680,7 +2674,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
DSSDBG("predecimation %d x %x, new input size %d x %d\n",
x_predecim, y_predecim, in_width, in_height);
- if (format_is_yuv(fourcc) && (in_width & 1)) {
+ if (info->is_yuv && (in_width & 1)) {
DSSDBG("predecimated input width is not even for YUV format\n");
DSSDBG("adjusting input width %d -> %d\n",
in_width, in_width & ~1);
@@ -2688,7 +2682,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
in_width &= ~1;
}
- if (format_is_yuv(fourcc))
+ if (info->is_yuv)
cconv = 1;
if (ilace && !fieldmode) {
@@ -2714,13 +2708,10 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc,
row_inc = 0;
pix_inc = 0;
- if (plane == OMAP_DSS_WB) {
+ if (plane == OMAP_DSS_WB)
frame_width = out_width;
- frame_height = out_height;
- } else {
+ else
frame_width = in_width;
- frame_height = height;
- }
calc_offset(screen_width, frame_width,
fourcc, fieldmode, field_offset,
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 19fc4dfc429e..1aaf260aa9b8 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -947,7 +947,7 @@ dss_debugfs_create_file(struct dss_device *dss, const char *name,
&dss_debug_fops);
if (IS_ERR(d)) {
kfree(entry);
- return ERR_PTR(PTR_ERR(d));
+ return ERR_CAST(d);
}
entry->dentry = d;
diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c
index 98f5ca29444a..b81302c4bf9e 100644
--- a/drivers/gpu/drm/omapdrm/omap_connector.c
+++ b/drivers/gpu/drm/omapdrm/omap_connector.c
@@ -164,10 +164,11 @@ static void omap_connector_destroy(struct drm_connector *connector)
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
- kfree(omap_connector);
omapdss_device_put(omap_connector->output);
omapdss_device_put(omap_connector->display);
+
+ kfree(omap_connector);
}
#define MAX_EDID 512
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_priv.h b/drivers/gpu/drm/omapdrm/omap_dmm_priv.h
index c2785cc98dc9..60bb3f9297bc 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_priv.h
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_priv.h
@@ -159,6 +159,7 @@ struct dmm_platform_data {
struct dmm {
struct device *dev;
+ dma_addr_t phys_base;
void __iomem *base;
int irq;
@@ -189,6 +190,12 @@ struct dmm {
struct list_head alloc_head;
const struct dmm_platform_data *plat_data;
+
+ bool dmm_workaround;
+ spinlock_t wa_lock;
+ u32 *wa_dma_data;
+ dma_addr_t wa_dma_handle;
+ struct dma_chan *wa_dma_chan;
};
#endif
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index f92fe205550b..252f5ebb1acc 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -18,6 +18,7 @@
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -79,14 +80,138 @@ static const u32 reg[][4] = {
DMM_PAT_DESCR__2, DMM_PAT_DESCR__3},
};
+static int dmm_dma_copy(struct dmm *dmm, dma_addr_t src, dma_addr_t dst)
+{
+ struct dma_device *dma_dev = dmm->wa_dma_chan->device;
+ struct dma_async_tx_descriptor *tx;
+ enum dma_status status;
+ dma_cookie_t cookie;
+
+ tx = dma_dev->device_prep_dma_memcpy(dmm->wa_dma_chan, dst, src, 4, 0);
+ if (!tx) {
+ dev_err(dmm->dev, "Failed to prepare DMA memcpy\n");
+ return -EIO;
+ }
+
+ cookie = tx->tx_submit(tx);
+ if (dma_submit_error(cookie)) {
+ dev_err(dmm->dev, "Failed to do DMA tx_submit\n");
+ return -EIO;
+ }
+
+ dma_async_issue_pending(dmm->wa_dma_chan);
+ status = dma_sync_wait(dmm->wa_dma_chan, cookie);
+ if (status != DMA_COMPLETE)
+ dev_err(dmm->dev, "i878 wa DMA copy failure\n");
+
+ dmaengine_terminate_all(dmm->wa_dma_chan);
+ return 0;
+}
+
+static u32 dmm_read_wa(struct dmm *dmm, u32 reg)
+{
+ dma_addr_t src, dst;
+ int r;
+
+ src = dmm->phys_base + reg;
+ dst = dmm->wa_dma_handle;
+
+ r = dmm_dma_copy(dmm, src, dst);
+ if (r) {
+ dev_err(dmm->dev, "sDMA read transfer timeout\n");
+ return readl(dmm->base + reg);
+ }
+
+ /*
+ * As per i878 workaround, the DMA is used to access the DMM registers.
+ * Make sure that the readl is not moved by the compiler or the CPU
+ * earlier than the DMA finished writing the value to memory.
+ */
+ rmb();
+ return readl(dmm->wa_dma_data);
+}
+
+static void dmm_write_wa(struct dmm *dmm, u32 val, u32 reg)
+{
+ dma_addr_t src, dst;
+ int r;
+
+ writel(val, dmm->wa_dma_data);
+ /*
+ * As per i878 workaround, the DMA is used to access the DMM registers.
+ * Make sure that the writel is not moved by the compiler or the CPU, so
+ * the data will be in place before we start the DMA to do the actual
+ * register write.
+ */
+ wmb();
+
+ src = dmm->wa_dma_handle;
+ dst = dmm->phys_base + reg;
+
+ r = dmm_dma_copy(dmm, src, dst);
+ if (r) {
+ dev_err(dmm->dev, "sDMA write transfer timeout\n");
+ writel(val, dmm->base + reg);
+ }
+}
+
static u32 dmm_read(struct dmm *dmm, u32 reg)
{
- return readl(dmm->base + reg);
+ if (dmm->dmm_workaround) {
+ u32 v;
+ unsigned long flags;
+
+ spin_lock_irqsave(&dmm->wa_lock, flags);
+ v = dmm_read_wa(dmm, reg);
+ spin_unlock_irqrestore(&dmm->wa_lock, flags);
+
+ return v;
+ } else {
+ return readl(dmm->base + reg);
+ }
}
static void dmm_write(struct dmm *dmm, u32 val, u32 reg)
{
- writel(val, dmm->base + reg);
+ if (dmm->dmm_workaround) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&dmm->wa_lock, flags);
+ dmm_write_wa(dmm, val, reg);
+ spin_unlock_irqrestore(&dmm->wa_lock, flags);
+ } else {
+ writel(val, dmm->base + reg);
+ }
+}
+
+static int dmm_workaround_init(struct dmm *dmm)
+{
+ dma_cap_mask_t mask;
+
+ spin_lock_init(&dmm->wa_lock);
+
+ dmm->wa_dma_data = dma_alloc_coherent(dmm->dev, sizeof(u32),
+ &dmm->wa_dma_handle, GFP_KERNEL);
+ if (!dmm->wa_dma_data)
+ return -ENOMEM;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_MEMCPY, mask);
+
+ dmm->wa_dma_chan = dma_request_channel(mask, NULL, NULL);
+ if (!dmm->wa_dma_chan) {
+ dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void dmm_workaround_uninit(struct dmm *dmm)
+{
+ dma_release_channel(dmm->wa_dma_chan);
+
+ dma_free_coherent(dmm->dev, 4, dmm->wa_dma_data, dmm->wa_dma_handle);
}
/* simple allocator to grab next 16 byte aligned memory from txn */
@@ -285,6 +410,17 @@ static int dmm_txn_commit(struct dmm_txn *txn, bool wait)
}
txn->last_pat->next_pa = 0;
+ /* ensure that the written descriptors are visible to DMM */
+ wmb();
+
+ /*
+ * NOTE: the wmb() above should be enough, but there seems to be a bug
+ * in OMAP's memory barrier implementation, which in some rare cases may
+ * cause the writes not to be observable after wmb().
+ */
+
+ /* read back to ensure the data is in RAM */
+ readl(&txn->last_pat->next_pa);
/* write to PAT_DESCR to clear out any pending transaction */
dmm_write(dmm, 0x0, reg[PAT_DESCR][engine->id]);
@@ -603,6 +739,10 @@ static int omap_dmm_remove(struct platform_device *dev)
unsigned long flags;
if (omap_dmm) {
+ /* Disable all enabled interrupts */
+ dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_CLR);
+ free_irq(omap_dmm->irq, omap_dmm);
+
/* free all area regions */
spin_lock_irqsave(&list_lock, flags);
list_for_each_entry_safe(block, _block, &omap_dmm->alloc_head,
@@ -625,8 +765,8 @@ static int omap_dmm_remove(struct platform_device *dev)
if (omap_dmm->dummy_page)
__free_page(omap_dmm->dummy_page);
- if (omap_dmm->irq > 0)
- free_irq(omap_dmm->irq, omap_dmm);
+ if (omap_dmm->dmm_workaround)
+ dmm_workaround_uninit(omap_dmm);
iounmap(omap_dmm->base);
kfree(omap_dmm);
@@ -673,6 +813,7 @@ static int omap_dmm_probe(struct platform_device *dev)
goto fail;
}
+ omap_dmm->phys_base = mem->start;
omap_dmm->base = ioremap(mem->start, SZ_2K);
if (!omap_dmm->base) {
@@ -688,6 +829,22 @@ static int omap_dmm_probe(struct platform_device *dev)
omap_dmm->dev = &dev->dev;
+ if (of_machine_is_compatible("ti,dra7")) {
+ /*
+ * DRA7 Errata i878 says that MPU should not be used to access
+ * RAM and DMM at the same time. As it's not possible to prevent
+ * MPU accessing RAM, we need to access DMM via a proxy.
+ */
+ if (!dmm_workaround_init(omap_dmm)) {
+ omap_dmm->dmm_workaround = true;
+ dev_info(&dev->dev,
+ "workaround for errata i878 in use\n");
+ } else {
+ dev_warn(&dev->dev,
+ "failed to initialize work-around for i878\n");
+ }
+ }
+
hwinfo = dmm_read(omap_dmm, DMM_PAT_HWINFO);
omap_dmm->num_engines = (hwinfo >> 24) & 0x1F;
omap_dmm->num_lut = (hwinfo >> 16) & 0x1F;
@@ -714,24 +871,6 @@ static int omap_dmm_probe(struct platform_device *dev)
dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__0);
dmm_write(omap_dmm, 0x88888888, DMM_TILER_OR__1);
- ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
- "omap_dmm_irq_handler", omap_dmm);
-
- if (ret) {
- dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
- omap_dmm->irq, ret);
- omap_dmm->irq = -1;
- goto fail;
- }
-
- /* Enable all interrupts for each refill engine except
- * ERR_LUT_MISS<n> (which is just advisory, and we don't care
- * about because we want to be able to refill live scanout
- * buffers for accelerated pan/scroll) and FILL_DSC<n> which
- * we just generally don't care about.
- */
- dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_SET);
-
omap_dmm->dummy_page = alloc_page(GFP_KERNEL | __GFP_DMA32);
if (!omap_dmm->dummy_page) {
dev_err(&dev->dev, "could not allocate dummy page\n");
@@ -823,6 +962,24 @@ static int omap_dmm_probe(struct platform_device *dev)
.p1.y = omap_dmm->container_height - 1,
};
+ ret = request_irq(omap_dmm->irq, omap_dmm_irq_handler, IRQF_SHARED,
+ "omap_dmm_irq_handler", omap_dmm);
+
+ if (ret) {
+ dev_err(&dev->dev, "couldn't register IRQ %d, error %d\n",
+ omap_dmm->irq, ret);
+ omap_dmm->irq = -1;
+ goto fail;
+ }
+
+ /* Enable all interrupts for each refill engine except
+ * ERR_LUT_MISS<n> (which is just advisory, and we don't care
+ * about because we want to be able to refill live scanout
+ * buffers for accelerated pan/scroll) and FILL_DSC<n> which
+ * we just generally don't care about.
+ */
+ dmm_write(omap_dmm, 0x7e7e7e7e, DMM_PAT_IRQENABLE_SET);
+
/* initialize all LUTs to dummy page entries */
for (i = 0; i < omap_dmm->num_lut; i++) {
area.tcm = omap_dmm->tcm[i];
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 5f98506ac2c5..5e67d58cbc28 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -439,7 +439,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data,
args->size = omap_gem_mmap_size(obj);
args->offset = omap_gem_mmap_offset(obj);
- drm_gem_object_unreference_unlocked(obj);
+ drm_gem_object_put_unlocked(obj);
return ret;
}
@@ -614,7 +614,7 @@ err_gem_deinit:
omap_disconnect_pipelines(ddev);
err_crtc_uninit:
omap_crtc_pre_uninit(priv);
- drm_dev_unref(ddev);
+ drm_dev_put(ddev);
return ret;
}
@@ -643,7 +643,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
omap_disconnect_pipelines(ddev);
omap_crtc_pre_uninit(priv);
- drm_dev_unref(ddev);
+ drm_dev_put(ddev);
}
static int pdev_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 9f1e3d8f8488..4d264fd554d8 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -319,7 +319,7 @@ struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
error:
while (--i >= 0)
- drm_gem_object_unreference_unlocked(bos[i]);
+ drm_gem_object_put_unlocked(bos[i]);
return fb;
}
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index b445309b0143..aee99194499f 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -150,7 +150,7 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
/* note: if fb creation failed, we can't rely on fb destroy
* to unref the bo:
*/
- drm_gem_object_unreference_unlocked(fbdev->bo);
+ drm_gem_object_put_unlocked(fbdev->bo);
ret = PTR_ERR(fb);
goto fail;
}
diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c
index 4ba5d035c590..8dcaf9f4aa75 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem.c
@@ -638,7 +638,7 @@ int omap_gem_dumb_map_offset(struct drm_file *file, struct drm_device *dev,
*offset = omap_gem_mmap_offset(obj);
- drm_gem_object_unreference_unlocked(obj);
+ drm_gem_object_put_unlocked(obj);
fail:
return ret;
@@ -1312,7 +1312,7 @@ int omap_gem_new_handle(struct drm_device *dev, struct drm_file *file,
}
/* drop reference from allocate - handle holds it now */
- drm_gem_object_unreference_unlocked(obj);
+ drm_gem_object_put_unlocked(obj);
return 0;
}
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index ec04a69ade46..0f8b597ccd10 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -168,7 +168,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
* Importing dmabuf exported from out own gem increases
* refcount on gem itself instead of f_count of dmabuf.
*/
- drm_gem_object_reference(obj);
+ drm_gem_object_get(obj);
return obj;
}
}
diff --git a/drivers/gpu/drm/omapdrm/tcm-sita.h b/drivers/gpu/drm/omapdrm/tcm-sita.h
deleted file mode 100644
index 460e63dbf825..000000000000
--- a/drivers/gpu/drm/omapdrm/tcm-sita.h
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * SImple Tiler Allocator (SiTA) private structures.
- *
- * Copyright (C) 2009-2011 Texas Instruments Incorporated - http://www.ti.com/
- * Author: Ravi Ramachandra <r.ramachandra@ti.com>
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * * Neither the name of Texas Instruments Incorporated nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _TCM_SITA_H
-#define _TCM_SITA_H
-
-#include "tcm.h"
-
-/* length between two coordinates */
-#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
-
-enum criteria {
- CR_MAX_NEIGHS = 0x01,
- CR_FIRST_FOUND = 0x10,
- CR_BIAS_HORIZONTAL = 0x20,
- CR_BIAS_VERTICAL = 0x40,
- CR_DIAGONAL_BALANCE = 0x80
-};
-
-/* nearness to the beginning of the search field from 0 to 1000 */
-struct nearness_factor {
- s32 x;
- s32 y;
-};
-
-/*
- * Statistics on immediately neighboring slots. Edge is the number of
- * border segments that are also border segments of the scan field. Busy
- * refers to the number of neighbors that are occupied.
- */
-struct neighbor_stats {
- u16 edge;
- u16 busy;
-};
-
-/* structure to keep the score of a potential allocation */
-struct score {
- struct nearness_factor f;
- struct neighbor_stats n;
- struct tcm_area a;
- u16 neighs; /* number of busy neighbors */
-};
-
-struct sita_pvt {
- spinlock_t lock; /* spinlock to protect access */
- struct tcm_pt div_pt; /* divider point splitting container */
- struct tcm_area ***map; /* pointers to the parent area for each slot */
-};
-
-/* assign coordinates to area */
-static inline
-void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
-{
- a->p0.x = x0;
- a->p0.y = y0;
- a->p1.x = x1;
- a->p1.y = y1;
-}
-
-#endif
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c
index 54324330b91f..f471537c852f 100644
--- a/drivers/gpu/drm/radeon/evergreen_cs.c
+++ b/drivers/gpu/drm/radeon/evergreen_cs.c
@@ -2416,7 +2416,7 @@ static int evergreen_packet3_check(struct radeon_cs_parser *p,
size = radeon_get_ib_value(p, idx+1+(i*8)+1);
if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
/* force size to size of the buffer */
- dev_warn(p->dev, "vbo resource seems too big for the bo\n");
+ dev_warn_ratelimited(p->dev, "vbo resource seems too big for the bo\n");
ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset;
}
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 4e5e95c0cab5..3e22a54a99c2 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -467,8 +467,7 @@ void drm_sched_entity_select_rq(struct drm_sched_entity *entity)
struct dma_fence *fence;
struct drm_sched_rq *rq;
- if (!spsc_queue_count(&entity->job_queue) == 0 ||
- entity->num_rq_list <= 1)
+ if (spsc_queue_count(&entity->job_queue) || entity->num_rq_list <= 1)
return;
fence = READ_ONCE(entity->last_scheduled);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 0fb300d41a09..33e533268488 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -554,29 +554,23 @@ static struct drm_driver tilcdc_driver = {
static int tilcdc_pm_suspend(struct device *dev)
{
struct drm_device *ddev = dev_get_drvdata(dev);
- struct tilcdc_drm_private *priv = ddev->dev_private;
+ int ret = 0;
- priv->saved_state = drm_atomic_helper_suspend(ddev);
+ ret = drm_mode_config_helper_suspend(ddev);
/* Select sleep pin state */
pinctrl_pm_select_sleep_state(dev);
- return 0;
+ return ret;
}
static int tilcdc_pm_resume(struct device *dev)
{
struct drm_device *ddev = dev_get_drvdata(dev);
- struct tilcdc_drm_private *priv = ddev->dev_private;
- int ret = 0;
/* Select default pin state */
pinctrl_pm_select_default_state(dev);
-
- if (priv->saved_state)
- ret = drm_atomic_helper_resume(ddev, priv->saved_state);
-
- return ret;
+ return drm_mode_config_helper_resume(ddev);
}
#endif
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
index ead512216669..62cea5ff5558 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h
@@ -70,9 +70,6 @@ struct tilcdc_drm_private {
const uint32_t *pixelformats;
uint32_t num_pixelformats;
- /* The context for pm susped/resume cycle is stored here */
- struct drm_atomic_state *saved_state;
-
#ifdef CONFIG_CPU_FREQ
struct notifier_block freq_transition;
#endif
diff --git a/drivers/gpu/drm/ttm/Makefile b/drivers/gpu/drm/ttm/Makefile
index a60e560804e0..01fc670ce7a2 100644
--- a/drivers/gpu/drm/ttm/Makefile
+++ b/drivers/gpu/drm/ttm/Makefile
@@ -4,8 +4,8 @@
ttm-y := ttm_memory.o ttm_tt.o ttm_bo.o \
ttm_bo_util.o ttm_bo_vm.o ttm_module.o \
- ttm_object.o ttm_lock.o ttm_execbuf_util.o ttm_page_alloc.o \
- ttm_bo_manager.o ttm_page_alloc_dma.o
+ ttm_execbuf_util.o ttm_page_alloc.o ttm_bo_manager.o \
+ ttm_page_alloc_dma.o
ttm-$(CONFIG_AGP) += ttm_agp_backend.o
obj-$(CONFIG_DRM_TTM) += ttm.o
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index b2a33bf1ef10..26b889f86670 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -247,20 +247,6 @@ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo,
}
EXPORT_SYMBOL(ttm_bo_move_to_lru_tail);
-static void ttm_list_move_bulk_tail(struct list_head *list,
- struct list_head *first,
- struct list_head *last)
-{
- first->prev->next = last->next;
- last->next->prev = first->prev;
-
- list->prev->next = first;
- first->prev = list->prev;
-
- last->next = list;
- list->prev = last;
-}
-
void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
{
unsigned i;
@@ -276,8 +262,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
reservation_object_assert_held(pos->last->resv);
man = &pos->first->bdev->man[TTM_PL_TT];
- ttm_list_move_bulk_tail(&man->lru[i], &pos->first->lru,
- &pos->last->lru);
+ list_bulk_move_tail(&man->lru[i], &pos->first->lru,
+ &pos->last->lru);
}
for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
@@ -291,8 +277,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
reservation_object_assert_held(pos->last->resv);
man = &pos->first->bdev->man[TTM_PL_VRAM];
- ttm_list_move_bulk_tail(&man->lru[i], &pos->first->lru,
- &pos->last->lru);
+ list_bulk_move_tail(&man->lru[i], &pos->first->lru,
+ &pos->last->lru);
}
for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) {
@@ -306,8 +292,7 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk)
reservation_object_assert_held(pos->last->resv);
lru = &pos->first->bdev->glob->swap_lru[i];
- ttm_list_move_bulk_tail(lru, &pos->first->swap,
- &pos->last->swap);
+ list_bulk_move_tail(lru, &pos->first->swap, &pos->last->swap);
}
}
EXPORT_SYMBOL(ttm_bo_bulk_move_lru_tail);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 6fe91c1b692d..a1d977fbade5 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -409,8 +409,7 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_bo_device *bdev,
node = drm_vma_offset_lookup_locked(&bdev->vma_manager, offset, pages);
if (likely(node)) {
bo = container_of(node, struct ttm_buffer_object, vma_node);
- if (!kref_get_unless_zero(&bo->kref))
- bo = NULL;
+ bo = ttm_bo_get_unless_zero(bo);
}
drm_vma_offset_unlock_lookup(&bdev->vma_manager);
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index 09b2aa08363e..8841bd30e1e5 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -7,6 +7,8 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \
vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \
vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \
- vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o
+ vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \
+ vmwgfx_validation.o \
+ ttm_object.o ttm_lock.o
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/vmwgfx/ttm_lock.c
index 20694b8a01ca..16b2083cb9d4 100644
--- a/drivers/gpu/drm/ttm/ttm_lock.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_lock.c
@@ -29,13 +29,13 @@
* Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
*/
-#include <drm/ttm/ttm_lock.h>
#include <drm/ttm/ttm_module.h>
#include <linux/atomic.h>
#include <linux/errno.h>
#include <linux/wait.h>
#include <linux/sched/signal.h>
-#include <linux/module.h>
+#include "ttm_lock.h"
+#include "ttm_object.h"
#define TTM_WRITE_LOCK_PENDING (1 << 0)
#define TTM_VT_LOCK_PENDING (1 << 1)
@@ -52,7 +52,6 @@ void ttm_lock_init(struct ttm_lock *lock)
lock->kill_takers = false;
lock->signal = SIGKILL;
}
-EXPORT_SYMBOL(ttm_lock_init);
void ttm_read_unlock(struct ttm_lock *lock)
{
@@ -61,7 +60,6 @@ void ttm_read_unlock(struct ttm_lock *lock)
wake_up_all(&lock->queue);
spin_unlock(&lock->lock);
}
-EXPORT_SYMBOL(ttm_read_unlock);
static bool __ttm_read_lock(struct ttm_lock *lock)
{
@@ -92,7 +90,6 @@ int ttm_read_lock(struct ttm_lock *lock, bool interruptible)
wait_event(lock->queue, __ttm_read_lock(lock));
return ret;
}
-EXPORT_SYMBOL(ttm_read_lock);
static bool __ttm_read_trylock(struct ttm_lock *lock, bool *locked)
{
@@ -144,7 +141,6 @@ void ttm_write_unlock(struct ttm_lock *lock)
wake_up_all(&lock->queue);
spin_unlock(&lock->lock);
}
-EXPORT_SYMBOL(ttm_write_unlock);
static bool __ttm_write_lock(struct ttm_lock *lock)
{
@@ -185,7 +181,6 @@ int ttm_write_lock(struct ttm_lock *lock, bool interruptible)
return ret;
}
-EXPORT_SYMBOL(ttm_write_lock);
static int __ttm_vt_unlock(struct ttm_lock *lock)
{
@@ -262,14 +257,12 @@ int ttm_vt_lock(struct ttm_lock *lock,
return ret;
}
-EXPORT_SYMBOL(ttm_vt_lock);
int ttm_vt_unlock(struct ttm_lock *lock)
{
return ttm_ref_object_base_unref(lock->vt_holder,
- lock->base.hash.key, TTM_REF_USAGE);
+ lock->base.handle, TTM_REF_USAGE);
}
-EXPORT_SYMBOL(ttm_vt_unlock);
void ttm_suspend_unlock(struct ttm_lock *lock)
{
@@ -278,7 +271,6 @@ void ttm_suspend_unlock(struct ttm_lock *lock)
wake_up_all(&lock->queue);
spin_unlock(&lock->lock);
}
-EXPORT_SYMBOL(ttm_suspend_unlock);
static bool __ttm_suspend_lock(struct ttm_lock *lock)
{
@@ -300,4 +292,3 @@ void ttm_suspend_lock(struct ttm_lock *lock)
{
wait_event(lock->queue, __ttm_suspend_lock(lock));
}
-EXPORT_SYMBOL(ttm_suspend_lock);
diff --git a/drivers/gpu/drm/vmwgfx/ttm_lock.h b/drivers/gpu/drm/vmwgfx/ttm_lock.h
new file mode 100644
index 000000000000..0c3af9836863
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/ttm_lock.h
@@ -0,0 +1,248 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2007-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+
+/** @file ttm_lock.h
+ * This file implements a simple replacement for the buffer manager use
+ * of the DRM heavyweight hardware lock.
+ * The lock is a read-write lock. Taking it in read mode and write mode
+ * is relatively fast, and intended for in-kernel use only.
+ *
+ * The vt mode is used only when there is a need to block all
+ * user-space processes from validating buffers.
+ * It's allowed to leave kernel space with the vt lock held.
+ * If a user-space process dies while having the vt-lock,
+ * it will be released during the file descriptor release. The vt lock
+ * excludes write lock and read lock.
+ *
+ * The suspend mode is used to lock out all TTM users when preparing for
+ * and executing suspend operations.
+ *
+ */
+
+#ifndef _TTM_LOCK_H_
+#define _TTM_LOCK_H_
+
+#include <linux/wait.h>
+#include <linux/atomic.h>
+
+#include "ttm_object.h"
+
+/**
+ * struct ttm_lock
+ *
+ * @base: ttm base object used solely to release the lock if the client
+ * holding the lock dies.
+ * @queue: Queue for processes waiting for lock change-of-status.
+ * @lock: Spinlock protecting some lock members.
+ * @rw: Read-write lock counter. Protected by @lock.
+ * @flags: Lock state. Protected by @lock.
+ * @kill_takers: Boolean whether to kill takers of the lock.
+ * @signal: Signal to send when kill_takers is true.
+ */
+
+struct ttm_lock {
+ struct ttm_base_object base;
+ wait_queue_head_t queue;
+ spinlock_t lock;
+ int32_t rw;
+ uint32_t flags;
+ bool kill_takers;
+ int signal;
+ struct ttm_object_file *vt_holder;
+};
+
+
+/**
+ * ttm_lock_init
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * Initializes the lock.
+ */
+extern void ttm_lock_init(struct ttm_lock *lock);
+
+/**
+ * ttm_read_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a read lock.
+ */
+extern void ttm_read_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_read_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Takes the lock in read mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_read_lock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_read_trylock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Tries to take the lock in read mode. If the lock is already held
+ * in write mode, the function will return -EBUSY. If the lock is held
+ * in vt or suspend mode, the function will sleep until these modes
+ * are unlocked.
+ *
+ * Returns:
+ * -EBUSY The lock was already held in write mode.
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_read_trylock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_write_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a write lock.
+ */
+extern void ttm_write_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_write_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Takes the lock in write mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_lock_downgrade
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Downgrades a write lock to a read lock.
+ */
+extern void ttm_lock_downgrade(struct ttm_lock *lock);
+
+/**
+ * ttm_suspend_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Takes the lock in suspend mode. Excludes read and write mode.
+ */
+extern void ttm_suspend_lock(struct ttm_lock *lock);
+
+/**
+ * ttm_suspend_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a suspend lock
+ */
+extern void ttm_suspend_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_vt_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ * @tfile: Pointer to a struct ttm_object_file to register the lock with.
+ *
+ * Takes the lock in vt mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ * -ENOMEM: Out of memory when locking.
+ */
+extern int ttm_vt_lock(struct ttm_lock *lock, bool interruptible,
+ struct ttm_object_file *tfile);
+
+/**
+ * ttm_vt_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a vt lock.
+ * Returns:
+ * -EINVAL If the lock was not held.
+ */
+extern int ttm_vt_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_write_unlock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ *
+ * Releases a write lock.
+ */
+extern void ttm_write_unlock(struct ttm_lock *lock);
+
+/**
+ * ttm_write_lock
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @interruptible: Interruptible sleeping while waiting for a lock.
+ *
+ * Takes the lock in write mode.
+ * Returns:
+ * -ERESTARTSYS If interrupted by a signal and interruptible is true.
+ */
+extern int ttm_write_lock(struct ttm_lock *lock, bool interruptible);
+
+/**
+ * ttm_lock_set_kill
+ *
+ * @lock: Pointer to a struct ttm_lock
+ * @val: Boolean whether to kill processes taking the lock.
+ * @signal: Signal to send to the process taking the lock.
+ *
+ * The kill-when-taking-lock functionality is used to kill processes that keep
+ * on using the TTM functionality when its resources has been taken down, for
+ * example when the X server exits. A typical sequence would look like this:
+ * - X server takes lock in write mode.
+ * - ttm_lock_set_kill() is called with @val set to true.
+ * - As part of X server exit, TTM resources are taken down.
+ * - X server releases the lock on file release.
+ * - Another dri client wants to render, takes the lock and is killed.
+ *
+ */
+static inline void ttm_lock_set_kill(struct ttm_lock *lock, bool val,
+ int signal)
+{
+ lock->kill_takers = val;
+ if (val)
+ lock->signal = signal;
+}
+
+#endif
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
index 74f1b1eb1f8e..36990b80e790 100644
--- a/drivers/gpu/drm/ttm/ttm_object.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
@@ -59,13 +59,12 @@
#define pr_fmt(fmt) "[TTM] " fmt
-#include <drm/ttm/ttm_object.h>
#include <drm/ttm/ttm_module.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
-#include <linux/module.h>
#include <linux/atomic.h>
+#include "ttm_object.h"
struct ttm_object_file {
struct ttm_object_device *tdev;
@@ -95,6 +94,7 @@ struct ttm_object_device {
struct dma_buf_ops ops;
void (*dmabuf_release)(struct dma_buf *dma_buf);
size_t dma_buf_size;
+ struct idr idr;
};
/**
@@ -172,14 +172,15 @@ int ttm_base_object_init(struct ttm_object_file *tfile,
base->ref_obj_release = ref_obj_release;
base->object_type = object_type;
kref_init(&base->refcount);
+ idr_preload(GFP_KERNEL);
spin_lock(&tdev->object_lock);
- ret = drm_ht_just_insert_please_rcu(&tdev->object_hash,
- &base->hash,
- (unsigned long)base, 31, 0, 0);
+ ret = idr_alloc(&tdev->idr, base, 0, 0, GFP_NOWAIT);
spin_unlock(&tdev->object_lock);
- if (unlikely(ret != 0))
- goto out_err0;
+ idr_preload_end();
+ if (ret < 0)
+ return ret;
+ base->handle = ret;
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
if (unlikely(ret != 0))
goto out_err1;
@@ -189,12 +190,10 @@ int ttm_base_object_init(struct ttm_object_file *tfile,
return 0;
out_err1:
spin_lock(&tdev->object_lock);
- (void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
+ idr_remove(&tdev->idr, base->handle);
spin_unlock(&tdev->object_lock);
-out_err0:
return ret;
}
-EXPORT_SYMBOL(ttm_base_object_init);
static void ttm_release_base(struct kref *kref)
{
@@ -203,7 +202,7 @@ static void ttm_release_base(struct kref *kref)
struct ttm_object_device *tdev = base->tfile->tdev;
spin_lock(&tdev->object_lock);
- (void)drm_ht_remove_item_rcu(&tdev->object_hash, &base->hash);
+ idr_remove(&tdev->idr, base->handle);
spin_unlock(&tdev->object_lock);
/*
@@ -225,7 +224,41 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
kref_put(&base->refcount, ttm_release_base);
}
-EXPORT_SYMBOL(ttm_base_object_unref);
+
+/**
+ * ttm_base_object_noref_lookup - look up a base object without reference
+ * @tfile: The struct ttm_object_file the object is registered with.
+ * @key: The object handle.
+ *
+ * This function looks up a ttm base object and returns a pointer to it
+ * without refcounting the pointer. The returned pointer is only valid
+ * until ttm_base_object_noref_release() is called, and the object
+ * pointed to by the returned pointer may be doomed. Any persistent usage
+ * of the object requires a refcount to be taken using kref_get_unless_zero().
+ * Iff this function returns successfully it needs to be paired with
+ * ttm_base_object_noref_release() and no sleeping- or scheduling functions
+ * may be called inbetween these function callse.
+ *
+ * Return: A pointer to the object if successful or NULL otherwise.
+ */
+struct ttm_base_object *
+ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
+{
+ struct drm_hash_item *hash;
+ struct drm_open_hash *ht = &tfile->ref_hash[TTM_REF_USAGE];
+ int ret;
+
+ rcu_read_lock();
+ ret = drm_ht_find_item_rcu(ht, key, &hash);
+ if (ret) {
+ rcu_read_unlock();
+ return NULL;
+ }
+
+ __release(RCU);
+ return drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
+}
+EXPORT_SYMBOL(ttm_base_object_noref_lookup);
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
uint32_t key)
@@ -247,29 +280,21 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
return base;
}
-EXPORT_SYMBOL(ttm_base_object_lookup);
struct ttm_base_object *
ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
{
- struct ttm_base_object *base = NULL;
- struct drm_hash_item *hash;
- struct drm_open_hash *ht = &tdev->object_hash;
- int ret;
+ struct ttm_base_object *base;
rcu_read_lock();
- ret = drm_ht_find_item_rcu(ht, key, &hash);
+ base = idr_find(&tdev->idr, key);
- if (likely(ret == 0)) {
- base = drm_hash_entry(hash, struct ttm_base_object, hash);
- if (!kref_get_unless_zero(&base->refcount))
- base = NULL;
- }
+ if (base && !kref_get_unless_zero(&base->refcount))
+ base = NULL;
rcu_read_unlock();
return base;
}
-EXPORT_SYMBOL(ttm_base_object_lookup_for_ref);
/**
* ttm_ref_object_exists - Check whether a caller has a valid ref object
@@ -289,7 +314,7 @@ bool ttm_ref_object_exists(struct ttm_object_file *tfile,
struct ttm_ref_object *ref;
rcu_read_lock();
- if (unlikely(drm_ht_find_item_rcu(ht, base->hash.key, &hash) != 0))
+ if (unlikely(drm_ht_find_item_rcu(ht, base->handle, &hash) != 0))
goto out_false;
/*
@@ -315,7 +340,6 @@ bool ttm_ref_object_exists(struct ttm_object_file *tfile,
rcu_read_unlock();
return false;
}
-EXPORT_SYMBOL(ttm_ref_object_exists);
int ttm_ref_object_add(struct ttm_object_file *tfile,
struct ttm_base_object *base,
@@ -340,7 +364,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
while (ret == -EINVAL) {
rcu_read_lock();
- ret = drm_ht_find_item_rcu(ht, base->hash.key, &hash);
+ ret = drm_ht_find_item_rcu(ht, base->handle, &hash);
if (ret == 0) {
ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
@@ -364,7 +388,7 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
return -ENOMEM;
}
- ref->hash.key = base->hash.key;
+ ref->hash.key = base->handle;
ref->obj = base;
ref->tfile = tfile;
ref->ref_type = ref_type;
@@ -391,9 +415,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
return ret;
}
-EXPORT_SYMBOL(ttm_ref_object_add);
-static void ttm_ref_object_release(struct kref *kref)
+static void __releases(tfile->lock) __acquires(tfile->lock)
+ttm_ref_object_release(struct kref *kref)
{
struct ttm_ref_object *ref =
container_of(kref, struct ttm_ref_object, kref);
@@ -435,7 +459,6 @@ int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
spin_unlock(&tfile->lock);
return 0;
}
-EXPORT_SYMBOL(ttm_ref_object_base_unref);
void ttm_object_file_release(struct ttm_object_file **p_tfile)
{
@@ -464,7 +487,6 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
ttm_object_file_unref(&tfile);
}
-EXPORT_SYMBOL(ttm_object_file_release);
struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
unsigned int hash_order)
@@ -499,7 +521,6 @@ out_err:
return NULL;
}
-EXPORT_SYMBOL(ttm_object_file_init);
struct ttm_object_device *
ttm_object_device_init(struct ttm_mem_global *mem_glob,
@@ -519,6 +540,7 @@ ttm_object_device_init(struct ttm_mem_global *mem_glob,
if (ret != 0)
goto out_no_object_hash;
+ idr_init(&tdev->idr);
tdev->ops = *ops;
tdev->dmabuf_release = tdev->ops.release;
tdev->ops.release = ttm_prime_dmabuf_release;
@@ -530,7 +552,6 @@ out_no_object_hash:
kfree(tdev);
return NULL;
}
-EXPORT_SYMBOL(ttm_object_device_init);
void ttm_object_device_release(struct ttm_object_device **p_tdev)
{
@@ -538,11 +559,12 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)
*p_tdev = NULL;
+ WARN_ON_ONCE(!idr_is_empty(&tdev->idr));
+ idr_destroy(&tdev->idr);
drm_ht_remove(&tdev->object_hash);
kfree(tdev);
}
-EXPORT_SYMBOL(ttm_object_device_release);
/**
* get_dma_buf_unless_doomed - get a dma_buf reference if possible.
@@ -641,14 +663,13 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
prime = (struct ttm_prime_object *) dma_buf->priv;
base = &prime->base;
- *handle = base->hash.key;
+ *handle = base->handle;
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
dma_buf_put(dma_buf);
return ret;
}
-EXPORT_SYMBOL_GPL(ttm_prime_fd_to_handle);
/**
* ttm_prime_handle_to_fd - Return a dma_buf fd from a ttm prime object
@@ -739,7 +760,6 @@ out_unref:
ttm_base_object_unref(&base);
return ret;
}
-EXPORT_SYMBOL_GPL(ttm_prime_handle_to_fd);
/**
* ttm_prime_object_init - Initialize a ttm_prime_object
@@ -772,4 +792,3 @@ int ttm_prime_object_init(struct ttm_object_file *tfile, size_t size,
ttm_prime_refcount_release,
ref_obj_release);
}
-EXPORT_SYMBOL(ttm_prime_object_init);
diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h
new file mode 100644
index 000000000000..50d26c7ff42d
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.h
@@ -0,0 +1,375 @@
+/**************************************************************************
+ *
+ * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+/*
+ * Authors: Thomas Hellstrom <thellstrom-at-vmware-dot-com>
+ */
+/** @file ttm_object.h
+ *
+ * Base- and reference object implementation for the various
+ * ttm objects. Implements reference counting, minimal security checks
+ * and release on file close.
+ */
+
+#ifndef _TTM_OBJECT_H_
+#define _TTM_OBJECT_H_
+
+#include <linux/list.h>
+#include <drm/drm_hashtab.h>
+#include <linux/kref.h>
+#include <linux/rcupdate.h>
+#include <linux/dma-buf.h>
+#include <drm/ttm/ttm_memory.h>
+
+/**
+ * enum ttm_ref_type
+ *
+ * Describes what type of reference a ref object holds.
+ *
+ * TTM_REF_USAGE is a simple refcount on a base object.
+ *
+ * TTM_REF_SYNCCPU_READ is a SYNCCPU_READ reference on a
+ * buffer object.
+ *
+ * TTM_REF_SYNCCPU_WRITE is a SYNCCPU_WRITE reference on a
+ * buffer object.
+ *
+ */
+
+enum ttm_ref_type {
+ TTM_REF_USAGE,
+ TTM_REF_SYNCCPU_READ,
+ TTM_REF_SYNCCPU_WRITE,
+ TTM_REF_NUM
+};
+
+/**
+ * enum ttm_object_type
+ *
+ * One entry per ttm object type.
+ * Device-specific types should use the
+ * ttm_driver_typex types.
+ */
+
+enum ttm_object_type {
+ ttm_fence_type,
+ ttm_buffer_type,
+ ttm_lock_type,
+ ttm_prime_type,
+ ttm_driver_type0 = 256,
+ ttm_driver_type1,
+ ttm_driver_type2,
+ ttm_driver_type3,
+ ttm_driver_type4,
+ ttm_driver_type5
+};
+
+struct ttm_object_file;
+struct ttm_object_device;
+
+/**
+ * struct ttm_base_object
+ *
+ * @hash: hash entry for the per-device object hash.
+ * @type: derived type this object is base class for.
+ * @shareable: Other ttm_object_files can access this object.
+ *
+ * @tfile: Pointer to ttm_object_file of the creator.
+ * NULL if the object was not created by a user request.
+ * (kernel object).
+ *
+ * @refcount: Number of references to this object, not
+ * including the hash entry. A reference to a base object can
+ * only be held by a ref object.
+ *
+ * @refcount_release: A function to be called when there are
+ * no more references to this object. This function should
+ * destroy the object (or make sure destruction eventually happens),
+ * and when it is called, the object has
+ * already been taken out of the per-device hash. The parameter
+ * "base" should be set to NULL by the function.
+ *
+ * @ref_obj_release: A function to be called when a reference object
+ * with another ttm_ref_type than TTM_REF_USAGE is deleted.
+ * This function may, for example, release a lock held by a user-space
+ * process.
+ *
+ * This struct is intended to be used as a base struct for objects that
+ * are visible to user-space. It provides a global name, race-safe
+ * access and refcounting, minimal access contol and hooks for unref actions.
+ */
+
+struct ttm_base_object {
+ struct rcu_head rhead;
+ struct ttm_object_file *tfile;
+ struct kref refcount;
+ void (*refcount_release) (struct ttm_base_object **base);
+ void (*ref_obj_release) (struct ttm_base_object *base,
+ enum ttm_ref_type ref_type);
+ u32 handle;
+ enum ttm_object_type object_type;
+ u32 shareable;
+};
+
+
+/**
+ * struct ttm_prime_object - Modified base object that is prime-aware
+ *
+ * @base: struct ttm_base_object that we derive from
+ * @mutex: Mutex protecting the @dma_buf member.
+ * @size: Size of the dma_buf associated with this object
+ * @real_type: Type of the underlying object. Needed since we're setting
+ * the value of @base::object_type to ttm_prime_type
+ * @dma_buf: Non ref-coutned pointer to a struct dma_buf created from this
+ * object.
+ * @refcount_release: The underlying object's release method. Needed since
+ * we set @base::refcount_release to our own release method.
+ */
+
+struct ttm_prime_object {
+ struct ttm_base_object base;
+ struct mutex mutex;
+ size_t size;
+ enum ttm_object_type real_type;
+ struct dma_buf *dma_buf;
+ void (*refcount_release) (struct ttm_base_object **);
+};
+
+/**
+ * ttm_base_object_init
+ *
+ * @tfile: Pointer to a struct ttm_object_file.
+ * @base: The struct ttm_base_object to initialize.
+ * @shareable: This object is shareable with other applcations.
+ * (different @tfile pointers.)
+ * @type: The object type.
+ * @refcount_release: See the struct ttm_base_object description.
+ * @ref_obj_release: See the struct ttm_base_object description.
+ *
+ * Initializes a struct ttm_base_object.
+ */
+
+extern int ttm_base_object_init(struct ttm_object_file *tfile,
+ struct ttm_base_object *base,
+ bool shareable,
+ enum ttm_object_type type,
+ void (*refcount_release) (struct ttm_base_object
+ **),
+ void (*ref_obj_release) (struct ttm_base_object
+ *,
+ enum ttm_ref_type
+ ref_type));
+
+/**
+ * ttm_base_object_lookup
+ *
+ * @tfile: Pointer to a struct ttm_object_file.
+ * @key: Hash key
+ *
+ * Looks up a struct ttm_base_object with the key @key.
+ */
+
+extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
+ *tfile, uint32_t key);
+
+/**
+ * ttm_base_object_lookup_for_ref
+ *
+ * @tdev: Pointer to a struct ttm_object_device.
+ * @key: Hash key
+ *
+ * Looks up a struct ttm_base_object with the key @key.
+ * This function should only be used when the struct tfile associated with the
+ * caller doesn't yet have a reference to the base object.
+ */
+
+extern struct ttm_base_object *
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
+
+/**
+ * ttm_base_object_unref
+ *
+ * @p_base: Pointer to a pointer referencing a struct ttm_base_object.
+ *
+ * Decrements the base object refcount and clears the pointer pointed to by
+ * p_base.
+ */
+
+extern void ttm_base_object_unref(struct ttm_base_object **p_base);
+
+/**
+ * ttm_ref_object_add.
+ *
+ * @tfile: A struct ttm_object_file representing the application owning the
+ * ref_object.
+ * @base: The base object to reference.
+ * @ref_type: The type of reference.
+ * @existed: Upon completion, indicates that an identical reference object
+ * already existed, and the refcount was upped on that object instead.
+ * @require_existed: Fail with -EPERM if an identical ref object didn't
+ * already exist.
+ *
+ * Checks that the base object is shareable and adds a ref object to it.
+ *
+ * Adding a ref object to a base object is basically like referencing the
+ * base object, but a user-space application holds the reference. When the
+ * file corresponding to @tfile is closed, all its reference objects are
+ * deleted. A reference object can have different types depending on what
+ * it's intended for. It can be refcounting to prevent object destruction,
+ * When user-space takes a lock, it can add a ref object to that lock to
+ * make sure the lock is released if the application dies. A ref object
+ * will hold a single reference on a base object.
+ */
+extern int ttm_ref_object_add(struct ttm_object_file *tfile,
+ struct ttm_base_object *base,
+ enum ttm_ref_type ref_type, bool *existed,
+ bool require_existed);
+
+extern bool ttm_ref_object_exists(struct ttm_object_file *tfile,
+ struct ttm_base_object *base);
+
+/**
+ * ttm_ref_object_base_unref
+ *
+ * @key: Key representing the base object.
+ * @ref_type: Ref type of the ref object to be dereferenced.
+ *
+ * Unreference a ref object with type @ref_type
+ * on the base object identified by @key. If there are no duplicate
+ * references, the ref object will be destroyed and the base object
+ * will be unreferenced.
+ */
+extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
+ unsigned long key,
+ enum ttm_ref_type ref_type);
+
+/**
+ * ttm_object_file_init - initialize a struct ttm_object file
+ *
+ * @tdev: A struct ttm_object device this file is initialized on.
+ * @hash_order: Order of the hash table used to hold the reference objects.
+ *
+ * This is typically called by the file_ops::open function.
+ */
+
+extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device
+ *tdev,
+ unsigned int hash_order);
+
+/**
+ * ttm_object_file_release - release data held by a ttm_object_file
+ *
+ * @p_tfile: Pointer to pointer to the ttm_object_file object to release.
+ * *p_tfile will be set to NULL by this function.
+ *
+ * Releases all data associated by a ttm_object_file.
+ * Typically called from file_ops::release. The caller must
+ * ensure that there are no concurrent users of tfile.
+ */
+
+extern void ttm_object_file_release(struct ttm_object_file **p_tfile);
+
+/**
+ * ttm_object device init - initialize a struct ttm_object_device
+ *
+ * @mem_glob: struct ttm_mem_global for memory accounting.
+ * @hash_order: Order of hash table used to hash the base objects.
+ * @ops: DMA buf ops for prime objects of this device.
+ *
+ * This function is typically called on device initialization to prepare
+ * data structures needed for ttm base and ref objects.
+ */
+
+extern struct ttm_object_device *
+ttm_object_device_init(struct ttm_mem_global *mem_glob,
+ unsigned int hash_order,
+ const struct dma_buf_ops *ops);
+
+/**
+ * ttm_object_device_release - release data held by a ttm_object_device
+ *
+ * @p_tdev: Pointer to pointer to the ttm_object_device object to release.
+ * *p_tdev will be set to NULL by this function.
+ *
+ * Releases all data associated by a ttm_object_device.
+ * Typically called from driver::unload before the destruction of the
+ * device private data structure.
+ */
+
+extern void ttm_object_device_release(struct ttm_object_device **p_tdev);
+
+#define ttm_base_object_kfree(__object, __base)\
+ kfree_rcu(__object, __base.rhead)
+
+extern int ttm_prime_object_init(struct ttm_object_file *tfile,
+ size_t size,
+ struct ttm_prime_object *prime,
+ bool shareable,
+ enum ttm_object_type type,
+ void (*refcount_release)
+ (struct ttm_base_object **),
+ void (*ref_obj_release)
+ (struct ttm_base_object *,
+ enum ttm_ref_type ref_type));
+
+static inline enum ttm_object_type
+ttm_base_object_type(struct ttm_base_object *base)
+{
+ return (base->object_type == ttm_prime_type) ?
+ container_of(base, struct ttm_prime_object, base)->real_type :
+ base->object_type;
+}
+extern int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
+ int fd, u32 *handle);
+extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
+ uint32_t handle, uint32_t flags,
+ int *prime_fd);
+
+#define ttm_prime_object_kfree(__obj, __prime) \
+ kfree_rcu(__obj, __prime.base.rhead)
+
+/*
+ * Extra memory required by the base object's idr storage, which is allocated
+ * separately from the base object itself. We estimate an on-average 128 bytes
+ * per idr.
+ */
+#define TTM_OBJ_EXTRA_SIZE 128
+
+struct ttm_base_object *
+ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key);
+
+/**
+ * ttm_base_object_noref_release - release a base object pointer looked up
+ * without reference
+ *
+ * Releases a base object pointer looked up with ttm_base_object_noref_lookup().
+ */
+static inline void ttm_base_object_noref_release(void)
+{
+ __acquire(RCU);
+ rcu_read_unlock();
+}
+#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index 2dda03345761..7ce1c2f87d9a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -30,7 +30,7 @@
#include <drm/drmP.h>
#include "vmwgfx_drv.h"
-#include "drm/ttm/ttm_object.h"
+#include "ttm_object.h"
/**
@@ -441,7 +441,8 @@ static size_t vmw_bo_acc_size(struct vmw_private *dev_priv, size_t size,
struct_size = backend_size +
ttm_round_pot(sizeof(struct vmw_buffer_object));
user_struct_size = backend_size +
- ttm_round_pot(sizeof(struct vmw_user_buffer_object));
+ ttm_round_pot(sizeof(struct vmw_user_buffer_object)) +
+ TTM_OBJ_EXTRA_SIZE;
}
if (dev_priv->map_mode == vmw_dma_alloc_coherent)
@@ -631,7 +632,7 @@ int vmw_user_bo_alloc(struct vmw_private *dev_priv,
*p_base = &user_bo->prime.base;
kref_get(&(*p_base)->refcount);
}
- *handle = user_bo->prime.base.hash.key;
+ *handle = user_bo->prime.base.handle;
out_no_base_object:
return ret;
@@ -920,6 +921,47 @@ int vmw_user_bo_lookup(struct ttm_object_file *tfile,
return 0;
}
+/**
+ * vmw_user_bo_noref_lookup - Look up a vmw user buffer object without reference
+ * @tfile: The TTM object file the handle is registered with.
+ * @handle: The user buffer object handle.
+ *
+ * This function looks up a struct vmw_user_bo and returns a pointer to the
+ * struct vmw_buffer_object it derives from without refcounting the pointer.
+ * The returned pointer is only valid until vmw_user_bo_noref_release() is
+ * called, and the object pointed to by the returned pointer may be doomed.
+ * Any persistent usage of the object requires a refcount to be taken using
+ * ttm_bo_reference_unless_doomed(). Iff this function returns successfully it
+ * needs to be paired with vmw_user_bo_noref_release() and no sleeping-
+ * or scheduling functions may be called inbetween these function calls.
+ *
+ * Return: A struct vmw_buffer_object pointer if successful or negative
+ * error pointer on failure.
+ */
+struct vmw_buffer_object *
+vmw_user_bo_noref_lookup(struct ttm_object_file *tfile, u32 handle)
+{
+ struct vmw_user_buffer_object *vmw_user_bo;
+ struct ttm_base_object *base;
+
+ base = ttm_base_object_noref_lookup(tfile, handle);
+ if (!base) {
+ DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
+ (unsigned long)handle);
+ return ERR_PTR(-ESRCH);
+ }
+
+ if (unlikely(ttm_base_object_type(base) != ttm_buffer_type)) {
+ ttm_base_object_noref_release();
+ DRM_ERROR("Invalid buffer object handle 0x%08lx.\n",
+ (unsigned long)handle);
+ return ERR_PTR(-EINVAL);
+ }
+
+ vmw_user_bo = container_of(base, struct vmw_user_buffer_object,
+ prime.base);
+ return &vmw_user_bo->vbo;
+}
/**
* vmw_user_bo_reference - Open a handle to a vmw user buffer object.
@@ -940,7 +982,7 @@ int vmw_user_bo_reference(struct ttm_object_file *tfile,
user_bo = container_of(vbo, struct vmw_user_buffer_object, vbo);
- *handle = user_bo->prime.base.hash.key;
+ *handle = user_bo->prime.base.handle;
return ttm_ref_object_add(tfile, &user_bo->prime.base,
TTM_REF_USAGE, NULL, false);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
index e7e4655d3f36..48d1380a952e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf.c
@@ -660,7 +660,7 @@ static void __vmw_cmdbuf_cur_flush(struct vmw_cmdbuf_man *man)
{
struct vmw_cmdbuf_header *cur = man->cur;
- WARN_ON(!mutex_is_locked(&man->cur_mutex));
+ lockdep_assert_held_once(&man->cur_mutex);
if (!cur)
return;
@@ -1045,7 +1045,7 @@ static void vmw_cmdbuf_commit_cur(struct vmw_cmdbuf_man *man,
{
struct vmw_cmdbuf_header *cur = man->cur;
- WARN_ON(!mutex_is_locked(&man->cur_mutex));
+ lockdep_assert_held_once(&man->cur_mutex);
WARN_ON(size > cur->reserved);
man->cur_pos += size;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
index 3b75af9bf85f..4ac55fc2bf97 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -89,8 +89,7 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
if (unlikely(ret != 0))
return ERR_PTR(ret);
- return vmw_resource_reference
- (drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res);
+ return drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res;
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
index 7c3cb8efd11a..14bd760a62fd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
@@ -217,9 +217,7 @@ static int vmw_gb_context_init(struct vmw_private *dev_priv,
}
}
-
-
- vmw_resource_activate(res, vmw_hw_context_destroy);
+ res->hw_destroy = vmw_hw_context_destroy;
return 0;
out_cotables:
@@ -274,7 +272,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
vmw_fifo_commit(dev_priv, sizeof(*cmd));
vmw_fifo_resource_inc(dev_priv);
- vmw_resource_activate(res, vmw_hw_context_destroy);
+ res->hw_destroy = vmw_hw_context_destroy;
return 0;
out_early:
@@ -757,14 +755,10 @@ static int vmw_context_define(struct drm_device *dev, void *data,
return -EINVAL;
}
- /*
- * Approximate idr memory usage with 128 bytes. It will be limited
- * by maximum number_of contexts anyway.
- */
-
if (unlikely(vmw_user_context_size == 0))
- vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) + 128 +
- ((dev_priv->has_mob) ? vmw_cmdbuf_res_man_size() : 0);
+ vmw_user_context_size = ttm_round_pot(sizeof(*ctx)) +
+ ((dev_priv->has_mob) ? vmw_cmdbuf_res_man_size() : 0) +
+ + VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
ret = ttm_read_lock(&dev_priv->reservation_sem, true);
if (unlikely(ret != 0))
@@ -809,7 +803,7 @@ static int vmw_context_define(struct drm_device *dev, void *data,
goto out_err;
}
- arg->cid = ctx->base.hash.key;
+ arg->cid = ctx->base.handle;
out_err:
vmw_resource_unreference(&res);
out_unlock:
@@ -867,9 +861,8 @@ struct vmw_resource *vmw_context_cotable(struct vmw_resource *ctx,
if (cotable_type >= SVGA_COTABLE_DX10_MAX)
return ERR_PTR(-EINVAL);
- return vmw_resource_reference
- (container_of(ctx, struct vmw_user_context, res)->
- cotables[cotable_type]);
+ return container_of(ctx, struct vmw_user_context, res)->
+ cotables[cotable_type];
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
index 1d45714e1d5a..44f3f6f107d3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
@@ -615,7 +615,7 @@ struct vmw_resource *vmw_cotable_alloc(struct vmw_private *dev_priv,
vcotbl->type = type;
vcotbl->ctx = ctx;
- vmw_resource_activate(&vcotbl->res, vmw_hw_cotable_destroy);
+ vcotbl->res.hw_destroy = vmw_hw_cotable_destroy;
return &vcotbl->res;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index bb6dbbe18835..61a84b958d67 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -30,9 +30,9 @@
#include <drm/drmP.h>
#include "vmwgfx_drv.h"
#include "vmwgfx_binding.h"
+#include "ttm_object.h"
#include <drm/ttm/ttm_placement.h>
#include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_object.h>
#include <drm/ttm/ttm_module.h>
#include <linux/dma_remapping.h>
@@ -667,8 +667,8 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
mutex_init(&dev_priv->binding_mutex);
mutex_init(&dev_priv->requested_layout_mutex);
mutex_init(&dev_priv->global_kms_state_mutex);
- rwlock_init(&dev_priv->resource_lock);
ttm_lock_init(&dev_priv->reservation_sem);
+ spin_lock_init(&dev_priv->resource_lock);
spin_lock_init(&dev_priv->hw_lock);
spin_lock_init(&dev_priv->waiter_lock);
spin_lock_init(&dev_priv->cap_lock);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 1abe21758b0d..59f614225bcd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -28,6 +28,7 @@
#ifndef _VMWGFX_DRV_H_
#define _VMWGFX_DRV_H_
+#include "vmwgfx_validation.h"
#include "vmwgfx_reg.h"
#include <drm/drmP.h>
#include <drm/vmwgfx_drm.h>
@@ -35,11 +36,11 @@
#include <drm/drm_auth.h>
#include <linux/suspend.h>
#include <drm/ttm/ttm_bo_driver.h>
-#include <drm/ttm/ttm_object.h>
-#include <drm/ttm/ttm_lock.h>
#include <drm/ttm/ttm_execbuf_util.h>
#include <drm/ttm/ttm_module.h>
#include "vmwgfx_fence.h"
+#include "ttm_object.h"
+#include "ttm_lock.h"
#include <linux/sync_file.h>
#define VMWGFX_DRIVER_NAME "vmwgfx"
@@ -112,21 +113,49 @@ struct vmw_validate_buffer {
};
struct vmw_res_func;
+
+
+/**
+ * struct vmw-resource - base class for hardware resources
+ *
+ * @kref: For refcounting.
+ * @dev_priv: Pointer to the device private for this resource. Immutable.
+ * @id: Device id. Protected by @dev_priv::resource_lock.
+ * @backup_size: Backup buffer size. Immutable.
+ * @res_dirty: Resource contains data not yet in the backup buffer. Protected
+ * by resource reserved.
+ * @backup_dirty: Backup buffer contains data not yet in the HW resource.
+ * Protecte by resource reserved.
+ * @backup: The backup buffer if any. Protected by resource reserved.
+ * @backup_offset: Offset into the backup buffer if any. Protected by resource
+ * reserved. Note that only a few resource types can have a @backup_offset
+ * different from zero.
+ * @pin_count: The pin count for this resource. A pinned resource has a
+ * pin-count greater than zero. It is not on the resource LRU lists and its
+ * backup buffer is pinned. Hence it can't be evicted.
+ * @func: Method vtable for this resource. Immutable.
+ * @lru_head: List head for the LRU list. Protected by @dev_priv::resource_lock.
+ * @mob_head: List head for the MOB backup list. Protected by @backup reserved.
+ * @binding_head: List head for the context binding list. Protected by
+ * the @dev_priv::binding_mutex
+ * @res_free: The resource destructor.
+ * @hw_destroy: Callback to destroy the resource on the device, as part of
+ * resource destruction.
+ */
struct vmw_resource {
struct kref kref;
struct vmw_private *dev_priv;
int id;
- bool avail;
unsigned long backup_size;
- bool res_dirty; /* Protected by backup buffer reserved */
- bool backup_dirty; /* Protected by backup buffer reserved */
+ bool res_dirty;
+ bool backup_dirty;
struct vmw_buffer_object *backup;
unsigned long backup_offset;
- unsigned long pin_count; /* Protected by resource reserved */
+ unsigned long pin_count;
const struct vmw_res_func *func;
- struct list_head lru_head; /* Protected by the resource lock */
- struct list_head mob_head; /* Protected by @backup reserved */
- struct list_head binding_head; /* Protected by binding_mutex */
+ struct list_head lru_head;
+ struct list_head mob_head;
+ struct list_head binding_head;
void (*res_free) (struct vmw_resource *res);
void (*hw_destroy) (struct vmw_resource *res);
};
@@ -204,29 +233,24 @@ struct vmw_fifo_state {
bool dx;
};
-struct vmw_relocation {
- SVGAMobId *mob_loc;
- SVGAGuestPtr *location;
- uint32_t index;
-};
-
/**
* struct vmw_res_cache_entry - resource information cache entry
- *
+ * @handle: User-space handle of a resource.
+ * @res: Non-ref-counted pointer to the resource.
+ * @valid_handle: Whether the @handle member is valid.
* @valid: Whether the entry is valid, which also implies that the execbuf
* code holds a reference to the resource, and it's placed on the
* validation list.
- * @handle: User-space handle of a resource.
- * @res: Non-ref-counted pointer to the resource.
*
* Used to avoid frequent repeated user-space handle lookups of the
* same resource.
*/
struct vmw_res_cache_entry {
- bool valid;
uint32_t handle;
struct vmw_resource *res;
- struct vmw_resource_val_node *node;
+ void *private;
+ unsigned short valid_handle;
+ unsigned short valid;
};
/**
@@ -291,35 +315,63 @@ enum vmw_display_unit_type {
vmw_du_screen_target
};
+struct vmw_validation_context;
+struct vmw_ctx_validation_info;
+/**
+ * struct vmw_sw_context - Command submission context
+ * @res_ht: Pointer hash table used to find validation duplicates
+ * @kernel: Whether the command buffer originates from kernel code rather
+ * than from user-space
+ * @fp: If @kernel is false, points to the file of the client. Otherwise
+ * NULL
+ * @cmd_bounce: Command bounce buffer used for command validation before
+ * copying to fifo space
+ * @cmd_bounce_size: Current command bounce buffer size
+ * @cur_query_bo: Current buffer object used as query result buffer
+ * @bo_relocations: List of buffer object relocations
+ * @res_relocations: List of resource relocations
+ * @buf_start: Pointer to start of memory where command validation takes
+ * place
+ * @res_cache: Cache of recently looked up resources
+ * @last_query_ctx: Last context that submitted a query
+ * @needs_post_query_barrier: Whether a query barrier is needed after
+ * command submission
+ * @staged_bindings: Cached per-context binding tracker
+ * @staged_bindings_inuse: Whether the cached per-context binding tracker
+ * is in use
+ * @staged_cmd_res: List of staged command buffer managed resources in this
+ * command buffer
+ * @ctx_list: List of context resources referenced in this command buffer
+ * @dx_ctx_node: Validation metadata of the current DX context
+ * @dx_query_mob: The MOB used for DX queries
+ * @dx_query_ctx: The DX context used for the last DX query
+ * @man: Pointer to the command buffer managed resource manager
+ * @ctx: The validation context
+ */
struct vmw_sw_context{
struct drm_open_hash res_ht;
bool res_ht_initialized;
- bool kernel; /**< is the called made from the kernel */
+ bool kernel;
struct vmw_fpriv *fp;
- struct list_head validate_nodes;
- struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS];
- uint32_t cur_reloc;
- struct vmw_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS];
- uint32_t cur_val_buf;
uint32_t *cmd_bounce;
uint32_t cmd_bounce_size;
- struct list_head resource_list;
- struct list_head ctx_resource_list; /* For contexts and cotables */
struct vmw_buffer_object *cur_query_bo;
+ struct list_head bo_relocations;
struct list_head res_relocations;
uint32_t *buf_start;
struct vmw_res_cache_entry res_cache[vmw_res_max];
struct vmw_resource *last_query_ctx;
bool needs_post_query_barrier;
- struct vmw_resource *error_resource;
struct vmw_ctx_binding_state *staged_bindings;
bool staged_bindings_inuse;
struct list_head staged_cmd_res;
- struct vmw_resource_val_node *dx_ctx_node;
+ struct list_head ctx_list;
+ struct vmw_ctx_validation_info *dx_ctx_node;
struct vmw_buffer_object *dx_query_mob;
struct vmw_resource *dx_query_ctx;
struct vmw_cmdbuf_res_manager *man;
+ struct vmw_validation_context *ctx;
};
struct vmw_legacy_display;
@@ -444,7 +496,7 @@ struct vmw_private {
* Context and surface management.
*/
- rwlock_t resource_lock;
+ spinlock_t resource_lock;
struct idr res_idr[vmw_res_max];
/*
* Block lastclose from racing with firstopen.
@@ -628,7 +680,7 @@ extern void vmw_resource_unreference(struct vmw_resource **p_res);
extern struct vmw_resource *vmw_resource_reference(struct vmw_resource *res);
extern struct vmw_resource *
vmw_resource_reference_unless_doomed(struct vmw_resource *res);
-extern int vmw_resource_validate(struct vmw_resource *res);
+extern int vmw_resource_validate(struct vmw_resource *res, bool intr);
extern int vmw_resource_reserve(struct vmw_resource *res, bool interruptible,
bool no_backup);
extern bool vmw_resource_needs_backup(const struct vmw_resource *res);
@@ -643,6 +695,12 @@ extern int vmw_user_resource_lookup_handle(
uint32_t handle,
const struct vmw_user_resource_conv *converter,
struct vmw_resource **p_res);
+extern struct vmw_resource *
+vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
+ struct ttm_object_file *tfile,
+ uint32_t handle,
+ const struct vmw_user_resource_conv *
+ converter);
extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data,
@@ -662,6 +720,15 @@ extern void vmw_resource_evict_all(struct vmw_private *dev_priv);
extern void vmw_resource_unbind_list(struct vmw_buffer_object *vbo);
/**
+ * vmw_user_resource_noref_release - release a user resource pointer looked up
+ * without reference
+ */
+static inline void vmw_user_resource_noref_release(void)
+{
+ ttm_base_object_noref_release();
+}
+
+/**
* Buffer object helper functions - vmwgfx_bo.c
*/
extern int vmw_bo_pin_in_placement(struct vmw_private *vmw_priv,
@@ -717,6 +784,18 @@ extern void vmw_bo_unmap(struct vmw_buffer_object *vbo);
extern void vmw_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem);
extern void vmw_bo_swap_notify(struct ttm_buffer_object *bo);
+extern struct vmw_buffer_object *
+vmw_user_bo_noref_lookup(struct ttm_object_file *tfile, u32 handle);
+
+/**
+ * vmw_user_bo_noref_release - release a buffer object pointer looked up
+ * without reference
+ */
+static inline void vmw_user_bo_noref_release(void)
+{
+ ttm_base_object_noref_release();
+}
+
/**
* Misc Ioctl functionality - vmwgfx_ioctl.c
@@ -864,10 +943,6 @@ extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv,
uint32_t fence_handle,
int32_t out_fence_fd,
struct sync_file *sync_file);
-extern int vmw_validate_single_buffer(struct vmw_private *dev_priv,
- struct ttm_buffer_object *bo,
- bool interruptible,
- bool validate_as_mob);
bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd);
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index f0ab6b2313bb..5a6b70ba137a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -35,6 +35,23 @@
#define VMW_RES_HT_ORDER 12
+/*
+ * struct vmw_relocation - Buffer object relocation
+ *
+ * @head: List head for the command submission context's relocation list
+ * @vbo: Non ref-counted pointer to buffer object
+ * @mob_loc: Pointer to location for mob id to be modified
+ * @location: Pointer to location for guest pointer to be modified
+ */
+struct vmw_relocation {
+ struct list_head head;
+ struct vmw_buffer_object *vbo;
+ union {
+ SVGAMobId *mob_loc;
+ SVGAGuestPtr *location;
+ };
+};
+
/**
* enum vmw_resource_relocation_type - Relocation type for resources
*
@@ -69,35 +86,18 @@ struct vmw_resource_relocation {
enum vmw_resource_relocation_type rel_type:3;
};
-/**
- * struct vmw_resource_val_node - Validation info for resources
- *
- * @head: List head for the software context's resource list.
- * @hash: Hash entry for quick resouce to val_node lookup.
- * @res: Ref-counted pointer to the resource.
- * @switch_backup: Boolean whether to switch backup buffer on unreserve.
- * @new_backup: Refcounted pointer to the new backup buffer.
- * @staged_bindings: If @res is a context, tracks bindings set up during
- * the command batch. Otherwise NULL.
- * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll.
- * @first_usage: Set to true the first time the resource is referenced in
- * the command stream.
- * @switching_backup: The command stream provides a new backup buffer for a
- * resource.
- * @no_buffer_needed: This means @switching_backup is true on first buffer
- * reference. So resource reservation does not need to allocate a backup
- * buffer for the resource.
+/*
+ * struct vmw_ctx_validation_info - Extra validation metadata for contexts
+ * @head: List head of context list
+ * @ctx: The context resource
+ * @cur: The context's persistent binding state
+ * @staged: The binding state changes of this command buffer
*/
-struct vmw_resource_val_node {
+struct vmw_ctx_validation_info {
struct list_head head;
- struct drm_hash_item hash;
- struct vmw_resource *res;
- struct vmw_buffer_object *new_backup;
- struct vmw_ctx_binding_state *staged_bindings;
- unsigned long new_backup_offset;
- u32 first_usage : 1;
- u32 switching_backup : 1;
- u32 no_buffer_needed : 1;
+ struct vmw_resource *ctx;
+ struct vmw_ctx_binding_state *cur;
+ struct vmw_ctx_binding_state *staged;
};
/**
@@ -127,10 +127,6 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGAMobId *id,
struct vmw_buffer_object **vmw_bo_p);
-static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
- struct vmw_buffer_object *vbo,
- bool validate_as_mob,
- uint32_t *p_val_node);
/**
* vmw_ptr_diff - Compute the offset from a to b in bytes
*
@@ -145,48 +141,38 @@ static size_t vmw_ptr_diff(void *a, void *b)
}
/**
- * vmw_resources_unreserve - unreserve resources previously reserved for
- * command submission.
- *
- * @sw_context: pointer to the software context
- * @backoff: Whether command submission failed.
+ * vmw_execbuf_bindings_commit - Commit modified binding state
+ * @sw_context: The command submission context
+ * @backoff: Whether this is part of the error path and binding state
+ * changes should be ignored
*/
-static void vmw_resources_unreserve(struct vmw_sw_context *sw_context,
- bool backoff)
+static void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context,
+ bool backoff)
{
- struct vmw_resource_val_node *val;
- struct list_head *list = &sw_context->resource_list;
+ struct vmw_ctx_validation_info *entry;
- if (sw_context->dx_query_mob && !backoff)
- vmw_context_bind_dx_query(sw_context->dx_query_ctx,
- sw_context->dx_query_mob);
+ list_for_each_entry(entry, &sw_context->ctx_list, head) {
+ if (!backoff)
+ vmw_binding_state_commit(entry->cur, entry->staged);
+ if (entry->staged != sw_context->staged_bindings)
+ vmw_binding_state_free(entry->staged);
+ else
+ sw_context->staged_bindings_inuse = false;
+ }
- list_for_each_entry(val, list, head) {
- struct vmw_resource *res = val->res;
- bool switch_backup =
- (backoff) ? false : val->switching_backup;
-
- /*
- * Transfer staged context bindings to the
- * persistent context binding tracker.
- */
- if (unlikely(val->staged_bindings)) {
- if (!backoff) {
- vmw_binding_state_commit
- (vmw_context_binding_state(val->res),
- val->staged_bindings);
- }
+ /* List entries are freed with the validation context */
+ INIT_LIST_HEAD(&sw_context->ctx_list);
+}
- if (val->staged_bindings != sw_context->staged_bindings)
- vmw_binding_state_free(val->staged_bindings);
- else
- sw_context->staged_bindings_inuse = false;
- val->staged_bindings = NULL;
- }
- vmw_resource_unreserve(res, switch_backup, val->new_backup,
- val->new_backup_offset);
- vmw_bo_unreference(&val->new_backup);
- }
+/**
+ * vmw_bind_dx_query_mob - Bind the DX query MOB if referenced
+ * @sw_context: The command submission context
+ */
+static void vmw_bind_dx_query_mob(struct vmw_sw_context *sw_context)
+{
+ if (sw_context->dx_query_mob)
+ vmw_context_bind_dx_query(sw_context->dx_query_ctx,
+ sw_context->dx_query_mob);
}
/**
@@ -194,16 +180,17 @@ static void vmw_resources_unreserve(struct vmw_sw_context *sw_context,
* added to the validate list.
*
* @dev_priv: Pointer to the device private:
- * @sw_context: The validation context:
- * @node: The validation node holding this context.
+ * @sw_context: The command submission context
+ * @node: The validation node holding the context resource metadata
*/
static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
- struct vmw_resource_val_node *node)
+ struct vmw_resource *res,
+ struct vmw_ctx_validation_info *node)
{
int ret;
- ret = vmw_resource_context_res_add(dev_priv, sw_context, node->res);
+ ret = vmw_resource_context_res_add(dev_priv, sw_context, res);
if (unlikely(ret != 0))
goto out_err;
@@ -220,91 +207,138 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv,
}
if (sw_context->staged_bindings_inuse) {
- node->staged_bindings = vmw_binding_state_alloc(dev_priv);
- if (IS_ERR(node->staged_bindings)) {
+ node->staged = vmw_binding_state_alloc(dev_priv);
+ if (IS_ERR(node->staged)) {
DRM_ERROR("Failed to allocate context binding "
"information.\n");
- ret = PTR_ERR(node->staged_bindings);
- node->staged_bindings = NULL;
+ ret = PTR_ERR(node->staged);
+ node->staged = NULL;
goto out_err;
}
} else {
- node->staged_bindings = sw_context->staged_bindings;
+ node->staged = sw_context->staged_bindings;
sw_context->staged_bindings_inuse = true;
}
+ node->ctx = res;
+ node->cur = vmw_context_binding_state(res);
+ list_add_tail(&node->head, &sw_context->ctx_list);
+
return 0;
out_err:
return ret;
}
/**
- * vmw_resource_val_add - Add a resource to the software context's
- * resource list if it's not already on it.
+ * vmw_execbuf_res_size - calculate extra size fore the resource validation
+ * node
+ * @dev_priv: Pointer to the device private struct.
+ * @res_type: The resource type.
*
- * @sw_context: Pointer to the software context.
+ * Guest-backed contexts and DX contexts require extra size to store
+ * execbuf private information in the validation node. Typically the
+ * binding manager associated data structures.
+ *
+ * Returns: The extra size requirement based on resource type.
+ */
+static unsigned int vmw_execbuf_res_size(struct vmw_private *dev_priv,
+ enum vmw_res_type res_type)
+{
+ return (res_type == vmw_res_dx_context ||
+ (res_type == vmw_res_context && dev_priv->has_mob)) ?
+ sizeof(struct vmw_ctx_validation_info) : 0;
+}
+
+/**
+ * vmw_execbuf_rcache_update - Update a resource-node cache entry
+ *
+ * @rcache: Pointer to the entry to update.
* @res: Pointer to the resource.
- * @p_node On successful return points to a valid pointer to a
- * struct vmw_resource_val_node, if non-NULL on entry.
+ * @private: Pointer to the execbuf-private space in the resource
+ * validation node.
+ */
+static void vmw_execbuf_rcache_update(struct vmw_res_cache_entry *rcache,
+ struct vmw_resource *res,
+ void *private)
+{
+ rcache->res = res;
+ rcache->private = private;
+ rcache->valid = 1;
+ rcache->valid_handle = 0;
+}
+
+/**
+ * vmw_execbuf_res_noref_val_add - Add a resource described by an
+ * unreferenced rcu-protected pointer to the validation list.
+ * @sw_context: Pointer to the software context.
+ * @res: Unreferenced rcu-protected pointer to the resource.
+ *
+ * Returns: 0 on success. Negative error code on failure. Typical error
+ * codes are %-EINVAL on inconsistency and %-ESRCH if the resource was
+ * doomed.
*/
-static int vmw_resource_val_add(struct vmw_sw_context *sw_context,
- struct vmw_resource *res,
- struct vmw_resource_val_node **p_node)
+static int vmw_execbuf_res_noref_val_add(struct vmw_sw_context *sw_context,
+ struct vmw_resource *res)
{
struct vmw_private *dev_priv = res->dev_priv;
- struct vmw_resource_val_node *node;
- struct drm_hash_item *hash;
int ret;
-
- if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) res,
- &hash) == 0)) {
- node = container_of(hash, struct vmw_resource_val_node, hash);
- node->first_usage = false;
- if (unlikely(p_node != NULL))
- *p_node = node;
+ enum vmw_res_type res_type = vmw_res_type(res);
+ struct vmw_res_cache_entry *rcache;
+ struct vmw_ctx_validation_info *ctx_info;
+ bool first_usage;
+ unsigned int priv_size;
+
+ rcache = &sw_context->res_cache[res_type];
+ if (likely(rcache->valid && rcache->res == res)) {
+ vmw_user_resource_noref_release();
return 0;
}
- node = kzalloc(sizeof(*node), GFP_KERNEL);
- if (unlikely(!node)) {
- DRM_ERROR("Failed to allocate a resource validation "
- "entry.\n");
- return -ENOMEM;
- }
-
- node->hash.key = (unsigned long) res;
- ret = drm_ht_insert_item(&sw_context->res_ht, &node->hash);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed to initialize a resource validation "
- "entry.\n");
- kfree(node);
+ priv_size = vmw_execbuf_res_size(dev_priv, res_type);
+ ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size,
+ (void **)&ctx_info, &first_usage);
+ vmw_user_resource_noref_release();
+ if (ret)
return ret;
+
+ if (priv_size && first_usage) {
+ ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res,
+ ctx_info);
+ if (ret)
+ return ret;
}
- node->res = vmw_resource_reference(res);
- node->first_usage = true;
- if (unlikely(p_node != NULL))
- *p_node = node;
- if (!dev_priv->has_mob) {
- list_add_tail(&node->head, &sw_context->resource_list);
+ vmw_execbuf_rcache_update(rcache, res, ctx_info);
+ return 0;
+}
+
+/**
+ * vmw_execbuf_res_noctx_val_add - Add a non-context resource to the resource
+ * validation list if it's not already on it
+ * @sw_context: Pointer to the software context.
+ * @res: Pointer to the resource.
+ *
+ * Returns: Zero on success. Negative error code on failure.
+ */
+static int vmw_execbuf_res_noctx_val_add(struct vmw_sw_context *sw_context,
+ struct vmw_resource *res)
+{
+ struct vmw_res_cache_entry *rcache;
+ enum vmw_res_type res_type = vmw_res_type(res);
+ void *ptr;
+ int ret;
+
+ rcache = &sw_context->res_cache[res_type];
+ if (likely(rcache->valid && rcache->res == res))
return 0;
- }
- switch (vmw_res_type(res)) {
- case vmw_res_context:
- case vmw_res_dx_context:
- list_add(&node->head, &sw_context->ctx_resource_list);
- ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, node);
- break;
- case vmw_res_cotable:
- list_add_tail(&node->head, &sw_context->ctx_resource_list);
- break;
- default:
- list_add_tail(&node->head, &sw_context->resource_list);
- break;
- }
+ ret = vmw_validation_add_resource(sw_context->ctx, res, 0, &ptr, NULL);
+ if (ret)
+ return ret;
- return ret;
+ vmw_execbuf_rcache_update(rcache, res, ptr);
+
+ return 0;
}
/**
@@ -325,11 +359,11 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context,
* First add the resource the view is pointing to, otherwise
* it may be swapped out when the view is validated.
*/
- ret = vmw_resource_val_add(sw_context, vmw_view_srf(view), NULL);
+ ret = vmw_execbuf_res_noctx_val_add(sw_context, vmw_view_srf(view));
if (ret)
return ret;
- return vmw_resource_val_add(sw_context, view, NULL);
+ return vmw_execbuf_res_noctx_val_add(sw_context, view);
}
/**
@@ -342,28 +376,33 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context,
*
* The view is represented by a view id and the DX context it's created on,
* or scheduled for creation on. If there is no DX context set, the function
- * will return -EINVAL. Otherwise returns 0 on success and -EINVAL on failure.
+ * will return an -EINVAL error pointer.
+ *
+ * Returns: Unreferenced pointer to the resource on success, negative error
+ * pointer on failure.
*/
-static int vmw_view_id_val_add(struct vmw_sw_context *sw_context,
- enum vmw_view_type view_type, u32 id)
+static struct vmw_resource *
+vmw_view_id_val_add(struct vmw_sw_context *sw_context,
+ enum vmw_view_type view_type, u32 id)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_resource *view;
int ret;
if (!ctx_node) {
DRM_ERROR("DX Context not set.\n");
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
}
view = vmw_view_lookup(sw_context->man, view_type, id);
if (IS_ERR(view))
- return PTR_ERR(view);
+ return view;
ret = vmw_view_res_val_add(sw_context, view);
- vmw_resource_unreference(&view);
+ if (ret)
+ return ERR_PTR(ret);
- return ret;
+ return view;
}
/**
@@ -394,8 +433,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
if (IS_ERR(res))
continue;
- ret = vmw_resource_val_add(sw_context, res, NULL);
- vmw_resource_unreference(&res);
+ ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
if (unlikely(ret != 0))
return ret;
}
@@ -407,17 +445,11 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
binding_list = vmw_context_binding_list(ctx);
list_for_each_entry(entry, binding_list, ctx_list) {
- /* entry->res is not refcounted */
- res = vmw_resource_reference_unless_doomed(entry->res);
- if (unlikely(res == NULL))
- continue;
-
if (vmw_res_type(entry->res) == vmw_res_view)
ret = vmw_view_res_val_add(sw_context, entry->res);
else
- ret = vmw_resource_val_add(sw_context, entry->res,
- NULL);
- vmw_resource_unreference(&res);
+ ret = vmw_execbuf_res_noctx_val_add(sw_context,
+ entry->res);
if (unlikely(ret != 0))
break;
}
@@ -427,9 +459,8 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
dx_query_mob = vmw_context_get_dx_query_mob(ctx);
if (dx_query_mob)
- ret = vmw_bo_to_validate_list(sw_context,
- dx_query_mob,
- true, NULL);
+ ret = vmw_validation_add_bo(sw_context->ctx,
+ dx_query_mob, true, false);
}
mutex_unlock(&dev_priv->binding_mutex);
@@ -445,7 +476,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv,
* id that needs fixup is located. Granularity is one byte.
* @rel_type: Relocation type.
*/
-static int vmw_resource_relocation_add(struct list_head *list,
+static int vmw_resource_relocation_add(struct vmw_sw_context *sw_context,
const struct vmw_resource *res,
unsigned long offset,
enum vmw_resource_relocation_type
@@ -453,7 +484,7 @@ static int vmw_resource_relocation_add(struct list_head *list,
{
struct vmw_resource_relocation *rel;
- rel = kmalloc(sizeof(*rel), GFP_KERNEL);
+ rel = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*rel));
if (unlikely(!rel)) {
DRM_ERROR("Failed to allocate a resource relocation.\n");
return -ENOMEM;
@@ -462,7 +493,7 @@ static int vmw_resource_relocation_add(struct list_head *list,
rel->res = res;
rel->offset = offset;
rel->rel_type = rel_type;
- list_add_tail(&rel->head, list);
+ list_add_tail(&rel->head, &sw_context->res_relocations);
return 0;
}
@@ -470,16 +501,13 @@ static int vmw_resource_relocation_add(struct list_head *list,
/**
* vmw_resource_relocations_free - Free all relocations on a list
*
- * @list: Pointer to the head of the relocation list.
+ * @list: Pointer to the head of the relocation list
*/
static void vmw_resource_relocations_free(struct list_head *list)
{
- struct vmw_resource_relocation *rel, *n;
+ /* Memory is validation context memory, so no need to free it */
- list_for_each_entry_safe(rel, n, list, head) {
- list_del(&rel->head);
- kfree(rel);
- }
+ INIT_LIST_HEAD(list);
}
/**
@@ -532,68 +560,6 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv,
}
/**
- * vmw_bo_to_validate_list - add a bo to a validate list
- *
- * @sw_context: The software context used for this command submission batch.
- * @bo: The buffer object to add.
- * @validate_as_mob: Validate this buffer as a MOB.
- * @p_val_node: If non-NULL Will be updated with the validate node number
- * on return.
- *
- * Returns -EINVAL if the limit of number of buffer objects per command
- * submission is reached.
- */
-static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
- struct vmw_buffer_object *vbo,
- bool validate_as_mob,
- uint32_t *p_val_node)
-{
- uint32_t val_node;
- struct vmw_validate_buffer *vval_buf;
- struct ttm_validate_buffer *val_buf;
- struct drm_hash_item *hash;
- int ret;
-
- if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) vbo,
- &hash) == 0)) {
- vval_buf = container_of(hash, struct vmw_validate_buffer,
- hash);
- if (unlikely(vval_buf->validate_as_mob != validate_as_mob)) {
- DRM_ERROR("Inconsistent buffer usage.\n");
- return -EINVAL;
- }
- val_buf = &vval_buf->base;
- val_node = vval_buf - sw_context->val_bufs;
- } else {
- val_node = sw_context->cur_val_buf;
- if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) {
- DRM_ERROR("Max number of DMA buffers per submission "
- "exceeded.\n");
- return -EINVAL;
- }
- vval_buf = &sw_context->val_bufs[val_node];
- vval_buf->hash.key = (unsigned long) vbo;
- ret = drm_ht_insert_item(&sw_context->res_ht, &vval_buf->hash);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Failed to initialize a buffer validation "
- "entry.\n");
- return ret;
- }
- ++sw_context->cur_val_buf;
- val_buf = &vval_buf->base;
- val_buf->bo = ttm_bo_reference(&vbo->base);
- val_buf->shared = false;
- list_add_tail(&val_buf->head, &sw_context->validate_nodes);
- vval_buf->validate_as_mob = validate_as_mob;
- }
-
- if (p_val_node)
- *p_val_node = val_node;
-
- return 0;
-}
-
-/**
* vmw_resources_reserve - Reserve all resources on the sw_context's
* resource list.
*
@@ -605,27 +571,11 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context,
*/
static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
{
- struct vmw_resource_val_node *val;
- int ret = 0;
-
- list_for_each_entry(val, &sw_context->resource_list, head) {
- struct vmw_resource *res = val->res;
-
- ret = vmw_resource_reserve(res, true, val->no_buffer_needed);
- if (unlikely(ret != 0))
- return ret;
-
- if (res->backup) {
- struct vmw_buffer_object *vbo = res->backup;
-
- ret = vmw_bo_to_validate_list
- (sw_context, vbo,
- vmw_resource_needs_backup(res), NULL);
+ int ret;
- if (unlikely(ret != 0))
- return ret;
- }
- }
+ ret = vmw_validation_res_reserve(sw_context->ctx, true);
+ if (ret)
+ return ret;
if (sw_context->dx_query_mob) {
struct vmw_buffer_object *expected_dx_query_mob;
@@ -642,87 +592,6 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context)
}
/**
- * vmw_resources_validate - Validate all resources on the sw_context's
- * resource list.
- *
- * @sw_context: Pointer to the software context.
- *
- * Before this function is called, all resource backup buffers must have
- * been validated.
- */
-static int vmw_resources_validate(struct vmw_sw_context *sw_context)
-{
- struct vmw_resource_val_node *val;
- int ret;
-
- list_for_each_entry(val, &sw_context->resource_list, head) {
- struct vmw_resource *res = val->res;
- struct vmw_buffer_object *backup = res->backup;
-
- ret = vmw_resource_validate(res);
- if (unlikely(ret != 0)) {
- if (ret != -ERESTARTSYS)
- DRM_ERROR("Failed to validate resource.\n");
- return ret;
- }
-
- /* Check if the resource switched backup buffer */
- if (backup && res->backup && (backup != res->backup)) {
- struct vmw_buffer_object *vbo = res->backup;
-
- ret = vmw_bo_to_validate_list
- (sw_context, vbo,
- vmw_resource_needs_backup(res), NULL);
- if (ret) {
- ttm_bo_unreserve(&vbo->base);
- return ret;
- }
- }
- }
- return 0;
-}
-
-/**
- * vmw_cmd_res_reloc_add - Add a resource to a software context's
- * relocation- and validation lists.
- *
- * @dev_priv: Pointer to a struct vmw_private identifying the device.
- * @sw_context: Pointer to the software context.
- * @id_loc: Pointer to where the id that needs translation is located.
- * @res: Valid pointer to a struct vmw_resource.
- * @p_val: If non null, a pointer to the struct vmw_resource_validate_node
- * used for this resource is returned here.
- */
-static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv,
- struct vmw_sw_context *sw_context,
- uint32_t *id_loc,
- struct vmw_resource *res,
- struct vmw_resource_val_node **p_val)
-{
- int ret;
- struct vmw_resource_val_node *node;
-
- *p_val = NULL;
- ret = vmw_resource_relocation_add(&sw_context->res_relocations,
- res,
- vmw_ptr_diff(sw_context->buf_start,
- id_loc),
- vmw_res_rel_normal);
- if (unlikely(ret != 0))
- return ret;
-
- ret = vmw_resource_val_add(sw_context, res, &node);
- if (unlikely(ret != 0))
- return ret;
-
- if (p_val)
- *p_val = node;
-
- return 0;
-}
-
-
-/**
* vmw_cmd_res_check - Check that a resource is present and if so, put it
* on the resource validate list unless it's already there.
*
@@ -741,17 +610,16 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
enum vmw_res_type res_type,
const struct vmw_user_resource_conv *converter,
uint32_t *id_loc,
- struct vmw_resource_val_node **p_val)
+ struct vmw_resource **p_res)
{
- struct vmw_res_cache_entry *rcache =
- &sw_context->res_cache[res_type];
+ struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type];
struct vmw_resource *res;
- struct vmw_resource_val_node *node;
int ret;
+ if (p_res)
+ *p_res = NULL;
+
if (*id_loc == SVGA3D_INVALID_ID) {
- if (p_val)
- *p_val = NULL;
if (res_type == vmw_res_context) {
DRM_ERROR("Illegal context invalid id.\n");
return -EINVAL;
@@ -759,56 +627,41 @@ vmw_cmd_res_check(struct vmw_private *dev_priv,
return 0;
}
- /*
- * Fastpath in case of repeated commands referencing the same
- * resource
- */
+ if (likely(rcache->valid_handle && *id_loc == rcache->handle)) {
+ res = rcache->res;
+ } else {
+ unsigned int size = vmw_execbuf_res_size(dev_priv, res_type);
- if (likely(rcache->valid && *id_loc == rcache->handle)) {
- const struct vmw_resource *res = rcache->res;
+ ret = vmw_validation_preload_res(sw_context->ctx, size);
+ if (ret)
+ return ret;
- rcache->node->first_usage = false;
- if (p_val)
- *p_val = rcache->node;
+ res = vmw_user_resource_noref_lookup_handle
+ (dev_priv, sw_context->fp->tfile, *id_loc, converter);
+ if (unlikely(IS_ERR(res))) {
+ DRM_ERROR("Could not find or use resource 0x%08x.\n",
+ (unsigned int) *id_loc);
+ return PTR_ERR(res);
+ }
- return vmw_resource_relocation_add
- (&sw_context->res_relocations, res,
- vmw_ptr_diff(sw_context->buf_start, id_loc),
- vmw_res_rel_normal);
- }
+ ret = vmw_execbuf_res_noref_val_add(sw_context, res);
+ if (unlikely(ret != 0))
+ return ret;
- ret = vmw_user_resource_lookup_handle(dev_priv,
- sw_context->fp->tfile,
- *id_loc,
- converter,
- &res);
- if (unlikely(ret != 0)) {
- DRM_ERROR("Could not find or use resource 0x%08x.\n",
- (unsigned) *id_loc);
- dump_stack();
- return ret;
+ if (rcache->valid && rcache->res == res) {
+ rcache->valid_handle = true;
+ rcache->handle = *id_loc;
+ }
}
- rcache->valid = true;
- rcache->res = res;
- rcache->handle = *id_loc;
-
- ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, id_loc,
- res, &node);
- if (unlikely(ret != 0))
- goto out_no_reloc;
+ ret = vmw_resource_relocation_add(sw_context, res,
+ vmw_ptr_diff(sw_context->buf_start,
+ id_loc),
+ vmw_res_rel_normal);
+ if (p_res)
+ *p_res = res;
- rcache->node = node;
- if (p_val)
- *p_val = node;
- vmw_resource_unreference(&res);
return 0;
-
-out_no_reloc:
- BUG_ON(sw_context->error_resource != NULL);
- sw_context->error_resource = res;
-
- return ret;
}
/**
@@ -861,22 +714,18 @@ static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res)
*/
static int vmw_rebind_contexts(struct vmw_sw_context *sw_context)
{
- struct vmw_resource_val_node *val;
+ struct vmw_ctx_validation_info *val;
int ret;
- list_for_each_entry(val, &sw_context->resource_list, head) {
- if (unlikely(!val->staged_bindings))
- break;
-
- ret = vmw_binding_rebind_all
- (vmw_context_binding_state(val->res));
+ list_for_each_entry(val, &sw_context->ctx_list, head) {
+ ret = vmw_binding_rebind_all(val->cur);
if (unlikely(ret != 0)) {
if (ret != -ERESTARTSYS)
DRM_ERROR("Failed to rebind context.\n");
return ret;
}
- ret = vmw_rebind_all_dx_query(val->res);
+ ret = vmw_rebind_all_dx_query(val->ctx);
if (ret != 0)
return ret;
}
@@ -903,45 +752,33 @@ static int vmw_view_bindings_add(struct vmw_sw_context *sw_context,
uint32 view_ids[], u32 num_views,
u32 first_slot)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
- struct vmw_cmdbuf_res_manager *man;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
u32 i;
- int ret;
if (!ctx_node) {
DRM_ERROR("DX Context not set.\n");
return -EINVAL;
}
- man = sw_context->man;
for (i = 0; i < num_views; ++i) {
struct vmw_ctx_bindinfo_view binding;
struct vmw_resource *view = NULL;
if (view_ids[i] != SVGA3D_INVALID_ID) {
- view = vmw_view_lookup(man, view_type, view_ids[i]);
+ view = vmw_view_id_val_add(sw_context, view_type,
+ view_ids[i]);
if (IS_ERR(view)) {
DRM_ERROR("View not found.\n");
return PTR_ERR(view);
}
-
- ret = vmw_view_res_val_add(sw_context, view);
- if (ret) {
- DRM_ERROR("Could not add view to "
- "validation list.\n");
- vmw_resource_unreference(&view);
- return ret;
- }
}
- binding.bi.ctx = ctx_node->res;
+ binding.bi.ctx = ctx_node->ctx;
binding.bi.res = view;
binding.bi.bt = binding_type;
binding.shader_slot = shader_slot;
binding.slot = first_slot + i;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
+ vmw_binding_add(ctx_node->staged, &binding.bi,
shader_slot, binding.slot);
- if (view)
- vmw_resource_unreference(&view);
}
return 0;
@@ -971,6 +808,34 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv,
user_context_converter, &cmd->cid, NULL);
}
+/**
+ * vmw_execbuf_info_from_res - Get the private validation metadata for a
+ * recently validated resource
+ * @sw_context: Pointer to the command submission context
+ * @res: The resource
+ *
+ * The resource pointed to by @res needs to be present in the command submission
+ * context's resource cache and hence the last resource of that type to be
+ * processed by the validation code.
+ *
+ * Return: a pointer to the private metadata of the resource, or NULL
+ * if it wasn't found
+ */
+static struct vmw_ctx_validation_info *
+vmw_execbuf_info_from_res(struct vmw_sw_context *sw_context,
+ struct vmw_resource *res)
+{
+ struct vmw_res_cache_entry *rcache =
+ &sw_context->res_cache[vmw_res_type(res)];
+
+ if (rcache->valid && rcache->res == res)
+ return rcache->private;
+
+ WARN_ON_ONCE(true);
+ return NULL;
+}
+
+
static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
@@ -979,8 +844,8 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
SVGA3dCmdHeader header;
SVGA3dCmdSetRenderTarget body;
} *cmd;
- struct vmw_resource_val_node *ctx_node;
- struct vmw_resource_val_node *res_node;
+ struct vmw_resource *ctx;
+ struct vmw_resource *res;
int ret;
cmd = container_of(header, struct vmw_sid_cmd, header);
@@ -993,25 +858,29 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv,
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->body.cid,
- &ctx_node);
+ &ctx);
if (unlikely(ret != 0))
return ret;
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
- user_surface_converter,
- &cmd->body.target.sid, &res_node);
- if (unlikely(ret != 0))
+ user_surface_converter, &cmd->body.target.sid,
+ &res);
+ if (unlikely(ret))
return ret;
if (dev_priv->has_mob) {
struct vmw_ctx_bindinfo_view binding;
+ struct vmw_ctx_validation_info *node;
- binding.bi.ctx = ctx_node->res;
- binding.bi.res = res_node ? res_node->res : NULL;
+ node = vmw_execbuf_info_from_res(sw_context, ctx);
+ if (!node)
+ return -EINVAL;
+
+ binding.bi.ctx = ctx;
+ binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_rt;
binding.slot = cmd->body.type;
- vmw_binding_add(ctx_node->staged_bindings,
- &binding.bi, 0, binding.slot);
+ vmw_binding_add(node->staged, &binding.bi, 0, binding.slot);
}
return 0;
@@ -1030,8 +899,8 @@ static int vmw_cmd_surface_copy_check(struct vmw_private *dev_priv,
cmd = container_of(header, struct vmw_sid_cmd, header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
- user_surface_converter,
- &cmd->body.src.sid, NULL);
+ user_surface_converter,
+ &cmd->body.src.sid, NULL);
if (ret)
return ret;
@@ -1171,17 +1040,17 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
if (unlikely(sw_context->cur_query_bo != NULL)) {
sw_context->needs_post_query_barrier = true;
- ret = vmw_bo_to_validate_list(sw_context,
- sw_context->cur_query_bo,
- dev_priv->has_mob, NULL);
+ ret = vmw_validation_add_bo(sw_context->ctx,
+ sw_context->cur_query_bo,
+ dev_priv->has_mob, false);
if (unlikely(ret != 0))
return ret;
}
sw_context->cur_query_bo = new_query_bo;
- ret = vmw_bo_to_validate_list(sw_context,
- dev_priv->dummy_query_bo,
- dev_priv->has_mob, NULL);
+ ret = vmw_validation_add_bo(sw_context->ctx,
+ dev_priv->dummy_query_bo,
+ dev_priv->has_mob, false);
if (unlikely(ret != 0))
return ret;
@@ -1269,7 +1138,7 @@ static void vmw_query_bo_switch_commit(struct vmw_private *dev_priv,
* @sw_context: The software context used for this command batch validation.
* @id: Pointer to the user-space handle to be translated.
* @vmw_bo_p: Points to a location that, on successful return will carry
- * a reference-counted pointer to the DMA buffer identified by the
+ * a non-reference-counted pointer to the buffer object identified by the
* user-space handle in @id.
*
* This function saves information needed to translate a user-space buffer
@@ -1284,40 +1153,34 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
SVGAMobId *id,
struct vmw_buffer_object **vmw_bo_p)
{
- struct vmw_buffer_object *vmw_bo = NULL;
+ struct vmw_buffer_object *vmw_bo;
uint32_t handle = *id;
struct vmw_relocation *reloc;
int ret;
- ret = vmw_user_bo_lookup(sw_context->fp->tfile, handle, &vmw_bo, NULL);
- if (unlikely(ret != 0)) {
+ vmw_validation_preload_bo(sw_context->ctx);
+ vmw_bo = vmw_user_bo_noref_lookup(sw_context->fp->tfile, handle);
+ if (IS_ERR(vmw_bo)) {
DRM_ERROR("Could not find or use MOB buffer.\n");
- ret = -EINVAL;
- goto out_no_reloc;
+ return PTR_ERR(vmw_bo);
}
- if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
- DRM_ERROR("Max number relocations per submission"
- " exceeded\n");
- ret = -EINVAL;
- goto out_no_reloc;
- }
+ ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);
+ vmw_user_bo_noref_release();
+ if (unlikely(ret != 0))
+ return ret;
- reloc = &sw_context->relocs[sw_context->cur_reloc++];
- reloc->mob_loc = id;
- reloc->location = NULL;
+ reloc = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*reloc));
+ if (!reloc)
+ return -ENOMEM;
- ret = vmw_bo_to_validate_list(sw_context, vmw_bo, true, &reloc->index);
- if (unlikely(ret != 0))
- goto out_no_reloc;
+ reloc->mob_loc = id;
+ reloc->vbo = vmw_bo;
*vmw_bo_p = vmw_bo;
- return 0;
+ list_add_tail(&reloc->head, &sw_context->bo_relocations);
-out_no_reloc:
- vmw_bo_unreference(&vmw_bo);
- *vmw_bo_p = NULL;
- return ret;
+ return 0;
}
/**
@@ -1328,7 +1191,7 @@ out_no_reloc:
* @sw_context: The software context used for this command batch validation.
* @ptr: Pointer to the user-space handle to be translated.
* @vmw_bo_p: Points to a location that, on successful return will carry
- * a reference-counted pointer to the DMA buffer identified by the
+ * a non-reference-counted pointer to the DMA buffer identified by the
* user-space handle in @id.
*
* This function saves information needed to translate a user-space buffer
@@ -1344,39 +1207,33 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
SVGAGuestPtr *ptr,
struct vmw_buffer_object **vmw_bo_p)
{
- struct vmw_buffer_object *vmw_bo = NULL;
+ struct vmw_buffer_object *vmw_bo;
uint32_t handle = ptr->gmrId;
struct vmw_relocation *reloc;
int ret;
- ret = vmw_user_bo_lookup(sw_context->fp->tfile, handle, &vmw_bo, NULL);
- if (unlikely(ret != 0)) {
+ vmw_validation_preload_bo(sw_context->ctx);
+ vmw_bo = vmw_user_bo_noref_lookup(sw_context->fp->tfile, handle);
+ if (IS_ERR(vmw_bo)) {
DRM_ERROR("Could not find or use GMR region.\n");
- ret = -EINVAL;
- goto out_no_reloc;
- }
-
- if (unlikely(sw_context->cur_reloc >= VMWGFX_MAX_RELOCATIONS)) {
- DRM_ERROR("Max number relocations per submission"
- " exceeded\n");
- ret = -EINVAL;
- goto out_no_reloc;
+ return PTR_ERR(vmw_bo);
}
- reloc = &sw_context->relocs[sw_context->cur_reloc++];
- reloc->location = ptr;
-
- ret = vmw_bo_to_validate_list(sw_context, vmw_bo, false, &reloc->index);
+ ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);
+ vmw_user_bo_noref_release();
if (unlikely(ret != 0))
- goto out_no_reloc;
+ return ret;
+
+ reloc = vmw_validation_mem_alloc(sw_context->ctx, sizeof(*reloc));
+ if (!reloc)
+ return -ENOMEM;
+ reloc->location = ptr;
+ reloc->vbo = vmw_bo;
*vmw_bo_p = vmw_bo;
- return 0;
+ list_add_tail(&reloc->head, &sw_context->bo_relocations);
-out_no_reloc:
- vmw_bo_unreference(&vmw_bo);
- *vmw_bo_p = NULL;
- return ret;
+ return 0;
}
@@ -1400,7 +1257,7 @@ static int vmw_cmd_dx_define_query(struct vmw_private *dev_priv,
} *cmd;
int ret;
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_resource *cotable_res;
@@ -1415,9 +1272,8 @@ static int vmw_cmd_dx_define_query(struct vmw_private *dev_priv,
cmd->q.type >= SVGA3D_QUERYTYPE_MAX)
return -EINVAL;
- cotable_res = vmw_context_cotable(ctx_node->res, SVGA_COTABLE_DXQUERY);
+ cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY);
ret = vmw_cotable_notify(cotable_res, cmd->q.queryId);
- vmw_resource_unreference(&cotable_res);
return ret;
}
@@ -1462,11 +1318,8 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv,
return ret;
sw_context->dx_query_mob = vmw_bo;
- sw_context->dx_query_ctx = sw_context->dx_ctx_node->res;
-
- vmw_bo_unreference(&vmw_bo);
-
- return ret;
+ sw_context->dx_query_ctx = sw_context->dx_ctx_node->ctx;
+ return 0;
}
@@ -1567,7 +1420,6 @@ static int vmw_cmd_end_gb_query(struct vmw_private *dev_priv,
ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context);
- vmw_bo_unreference(&vmw_bo);
return ret;
}
@@ -1621,7 +1473,6 @@ static int vmw_cmd_end_query(struct vmw_private *dev_priv,
ret = vmw_query_bo_switch_prepare(dev_priv, vmw_bo, sw_context);
- vmw_bo_unreference(&vmw_bo);
return ret;
}
@@ -1654,7 +1505,6 @@ static int vmw_cmd_wait_gb_query(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
return ret;
- vmw_bo_unreference(&vmw_bo);
return 0;
}
@@ -1706,7 +1556,6 @@ static int vmw_cmd_wait_query(struct vmw_private *dev_priv,
if (unlikely(ret != 0))
return ret;
- vmw_bo_unreference(&vmw_bo);
return 0;
}
@@ -1757,7 +1606,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
if (unlikely(ret != 0)) {
if (unlikely(ret != -ERESTARTSYS))
DRM_ERROR("could not find surface for DMA.\n");
- goto out_no_surface;
+ return ret;
}
srf = vmw_res_to_srf(sw_context->res_cache[vmw_res_surface].res);
@@ -1765,9 +1614,7 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
vmw_kms_cursor_snoop(srf, sw_context->fp->tfile, &vmw_bo->base,
header);
-out_no_surface:
- vmw_bo_unreference(&vmw_bo);
- return ret;
+ return 0;
}
static int vmw_cmd_draw(struct vmw_private *dev_priv,
@@ -1837,8 +1684,8 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
((unsigned long) header + header->size + sizeof(header));
SVGA3dTextureState *cur_state = (SVGA3dTextureState *)
((unsigned long) header + sizeof(struct vmw_tex_state_cmd));
- struct vmw_resource_val_node *ctx_node;
- struct vmw_resource_val_node *res_node;
+ struct vmw_resource *ctx;
+ struct vmw_resource *res;
int ret;
cmd = container_of(header, struct vmw_tex_state_cmd,
@@ -1846,7 +1693,7 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->state.cid,
- &ctx_node);
+ &ctx);
if (unlikely(ret != 0))
return ret;
@@ -1862,19 +1709,24 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv,
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
- &cur_state->value, &res_node);
+ &cur_state->value, &res);
if (unlikely(ret != 0))
return ret;
if (dev_priv->has_mob) {
struct vmw_ctx_bindinfo_tex binding;
+ struct vmw_ctx_validation_info *node;
+
+ node = vmw_execbuf_info_from_res(sw_context, ctx);
+ if (!node)
+ return -EINVAL;
- binding.bi.ctx = ctx_node->res;
- binding.bi.res = res_node ? res_node->res : NULL;
+ binding.bi.ctx = ctx;
+ binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_tex;
binding.texture_stage = cur_state->stage;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
- 0, binding.texture_stage);
+ vmw_binding_add(node->staged, &binding.bi, 0,
+ binding.texture_stage);
}
}
@@ -1893,14 +1745,9 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
SVGAFifoCmdDefineGMRFB body;
} *cmd = buf;
- ret = vmw_translate_guest_ptr(dev_priv, sw_context,
- &cmd->body.ptr,
- &vmw_bo);
- if (unlikely(ret != 0))
- return ret;
-
- vmw_bo_unreference(&vmw_bo);
-
+ return vmw_translate_guest_ptr(dev_priv, sw_context,
+ &cmd->body.ptr,
+ &vmw_bo);
return ret;
}
@@ -1922,25 +1769,24 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv,
*/
static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
- struct vmw_resource_val_node *val_node,
+ struct vmw_resource *res,
uint32_t *buf_id,
unsigned long backup_offset)
{
- struct vmw_buffer_object *dma_buf;
+ struct vmw_buffer_object *vbo;
+ void *info;
int ret;
- ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf);
+ info = vmw_execbuf_info_from_res(sw_context, res);
+ if (!info)
+ return -EINVAL;
+
+ ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &vbo);
if (ret)
return ret;
- val_node->switching_backup = true;
- if (val_node->first_usage)
- val_node->no_buffer_needed = true;
-
- vmw_bo_unreference(&val_node->new_backup);
- val_node->new_backup = dma_buf;
- val_node->new_backup_offset = backup_offset;
-
+ vmw_validation_res_switch_backup(sw_context->ctx, info, vbo,
+ backup_offset);
return 0;
}
@@ -1970,15 +1816,15 @@ static int vmw_cmd_switch_backup(struct vmw_private *dev_priv,
uint32_t *buf_id,
unsigned long backup_offset)
{
- struct vmw_resource_val_node *val_node;
+ struct vmw_resource *res;
int ret;
ret = vmw_cmd_res_check(dev_priv, sw_context, res_type,
- converter, res_id, &val_node);
+ converter, res_id, &res);
if (ret)
return ret;
- return vmw_cmd_res_switch_backup(dev_priv, sw_context, val_node,
+ return vmw_cmd_res_switch_backup(dev_priv, sw_context, res,
buf_id, backup_offset);
}
@@ -2170,14 +2016,14 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
} *cmd;
int ret;
size_t size;
- struct vmw_resource_val_node *val;
+ struct vmw_resource *ctx;
cmd = container_of(header, struct vmw_shader_define_cmd,
header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->body.cid,
- &val);
+ &ctx);
if (unlikely(ret != 0))
return ret;
@@ -2186,14 +2032,14 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv,
size = cmd->header.size - sizeof(cmd->body);
ret = vmw_compat_shader_add(dev_priv,
- vmw_context_res_man(val->res),
+ vmw_context_res_man(ctx),
cmd->body.shid, cmd + 1,
cmd->body.type, size,
&sw_context->staged_cmd_res);
if (unlikely(ret != 0))
return ret;
- return vmw_resource_relocation_add(&sw_context->res_relocations,
+ return vmw_resource_relocation_add(sw_context,
NULL,
vmw_ptr_diff(sw_context->buf_start,
&cmd->header.id),
@@ -2217,28 +2063,28 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv,
SVGA3dCmdDestroyShader body;
} *cmd;
int ret;
- struct vmw_resource_val_node *val;
+ struct vmw_resource *ctx;
cmd = container_of(header, struct vmw_shader_destroy_cmd,
header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->body.cid,
- &val);
+ &ctx);
if (unlikely(ret != 0))
return ret;
if (unlikely(!dev_priv->has_mob))
return 0;
- ret = vmw_shader_remove(vmw_context_res_man(val->res),
+ ret = vmw_shader_remove(vmw_context_res_man(ctx),
cmd->body.shid,
cmd->body.type,
&sw_context->staged_cmd_res);
if (unlikely(ret != 0))
return ret;
- return vmw_resource_relocation_add(&sw_context->res_relocations,
+ return vmw_resource_relocation_add(sw_context,
NULL,
vmw_ptr_diff(sw_context->buf_start,
&cmd->header.id),
@@ -2261,9 +2107,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
SVGA3dCmdHeader header;
SVGA3dCmdSetShader body;
} *cmd;
- struct vmw_resource_val_node *ctx_node, *res_node = NULL;
struct vmw_ctx_bindinfo_shader binding;
- struct vmw_resource *res = NULL;
+ struct vmw_resource *ctx, *res = NULL;
+ struct vmw_ctx_validation_info *ctx_info;
int ret;
cmd = container_of(header, struct vmw_set_shader_cmd,
@@ -2277,7 +2123,7 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter, &cmd->body.cid,
- &ctx_node);
+ &ctx);
if (unlikely(ret != 0))
return ret;
@@ -2285,34 +2131,35 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv,
return 0;
if (cmd->body.shid != SVGA3D_INVALID_ID) {
- res = vmw_shader_lookup(vmw_context_res_man(ctx_node->res),
+ res = vmw_shader_lookup(vmw_context_res_man(ctx),
cmd->body.shid,
cmd->body.type);
if (!IS_ERR(res)) {
- ret = vmw_cmd_res_reloc_add(dev_priv, sw_context,
- &cmd->body.shid, res,
- &res_node);
- vmw_resource_unreference(&res);
+ ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
if (unlikely(ret != 0))
return ret;
}
}
- if (!res_node) {
+ if (IS_ERR_OR_NULL(res)) {
ret = vmw_cmd_res_check(dev_priv, sw_context,
vmw_res_shader,
user_shader_converter,
- &cmd->body.shid, &res_node);
+ &cmd->body.shid, &res);
if (unlikely(ret != 0))
return ret;
}
- binding.bi.ctx = ctx_node->res;
- binding.bi.res = res_node ? res_node->res : NULL;
+ ctx_info = vmw_execbuf_info_from_res(sw_context, ctx);
+ if (!ctx_info)
+ return -EINVAL;
+
+ binding.bi.ctx = ctx;
+ binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_shader;
binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
+ vmw_binding_add(ctx_info->staged, &binding.bi,
binding.shader_slot, 0);
return 0;
}
@@ -2393,8 +2240,8 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
SVGA3dCmdHeader header;
SVGA3dCmdDXSetSingleConstantBuffer body;
} *cmd;
- struct vmw_resource_val_node *res_node = NULL;
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_resource *res = NULL;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_ctx_bindinfo_cb binding;
int ret;
@@ -2406,12 +2253,12 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
cmd = container_of(header, typeof(*cmd), header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
- &cmd->body.sid, &res_node);
+ &cmd->body.sid, &res);
if (unlikely(ret != 0))
return ret;
- binding.bi.ctx = ctx_node->res;
- binding.bi.res = res_node ? res_node->res : NULL;
+ binding.bi.ctx = ctx_node->ctx;
+ binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_cb;
binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN;
binding.offset = cmd->body.offsetInBytes;
@@ -2426,7 +2273,7 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv,
return -EINVAL;
}
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
+ vmw_binding_add(ctx_node->staged, &binding.bi,
binding.shader_slot, binding.slot);
return 0;
@@ -2482,7 +2329,7 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
SVGA3dCmdDXSetShader body;
} *cmd;
struct vmw_resource *res = NULL;
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_ctx_bindinfo_shader binding;
int ret = 0;
@@ -2506,23 +2353,20 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv,
return PTR_ERR(res);
}
- ret = vmw_resource_val_add(sw_context, res, NULL);
+ ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
if (ret)
- goto out_unref;
+ return ret;
}
- binding.bi.ctx = ctx_node->res;
+ binding.bi.ctx = ctx_node->ctx;
binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_dx_shader;
binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
+ vmw_binding_add(ctx_node->staged, &binding.bi,
binding.shader_slot, 0);
-out_unref:
- if (res)
- vmw_resource_unreference(&res);
- return ret;
+ return 0;
}
/**
@@ -2537,9 +2381,9 @@ static int vmw_cmd_dx_set_vertex_buffers(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_ctx_bindinfo_vb binding;
- struct vmw_resource_val_node *res_node;
+ struct vmw_resource *res;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetVertexBuffers body;
@@ -2564,18 +2408,18 @@ static int vmw_cmd_dx_set_vertex_buffers(struct vmw_private *dev_priv,
for (i = 0; i < num; i++) {
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
- &cmd->buf[i].sid, &res_node);
+ &cmd->buf[i].sid, &res);
if (unlikely(ret != 0))
return ret;
- binding.bi.ctx = ctx_node->res;
+ binding.bi.ctx = ctx_node->ctx;
binding.bi.bt = vmw_ctx_binding_vb;
- binding.bi.res = ((res_node) ? res_node->res : NULL);
+ binding.bi.res = res;
binding.offset = cmd->buf[i].offset;
binding.stride = cmd->buf[i].stride;
binding.slot = i + cmd->body.startBuffer;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
+ vmw_binding_add(ctx_node->staged, &binding.bi,
0, binding.slot);
}
@@ -2594,9 +2438,9 @@ static int vmw_cmd_dx_set_index_buffer(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_ctx_bindinfo_ib binding;
- struct vmw_resource_val_node *res_node;
+ struct vmw_resource *res;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetIndexBuffer body;
@@ -2611,17 +2455,17 @@ static int vmw_cmd_dx_set_index_buffer(struct vmw_private *dev_priv,
cmd = container_of(header, typeof(*cmd), header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
- &cmd->body.sid, &res_node);
+ &cmd->body.sid, &res);
if (unlikely(ret != 0))
return ret;
- binding.bi.ctx = ctx_node->res;
- binding.bi.res = ((res_node) ? res_node->res : NULL);
+ binding.bi.ctx = ctx_node->ctx;
+ binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_ib;
binding.offset = cmd->body.offset;
binding.format = cmd->body.format;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi, 0, 0);
+ vmw_binding_add(ctx_node->staged, &binding.bi, 0, 0);
return 0;
}
@@ -2679,8 +2523,8 @@ static int vmw_cmd_dx_clear_rendertarget_view(struct vmw_private *dev_priv,
SVGA3dCmdDXClearRenderTargetView body;
} *cmd = container_of(header, typeof(*cmd), header);
- return vmw_view_id_val_add(sw_context, vmw_view_rt,
- cmd->body.renderTargetViewId);
+ return PTR_RET(vmw_view_id_val_add(sw_context, vmw_view_rt,
+ cmd->body.renderTargetViewId));
}
/**
@@ -2700,16 +2544,16 @@ static int vmw_cmd_dx_clear_depthstencil_view(struct vmw_private *dev_priv,
SVGA3dCmdDXClearDepthStencilView body;
} *cmd = container_of(header, typeof(*cmd), header);
- return vmw_view_id_val_add(sw_context, vmw_view_ds,
- cmd->body.depthStencilViewId);
+ return PTR_RET(vmw_view_id_val_add(sw_context, vmw_view_ds,
+ cmd->body.depthStencilViewId));
}
static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
- struct vmw_resource_val_node *srf_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_resource *srf;
struct vmw_resource *res;
enum vmw_view_type view_type;
int ret;
@@ -2734,19 +2578,18 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv,
cmd = container_of(header, typeof(*cmd), header);
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
- &cmd->sid, &srf_node);
+ &cmd->sid, &srf);
if (unlikely(ret != 0))
return ret;
- res = vmw_context_cotable(ctx_node->res, vmw_view_cotables[view_type]);
+ res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]);
ret = vmw_cotable_notify(res, cmd->defined_id);
- vmw_resource_unreference(&res);
if (unlikely(ret != 0))
return ret;
return vmw_view_add(sw_context->man,
- ctx_node->res,
- srf_node->res,
+ ctx_node->ctx,
+ srf,
view_type,
cmd->defined_id,
header,
@@ -2766,9 +2609,9 @@ static int vmw_cmd_dx_set_so_targets(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_ctx_bindinfo_so binding;
- struct vmw_resource_val_node *res_node;
+ struct vmw_resource *res;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXSetSOTargets body;
@@ -2793,18 +2636,18 @@ static int vmw_cmd_dx_set_so_targets(struct vmw_private *dev_priv,
for (i = 0; i < num; i++) {
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface,
user_surface_converter,
- &cmd->targets[i].sid, &res_node);
+ &cmd->targets[i].sid, &res);
if (unlikely(ret != 0))
return ret;
- binding.bi.ctx = ctx_node->res;
- binding.bi.res = ((res_node) ? res_node->res : NULL);
+ binding.bi.ctx = ctx_node->ctx;
+ binding.bi.res = res;
binding.bi.bt = vmw_ctx_binding_so,
binding.offset = cmd->targets[i].offset;
binding.size = cmd->targets[i].sizeInBytes;
binding.slot = i;
- vmw_binding_add(ctx_node->staged_bindings, &binding.bi,
+ vmw_binding_add(ctx_node->staged, &binding.bi,
0, binding.slot);
}
@@ -2815,7 +2658,7 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_resource *res;
/*
* This is based on the fact that all affected define commands have
@@ -2834,10 +2677,9 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv,
}
so_type = vmw_so_cmd_to_type(header->id);
- res = vmw_context_cotable(ctx_node->res, vmw_so_cotables[so_type]);
+ res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]);
cmd = container_of(header, typeof(*cmd), header);
ret = vmw_cotable_notify(res, cmd->defined_id);
- vmw_resource_unreference(&res);
return ret;
}
@@ -2882,7 +2724,7 @@ static int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
if (unlikely(ctx_node == NULL)) {
DRM_ERROR("DX Context not set.\n");
@@ -2907,7 +2749,7 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct {
SVGA3dCmdHeader header;
union vmw_view_destroy body;
@@ -2934,7 +2776,7 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv,
* relocation to conditionally make this command a NOP to avoid
* device errors.
*/
- return vmw_resource_relocation_add(&sw_context->res_relocations,
+ return vmw_resource_relocation_add(sw_context,
view,
vmw_ptr_diff(sw_context->buf_start,
&cmd->header.id),
@@ -2953,7 +2795,7 @@ static int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct vmw_resource *res;
struct {
SVGA3dCmdHeader header;
@@ -2966,13 +2808,12 @@ static int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv,
return -EINVAL;
}
- res = vmw_context_cotable(ctx_node->res, SVGA_COTABLE_DXSHADER);
+ res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER);
ret = vmw_cotable_notify(res, cmd->body.shaderId);
- vmw_resource_unreference(&res);
if (ret)
return ret;
- return vmw_dx_shader_add(sw_context->man, ctx_node->res,
+ return vmw_dx_shader_add(sw_context->man, ctx_node->ctx,
cmd->body.shaderId, cmd->body.type,
&sw_context->staged_cmd_res);
}
@@ -2989,7 +2830,7 @@ static int vmw_cmd_dx_destroy_shader(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node;
+ struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node;
struct {
SVGA3dCmdHeader header;
SVGA3dCmdDXDestroyShader body;
@@ -3021,8 +2862,7 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- struct vmw_resource_val_node *ctx_node;
- struct vmw_resource_val_node *res_node;
+ struct vmw_resource *ctx;
struct vmw_resource *res;
struct {
SVGA3dCmdHeader header;
@@ -3033,38 +2873,33 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv,
if (cmd->body.cid != SVGA3D_INVALID_ID) {
ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context,
user_context_converter,
- &cmd->body.cid, &ctx_node);
+ &cmd->body.cid, &ctx);
if (ret)
return ret;
} else {
- ctx_node = sw_context->dx_ctx_node;
- if (!ctx_node) {
+ if (!sw_context->dx_ctx_node) {
DRM_ERROR("DX Context not set.\n");
return -EINVAL;
}
+ ctx = sw_context->dx_ctx_node->ctx;
}
- res = vmw_shader_lookup(vmw_context_res_man(ctx_node->res),
+ res = vmw_shader_lookup(vmw_context_res_man(ctx),
cmd->body.shid, 0);
if (IS_ERR(res)) {
DRM_ERROR("Could not find shader to bind.\n");
return PTR_ERR(res);
}
- ret = vmw_resource_val_add(sw_context, res, &res_node);
+ ret = vmw_execbuf_res_noctx_val_add(sw_context, res);
if (ret) {
DRM_ERROR("Error creating resource validation node.\n");
- goto out_unref;
+ return ret;
}
-
- ret = vmw_cmd_res_switch_backup(dev_priv, sw_context, res_node,
- &cmd->body.mobid,
- cmd->body.offsetInBytes);
-out_unref:
- vmw_resource_unreference(&res);
-
- return ret;
+ return vmw_cmd_res_switch_backup(dev_priv, sw_context, res,
+ &cmd->body.mobid,
+ cmd->body.offsetInBytes);
}
/**
@@ -3083,8 +2918,8 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv,
SVGA3dCmdDXGenMips body;
} *cmd = container_of(header, typeof(*cmd), header);
- return vmw_view_id_val_add(sw_context, vmw_view_sr,
- cmd->body.shaderResourceViewId);
+ return PTR_RET(vmw_view_id_val_add(sw_context, vmw_view_sr,
+ cmd->body.shaderResourceViewId));
}
/**
@@ -3638,20 +3473,18 @@ static int vmw_cmd_check_all(struct vmw_private *dev_priv,
static void vmw_free_relocations(struct vmw_sw_context *sw_context)
{
- sw_context->cur_reloc = 0;
+ /* Memory is validation context memory, so no need to free it */
+
+ INIT_LIST_HEAD(&sw_context->bo_relocations);
}
static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
{
- uint32_t i;
struct vmw_relocation *reloc;
- struct ttm_validate_buffer *validate;
struct ttm_buffer_object *bo;
- for (i = 0; i < sw_context->cur_reloc; ++i) {
- reloc = &sw_context->relocs[i];
- validate = &sw_context->val_bufs[reloc->index].base;
- bo = validate->bo;
+ list_for_each_entry(reloc, &sw_context->bo_relocations, head) {
+ bo = &reloc->vbo->base;
switch (bo->mem.mem_type) {
case TTM_PL_VRAM:
reloc->location->offset += bo->offset;
@@ -3670,110 +3503,6 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context)
vmw_free_relocations(sw_context);
}
-/**
- * vmw_resource_list_unrefererence - Free up a resource list and unreference
- * all resources referenced by it.
- *
- * @list: The resource list.
- */
-static void vmw_resource_list_unreference(struct vmw_sw_context *sw_context,
- struct list_head *list)
-{
- struct vmw_resource_val_node *val, *val_next;
-
- /*
- * Drop references to resources held during command submission.
- */
-
- list_for_each_entry_safe(val, val_next, list, head) {
- list_del_init(&val->head);
- vmw_resource_unreference(&val->res);
-
- if (val->staged_bindings) {
- if (val->staged_bindings != sw_context->staged_bindings)
- vmw_binding_state_free(val->staged_bindings);
- else
- sw_context->staged_bindings_inuse = false;
- val->staged_bindings = NULL;
- }
-
- kfree(val);
- }
-}
-
-static void vmw_clear_validations(struct vmw_sw_context *sw_context)
-{
- struct vmw_validate_buffer *entry, *next;
- struct vmw_resource_val_node *val;
-
- /*
- * Drop references to DMA buffers held during command submission.
- */
- list_for_each_entry_safe(entry, next, &sw_context->validate_nodes,
- base.head) {
- list_del(&entry->base.head);
- ttm_bo_unref(&entry->base.bo);
- (void) drm_ht_remove_item(&sw_context->res_ht, &entry->hash);
- sw_context->cur_val_buf--;
- }
- BUG_ON(sw_context->cur_val_buf != 0);
-
- list_for_each_entry(val, &sw_context->resource_list, head)
- (void) drm_ht_remove_item(&sw_context->res_ht, &val->hash);
-}
-
-int vmw_validate_single_buffer(struct vmw_private *dev_priv,
- struct ttm_buffer_object *bo,
- bool interruptible,
- bool validate_as_mob)
-{
- struct vmw_buffer_object *vbo =
- container_of(bo, struct vmw_buffer_object, base);
- struct ttm_operation_ctx ctx = { interruptible, false };
- int ret;
-
- if (vbo->pin_count > 0)
- return 0;
-
- if (validate_as_mob)
- return ttm_bo_validate(bo, &vmw_mob_placement, &ctx);
-
- /**
- * Put BO in VRAM if there is space, otherwise as a GMR.
- * If there is no space in VRAM and GMR ids are all used up,
- * start evicting GMRs to make room. If the DMA buffer can't be
- * used as a GMR, this will return -ENOMEM.
- */
-
- ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx);
- if (likely(ret == 0 || ret == -ERESTARTSYS))
- return ret;
-
- /**
- * If that failed, try VRAM again, this time evicting
- * previous contents.
- */
-
- ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx);
- return ret;
-}
-
-static int vmw_validate_buffers(struct vmw_private *dev_priv,
- struct vmw_sw_context *sw_context)
-{
- struct vmw_validate_buffer *entry;
- int ret;
-
- list_for_each_entry(entry, &sw_context->validate_nodes, base.head) {
- ret = vmw_validate_single_buffer(dev_priv, entry->base.bo,
- true,
- entry->validate_as_mob);
- if (unlikely(ret != 0))
- return ret;
- }
- return 0;
-}
-
static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context,
uint32_t size)
{
@@ -3946,7 +3675,7 @@ static int vmw_execbuf_submit_fifo(struct vmw_private *dev_priv,
if (sw_context->dx_ctx_node)
cmd = vmw_fifo_reserve_dx(dev_priv, command_size,
- sw_context->dx_ctx_node->res->id);
+ sw_context->dx_ctx_node->ctx->id);
else
cmd = vmw_fifo_reserve(dev_priv, command_size);
if (!cmd) {
@@ -3980,7 +3709,7 @@ static int vmw_execbuf_submit_cmdbuf(struct vmw_private *dev_priv,
u32 command_size,
struct vmw_sw_context *sw_context)
{
- u32 id = ((sw_context->dx_ctx_node) ? sw_context->dx_ctx_node->res->id :
+ u32 id = ((sw_context->dx_ctx_node) ? sw_context->dx_ctx_node->ctx->id :
SVGA3D_INVALID_ID);
void *cmd = vmw_cmdbuf_reserve(dev_priv->cman, command_size,
id, false, header);
@@ -4057,31 +3786,35 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
uint32_t handle)
{
- struct vmw_resource_val_node *ctx_node;
struct vmw_resource *res;
int ret;
+ unsigned int size;
if (handle == SVGA3D_INVALID_ID)
return 0;
- ret = vmw_user_resource_lookup_handle(dev_priv, sw_context->fp->tfile,
- handle, user_context_converter,
- &res);
- if (unlikely(ret != 0)) {
+ size = vmw_execbuf_res_size(dev_priv, vmw_res_dx_context);
+ ret = vmw_validation_preload_res(sw_context->ctx, size);
+ if (ret)
+ return ret;
+
+ res = vmw_user_resource_noref_lookup_handle
+ (dev_priv, sw_context->fp->tfile, handle,
+ user_context_converter);
+ if (unlikely(IS_ERR(res))) {
DRM_ERROR("Could not find or user DX context 0x%08x.\n",
(unsigned) handle);
- return ret;
+ return PTR_ERR(res);
}
- ret = vmw_resource_val_add(sw_context, res, &ctx_node);
+ ret = vmw_execbuf_res_noref_val_add(sw_context, res);
if (unlikely(ret != 0))
- goto out_err;
+ return ret;
- sw_context->dx_ctx_node = ctx_node;
+ sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res);
sw_context->man = vmw_context_res_man(res);
-out_err:
- vmw_resource_unreference(&res);
- return ret;
+
+ return 0;
}
int vmw_execbuf_process(struct drm_file *file_priv,
@@ -4097,15 +3830,12 @@ int vmw_execbuf_process(struct drm_file *file_priv,
{
struct vmw_sw_context *sw_context = &dev_priv->ctx;
struct vmw_fence_obj *fence = NULL;
- struct vmw_resource *error_resource;
- struct list_head resource_list;
struct vmw_cmdbuf_header *header;
- struct ww_acquire_ctx ticket;
uint32_t handle;
int ret;
int32_t out_fence_fd = -1;
struct sync_file *sync_file = NULL;
-
+ DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1);
if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
@@ -4157,10 +3887,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
sw_context->kernel = true;
sw_context->fp = vmw_fpriv(file_priv);
- sw_context->cur_reloc = 0;
- sw_context->cur_val_buf = 0;
- INIT_LIST_HEAD(&sw_context->resource_list);
- INIT_LIST_HEAD(&sw_context->ctx_resource_list);
+ INIT_LIST_HEAD(&sw_context->ctx_list);
sw_context->cur_query_bo = dev_priv->pinned_bo;
sw_context->last_query_ctx = NULL;
sw_context->needs_post_query_barrier = false;
@@ -4168,8 +3895,8 @@ int vmw_execbuf_process(struct drm_file *file_priv,
sw_context->dx_query_mob = NULL;
sw_context->dx_query_ctx = NULL;
memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache));
- INIT_LIST_HEAD(&sw_context->validate_nodes);
INIT_LIST_HEAD(&sw_context->res_relocations);
+ INIT_LIST_HEAD(&sw_context->bo_relocations);
if (sw_context->staged_bindings)
vmw_binding_state_reset(sw_context->staged_bindings);
@@ -4180,24 +3907,13 @@ int vmw_execbuf_process(struct drm_file *file_priv,
sw_context->res_ht_initialized = true;
}
INIT_LIST_HEAD(&sw_context->staged_cmd_res);
- INIT_LIST_HEAD(&resource_list);
+ sw_context->ctx = &val_ctx;
ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle);
- if (unlikely(ret != 0)) {
- list_splice_init(&sw_context->ctx_resource_list,
- &sw_context->resource_list);
+ if (unlikely(ret != 0))
goto out_err_nores;
- }
ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands,
command_size);
- /*
- * Merge the resource lists before checking the return status
- * from vmd_cmd_check_all so that all the open hashtabs will
- * be handled properly even if vmw_cmd_check_all fails.
- */
- list_splice_init(&sw_context->ctx_resource_list,
- &sw_context->resource_list);
-
if (unlikely(ret != 0))
goto out_err_nores;
@@ -4205,18 +3921,18 @@ int vmw_execbuf_process(struct drm_file *file_priv,
if (unlikely(ret != 0))
goto out_err_nores;
- ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes,
- true, NULL);
+ ret = vmw_validation_bo_reserve(&val_ctx, true);
if (unlikely(ret != 0))
goto out_err_nores;
- ret = vmw_validate_buffers(dev_priv, sw_context);
+ ret = vmw_validation_bo_validate(&val_ctx, true);
if (unlikely(ret != 0))
goto out_err;
- ret = vmw_resources_validate(sw_context);
+ ret = vmw_validation_res_validate(&val_ctx, true);
if (unlikely(ret != 0))
goto out_err;
+ vmw_validation_drop_ht(&val_ctx);
ret = mutex_lock_interruptible(&dev_priv->binding_mutex);
if (unlikely(ret != 0)) {
@@ -4255,17 +3971,16 @@ int vmw_execbuf_process(struct drm_file *file_priv,
if (ret != 0)
DRM_ERROR("Fence submission error. Syncing.\n");
- vmw_resources_unreserve(sw_context, false);
+ vmw_execbuf_bindings_commit(sw_context, false);
+ vmw_bind_dx_query_mob(sw_context);
+ vmw_validation_res_unreserve(&val_ctx, false);
- ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes,
- (void *) fence);
+ vmw_validation_bo_fence(sw_context->ctx, fence);
if (unlikely(dev_priv->pinned_bo != NULL &&
!dev_priv->query_cid_valid))
__vmw_execbuf_release_pinned_bo(dev_priv, fence);
- vmw_clear_validations(sw_context);
-
/*
* If anything fails here, give up trying to export the fence
* and do a sync since the user mode will not be able to sync
@@ -4300,7 +4015,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
vmw_fence_obj_unreference(&fence);
}
- list_splice_init(&sw_context->resource_list, &resource_list);
vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res);
mutex_unlock(&dev_priv->cmdbuf_mutex);
@@ -4308,36 +4022,33 @@ int vmw_execbuf_process(struct drm_file *file_priv,
* Unreference resources outside of the cmdbuf_mutex to
* avoid deadlocks in resource destruction paths.
*/
- vmw_resource_list_unreference(sw_context, &resource_list);
+ vmw_validation_unref_lists(&val_ctx);
return 0;
out_unlock_binding:
mutex_unlock(&dev_priv->binding_mutex);
out_err:
- ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes);
+ vmw_validation_bo_backoff(&val_ctx);
out_err_nores:
- vmw_resources_unreserve(sw_context, true);
+ vmw_execbuf_bindings_commit(sw_context, true);
+ vmw_validation_res_unreserve(&val_ctx, true);
vmw_resource_relocations_free(&sw_context->res_relocations);
vmw_free_relocations(sw_context);
- vmw_clear_validations(sw_context);
if (unlikely(dev_priv->pinned_bo != NULL &&
!dev_priv->query_cid_valid))
__vmw_execbuf_release_pinned_bo(dev_priv, NULL);
out_unlock:
- list_splice_init(&sw_context->resource_list, &resource_list);
- error_resource = sw_context->error_resource;
- sw_context->error_resource = NULL;
vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res);
+ vmw_validation_drop_ht(&val_ctx);
+ WARN_ON(!list_empty(&sw_context->ctx_list));
mutex_unlock(&dev_priv->cmdbuf_mutex);
/*
* Unreference resources outside of the cmdbuf_mutex to
* avoid deadlocks in resource destruction paths.
*/
- vmw_resource_list_unreference(sw_context, &resource_list);
- if (unlikely(error_resource != NULL))
- vmw_resource_unreference(&error_resource);
+ vmw_validation_unref_lists(&val_ctx);
out_free_header:
if (header)
vmw_cmdbuf_header_free(header);
@@ -4398,38 +4109,31 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
struct vmw_fence_obj *fence)
{
int ret = 0;
- struct list_head validate_list;
- struct ttm_validate_buffer pinned_val, query_val;
struct vmw_fence_obj *lfence = NULL;
- struct ww_acquire_ctx ticket;
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
if (dev_priv->pinned_bo == NULL)
goto out_unlock;
- INIT_LIST_HEAD(&validate_list);
-
- pinned_val.bo = ttm_bo_reference(&dev_priv->pinned_bo->base);
- pinned_val.shared = false;
- list_add_tail(&pinned_val.head, &validate_list);
+ ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false,
+ false);
+ if (ret)
+ goto out_no_reserve;
- query_val.bo = ttm_bo_reference(&dev_priv->dummy_query_bo->base);
- query_val.shared = false;
- list_add_tail(&query_val.head, &validate_list);
+ ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false,
+ false);
+ if (ret)
+ goto out_no_reserve;
- ret = ttm_eu_reserve_buffers(&ticket, &validate_list,
- false, NULL);
- if (unlikely(ret != 0)) {
- vmw_execbuf_unpin_panic(dev_priv);
+ ret = vmw_validation_bo_reserve(&val_ctx, false);
+ if (ret)
goto out_no_reserve;
- }
if (dev_priv->query_cid_valid) {
BUG_ON(fence != NULL);
ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid);
- if (unlikely(ret != 0)) {
- vmw_execbuf_unpin_panic(dev_priv);
+ if (ret)
goto out_no_emit;
- }
dev_priv->query_cid_valid = false;
}
@@ -4443,22 +4147,22 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv,
NULL);
fence = lfence;
}
- ttm_eu_fence_buffer_objects(&ticket, &validate_list, (void *) fence);
+ vmw_validation_bo_fence(&val_ctx, fence);
if (lfence != NULL)
vmw_fence_obj_unreference(&lfence);
- ttm_bo_unref(&query_val.bo);
- ttm_bo_unref(&pinned_val.bo);
+ vmw_validation_unref_lists(&val_ctx);
vmw_bo_unreference(&dev_priv->pinned_bo);
out_unlock:
return;
out_no_emit:
- ttm_eu_backoff_reservation(&ticket, &validate_list);
+ vmw_validation_bo_backoff(&val_ctx);
out_no_reserve:
- ttm_bo_unref(&query_val.bo);
- ttm_bo_unref(&pinned_val.bo);
+ vmw_validation_unref_lists(&val_ctx);
+ vmw_execbuf_unpin_panic(dev_priv);
vmw_bo_unreference(&dev_priv->pinned_bo);
+
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 3d546d409334..f87261545f2c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -306,7 +306,8 @@ struct vmw_fence_manager *vmw_fence_manager_init(struct vmw_private *dev_priv)
INIT_LIST_HEAD(&fman->cleanup_list);
INIT_WORK(&fman->work, &vmw_fence_work_func);
fman->fifo_down = true;
- fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence));
+ fman->user_fence_size = ttm_round_pot(sizeof(struct vmw_user_fence)) +
+ TTM_OBJ_EXTRA_SIZE;
fman->fence_size = ttm_round_pot(sizeof(struct vmw_fence_obj));
fman->event_fence_action_size =
ttm_round_pot(sizeof(struct vmw_event_fence_action));
@@ -650,7 +651,7 @@ int vmw_user_fence_create(struct drm_file *file_priv,
}
*p_fence = &ufence->fence;
- *p_handle = ufence->base.hash.key;
+ *p_handle = ufence->base.handle;
return 0;
out_err:
@@ -1137,7 +1138,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
"object.\n");
goto out_no_ref_obj;
}
- handle = base->hash.key;
+ handle = base->handle;
}
ttm_base_object_unref(&base);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 292e48feba83..dca04d4246ea 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -2575,88 +2575,31 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
}
/**
- * vmw_kms_helper_buffer_prepare - Reserve and validate a buffer object before
- * command submission.
- *
- * @dev_priv. Pointer to a device private structure.
- * @buf: The buffer object
- * @interruptible: Whether to perform waits as interruptible.
- * @validate_as_mob: Whether the buffer should be validated as a MOB. If false,
- * The buffer will be validated as a GMR. Already pinned buffers will not be
- * validated.
- *
- * Returns 0 on success, negative error code on failure, -ERESTARTSYS if
- * interrupted by a signal.
+ * vmw_kms_helper_validation_finish - Helper for post KMS command submission
+ * cleanup and fencing
+ * @dev_priv: Pointer to the device-private struct
+ * @file_priv: Pointer identifying the client when user-space fencing is used
+ * @ctx: Pointer to the validation context
+ * @out_fence: If non-NULL, returned refcounted fence-pointer
+ * @user_fence_rep: If non-NULL, pointer to user-space address area
+ * in which to copy user-space fence info
*/
-int vmw_kms_helper_buffer_prepare(struct vmw_private *dev_priv,
- struct vmw_buffer_object *buf,
- bool interruptible,
- bool validate_as_mob,
- bool for_cpu_blit)
-{
- struct ttm_operation_ctx ctx = {
- .interruptible = interruptible,
- .no_wait_gpu = false};
- struct ttm_buffer_object *bo = &buf->base;
- int ret;
-
- ttm_bo_reserve(bo, false, false, NULL);
- if (for_cpu_blit)
- ret = ttm_bo_validate(bo, &vmw_nonfixed_placement, &ctx);
- else
- ret = vmw_validate_single_buffer(dev_priv, bo, interruptible,
- validate_as_mob);
- if (ret)
- ttm_bo_unreserve(bo);
-
- return ret;
-}
-
-/**
- * vmw_kms_helper_buffer_revert - Undo the actions of
- * vmw_kms_helper_buffer_prepare.
- *
- * @res: Pointer to the buffer object.
- *
- * Helper to be used if an error forces the caller to undo the actions of
- * vmw_kms_helper_buffer_prepare.
- */
-void vmw_kms_helper_buffer_revert(struct vmw_buffer_object *buf)
-{
- if (buf)
- ttm_bo_unreserve(&buf->base);
-}
-
-/**
- * vmw_kms_helper_buffer_finish - Unreserve and fence a buffer object after
- * kms command submission.
- *
- * @dev_priv: Pointer to a device private structure.
- * @file_priv: Pointer to a struct drm_file representing the caller's
- * connection. Must be set to NULL if @user_fence_rep is NULL, and conversely
- * if non-NULL, @user_fence_rep must be non-NULL.
- * @buf: The buffer object.
- * @out_fence: Optional pointer to a fence pointer. If non-NULL, a
- * ref-counted fence pointer is returned here.
- * @user_fence_rep: Optional pointer to a user-space provided struct
- * drm_vmw_fence_rep. If provided, @file_priv must also be provided and the
- * function copies fence data to user-space in a fail-safe manner.
- */
-void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
- struct drm_file *file_priv,
- struct vmw_buffer_object *buf,
- struct vmw_fence_obj **out_fence,
- struct drm_vmw_fence_rep __user *
- user_fence_rep)
-{
- struct vmw_fence_obj *fence;
+void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_validation_context *ctx,
+ struct vmw_fence_obj **out_fence,
+ struct drm_vmw_fence_rep __user *
+ user_fence_rep)
+{
+ struct vmw_fence_obj *fence = NULL;
uint32_t handle;
int ret;
- ret = vmw_execbuf_fence_commands(file_priv, dev_priv, &fence,
- file_priv ? &handle : NULL);
- if (buf)
- vmw_bo_fence_single(&buf->base, fence);
+ if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) ||
+ out_fence)
+ ret = vmw_execbuf_fence_commands(file_priv, dev_priv, &fence,
+ file_priv ? &handle : NULL);
+ vmw_validation_done(ctx, fence);
if (file_priv)
vmw_execbuf_copy_fence_user(dev_priv, vmw_fpriv(file_priv),
ret, user_fence_rep, fence,
@@ -2665,106 +2608,6 @@ void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
*out_fence = fence;
else
vmw_fence_obj_unreference(&fence);
-
- vmw_kms_helper_buffer_revert(buf);
-}
-
-
-/**
- * vmw_kms_helper_resource_revert - Undo the actions of
- * vmw_kms_helper_resource_prepare.
- *
- * @res: Pointer to the resource. Typically a surface.
- *
- * Helper to be used if an error forces the caller to undo the actions of
- * vmw_kms_helper_resource_prepare.
- */
-void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx)
-{
- struct vmw_resource *res = ctx->res;
-
- vmw_kms_helper_buffer_revert(ctx->buf);
- vmw_bo_unreference(&ctx->buf);
- vmw_resource_unreserve(res, false, NULL, 0);
- mutex_unlock(&res->dev_priv->cmdbuf_mutex);
-}
-
-/**
- * vmw_kms_helper_resource_prepare - Reserve and validate a resource before
- * command submission.
- *
- * @res: Pointer to the resource. Typically a surface.
- * @interruptible: Whether to perform waits as interruptible.
- *
- * Reserves and validates also the backup buffer if a guest-backed resource.
- * Returns 0 on success, negative error code on failure. -ERESTARTSYS if
- * interrupted by a signal.
- */
-int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
- bool interruptible,
- struct vmw_validation_ctx *ctx)
-{
- int ret = 0;
-
- ctx->buf = NULL;
- ctx->res = res;
-
- if (interruptible)
- ret = mutex_lock_interruptible(&res->dev_priv->cmdbuf_mutex);
- else
- mutex_lock(&res->dev_priv->cmdbuf_mutex);
-
- if (unlikely(ret != 0))
- return -ERESTARTSYS;
-
- ret = vmw_resource_reserve(res, interruptible, false);
- if (ret)
- goto out_unlock;
-
- if (res->backup) {
- ret = vmw_kms_helper_buffer_prepare(res->dev_priv, res->backup,
- interruptible,
- res->dev_priv->has_mob,
- false);
- if (ret)
- goto out_unreserve;
-
- ctx->buf = vmw_bo_reference(res->backup);
- }
- ret = vmw_resource_validate(res);
- if (ret)
- goto out_revert;
- return 0;
-
-out_revert:
- vmw_kms_helper_buffer_revert(ctx->buf);
-out_unreserve:
- vmw_resource_unreserve(res, false, NULL, 0);
-out_unlock:
- mutex_unlock(&res->dev_priv->cmdbuf_mutex);
- return ret;
-}
-
-/**
- * vmw_kms_helper_resource_finish - Unreserve and fence a resource after
- * kms command submission.
- *
- * @res: Pointer to the resource. Typically a surface.
- * @out_fence: Optional pointer to a fence pointer. If non-NULL, a
- * ref-counted fence pointer is returned here.
- */
-void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
- struct vmw_fence_obj **out_fence)
-{
- struct vmw_resource *res = ctx->res;
-
- if (ctx->buf || out_fence)
- vmw_kms_helper_buffer_finish(res->dev_priv, NULL, ctx->buf,
- out_fence, NULL);
-
- vmw_bo_unreference(&ctx->buf);
- vmw_resource_unreserve(res, false, NULL, 0);
- mutex_unlock(&res->dev_priv->cmdbuf_mutex);
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 31311298ec0b..76ec570c0684 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -308,24 +308,12 @@ int vmw_kms_helper_dirty(struct vmw_private *dev_priv,
int increment,
struct vmw_kms_dirty *dirty);
-int vmw_kms_helper_buffer_prepare(struct vmw_private *dev_priv,
- struct vmw_buffer_object *buf,
- bool interruptible,
- bool validate_as_mob,
- bool for_cpu_blit);
-void vmw_kms_helper_buffer_revert(struct vmw_buffer_object *buf);
-void vmw_kms_helper_buffer_finish(struct vmw_private *dev_priv,
- struct drm_file *file_priv,
- struct vmw_buffer_object *buf,
- struct vmw_fence_obj **out_fence,
- struct drm_vmw_fence_rep __user *
- user_fence_rep);
-int vmw_kms_helper_resource_prepare(struct vmw_resource *res,
- bool interruptible,
- struct vmw_validation_ctx *ctx);
-void vmw_kms_helper_resource_revert(struct vmw_validation_ctx *ctx);
-void vmw_kms_helper_resource_finish(struct vmw_validation_ctx *ctx,
- struct vmw_fence_obj **out_fence);
+void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
+ struct drm_file *file_priv,
+ struct vmw_validation_context *ctx,
+ struct vmw_fence_obj **out_fence,
+ struct drm_vmw_fence_rep __user *
+ user_fence_rep);
int vmw_kms_readback(struct vmw_private *dev_priv,
struct drm_file *file_priv,
struct vmw_framebuffer *vfb,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
index 0861c821a7fe..e420675e8db3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c
@@ -31,8 +31,8 @@
*/
#include "vmwgfx_drv.h"
+#include "ttm_object.h"
#include <linux/dma-buf.h>
-#include <drm/ttm/ttm_object.h>
/*
* DMA-BUF attach- and mapping methods. No need to implement
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
index 92003ea5a219..8a029bade32a 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
@@ -58,11 +58,11 @@ void vmw_resource_release_id(struct vmw_resource *res)
struct vmw_private *dev_priv = res->dev_priv;
struct idr *idr = &dev_priv->res_idr[res->func->res_type];
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
if (res->id != -1)
idr_remove(idr, res->id);
res->id = -1;
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
}
static void vmw_resource_release(struct kref *kref)
@@ -73,10 +73,9 @@ static void vmw_resource_release(struct kref *kref)
int id;
struct idr *idr = &dev_priv->res_idr[res->func->res_type];
- write_lock(&dev_priv->resource_lock);
- res->avail = false;
+ spin_lock(&dev_priv->resource_lock);
list_del_init(&res->lru_head);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
if (res->backup) {
struct ttm_buffer_object *bo = &res->backup->base;
@@ -108,10 +107,10 @@ static void vmw_resource_release(struct kref *kref)
else
kfree(res);
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
if (id != -1)
idr_remove(idr, id);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
}
void vmw_resource_unreference(struct vmw_resource **p_res)
@@ -140,13 +139,13 @@ int vmw_resource_alloc_id(struct vmw_resource *res)
BUG_ON(res->id != -1);
idr_preload(GFP_KERNEL);
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
ret = idr_alloc(idr, res, 1, 0, GFP_NOWAIT);
if (ret >= 0)
res->id = ret;
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
idr_preload_end();
return ret < 0 ? ret : 0;
}
@@ -170,7 +169,6 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
kref_init(&res->kref);
res->hw_destroy = NULL;
res->res_free = res_free;
- res->avail = false;
res->dev_priv = dev_priv;
res->func = func;
INIT_LIST_HEAD(&res->lru_head);
@@ -187,28 +185,6 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
return vmw_resource_alloc_id(res);
}
-/**
- * vmw_resource_activate
- *
- * @res: Pointer to the newly created resource
- * @hw_destroy: Destroy function. NULL if none.
- *
- * Activate a resource after the hardware has been made aware of it.
- * Set tye destroy function to @destroy. Typically this frees the
- * resource and destroys the hardware resources associated with it.
- * Activate basically means that the function vmw_resource_lookup will
- * find it.
- */
-void vmw_resource_activate(struct vmw_resource *res,
- void (*hw_destroy) (struct vmw_resource *))
-{
- struct vmw_private *dev_priv = res->dev_priv;
-
- write_lock(&dev_priv->resource_lock);
- res->avail = true;
- res->hw_destroy = hw_destroy;
- write_unlock(&dev_priv->resource_lock);
-}
/**
* vmw_user_resource_lookup_handle - lookup a struct resource from a
@@ -243,15 +219,7 @@ int vmw_user_resource_lookup_handle(struct vmw_private *dev_priv,
goto out_bad_resource;
res = converter->base_obj_to_res(base);
-
- read_lock(&dev_priv->resource_lock);
- if (!res->avail || res->res_free != converter->res_free) {
- read_unlock(&dev_priv->resource_lock);
- goto out_bad_resource;
- }
-
kref_get(&res->kref);
- read_unlock(&dev_priv->resource_lock);
*p_res = res;
ret = 0;
@@ -263,6 +231,41 @@ out_bad_resource:
}
/**
+ * vmw_user_resource_lookup_handle - lookup a struct resource from a
+ * TTM user-space handle and perform basic type checks
+ *
+ * @dev_priv: Pointer to a device private struct
+ * @tfile: Pointer to a struct ttm_object_file identifying the caller
+ * @handle: The TTM user-space handle
+ * @converter: Pointer to an object describing the resource type
+ * @p_res: On successful return the location pointed to will contain
+ * a pointer to a refcounted struct vmw_resource.
+ *
+ * If the handle can't be found or is associated with an incorrect resource
+ * type, -EINVAL will be returned.
+ */
+struct vmw_resource *
+vmw_user_resource_noref_lookup_handle(struct vmw_private *dev_priv,
+ struct ttm_object_file *tfile,
+ uint32_t handle,
+ const struct vmw_user_resource_conv
+ *converter)
+{
+ struct ttm_base_object *base;
+
+ base = ttm_base_object_noref_lookup(tfile, handle);
+ if (!base)
+ return ERR_PTR(-ESRCH);
+
+ if (unlikely(ttm_base_object_type(base) != converter->object_type)) {
+ ttm_base_object_noref_release();
+ return ERR_PTR(-EINVAL);
+ }
+
+ return converter->base_obj_to_res(base);
+}
+
+/**
* Helper function that looks either a surface or bo.
*
* The pointer this pointed at by out_surf and out_buf needs to be null.
@@ -422,10 +425,10 @@ void vmw_resource_unreserve(struct vmw_resource *res,
if (!res->func->may_evict || res->id == -1 || res->pin_count)
return;
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
list_add_tail(&res->lru_head,
&res->dev_priv->res_lru[res->func->res_type]);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
}
/**
@@ -504,9 +507,9 @@ int vmw_resource_reserve(struct vmw_resource *res, bool interruptible,
struct vmw_private *dev_priv = res->dev_priv;
int ret;
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
list_del_init(&res->lru_head);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
if (res->func->needs_backup && res->backup == NULL &&
!no_backup) {
@@ -587,15 +590,18 @@ out_no_unbind:
/**
* vmw_resource_validate - Make a resource up-to-date and visible
* to the device.
- *
- * @res: The resource to make visible to the device.
+ * @res: The resource to make visible to the device.
+ * @intr: Perform waits interruptible if possible.
*
* On succesful return, any backup DMA buffer pointed to by @res->backup will
* be reserved and validated.
* On hardware resource shortage, this function will repeatedly evict
* resources of the same type until the validation succeeds.
+ *
+ * Return: Zero on success, -ERESTARTSYS if interrupted, negative error code
+ * on failure.
*/
-int vmw_resource_validate(struct vmw_resource *res)
+int vmw_resource_validate(struct vmw_resource *res, bool intr)
{
int ret;
struct vmw_resource *evict_res;
@@ -616,12 +622,12 @@ int vmw_resource_validate(struct vmw_resource *res)
if (likely(ret != -EBUSY))
break;
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
if (list_empty(lru_list) || !res->func->may_evict) {
DRM_ERROR("Out of device device resources "
"for %s.\n", res->func->type_name);
ret = -EBUSY;
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
break;
}
@@ -630,14 +636,14 @@ int vmw_resource_validate(struct vmw_resource *res)
lru_head));
list_del_init(&evict_res->lru_head);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
/* Trylock backup buffers with a NULL ticket. */
- ret = vmw_resource_do_evict(NULL, evict_res, true);
+ ret = vmw_resource_do_evict(NULL, evict_res, intr);
if (unlikely(ret != 0)) {
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
list_add_tail(&evict_res->lru_head, lru_list);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
if (ret == -ERESTARTSYS ||
++err_count > VMW_RES_EVICT_ERR_COUNT) {
vmw_resource_unreference(&evict_res);
@@ -819,7 +825,7 @@ static void vmw_resource_evict_type(struct vmw_private *dev_priv,
struct ww_acquire_ctx ticket;
do {
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
if (list_empty(lru_list))
goto out_unlock;
@@ -828,14 +834,14 @@ static void vmw_resource_evict_type(struct vmw_private *dev_priv,
list_first_entry(lru_list, struct vmw_resource,
lru_head));
list_del_init(&evict_res->lru_head);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
/* Wait lock backup buffers with a ticket. */
ret = vmw_resource_do_evict(&ticket, evict_res, false);
if (unlikely(ret != 0)) {
- write_lock(&dev_priv->resource_lock);
+ spin_lock(&dev_priv->resource_lock);
list_add_tail(&evict_res->lru_head, lru_list);
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
if (++err_count > VMW_RES_EVICT_ERR_COUNT) {
vmw_resource_unreference(&evict_res);
return;
@@ -846,7 +852,7 @@ static void vmw_resource_evict_type(struct vmw_private *dev_priv,
} while (1);
out_unlock:
- write_unlock(&dev_priv->resource_lock);
+ spin_unlock(&dev_priv->resource_lock);
}
/**
@@ -914,7 +920,7 @@ int vmw_resource_pin(struct vmw_resource *res, bool interruptible)
/* Do we really need to pin the MOB as well? */
vmw_bo_pin_reserved(vbo, true);
}
- ret = vmw_resource_validate(res);
+ ret = vmw_resource_validate(res, interruptible);
if (vbo)
ttm_bo_unreserve(&vbo->base);
if (ret)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h
index a8c1c5ebd71d..7e19eba0b0b8 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource_priv.h
@@ -30,6 +30,11 @@
#include "vmwgfx_drv.h"
+/*
+ * Extra memory required by the resource id's ida storage, which is allocated
+ * separately from the base object itself. We estimate an on-average 128 bytes
+ * per ida.
+ */
#define VMW_IDA_ACC_SIZE 128
enum vmw_cmdbuf_res_state {
@@ -120,8 +125,6 @@ int vmw_resource_init(struct vmw_private *dev_priv, struct vmw_resource *res,
bool delay_id,
void (*res_free) (struct vmw_resource *res),
const struct vmw_res_func *func);
-void vmw_resource_activate(struct vmw_resource *res,
- void (*hw_destroy) (struct vmw_resource *));
int
vmw_simple_resource_create_ioctl(struct drm_device *dev,
void *data,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index ad0de7f0cd60..53316b1bda3d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -946,16 +946,20 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base);
struct vmw_kms_sou_surface_dirty sdirty;
- struct vmw_validation_ctx ctx;
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
int ret;
if (!srf)
srf = &vfbs->surface->res;
- ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
+ ret = vmw_validation_add_resource(&val_ctx, srf, 0, NULL, NULL);
if (ret)
return ret;
+ ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true);
+ if (ret)
+ goto out_unref;
+
sdirty.base.fifo_commit = vmw_sou_surface_fifo_commit;
sdirty.base.clip = vmw_sou_surface_clip;
sdirty.base.dev_priv = dev_priv;
@@ -972,9 +976,14 @@ int vmw_kms_sou_do_surface_dirty(struct vmw_private *dev_priv,
ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
dest_x, dest_y, num_clips, inc,
&sdirty.base);
- vmw_kms_helper_resource_finish(&ctx, out_fence);
+ vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
+ NULL);
return ret;
+
+out_unref:
+ vmw_validation_unref_lists(&val_ctx);
+ return ret;
}
/**
@@ -1051,13 +1060,17 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv,
container_of(framebuffer, struct vmw_framebuffer_bo,
base)->buffer;
struct vmw_kms_dirty dirty;
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
int ret;
- ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible,
- false, false);
+ ret = vmw_validation_add_bo(&val_ctx, buf, false, false);
if (ret)
return ret;
+ ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);
+ if (ret)
+ goto out_unref;
+
ret = do_bo_define_gmrfb(dev_priv, framebuffer);
if (unlikely(ret != 0))
goto out_revert;
@@ -1069,12 +1082,15 @@ int vmw_kms_sou_do_bo_dirty(struct vmw_private *dev_priv,
num_clips;
ret = vmw_kms_helper_dirty(dev_priv, framebuffer, clips, vclips,
0, 0, num_clips, increment, &dirty);
- vmw_kms_helper_buffer_finish(dev_priv, NULL, buf, out_fence, NULL);
+ vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
+ NULL);
return ret;
out_revert:
- vmw_kms_helper_buffer_revert(buf);
+ vmw_validation_revert(&val_ctx);
+out_unref:
+ vmw_validation_unref_lists(&val_ctx);
return ret;
}
@@ -1150,13 +1166,17 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv,
struct vmw_buffer_object *buf =
container_of(vfb, struct vmw_framebuffer_bo, base)->buffer;
struct vmw_kms_dirty dirty;
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
int ret;
- ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, true, false,
- false);
+ ret = vmw_validation_add_bo(&val_ctx, buf, false, false);
if (ret)
return ret;
+ ret = vmw_validation_prepare(&val_ctx, NULL, true);
+ if (ret)
+ goto out_unref;
+
ret = do_bo_define_gmrfb(dev_priv, vfb);
if (unlikely(ret != 0))
goto out_revert;
@@ -1168,13 +1188,15 @@ int vmw_kms_sou_readback(struct vmw_private *dev_priv,
num_clips;
ret = vmw_kms_helper_dirty(dev_priv, vfb, NULL, vclips,
0, 0, num_clips, 1, &dirty);
- vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL,
- user_fence_rep);
+ vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL,
+ user_fence_rep);
return ret;
out_revert:
- vmw_kms_helper_buffer_revert(buf);
-
+ vmw_validation_revert(&val_ctx);
+out_unref:
+ vmw_validation_unref_lists(&val_ctx);
+
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
index fe4842ca3b6e..bf32fe446219 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
@@ -186,7 +186,7 @@ static int vmw_gb_shader_init(struct vmw_private *dev_priv,
shader->num_input_sig = num_input_sig;
shader->num_output_sig = num_output_sig;
- vmw_resource_activate(res, vmw_hw_shader_destroy);
+ res->hw_destroy = vmw_hw_shader_destroy;
return 0;
}
@@ -562,7 +562,7 @@ void vmw_dx_shader_cotable_list_scrub(struct vmw_private *dev_priv,
{
struct vmw_dx_shader *entry, *next;
- WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex));
+ lockdep_assert_held_once(&dev_priv->binding_mutex);
list_for_each_entry_safe(entry, next, list, cotable_head) {
WARN_ON(vmw_dx_shader_scrub(&entry->res));
@@ -636,7 +636,8 @@ int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man,
res = &shader->res;
shader->ctx = ctx;
- shader->cotable = vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER);
+ shader->cotable = vmw_resource_reference
+ (vmw_context_cotable(ctx, SVGA_COTABLE_DXSHADER));
shader->id = user_key;
shader->committed = false;
INIT_LIST_HEAD(&shader->cotable_head);
@@ -656,7 +657,7 @@ int vmw_dx_shader_add(struct vmw_cmdbuf_res_manager *man,
goto out_resource_init;
res->id = shader->id;
- vmw_resource_activate(res, vmw_hw_shader_destroy);
+ res->hw_destroy = vmw_hw_shader_destroy;
out_resource_init:
vmw_resource_unreference(&res);
@@ -740,13 +741,10 @@ static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
};
int ret;
- /*
- * Approximate idr memory usage with 128 bytes. It will be limited
- * by maximum number_of shaders anyway.
- */
if (unlikely(vmw_user_shader_size == 0))
vmw_user_shader_size =
- ttm_round_pot(sizeof(struct vmw_user_shader)) + 128;
+ ttm_round_pot(sizeof(struct vmw_user_shader)) +
+ VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
vmw_user_shader_size,
@@ -792,7 +790,7 @@ static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
}
if (handle)
- *handle = ushader->base.hash.key;
+ *handle = ushader->base.handle;
out_err:
vmw_resource_unreference(&res);
out:
@@ -814,13 +812,10 @@ static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
};
int ret;
- /*
- * Approximate idr memory usage with 128 bytes. It will be limited
- * by maximum number_of shaders anyway.
- */
if (unlikely(vmw_shader_size == 0))
vmw_shader_size =
- ttm_round_pot(sizeof(struct vmw_shader)) + 128;
+ ttm_round_pot(sizeof(struct vmw_shader)) +
+ VMW_IDA_ACC_SIZE;
ret = ttm_mem_global_alloc(vmw_mem_glob(dev_priv),
vmw_shader_size,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c
index 6ebc5affde14..6a6865384e91 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_simple_resource.c
@@ -81,7 +81,7 @@ static int vmw_simple_resource_init(struct vmw_private *dev_priv,
return ret;
}
- vmw_resource_activate(&simple->res, simple->func->hw_destroy);
+ simple->res.hw_destroy = simple->func->hw_destroy;
return 0;
}
@@ -159,7 +159,8 @@ vmw_simple_resource_create_ioctl(struct drm_device *dev, void *data,
alloc_size = offsetof(struct vmw_user_simple_resource, simple) +
func->size;
- account_size = ttm_round_pot(alloc_size) + VMW_IDA_ACC_SIZE;
+ account_size = ttm_round_pot(alloc_size) + VMW_IDA_ACC_SIZE +
+ TTM_OBJ_EXTRA_SIZE;
ret = ttm_read_lock(&dev_priv->reservation_sem, true);
if (ret)
@@ -208,7 +209,7 @@ vmw_simple_resource_create_ioctl(struct drm_device *dev, void *data,
goto out_err;
}
- func->set_arg_handle(data, usimple->base.hash.key);
+ func->set_arg_handle(data, usimple->base.handle);
out_err:
vmw_resource_unreference(&res);
out_ret:
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
index e9b6b7baa009..bc8bb690f1ea 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_so.c
@@ -208,7 +208,7 @@ static int vmw_view_destroy(struct vmw_resource *res)
union vmw_view_destroy body;
} *cmd;
- WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex));
+ lockdep_assert_held_once(&dev_priv->binding_mutex);
vmw_binding_res_list_scrub(&res->binding_head);
if (!view->committed || res->id == -1)
@@ -366,7 +366,8 @@ int vmw_view_add(struct vmw_cmdbuf_res_manager *man,
res = &view->res;
view->ctx = ctx;
view->srf = vmw_resource_reference(srf);
- view->cotable = vmw_context_cotable(ctx, vmw_view_cotables[view_type]);
+ view->cotable = vmw_resource_reference
+ (vmw_context_cotable(ctx, vmw_view_cotables[view_type]));
view->view_type = view_type;
view->view_id = user_key;
view->cmd_size = cmd_size;
@@ -386,7 +387,7 @@ int vmw_view_add(struct vmw_cmdbuf_res_manager *man,
goto out_resource_init;
res->id = view->view_id;
- vmw_resource_activate(res, vmw_hw_view_destroy);
+ res->hw_destroy = vmw_hw_view_destroy;
out_resource_init:
vmw_resource_unreference(&res);
@@ -439,7 +440,7 @@ void vmw_view_cotable_list_destroy(struct vmw_private *dev_priv,
{
struct vmw_view *entry, *next;
- WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex));
+ lockdep_assert_held_once(&dev_priv->binding_mutex);
list_for_each_entry_safe(entry, next, list, cotable_head)
WARN_ON(vmw_view_destroy(&entry->res));
@@ -459,7 +460,7 @@ void vmw_view_surface_list_destroy(struct vmw_private *dev_priv,
{
struct vmw_view *entry, *next;
- WARN_ON_ONCE(!mutex_is_locked(&dev_priv->binding_mutex));
+ lockdep_assert_held_once(&dev_priv->binding_mutex);
list_for_each_entry_safe(entry, next, list, srf_head)
WARN_ON(vmw_view_destroy(&entry->res));
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index f30e839f7bfd..e086565c1da6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -759,17 +759,21 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
struct vmw_stdu_dirty ddirty;
int ret;
bool cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D);
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
/*
* VMs without 3D support don't have the surface DMA command and
* we'll be using a CPU blit, and the framebuffer should be moved out
* of VRAM.
*/
- ret = vmw_kms_helper_buffer_prepare(dev_priv, buf, interruptible,
- false, cpu_blit);
+ ret = vmw_validation_add_bo(&val_ctx, buf, false, cpu_blit);
if (ret)
return ret;
+ ret = vmw_validation_prepare(&val_ctx, NULL, interruptible);
+ if (ret)
+ goto out_unref;
+
ddirty.transfer = (to_surface) ? SVGA3D_WRITE_HOST_VRAM :
SVGA3D_READ_HOST_VRAM;
ddirty.left = ddirty.top = S32_MAX;
@@ -796,9 +800,13 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv,
ret = vmw_kms_helper_dirty(dev_priv, vfb, clips, vclips,
0, 0, num_clips, increment, &ddirty.base);
- vmw_kms_helper_buffer_finish(dev_priv, file_priv, buf, NULL,
- user_fence_rep);
+ vmw_kms_helper_validation_finish(dev_priv, file_priv, &val_ctx, NULL,
+ user_fence_rep);
+ return ret;
+
+out_unref:
+ vmw_validation_unref_lists(&val_ctx);
return ret;
}
@@ -924,16 +932,20 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
struct vmw_framebuffer_surface *vfbs =
container_of(framebuffer, typeof(*vfbs), base);
struct vmw_stdu_dirty sdirty;
- struct vmw_validation_ctx ctx;
+ DECLARE_VAL_CONTEXT(val_ctx, NULL, 0);
int ret;
if (!srf)
srf = &vfbs->surface->res;
- ret = vmw_kms_helper_resource_prepare(srf, true, &ctx);
+ ret = vmw_validation_add_resource(&val_ctx, srf, 0, NULL, NULL);
if (ret)
return ret;
+ ret = vmw_validation_prepare(&val_ctx, &dev_priv->cmdbuf_mutex, true);
+ if (ret)
+ goto out_unref;
+
if (vfbs->is_bo_proxy) {
ret = vmw_kms_update_proxy(srf, clips, num_clips, inc);
if (ret)
@@ -954,8 +966,13 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv,
dest_x, dest_y, num_clips, inc,
&sdirty.base);
out_finish:
- vmw_kms_helper_resource_finish(&ctx, out_fence);
+ vmw_kms_helper_validation_finish(dev_priv, NULL, &val_ctx, out_fence,
+ NULL);
+
+ return ret;
+out_unref:
+ vmw_validation_unref_lists(&val_ctx);
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index 80a01cd4c051..ef09f7edf931 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -614,7 +614,7 @@ static int vmw_surface_init(struct vmw_private *dev_priv,
*/
INIT_LIST_HEAD(&srf->view_list);
- vmw_resource_activate(res, vmw_hw_surface_destroy);
+ res->hw_destroy = vmw_hw_surface_destroy;
return ret;
}
@@ -731,7 +731,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
if (unlikely(vmw_user_surface_size == 0))
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
- 128;
+ VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
num_sizes = 0;
for (i = 0; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
@@ -744,7 +744,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
num_sizes == 0)
return -EINVAL;
- size = vmw_user_surface_size + 128 +
+ size = vmw_user_surface_size +
ttm_round_pot(num_sizes * sizeof(struct drm_vmw_size)) +
ttm_round_pot(num_sizes * sizeof(struct vmw_surface_offset));
@@ -886,7 +886,7 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
- rep->sid = user_srf->prime.base.hash.key;
+ rep->sid = user_srf->prime.base.handle;
vmw_resource_unreference(&res);
ttm_read_unlock(&dev_priv->reservation_sem);
@@ -1024,7 +1024,7 @@ int vmw_surface_reference_ioctl(struct drm_device *dev, void *data,
if (unlikely(ret != 0)) {
DRM_ERROR("copy_to_user failed %p %u\n",
user_sizes, srf->num_sizes);
- ttm_ref_object_base_unref(tfile, base->hash.key, TTM_REF_USAGE);
+ ttm_ref_object_base_unref(tfile, base->handle, TTM_REF_USAGE);
ret = -EFAULT;
}
@@ -1613,9 +1613,9 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
if (unlikely(vmw_user_surface_size == 0))
vmw_user_surface_size = ttm_round_pot(sizeof(*user_srf)) +
- 128;
+ VMW_IDA_ACC_SIZE + TTM_OBJ_EXTRA_SIZE;
- size = vmw_user_surface_size + 128;
+ size = vmw_user_surface_size;
/* Define a surface based on the parameters. */
ret = vmw_surface_gb_priv_define(dev,
@@ -1687,7 +1687,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
goto out_unlock;
}
- rep->handle = user_srf->prime.base.hash.key;
+ rep->handle = user_srf->prime.base.handle;
rep->backup_size = res->backup_size;
if (res->backup) {
rep->buffer_map_handle =
@@ -1749,7 +1749,7 @@ vmw_gb_surface_reference_internal(struct drm_device *dev,
if (unlikely(ret != 0)) {
DRM_ERROR("Could not add a reference to a GB surface "
"backup buffer.\n");
- (void) ttm_ref_object_base_unref(tfile, base->hash.key,
+ (void) ttm_ref_object_base_unref(tfile, base->handle,
TTM_REF_USAGE);
goto out_bad_resource;
}
@@ -1763,7 +1763,7 @@ vmw_gb_surface_reference_internal(struct drm_device *dev,
rep->creq.base.array_size = srf->array_size;
rep->creq.base.buffer_handle = backup_handle;
rep->creq.base.base_size = srf->base_size;
- rep->crep.handle = user_srf->prime.base.hash.key;
+ rep->crep.handle = user_srf->prime.base.handle;
rep->crep.backup_size = srf->res.backup_size;
rep->crep.buffer_handle = backup_handle;
rep->crep.buffer_map_handle =
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
new file mode 100644
index 000000000000..184025fa938e
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
@@ -0,0 +1,770 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/**************************************************************************
+ *
+ * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+#include <linux/slab.h>
+#include "vmwgfx_validation.h"
+#include "vmwgfx_drv.h"
+
+/**
+ * struct vmw_validation_bo_node - Buffer object validation metadata.
+ * @base: Metadata used for TTM reservation- and validation.
+ * @hash: A hash entry used for the duplicate detection hash table.
+ * @as_mob: Validate as mob.
+ * @cpu_blit: Validate for cpu blit access.
+ *
+ * Bit fields are used since these structures are allocated and freed in
+ * large numbers and space conservation is desired.
+ */
+struct vmw_validation_bo_node {
+ struct ttm_validate_buffer base;
+ struct drm_hash_item hash;
+ u32 as_mob : 1;
+ u32 cpu_blit : 1;
+};
+
+/**
+ * struct vmw_validation_res_node - Resource validation metadata.
+ * @head: List head for the resource validation list.
+ * @hash: A hash entry used for the duplicate detection hash table.
+ * @res: Reference counted resource pointer.
+ * @new_backup: Non ref-counted pointer to new backup buffer to be assigned
+ * to a resource.
+ * @new_backup_offset: Offset into the new backup mob for resources that can
+ * share MOBs.
+ * @no_buffer_needed: Kernel does not need to allocate a MOB during validation,
+ * the command stream provides a mob bind operation.
+ * @switching_backup: The validation process is switching backup MOB.
+ * @first_usage: True iff the resource has been seen only once in the current
+ * validation batch.
+ * @reserved: Whether the resource is currently reserved by this process.
+ * @private: Optionally additional memory for caller-private data.
+ *
+ * Bit fields are used since these structures are allocated and freed in
+ * large numbers and space conservation is desired.
+ */
+struct vmw_validation_res_node {
+ struct list_head head;
+ struct drm_hash_item hash;
+ struct vmw_resource *res;
+ struct vmw_buffer_object *new_backup;
+ unsigned long new_backup_offset;
+ u32 no_buffer_needed : 1;
+ u32 switching_backup : 1;
+ u32 first_usage : 1;
+ u32 reserved : 1;
+ unsigned long private[0];
+};
+
+/**
+ * vmw_validation_mem_alloc - Allocate kernel memory from the validation
+ * context based allocator
+ * @ctx: The validation context
+ * @size: The number of bytes to allocated.
+ *
+ * The memory allocated may not exceed PAGE_SIZE, and the returned
+ * address is aligned to sizeof(long). All memory allocated this way is
+ * reclaimed after validation when calling any of the exported functions:
+ * vmw_validation_unref_lists()
+ * vmw_validation_revert()
+ * vmw_validation_done()
+ *
+ * Return: Pointer to the allocated memory on success. NULL on failure.
+ */
+void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
+ unsigned int size)
+{
+ void *addr;
+
+ size = vmw_validation_align(size);
+ if (size > PAGE_SIZE)
+ return NULL;
+
+ if (ctx->mem_size_left < size) {
+ struct page *page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+
+ if (!page)
+ return NULL;
+
+ list_add_tail(&page->lru, &ctx->page_list);
+ ctx->page_address = page_address(page);
+ ctx->mem_size_left = PAGE_SIZE;
+ }
+
+ addr = (void *) (ctx->page_address + (PAGE_SIZE - ctx->mem_size_left));
+ ctx->mem_size_left -= size;
+
+ return addr;
+}
+
+/**
+ * vmw_validation_mem_free - Free all memory allocated using
+ * vmw_validation_mem_alloc()
+ * @ctx: The validation context
+ *
+ * All memory previously allocated for this context using
+ * vmw_validation_mem_alloc() is freed.
+ */
+static void vmw_validation_mem_free(struct vmw_validation_context *ctx)
+{
+ struct page *entry, *next;
+
+ list_for_each_entry_safe(entry, next, &ctx->page_list, lru) {
+ list_del_init(&entry->lru);
+ __free_page(entry);
+ }
+
+ ctx->mem_size_left = 0;
+}
+
+/**
+ * vmw_validation_find_bo_dup - Find a duplicate buffer object entry in the
+ * validation context's lists.
+ * @ctx: The validation context to search.
+ * @vbo: The buffer object to search for.
+ *
+ * Return: Pointer to the struct vmw_validation_bo_node referencing the
+ * duplicate, or NULL if none found.
+ */
+static struct vmw_validation_bo_node *
+vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,
+ struct vmw_buffer_object *vbo)
+{
+ struct vmw_validation_bo_node *bo_node = NULL;
+
+ if (!ctx->merge_dups)
+ return NULL;
+
+ if (ctx->ht) {
+ struct drm_hash_item *hash;
+
+ if (!drm_ht_find_item(ctx->ht, (unsigned long) vbo, &hash))
+ bo_node = container_of(hash, typeof(*bo_node), hash);
+ } else {
+ struct vmw_validation_bo_node *entry;
+
+ list_for_each_entry(entry, &ctx->bo_list, base.head) {
+ if (entry->base.bo == &vbo->base) {
+ bo_node = entry;
+ break;
+ }
+ }
+ }
+
+ return bo_node;
+}
+
+/**
+ * vmw_validation_find_res_dup - Find a duplicate resource entry in the
+ * validation context's lists.
+ * @ctx: The validation context to search.
+ * @vbo: The buffer object to search for.
+ *
+ * Return: Pointer to the struct vmw_validation_bo_node referencing the
+ * duplicate, or NULL if none found.
+ */
+static struct vmw_validation_res_node *
+vmw_validation_find_res_dup(struct vmw_validation_context *ctx,
+ struct vmw_resource *res)
+{
+ struct vmw_validation_res_node *res_node = NULL;
+
+ if (!ctx->merge_dups)
+ return NULL;
+
+ if (ctx->ht) {
+ struct drm_hash_item *hash;
+
+ if (!drm_ht_find_item(ctx->ht, (unsigned long) res, &hash))
+ res_node = container_of(hash, typeof(*res_node), hash);
+ } else {
+ struct vmw_validation_res_node *entry;
+
+ list_for_each_entry(entry, &ctx->resource_ctx_list, head) {
+ if (entry->res == res) {
+ res_node = entry;
+ goto out;
+ }
+ }
+
+ list_for_each_entry(entry, &ctx->resource_list, head) {
+ if (entry->res == res) {
+ res_node = entry;
+ break;
+ }
+ }
+
+ }
+out:
+ return res_node;
+}
+
+/**
+ * vmw_validation_add_bo - Add a buffer object to the validation context.
+ * @ctx: The validation context.
+ * @vbo: The buffer object.
+ * @as_mob: Validate as mob, otherwise suitable for GMR operations.
+ * @cpu_blit: Validate in a page-mappable location.
+ *
+ * Return: Zero on success, negative error code otherwise.
+ */
+int vmw_validation_add_bo(struct vmw_validation_context *ctx,
+ struct vmw_buffer_object *vbo,
+ bool as_mob,
+ bool cpu_blit)
+{
+ struct vmw_validation_bo_node *bo_node;
+
+ bo_node = vmw_validation_find_bo_dup(ctx, vbo);
+ if (bo_node) {
+ if (bo_node->as_mob != as_mob ||
+ bo_node->cpu_blit != cpu_blit) {
+ DRM_ERROR("Inconsistent buffer usage.\n");
+ return -EINVAL;
+ }
+ } else {
+ struct ttm_validate_buffer *val_buf;
+ int ret;
+
+ bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node));
+ if (!bo_node)
+ return -ENOMEM;
+
+ if (ctx->ht) {
+ bo_node->hash.key = (unsigned long) vbo;
+ ret = drm_ht_insert_item(ctx->ht, &bo_node->hash);
+ if (ret) {
+ DRM_ERROR("Failed to initialize a buffer "
+ "validation entry.\n");
+ return ret;
+ }
+ }
+ val_buf = &bo_node->base;
+ val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);
+ if (!val_buf->bo)
+ return -ESRCH;
+ val_buf->shared = false;
+ list_add_tail(&val_buf->head, &ctx->bo_list);
+ bo_node->as_mob = as_mob;
+ bo_node->cpu_blit = cpu_blit;
+ }
+
+ return 0;
+}
+
+/**
+ * vmw_validation_add_resource - Add a resource to the validation context.
+ * @ctx: The validation context.
+ * @res: The resource.
+ * @priv_size: Size of private, additional metadata.
+ * @p_node: Output pointer of additional metadata address.
+ * @first_usage: Whether this was the first time this resource was seen.
+ *
+ * Return: Zero on success, negative error code otherwise.
+ */
+int vmw_validation_add_resource(struct vmw_validation_context *ctx,
+ struct vmw_resource *res,
+ size_t priv_size,
+ void **p_node,
+ bool *first_usage)
+{
+ struct vmw_validation_res_node *node;
+ int ret;
+
+ node = vmw_validation_find_res_dup(ctx, res);
+ if (node) {
+ node->first_usage = 0;
+ goto out_fill;
+ }
+
+ node = vmw_validation_mem_alloc(ctx, sizeof(*node) + priv_size);
+ if (!node) {
+ DRM_ERROR("Failed to allocate a resource validation "
+ "entry.\n");
+ return -ENOMEM;
+ }
+
+ if (ctx->ht) {
+ node->hash.key = (unsigned long) res;
+ ret = drm_ht_insert_item(ctx->ht, &node->hash);
+ if (ret) {
+ DRM_ERROR("Failed to initialize a resource validation "
+ "entry.\n");
+ return ret;
+ }
+ }
+ node->res = vmw_resource_reference_unless_doomed(res);
+ if (!node->res)
+ return -ESRCH;
+
+ node->first_usage = 1;
+ if (!res->dev_priv->has_mob) {
+ list_add_tail(&node->head, &ctx->resource_list);
+ } else {
+ switch (vmw_res_type(res)) {
+ case vmw_res_context:
+ case vmw_res_dx_context:
+ list_add(&node->head, &ctx->resource_ctx_list);
+ break;
+ case vmw_res_cotable:
+ list_add_tail(&node->head, &ctx->resource_ctx_list);
+ break;
+ default:
+ list_add_tail(&node->head, &ctx->resource_list);
+ break;
+ }
+ }
+
+out_fill:
+ if (first_usage)
+ *first_usage = node->first_usage;
+ if (p_node)
+ *p_node = &node->private;
+
+ return 0;
+}
+
+/**
+ * vmw_validation_res_switch_backup - Register a backup MOB switch during
+ * validation.
+ * @ctx: The validation context.
+ * @val_private: The additional meta-data pointer returned when the
+ * resource was registered with the validation context. Used to identify
+ * the resource.
+ * @vbo: The new backup buffer object MOB. This buffer object needs to have
+ * already been registered with the validation context.
+ * @backup_offset: Offset into the new backup MOB.
+ */
+void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,
+ void *val_private,
+ struct vmw_buffer_object *vbo,
+ unsigned long backup_offset)
+{
+ struct vmw_validation_res_node *val;
+
+ val = container_of(val_private, typeof(*val), private);
+
+ val->switching_backup = 1;
+ if (val->first_usage)
+ val->no_buffer_needed = 1;
+
+ val->new_backup = vbo;
+ val->new_backup_offset = backup_offset;
+}
+
+/**
+ * vmw_validation_res_reserve - Reserve all resources registered with this
+ * validation context.
+ * @ctx: The validation context.
+ * @intr: Use interruptible waits when possible.
+ *
+ * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error
+ * code on failure.
+ */
+int vmw_validation_res_reserve(struct vmw_validation_context *ctx,
+ bool intr)
+{
+ struct vmw_validation_res_node *val;
+ int ret = 0;
+
+ list_splice_init(&ctx->resource_ctx_list, &ctx->resource_list);
+
+ list_for_each_entry(val, &ctx->resource_list, head) {
+ struct vmw_resource *res = val->res;
+
+ ret = vmw_resource_reserve(res, intr, val->no_buffer_needed);
+ if (ret)
+ goto out_unreserve;
+
+ val->reserved = 1;
+ if (res->backup) {
+ struct vmw_buffer_object *vbo = res->backup;
+
+ ret = vmw_validation_add_bo
+ (ctx, vbo, vmw_resource_needs_backup(res),
+ false);
+ if (ret)
+ goto out_unreserve;
+ }
+ }
+
+ return 0;
+
+out_unreserve:
+ vmw_validation_res_unreserve(ctx, true);
+ return ret;
+}
+
+/**
+ * vmw_validation_res_unreserve - Unreserve all reserved resources
+ * registered with this validation context.
+ * @ctx: The validation context.
+ * @backoff: Whether this is a backoff- of a commit-type operation. This
+ * is used to determine whether to switch backup MOBs or not.
+ */
+void vmw_validation_res_unreserve(struct vmw_validation_context *ctx,
+ bool backoff)
+{
+ struct vmw_validation_res_node *val;
+
+ list_splice_init(&ctx->resource_ctx_list, &ctx->resource_list);
+
+ list_for_each_entry(val, &ctx->resource_list, head) {
+ if (val->reserved)
+ vmw_resource_unreserve(val->res,
+ !backoff &&
+ val->switching_backup,
+ val->new_backup,
+ val->new_backup_offset);
+ }
+}
+
+/**
+ * vmw_validation_bo_validate_single - Validate a single buffer object.
+ * @bo: The TTM buffer object base.
+ * @interruptible: Whether to perform waits interruptible if possible.
+ * @validate_as_mob: Whether to validate in MOB memory.
+ *
+ * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error
+ * code on failure.
+ */
+int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo,
+ bool interruptible,
+ bool validate_as_mob)
+{
+ struct vmw_buffer_object *vbo =
+ container_of(bo, struct vmw_buffer_object, base);
+ struct ttm_operation_ctx ctx = {
+ .interruptible = interruptible,
+ .no_wait_gpu = false
+ };
+ int ret;
+
+ if (vbo->pin_count > 0)
+ return 0;
+
+ if (validate_as_mob)
+ return ttm_bo_validate(bo, &vmw_mob_placement, &ctx);
+
+ /**
+ * Put BO in VRAM if there is space, otherwise as a GMR.
+ * If there is no space in VRAM and GMR ids are all used up,
+ * start evicting GMRs to make room. If the DMA buffer can't be
+ * used as a GMR, this will return -ENOMEM.
+ */
+
+ ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx);
+ if (ret == 0 || ret == -ERESTARTSYS)
+ return ret;
+
+ /**
+ * If that failed, try VRAM again, this time evicting
+ * previous contents.
+ */
+
+ ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx);
+ return ret;
+}
+
+/**
+ * vmw_validation_bo_validate - Validate all buffer objects registered with
+ * the validation context.
+ * @ctx: The validation context.
+ * @intr: Whether to perform waits interruptible if possible.
+ *
+ * Return: Zero on success, -ERESTARTSYS if interrupted,
+ * negative error code on failure.
+ */
+int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr)
+{
+ struct vmw_validation_bo_node *entry;
+ int ret;
+
+ list_for_each_entry(entry, &ctx->bo_list, base.head) {
+ if (entry->cpu_blit) {
+ struct ttm_operation_ctx ctx = {
+ .interruptible = intr,
+ .no_wait_gpu = false
+ };
+
+ ret = ttm_bo_validate(entry->base.bo,
+ &vmw_nonfixed_placement, &ctx);
+ } else {
+ ret = vmw_validation_bo_validate_single
+ (entry->base.bo, intr, entry->as_mob);
+ }
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+/**
+ * vmw_validation_res_validate - Validate all resources registered with the
+ * validation context.
+ * @ctx: The validation context.
+ * @intr: Whether to perform waits interruptible if possible.
+ *
+ * Before this function is called, all resource backup buffers must have
+ * been validated.
+ *
+ * Return: Zero on success, -ERESTARTSYS if interrupted,
+ * negative error code on failure.
+ */
+int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr)
+{
+ struct vmw_validation_res_node *val;
+ int ret;
+
+ list_for_each_entry(val, &ctx->resource_list, head) {
+ struct vmw_resource *res = val->res;
+ struct vmw_buffer_object *backup = res->backup;
+
+ ret = vmw_resource_validate(res, intr);
+ if (ret) {
+ if (ret != -ERESTARTSYS)
+ DRM_ERROR("Failed to validate resource.\n");
+ return ret;
+ }
+
+ /* Check if the resource switched backup buffer */
+ if (backup && res->backup && (backup != res->backup)) {
+ struct vmw_buffer_object *vbo = res->backup;
+
+ ret = vmw_validation_add_bo
+ (ctx, vbo, vmw_resource_needs_backup(res),
+ false);
+ if (ret)
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/**
+ * vmw_validation_drop_ht - Reset the hash table used for duplicate finding
+ * and unregister it from this validation context.
+ * @ctx: The validation context.
+ *
+ * The hash table used for duplicate finding is an expensive resource and
+ * may be protected by mutexes that may cause deadlocks during resource
+ * unreferencing if held. After resource- and buffer object registering,
+ * there is no longer any use for this hash table, so allow freeing it
+ * either to shorten any mutex locking time, or before resources- and
+ * buffer objects are freed during validation context cleanup.
+ */
+void vmw_validation_drop_ht(struct vmw_validation_context *ctx)
+{
+ struct vmw_validation_bo_node *entry;
+ struct vmw_validation_res_node *val;
+
+ if (!ctx->ht)
+ return;
+
+ list_for_each_entry(entry, &ctx->bo_list, base.head)
+ (void) drm_ht_remove_item(ctx->ht, &entry->hash);
+
+ list_for_each_entry(val, &ctx->resource_list, head)
+ (void) drm_ht_remove_item(ctx->ht, &val->hash);
+
+ list_for_each_entry(val, &ctx->resource_ctx_list, head)
+ (void) drm_ht_remove_item(ctx->ht, &val->hash);
+
+ ctx->ht = NULL;
+}
+
+/**
+ * vmw_validation_unref_lists - Unregister previously registered buffer
+ * object and resources.
+ * @ctx: The validation context.
+ *
+ * Note that this function may cause buffer object- and resource destructors
+ * to be invoked.
+ */
+void vmw_validation_unref_lists(struct vmw_validation_context *ctx)
+{
+ struct vmw_validation_bo_node *entry;
+ struct vmw_validation_res_node *val;
+
+ list_for_each_entry(entry, &ctx->bo_list, base.head)
+ ttm_bo_unref(&entry->base.bo);
+
+ list_splice_init(&ctx->resource_ctx_list, &ctx->resource_list);
+ list_for_each_entry(val, &ctx->resource_list, head)
+ vmw_resource_unreference(&val->res);
+
+ /*
+ * No need to detach each list entry since they are all freed with
+ * vmw_validation_free_mem. Just make the inaccessible.
+ */
+ INIT_LIST_HEAD(&ctx->bo_list);
+ INIT_LIST_HEAD(&ctx->resource_list);
+
+ vmw_validation_mem_free(ctx);
+}
+
+/**
+ * vmw_validation_prepare - Prepare a validation context for command
+ * submission.
+ * @ctx: The validation context.
+ * @mutex: The mutex used to protect resource reservation.
+ * @intr: Whether to perform waits interruptible if possible.
+ *
+ * Note that the single reservation mutex @mutex is an unfortunate
+ * construct. Ideally resource reservation should be moved to per-resource
+ * ww_mutexes.
+ * If this functions doesn't return Zero to indicate success, all resources
+ * are left unreserved but still referenced.
+ * Return: Zero on success, -ERESTARTSYS if interrupted, negative error code
+ * on error.
+ */
+int vmw_validation_prepare(struct vmw_validation_context *ctx,
+ struct mutex *mutex,
+ bool intr)
+{
+ int ret = 0;
+
+ if (mutex) {
+ if (intr)
+ ret = mutex_lock_interruptible(mutex);
+ else
+ mutex_lock(mutex);
+ if (ret)
+ return -ERESTARTSYS;
+ }
+
+ ctx->res_mutex = mutex;
+ ret = vmw_validation_res_reserve(ctx, intr);
+ if (ret)
+ goto out_no_res_reserve;
+
+ ret = vmw_validation_bo_reserve(ctx, intr);
+ if (ret)
+ goto out_no_bo_reserve;
+
+ ret = vmw_validation_bo_validate(ctx, intr);
+ if (ret)
+ goto out_no_validate;
+
+ ret = vmw_validation_res_validate(ctx, intr);
+ if (ret)
+ goto out_no_validate;
+
+ return 0;
+
+out_no_validate:
+ vmw_validation_bo_backoff(ctx);
+out_no_bo_reserve:
+ vmw_validation_res_unreserve(ctx, true);
+out_no_res_reserve:
+ if (mutex)
+ mutex_unlock(mutex);
+
+ return ret;
+}
+
+/**
+ * vmw_validation_revert - Revert validation actions if command submission
+ * failed.
+ *
+ * @ctx: The validation context.
+ *
+ * The caller still needs to unref resources after a call to this function.
+ */
+void vmw_validation_revert(struct vmw_validation_context *ctx)
+{
+ vmw_validation_bo_backoff(ctx);
+ vmw_validation_res_unreserve(ctx, true);
+ if (ctx->res_mutex)
+ mutex_unlock(ctx->res_mutex);
+ vmw_validation_unref_lists(ctx);
+}
+
+/**
+ * vmw_validation_cone - Commit validation actions after command submission
+ * success.
+ * @ctx: The validation context.
+ * @fence: Fence with which to fence all buffer objects taking part in the
+ * command submission.
+ *
+ * The caller does NOT need to unref resources after a call to this function.
+ */
+void vmw_validation_done(struct vmw_validation_context *ctx,
+ struct vmw_fence_obj *fence)
+{
+ vmw_validation_bo_fence(ctx, fence);
+ vmw_validation_res_unreserve(ctx, false);
+ if (ctx->res_mutex)
+ mutex_unlock(ctx->res_mutex);
+ vmw_validation_unref_lists(ctx);
+}
+
+/**
+ * vmw_validation_preload_bo - Preload the validation memory allocator for a
+ * call to vmw_validation_add_bo().
+ * @ctx: Pointer to the validation context.
+ *
+ * Iff this function returns successfully, the next call to
+ * vmw_validation_add_bo() is guaranteed not to sleep. An error is not fatal
+ * but voids the guarantee.
+ *
+ * Returns: Zero if successful, %-EINVAL otherwise.
+ */
+int vmw_validation_preload_bo(struct vmw_validation_context *ctx)
+{
+ unsigned int size = sizeof(struct vmw_validation_bo_node);
+
+ if (!vmw_validation_mem_alloc(ctx, size))
+ return -ENOMEM;
+
+ ctx->mem_size_left += size;
+ return 0;
+}
+
+/**
+ * vmw_validation_preload_res - Preload the validation memory allocator for a
+ * call to vmw_validation_add_res().
+ * @ctx: Pointer to the validation context.
+ * @size: Size of the validation node extra data. See below.
+ *
+ * Iff this function returns successfully, the next call to
+ * vmw_validation_add_res() with the same or smaller @size is guaranteed not to
+ * sleep. An error is not fatal but voids the guarantee.
+ *
+ * Returns: Zero if successful, %-EINVAL otherwise.
+ */
+int vmw_validation_preload_res(struct vmw_validation_context *ctx,
+ unsigned int size)
+{
+ size = vmw_validation_align(sizeof(struct vmw_validation_res_node) +
+ size) +
+ vmw_validation_align(sizeof(struct vmw_validation_bo_node));
+ if (!vmw_validation_mem_alloc(ctx, size))
+ return -ENOMEM;
+
+ ctx->mem_size_left += size;
+ return 0;
+}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
new file mode 100644
index 000000000000..b57e3292c386
--- /dev/null
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+/**************************************************************************
+ *
+ * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+#ifndef _VMWGFX_VALIDATION_H_
+#define _VMWGFX_VALIDATION_H_
+
+#include <drm/drm_hashtab.h>
+#include <linux/list.h>
+#include <linux/ww_mutex.h>
+#include <drm/ttm/ttm_execbuf_util.h>
+
+/**
+ * struct vmw_validation_context - Per command submission validation context
+ * @ht: Hash table used to find resource- or buffer object duplicates
+ * @resource_list: List head for resource validation metadata
+ * @resource_ctx_list: List head for resource validation metadata for
+ * resources that need to be validated before those in @resource_list
+ * @bo_list: List head for buffer objects
+ * @page_list: List of pages used by the memory allocator
+ * @ticket: Ticked used for ww mutex locking
+ * @res_mutex: Pointer to mutex used for resource reserving
+ * @merge_dups: Whether to merge metadata for duplicate resources or
+ * buffer objects
+ * @mem_size_left: Free memory left in the last page in @page_list
+ * @page_address: Kernel virtual address of the last page in @page_list
+ */
+struct vmw_validation_context {
+ struct drm_open_hash *ht;
+ struct list_head resource_list;
+ struct list_head resource_ctx_list;
+ struct list_head bo_list;
+ struct list_head page_list;
+ struct ww_acquire_ctx ticket;
+ struct mutex *res_mutex;
+ unsigned int merge_dups;
+ unsigned int mem_size_left;
+ u8 *page_address;
+};
+
+struct vmw_buffer_object;
+struct vmw_resource;
+struct vmw_fence_obj;
+
+#if 0
+/**
+ * DECLARE_VAL_CONTEXT - Declare a validation context with initialization
+ * @_name: The name of the variable
+ * @_ht: The hash table used to find dups or NULL if none
+ * @_merge_dups: Whether to merge duplicate buffer object- or resource
+ * entries. If set to true, ideally a hash table pointer should be supplied
+ * as well unless the number of resources and buffer objects per validation
+ * is known to be very small
+ */
+#endif
+#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups) \
+ struct vmw_validation_context _name = \
+ { .ht = _ht, \
+ .resource_list = LIST_HEAD_INIT((_name).resource_list), \
+ .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \
+ .bo_list = LIST_HEAD_INIT((_name).bo_list), \
+ .page_list = LIST_HEAD_INIT((_name).page_list), \
+ .res_mutex = NULL, \
+ .merge_dups = _merge_dups, \
+ .mem_size_left = 0, \
+ }
+
+/**
+ * vmw_validation_has_bos - return whether the validation context has
+ * any buffer objects registered.
+ *
+ * @ctx: The validation context
+ * Returns: Whether any buffer objects are registered
+ */
+static inline bool
+vmw_validation_has_bos(struct vmw_validation_context *ctx)
+{
+ return !list_empty(&ctx->bo_list);
+}
+
+/**
+ * vmw_validation_set_ht - Register a hash table for duplicate finding
+ * @ctx: The validation context
+ * @ht: Pointer to a hash table to use for duplicate finding
+ * This function is intended to be used if the hash table wasn't
+ * available at validation context declaration time
+ */
+static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx,
+ struct drm_open_hash *ht)
+{
+ ctx->ht = ht;
+}
+
+/**
+ * vmw_validation_bo_reserve - Reserve buffer objects registered with a
+ * validation context
+ * @ctx: The validation context
+ * @intr: Perform waits interruptible
+ *
+ * Return: Zero on success, -ERESTARTSYS when interrupted, negative error
+ * code on failure
+ */
+static inline int
+vmw_validation_bo_reserve(struct vmw_validation_context *ctx,
+ bool intr)
+{
+ return ttm_eu_reserve_buffers(&ctx->ticket, &ctx->bo_list, intr,
+ NULL);
+}
+
+/**
+ * vmw_validation_bo_backoff - Unreserve buffer objects registered with a
+ * validation context
+ * @ctx: The validation context
+ *
+ * This function unreserves the buffer objects previously reserved using
+ * vmw_validation_bo_reserve. It's typically used as part of an error path
+ */
+static inline void
+vmw_validation_bo_backoff(struct vmw_validation_context *ctx)
+{
+ ttm_eu_backoff_reservation(&ctx->ticket, &ctx->bo_list);
+}
+
+/**
+ * vmw_validation_bo_fence - Unreserve and fence buffer objects registered
+ * with a validation context
+ * @ctx: The validation context
+ *
+ * This function unreserves the buffer objects previously reserved using
+ * vmw_validation_bo_reserve, and fences them with a fence object.
+ */
+static inline void
+vmw_validation_bo_fence(struct vmw_validation_context *ctx,
+ struct vmw_fence_obj *fence)
+{
+ ttm_eu_fence_buffer_objects(&ctx->ticket, &ctx->bo_list,
+ (void *) fence);
+}
+
+/**
+ * vmw_validation_context_init - Initialize a validation context
+ * @ctx: Pointer to the validation context to initialize
+ *
+ * This function initializes a validation context with @merge_dups set
+ * to false
+ */
+static inline void
+vmw_validation_context_init(struct vmw_validation_context *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ INIT_LIST_HEAD(&ctx->resource_list);
+ INIT_LIST_HEAD(&ctx->resource_ctx_list);
+ INIT_LIST_HEAD(&ctx->bo_list);
+}
+
+/**
+ * vmw_validation_align - Align a validation memory allocation
+ * @val: The size to be aligned
+ *
+ * Returns: @val aligned to the granularity used by the validation memory
+ * allocator.
+ */
+static inline unsigned int vmw_validation_align(unsigned int val)
+{
+ return ALIGN(val, sizeof(long));
+}
+
+int vmw_validation_add_bo(struct vmw_validation_context *ctx,
+ struct vmw_buffer_object *vbo,
+ bool as_mob, bool cpu_blit);
+int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo,
+ bool interruptible,
+ bool validate_as_mob);
+int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr);
+void vmw_validation_unref_lists(struct vmw_validation_context *ctx);
+int vmw_validation_add_resource(struct vmw_validation_context *ctx,
+ struct vmw_resource *res,
+ size_t priv_size,
+ void **p_node,
+ bool *first_usage);
+void vmw_validation_drop_ht(struct vmw_validation_context *ctx);
+int vmw_validation_res_reserve(struct vmw_validation_context *ctx,
+ bool intr);
+void vmw_validation_res_unreserve(struct vmw_validation_context *ctx,
+ bool backoff);
+void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx,
+ void *val_private,
+ struct vmw_buffer_object *vbo,
+ unsigned long backup_offset);
+int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr);
+
+int vmw_validation_prepare(struct vmw_validation_context *ctx,
+ struct mutex *mutex, bool intr);
+void vmw_validation_revert(struct vmw_validation_context *ctx);
+void vmw_validation_done(struct vmw_validation_context *ctx,
+ struct vmw_fence_obj *fence);
+
+void *vmw_validation_mem_alloc(struct vmw_validation_context *ctx,
+ unsigned int size);
+int vmw_validation_preload_bo(struct vmw_validation_context *ctx);
+int vmw_validation_preload_res(struct vmw_validation_context *ctx,
+ unsigned int size);
+#endif
diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c
index da962aa2cef5..fc6b7f8b62fb 100644
--- a/drivers/hwtracing/intel_th/core.c
+++ b/drivers/hwtracing/intel_th/core.c
@@ -139,7 +139,8 @@ static int intel_th_remove(struct device *dev)
th->thdev[i] = NULL;
}
- th->num_thdevs = lowest;
+ if (lowest >= 0)
+ th->num_thdevs = lowest;
}
if (thdrv->attr_group)
@@ -487,7 +488,7 @@ static const struct intel_th_subdevice {
.flags = IORESOURCE_MEM,
},
{
- .start = TH_MMIO_SW,
+ .start = 1, /* use resource[1] */
.end = 0,
.flags = IORESOURCE_MEM,
},
@@ -580,6 +581,7 @@ intel_th_subdevice_alloc(struct intel_th *th,
struct intel_th_device *thdev;
struct resource res[3];
unsigned int req = 0;
+ bool is64bit = false;
int r, err;
thdev = intel_th_device_alloc(th, subdev->type, subdev->name,
@@ -589,12 +591,18 @@ intel_th_subdevice_alloc(struct intel_th *th,
thdev->drvdata = th->drvdata;
+ for (r = 0; r < th->num_resources; r++)
+ if (th->resource[r].flags & IORESOURCE_MEM_64) {
+ is64bit = true;
+ break;
+ }
+
memcpy(res, subdev->res,
sizeof(struct resource) * subdev->nres);
for (r = 0; r < subdev->nres; r++) {
struct resource *devres = th->resource;
- int bar = TH_MMIO_CONFIG;
+ int bar = 0; /* cut subdevices' MMIO from resource[0] */
/*
* Take .end == 0 to mean 'take the whole bar',
@@ -603,6 +611,8 @@ intel_th_subdevice_alloc(struct intel_th *th,
*/
if (!res[r].end && res[r].flags == IORESOURCE_MEM) {
bar = res[r].start;
+ if (is64bit)
+ bar *= 2;
res[r].start = 0;
res[r].end = resource_size(&devres[bar]) - 1;
}
diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
index c2e55e5d97f6..1cf6290d6435 100644
--- a/drivers/hwtracing/intel_th/pci.c
+++ b/drivers/hwtracing/intel_th/pci.c
@@ -160,6 +160,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1),
.driver_data = (kernel_ulong_t)&intel_th_2x,
},
+ {
+ /* Ice Lake PCH */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x34a6),
+ .driver_data = (kernel_ulong_t)&intel_th_2x,
+ },
{ 0 },
};
diff --git a/drivers/infiniband/core/cache.c b/drivers/infiniband/core/cache.c
index 0bee1f4b914e..3208ad6ad540 100644
--- a/drivers/infiniband/core/cache.c
+++ b/drivers/infiniband/core/cache.c
@@ -338,6 +338,39 @@ static int add_roce_gid(struct ib_gid_table_entry *entry)
}
/**
+ * del_gid - Delete GID table entry
+ *
+ * @ib_dev: IB device whose GID entry to be deleted
+ * @port: Port number of the IB device
+ * @table: GID table of the IB device for a port
+ * @ix: GID entry index to delete
+ *
+ */
+static void del_gid(struct ib_device *ib_dev, u8 port,
+ struct ib_gid_table *table, int ix)
+{
+ struct ib_gid_table_entry *entry;
+
+ lockdep_assert_held(&table->lock);
+
+ pr_debug("%s device=%s port=%d index=%d gid %pI6\n", __func__,
+ ib_dev->name, port, ix,
+ table->data_vec[ix]->attr.gid.raw);
+
+ write_lock_irq(&table->rwlock);
+ entry = table->data_vec[ix];
+ entry->state = GID_TABLE_ENTRY_PENDING_DEL;
+ /*
+ * For non RoCE protocol, GID entry slot is ready to use.
+ */
+ if (!rdma_protocol_roce(ib_dev, port))
+ table->data_vec[ix] = NULL;
+ write_unlock_irq(&table->rwlock);
+
+ put_gid_entry_locked(entry);
+}
+
+/**
* add_modify_gid - Add or modify GID table entry
*
* @table: GID table in which GID to be added or modified
@@ -358,7 +391,7 @@ static int add_modify_gid(struct ib_gid_table *table,
* this index.
*/
if (is_gid_entry_valid(table->data_vec[attr->index]))
- put_gid_entry(table->data_vec[attr->index]);
+ del_gid(attr->device, attr->port_num, table, attr->index);
/*
* Some HCA's report multiple GID entries with only one valid GID, and
@@ -386,39 +419,6 @@ done:
return ret;
}
-/**
- * del_gid - Delete GID table entry
- *
- * @ib_dev: IB device whose GID entry to be deleted
- * @port: Port number of the IB device
- * @table: GID table of the IB device for a port
- * @ix: GID entry index to delete
- *
- */
-static void del_gid(struct ib_device *ib_dev, u8 port,
- struct ib_gid_table *table, int ix)
-{
- struct ib_gid_table_entry *entry;
-
- lockdep_assert_held(&table->lock);
-
- pr_debug("%s device=%s port=%d index=%d gid %pI6\n", __func__,
- ib_dev->name, port, ix,
- table->data_vec[ix]->attr.gid.raw);
-
- write_lock_irq(&table->rwlock);
- entry = table->data_vec[ix];
- entry->state = GID_TABLE_ENTRY_PENDING_DEL;
- /*
- * For non RoCE protocol, GID entry slot is ready to use.
- */
- if (!rdma_protocol_roce(ib_dev, port))
- table->data_vec[ix] = NULL;
- write_unlock_irq(&table->rwlock);
-
- put_gid_entry_locked(entry);
-}
-
/* rwlock should be read locked, or lock should be held */
static int find_gid(struct ib_gid_table *table, const union ib_gid *gid,
const struct ib_gid_attr *val, bool default_gid,
diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c
index 5f437d1570fb..21863ddde63e 100644
--- a/drivers/infiniband/core/ucma.c
+++ b/drivers/infiniband/core/ucma.c
@@ -1759,6 +1759,8 @@ static int ucma_close(struct inode *inode, struct file *filp)
mutex_lock(&mut);
if (!ctx->closing) {
mutex_unlock(&mut);
+ ucma_put_ctx(ctx);
+ wait_for_completion(&ctx->comp);
/* rdma_destroy_id ensures that no event handlers are
* inflight for that id before releasing it.
*/
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index a21d5214afc3..e012ca80f9d1 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -2027,33 +2027,55 @@ static int modify_qp(struct ib_uverbs_file *file,
if ((cmd->base.attr_mask & IB_QP_CUR_STATE &&
cmd->base.cur_qp_state > IB_QPS_ERR) ||
- cmd->base.qp_state > IB_QPS_ERR) {
+ (cmd->base.attr_mask & IB_QP_STATE &&
+ cmd->base.qp_state > IB_QPS_ERR)) {
ret = -EINVAL;
goto release_qp;
}
- attr->qp_state = cmd->base.qp_state;
- attr->cur_qp_state = cmd->base.cur_qp_state;
- attr->path_mtu = cmd->base.path_mtu;
- attr->path_mig_state = cmd->base.path_mig_state;
- attr->qkey = cmd->base.qkey;
- attr->rq_psn = cmd->base.rq_psn;
- attr->sq_psn = cmd->base.sq_psn;
- attr->dest_qp_num = cmd->base.dest_qp_num;
- attr->qp_access_flags = cmd->base.qp_access_flags;
- attr->pkey_index = cmd->base.pkey_index;
- attr->alt_pkey_index = cmd->base.alt_pkey_index;
- attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify;
- attr->max_rd_atomic = cmd->base.max_rd_atomic;
- attr->max_dest_rd_atomic = cmd->base.max_dest_rd_atomic;
- attr->min_rnr_timer = cmd->base.min_rnr_timer;
- attr->port_num = cmd->base.port_num;
- attr->timeout = cmd->base.timeout;
- attr->retry_cnt = cmd->base.retry_cnt;
- attr->rnr_retry = cmd->base.rnr_retry;
- attr->alt_port_num = cmd->base.alt_port_num;
- attr->alt_timeout = cmd->base.alt_timeout;
- attr->rate_limit = cmd->rate_limit;
+ if (cmd->base.attr_mask & IB_QP_STATE)
+ attr->qp_state = cmd->base.qp_state;
+ if (cmd->base.attr_mask & IB_QP_CUR_STATE)
+ attr->cur_qp_state = cmd->base.cur_qp_state;
+ if (cmd->base.attr_mask & IB_QP_PATH_MTU)
+ attr->path_mtu = cmd->base.path_mtu;
+ if (cmd->base.attr_mask & IB_QP_PATH_MIG_STATE)
+ attr->path_mig_state = cmd->base.path_mig_state;
+ if (cmd->base.attr_mask & IB_QP_QKEY)
+ attr->qkey = cmd->base.qkey;
+ if (cmd->base.attr_mask & IB_QP_RQ_PSN)
+ attr->rq_psn = cmd->base.rq_psn;
+ if (cmd->base.attr_mask & IB_QP_SQ_PSN)
+ attr->sq_psn = cmd->base.sq_psn;
+ if (cmd->base.attr_mask & IB_QP_DEST_QPN)
+ attr->dest_qp_num = cmd->base.dest_qp_num;
+ if (cmd->base.attr_mask & IB_QP_ACCESS_FLAGS)
+ attr->qp_access_flags = cmd->base.qp_access_flags;
+ if (cmd->base.attr_mask & IB_QP_PKEY_INDEX)
+ attr->pkey_index = cmd->base.pkey_index;
+ if (cmd->base.attr_mask & IB_QP_EN_SQD_ASYNC_NOTIFY)
+ attr->en_sqd_async_notify = cmd->base.en_sqd_async_notify;
+ if (cmd->base.attr_mask & IB_QP_MAX_QP_RD_ATOMIC)
+ attr->max_rd_atomic = cmd->base.max_rd_atomic;
+ if (cmd->base.attr_mask & IB_QP_MAX_DEST_RD_ATOMIC)
+ attr->max_dest_rd_atomic = cmd->base.max_dest_rd_atomic;
+ if (cmd->base.attr_mask & IB_QP_MIN_RNR_TIMER)
+ attr->min_rnr_timer = cmd->base.min_rnr_timer;
+ if (cmd->base.attr_mask & IB_QP_PORT)
+ attr->port_num = cmd->base.port_num;
+ if (cmd->base.attr_mask & IB_QP_TIMEOUT)
+ attr->timeout = cmd->base.timeout;
+ if (cmd->base.attr_mask & IB_QP_RETRY_CNT)
+ attr->retry_cnt = cmd->base.retry_cnt;
+ if (cmd->base.attr_mask & IB_QP_RNR_RETRY)
+ attr->rnr_retry = cmd->base.rnr_retry;
+ if (cmd->base.attr_mask & IB_QP_ALT_PATH) {
+ attr->alt_port_num = cmd->base.alt_port_num;
+ attr->alt_timeout = cmd->base.alt_timeout;
+ attr->alt_pkey_index = cmd->base.alt_pkey_index;
+ }
+ if (cmd->base.attr_mask & IB_QP_RATE_LIMIT)
+ attr->rate_limit = cmd->rate_limit;
if (cmd->base.attr_mask & IB_QP_AV)
copy_ah_attr_from_uverbs(qp->device, &attr->ah_attr,
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 6d974e2363df..50152c1b1004 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -440,6 +440,7 @@ static int ib_uverbs_comp_event_close(struct inode *inode, struct file *filp)
list_del(&entry->obj_list);
kfree(entry);
}
+ file->ev_queue.is_closed = 1;
spin_unlock_irq(&file->ev_queue.lock);
uverbs_close_fd(filp);
diff --git a/drivers/infiniband/core/uverbs_uapi.c b/drivers/infiniband/core/uverbs_uapi.c
index 73ea6f0db88f..be854628a7c6 100644
--- a/drivers/infiniband/core/uverbs_uapi.c
+++ b/drivers/infiniband/core/uverbs_uapi.c
@@ -248,6 +248,7 @@ void uverbs_destroy_api(struct uverbs_api *uapi)
kfree(rcu_dereference_protected(*slot, true));
radix_tree_iter_delete(&uapi->radix, &iter, slot);
}
+ kfree(uapi);
}
struct uverbs_api *uverbs_alloc_api(
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index 20b9f31052bf..85cd1a3593d6 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -78,7 +78,7 @@ static struct list_head bnxt_re_dev_list = LIST_HEAD_INIT(bnxt_re_dev_list);
/* Mutex to protect the list of bnxt_re devices added */
static DEFINE_MUTEX(bnxt_re_dev_lock);
static struct workqueue_struct *bnxt_re_wq;
-static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev, bool lock_wait);
+static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev);
/* SR-IOV helper functions */
@@ -182,7 +182,7 @@ static void bnxt_re_shutdown(void *p)
if (!rdev)
return;
- bnxt_re_ib_unreg(rdev, false);
+ bnxt_re_ib_unreg(rdev);
}
static void bnxt_re_stop_irq(void *handle)
@@ -251,7 +251,7 @@ static struct bnxt_ulp_ops bnxt_re_ulp_ops = {
/* Driver registration routines used to let the networking driver (bnxt_en)
* to know that the RoCE driver is now installed
*/
-static int bnxt_re_unregister_netdev(struct bnxt_re_dev *rdev, bool lock_wait)
+static int bnxt_re_unregister_netdev(struct bnxt_re_dev *rdev)
{
struct bnxt_en_dev *en_dev;
int rc;
@@ -260,14 +260,9 @@ static int bnxt_re_unregister_netdev(struct bnxt_re_dev *rdev, bool lock_wait)
return -EINVAL;
en_dev = rdev->en_dev;
- /* Acquire rtnl lock if it is not invokded from netdev event */
- if (lock_wait)
- rtnl_lock();
rc = en_dev->en_ops->bnxt_unregister_device(rdev->en_dev,
BNXT_ROCE_ULP);
- if (lock_wait)
- rtnl_unlock();
return rc;
}
@@ -281,14 +276,12 @@ static int bnxt_re_register_netdev(struct bnxt_re_dev *rdev)
en_dev = rdev->en_dev;
- rtnl_lock();
rc = en_dev->en_ops->bnxt_register_device(en_dev, BNXT_ROCE_ULP,
&bnxt_re_ulp_ops, rdev);
- rtnl_unlock();
return rc;
}
-static int bnxt_re_free_msix(struct bnxt_re_dev *rdev, bool lock_wait)
+static int bnxt_re_free_msix(struct bnxt_re_dev *rdev)
{
struct bnxt_en_dev *en_dev;
int rc;
@@ -298,13 +291,9 @@ static int bnxt_re_free_msix(struct bnxt_re_dev *rdev, bool lock_wait)
en_dev = rdev->en_dev;
- if (lock_wait)
- rtnl_lock();
rc = en_dev->en_ops->bnxt_free_msix(rdev->en_dev, BNXT_ROCE_ULP);
- if (lock_wait)
- rtnl_unlock();
return rc;
}
@@ -320,7 +309,6 @@ static int bnxt_re_request_msix(struct bnxt_re_dev *rdev)
num_msix_want = min_t(u32, BNXT_RE_MAX_MSIX, num_online_cpus());
- rtnl_lock();
num_msix_got = en_dev->en_ops->bnxt_request_msix(en_dev, BNXT_ROCE_ULP,
rdev->msix_entries,
num_msix_want);
@@ -335,7 +323,6 @@ static int bnxt_re_request_msix(struct bnxt_re_dev *rdev)
}
rdev->num_msix = num_msix_got;
done:
- rtnl_unlock();
return rc;
}
@@ -358,24 +345,18 @@ static void bnxt_re_fill_fw_msg(struct bnxt_fw_msg *fw_msg, void *msg,
fw_msg->timeout = timeout;
}
-static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev, u16 fw_ring_id,
- bool lock_wait)
+static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev, u16 fw_ring_id)
{
struct bnxt_en_dev *en_dev = rdev->en_dev;
struct hwrm_ring_free_input req = {0};
struct hwrm_ring_free_output resp;
struct bnxt_fw_msg fw_msg;
- bool do_unlock = false;
int rc = -EINVAL;
if (!en_dev)
return rc;
memset(&fw_msg, 0, sizeof(fw_msg));
- if (lock_wait) {
- rtnl_lock();
- do_unlock = true;
- }
bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_FREE, -1, -1);
req.ring_type = RING_ALLOC_REQ_RING_TYPE_L2_CMPL;
@@ -386,8 +367,6 @@ static int bnxt_re_net_ring_free(struct bnxt_re_dev *rdev, u16 fw_ring_id,
if (rc)
dev_err(rdev_to_dev(rdev),
"Failed to free HW ring:%d :%#x", req.ring_id, rc);
- if (do_unlock)
- rtnl_unlock();
return rc;
}
@@ -405,7 +384,6 @@ static int bnxt_re_net_ring_alloc(struct bnxt_re_dev *rdev, dma_addr_t *dma_arr,
return rc;
memset(&fw_msg, 0, sizeof(fw_msg));
- rtnl_lock();
bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_RING_ALLOC, -1, -1);
req.enables = 0;
req.page_tbl_addr = cpu_to_le64(dma_arr[0]);
@@ -426,27 +404,21 @@ static int bnxt_re_net_ring_alloc(struct bnxt_re_dev *rdev, dma_addr_t *dma_arr,
if (!rc)
*fw_ring_id = le16_to_cpu(resp.ring_id);
- rtnl_unlock();
return rc;
}
static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev,
- u32 fw_stats_ctx_id, bool lock_wait)
+ u32 fw_stats_ctx_id)
{
struct bnxt_en_dev *en_dev = rdev->en_dev;
struct hwrm_stat_ctx_free_input req = {0};
struct bnxt_fw_msg fw_msg;
- bool do_unlock = false;
int rc = -EINVAL;
if (!en_dev)
return rc;
memset(&fw_msg, 0, sizeof(fw_msg));
- if (lock_wait) {
- rtnl_lock();
- do_unlock = true;
- }
bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_FREE, -1, -1);
req.stat_ctx_id = cpu_to_le32(fw_stats_ctx_id);
@@ -457,8 +429,6 @@ static int bnxt_re_net_stats_ctx_free(struct bnxt_re_dev *rdev,
dev_err(rdev_to_dev(rdev),
"Failed to free HW stats context %#x", rc);
- if (do_unlock)
- rtnl_unlock();
return rc;
}
@@ -478,7 +448,6 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev,
return rc;
memset(&fw_msg, 0, sizeof(fw_msg));
- rtnl_lock();
bnxt_re_init_hwrm_hdr(rdev, (void *)&req, HWRM_STAT_CTX_ALLOC, -1, -1);
req.update_period_ms = cpu_to_le32(1000);
@@ -490,7 +459,6 @@ static int bnxt_re_net_stats_ctx_alloc(struct bnxt_re_dev *rdev,
if (!rc)
*fw_stats_ctx_id = le32_to_cpu(resp.stat_ctx_id);
- rtnl_unlock();
return rc;
}
@@ -929,19 +897,19 @@ fail:
return rc;
}
-static void bnxt_re_free_nq_res(struct bnxt_re_dev *rdev, bool lock_wait)
+static void bnxt_re_free_nq_res(struct bnxt_re_dev *rdev)
{
int i;
for (i = 0; i < rdev->num_msix - 1; i++) {
- bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id, lock_wait);
+ bnxt_re_net_ring_free(rdev, rdev->nq[i].ring_id);
bnxt_qplib_free_nq(&rdev->nq[i]);
}
}
-static void bnxt_re_free_res(struct bnxt_re_dev *rdev, bool lock_wait)
+static void bnxt_re_free_res(struct bnxt_re_dev *rdev)
{
- bnxt_re_free_nq_res(rdev, lock_wait);
+ bnxt_re_free_nq_res(rdev);
if (rdev->qplib_res.dpi_tbl.max) {
bnxt_qplib_dealloc_dpi(&rdev->qplib_res,
@@ -1219,7 +1187,7 @@ static int bnxt_re_setup_qos(struct bnxt_re_dev *rdev)
return 0;
}
-static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev, bool lock_wait)
+static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev)
{
int i, rc;
@@ -1234,28 +1202,27 @@ static void bnxt_re_ib_unreg(struct bnxt_re_dev *rdev, bool lock_wait)
cancel_delayed_work(&rdev->worker);
bnxt_re_cleanup_res(rdev);
- bnxt_re_free_res(rdev, lock_wait);
+ bnxt_re_free_res(rdev);
if (test_and_clear_bit(BNXT_RE_FLAG_RCFW_CHANNEL_EN, &rdev->flags)) {
rc = bnxt_qplib_deinit_rcfw(&rdev->rcfw);
if (rc)
dev_warn(rdev_to_dev(rdev),
"Failed to deinitialize RCFW: %#x", rc);
- bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id,
- lock_wait);
+ bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id);
bnxt_qplib_free_ctx(rdev->en_dev->pdev, &rdev->qplib_ctx);
bnxt_qplib_disable_rcfw_channel(&rdev->rcfw);
- bnxt_re_net_ring_free(rdev, rdev->rcfw.creq_ring_id, lock_wait);
+ bnxt_re_net_ring_free(rdev, rdev->rcfw.creq_ring_id);
bnxt_qplib_free_rcfw_channel(&rdev->rcfw);
}
if (test_and_clear_bit(BNXT_RE_FLAG_GOT_MSIX, &rdev->flags)) {
- rc = bnxt_re_free_msix(rdev, lock_wait);
+ rc = bnxt_re_free_msix(rdev);
if (rc)
dev_warn(rdev_to_dev(rdev),
"Failed to free MSI-X vectors: %#x", rc);
}
if (test_and_clear_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags)) {
- rc = bnxt_re_unregister_netdev(rdev, lock_wait);
+ rc = bnxt_re_unregister_netdev(rdev);
if (rc)
dev_warn(rdev_to_dev(rdev),
"Failed to unregister with netdev: %#x", rc);
@@ -1276,6 +1243,12 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
{
int i, j, rc;
+ bool locked;
+
+ /* Acquire rtnl lock through out this function */
+ rtnl_lock();
+ locked = true;
+
/* Registered a new RoCE device instance to netdev */
rc = bnxt_re_register_netdev(rdev);
if (rc) {
@@ -1374,12 +1347,16 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
schedule_delayed_work(&rdev->worker, msecs_to_jiffies(30000));
}
+ rtnl_unlock();
+ locked = false;
+
/* Register ib dev */
rc = bnxt_re_register_ib(rdev);
if (rc) {
pr_err("Failed to register with IB: %#x\n", rc);
goto fail;
}
+ set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
dev_info(rdev_to_dev(rdev), "Device registered successfully");
for (i = 0; i < ARRAY_SIZE(bnxt_re_attributes); i++) {
rc = device_create_file(&rdev->ibdev.dev,
@@ -1395,7 +1372,6 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
goto fail;
}
}
- set_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags);
ib_get_eth_speed(&rdev->ibdev, 1, &rdev->active_speed,
&rdev->active_width);
set_bit(BNXT_RE_FLAG_ISSUE_ROCE_STATS, &rdev->flags);
@@ -1404,17 +1380,21 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
return 0;
free_sctx:
- bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id, true);
+ bnxt_re_net_stats_ctx_free(rdev, rdev->qplib_ctx.stats.fw_id);
free_ctx:
bnxt_qplib_free_ctx(rdev->en_dev->pdev, &rdev->qplib_ctx);
disable_rcfw:
bnxt_qplib_disable_rcfw_channel(&rdev->rcfw);
free_ring:
- bnxt_re_net_ring_free(rdev, rdev->rcfw.creq_ring_id, true);
+ bnxt_re_net_ring_free(rdev, rdev->rcfw.creq_ring_id);
free_rcfw:
bnxt_qplib_free_rcfw_channel(&rdev->rcfw);
fail:
- bnxt_re_ib_unreg(rdev, true);
+ if (!locked)
+ rtnl_lock();
+ bnxt_re_ib_unreg(rdev);
+ rtnl_unlock();
+
return rc;
}
@@ -1567,7 +1547,7 @@ static int bnxt_re_netdev_event(struct notifier_block *notifier,
*/
if (atomic_read(&rdev->sched_count) > 0)
goto exit;
- bnxt_re_ib_unreg(rdev, false);
+ bnxt_re_ib_unreg(rdev);
bnxt_re_remove_one(rdev);
bnxt_re_dev_unreg(rdev);
break;
@@ -1646,7 +1626,10 @@ static void __exit bnxt_re_mod_exit(void)
*/
flush_workqueue(bnxt_re_wq);
bnxt_re_dev_stop(rdev);
- bnxt_re_ib_unreg(rdev, true);
+ /* Acquire the rtnl_lock as the L2 resources are freed here */
+ rtnl_lock();
+ bnxt_re_ib_unreg(rdev);
+ rtnl_unlock();
bnxt_re_remove_one(rdev);
bnxt_re_dev_unreg(rdev);
}
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c
index 2c19bf772451..e1668bcc2d13 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -6733,6 +6733,7 @@ void start_freeze_handling(struct hfi1_pportdata *ppd, int flags)
struct hfi1_devdata *dd = ppd->dd;
struct send_context *sc;
int i;
+ int sc_flags;
if (flags & FREEZE_SELF)
write_csr(dd, CCE_CTRL, CCE_CTRL_SPC_FREEZE_SMASK);
@@ -6743,11 +6744,13 @@ void start_freeze_handling(struct hfi1_pportdata *ppd, int flags)
/* notify all SDMA engines that they are going into a freeze */
sdma_freeze_notify(dd, !!(flags & FREEZE_LINK_DOWN));
+ sc_flags = SCF_FROZEN | SCF_HALTED | (flags & FREEZE_LINK_DOWN ?
+ SCF_LINK_DOWN : 0);
/* do halt pre-handling on all enabled send contexts */
for (i = 0; i < dd->num_send_contexts; i++) {
sc = dd->send_contexts[i].sc;
if (sc && (sc->flags & SCF_ENABLED))
- sc_stop(sc, SCF_FROZEN | SCF_HALTED);
+ sc_stop(sc, sc_flags);
}
/* Send context are frozen. Notify user space */
@@ -10674,6 +10677,7 @@ int set_link_state(struct hfi1_pportdata *ppd, u32 state)
add_rcvctrl(dd, RCV_CTRL_RCV_PORT_ENABLE_SMASK);
handle_linkup_change(dd, 1);
+ pio_kernel_linkup(dd);
/*
* After link up, a new link width will have been set.
diff --git a/drivers/infiniband/hw/hfi1/pio.c b/drivers/infiniband/hw/hfi1/pio.c
index c2c1cba5b23b..752057647f09 100644
--- a/drivers/infiniband/hw/hfi1/pio.c
+++ b/drivers/infiniband/hw/hfi1/pio.c
@@ -86,6 +86,7 @@ void pio_send_control(struct hfi1_devdata *dd, int op)
unsigned long flags;
int write = 1; /* write sendctrl back */
int flush = 0; /* re-read sendctrl to make sure it is flushed */
+ int i;
spin_lock_irqsave(&dd->sendctrl_lock, flags);
@@ -95,9 +96,13 @@ void pio_send_control(struct hfi1_devdata *dd, int op)
reg |= SEND_CTRL_SEND_ENABLE_SMASK;
/* Fall through */
case PSC_DATA_VL_ENABLE:
+ mask = 0;
+ for (i = 0; i < ARRAY_SIZE(dd->vld); i++)
+ if (!dd->vld[i].mtu)
+ mask |= BIT_ULL(i);
/* Disallow sending on VLs not enabled */
- mask = (((~0ull) << num_vls) & SEND_CTRL_UNSUPPORTED_VL_MASK) <<
- SEND_CTRL_UNSUPPORTED_VL_SHIFT;
+ mask = (mask & SEND_CTRL_UNSUPPORTED_VL_MASK) <<
+ SEND_CTRL_UNSUPPORTED_VL_SHIFT;
reg = (reg & ~SEND_CTRL_UNSUPPORTED_VL_SMASK) | mask;
break;
case PSC_GLOBAL_DISABLE:
@@ -921,20 +926,18 @@ void sc_free(struct send_context *sc)
void sc_disable(struct send_context *sc)
{
u64 reg;
- unsigned long flags;
struct pio_buf *pbuf;
if (!sc)
return;
/* do all steps, even if already disabled */
- spin_lock_irqsave(&sc->alloc_lock, flags);
+ spin_lock_irq(&sc->alloc_lock);
reg = read_kctxt_csr(sc->dd, sc->hw_context, SC(CTRL));
reg &= ~SC(CTRL_CTXT_ENABLE_SMASK);
sc->flags &= ~SCF_ENABLED;
sc_wait_for_packet_egress(sc, 1);
write_kctxt_csr(sc->dd, sc->hw_context, SC(CTRL), reg);
- spin_unlock_irqrestore(&sc->alloc_lock, flags);
/*
* Flush any waiters. Once the context is disabled,
@@ -944,7 +947,7 @@ void sc_disable(struct send_context *sc)
* proceed with the flush.
*/
udelay(1);
- spin_lock_irqsave(&sc->release_lock, flags);
+ spin_lock(&sc->release_lock);
if (sc->sr) { /* this context has a shadow ring */
while (sc->sr_tail != sc->sr_head) {
pbuf = &sc->sr[sc->sr_tail].pbuf;
@@ -955,7 +958,8 @@ void sc_disable(struct send_context *sc)
sc->sr_tail = 0;
}
}
- spin_unlock_irqrestore(&sc->release_lock, flags);
+ spin_unlock(&sc->release_lock);
+ spin_unlock_irq(&sc->alloc_lock);
}
/* return SendEgressCtxtStatus.PacketOccupancy */
@@ -1178,11 +1182,39 @@ void pio_kernel_unfreeze(struct hfi1_devdata *dd)
sc = dd->send_contexts[i].sc;
if (!sc || !(sc->flags & SCF_FROZEN) || sc->type == SC_USER)
continue;
+ if (sc->flags & SCF_LINK_DOWN)
+ continue;
sc_enable(sc); /* will clear the sc frozen flag */
}
}
+/**
+ * pio_kernel_linkup() - Re-enable send contexts after linkup event
+ * @dd: valid devive data
+ *
+ * When the link goes down, the freeze path is taken. However, a link down
+ * event is different from a freeze because if the send context is re-enabled
+ * whowever is sending data will start sending data again, which will hang
+ * any QP that is sending data.
+ *
+ * The freeze path now looks at the type of event that occurs and takes this
+ * path for link down event.
+ */
+void pio_kernel_linkup(struct hfi1_devdata *dd)
+{
+ struct send_context *sc;
+ int i;
+
+ for (i = 0; i < dd->num_send_contexts; i++) {
+ sc = dd->send_contexts[i].sc;
+ if (!sc || !(sc->flags & SCF_LINK_DOWN) || sc->type == SC_USER)
+ continue;
+
+ sc_enable(sc); /* will clear the sc link down flag */
+ }
+}
+
/*
* Wait for the SendPioInitCtxt.PioInitInProgress bit to clear.
* Returns:
@@ -1382,11 +1414,10 @@ void sc_stop(struct send_context *sc, int flag)
{
unsigned long flags;
- /* mark the context */
- sc->flags |= flag;
-
/* stop buffer allocations */
spin_lock_irqsave(&sc->alloc_lock, flags);
+ /* mark the context */
+ sc->flags |= flag;
sc->flags &= ~SCF_ENABLED;
spin_unlock_irqrestore(&sc->alloc_lock, flags);
wake_up(&sc->halt_wait);
diff --git a/drivers/infiniband/hw/hfi1/pio.h b/drivers/infiniband/hw/hfi1/pio.h
index 058b08f459ab..aaf372c3e5d6 100644
--- a/drivers/infiniband/hw/hfi1/pio.h
+++ b/drivers/infiniband/hw/hfi1/pio.h
@@ -139,6 +139,7 @@ struct send_context {
#define SCF_IN_FREE 0x02
#define SCF_HALTED 0x04
#define SCF_FROZEN 0x08
+#define SCF_LINK_DOWN 0x10
struct send_context_info {
struct send_context *sc; /* allocated working context */
@@ -306,6 +307,7 @@ void set_pio_integrity(struct send_context *sc);
void pio_reset_all(struct hfi1_devdata *dd);
void pio_freeze(struct hfi1_devdata *dd);
void pio_kernel_unfreeze(struct hfi1_devdata *dd);
+void pio_kernel_linkup(struct hfi1_devdata *dd);
/* global PIO send control operations */
#define PSC_GLOBAL_ENABLE 0
diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c
index a3a7b33196d6..5c88706121c1 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -828,7 +828,7 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
if (READ_ONCE(iovec->offset) == iovec->iov.iov_len) {
if (++req->iov_idx == req->data_iovs) {
ret = -EFAULT;
- goto free_txreq;
+ goto free_tx;
}
iovec = &req->iovs[req->iov_idx];
WARN_ON(iovec->offset);
diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c
index 13374c727b14..a7c586a5589d 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1582,6 +1582,7 @@ static int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr)
struct hfi1_pportdata *ppd;
struct hfi1_devdata *dd;
u8 sc5;
+ u8 sl;
if (hfi1_check_mcast(rdma_ah_get_dlid(ah_attr)) &&
!(rdma_ah_get_ah_flags(ah_attr) & IB_AH_GRH))
@@ -1590,8 +1591,13 @@ static int hfi1_check_ah(struct ib_device *ibdev, struct rdma_ah_attr *ah_attr)
/* test the mapping for validity */
ibp = to_iport(ibdev, rdma_ah_get_port_num(ah_attr));
ppd = ppd_from_ibp(ibp);
- sc5 = ibp->sl_to_sc[rdma_ah_get_sl(ah_attr)];
dd = dd_from_ppd(ppd);
+
+ sl = rdma_ah_get_sl(ah_attr);
+ if (sl >= ARRAY_SIZE(ibp->sl_to_sc))
+ return -EINVAL;
+
+ sc5 = ibp->sl_to_sc[sl];
if (sc_to_vlt(dd, sc5) > num_vls && sc_to_vlt(dd, sc5) != 0xf)
return -EINVAL;
return 0;
diff --git a/drivers/infiniband/hw/mlx5/devx.c b/drivers/infiniband/hw/mlx5/devx.c
index ac116d63e466..f2f11e652dcd 100644
--- a/drivers/infiniband/hw/mlx5/devx.c
+++ b/drivers/infiniband/hw/mlx5/devx.c
@@ -723,6 +723,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_HANDLE);
struct mlx5_ib_ucontext *c = to_mucontext(uobj->context);
struct mlx5_ib_dev *dev = to_mdev(c->ibucontext.device);
+ u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)];
struct devx_obj *obj;
int err;
@@ -754,10 +755,12 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_CREATE)(
err = uverbs_copy_to(attrs, MLX5_IB_ATTR_DEVX_OBJ_CREATE_CMD_OUT, cmd_out, cmd_out_len);
if (err)
- goto obj_free;
+ goto obj_destroy;
return 0;
+obj_destroy:
+ mlx5_cmd_exec(obj->mdev, obj->dinbox, obj->dinlen, out, sizeof(out));
obj_free:
kfree(obj);
return err;
diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c
index 444d16520506..0b34e909505f 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -2951,7 +2951,7 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
{
struct srp_target_port *target = host_to_target(scmnd->device->host);
struct srp_rdma_ch *ch;
- int i;
+ int i, j;
u8 status;
shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
@@ -2965,8 +2965,8 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
for (i = 0; i < target->ch_count; i++) {
ch = &target->ch[i];
- for (i = 0; i < target->req_ring_size; ++i) {
- struct srp_request *req = &ch->req_ring[i];
+ for (j = 0; j < target->req_ring_size; ++j) {
+ struct srp_request *req = &ch->req_ring[j];
srp_finish_req(ch, req, scmnd->device, DID_RESET << 16);
}
diff --git a/drivers/input/keyboard/atakbd.c b/drivers/input/keyboard/atakbd.c
index 6f62da2909ec..6caee807cafa 100644
--- a/drivers/input/keyboard/atakbd.c
+++ b/drivers/input/keyboard/atakbd.c
@@ -75,8 +75,7 @@ MODULE_LICENSE("GPL");
*/
-static unsigned char atakbd_keycode[0x72] = { /* American layout */
- [0] = KEY_GRAVE,
+static unsigned char atakbd_keycode[0x73] = { /* American layout */
[1] = KEY_ESC,
[2] = KEY_1,
[3] = KEY_2,
@@ -117,9 +116,9 @@ static unsigned char atakbd_keycode[0x72] = { /* American layout */
[38] = KEY_L,
[39] = KEY_SEMICOLON,
[40] = KEY_APOSTROPHE,
- [41] = KEY_BACKSLASH, /* FIXME, '#' */
+ [41] = KEY_GRAVE,
[42] = KEY_LEFTSHIFT,
- [43] = KEY_GRAVE, /* FIXME: '~' */
+ [43] = KEY_BACKSLASH,
[44] = KEY_Z,
[45] = KEY_X,
[46] = KEY_C,
@@ -145,45 +144,34 @@ static unsigned char atakbd_keycode[0x72] = { /* American layout */
[66] = KEY_F8,
[67] = KEY_F9,
[68] = KEY_F10,
- [69] = KEY_ESC,
- [70] = KEY_DELETE,
- [71] = KEY_KP7,
- [72] = KEY_KP8,
- [73] = KEY_KP9,
+ [71] = KEY_HOME,
+ [72] = KEY_UP,
[74] = KEY_KPMINUS,
- [75] = KEY_KP4,
- [76] = KEY_KP5,
- [77] = KEY_KP6,
+ [75] = KEY_LEFT,
+ [77] = KEY_RIGHT,
[78] = KEY_KPPLUS,
- [79] = KEY_KP1,
- [80] = KEY_KP2,
- [81] = KEY_KP3,
- [82] = KEY_KP0,
- [83] = KEY_KPDOT,
- [90] = KEY_KPLEFTPAREN,
- [91] = KEY_KPRIGHTPAREN,
- [92] = KEY_KPASTERISK, /* FIXME */
- [93] = KEY_KPASTERISK,
- [94] = KEY_KPPLUS,
- [95] = KEY_HELP,
+ [80] = KEY_DOWN,
+ [82] = KEY_INSERT,
+ [83] = KEY_DELETE,
[96] = KEY_102ND,
- [97] = KEY_KPASTERISK, /* FIXME */
- [98] = KEY_KPSLASH,
+ [97] = KEY_UNDO,
+ [98] = KEY_HELP,
[99] = KEY_KPLEFTPAREN,
[100] = KEY_KPRIGHTPAREN,
[101] = KEY_KPSLASH,
[102] = KEY_KPASTERISK,
- [103] = KEY_UP,
- [104] = KEY_KPASTERISK, /* FIXME */
- [105] = KEY_LEFT,
- [106] = KEY_RIGHT,
- [107] = KEY_KPASTERISK, /* FIXME */
- [108] = KEY_DOWN,
- [109] = KEY_KPASTERISK, /* FIXME */
- [110] = KEY_KPASTERISK, /* FIXME */
- [111] = KEY_KPASTERISK, /* FIXME */
- [112] = KEY_KPASTERISK, /* FIXME */
- [113] = KEY_KPASTERISK /* FIXME */
+ [103] = KEY_KP7,
+ [104] = KEY_KP8,
+ [105] = KEY_KP9,
+ [106] = KEY_KP4,
+ [107] = KEY_KP5,
+ [108] = KEY_KP6,
+ [109] = KEY_KP1,
+ [110] = KEY_KP2,
+ [111] = KEY_KP3,
+ [112] = KEY_KP0,
+ [113] = KEY_KPDOT,
+ [114] = KEY_KPENTER,
};
static struct input_dev *atakbd_dev;
@@ -191,21 +179,15 @@ static struct input_dev *atakbd_dev;
static void atakbd_interrupt(unsigned char scancode, char down)
{
- if (scancode < 0x72) { /* scancodes < 0xf2 are keys */
+ if (scancode < 0x73) { /* scancodes < 0xf3 are keys */
// report raw events here?
scancode = atakbd_keycode[scancode];
- if (scancode == KEY_CAPSLOCK) { /* CapsLock is a toggle switch key on Amiga */
- input_report_key(atakbd_dev, scancode, 1);
- input_report_key(atakbd_dev, scancode, 0);
- input_sync(atakbd_dev);
- } else {
- input_report_key(atakbd_dev, scancode, down);
- input_sync(atakbd_dev);
- }
- } else /* scancodes >= 0xf2 are mouse data, most likely */
+ input_report_key(atakbd_dev, scancode, down);
+ input_sync(atakbd_dev);
+ } else /* scancodes >= 0xf3 are mouse data, most likely */
printk(KERN_INFO "atakbd: unhandled scancode %x\n", scancode);
return;
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 96a887f33698..eb14ddf69346 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -410,7 +410,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
min = abs->minimum;
max = abs->maximum;
- if ((min != 0 || max != 0) && max <= min) {
+ if ((min != 0 || max != 0) && max < min) {
printk(KERN_DEBUG
"%s: invalid abs[%02x] min:%d max:%d\n",
UINPUT_NAME, code, min, max);
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c
index 44f57cf6675b..2d95e8d93cc7 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1178,6 +1178,8 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
static const char * const middle_button_pnp_ids[] = {
"LEN2131", /* ThinkPad P52 w/ NFC */
"LEN2132", /* ThinkPad P52 */
+ "LEN2133", /* ThinkPad P72 w/ NFC */
+ "LEN2134", /* ThinkPad P72 */
NULL
};
diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c
index 80e69bb8283e..83ac8c128192 100644
--- a/drivers/input/touchscreen/egalax_ts.c
+++ b/drivers/input/touchscreen/egalax_ts.c
@@ -241,6 +241,9 @@ static int __maybe_unused egalax_ts_suspend(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
int ret;
+ if (device_may_wakeup(dev))
+ return enable_irq_wake(client->irq);
+
ret = i2c_master_send(client, suspend_cmd, MAX_I2C_DATA_LEN);
return ret > 0 ? 0 : ret;
}
@@ -249,6 +252,9 @@ static int __maybe_unused egalax_ts_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
+ if (device_may_wakeup(dev))
+ return disable_irq_wake(client->irq);
+
return egalax_wake_up_device(client);
}
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 4e04fff23977..73e47d93e7a0 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -246,7 +246,13 @@ static u16 get_alias(struct device *dev)
/* The callers make sure that get_device_id() does not fail here */
devid = get_device_id(dev);
+
+ /* For ACPI HID devices, we simply return the devid as such */
+ if (!dev_is_pci(dev))
+ return devid;
+
ivrs_alias = amd_iommu_alias_table[devid];
+
pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
if (ivrs_alias == pci_alias)
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 5f3f10cf9d9d..bedc801b06a0 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2540,9 +2540,9 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
if (dev && dev_is_pci(dev) && info->pasid_supported) {
ret = intel_pasid_alloc_table(dev);
if (ret) {
- __dmar_remove_one_dev_info(info);
- spin_unlock_irqrestore(&device_domain_lock, flags);
- return NULL;
+ pr_warn("No pasid table for %s, pasid disabled\n",
+ dev_name(dev));
+ info->pasid_supported = 0;
}
}
spin_unlock_irqrestore(&device_domain_lock, flags);
diff --git a/drivers/iommu/intel-pasid.h b/drivers/iommu/intel-pasid.h
index 1c05ed6fc5a5..1fb5e12b029a 100644
--- a/drivers/iommu/intel-pasid.h
+++ b/drivers/iommu/intel-pasid.h
@@ -11,7 +11,7 @@
#define __INTEL_PASID_H
#define PASID_MIN 0x1
-#define PASID_MAX 0x100000
+#define PASID_MAX 0x20000
struct pasid_entry {
u64 val;
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 258115b10fa9..ad3e2b97469e 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -1241,6 +1241,12 @@ err_unprepare_clocks:
static void rk_iommu_shutdown(struct platform_device *pdev)
{
+ struct rk_iommu *iommu = platform_get_drvdata(pdev);
+ int i = 0, irq;
+
+ while ((irq = platform_get_irq(pdev, i++)) != -ENXIO)
+ devm_free_irq(iommu->dev, irq, iommu);
+
pm_runtime_force_suspend(&pdev->dev);
}
diff --git a/drivers/md/bcache/bcache.h b/drivers/md/bcache/bcache.h
index 83504dd8100a..954dad29e6e8 100644
--- a/drivers/md/bcache/bcache.h
+++ b/drivers/md/bcache/bcache.h
@@ -965,6 +965,7 @@ void bch_prio_write(struct cache *ca);
void bch_write_bdev_super(struct cached_dev *dc, struct closure *parent);
extern struct workqueue_struct *bcache_wq;
+extern struct workqueue_struct *bch_journal_wq;
extern struct mutex bch_register_lock;
extern struct list_head bch_cache_sets;
diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c
index 6116bbf870d8..522c7426f3a0 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -485,7 +485,7 @@ static void do_journal_discard(struct cache *ca)
closure_get(&ca->set->cl);
INIT_WORK(&ja->discard_work, journal_discard_work);
- schedule_work(&ja->discard_work);
+ queue_work(bch_journal_wq, &ja->discard_work);
}
}
@@ -592,7 +592,7 @@ static void journal_write_done(struct closure *cl)
: &j->w[0];
__closure_wake_up(&w->wait);
- continue_at_nobarrier(cl, journal_write, system_wq);
+ continue_at_nobarrier(cl, journal_write, bch_journal_wq);
}
static void journal_write_unlock(struct closure *cl)
@@ -627,7 +627,7 @@ static void journal_write_unlocked(struct closure *cl)
spin_unlock(&c->journal.lock);
btree_flush_write(c);
- continue_at(cl, journal_write, system_wq);
+ continue_at(cl, journal_write, bch_journal_wq);
return;
}
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 94c756c66bd7..30ba9aeb5ee8 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -47,6 +47,7 @@ static int bcache_major;
static DEFINE_IDA(bcache_device_idx);
static wait_queue_head_t unregister_wait;
struct workqueue_struct *bcache_wq;
+struct workqueue_struct *bch_journal_wq;
#define BTREE_MAX_PAGES (256 * 1024 / PAGE_SIZE)
/* limitation of partitions number on single bcache device */
@@ -2341,6 +2342,9 @@ static void bcache_exit(void)
kobject_put(bcache_kobj);
if (bcache_wq)
destroy_workqueue(bcache_wq);
+ if (bch_journal_wq)
+ destroy_workqueue(bch_journal_wq);
+
if (bcache_major)
unregister_blkdev(bcache_major, "bcache");
unregister_reboot_notifier(&reboot);
@@ -2370,6 +2374,10 @@ static int __init bcache_init(void)
if (!bcache_wq)
goto err;
+ bch_journal_wq = alloc_workqueue("bch_journal", WQ_MEM_RECLAIM, 0);
+ if (!bch_journal_wq)
+ goto err;
+
bcache_kobj = kobject_create_and_add("bcache", fs_kobj);
if (!bcache_kobj)
goto err;
diff --git a/drivers/media/i2c/mt9v111.c b/drivers/media/i2c/mt9v111.c
index b5410aeb5fe2..bb41bea950ac 100644
--- a/drivers/media/i2c/mt9v111.c
+++ b/drivers/media/i2c/mt9v111.c
@@ -1159,41 +1159,21 @@ static int mt9v111_probe(struct i2c_client *client)
V4L2_CID_AUTO_WHITE_BALANCE,
0, 1, 1,
V4L2_WHITE_BALANCE_AUTO);
- if (IS_ERR_OR_NULL(mt9v111->auto_awb)) {
- ret = PTR_ERR(mt9v111->auto_awb);
- goto error_free_ctrls;
- }
-
mt9v111->auto_exp = v4l2_ctrl_new_std_menu(&mt9v111->ctrls,
&mt9v111_ctrl_ops,
V4L2_CID_EXPOSURE_AUTO,
V4L2_EXPOSURE_MANUAL,
0, V4L2_EXPOSURE_AUTO);
- if (IS_ERR_OR_NULL(mt9v111->auto_exp)) {
- ret = PTR_ERR(mt9v111->auto_exp);
- goto error_free_ctrls;
- }
-
- /* Initialize timings */
mt9v111->hblank = v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops,
V4L2_CID_HBLANK,
MT9V111_CORE_R05_MIN_HBLANK,
MT9V111_CORE_R05_MAX_HBLANK, 1,
MT9V111_CORE_R05_DEF_HBLANK);
- if (IS_ERR_OR_NULL(mt9v111->hblank)) {
- ret = PTR_ERR(mt9v111->hblank);
- goto error_free_ctrls;
- }
-
mt9v111->vblank = v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops,
V4L2_CID_VBLANK,
MT9V111_CORE_R06_MIN_VBLANK,
MT9V111_CORE_R06_MAX_VBLANK, 1,
MT9V111_CORE_R06_DEF_VBLANK);
- if (IS_ERR_OR_NULL(mt9v111->vblank)) {
- ret = PTR_ERR(mt9v111->vblank);
- goto error_free_ctrls;
- }
/* PIXEL_RATE is fixed: just expose it to user space. */
v4l2_ctrl_new_std(&mt9v111->ctrls, &mt9v111_ctrl_ops,
@@ -1201,6 +1181,10 @@ static int mt9v111_probe(struct i2c_client *client)
DIV_ROUND_CLOSEST(mt9v111->sysclk, 2), 1,
DIV_ROUND_CLOSEST(mt9v111->sysclk, 2));
+ if (mt9v111->ctrls.error) {
+ ret = mt9v111->ctrls.error;
+ goto error_free_ctrls;
+ }
mt9v111->sd.ctrl_handler = &mt9v111->ctrls;
/* Start with default configuration: 640x480 UYVY. */
@@ -1226,26 +1210,27 @@ static int mt9v111_probe(struct i2c_client *client)
mt9v111->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&mt9v111->sd.entity, 1, &mt9v111->pad);
if (ret)
- goto error_free_ctrls;
+ goto error_free_entity;
#endif
ret = mt9v111_chip_probe(mt9v111);
if (ret)
- goto error_free_ctrls;
+ goto error_free_entity;
ret = v4l2_async_register_subdev(&mt9v111->sd);
if (ret)
- goto error_free_ctrls;
+ goto error_free_entity;
return 0;
-error_free_ctrls:
- v4l2_ctrl_handler_free(&mt9v111->ctrls);
-
+error_free_entity:
#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&mt9v111->sd.entity);
#endif
+error_free_ctrls:
+ v4l2_ctrl_handler_free(&mt9v111->ctrls);
+
mutex_destroy(&mt9v111->pwr_mutex);
mutex_destroy(&mt9v111->stream_mutex);
@@ -1259,12 +1244,12 @@ static int mt9v111_remove(struct i2c_client *client)
v4l2_async_unregister_subdev(sd);
- v4l2_ctrl_handler_free(&mt9v111->ctrls);
-
#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
media_entity_cleanup(&sd->entity);
#endif
+ v4l2_ctrl_handler_free(&mt9v111->ctrls);
+
mutex_destroy(&mt9v111->pwr_mutex);
mutex_destroy(&mt9v111->stream_mutex);
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 94c1fe0e9787..54fe90acb5b2 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -541,6 +541,8 @@ config VIDEO_CROS_EC_CEC
depends on MFD_CROS_EC
select CEC_CORE
select CEC_NOTIFIER
+ select CHROME_PLATFORMS
+ select CROS_EC_PROTO
---help---
If you say yes here you will get support for the
ChromeOS Embedded Controller's CEC.
diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c
index 729b31891466..a5ae85674ffb 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.c
+++ b/drivers/media/platform/qcom/camss/camss-csid.c
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-2ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-2ph-1-0.c
index c832539397d7..12bce391d71f 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy-2ph-1-0.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy-2ph-1-0.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#define CAMSS_CSI_PHY_LNn_CFG2(n) (0x004 + 0x40 * (n))
#define CAMSS_CSI_PHY_LNn_CFG3(n) (0x008 + 0x40 * (n))
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c
index bcd0dfd33618..2e65caf1ecae 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c
@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#define CSIPHY_3PH_LNn_CFG1(n) (0x000 + 0x100 * (n))
#define CSIPHY_3PH_LNn_CFG1_SWI_REC_DLY_PRG (BIT(7) | BIT(6))
diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index 4559f3b1b38c..008afb85023b 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/media/platform/qcom/camss/camss-ispif.c b/drivers/media/platform/qcom/camss/camss-ispif.c
index 7f269021d08c..1f33b4eb198c 100644
--- a/drivers/media/platform/qcom/camss/camss-ispif.c
+++ b/drivers/media/platform/qcom/camss/camss-ispif.c
@@ -10,6 +10,7 @@
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
@@ -1076,8 +1077,8 @@ int msm_ispif_subdev_init(struct ispif_device *ispif,
else
return -EINVAL;
- ispif->line = kcalloc(ispif->line_num, sizeof(*ispif->line),
- GFP_KERNEL);
+ ispif->line = devm_kcalloc(dev, ispif->line_num, sizeof(*ispif->line),
+ GFP_KERNEL);
if (!ispif->line)
return -ENOMEM;
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
index da3a9fed9f2d..174a36be6f5d 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-1.c
@@ -9,6 +9,7 @@
*/
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/iopoll.h>
#include "camss-vfe.h"
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
index 4c584bffd179..0dca8bf9281e 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe-4-7.c
@@ -9,6 +9,7 @@
*/
#include <linux/interrupt.h>
+#include <linux/io.h>
#include <linux/iopoll.h>
#include "camss-vfe.h"
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index dcc0c30ef1b1..669615fff6a0 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -848,17 +848,18 @@ static int camss_probe(struct platform_device *pdev)
return -EINVAL;
}
- camss->csiphy = kcalloc(camss->csiphy_num, sizeof(*camss->csiphy),
- GFP_KERNEL);
+ camss->csiphy = devm_kcalloc(dev, camss->csiphy_num,
+ sizeof(*camss->csiphy), GFP_KERNEL);
if (!camss->csiphy)
return -ENOMEM;
- camss->csid = kcalloc(camss->csid_num, sizeof(*camss->csid),
- GFP_KERNEL);
+ camss->csid = devm_kcalloc(dev, camss->csid_num, sizeof(*camss->csid),
+ GFP_KERNEL);
if (!camss->csid)
return -ENOMEM;
- camss->vfe = kcalloc(camss->vfe_num, sizeof(*camss->vfe), GFP_KERNEL);
+ camss->vfe = devm_kcalloc(dev, camss->vfe_num, sizeof(*camss->vfe),
+ GFP_KERNEL);
if (!camss->vfe)
return -ENOMEM;
@@ -993,12 +994,12 @@ static const struct of_device_id camss_dt_match[] = {
MODULE_DEVICE_TABLE(of, camss_dt_match);
-static int camss_runtime_suspend(struct device *dev)
+static int __maybe_unused camss_runtime_suspend(struct device *dev)
{
return 0;
}
-static int camss_runtime_resume(struct device *dev)
+static int __maybe_unused camss_runtime_resume(struct device *dev)
{
return 0;
}
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 666d319d3d1a..1f6c1eefe389 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -402,8 +402,10 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
if (msg[0].addr == state->af9033_i2c_addr[1])
reg |= 0x100000;
- ret = af9035_wr_regs(d, reg, &msg[0].buf[3],
- msg[0].len - 3);
+ ret = (msg[0].len >= 3) ? af9035_wr_regs(d, reg,
+ &msg[0].buf[3],
+ msg[0].len - 3)
+ : -EOPNOTSUPP;
} else {
/* I2C write */
u8 buf[MAX_XFER_SIZE];
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index a764a83f99da..0d87e11e7f1d 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -971,16 +971,13 @@ static void bond_poll_controller(struct net_device *bond_dev)
struct slave *slave = NULL;
struct list_head *iter;
struct ad_info ad_info;
- struct netpoll_info *ni;
- const struct net_device_ops *ops;
if (BOND_MODE(bond) == BOND_MODE_8023AD)
if (bond_3ad_get_active_agg_info(bond, &ad_info))
return;
bond_for_each_slave_rcu(bond, slave, iter) {
- ops = slave->dev->netdev_ops;
- if (!bond_slave_is_up(slave) || !ops->ndo_poll_controller)
+ if (!bond_slave_is_up(slave))
continue;
if (BOND_MODE(bond) == BOND_MODE_8023AD) {
@@ -992,11 +989,7 @@ static void bond_poll_controller(struct net_device *bond_dev)
continue;
}
- ni = rcu_dereference_bh(slave->dev->npinfo);
- if (down_trylock(&ni->dev_lock))
- continue;
- ops->ndo_poll_controller(slave->dev);
- up(&ni->dev_lock);
+ netpoll_poll_dev(slave->dev);
}
}
diff --git a/drivers/net/ethernet/apple/bmac.c b/drivers/net/ethernet/apple/bmac.c
index 024998d6d8c6..6a8e2567f2bd 100644
--- a/drivers/net/ethernet/apple/bmac.c
+++ b/drivers/net/ethernet/apple/bmac.c
@@ -154,7 +154,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id);
static irqreturn_t bmac_rxdma_intr(int irq, void *dev_id);
static void bmac_set_timeout(struct net_device *dev);
static void bmac_tx_timeout(struct timer_list *t);
-static int bmac_output(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t bmac_output(struct sk_buff *skb, struct net_device *dev);
static void bmac_start(struct net_device *dev);
#define DBDMA_SET(x) ( ((x) | (x) << 16) )
@@ -1456,7 +1456,7 @@ bmac_start(struct net_device *dev)
spin_unlock_irqrestore(&bp->lock, flags);
}
-static int
+static netdev_tx_t
bmac_output(struct sk_buff *skb, struct net_device *dev)
{
struct bmac_data *bp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/apple/mace.c b/drivers/net/ethernet/apple/mace.c
index 0b5429d76bcf..68b9ee489489 100644
--- a/drivers/net/ethernet/apple/mace.c
+++ b/drivers/net/ethernet/apple/mace.c
@@ -78,7 +78,7 @@ struct mace_data {
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
-static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
static void mace_set_multicast(struct net_device *dev);
static void mace_reset(struct net_device *dev);
static int mace_set_address(struct net_device *dev, void *addr);
@@ -525,7 +525,7 @@ static inline void mace_set_timeout(struct net_device *dev)
mp->timeout_active = 1;
}
-static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct dbdma_regs __iomem *td = mp->tx_dma;
diff --git a/drivers/net/ethernet/apple/macmace.c b/drivers/net/ethernet/apple/macmace.c
index 137cbb470af2..376f2c2613e7 100644
--- a/drivers/net/ethernet/apple/macmace.c
+++ b/drivers/net/ethernet/apple/macmace.c
@@ -89,7 +89,7 @@ struct mace_frame {
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
-static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
static void mace_set_multicast(struct net_device *dev);
static int mace_set_address(struct net_device *dev, void *addr);
static void mace_reset(struct net_device *dev);
@@ -444,7 +444,7 @@ static int mace_close(struct net_device *dev)
* Transmit a frame
*/
-static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
unsigned long flags;
diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
index b5f1f62e8e25..d1e1a0ba8615 100644
--- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
+++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c
@@ -225,9 +225,10 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
}
/* for single fragment packets use build_skb() */
- if (buff->is_eop) {
+ if (buff->is_eop &&
+ buff->len <= AQ_CFG_RX_FRAME_MAX - AQ_SKB_ALIGN) {
skb = build_skb(page_address(buff->page),
- buff->len + AQ_SKB_ALIGN);
+ AQ_CFG_RX_FRAME_MAX);
if (unlikely(!skb)) {
err = -ENOMEM;
goto err_exit;
@@ -247,18 +248,21 @@ int aq_ring_rx_clean(struct aq_ring_s *self,
buff->len - ETH_HLEN,
SKB_TRUESIZE(buff->len - ETH_HLEN));
- for (i = 1U, next_ = buff->next,
- buff_ = &self->buff_ring[next_]; true;
- next_ = buff_->next,
- buff_ = &self->buff_ring[next_], ++i) {
- skb_add_rx_frag(skb, i, buff_->page, 0,
- buff_->len,
- SKB_TRUESIZE(buff->len -
- ETH_HLEN));
- buff_->is_cleaned = 1;
-
- if (buff_->is_eop)
- break;
+ if (!buff->is_eop) {
+ for (i = 1U, next_ = buff->next,
+ buff_ = &self->buff_ring[next_];
+ true; next_ = buff_->next,
+ buff_ = &self->buff_ring[next_], ++i) {
+ skb_add_rx_frag(skb, i,
+ buff_->page, 0,
+ buff_->len,
+ SKB_TRUESIZE(buff->len -
+ ETH_HLEN));
+ buff_->is_cleaned = 1;
+
+ if (buff_->is_eop)
+ break;
+ }
}
}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 71362b7f6040..fcc2328bb0d9 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -12894,19 +12894,6 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
}
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void poll_bnx2x(struct net_device *dev)
-{
- struct bnx2x *bp = netdev_priv(dev);
- int i;
-
- for_each_eth_queue(bp, i) {
- struct bnx2x_fastpath *fp = &bp->fp[i];
- napi_schedule(&bnx2x_fp(bp, fp->index, napi));
- }
-}
-#endif
-
static int bnx2x_validate_addr(struct net_device *dev)
{
struct bnx2x *bp = netdev_priv(dev);
@@ -13113,9 +13100,6 @@ static const struct net_device_ops bnx2x_netdev_ops = {
.ndo_tx_timeout = bnx2x_tx_timeout,
.ndo_vlan_rx_add_vid = bnx2x_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = bnx2x_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = poll_bnx2x,
-#endif
.ndo_setup_tc = __bnx2x_setup_tc,
#ifdef CONFIG_BNX2X_SRIOV
.ndo_set_vf_mac = bnx2x_set_vf_mac,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 177587f9c3f1..61957b0bbd8c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -7672,21 +7672,6 @@ static void bnxt_tx_timeout(struct net_device *dev)
bnxt_queue_sp_work(bp);
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void bnxt_poll_controller(struct net_device *dev)
-{
- struct bnxt *bp = netdev_priv(dev);
- int i;
-
- /* Only process tx rings/combined rings in netpoll mode. */
- for (i = 0; i < bp->tx_nr_rings; i++) {
- struct bnxt_tx_ring_info *txr = &bp->tx_ring[i];
-
- napi_schedule(&txr->bnapi->napi);
- }
-}
-#endif
-
static void bnxt_timer(struct timer_list *t)
{
struct bnxt *bp = from_timer(bp, t, timer);
@@ -8520,9 +8505,6 @@ static const struct net_device_ops bnxt_netdev_ops = {
.ndo_set_vf_spoofchk = bnxt_set_vf_spoofchk,
.ndo_set_vf_trust = bnxt_set_vf_trust,
#endif
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = bnxt_poll_controller,
-#endif
.ndo_setup_tc = bnxt_setup_tc,
#ifdef CONFIG_RFS_ACCEL
.ndo_rx_flow_steer = bnxt_rx_flow_steer,
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
index f3b9fbcc705b..790c684f08ab 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
@@ -46,6 +46,9 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
}
}
+ if (i == ARRAY_SIZE(nvm_params))
+ return -EOPNOTSUPP;
+
if (nvm_param.dir_type == BNXT_NVM_PORT_CFG)
idx = bp->pf.port_id;
else if (nvm_param.dir_type == BNXT_NVM_FUNC_CFG)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 092c817f8f11..e1594c9df4c6 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -75,17 +75,23 @@ static int bnxt_tc_parse_redir(struct bnxt *bp,
return 0;
}
-static void bnxt_tc_parse_vlan(struct bnxt *bp,
- struct bnxt_tc_actions *actions,
- const struct tc_action *tc_act)
+static int bnxt_tc_parse_vlan(struct bnxt *bp,
+ struct bnxt_tc_actions *actions,
+ const struct tc_action *tc_act)
{
- if (tcf_vlan_action(tc_act) == TCA_VLAN_ACT_POP) {
+ switch (tcf_vlan_action(tc_act)) {
+ case TCA_VLAN_ACT_POP:
actions->flags |= BNXT_TC_ACTION_FLAG_POP_VLAN;
- } else if (tcf_vlan_action(tc_act) == TCA_VLAN_ACT_PUSH) {
+ break;
+ case TCA_VLAN_ACT_PUSH:
actions->flags |= BNXT_TC_ACTION_FLAG_PUSH_VLAN;
actions->push_vlan_tci = htons(tcf_vlan_push_vid(tc_act));
actions->push_vlan_tpid = tcf_vlan_push_proto(tc_act);
+ break;
+ default:
+ return -EOPNOTSUPP;
}
+ return 0;
}
static int bnxt_tc_parse_tunnel_set(struct bnxt *bp,
@@ -134,7 +140,9 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
/* Push/pop VLAN */
if (is_tcf_vlan(tc_act)) {
- bnxt_tc_parse_vlan(bp, actions, tc_act);
+ rc = bnxt_tc_parse_vlan(bp, actions, tc_act);
+ if (rc)
+ return rc;
continue;
}
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
index b8f75a22fb6c..f152da1ce046 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_msg.h
@@ -753,7 +753,6 @@ struct cpl_abort_req_rss {
};
struct cpl_abort_req_rss6 {
- WR_HDR;
union opcode_tid ot;
__be32 srqidx_status;
};
diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c
index e2a702996db4..13dfdfca49fc 100644
--- a/drivers/net/ethernet/cirrus/ep93xx_eth.c
+++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c
@@ -332,7 +332,7 @@ static int ep93xx_poll(struct napi_struct *napi, int budget)
return rx;
}
-static int ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ep93xx_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct ep93xx_priv *ep = netdev_priv(dev);
struct ep93xx_tdesc *txd;
diff --git a/drivers/net/ethernet/cirrus/mac89x0.c b/drivers/net/ethernet/cirrus/mac89x0.c
index 3f8fe8fd79cc..6324e80960c3 100644
--- a/drivers/net/ethernet/cirrus/mac89x0.c
+++ b/drivers/net/ethernet/cirrus/mac89x0.c
@@ -113,7 +113,7 @@ struct net_local {
/* Index to functions, as function prototypes. */
static int net_open(struct net_device *dev);
-static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t net_send_packet(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t net_interrupt(int irq, void *dev_id);
static void set_multicast_list(struct net_device *dev);
static void net_rx(struct net_device *dev);
@@ -324,7 +324,7 @@ net_open(struct net_device *dev)
return 0;
}
-static int
+static netdev_tx_t
net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
diff --git a/drivers/net/ethernet/i825xx/ether1.c b/drivers/net/ethernet/i825xx/ether1.c
index dc983450354b..35f6291a3672 100644
--- a/drivers/net/ethernet/i825xx/ether1.c
+++ b/drivers/net/ethernet/i825xx/ether1.c
@@ -64,7 +64,8 @@ static unsigned int net_debug = NET_DEBUG;
#define RX_AREA_END 0x0fc00
static int ether1_open(struct net_device *dev);
-static int ether1_sendpacket(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t ether1_sendpacket(struct sk_buff *skb,
+ struct net_device *dev);
static irqreturn_t ether1_interrupt(int irq, void *dev_id);
static int ether1_close(struct net_device *dev);
static void ether1_setmulticastlist(struct net_device *dev);
@@ -667,7 +668,7 @@ ether1_timeout(struct net_device *dev)
netif_wake_queue(dev);
}
-static int
+static netdev_tx_t
ether1_sendpacket (struct sk_buff *skb, struct net_device *dev)
{
int tmp, tst, nopaddr, txaddr, tbdaddr, dataddr;
diff --git a/drivers/net/ethernet/i825xx/lib82596.c b/drivers/net/ethernet/i825xx/lib82596.c
index f00a1dc2128c..2f7ae118217f 100644
--- a/drivers/net/ethernet/i825xx/lib82596.c
+++ b/drivers/net/ethernet/i825xx/lib82596.c
@@ -347,7 +347,7 @@ static const char init_setup[] =
0x7f /* *multi IA */ };
static int i596_open(struct net_device *dev);
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t i596_interrupt(int irq, void *dev_id);
static int i596_close(struct net_device *dev);
static void i596_add_cmd(struct net_device *dev, struct i596_cmd *cmd);
@@ -966,7 +966,7 @@ static void i596_tx_timeout (struct net_device *dev)
}
-static int i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t i596_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct i596_private *lp = netdev_priv(dev);
struct tx_cmd *tx_cmd;
diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
index 8bb15a8c2a40..1a86184d44c0 100644
--- a/drivers/net/ethernet/i825xx/sun3_82586.c
+++ b/drivers/net/ethernet/i825xx/sun3_82586.c
@@ -121,7 +121,8 @@ static int sun3_82586_probe1(struct net_device *dev,int ioaddr);
static irqreturn_t sun3_82586_interrupt(int irq,void *dev_id);
static int sun3_82586_open(struct net_device *dev);
static int sun3_82586_close(struct net_device *dev);
-static int sun3_82586_send_packet(struct sk_buff *,struct net_device *);
+static netdev_tx_t sun3_82586_send_packet(struct sk_buff *,
+ struct net_device *);
static struct net_device_stats *sun3_82586_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
static void sun3_82586_timeout(struct net_device *dev);
@@ -1002,7 +1003,8 @@ static void sun3_82586_timeout(struct net_device *dev)
* send frame
*/
-static int sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t
+sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
{
int len,i;
#ifndef NO_NOPCOMMANDS
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c
index 372664686309..129f4e9f38da 100644
--- a/drivers/net/ethernet/ibm/emac/core.c
+++ b/drivers/net/ethernet/ibm/emac/core.c
@@ -2677,12 +2677,17 @@ static int emac_init_phy(struct emac_instance *dev)
if (of_phy_is_fixed_link(np)) {
int res = emac_dt_mdio_probe(dev);
- if (!res) {
- res = of_phy_register_fixed_link(np);
- if (res)
- mdiobus_unregister(dev->mii_bus);
+ if (res)
+ return res;
+
+ res = of_phy_register_fixed_link(np);
+ dev->phy_dev = of_phy_find_device(np);
+ if (res || !dev->phy_dev) {
+ mdiobus_unregister(dev->mii_bus);
+ return res ? res : -EINVAL;
}
- return res;
+ emac_adjust_link(dev->ndev);
+ put_device(&dev->phy_dev->mdio.dev);
}
return 0;
}
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k.h b/drivers/net/ethernet/intel/fm10k/fm10k.h
index a903a0ba45e1..7d42582ed48d 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k.h
@@ -504,9 +504,6 @@ void fm10k_update_stats(struct fm10k_intfc *interface);
void fm10k_service_event_schedule(struct fm10k_intfc *interface);
void fm10k_macvlan_schedule(struct fm10k_intfc *interface);
void fm10k_update_rx_drop_en(struct fm10k_intfc *interface);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-void fm10k_netpoll(struct net_device *netdev);
-#endif
/* Netdev */
struct net_device *fm10k_alloc_netdev(const struct fm10k_info *info);
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
index 929f538d28bc..538a8467f434 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
@@ -1648,9 +1648,6 @@ static const struct net_device_ops fm10k_netdev_ops = {
.ndo_udp_tunnel_del = fm10k_udp_tunnel_del,
.ndo_dfwd_add_station = fm10k_dfwd_add_station,
.ndo_dfwd_del_station = fm10k_dfwd_del_station,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = fm10k_netpoll,
-#endif
.ndo_features_check = fm10k_features_check,
};
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
index 15071e4adb98..c859ababeed5 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pci.c
@@ -1210,28 +1210,6 @@ static irqreturn_t fm10k_msix_mbx_vf(int __always_unused irq, void *data)
return IRQ_HANDLED;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * fm10k_netpoll - A Polling 'interrupt' handler
- * @netdev: network interface device structure
- *
- * This is used by netconsole to send skbs without having to re-enable
- * interrupts. It's not called while the normal interrupt routine is executing.
- **/
-void fm10k_netpoll(struct net_device *netdev)
-{
- struct fm10k_intfc *interface = netdev_priv(netdev);
- int i;
-
- /* if interface is down do nothing */
- if (test_bit(__FM10K_DOWN, interface->state))
- return;
-
- for (i = 0; i < interface->num_q_vectors; i++)
- fm10k_msix_clean_rings(0, interface->q_vector[i]);
-}
-
-#endif
#define FM10K_ERR_MSG(type) case (type): error = #type; break
static void fm10k_handle_fault(struct fm10k_intfc *interface, int type,
struct fm10k_fault *fault)
diff --git a/drivers/net/ethernet/intel/i40evf/i40evf_main.c b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
index 5906c1c1d19d..fef6d892ed4c 100644
--- a/drivers/net/ethernet/intel/i40evf/i40evf_main.c
+++ b/drivers/net/ethernet/intel/i40evf/i40evf_main.c
@@ -396,29 +396,6 @@ static void i40evf_map_rings_to_vectors(struct i40evf_adapter *adapter)
adapter->aq_required |= I40EVF_FLAG_AQ_MAP_VECTORS;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * i40evf_netpoll - A Polling 'interrupt' handler
- * @netdev: network interface device structure
- *
- * This is used by netconsole to send skbs without having to re-enable
- * interrupts. It's not called while the normal interrupt routine is executing.
- **/
-static void i40evf_netpoll(struct net_device *netdev)
-{
- struct i40evf_adapter *adapter = netdev_priv(netdev);
- int q_vectors = adapter->num_msix_vectors - NONQ_VECS;
- int i;
-
- /* if interface is down do nothing */
- if (test_bit(__I40E_VSI_DOWN, adapter->vsi.state))
- return;
-
- for (i = 0; i < q_vectors; i++)
- i40evf_msix_clean_rings(0, &adapter->q_vectors[i]);
-}
-
-#endif
/**
* i40evf_irq_affinity_notify - Callback for affinity changes
* @notify: context as to what irq was changed
@@ -3229,9 +3206,6 @@ static const struct net_device_ops i40evf_netdev_ops = {
.ndo_features_check = i40evf_features_check,
.ndo_fix_features = i40evf_fix_features,
.ndo_set_features = i40evf_set_features,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = i40evf_netpoll,
-#endif
.ndo_setup_tc = i40evf_setup_tc,
};
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index f1e80eed2fd6..3f047bb43348 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -4806,30 +4806,6 @@ void ice_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats)
stats->rx_length_errors = vsi_stats->rx_length_errors;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/**
- * ice_netpoll - polling "interrupt" handler
- * @netdev: network interface device structure
- *
- * Used by netconsole to send skbs without having to re-enable interrupts.
- * This is not called in the normal interrupt path.
- */
-static void ice_netpoll(struct net_device *netdev)
-{
- struct ice_netdev_priv *np = netdev_priv(netdev);
- struct ice_vsi *vsi = np->vsi;
- struct ice_pf *pf = vsi->back;
- int i;
-
- if (test_bit(__ICE_DOWN, vsi->state) ||
- !test_bit(ICE_FLAG_MSIX_ENA, pf->flags))
- return;
-
- for (i = 0; i < vsi->num_q_vectors; i++)
- ice_msix_clean_rings(0, vsi->q_vectors[i]);
-}
-#endif /* CONFIG_NET_POLL_CONTROLLER */
-
/**
* ice_napi_disable_all - Disable NAPI for all q_vectors in the VSI
* @vsi: VSI having NAPI disabled
@@ -5497,9 +5473,6 @@ static const struct net_device_ops ice_netdev_ops = {
.ndo_validate_addr = eth_validate_addr,
.ndo_change_mtu = ice_change_mtu,
.ndo_get_stats64 = ice_get_stats64,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ice_netpoll,
-#endif /* CONFIG_NET_POLL_CONTROLLER */
.ndo_vlan_rx_add_vid = ice_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ice_vlan_rx_kill_vid,
.ndo_set_features = ice_set_features,
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index a32c576c1e65..0796cef96fa3 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -205,10 +205,6 @@ static struct notifier_block dca_notifier = {
.priority = 0
};
#endif
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* for netdump / net console */
-static void igb_netpoll(struct net_device *);
-#endif
#ifdef CONFIG_PCI_IOV
static unsigned int max_vfs;
module_param(max_vfs, uint, 0);
@@ -2881,9 +2877,6 @@ static const struct net_device_ops igb_netdev_ops = {
.ndo_set_vf_spoofchk = igb_ndo_set_vf_spoofchk,
.ndo_set_vf_trust = igb_ndo_set_vf_trust,
.ndo_get_vf_config = igb_ndo_get_vf_config,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = igb_netpoll,
-#endif
.ndo_fix_features = igb_fix_features,
.ndo_set_features = igb_set_features,
.ndo_fdb_add = igb_ndo_fdb_add,
@@ -9053,29 +9046,6 @@ static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
return 0;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void igb_netpoll(struct net_device *netdev)
-{
- struct igb_adapter *adapter = netdev_priv(netdev);
- struct e1000_hw *hw = &adapter->hw;
- struct igb_q_vector *q_vector;
- int i;
-
- for (i = 0; i < adapter->num_q_vectors; i++) {
- q_vector = adapter->q_vector[i];
- if (adapter->flags & IGB_FLAG_HAS_MSIX)
- wr32(E1000_EIMC, q_vector->eims_value);
- else
- igb_irq_disable(adapter);
- napi_schedule(&q_vector->napi);
- }
-}
-#endif /* CONFIG_NET_POLL_CONTROLLER */
-
/**
* igb_io_error_detected - called when PCI error is detected
* @pdev: Pointer to PCI device
diff --git a/drivers/net/ethernet/intel/ixgb/ixgb_main.c b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
index d3e72d0f66ef..7722153c4ac2 100644
--- a/drivers/net/ethernet/intel/ixgb/ixgb_main.c
+++ b/drivers/net/ethernet/intel/ixgb/ixgb_main.c
@@ -81,11 +81,6 @@ static int ixgb_vlan_rx_kill_vid(struct net_device *netdev,
__be16 proto, u16 vid);
static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* for netdump / net console */
-static void ixgb_netpoll(struct net_device *dev);
-#endif
-
static pci_ers_result_t ixgb_io_error_detected (struct pci_dev *pdev,
enum pci_channel_state state);
static pci_ers_result_t ixgb_io_slot_reset (struct pci_dev *pdev);
@@ -348,9 +343,6 @@ static const struct net_device_ops ixgb_netdev_ops = {
.ndo_tx_timeout = ixgb_tx_timeout,
.ndo_vlan_rx_add_vid = ixgb_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ixgb_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ixgb_netpoll,
-#endif
.ndo_fix_features = ixgb_fix_features,
.ndo_set_features = ixgb_set_features,
};
@@ -2195,23 +2187,6 @@ ixgb_restore_vlan(struct ixgb_adapter *adapter)
ixgb_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid);
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-
-static void ixgb_netpoll(struct net_device *dev)
-{
- struct ixgb_adapter *adapter = netdev_priv(dev);
-
- disable_irq(adapter->pdev->irq);
- ixgb_intr(adapter->pdev->irq, dev);
- enable_irq(adapter->pdev->irq);
-}
-#endif
-
/**
* ixgb_io_error_detected - called when PCI error is detected
* @pdev: pointer to pci device with error
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 9a23d33a47ed..f27d73a7bf16 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -8768,28 +8768,6 @@ static int ixgbe_del_sanmac_netdev(struct net_device *dev)
return err;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void ixgbe_netpoll(struct net_device *netdev)
-{
- struct ixgbe_adapter *adapter = netdev_priv(netdev);
- int i;
-
- /* if interface is down do nothing */
- if (test_bit(__IXGBE_DOWN, &adapter->state))
- return;
-
- /* loop through and schedule all active queues */
- for (i = 0; i < adapter->num_q_vectors; i++)
- ixgbe_msix_clean_rings(0, adapter->q_vector[i]);
-}
-
-#endif
-
static void ixgbe_get_ring_stats64(struct rtnl_link_stats64 *stats,
struct ixgbe_ring *ring)
{
@@ -10251,9 +10229,6 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_stats64 = ixgbe_get_stats64,
.ndo_setup_tc = __ixgbe_setup_tc,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ixgbe_netpoll,
-#endif
#ifdef IXGBE_FCOE
.ndo_select_queue = ixgbe_select_queue,
.ndo_fcoe_ddp_setup = ixgbe_fcoe_ddp_get,
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index d86446d202d5..5a228582423b 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -4233,24 +4233,6 @@ static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
return 0;
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* Polling 'interrupt' - used by things like netconsole to send skbs
- * without having to re-enable interrupts. It's not called while
- * the interrupt routine is executing.
- */
-static void ixgbevf_netpoll(struct net_device *netdev)
-{
- struct ixgbevf_adapter *adapter = netdev_priv(netdev);
- int i;
-
- /* if interface is down do nothing */
- if (test_bit(__IXGBEVF_DOWN, &adapter->state))
- return;
- for (i = 0; i < adapter->num_rx_queues; i++)
- ixgbevf_msix_clean_rings(0, adapter->q_vector[i]);
-}
-#endif /* CONFIG_NET_POLL_CONTROLLER */
-
static int ixgbevf_suspend(struct pci_dev *pdev, pm_message_t state)
{
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -4482,9 +4464,6 @@ static const struct net_device_ops ixgbevf_netdev_ops = {
.ndo_tx_timeout = ixgbevf_tx_timeout,
.ndo_vlan_rx_add_vid = ixgbevf_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = ixgbevf_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = ixgbevf_netpoll,
-#endif
.ndo_features_check = ixgbevf_features_check,
.ndo_bpf = ixgbevf_xdp,
};
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index bc80a678abc3..b4ed7d394d07 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -1890,8 +1890,8 @@ static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
if (!data || !(rx_desc->buf_phys_addr))
continue;
- dma_unmap_single(pp->dev->dev.parent, rx_desc->buf_phys_addr,
- MVNETA_RX_BUF_SIZE(pp->pkt_size), DMA_FROM_DEVICE);
+ dma_unmap_page(pp->dev->dev.parent, rx_desc->buf_phys_addr,
+ PAGE_SIZE, DMA_FROM_DEVICE);
__free_page(data);
}
}
@@ -2008,8 +2008,8 @@ static int mvneta_rx_swbm(struct napi_struct *napi,
skb_add_rx_frag(rxq->skb, frag_num, page,
frag_offset, frag_size,
PAGE_SIZE);
- dma_unmap_single(dev->dev.parent, phys_addr,
- PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_unmap_page(dev->dev.parent, phys_addr,
+ PAGE_SIZE, DMA_FROM_DEVICE);
rxq->left_size -= frag_size;
}
} else {
@@ -2039,9 +2039,8 @@ static int mvneta_rx_swbm(struct napi_struct *napi,
frag_offset, frag_size,
PAGE_SIZE);
- dma_unmap_single(dev->dev.parent, phys_addr,
- PAGE_SIZE,
- DMA_FROM_DEVICE);
+ dma_unmap_page(dev->dev.parent, phys_addr,
+ PAGE_SIZE, DMA_FROM_DEVICE);
rxq->left_size -= frag_size;
}
diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
index 702fec82d806..38cc01beea79 100644
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
@@ -3055,10 +3055,12 @@ static int mvpp2_poll(struct napi_struct *napi, int budget)
cause_rx_tx & ~MVPP2_CAUSE_MISC_SUM_MASK);
}
- cause_tx = cause_rx_tx & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
- if (cause_tx) {
- cause_tx >>= MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_OFFSET;
- mvpp2_tx_done(port, cause_tx, qv->sw_thread_id);
+ if (port->has_tx_irqs) {
+ cause_tx = cause_rx_tx & MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_MASK;
+ if (cause_tx) {
+ cause_tx >>= MVPP2_CAUSE_TXQ_OCCUP_DESC_ALL_OFFSET;
+ mvpp2_tx_done(port, cause_tx, qv->sw_thread_id);
+ }
}
/* Process RX packets */
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
index 6785661d1a72..fe49384eba48 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c
@@ -1286,20 +1286,6 @@ out:
mutex_unlock(&mdev->state_lock);
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void mlx4_en_netpoll(struct net_device *dev)
-{
- struct mlx4_en_priv *priv = netdev_priv(dev);
- struct mlx4_en_cq *cq;
- int i;
-
- for (i = 0; i < priv->tx_ring_num[TX]; i++) {
- cq = priv->tx_cq[TX][i];
- napi_schedule(&cq->napi);
- }
-}
-#endif
-
static int mlx4_en_set_rss_steer_rules(struct mlx4_en_priv *priv)
{
u64 reg_id;
@@ -2946,9 +2932,6 @@ static const struct net_device_ops mlx4_netdev_ops = {
.ndo_tx_timeout = mlx4_en_tx_timeout,
.ndo_vlan_rx_add_vid = mlx4_en_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = mlx4_en_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = mlx4_en_netpoll,
-#endif
.ndo_set_features = mlx4_en_set_features,
.ndo_fix_features = mlx4_en_fix_features,
.ndo_setup_tc = __mlx4_en_setup_tc,
@@ -2983,9 +2966,6 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
.ndo_set_vf_link_state = mlx4_en_set_vf_link_state,
.ndo_get_vf_stats = mlx4_en_get_vf_stats,
.ndo_get_vf_config = mlx4_en_get_vf_config,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = mlx4_en_netpoll,
-#endif
.ndo_set_features = mlx4_en_set_features,
.ndo_fix_features = mlx4_en_fix_features,
.ndo_setup_tc = __mlx4_en_setup_tc,
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index 1f3372c1802e..2df92dbd38e1 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -240,7 +240,8 @@ static void mlx4_set_eq_affinity_hint(struct mlx4_priv *priv, int vec)
struct mlx4_dev *dev = &priv->dev;
struct mlx4_eq *eq = &priv->eq_table.eq[vec];
- if (!eq->affinity_mask || cpumask_empty(eq->affinity_mask))
+ if (!cpumask_available(eq->affinity_mask) ||
+ cpumask_empty(eq->affinity_mask))
return;
hint_err = irq_set_affinity_hint(eq->irq, eq->affinity_mask);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 3ce14d42ddc8..a53736c26c0c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -206,7 +206,7 @@ static void poll_timeout(struct mlx5_cmd_work_ent *ent)
u8 own;
do {
- own = ent->lay->status_own;
+ own = READ_ONCE(ent->lay->status_own);
if (!(own & CMD_OWNER_HW)) {
ent->ret = 0;
return;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
index eddd7702680b..e88340e196f7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.c
@@ -183,12 +183,13 @@ static const struct tlsdev_ops mlx5e_tls_ops = {
void mlx5e_tls_build_netdev(struct mlx5e_priv *priv)
{
- u32 caps = mlx5_accel_tls_device_caps(priv->mdev);
struct net_device *netdev = priv->netdev;
+ u32 caps;
if (!mlx5_accel_is_tls_device(priv->mdev))
return;
+ caps = mlx5_accel_tls_device_caps(priv->mdev);
if (caps & MLX5_ACCEL_TLS_TX) {
netdev->features |= NETIF_F_HW_TLS_TX;
netdev->hw_features |= NETIF_F_HW_TLS_TX;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index 5a7939e70190..54118b77dc1f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -4315,22 +4315,6 @@ static int mlx5e_xdp(struct net_device *dev, struct netdev_bpf *xdp)
}
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-/* Fake "interrupt" called by netpoll (eg netconsole) to send skbs without
- * reenabling interrupts.
- */
-static void mlx5e_netpoll(struct net_device *dev)
-{
- struct mlx5e_priv *priv = netdev_priv(dev);
- struct mlx5e_channels *chs = &priv->channels;
-
- int i;
-
- for (i = 0; i < chs->num; i++)
- napi_schedule(&chs->c[i]->napi);
-}
-#endif
-
static const struct net_device_ops mlx5e_netdev_ops = {
.ndo_open = mlx5e_open,
.ndo_stop = mlx5e_close,
@@ -4356,9 +4340,6 @@ static const struct net_device_ops mlx5e_netdev_ops = {
#ifdef CONFIG_MLX5_EN_ARFS
.ndo_rx_flow_steer = mlx5e_rx_flow_steer,
#endif
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = mlx5e_netpoll,
-#endif
#ifdef CONFIG_MLX5_ESWITCH
/* SRIOV E-Switch NDOs */
.ndo_set_vf_mac = mlx5e_set_vf_mac,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
index dae1c5c5d27c..d2f76070ea7c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/transobj.c
@@ -509,7 +509,7 @@ static int mlx5_hairpin_modify_sq(struct mlx5_core_dev *peer_mdev, u32 sqn,
sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx);
- if (next_state == MLX5_RQC_STATE_RDY) {
+ if (next_state == MLX5_SQC_STATE_RDY) {
MLX5_SET(sqc, sqc, hairpin_peer_rq, peer_rq);
MLX5_SET(sqc, sqc, hairpin_peer_vhca, peer_vhca);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 930700413b1d..b492152c8881 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -44,8 +44,8 @@
#define MLXSW_SP_FWREV_MINOR_TO_BRANCH(minor) ((minor) / 100)
#define MLXSW_SP1_FWREV_MAJOR 13
-#define MLXSW_SP1_FWREV_MINOR 1702
-#define MLXSW_SP1_FWREV_SUBMINOR 6
+#define MLXSW_SP1_FWREV_MINOR 1703
+#define MLXSW_SP1_FWREV_SUBMINOR 4
#define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702
static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
diff --git a/drivers/net/ethernet/mscc/ocelot_board.c b/drivers/net/ethernet/mscc/ocelot_board.c
index 26bb3b18f3be..3cdf63e35b53 100644
--- a/drivers/net/ethernet/mscc/ocelot_board.c
+++ b/drivers/net/ethernet/mscc/ocelot_board.c
@@ -91,7 +91,7 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
struct sk_buff *skb;
struct net_device *dev;
u32 *buf;
- int sz, len;
+ int sz, len, buf_len;
u32 ifh[4];
u32 val;
struct frame_info info;
@@ -116,14 +116,20 @@ static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
err = -ENOMEM;
break;
}
- buf = (u32 *)skb_put(skb, info.len);
+ buf_len = info.len - ETH_FCS_LEN;
+ buf = (u32 *)skb_put(skb, buf_len);
len = 0;
do {
sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
*buf++ = val;
len += sz;
- } while ((sz == 4) && (len < info.len));
+ } while (len < buf_len);
+
+ /* Read the FCS and discard it */
+ sz = ocelot_rx_frame_word(ocelot, grp, false, &val);
+ /* Update the statistics if part of the FCS was read before */
+ len -= ETH_FCS_LEN - sz;
if (sz < 0) {
err = sz;
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 253bdaef1505..8ed38fd5a852 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3146,21 +3146,6 @@ nfp_net_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid)
return nfp_net_reconfig_mbox(nn, NFP_NET_CFG_MBOX_CMD_CTAG_FILTER_KILL);
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void nfp_net_netpoll(struct net_device *netdev)
-{
- struct nfp_net *nn = netdev_priv(netdev);
- int i;
-
- /* nfp_net's NAPIs are statically allocated so even if there is a race
- * with reconfig path this will simply try to schedule some disabled
- * NAPI instances.
- */
- for (i = 0; i < nn->dp.num_stack_tx_rings; i++)
- napi_schedule_irqoff(&nn->r_vecs[i].napi);
-}
-#endif
-
static void nfp_net_stat64(struct net_device *netdev,
struct rtnl_link_stats64 *stats)
{
@@ -3519,9 +3504,6 @@ const struct net_device_ops nfp_net_netdev_ops = {
.ndo_get_stats64 = nfp_net_stat64,
.ndo_vlan_rx_add_vid = nfp_net_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = nfp_net_vlan_rx_kill_vid,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = nfp_net_netpoll,
-#endif
.ndo_set_vf_mac = nfp_app_set_vf_mac,
.ndo_set_vf_vlan = nfp_app_set_vf_vlan,
.ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
index 6bb76e6d3c14..f5459de6d60a 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c
@@ -190,10 +190,8 @@ qed_dcbx_dp_protocol(struct qed_hwfn *p_hwfn, struct qed_dcbx_results *p_data)
static void
qed_dcbx_set_params(struct qed_dcbx_results *p_data,
- struct qed_hw_info *p_info,
- bool enable,
- u8 prio,
- u8 tc,
+ struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+ bool enable, u8 prio, u8 tc,
enum dcbx_protocol_type type,
enum qed_pci_personality personality)
{
@@ -206,19 +204,30 @@ qed_dcbx_set_params(struct qed_dcbx_results *p_data,
else
p_data->arr[type].update = DONT_UPDATE_DCB_DSCP;
+ /* Do not add vlan tag 0 when DCB is enabled and port in UFP/OV mode */
+ if ((test_bit(QED_MF_8021Q_TAGGING, &p_hwfn->cdev->mf_bits) ||
+ test_bit(QED_MF_8021AD_TAGGING, &p_hwfn->cdev->mf_bits)))
+ p_data->arr[type].dont_add_vlan0 = true;
+
/* QM reconf data */
- if (p_info->personality == personality)
- qed_hw_info_set_offload_tc(p_info, tc);
+ if (p_hwfn->hw_info.personality == personality)
+ qed_hw_info_set_offload_tc(&p_hwfn->hw_info, tc);
+
+ /* Configure dcbx vlan priority in doorbell block for roce EDPM */
+ if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits) &&
+ type == DCBX_PROTOCOL_ROCE) {
+ qed_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1);
+ qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_PCP_BB_K2, prio << 1);
+ }
}
/* Update app protocol data and hw_info fields with the TLV info */
static void
qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,
- struct qed_hwfn *p_hwfn,
- bool enable,
- u8 prio, u8 tc, enum dcbx_protocol_type type)
+ struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
+ bool enable, u8 prio, u8 tc,
+ enum dcbx_protocol_type type)
{
- struct qed_hw_info *p_info = &p_hwfn->hw_info;
enum qed_pci_personality personality;
enum dcbx_protocol_type id;
int i;
@@ -231,7 +240,7 @@ qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,
personality = qed_dcbx_app_update[i].personality;
- qed_dcbx_set_params(p_data, p_info, enable,
+ qed_dcbx_set_params(p_data, p_hwfn, p_ptt, enable,
prio, tc, type, personality);
}
}
@@ -265,7 +274,7 @@ qed_dcbx_get_app_protocol_type(struct qed_hwfn *p_hwfn,
* reconfiguring QM. Get protocol specific data for PF update ramrod command.
*/
static int
-qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
+qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,
struct qed_dcbx_results *p_data,
struct dcbx_app_priority_entry *p_tbl,
u32 pri_tc_tbl, int count, u8 dcbx_version)
@@ -309,7 +318,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
enable = true;
}
- qed_dcbx_update_app_info(p_data, p_hwfn, enable,
+ qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, enable,
priority, tc, type);
}
}
@@ -331,7 +340,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
continue;
enable = (type == DCBX_PROTOCOL_ETH) ? false : !!dcbx_version;
- qed_dcbx_update_app_info(p_data, p_hwfn, enable,
+ qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, enable,
priority, tc, type);
}
@@ -341,7 +350,8 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn,
/* Parse app TLV's to update TC information in hw_info structure for
* reconfiguring QM. Get protocol specific data for PF update ramrod command.
*/
-static int qed_dcbx_process_mib_info(struct qed_hwfn *p_hwfn)
+static int
+qed_dcbx_process_mib_info(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
{
struct dcbx_app_priority_feature *p_app;
struct dcbx_app_priority_entry *p_tbl;
@@ -365,7 +375,7 @@ static int qed_dcbx_process_mib_info(struct qed_hwfn *p_hwfn)
p_info = &p_hwfn->hw_info;
num_entries = QED_MFW_GET_FIELD(p_app->flags, DCBX_APP_NUM_ENTRIES);
- rc = qed_dcbx_process_tlv(p_hwfn, &data, p_tbl, pri_tc_tbl,
+ rc = qed_dcbx_process_tlv(p_hwfn, p_ptt, &data, p_tbl, pri_tc_tbl,
num_entries, dcbx_version);
if (rc)
return rc;
@@ -891,7 +901,7 @@ qed_dcbx_mib_update_event(struct qed_hwfn *p_hwfn,
return rc;
if (type == QED_DCBX_OPERATIONAL_MIB) {
- rc = qed_dcbx_process_mib_info(p_hwfn);
+ rc = qed_dcbx_process_mib_info(p_hwfn, p_ptt);
if (!rc) {
/* reconfigure tcs of QM queues according
* to negotiation results
@@ -954,6 +964,7 @@ static void qed_dcbx_update_protocol_data(struct protocol_dcb_data *p_data,
p_data->dcb_enable_flag = p_src->arr[type].enable;
p_data->dcb_priority = p_src->arr[type].priority;
p_data->dcb_tc = p_src->arr[type].tc;
+ p_data->dcb_dont_add_vlan0 = p_src->arr[type].dont_add_vlan0;
}
/* Set pf update ramrod command params */
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.h b/drivers/net/ethernet/qlogic/qed/qed_dcbx.h
index a4d688c04e18..01f253ea4b22 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.h
@@ -55,6 +55,7 @@ struct qed_dcbx_app_data {
u8 update; /* Update indication */
u8 priority; /* Priority */
u8 tc; /* Traffic Class */
+ bool dont_add_vlan0; /* Do not insert a vlan tag with id 0 */
};
#define QED_DCBX_VERSION_DISABLED 0
diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c
index 016ca8a7ec8a..97f073fd3725 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_dev.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c
@@ -1706,7 +1706,7 @@ static int qed_vf_start(struct qed_hwfn *p_hwfn,
int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
{
struct qed_load_req_params load_req_params;
- u32 load_code, param, drv_mb_param;
+ u32 load_code, resp, param, drv_mb_param;
bool b_default_mtu = true;
struct qed_hwfn *p_hwfn;
int rc = 0, mfw_rc, i;
@@ -1852,6 +1852,19 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params)
if (IS_PF(cdev)) {
p_hwfn = QED_LEADING_HWFN(cdev);
+
+ /* Get pre-negotiated values for stag, bandwidth etc. */
+ DP_VERBOSE(p_hwfn,
+ QED_MSG_SPQ,
+ "Sending GET_OEM_UPDATES command to trigger stag/bandwidth attention handling\n");
+ drv_mb_param = 1 << DRV_MB_PARAM_DUMMY_OEM_UPDATES_OFFSET;
+ rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
+ DRV_MSG_CODE_GET_OEM_UPDATES,
+ drv_mb_param, &resp, &param);
+ if (rc)
+ DP_NOTICE(p_hwfn,
+ "Failed to send GET_OEM_UPDATES attention request\n");
+
drv_mb_param = STORM_FW_VERSION;
rc = qed_mcp_cmd(p_hwfn, p_hwfn->p_main_ptt,
DRV_MSG_CODE_OV_UPDATE_STORM_FW_VER,
diff --git a/drivers/net/ethernet/qlogic/qed/qed_hsi.h b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
index 8faceb691657..9b3ef00e5782 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_hsi.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_hsi.h
@@ -12414,6 +12414,7 @@ struct public_drv_mb {
#define DRV_MSG_SET_RESOURCE_VALUE_MSG 0x35000000
#define DRV_MSG_CODE_OV_UPDATE_WOL 0x38000000
#define DRV_MSG_CODE_OV_UPDATE_ESWITCH_MODE 0x39000000
+#define DRV_MSG_CODE_GET_OEM_UPDATES 0x41000000
#define DRV_MSG_CODE_BW_UPDATE_ACK 0x32000000
#define DRV_MSG_CODE_NIG_DRAIN 0x30000000
@@ -12541,6 +12542,9 @@ struct public_drv_mb {
#define DRV_MB_PARAM_ESWITCH_MODE_VEB 0x1
#define DRV_MB_PARAM_ESWITCH_MODE_VEPA 0x2
+#define DRV_MB_PARAM_DUMMY_OEM_UPDATES_MASK 0x1
+#define DRV_MB_PARAM_DUMMY_OEM_UPDATES_OFFSET 0
+
#define DRV_MB_PARAM_SET_LED_MODE_OPER 0x0
#define DRV_MB_PARAM_SET_LED_MODE_ON 0x1
#define DRV_MB_PARAM_SET_LED_MODE_OFF 0x2
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 5d37ec7e9b0b..58c7eb9d8e1b 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -1581,13 +1581,29 @@ static void qed_mcp_update_stag(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
p_hwfn->mcp_info->func_info.ovlan = (u16)shmem_info.ovlan_stag &
FUNC_MF_CFG_OV_STAG_MASK;
p_hwfn->hw_info.ovlan = p_hwfn->mcp_info->func_info.ovlan;
- if ((p_hwfn->hw_info.hw_mode & BIT(MODE_MF_SD)) &&
- (p_hwfn->hw_info.ovlan != QED_MCP_VLAN_UNSET)) {
- qed_wr(p_hwfn, p_ptt,
- NIG_REG_LLH_FUNC_TAG_VALUE, p_hwfn->hw_info.ovlan);
+ if (test_bit(QED_MF_OVLAN_CLSS, &p_hwfn->cdev->mf_bits)) {
+ if (p_hwfn->hw_info.ovlan != QED_MCP_VLAN_UNSET) {
+ qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_FUNC_TAG_VALUE,
+ p_hwfn->hw_info.ovlan);
+ qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_FUNC_TAG_EN, 1);
+
+ /* Configure DB to add external vlan to EDPM packets */
+ qed_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 1);
+ qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_EXT_VID_BB_K2,
+ p_hwfn->hw_info.ovlan);
+ } else {
+ qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_FUNC_TAG_EN, 0);
+ qed_wr(p_hwfn, p_ptt, NIG_REG_LLH_FUNC_TAG_VALUE, 0);
+ qed_wr(p_hwfn, p_ptt, DORQ_REG_TAG1_OVRD_MODE, 0);
+ qed_wr(p_hwfn, p_ptt, DORQ_REG_PF_EXT_VID_BB_K2, 0);
+ }
+
qed_sp_pf_update_stag(p_hwfn);
}
+ DP_VERBOSE(p_hwfn, QED_MSG_SP, "ovlan = %d hw_mode = 0x%x\n",
+ p_hwfn->mcp_info->func_info.ovlan, p_hwfn->hw_info.hw_mode);
+
/* Acknowledge the MFW */
qed_mcp_cmd(p_hwfn, p_ptt, DRV_MSG_CODE_S_TAG_UPDATE_ACK, 0,
&resp, &param);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
index f736f70956fd..2440970882c4 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_reg_addr.h
@@ -216,6 +216,12 @@
0x00c000UL
#define DORQ_REG_IFEN \
0x100040UL
+#define DORQ_REG_TAG1_OVRD_MODE \
+ 0x1008b4UL
+#define DORQ_REG_PF_PCP_BB_K2 \
+ 0x1008c4UL
+#define DORQ_REG_PF_EXT_VID_BB_K2 \
+ 0x1008c8UL
#define DORQ_REG_DB_DROP_REASON \
0x100a2cUL
#define DORQ_REG_DB_DROP_DETAILS \
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index bb529ff2ca81..ab30aaeac6d3 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -4071,6 +4071,15 @@ static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp)
phy_speed_up(dev->phydev);
genphy_soft_reset(dev->phydev);
+
+ /* It was reported that chip version 33 ends up with 10MBit/Half on a
+ * 1GBit link after resuming from S3. For whatever reason the PHY on
+ * this chip doesn't properly start a renegotiation when soft-reset.
+ * Explicitly requesting a renegotiation fixes this.
+ */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_33 &&
+ dev->phydev->autoneg == AUTONEG_ENABLE)
+ phy_restart_aneg(dev->phydev);
}
static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
diff --git a/drivers/net/ethernet/renesas/ravb.h b/drivers/net/ethernet/renesas/ravb.h
index 1470fc12282b..9b6bf557a2f5 100644
--- a/drivers/net/ethernet/renesas/ravb.h
+++ b/drivers/net/ethernet/renesas/ravb.h
@@ -428,6 +428,7 @@ enum EIS_BIT {
EIS_CULF1 = 0x00000080,
EIS_TFFF = 0x00000100,
EIS_QFS = 0x00010000,
+ EIS_RESERVED = (GENMASK(31, 17) | GENMASK(15, 11)),
};
/* RIC0 */
@@ -472,6 +473,7 @@ enum RIS0_BIT {
RIS0_FRF15 = 0x00008000,
RIS0_FRF16 = 0x00010000,
RIS0_FRF17 = 0x00020000,
+ RIS0_RESERVED = GENMASK(31, 18),
};
/* RIC1 */
@@ -528,6 +530,7 @@ enum RIS2_BIT {
RIS2_QFF16 = 0x00010000,
RIS2_QFF17 = 0x00020000,
RIS2_RFFF = 0x80000000,
+ RIS2_RESERVED = GENMASK(30, 18),
};
/* TIC */
@@ -544,6 +547,7 @@ enum TIS_BIT {
TIS_FTF1 = 0x00000002, /* Undocumented? */
TIS_TFUF = 0x00000100,
TIS_TFWF = 0x00000200,
+ TIS_RESERVED = (GENMASK(31, 20) | GENMASK(15, 12) | GENMASK(7, 4))
};
/* ISS */
@@ -617,6 +621,7 @@ enum GIC_BIT {
enum GIS_BIT {
GIS_PTCF = 0x00000001, /* Undocumented? */
GIS_PTMF = 0x00000004,
+ GIS_RESERVED = GENMASK(15, 10),
};
/* GIE (R-Car Gen3 only) */
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index aff5516b781e..d6f753925352 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -739,10 +739,11 @@ static void ravb_error_interrupt(struct net_device *ndev)
u32 eis, ris2;
eis = ravb_read(ndev, EIS);
- ravb_write(ndev, ~EIS_QFS, EIS);
+ ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS);
if (eis & EIS_QFS) {
ris2 = ravb_read(ndev, RIS2);
- ravb_write(ndev, ~(RIS2_QFF0 | RIS2_RFFF), RIS2);
+ ravb_write(ndev, ~(RIS2_QFF0 | RIS2_RFFF | RIS2_RESERVED),
+ RIS2);
/* Receive Descriptor Empty int */
if (ris2 & RIS2_QFF0)
@@ -795,7 +796,7 @@ static bool ravb_timestamp_interrupt(struct net_device *ndev)
u32 tis = ravb_read(ndev, TIS);
if (tis & TIS_TFUF) {
- ravb_write(ndev, ~TIS_TFUF, TIS);
+ ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS);
ravb_get_tx_tstamp(ndev);
return true;
}
@@ -930,7 +931,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
/* Processing RX Descriptor Ring */
if (ris0 & mask) {
/* Clear RX interrupt */
- ravb_write(ndev, ~mask, RIS0);
+ ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
if (ravb_rx(ndev, &quota, q))
goto out;
}
@@ -938,7 +939,7 @@ static int ravb_poll(struct napi_struct *napi, int budget)
if (tis & mask) {
spin_lock_irqsave(&priv->lock, flags);
/* Clear TX interrupt */
- ravb_write(ndev, ~mask, TIS);
+ ravb_write(ndev, ~(mask | TIS_RESERVED), TIS);
ravb_tx_free(ndev, q, true);
netif_wake_subqueue(ndev, q);
mmiowb();
diff --git a/drivers/net/ethernet/renesas/ravb_ptp.c b/drivers/net/ethernet/renesas/ravb_ptp.c
index 0721b5c35d91..dce2a40a31e3 100644
--- a/drivers/net/ethernet/renesas/ravb_ptp.c
+++ b/drivers/net/ethernet/renesas/ravb_ptp.c
@@ -315,7 +315,7 @@ void ravb_ptp_interrupt(struct net_device *ndev)
}
}
- ravb_write(ndev, ~gis, GIS);
+ ravb_write(ndev, ~(gis | GIS_RESERVED), GIS);
}
void ravb_ptp_init(struct net_device *ndev, struct platform_device *pdev)
diff --git a/drivers/net/ethernet/seeq/ether3.c b/drivers/net/ethernet/seeq/ether3.c
index c5bc124b41a9..d1bb73bf9914 100644
--- a/drivers/net/ethernet/seeq/ether3.c
+++ b/drivers/net/ethernet/seeq/ether3.c
@@ -77,7 +77,8 @@ static void ether3_setmulticastlist(struct net_device *dev);
static int ether3_rx(struct net_device *dev, unsigned int maxcnt);
static void ether3_tx(struct net_device *dev);
static int ether3_open (struct net_device *dev);
-static int ether3_sendpacket (struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t ether3_sendpacket(struct sk_buff *skb,
+ struct net_device *dev);
static irqreturn_t ether3_interrupt (int irq, void *dev_id);
static int ether3_close (struct net_device *dev);
static void ether3_setmulticastlist (struct net_device *dev);
@@ -481,7 +482,7 @@ static void ether3_timeout(struct net_device *dev)
/*
* Transmit a packet
*/
-static int
+static netdev_tx_t
ether3_sendpacket(struct sk_buff *skb, struct net_device *dev)
{
unsigned long flags;
diff --git a/drivers/net/ethernet/seeq/sgiseeq.c b/drivers/net/ethernet/seeq/sgiseeq.c
index 573691bc3b71..70cce63a6081 100644
--- a/drivers/net/ethernet/seeq/sgiseeq.c
+++ b/drivers/net/ethernet/seeq/sgiseeq.c
@@ -578,7 +578,8 @@ static inline int sgiseeq_reset(struct net_device *dev)
return 0;
}
-static int sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t
+sgiseeq_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct sgiseeq_private *sp = netdev_priv(dev);
struct hpc3_ethregs *hregs = sp->hregs;
diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c
index 18d533fdf14c..3140999642ba 100644
--- a/drivers/net/ethernet/sgi/ioc3-eth.c
+++ b/drivers/net/ethernet/sgi/ioc3-eth.c
@@ -99,7 +99,7 @@ struct ioc3_private {
static int ioc3_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static void ioc3_set_multicast_list(struct net_device *dev);
-static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev);
static void ioc3_timeout(struct net_device *dev);
static inline unsigned int ioc3_hash(const unsigned char *addr);
static inline void ioc3_stop(struct ioc3_private *ip);
@@ -1390,7 +1390,7 @@ static struct pci_driver ioc3_driver = {
.remove = ioc3_remove_one,
};
-static int ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t ioc3_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned long data;
struct ioc3_private *ip = netdev_priv(dev);
diff --git a/drivers/net/ethernet/sgi/meth.c b/drivers/net/ethernet/sgi/meth.c
index ea55abd62ec7..703fbbefea44 100644
--- a/drivers/net/ethernet/sgi/meth.c
+++ b/drivers/net/ethernet/sgi/meth.c
@@ -697,7 +697,7 @@ static void meth_add_to_tx_ring(struct meth_private *priv, struct sk_buff *skb)
/*
* Transmit a packet (called by the kernel)
*/
-static int meth_tx(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t meth_tx(struct sk_buff *skb, struct net_device *dev)
{
struct meth_private *priv = netdev_priv(dev);
unsigned long flags;
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 1854f270ad66..b1b305f8f414 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -258,10 +258,10 @@ struct stmmac_safety_stats {
#define MAX_DMA_RIWT 0xff
#define MIN_DMA_RIWT 0x20
/* Tx coalesce parameters */
-#define STMMAC_COAL_TX_TIMER 40000
+#define STMMAC_COAL_TX_TIMER 1000
#define STMMAC_MAX_COAL_TX_TICK 100000
#define STMMAC_TX_MAX_FRAMES 256
-#define STMMAC_TX_FRAMES 64
+#define STMMAC_TX_FRAMES 25
/* Packets types */
enum packets_types {
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index c0a855b7ab3b..63e1064b27a2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -48,6 +48,8 @@ struct stmmac_tx_info {
/* Frequently used values are kept adjacent for cache effect */
struct stmmac_tx_queue {
+ u32 tx_count_frames;
+ struct timer_list txtimer;
u32 queue_index;
struct stmmac_priv *priv_data;
struct dma_extended_desc *dma_etx ____cacheline_aligned_in_smp;
@@ -73,7 +75,14 @@ struct stmmac_rx_queue {
u32 rx_zeroc_thresh;
dma_addr_t dma_rx_phy;
u32 rx_tail_addr;
+};
+
+struct stmmac_channel {
struct napi_struct napi ____cacheline_aligned_in_smp;
+ struct stmmac_priv *priv_data;
+ u32 index;
+ int has_rx;
+ int has_tx;
};
struct stmmac_tc_entry {
@@ -109,14 +118,12 @@ struct stmmac_pps_cfg {
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
- u32 tx_count_frames;
u32 tx_coal_frames;
u32 tx_coal_timer;
int tx_coalesce;
int hwts_tx_en;
bool tx_path_in_lpi_mode;
- struct timer_list txtimer;
bool tso;
unsigned int dma_buf_sz;
@@ -137,6 +144,9 @@ struct stmmac_priv {
/* TX Queue */
struct stmmac_tx_queue tx_queue[MTL_MAX_TX_QUEUES];
+ /* Generic channel for NAPI */
+ struct stmmac_channel channel[STMMAC_CH_MAX];
+
bool oldlink;
int speed;
int oldduplex;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 9f458bb16f2a..75896d6ba6e2 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -148,12 +148,14 @@ static void stmmac_verify_args(void)
static void stmmac_disable_all_queues(struct stmmac_priv *priv)
{
u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
+ u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
+ u32 maxq = max(rx_queues_cnt, tx_queues_cnt);
u32 queue;
- for (queue = 0; queue < rx_queues_cnt; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
- napi_disable(&rx_q->napi);
+ napi_disable(&ch->napi);
}
}
@@ -164,12 +166,14 @@ static void stmmac_disable_all_queues(struct stmmac_priv *priv)
static void stmmac_enable_all_queues(struct stmmac_priv *priv)
{
u32 rx_queues_cnt = priv->plat->rx_queues_to_use;
+ u32 tx_queues_cnt = priv->plat->tx_queues_to_use;
+ u32 maxq = max(rx_queues_cnt, tx_queues_cnt);
u32 queue;
- for (queue = 0; queue < rx_queues_cnt; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
- napi_enable(&rx_q->napi);
+ napi_enable(&ch->napi);
}
}
@@ -1843,18 +1847,18 @@ static void stmmac_dma_operation_mode(struct stmmac_priv *priv)
* @queue: TX queue index
* Description: it reclaims the transmit resources after transmission completes.
*/
-static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
+static int stmmac_tx_clean(struct stmmac_priv *priv, int budget, u32 queue)
{
struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
unsigned int bytes_compl = 0, pkts_compl = 0;
- unsigned int entry;
+ unsigned int entry, count = 0;
- netif_tx_lock(priv->dev);
+ __netif_tx_lock_bh(netdev_get_tx_queue(priv->dev, queue));
priv->xstats.tx_clean++;
entry = tx_q->dirty_tx;
- while (entry != tx_q->cur_tx) {
+ while ((entry != tx_q->cur_tx) && (count < budget)) {
struct sk_buff *skb = tx_q->tx_skbuff[entry];
struct dma_desc *p;
int status;
@@ -1870,6 +1874,8 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
if (unlikely(status & tx_dma_own))
break;
+ count++;
+
/* Make sure descriptor fields are read after reading
* the own bit.
*/
@@ -1937,7 +1943,10 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
stmmac_enable_eee_mode(priv);
mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
}
- netif_tx_unlock(priv->dev);
+
+ __netif_tx_unlock_bh(netdev_get_tx_queue(priv->dev, queue));
+
+ return count;
}
/**
@@ -2020,6 +2029,33 @@ static bool stmmac_safety_feat_interrupt(struct stmmac_priv *priv)
return false;
}
+static int stmmac_napi_check(struct stmmac_priv *priv, u32 chan)
+{
+ int status = stmmac_dma_interrupt_status(priv, priv->ioaddr,
+ &priv->xstats, chan);
+ struct stmmac_channel *ch = &priv->channel[chan];
+ bool needs_work = false;
+
+ if ((status & handle_rx) && ch->has_rx) {
+ needs_work = true;
+ } else {
+ status &= ~handle_rx;
+ }
+
+ if ((status & handle_tx) && ch->has_tx) {
+ needs_work = true;
+ } else {
+ status &= ~handle_tx;
+ }
+
+ if (needs_work && napi_schedule_prep(&ch->napi)) {
+ stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+ __napi_schedule(&ch->napi);
+ }
+
+ return status;
+}
+
/**
* stmmac_dma_interrupt - DMA ISR
* @priv: driver private structure
@@ -2034,57 +2070,14 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
u32 channels_to_check = tx_channel_count > rx_channel_count ?
tx_channel_count : rx_channel_count;
u32 chan;
- bool poll_scheduled = false;
int status[max_t(u32, MTL_MAX_TX_QUEUES, MTL_MAX_RX_QUEUES)];
/* Make sure we never check beyond our status buffer. */
if (WARN_ON_ONCE(channels_to_check > ARRAY_SIZE(status)))
channels_to_check = ARRAY_SIZE(status);
- /* Each DMA channel can be used for rx and tx simultaneously, yet
- * napi_struct is embedded in struct stmmac_rx_queue rather than in a
- * stmmac_channel struct.
- * Because of this, stmmac_poll currently checks (and possibly wakes)
- * all tx queues rather than just a single tx queue.
- */
for (chan = 0; chan < channels_to_check; chan++)
- status[chan] = stmmac_dma_interrupt_status(priv, priv->ioaddr,
- &priv->xstats, chan);
-
- for (chan = 0; chan < rx_channel_count; chan++) {
- if (likely(status[chan] & handle_rx)) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[chan];
-
- if (likely(napi_schedule_prep(&rx_q->napi))) {
- stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
- __napi_schedule(&rx_q->napi);
- poll_scheduled = true;
- }
- }
- }
-
- /* If we scheduled poll, we already know that tx queues will be checked.
- * If we didn't schedule poll, see if any DMA channel (used by tx) has a
- * completed transmission, if so, call stmmac_poll (once).
- */
- if (!poll_scheduled) {
- for (chan = 0; chan < tx_channel_count; chan++) {
- if (status[chan] & handle_tx) {
- /* It doesn't matter what rx queue we choose
- * here. We use 0 since it always exists.
- */
- struct stmmac_rx_queue *rx_q =
- &priv->rx_queue[0];
-
- if (likely(napi_schedule_prep(&rx_q->napi))) {
- stmmac_disable_dma_irq(priv,
- priv->ioaddr, chan);
- __napi_schedule(&rx_q->napi);
- }
- break;
- }
- }
- }
+ status[chan] = stmmac_napi_check(priv, chan);
for (chan = 0; chan < tx_channel_count; chan++) {
if (unlikely(status[chan] & tx_hard_error_bump_tc)) {
@@ -2220,8 +2213,7 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
stmmac_init_tx_chan(priv, priv->ioaddr, priv->plat->dma_cfg,
tx_q->dma_tx_phy, chan);
- tx_q->tx_tail_addr = tx_q->dma_tx_phy +
- (DMA_TX_SIZE * sizeof(struct dma_desc));
+ tx_q->tx_tail_addr = tx_q->dma_tx_phy;
stmmac_set_tx_tail_ptr(priv, priv->ioaddr,
tx_q->tx_tail_addr, chan);
}
@@ -2233,6 +2225,13 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
return ret;
}
+static void stmmac_tx_timer_arm(struct stmmac_priv *priv, u32 queue)
+{
+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue];
+
+ mod_timer(&tx_q->txtimer, STMMAC_COAL_TIMER(priv->tx_coal_timer));
+}
+
/**
* stmmac_tx_timer - mitigation sw timer for tx.
* @data: data pointer
@@ -2241,13 +2240,14 @@ static int stmmac_init_dma_engine(struct stmmac_priv *priv)
*/
static void stmmac_tx_timer(struct timer_list *t)
{
- struct stmmac_priv *priv = from_timer(priv, t, txtimer);
- u32 tx_queues_count = priv->plat->tx_queues_to_use;
- u32 queue;
+ struct stmmac_tx_queue *tx_q = from_timer(tx_q, t, txtimer);
+ struct stmmac_priv *priv = tx_q->priv_data;
+ struct stmmac_channel *ch;
+
+ ch = &priv->channel[tx_q->queue_index];
- /* let's scan all the tx queues */
- for (queue = 0; queue < tx_queues_count; queue++)
- stmmac_tx_clean(priv, queue);
+ if (likely(napi_schedule_prep(&ch->napi)))
+ __napi_schedule(&ch->napi);
}
/**
@@ -2260,11 +2260,17 @@ static void stmmac_tx_timer(struct timer_list *t)
*/
static void stmmac_init_tx_coalesce(struct stmmac_priv *priv)
{
+ u32 tx_channel_count = priv->plat->tx_queues_to_use;
+ u32 chan;
+
priv->tx_coal_frames = STMMAC_TX_FRAMES;
priv->tx_coal_timer = STMMAC_COAL_TX_TIMER;
- timer_setup(&priv->txtimer, stmmac_tx_timer, 0);
- priv->txtimer.expires = STMMAC_COAL_TIMER(priv->tx_coal_timer);
- add_timer(&priv->txtimer);
+
+ for (chan = 0; chan < tx_channel_count; chan++) {
+ struct stmmac_tx_queue *tx_q = &priv->tx_queue[chan];
+
+ timer_setup(&tx_q->txtimer, stmmac_tx_timer, 0);
+ }
}
static void stmmac_set_rings_length(struct stmmac_priv *priv)
@@ -2592,6 +2598,7 @@ static void stmmac_hw_teardown(struct net_device *dev)
static int stmmac_open(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ u32 chan;
int ret;
stmmac_check_ether_addr(priv);
@@ -2688,7 +2695,9 @@ irq_error:
if (dev->phydev)
phy_stop(dev->phydev);
- del_timer_sync(&priv->txtimer);
+ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
+ del_timer_sync(&priv->tx_queue[chan].txtimer);
+
stmmac_hw_teardown(dev);
init_error:
free_dma_desc_resources(priv);
@@ -2708,6 +2717,7 @@ dma_desc_error:
static int stmmac_release(struct net_device *dev)
{
struct stmmac_priv *priv = netdev_priv(dev);
+ u32 chan;
if (priv->eee_enabled)
del_timer_sync(&priv->eee_ctrl_timer);
@@ -2722,7 +2732,8 @@ static int stmmac_release(struct net_device *dev)
stmmac_disable_all_queues(priv);
- del_timer_sync(&priv->txtimer);
+ for (chan = 0; chan < priv->plat->tx_queues_to_use; chan++)
+ del_timer_sync(&priv->tx_queue[chan].txtimer);
/* Free the IRQ lines */
free_irq(dev->irq, dev);
@@ -2936,14 +2947,13 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
priv->xstats.tx_tso_nfrags += nfrags;
/* Manage tx mitigation */
- priv->tx_count_frames += nfrags + 1;
- if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
- mod_timer(&priv->txtimer,
- STMMAC_COAL_TIMER(priv->tx_coal_timer));
- } else {
- priv->tx_count_frames = 0;
+ tx_q->tx_count_frames += nfrags + 1;
+ if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
stmmac_set_tx_ic(priv, desc);
priv->xstats.tx_set_ic_bit++;
+ tx_q->tx_count_frames = 0;
+ } else {
+ stmmac_tx_timer_arm(priv, queue);
}
skb_tx_timestamp(skb);
@@ -2992,6 +3002,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
+ tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK;
@@ -3146,14 +3157,13 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
* This approach takes care about the fragments: desc is the first
* element in case of no SG.
*/
- priv->tx_count_frames += nfrags + 1;
- if (likely(priv->tx_coal_frames > priv->tx_count_frames)) {
- mod_timer(&priv->txtimer,
- STMMAC_COAL_TIMER(priv->tx_coal_timer));
- } else {
- priv->tx_count_frames = 0;
+ tx_q->tx_count_frames += nfrags + 1;
+ if (priv->tx_coal_frames <= tx_q->tx_count_frames) {
stmmac_set_tx_ic(priv, desc);
priv->xstats.tx_set_ic_bit++;
+ tx_q->tx_count_frames = 0;
+ } else {
+ stmmac_tx_timer_arm(priv, queue);
}
skb_tx_timestamp(skb);
@@ -3199,6 +3209,8 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
netdev_tx_sent_queue(netdev_get_tx_queue(dev, queue), skb->len);
stmmac_enable_dma_transmission(priv, priv->ioaddr);
+
+ tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
return NETDEV_TX_OK;
@@ -3319,6 +3331,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue)
static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
{
struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ struct stmmac_channel *ch = &priv->channel[queue];
unsigned int entry = rx_q->cur_rx;
int coe = priv->hw->rx_csum;
unsigned int next_entry;
@@ -3491,7 +3504,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
else
skb->ip_summed = CHECKSUM_UNNECESSARY;
- napi_gro_receive(&rx_q->napi, skb);
+ napi_gro_receive(&ch->napi, skb);
priv->dev->stats.rx_packets++;
priv->dev->stats.rx_bytes += frame_len;
@@ -3514,27 +3527,33 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue)
* Description :
* To look at the incoming frames and clear the tx resources.
*/
-static int stmmac_poll(struct napi_struct *napi, int budget)
+static int stmmac_napi_poll(struct napi_struct *napi, int budget)
{
- struct stmmac_rx_queue *rx_q =
- container_of(napi, struct stmmac_rx_queue, napi);
- struct stmmac_priv *priv = rx_q->priv_data;
- u32 tx_count = priv->plat->tx_queues_to_use;
- u32 chan = rx_q->queue_index;
- int work_done = 0;
- u32 queue;
+ struct stmmac_channel *ch =
+ container_of(napi, struct stmmac_channel, napi);
+ struct stmmac_priv *priv = ch->priv_data;
+ int work_done = 0, work_rem = budget;
+ u32 chan = ch->index;
priv->xstats.napi_poll++;
- /* check all the queues */
- for (queue = 0; queue < tx_count; queue++)
- stmmac_tx_clean(priv, queue);
+ if (ch->has_tx) {
+ int done = stmmac_tx_clean(priv, work_rem, chan);
- work_done = stmmac_rx(priv, budget, rx_q->queue_index);
- if (work_done < budget) {
- napi_complete_done(napi, work_done);
- stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+ work_done += done;
+ work_rem -= done;
+ }
+
+ if (ch->has_rx) {
+ int done = stmmac_rx(priv, work_rem, chan);
+
+ work_done += done;
+ work_rem -= done;
}
+
+ if (work_done < budget && napi_complete_done(napi, work_done))
+ stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+
return work_done;
}
@@ -4198,8 +4217,8 @@ int stmmac_dvr_probe(struct device *device,
{
struct net_device *ndev = NULL;
struct stmmac_priv *priv;
+ u32 queue, maxq;
int ret = 0;
- u32 queue;
ndev = alloc_etherdev_mqs(sizeof(struct stmmac_priv),
MTL_MAX_TX_QUEUES,
@@ -4322,11 +4341,22 @@ int stmmac_dvr_probe(struct device *device,
"Enable RX Mitigation via HW Watchdog Timer\n");
}
- for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ /* Setup channels NAPI */
+ maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
- netif_napi_add(ndev, &rx_q->napi, stmmac_poll,
- (8 * priv->plat->rx_queues_to_use));
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
+
+ ch->priv_data = priv;
+ ch->index = queue;
+
+ if (queue < priv->plat->rx_queues_to_use)
+ ch->has_rx = true;
+ if (queue < priv->plat->tx_queues_to_use)
+ ch->has_tx = true;
+
+ netif_napi_add(ndev, &ch->napi, stmmac_napi_poll,
+ NAPI_POLL_WEIGHT);
}
mutex_init(&priv->lock);
@@ -4372,10 +4402,10 @@ error_netdev_register:
priv->hw->pcs != STMMAC_PCS_RTBI)
stmmac_mdio_unregister(ndev);
error_mdio_register:
- for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
- struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue];
+ for (queue = 0; queue < maxq; queue++) {
+ struct stmmac_channel *ch = &priv->channel[queue];
- netif_napi_del(&rx_q->napi);
+ netif_napi_del(&ch->napi);
}
error_hw_init:
destroy_workqueue(priv->wq);
diff --git a/drivers/net/ethernet/wiznet/w5100.c b/drivers/net/ethernet/wiznet/w5100.c
index 2bdfb39215e9..d8ba512f166a 100644
--- a/drivers/net/ethernet/wiznet/w5100.c
+++ b/drivers/net/ethernet/wiznet/w5100.c
@@ -835,7 +835,7 @@ static void w5100_tx_work(struct work_struct *work)
w5100_tx_skb(priv->ndev, skb);
}
-static int w5100_start_tx(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t w5100_start_tx(struct sk_buff *skb, struct net_device *ndev)
{
struct w5100_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/wiznet/w5300.c b/drivers/net/ethernet/wiznet/w5300.c
index 56ae573001e8..80fdbff67d82 100644
--- a/drivers/net/ethernet/wiznet/w5300.c
+++ b/drivers/net/ethernet/wiznet/w5300.c
@@ -365,7 +365,7 @@ static void w5300_tx_timeout(struct net_device *ndev)
netif_wake_queue(ndev);
}
-static int w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t w5300_start_tx(struct sk_buff *skb, struct net_device *ndev)
{
struct w5300_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/phy/sfp-bus.c b/drivers/net/phy/sfp-bus.c
index 740655261e5b..83060fb349f4 100644
--- a/drivers/net/phy/sfp-bus.c
+++ b/drivers/net/phy/sfp-bus.c
@@ -349,6 +349,7 @@ static int sfp_register_bus(struct sfp_bus *bus)
}
if (bus->started)
bus->socket_ops->start(bus->sfp);
+ bus->netdev->sfp_bus = bus;
bus->registered = true;
return 0;
}
@@ -357,6 +358,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
{
const struct sfp_upstream_ops *ops = bus->upstream_ops;
+ bus->netdev->sfp_bus = NULL;
if (bus->registered) {
if (bus->started)
bus->socket_ops->stop(bus->sfp);
@@ -438,7 +440,6 @@ static void sfp_upstream_clear(struct sfp_bus *bus)
{
bus->upstream_ops = NULL;
bus->upstream = NULL;
- bus->netdev->sfp_bus = NULL;
bus->netdev = NULL;
}
@@ -467,7 +468,6 @@ struct sfp_bus *sfp_register_upstream(struct fwnode_handle *fwnode,
bus->upstream_ops = ops;
bus->upstream = upstream;
bus->netdev = ndev;
- ndev->sfp_bus = bus;
if (bus->sfp) {
ret = sfp_register_bus(bus);
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index ebd07ad82431..e2648b5a3861 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -1153,43 +1153,6 @@ static netdev_features_t tun_net_fix_features(struct net_device *dev,
return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
}
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void tun_poll_controller(struct net_device *dev)
-{
- /*
- * Tun only receives frames when:
- * 1) the char device endpoint gets data from user space
- * 2) the tun socket gets a sendmsg call from user space
- * If NAPI is not enabled, since both of those are synchronous
- * operations, we are guaranteed never to have pending data when we poll
- * for it so there is nothing to do here but return.
- * We need this though so netpoll recognizes us as an interface that
- * supports polling, which enables bridge devices in virt setups to
- * still use netconsole
- * If NAPI is enabled, however, we need to schedule polling for all
- * queues unless we are using napi_gro_frags(), which we call in
- * process context and not in NAPI context.
- */
- struct tun_struct *tun = netdev_priv(dev);
-
- if (tun->flags & IFF_NAPI) {
- struct tun_file *tfile;
- int i;
-
- if (tun_napi_frags_enabled(tun))
- return;
-
- rcu_read_lock();
- for (i = 0; i < tun->numqueues; i++) {
- tfile = rcu_dereference(tun->tfiles[i]);
- if (tfile->napi_enabled)
- napi_schedule(&tfile->napi);
- }
- rcu_read_unlock();
- }
- return;
-}
-#endif
static void tun_set_headroom(struct net_device *dev, int new_hr)
{
@@ -1283,9 +1246,6 @@ static const struct net_device_ops tun_netdev_ops = {
.ndo_start_xmit = tun_net_xmit,
.ndo_fix_features = tun_net_fix_features,
.ndo_select_queue = tun_select_queue,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = tun_poll_controller,
-#endif
.ndo_set_rx_headroom = tun_set_headroom,
.ndo_get_stats64 = tun_net_get_stats64,
};
@@ -1365,9 +1325,6 @@ static const struct net_device_ops tap_netdev_ops = {
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
.ndo_select_queue = tun_select_queue,
-#ifdef CONFIG_NET_POLL_CONTROLLER
- .ndo_poll_controller = tun_poll_controller,
-#endif
.ndo_features_check = passthru_features_check,
.ndo_set_rx_headroom = tun_set_headroom,
.ndo_get_stats64 = tun_net_get_stats64,
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index 5a9562881d4e..9fe3fff818b8 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -537,8 +537,10 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
INIT_WORK(&ctrl->ana_work, nvme_ana_work);
ctrl->ana_log_buf = kmalloc(ctrl->ana_log_size, GFP_KERNEL);
- if (!ctrl->ana_log_buf)
+ if (!ctrl->ana_log_buf) {
+ error = -ENOMEM;
goto out;
+ }
error = nvme_read_ana_log(ctrl, true);
if (error)
@@ -547,7 +549,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
out_free_ana_log_buf:
kfree(ctrl->ana_log_buf);
out:
- return -ENOMEM;
+ return error;
}
void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c
index 778c4f76a884..2153956a0b20 100644
--- a/drivers/pci/controller/dwc/pcie-designware.c
+++ b/drivers/pci/controller/dwc/pcie-designware.c
@@ -135,7 +135,7 @@ static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index,
if (val & PCIE_ATU_ENABLE)
return;
- usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+ mdelay(LINK_WAIT_IATU);
}
dev_err(pci->dev, "Outbound iATU is not being enabled\n");
}
@@ -178,7 +178,7 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
if (val & PCIE_ATU_ENABLE)
return;
- usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+ mdelay(LINK_WAIT_IATU);
}
dev_err(pci->dev, "Outbound iATU is not being enabled\n");
}
@@ -236,7 +236,7 @@ static int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index,
if (val & PCIE_ATU_ENABLE)
return 0;
- usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+ mdelay(LINK_WAIT_IATU);
}
dev_err(pci->dev, "Inbound iATU is not being enabled\n");
@@ -282,7 +282,7 @@ int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
if (val & PCIE_ATU_ENABLE)
return 0;
- usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+ mdelay(LINK_WAIT_IATU);
}
dev_err(pci->dev, "Inbound iATU is not being enabled\n");
diff --git a/drivers/pci/controller/dwc/pcie-designware.h b/drivers/pci/controller/dwc/pcie-designware.h
index 96126fd8403c..9f1a5e399b70 100644
--- a/drivers/pci/controller/dwc/pcie-designware.h
+++ b/drivers/pci/controller/dwc/pcie-designware.h
@@ -26,8 +26,7 @@
/* Parameters for the waiting for iATU enabled routine */
#define LINK_WAIT_MAX_IATU_RETRIES 5
-#define LINK_WAIT_IATU_MIN 9000
-#define LINK_WAIT_IATU_MAX 10000
+#define LINK_WAIT_IATU 9
/* Synopsys-specific PCIe configuration registers */
#define PCIE_PORT_LINK_CONTROL 0x710
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index ee80e79db21a..9ba4d12c179c 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -1484,8 +1484,10 @@ static void hv_pci_assign_slots(struct hv_pcibus_device *hbus)
snprintf(name, SLOT_NAME_SIZE, "%u", hpdev->desc.ser);
hpdev->pci_slot = pci_create_slot(hbus->pci_bus, slot_nr,
name, NULL);
- if (!hpdev->pci_slot)
+ if (IS_ERR(hpdev->pci_slot)) {
pr_warn("pci_create slot %s failed\n", name);
+ hpdev->pci_slot = NULL;
+ }
}
}
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index ef0b1b6ba86f..12afa7fdf77e 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -457,17 +457,18 @@ static void acpiphp_native_scan_bridge(struct pci_dev *bridge)
/**
* enable_slot - enable, configure a slot
* @slot: slot to be enabled
+ * @bridge: true if enable is for the whole bridge (not a single slot)
*
* This function should be called per *physical slot*,
* not per each slot object in ACPI namespace.
*/
-static void enable_slot(struct acpiphp_slot *slot)
+static void enable_slot(struct acpiphp_slot *slot, bool bridge)
{
struct pci_dev *dev;
struct pci_bus *bus = slot->bus;
struct acpiphp_func *func;
- if (bus->self && hotplug_is_native(bus->self)) {
+ if (bridge && bus->self && hotplug_is_native(bus->self)) {
/*
* If native hotplug is used, it will take care of hotplug
* slot management and resource allocation for hotplug
@@ -701,7 +702,7 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
trim_stale_devices(dev);
/* configure all functions */
- enable_slot(slot);
+ enable_slot(slot, true);
} else {
disable_slot(slot);
}
@@ -785,7 +786,7 @@ static void hotplug_event(u32 type, struct acpiphp_context *context)
if (bridge)
acpiphp_check_bridge(bridge);
else if (!(slot->flags & SLOT_IS_GOING_AWAY))
- enable_slot(slot);
+ enable_slot(slot, false);
break;
@@ -973,7 +974,7 @@ int acpiphp_enable_slot(struct acpiphp_slot *slot)
/* configure all functions */
if (!(slot->flags & SLOT_ENABLED))
- enable_slot(slot);
+ enable_slot(slot, false);
pci_unlock_rescan_remove();
return 0;
diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c
index 8d48371caaa2..e7f45d96b0cb 100644
--- a/drivers/pinctrl/intel/pinctrl-cannonlake.c
+++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c
@@ -15,10 +15,11 @@
#include "pinctrl-intel.h"
-#define CNL_PAD_OWN 0x020
-#define CNL_PADCFGLOCK 0x080
-#define CNL_HOSTSW_OWN 0x0b0
-#define CNL_GPI_IE 0x120
+#define CNL_PAD_OWN 0x020
+#define CNL_PADCFGLOCK 0x080
+#define CNL_LP_HOSTSW_OWN 0x0b0
+#define CNL_H_HOSTSW_OWN 0x0c0
+#define CNL_GPI_IE 0x120
#define CNL_GPP(r, s, e, g) \
{ \
@@ -30,12 +31,12 @@
#define CNL_NO_GPIO -1
-#define CNL_COMMUNITY(b, s, e, g) \
+#define CNL_COMMUNITY(b, s, e, o, g) \
{ \
.barno = (b), \
.padown_offset = CNL_PAD_OWN, \
.padcfglock_offset = CNL_PADCFGLOCK, \
- .hostown_offset = CNL_HOSTSW_OWN, \
+ .hostown_offset = (o), \
.ie_offset = CNL_GPI_IE, \
.pin_base = (s), \
.npins = ((e) - (s) + 1), \
@@ -43,6 +44,12 @@
.ngpps = ARRAY_SIZE(g), \
}
+#define CNLLP_COMMUNITY(b, s, e, g) \
+ CNL_COMMUNITY(b, s, e, CNL_LP_HOSTSW_OWN, g)
+
+#define CNLH_COMMUNITY(b, s, e, g) \
+ CNL_COMMUNITY(b, s, e, CNL_H_HOSTSW_OWN, g)
+
/* Cannon Lake-H */
static const struct pinctrl_pin_desc cnlh_pins[] = {
/* GPP_A */
@@ -442,10 +449,10 @@ static const struct intel_function cnlh_functions[] = {
};
static const struct intel_community cnlh_communities[] = {
- CNL_COMMUNITY(0, 0, 50, cnlh_community0_gpps),
- CNL_COMMUNITY(1, 51, 154, cnlh_community1_gpps),
- CNL_COMMUNITY(2, 155, 248, cnlh_community3_gpps),
- CNL_COMMUNITY(3, 249, 298, cnlh_community4_gpps),
+ CNLH_COMMUNITY(0, 0, 50, cnlh_community0_gpps),
+ CNLH_COMMUNITY(1, 51, 154, cnlh_community1_gpps),
+ CNLH_COMMUNITY(2, 155, 248, cnlh_community3_gpps),
+ CNLH_COMMUNITY(3, 249, 298, cnlh_community4_gpps),
};
static const struct intel_pinctrl_soc_data cnlh_soc_data = {
@@ -803,9 +810,9 @@ static const struct intel_padgroup cnllp_community4_gpps[] = {
};
static const struct intel_community cnllp_communities[] = {
- CNL_COMMUNITY(0, 0, 67, cnllp_community0_gpps),
- CNL_COMMUNITY(1, 68, 180, cnllp_community1_gpps),
- CNL_COMMUNITY(2, 181, 243, cnllp_community4_gpps),
+ CNLLP_COMMUNITY(0, 0, 67, cnllp_community0_gpps),
+ CNLLP_COMMUNITY(1, 68, 180, cnllp_community1_gpps),
+ CNLLP_COMMUNITY(2, 181, 243, cnllp_community4_gpps),
};
static const struct intel_pinctrl_soc_data cnllp_soc_data = {
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index ec8dafc94694..1ea3438ea67e 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -887,36 +887,6 @@ static const struct gpio_chip intel_gpio_chip = {
.set_config = gpiochip_generic_config,
};
-static int intel_gpio_irq_reqres(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- int pin;
- int ret;
-
- pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
- if (pin >= 0) {
- ret = gpiochip_lock_as_irq(gc, pin);
- if (ret) {
- dev_err(pctrl->dev, "unable to lock HW IRQ %d for IRQ\n",
- pin);
- return ret;
- }
- }
- return 0;
-}
-
-static void intel_gpio_irq_relres(struct irq_data *d)
-{
- struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
- int pin;
-
- pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
- if (pin >= 0)
- gpiochip_unlock_as_irq(gc, pin);
-}
-
static void intel_gpio_irq_ack(struct irq_data *d)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
@@ -1132,8 +1102,6 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
static struct irq_chip intel_gpio_irqchip = {
.name = "intel-gpio",
- .irq_request_resources = intel_gpio_irq_reqres,
- .irq_release_resources = intel_gpio_irq_relres,
.irq_enable = intel_gpio_irq_enable,
.irq_ack = intel_gpio_irq_ack,
.irq_mask = intel_gpio_irq_mask,
diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
index 41ccc759b8b8..1425c2874d40 100644
--- a/drivers/pinctrl/pinctrl-amd.c
+++ b/drivers/pinctrl/pinctrl-amd.c
@@ -348,21 +348,12 @@ static void amd_gpio_irq_enable(struct irq_data *d)
unsigned long flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
- u32 mask = BIT(INTERRUPT_ENABLE_OFF) | BIT(INTERRUPT_MASK_OFF);
raw_spin_lock_irqsave(&gpio_dev->lock, flags);
pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
pin_reg |= BIT(INTERRUPT_ENABLE_OFF);
pin_reg |= BIT(INTERRUPT_MASK_OFF);
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
- /*
- * When debounce logic is enabled it takes ~900 us before interrupts
- * can be enabled. During this "debounce warm up" period the
- * "INTERRUPT_ENABLE" bit will read as 0. Poll the bit here until it
- * reads back as 1, signaling that interrupts are now enabled.
- */
- while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
- continue;
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
}
@@ -426,7 +417,7 @@ static void amd_gpio_irq_eoi(struct irq_data *d)
static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
int ret = 0;
- u32 pin_reg;
+ u32 pin_reg, pin_reg_irq_en, mask;
unsigned long flags, irq_flags;
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
@@ -495,6 +486,28 @@ static int amd_gpio_irq_set_type(struct irq_data *d, unsigned int type)
}
pin_reg |= CLR_INTR_STAT << INTERRUPT_STS_OFF;
+ /*
+ * If WAKE_INT_MASTER_REG.MaskStsEn is set, a software write to the
+ * debounce registers of any GPIO will block wake/interrupt status
+ * generation for *all* GPIOs for a lenght of time that depends on
+ * WAKE_INT_MASTER_REG.MaskStsLength[11:0]. During this period the
+ * INTERRUPT_ENABLE bit will read as 0.
+ *
+ * We temporarily enable irq for the GPIO whose configuration is
+ * changing, and then wait for it to read back as 1 to know when
+ * debounce has settled and then disable the irq again.
+ * We do this polling with the spinlock held to ensure other GPIO
+ * access routines do not read an incorrect value for the irq enable
+ * bit of other GPIOs. We keep the GPIO masked while polling to avoid
+ * spurious irqs, and disable the irq again after polling.
+ */
+ mask = BIT(INTERRUPT_ENABLE_OFF);
+ pin_reg_irq_en = pin_reg;
+ pin_reg_irq_en |= mask;
+ pin_reg_irq_en &= ~BIT(INTERRUPT_MASK_OFF);
+ writel(pin_reg_irq_en, gpio_dev->base + (d->hwirq)*4);
+ while ((readl(gpio_dev->base + (d->hwirq)*4) & mask) != mask)
+ continue;
writel(pin_reg, gpio_dev->base + (d->hwirq)*4);
raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
diff --git a/drivers/regulator/bd71837-regulator.c b/drivers/regulator/bd71837-regulator.c
index 0f8ac8dec3e1..a1bd8aaf4d98 100644
--- a/drivers/regulator/bd71837-regulator.c
+++ b/drivers/regulator/bd71837-regulator.c
@@ -569,6 +569,25 @@ static int bd71837_probe(struct platform_device *pdev)
BD71837_REG_REGLOCK);
}
+ /*
+ * There is a HW quirk in BD71837. The shutdown sequence timings for
+ * bucks/LDOs which are controlled via register interface are changed.
+ * At PMIC poweroff the voltage for BUCK6/7 is cut immediately at the
+ * beginning of shut-down sequence. As bucks 6 and 7 are parent
+ * supplies for LDO5 and LDO6 - this causes LDO5/6 voltage
+ * monitoring to errorneously detect under voltage and force PMIC to
+ * emergency state instead of poweroff. In order to avoid this we
+ * disable voltage monitoring for LDO5 and LDO6
+ */
+ err = regmap_update_bits(pmic->mfd->regmap, BD718XX_REG_MVRFLTMASK2,
+ BD718XX_LDO5_VRMON80 | BD718XX_LDO6_VRMON80,
+ BD718XX_LDO5_VRMON80 | BD718XX_LDO6_VRMON80);
+ if (err) {
+ dev_err(&pmic->pdev->dev,
+ "Failed to disable voltage monitoring\n");
+ goto err;
+ }
+
for (i = 0; i < ARRAY_SIZE(pmic_regulator_inits); i++) {
struct regulator_desc *desc;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index bb1324f93143..9577d8941846 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -3161,7 +3161,7 @@ static inline int regulator_suspend_toggle(struct regulator_dev *rdev,
if (!rstate->changeable)
return -EPERM;
- rstate->enabled = en;
+ rstate->enabled = (en) ? ENABLE_IN_SUSPEND : DISABLE_IN_SUSPEND;
return 0;
}
@@ -4395,13 +4395,13 @@ regulator_register(const struct regulator_desc *regulator_desc,
!rdev->desc->fixed_uV)
rdev->is_switch = true;
+ dev_set_drvdata(&rdev->dev, rdev);
ret = device_register(&rdev->dev);
if (ret != 0) {
put_device(&rdev->dev);
goto unset_supplies;
}
- dev_set_drvdata(&rdev->dev, rdev);
rdev_init_debugfs(rdev);
/* try to resolve regulators supply since a new one was registered */
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 638f17d4c848..210fc20f7de7 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -213,8 +213,6 @@ static void of_get_regulation_constraints(struct device_node *np,
else if (of_property_read_bool(suspend_np,
"regulator-off-in-suspend"))
suspend_state->enabled = DISABLE_IN_SUSPEND;
- else
- suspend_state->enabled = DO_NOTHING_IN_SUSPEND;
if (!of_property_read_u32(np, "regulator-suspend-min-microvolt",
&pval))
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index fac377320158..f42a619198c4 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -3474,11 +3474,10 @@ static int ibmvscsis_probe(struct vio_dev *vdev,
vscsi->dds.window[LOCAL].liobn,
vscsi->dds.window[REMOTE].liobn);
- strcpy(vscsi->eye, "VSCSI ");
- strncat(vscsi->eye, vdev->name, MAX_EYE);
+ snprintf(vscsi->eye, sizeof(vscsi->eye), "VSCSI %s", vdev->name);
vscsi->dds.unit_id = vdev->unit_address;
- strncpy(vscsi->dds.partition_name, partition_name,
+ strscpy(vscsi->dds.partition_name, partition_name,
sizeof(vscsi->dds.partition_name));
vscsi->dds.partition_num = partition_number;
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index f2ec80b0ffc0..271990bc065b 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -3335,6 +3335,65 @@ static void ipr_release_dump(struct kref *kref)
LEAVE;
}
+static void ipr_add_remove_thread(struct work_struct *work)
+{
+ unsigned long lock_flags;
+ struct ipr_resource_entry *res;
+ struct scsi_device *sdev;
+ struct ipr_ioa_cfg *ioa_cfg =
+ container_of(work, struct ipr_ioa_cfg, scsi_add_work_q);
+ u8 bus, target, lun;
+ int did_work;
+
+ ENTER;
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+
+restart:
+ do {
+ did_work = 0;
+ if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ return;
+ }
+
+ list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
+ if (res->del_from_ml && res->sdev) {
+ did_work = 1;
+ sdev = res->sdev;
+ if (!scsi_device_get(sdev)) {
+ if (!res->add_to_ml)
+ list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+ else
+ res->del_from_ml = 0;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ scsi_remove_device(sdev);
+ scsi_device_put(sdev);
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ }
+ break;
+ }
+ }
+ } while (did_work);
+
+ list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
+ if (res->add_to_ml) {
+ bus = res->bus;
+ target = res->target;
+ lun = res->lun;
+ res->add_to_ml = 0;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ scsi_add_device(ioa_cfg->host, bus, target, lun);
+ spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
+ goto restart;
+ }
+ }
+
+ ioa_cfg->scan_done = 1;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+ kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
+ LEAVE;
+}
+
/**
* ipr_worker_thread - Worker thread
* @work: ioa config struct
@@ -3349,13 +3408,9 @@ static void ipr_release_dump(struct kref *kref)
static void ipr_worker_thread(struct work_struct *work)
{
unsigned long lock_flags;
- struct ipr_resource_entry *res;
- struct scsi_device *sdev;
struct ipr_dump *dump;
struct ipr_ioa_cfg *ioa_cfg =
container_of(work, struct ipr_ioa_cfg, work_q);
- u8 bus, target, lun;
- int did_work;
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
@@ -3393,49 +3448,9 @@ static void ipr_worker_thread(struct work_struct *work)
return;
}
-restart:
- do {
- did_work = 0;
- if (!ioa_cfg->hrrq[IPR_INIT_HRRQ].allow_cmds) {
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- return;
- }
+ schedule_work(&ioa_cfg->scsi_add_work_q);
- list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
- if (res->del_from_ml && res->sdev) {
- did_work = 1;
- sdev = res->sdev;
- if (!scsi_device_get(sdev)) {
- if (!res->add_to_ml)
- list_move_tail(&res->queue, &ioa_cfg->free_res_q);
- else
- res->del_from_ml = 0;
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- scsi_remove_device(sdev);
- scsi_device_put(sdev);
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- }
- break;
- }
- }
- } while (did_work);
-
- list_for_each_entry(res, &ioa_cfg->used_res_q, queue) {
- if (res->add_to_ml) {
- bus = res->bus;
- target = res->target;
- lun = res->lun;
- res->add_to_ml = 0;
- spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- scsi_add_device(ioa_cfg->host, bus, target, lun);
- spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
- goto restart;
- }
- }
-
- ioa_cfg->scan_done = 1;
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
- kobject_uevent(&ioa_cfg->host->shost_dev.kobj, KOBJ_CHANGE);
LEAVE;
}
@@ -9933,6 +9948,7 @@ static void ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg,
INIT_LIST_HEAD(&ioa_cfg->free_res_q);
INIT_LIST_HEAD(&ioa_cfg->used_res_q);
INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread);
+ INIT_WORK(&ioa_cfg->scsi_add_work_q, ipr_add_remove_thread);
init_waitqueue_head(&ioa_cfg->reset_wait_q);
init_waitqueue_head(&ioa_cfg->msi_wait_q);
init_waitqueue_head(&ioa_cfg->eeh_wait_q);
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 68afbbde54d3..f6baa2351313 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1575,6 +1575,7 @@ struct ipr_ioa_cfg {
u8 saved_mode_page_len;
struct work_struct work_q;
+ struct work_struct scsi_add_work_q;
struct workqueue_struct *reset_work_q;
wait_queue_head_t reset_wait_q;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 057a60abe664..1a6ed9b0a249 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -360,12 +360,12 @@ lpfc_nvme_info_show(struct device *dev, struct device_attribute *attr,
goto buffer_done;
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
+ nrport = NULL;
+ spin_lock(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
- if (!rport)
- continue;
-
- /* local short-hand pointer. */
- nrport = rport->remoteport;
+ if (rport)
+ nrport = rport->remoteport;
+ spin_unlock(&vport->phba->hbalock);
if (!nrport)
continue;
@@ -3386,6 +3386,7 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
struct lpfc_nodelist *ndlp;
#if (IS_ENABLED(CONFIG_NVME_FC))
struct lpfc_nvme_rport *rport;
+ struct nvme_fc_remote_port *remoteport = NULL;
#endif
shost = lpfc_shost_from_vport(vport);
@@ -3396,8 +3397,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
if (ndlp->rport)
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
#if (IS_ENABLED(CONFIG_NVME_FC))
+ spin_lock(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
if (rport)
+ remoteport = rport->remoteport;
+ spin_unlock(&vport->phba->hbalock);
+ if (remoteport)
nvme_fc_set_remoteport_devloss(rport->remoteport,
vport->cfg_devloss_tmo);
#endif
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 9df0c051349f..aec5b10a8c85 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -551,7 +551,7 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
unsigned char *statep;
struct nvme_fc_local_port *localport;
struct lpfc_nvmet_tgtport *tgtp;
- struct nvme_fc_remote_port *nrport;
+ struct nvme_fc_remote_port *nrport = NULL;
struct lpfc_nvme_rport *rport;
cnt = (LPFC_NODELIST_SIZE / LPFC_NODELIST_ENTRY_SIZE);
@@ -696,11 +696,11 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char *buf, int size)
len += snprintf(buf + len, size - len, "\tRport List:\n");
list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) {
/* local short-hand pointer. */
+ spin_lock(&phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
- if (!rport)
- continue;
-
- nrport = rport->remoteport;
+ if (rport)
+ nrport = rport->remoteport;
+ spin_unlock(&phba->hbalock);
if (!nrport)
continue;
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 028462e5994d..918ae18ef8a8 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -2725,7 +2725,9 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
rpinfo.node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
+ spin_lock_irq(&vport->phba->hbalock);
oldrport = lpfc_ndlp_get_nrport(ndlp);
+ spin_unlock_irq(&vport->phba->hbalock);
if (!oldrport)
lpfc_nlp_get(ndlp);
@@ -2840,7 +2842,7 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
struct nvme_fc_local_port *localport;
struct lpfc_nvme_lport *lport;
struct lpfc_nvme_rport *rport;
- struct nvme_fc_remote_port *remoteport;
+ struct nvme_fc_remote_port *remoteport = NULL;
localport = vport->localport;
@@ -2854,11 +2856,14 @@ lpfc_nvme_unregister_port(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
if (!lport)
goto input_err;
+ spin_lock_irq(&vport->phba->hbalock);
rport = lpfc_ndlp_get_nrport(ndlp);
- if (!rport)
+ if (rport)
+ remoteport = rport->remoteport;
+ spin_unlock_irq(&vport->phba->hbalock);
+ if (!remoteport)
goto input_err;
- remoteport = rport->remoteport;
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
"6033 Unreg nvme remoteport %p, portname x%llx, "
"port_id x%06x, portstate x%x port type x%x\n",
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b79b366a94f7..4a57ffecc7e6 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1276,7 +1276,8 @@ static int sd_init_command(struct scsi_cmnd *cmd)
case REQ_OP_ZONE_RESET:
return sd_zbc_setup_reset_cmnd(cmd);
default:
- BUG();
+ WARN_ON_ONCE(1);
+ return BLKPREP_KILL;
}
}
@@ -2959,6 +2960,9 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
if (rot == 1) {
blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
+ } else {
+ blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+ blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
}
if (sdkp->device->type == TYPE_ZBC) {
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 9d5d2ca7fc4f..c55f38ec391c 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -7940,6 +7940,13 @@ int ufshcd_alloc_host(struct device *dev, struct ufs_hba **hba_handle)
err = -ENOMEM;
goto out_error;
}
+
+ /*
+ * Do not use blk-mq at this time because blk-mq does not support
+ * runtime pm.
+ */
+ host->use_blk_mq = false;
+
hba = shost_priv(host);
hba->host = host;
hba->dev = dev;
diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c
index 4b5e250e8615..e5c7e1ef6318 100644
--- a/drivers/soundwire/stream.c
+++ b/drivers/soundwire/stream.c
@@ -899,9 +899,10 @@ static void sdw_release_master_stream(struct sdw_stream_runtime *stream)
struct sdw_master_runtime *m_rt = stream->m_rt;
struct sdw_slave_runtime *s_rt, *_s_rt;
- list_for_each_entry_safe(s_rt, _s_rt,
- &m_rt->slave_rt_list, m_rt_node)
- sdw_stream_remove_slave(s_rt->slave, stream);
+ list_for_each_entry_safe(s_rt, _s_rt, &m_rt->slave_rt_list, m_rt_node) {
+ sdw_slave_port_release(s_rt->slave->bus, s_rt->slave, stream);
+ sdw_release_slave_stream(s_rt->slave, stream);
+ }
list_del(&m_rt->bus_node);
}
@@ -1112,7 +1113,7 @@ int sdw_stream_add_master(struct sdw_bus *bus,
"Master runtime config failed for stream:%s",
stream->name);
ret = -ENOMEM;
- goto error;
+ goto unlock;
}
ret = sdw_config_stream(bus->dev, stream, stream_config, false);
@@ -1123,11 +1124,11 @@ int sdw_stream_add_master(struct sdw_bus *bus,
if (ret)
goto stream_error;
- stream->state = SDW_STREAM_CONFIGURED;
+ goto unlock;
stream_error:
sdw_release_master_stream(stream);
-error:
+unlock:
mutex_unlock(&bus->bus_lock);
return ret;
}
@@ -1141,6 +1142,10 @@ EXPORT_SYMBOL(sdw_stream_add_master);
* @stream: SoundWire stream
* @port_config: Port configuration for audio stream
* @num_ports: Number of ports
+ *
+ * It is expected that Slave is added before adding Master
+ * to the Stream.
+ *
*/
int sdw_stream_add_slave(struct sdw_slave *slave,
struct sdw_stream_config *stream_config,
@@ -1186,6 +1191,12 @@ int sdw_stream_add_slave(struct sdw_slave *slave,
if (ret)
goto stream_error;
+ /*
+ * Change stream state to CONFIGURED on first Slave add.
+ * Bus is not aware of number of Slave(s) in a stream at this
+ * point so cannot depend on all Slave(s) to be added in order to
+ * change stream state to CONFIGURED.
+ */
stream->state = SDW_STREAM_CONFIGURED;
goto error;
diff --git a/drivers/spi/spi-gpio.c b/drivers/spi/spi-gpio.c
index 0626e6e3ea0c..421bfc7dda67 100644
--- a/drivers/spi/spi-gpio.c
+++ b/drivers/spi/spi-gpio.c
@@ -300,8 +300,8 @@ static int spi_gpio_request(struct device *dev,
*mflags |= SPI_MASTER_NO_RX;
spi_gpio->sck = devm_gpiod_get(dev, "sck", GPIOD_OUT_LOW);
- if (IS_ERR(spi_gpio->mosi))
- return PTR_ERR(spi_gpio->mosi);
+ if (IS_ERR(spi_gpio->sck))
+ return PTR_ERR(spi_gpio->sck);
for (i = 0; i < num_chipselects; i++) {
spi_gpio->cs_gpios[i] = devm_gpiod_get_index(dev, "cs",
diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c
index 95dc4d78618d..b37de1d991d6 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -598,11 +598,13 @@ static int rspi_dma_transfer(struct rspi_data *rspi, struct sg_table *tx,
ret = wait_event_interruptible_timeout(rspi->wait,
rspi->dma_callbacked, HZ);
- if (ret > 0 && rspi->dma_callbacked)
+ if (ret > 0 && rspi->dma_callbacked) {
ret = 0;
- else if (!ret) {
- dev_err(&rspi->master->dev, "DMA timeout\n");
- ret = -ETIMEDOUT;
+ } else {
+ if (!ret) {
+ dev_err(&rspi->master->dev, "DMA timeout\n");
+ ret = -ETIMEDOUT;
+ }
if (tx)
dmaengine_terminate_all(rspi->master->dma_tx);
if (rx)
@@ -1350,12 +1352,36 @@ static const struct platform_device_id spi_driver_ids[] = {
MODULE_DEVICE_TABLE(platform, spi_driver_ids);
+#ifdef CONFIG_PM_SLEEP
+static int rspi_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rspi_data *rspi = platform_get_drvdata(pdev);
+
+ return spi_master_suspend(rspi->master);
+}
+
+static int rspi_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct rspi_data *rspi = platform_get_drvdata(pdev);
+
+ return spi_master_resume(rspi->master);
+}
+
+static SIMPLE_DEV_PM_OPS(rspi_pm_ops, rspi_suspend, rspi_resume);
+#define DEV_PM_OPS &rspi_pm_ops
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
static struct platform_driver rspi_driver = {
.probe = rspi_probe,
.remove = rspi_remove,
.id_table = spi_driver_ids,
.driver = {
.name = "renesas_spi",
+ .pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(rspi_of_match),
},
};
diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c
index 539d6d1a277a..101cd6aae2ea 100644
--- a/drivers/spi/spi-sh-msiof.c
+++ b/drivers/spi/spi-sh-msiof.c
@@ -397,7 +397,8 @@ static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
static void sh_msiof_reset_str(struct sh_msiof_spi_priv *p)
{
- sh_msiof_write(p, STR, sh_msiof_read(p, STR));
+ sh_msiof_write(p, STR,
+ sh_msiof_read(p, STR) & ~(STR_TDREQ | STR_RDREQ));
}
static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
@@ -1426,12 +1427,37 @@ static const struct platform_device_id spi_driver_ids[] = {
};
MODULE_DEVICE_TABLE(platform, spi_driver_ids);
+#ifdef CONFIG_PM_SLEEP
+static int sh_msiof_spi_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
+
+ return spi_master_suspend(p->master);
+}
+
+static int sh_msiof_spi_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev);
+
+ return spi_master_resume(p->master);
+}
+
+static SIMPLE_DEV_PM_OPS(sh_msiof_spi_pm_ops, sh_msiof_spi_suspend,
+ sh_msiof_spi_resume);
+#define DEV_PM_OPS &sh_msiof_spi_pm_ops
+#else
+#define DEV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
static struct platform_driver sh_msiof_spi_drv = {
.probe = sh_msiof_spi_probe,
.remove = sh_msiof_spi_remove,
.id_table = spi_driver_ids,
.driver = {
.name = "spi_sh_msiof",
+ .pm = DEV_PM_OPS,
.of_match_table = of_match_ptr(sh_msiof_match),
},
};
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index 6f7b946b5ced..1427f343b39a 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -1063,6 +1063,24 @@ static int tegra_slink_probe(struct platform_device *pdev)
goto exit_free_master;
}
+ /* disabled clock may cause interrupt storm upon request */
+ tspi->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(tspi->clk)) {
+ ret = PTR_ERR(tspi->clk);
+ dev_err(&pdev->dev, "Can not get clock %d\n", ret);
+ goto exit_free_master;
+ }
+ ret = clk_prepare(tspi->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Clock prepare failed %d\n", ret);
+ goto exit_free_master;
+ }
+ ret = clk_enable(tspi->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Clock enable failed %d\n", ret);
+ goto exit_free_master;
+ }
+
spi_irq = platform_get_irq(pdev, 0);
tspi->irq = spi_irq;
ret = request_threaded_irq(tspi->irq, tegra_slink_isr,
@@ -1071,14 +1089,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n",
tspi->irq);
- goto exit_free_master;
- }
-
- tspi->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(tspi->clk)) {
- dev_err(&pdev->dev, "can not get clock\n");
- ret = PTR_ERR(tspi->clk);
- goto exit_free_irq;
+ goto exit_clk_disable;
}
tspi->rst = devm_reset_control_get_exclusive(&pdev->dev, "spi");
@@ -1138,6 +1149,8 @@ exit_rx_dma_free:
tegra_slink_deinit_dma_param(tspi, true);
exit_free_irq:
free_irq(spi_irq, tspi);
+exit_clk_disable:
+ clk_disable(tspi->clk);
exit_free_master:
spi_master_put(master);
return ret;
@@ -1150,6 +1163,8 @@ static int tegra_slink_remove(struct platform_device *pdev)
free_irq(tspi->irq, tspi);
+ clk_disable(tspi->clk);
+
if (tspi->tx_dma_chan)
tegra_slink_deinit_dma_param(tspi, false);
diff --git a/drivers/staging/media/mt9t031/Kconfig b/drivers/staging/media/mt9t031/Kconfig
index f48e06a03cdb..9a58aaf72edd 100644
--- a/drivers/staging/media/mt9t031/Kconfig
+++ b/drivers/staging/media/mt9t031/Kconfig
@@ -1,9 +1,3 @@
-config SOC_CAMERA_IMX074
- tristate "imx074 support (DEPRECATED)"
- depends on SOC_CAMERA && I2C
- help
- This driver supports IMX074 cameras from Sony
-
config SOC_CAMERA_MT9T031
tristate "mt9t031 support (DEPRECATED)"
depends on SOC_CAMERA && I2C
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c
index 9518ffd8b8ba..4e680d753941 100644
--- a/drivers/target/iscsi/iscsi_target_auth.c
+++ b/drivers/target/iscsi/iscsi_target_auth.c
@@ -26,27 +26,6 @@
#include "iscsi_target_nego.h"
#include "iscsi_target_auth.h"
-static int chap_string_to_hex(unsigned char *dst, unsigned char *src, int len)
-{
- int j = DIV_ROUND_UP(len, 2), rc;
-
- rc = hex2bin(dst, src, j);
- if (rc < 0)
- pr_debug("CHAP string contains non hex digit symbols\n");
-
- dst[j] = '\0';
- return j;
-}
-
-static void chap_binaryhex_to_asciihex(char *dst, char *src, int src_len)
-{
- int i;
-
- for (i = 0; i < src_len; i++) {
- sprintf(&dst[i*2], "%02x", (int) src[i] & 0xff);
- }
-}
-
static int chap_gen_challenge(
struct iscsi_conn *conn,
int caller,
@@ -62,7 +41,7 @@ static int chap_gen_challenge(
ret = get_random_bytes_wait(chap->challenge, CHAP_CHALLENGE_LENGTH);
if (unlikely(ret))
return ret;
- chap_binaryhex_to_asciihex(challenge_asciihex, chap->challenge,
+ bin2hex(challenge_asciihex, chap->challenge,
CHAP_CHALLENGE_LENGTH);
/*
* Set CHAP_C, and copy the generated challenge into c_str.
@@ -248,9 +227,16 @@ static int chap_server_compute_md5(
pr_err("Could not find CHAP_R.\n");
goto out;
}
+ if (strlen(chap_r) != MD5_SIGNATURE_SIZE * 2) {
+ pr_err("Malformed CHAP_R\n");
+ goto out;
+ }
+ if (hex2bin(client_digest, chap_r, MD5_SIGNATURE_SIZE) < 0) {
+ pr_err("Malformed CHAP_R\n");
+ goto out;
+ }
pr_debug("[server] Got CHAP_R=%s\n", chap_r);
- chap_string_to_hex(client_digest, chap_r, strlen(chap_r));
tfm = crypto_alloc_shash("md5", 0, 0);
if (IS_ERR(tfm)) {
@@ -294,7 +280,7 @@ static int chap_server_compute_md5(
goto out;
}
- chap_binaryhex_to_asciihex(response, server_digest, MD5_SIGNATURE_SIZE);
+ bin2hex(response, server_digest, MD5_SIGNATURE_SIZE);
pr_debug("[server] MD5 Server Digest: %s\n", response);
if (memcmp(server_digest, client_digest, MD5_SIGNATURE_SIZE) != 0) {
@@ -349,9 +335,7 @@ static int chap_server_compute_md5(
pr_err("Could not find CHAP_C.\n");
goto out;
}
- pr_debug("[server] Got CHAP_C=%s\n", challenge);
- challenge_len = chap_string_to_hex(challenge_binhex, challenge,
- strlen(challenge));
+ challenge_len = DIV_ROUND_UP(strlen(challenge), 2);
if (!challenge_len) {
pr_err("Unable to convert incoming challenge\n");
goto out;
@@ -360,6 +344,11 @@ static int chap_server_compute_md5(
pr_err("CHAP_C exceeds maximum binary size of 1024 bytes\n");
goto out;
}
+ if (hex2bin(challenge_binhex, challenge, challenge_len) < 0) {
+ pr_err("Malformed CHAP_C\n");
+ goto out;
+ }
+ pr_debug("[server] Got CHAP_C=%s\n", challenge);
/*
* During mutual authentication, the CHAP_C generated by the
* initiator must not match the original CHAP_C generated by
@@ -413,7 +402,7 @@ static int chap_server_compute_md5(
/*
* Convert response from binary hex to ascii hext.
*/
- chap_binaryhex_to_asciihex(response, digest, MD5_SIGNATURE_SIZE);
+ bin2hex(response, digest, MD5_SIGNATURE_SIZE);
*nr_out_len += sprintf(nr_out_ptr + *nr_out_len, "CHAP_R=0x%s",
response);
*nr_out_len += 1;
diff --git a/drivers/tty/serial/cpm_uart/cpm_uart_core.c b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
index 24a5f05e769b..e5389591bb4f 100644
--- a/drivers/tty/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/tty/serial/cpm_uart/cpm_uart_core.c
@@ -1054,8 +1054,8 @@ static int poll_wait_key(char *obuf, struct uart_cpm_port *pinfo)
/* Get the address of the host memory buffer.
*/
bdp = pinfo->rx_cur;
- while (bdp->cbd_sc & BD_SC_EMPTY)
- ;
+ if (bdp->cbd_sc & BD_SC_EMPTY)
+ return NO_POLL_CHAR;
/* If the buffer address is in the CPM DPRAM, don't
* convert it.
@@ -1090,7 +1090,11 @@ static int cpm_get_poll_char(struct uart_port *port)
poll_chars = 0;
}
if (poll_chars <= 0) {
- poll_chars = poll_wait_key(poll_buf, pinfo);
+ int ret = poll_wait_key(poll_buf, pinfo);
+
+ if (ret == NO_POLL_CHAR)
+ return ret;
+ poll_chars = ret;
pollp = poll_buf;
}
poll_chars--;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 51e47a63d61a..3f8d1274fc85 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -979,7 +979,8 @@ static inline int lpuart_start_rx_dma(struct lpuart_port *sport)
struct circ_buf *ring = &sport->rx_ring;
int ret, nent;
int bits, baud;
- struct tty_struct *tty = tty_port_tty_get(&sport->port.state->port);
+ struct tty_port *port = &sport->port.state->port;
+ struct tty_struct *tty = port->tty;
struct ktermios *termios = &tty->termios;
baud = tty_get_baud_rate(tty);
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 239c0fa2e981..0f67197a3783 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -2351,6 +2351,14 @@ static int imx_uart_probe(struct platform_device *pdev)
ret);
return ret;
}
+
+ ret = devm_request_irq(&pdev->dev, rtsirq, imx_uart_rtsint, 0,
+ dev_name(&pdev->dev), sport);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request rts irq: %d\n",
+ ret);
+ return ret;
+ }
} else {
ret = devm_request_irq(&pdev->dev, rxirq, imx_uart_int, 0,
dev_name(&pdev->dev), sport);
diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c
index d04b5eeea3c6..170e446a2f62 100644
--- a/drivers/tty/serial/mvebu-uart.c
+++ b/drivers/tty/serial/mvebu-uart.c
@@ -511,6 +511,7 @@ static void mvebu_uart_set_termios(struct uart_port *port,
termios->c_iflag |= old->c_iflag & ~(INPCK | IGNPAR);
termios->c_cflag &= CREAD | CBAUD;
termios->c_cflag |= old->c_cflag & ~(CREAD | CBAUD);
+ termios->c_cflag |= CS8;
}
spin_unlock_irqrestore(&port->lock, flags);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 32bc3e3fe4d3..5e5da9acaf0a 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1255,6 +1255,7 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *
static int tty_reopen(struct tty_struct *tty)
{
struct tty_driver *driver = tty->driver;
+ int retval;
if (driver->type == TTY_DRIVER_TYPE_PTY &&
driver->subtype == PTY_TYPE_MASTER)
@@ -1268,10 +1269,14 @@ static int tty_reopen(struct tty_struct *tty)
tty->count++;
- if (!tty->ldisc)
- return tty_ldisc_reinit(tty, tty->termios.c_line);
+ if (tty->ldisc)
+ return 0;
- return 0;
+ retval = tty_ldisc_reinit(tty, tty->termios.c_line);
+ if (retval)
+ tty->count--;
+
+ return retval;
}
/**
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index a78ad10a119b..73cdc0d633dd 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -32,6 +32,8 @@
#include <asm/io.h>
#include <linux/uaccess.h>
+#include <linux/nospec.h>
+
#include <linux/kbd_kern.h>
#include <linux/vt_kern.h>
#include <linux/kbd_diacr.h>
@@ -700,6 +702,8 @@ int vt_ioctl(struct tty_struct *tty,
if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
ret = -ENXIO;
else {
+ vsa.console = array_index_nospec(vsa.console,
+ MAX_NR_CONSOLES + 1);
vsa.console--;
console_lock();
ret = vc_allocate(vsa.console);
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 656d247819c9..bec581fb7c63 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -460,7 +460,7 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
set_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
- rv = usb_submit_urb(desc->response, GFP_ATOMIC);
+ rv = usb_submit_urb(desc->response, GFP_KERNEL);
spin_lock_irq(&desc->iuspin);
if (rv) {
dev_err(&desc->intf->dev,
diff --git a/drivers/usb/common/roles.c b/drivers/usb/common/roles.c
index 15cc76e22123..99116af07f1d 100644
--- a/drivers/usb/common/roles.c
+++ b/drivers/usb/common/roles.c
@@ -109,8 +109,15 @@ static void *usb_role_switch_match(struct device_connection *con, int ep,
*/
struct usb_role_switch *usb_role_switch_get(struct device *dev)
{
- return device_connection_find_match(dev, "usb-role-switch", NULL,
- usb_role_switch_match);
+ struct usb_role_switch *sw;
+
+ sw = device_connection_find_match(dev, "usb-role-switch", NULL,
+ usb_role_switch_match);
+
+ if (!IS_ERR_OR_NULL(sw))
+ WARN_ON(!try_module_get(sw->dev.parent->driver->owner));
+
+ return sw;
}
EXPORT_SYMBOL_GPL(usb_role_switch_get);
@@ -122,8 +129,10 @@ EXPORT_SYMBOL_GPL(usb_role_switch_get);
*/
void usb_role_switch_put(struct usb_role_switch *sw)
{
- if (!IS_ERR_OR_NULL(sw))
+ if (!IS_ERR_OR_NULL(sw)) {
put_device(&sw->dev);
+ module_put(sw->dev.parent->driver->owner);
+ }
}
EXPORT_SYMBOL_GPL(usb_role_switch_put);
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 6ce77b33da61..244417d0dfd1 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -1434,10 +1434,13 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
struct async *as = NULL;
struct usb_ctrlrequest *dr = NULL;
unsigned int u, totlen, isofrmlen;
- int i, ret, is_in, num_sgs = 0, ifnum = -1;
+ int i, ret, num_sgs = 0, ifnum = -1;
int number_of_packets = 0;
unsigned int stream_id = 0;
void *buf;
+ bool is_in;
+ bool allow_short = false;
+ bool allow_zero = false;
unsigned long mask = USBDEVFS_URB_SHORT_NOT_OK |
USBDEVFS_URB_BULK_CONTINUATION |
USBDEVFS_URB_NO_FSBR |
@@ -1471,6 +1474,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
u = 0;
switch (uurb->type) {
case USBDEVFS_URB_TYPE_CONTROL:
+ if (is_in)
+ allow_short = true;
if (!usb_endpoint_xfer_control(&ep->desc))
return -EINVAL;
/* min 8 byte setup packet */
@@ -1511,6 +1516,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
break;
case USBDEVFS_URB_TYPE_BULK:
+ if (!is_in)
+ allow_zero = true;
+ else
+ allow_short = true;
switch (usb_endpoint_type(&ep->desc)) {
case USB_ENDPOINT_XFER_CONTROL:
case USB_ENDPOINT_XFER_ISOC:
@@ -1531,6 +1540,10 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
if (!usb_endpoint_xfer_int(&ep->desc))
return -EINVAL;
interrupt_urb:
+ if (!is_in)
+ allow_zero = true;
+ else
+ allow_short = true;
break;
case USBDEVFS_URB_TYPE_ISO:
@@ -1676,14 +1689,19 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
u = (is_in ? URB_DIR_IN : URB_DIR_OUT);
if (uurb->flags & USBDEVFS_URB_ISO_ASAP)
u |= URB_ISO_ASAP;
- if (uurb->flags & USBDEVFS_URB_SHORT_NOT_OK && is_in)
+ if (allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
u |= URB_SHORT_NOT_OK;
- if (uurb->flags & USBDEVFS_URB_ZERO_PACKET)
+ if (allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET)
u |= URB_ZERO_PACKET;
if (uurb->flags & USBDEVFS_URB_NO_INTERRUPT)
u |= URB_NO_INTERRUPT;
as->urb->transfer_flags = u;
+ if (!allow_short && uurb->flags & USBDEVFS_URB_SHORT_NOT_OK)
+ dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_SHORT_NOT_OK.\n");
+ if (!allow_zero && uurb->flags & USBDEVFS_URB_ZERO_PACKET)
+ dev_warn(&ps->dev->dev, "Requested nonsensical USBDEVFS_URB_ZERO_PACKET.\n");
+
as->urb->transfer_buffer_length = uurb->buffer_length;
as->urb->setup_packet = (unsigned char *)dr;
dr = NULL;
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index e76e95f62f76..a1f225f077cd 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -512,7 +512,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
struct device *dev;
struct usb_device *udev;
int retval = 0;
- int lpm_disable_error = -ENODEV;
if (!iface)
return -ENODEV;
@@ -533,16 +532,6 @@ int usb_driver_claim_interface(struct usb_driver *driver,
iface->condition = USB_INTERFACE_BOUND;
- /* See the comment about disabling LPM in usb_probe_interface(). */
- if (driver->disable_hub_initiated_lpm) {
- lpm_disable_error = usb_unlocked_disable_lpm(udev);
- if (lpm_disable_error) {
- dev_err(&iface->dev, "%s Failed to disable LPM for driver %s\n",
- __func__, driver->name);
- return -ENOMEM;
- }
- }
-
/* Claimed interfaces are initially inactive (suspended) and
* runtime-PM-enabled, but only if the driver has autosuspend
* support. Otherwise they are marked active, to prevent the
@@ -561,9 +550,20 @@ int usb_driver_claim_interface(struct usb_driver *driver,
if (device_is_registered(dev))
retval = device_bind_driver(dev);
- /* Attempt to re-enable USB3 LPM, if the disable was successful. */
- if (!lpm_disable_error)
- usb_unlocked_enable_lpm(udev);
+ if (retval) {
+ dev->driver = NULL;
+ usb_set_intfdata(iface, NULL);
+ iface->needs_remote_wakeup = 0;
+ iface->condition = USB_INTERFACE_UNBOUND;
+
+ /*
+ * Unbound interfaces are always runtime-PM-disabled
+ * and runtime-PM-suspended
+ */
+ if (driver->supports_autosuspend)
+ pm_runtime_disable(dev);
+ pm_runtime_set_suspended(dev);
+ }
return retval;
}
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index e77dfe5ed5ec..178d6c6063c0 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -58,6 +58,7 @@ static int quirks_param_set(const char *val, const struct kernel_param *kp)
quirk_list = kcalloc(quirk_count, sizeof(struct quirk_entry),
GFP_KERNEL);
if (!quirk_list) {
+ quirk_count = 0;
mutex_unlock(&quirk_mutex);
return -ENOMEM;
}
@@ -154,7 +155,7 @@ static struct kparam_string quirks_param_string = {
.string = quirks_param,
};
-module_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
+device_param_cb(quirks, &quirks_param_ops, &quirks_param_string, 0644);
MODULE_PARM_DESC(quirks, "Add/modify USB quirks by specifying quirks=vendorID:productID:quirks");
/* Lists of quirky USB devices, split in device quirks and interface quirks.
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 623be3174fb3..79d8bd7a612e 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -228,6 +228,8 @@ struct usb_host_interface *usb_find_alt_setting(
struct usb_interface_cache *intf_cache = NULL;
int i;
+ if (!config)
+ return NULL;
for (i = 0; i < config->desc.bNumInterfaces; i++) {
if (config->intf_cache[i]->altsetting[0].desc.bInterfaceNumber
== iface_num) {
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index df827ff57b0d..23a0df79ef21 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -658,16 +658,6 @@ dsps_dma_controller_create(struct musb *musb, void __iomem *base)
return controller;
}
-static void dsps_dma_controller_destroy(struct dma_controller *c)
-{
- struct musb *musb = c->musb;
- struct dsps_glue *glue = dev_get_drvdata(musb->controller->parent);
- void __iomem *usbss_base = glue->usbss_base;
-
- musb_writel(usbss_base, USBSS_IRQ_CLEARR, USBSS_IRQ_PD_COMP);
- cppi41_dma_controller_destroy(c);
-}
-
#ifdef CONFIG_PM_SLEEP
static void dsps_dma_controller_suspend(struct dsps_glue *glue)
{
@@ -697,7 +687,7 @@ static struct musb_platform_ops dsps_ops = {
#ifdef CONFIG_USB_TI_CPPI41_DMA
.dma_init = dsps_dma_controller_create,
- .dma_exit = dsps_dma_controller_destroy,
+ .dma_exit = cppi41_dma_controller_destroy,
#endif
.enable = dsps_musb_enable,
.disable = dsps_musb_disable,
diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index ddaac63ecf12..d990aa510fab 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -9,6 +9,7 @@
#include <linux/device.h>
#include <linux/list.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/usb/typec_mux.h>
@@ -49,8 +50,10 @@ struct typec_switch *typec_switch_get(struct device *dev)
mutex_lock(&switch_lock);
sw = device_connection_find_match(dev, "typec-switch", NULL,
typec_switch_match);
- if (!IS_ERR_OR_NULL(sw))
+ if (!IS_ERR_OR_NULL(sw)) {
+ WARN_ON(!try_module_get(sw->dev->driver->owner));
get_device(sw->dev);
+ }
mutex_unlock(&switch_lock);
return sw;
@@ -65,8 +68,10 @@ EXPORT_SYMBOL_GPL(typec_switch_get);
*/
void typec_switch_put(struct typec_switch *sw)
{
- if (!IS_ERR_OR_NULL(sw))
+ if (!IS_ERR_OR_NULL(sw)) {
+ module_put(sw->dev->driver->owner);
put_device(sw->dev);
+ }
}
EXPORT_SYMBOL_GPL(typec_switch_put);
@@ -136,8 +141,10 @@ struct typec_mux *typec_mux_get(struct device *dev, const char *name)
mutex_lock(&mux_lock);
mux = device_connection_find_match(dev, name, NULL, typec_mux_match);
- if (!IS_ERR_OR_NULL(mux))
+ if (!IS_ERR_OR_NULL(mux)) {
+ WARN_ON(!try_module_get(mux->dev->driver->owner));
get_device(mux->dev);
+ }
mutex_unlock(&mux_lock);
return mux;
@@ -152,8 +159,10 @@ EXPORT_SYMBOL_GPL(typec_mux_get);
*/
void typec_mux_put(struct typec_mux *mux)
{
- if (!IS_ERR_OR_NULL(mux))
+ if (!IS_ERR_OR_NULL(mux)) {
+ module_put(mux->dev->driver->owner);
put_device(mux->dev);
+ }
}
EXPORT_SYMBOL_GPL(typec_mux_put);