[BUG 5.15-rc3] kernel BUG at drivers/gpu/drm/i915/i915_sw_fence.c:245!
When I tried to test patches applied to v5.15-rc3, I hit this bug (and hence can not test my code), on 32 bit x86. [ cut here ] kernel BUG at drivers/gpu/drm/i915/i915_sw_fence.c:245! invalid opcode: [#1] SMP PTI CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.14.0-rc1-test+ #456 Hardware name: MSI MS-7823/CSM-H87M-G43 (MS-7823), BIOS V1.6 02/22/2014 EIP: __i915_sw_fence_init+0x15/0x38 Code: 2b 3d 58 98 88 c1 74 05 e8 60 d9 58 00 8d 65 f4 5b 5e 5f 5d c3 3e 8d 74 26 00 55 89 e5 56 89 d6 53 85 d2 74 05 f6 c2 03 74 02 <0f> 0b 89 ca 8b 4d 08 89 c3 e8 48 94 ab ff 89 73 34 c7 43 38 01 00 EAX: c2508260 EBX: c2508000 ECX: c143de1e EDX: c09dfadd ESI: c09dfadd EDI: c45e7200 EBP: c26c9c68 ESP: c26c9c60 DS: 007b ES: 007b FS: 00d8 GS: SS: 0068 EFLAGS: 00010202 CR0: 80050033 CR2: CR3: 019e2000 CR4: 001506f0 Call Trace: intel_context_init+0x112/0x145 intel_context_create+0x29/0x37 intel_ring_submission_setup+0x3cb/0x5a8 ? kfree+0x135/0x1c6 ? wa_init_finish+0x32/0x59 ? wa_init_finish+0x4f/0x59 ? intel_engine_init_ctx_wa+0x39a/0x3b3 intel_engines_init+0x2dd/0x4d0 ? gen6_bsd_submit_request+0x97/0x97 intel_gt_init+0x122/0x20d i915_gem_init+0x80/0xef i915_driver_probe+0x880/0xa90 ? i915_pci_remove+0x27/0x27 i915_pci_probe+0xdd/0xf6 ? __pm_runtime_resume+0x63/0x6b ? i915_pci_remove+0x27/0x27 pci_device_probe+0xbc/0x11e really_probe+0x13e/0x328 __driver_probe_device+0x140/0x176 driver_probe_device+0x1f/0x71 __driver_attach+0xf6/0x109 ? __device_attach_driver+0xbd/0xbd bus_for_each_dev+0x5b/0x88 driver_attach+0x19/0x1b ? __device_attach_driver+0xbd/0xbd bus_add_driver+0xf2/0x199 driver_register+0x8c/0xbe __pci_register_driver+0x5b/0x60 i915_register_pci_driver+0x19/0x1b i915_init+0x15/0x67 ? radeon_module_init+0x6a/0x6a do_one_initcall+0xce/0x21c ? rcu_read_lock_sched_held+0x35/0x6d ? trace_initcall_level+0x5f/0x99 kernel_init_freeable+0x1fb/0x247 ? rest_init+0x129/0x129 kernel_init+0x17/0xfd ret_from_fork+0x1c/0x28 Modules linked in: ---[ end trace 791dc89810d853da ]--- EIP: __i915_sw_fence_init+0x15/0x38 Code: 2b 3d 58 98 88 c1 74 05 e8 60 d9 58 00 8d 65 f4 5b 5e 5f 5d c3 3e 8d 74 26 00 55 89 e5 56 89 d6 53 85 d2 74 05 f6 c2 03 74 02 <0f> 0b 89 ca 8b 4d 08 89 c3 e8 48 94 ab ff 89 73 34 c7 43 38 01 00 EAX: c2508260 EBX: c2508000 ECX: c143de1e EDX: c09dfadd ESI: c09dfadd EDI: c45e7200 EBP: c26c9c68 ESP: c26c9c60 DS: 007b ES: 007b FS: 00d8 GS: SS: 0068 EFLAGS: 00010202 CR0: 80050033 CR2: CR3: 019e2000 CR4: 001506f0 Kernel panic - not syncing: Attempted to kill init! exitcode=0x000b Kernel Offset: disabled ---[ end Kernel panic - not syncing: Attempted to kill init! exitcode=0x000b ]--- Attached is the dmesg and the config. I bisected it down to this commit: 3ffe82d701a4 ("drm/i915/xehp: handle new steering options") -- Steve mitest-config.gz Description: application/gzip mitest-dmesg.gz Description: application/gzip
Re: [PATCH] drm/i915: remove IS_ACTIVE
Hi Lucas, Thank you for the patch! Yet something to improve: [auto build test ERROR on drm-intel/for-linux-next] [also build test ERROR on drm-tip/drm-tip drm-exynos/exynos-drm-next tegra-drm/drm/tegra/for-next v5.15-rc3 next-20210823] [cannot apply to airlied/drm-next] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Lucas-De-Marchi/drm-i915-remove-IS_ACTIVE/20211001-154226 base: git://anongit.freedesktop.org/drm-intel for-linux-next config: i386-randconfig-r024-20211001 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project 962e503cc8bc411f7523cc393acae8aae425b1c4) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/0day-ci/linux/commit/50006042f1d264599bd1be1942f9958112e15c01 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Lucas-De-Marchi/drm-i915-remove-IS_ACTIVE/20211001-154226 git checkout 50006042f1d264599bd1be1942f9958112e15c01 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=i386 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): >> drivers/gpu/drm/i915/i915_config.c:11:14: error: use of logical '&&' with >> constant operand [-Werror,-Wconstant-logical-operand] if (context && CONFIG_DRM_I915_FENCE_TIMEOUT) ^ ~ drivers/gpu/drm/i915/i915_config.c:11:14: note: use '&' for a bitwise operation if (context && CONFIG_DRM_I915_FENCE_TIMEOUT) ^~ & drivers/gpu/drm/i915/i915_config.c:11:14: note: remove constant to silence this warning if (context && CONFIG_DRM_I915_FENCE_TIMEOUT) ~^~~~ 1 error generated. vim +11 drivers/gpu/drm/i915/i915_config.c 7 8 unsigned long 9 i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context) 10 { > 11 if (context && CONFIG_DRM_I915_FENCE_TIMEOUT) --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [Intel-gfx] [PATCH v2 00/17] drm: cleanup: Use DRM_MODESET_LOCK_ALL_* helpers where possible
On Sat, Oct 02, 2021 at 01:05:47AM +0300, Ville Syrjälä wrote: > On Fri, Oct 01, 2021 at 04:48:15PM -0400, Sean Paul wrote: > > On Fri, Oct 01, 2021 at 10:00:50PM +0300, Ville Syrjälä wrote: > > > On Fri, Oct 01, 2021 at 02:36:55PM -0400, Sean Paul wrote: > > > > On Fri, Sep 24, 2021 at 08:43:07AM +0200, Fernando Ramos wrote: > > > > > Hi all, > > > > > > > > > > One of the things in the DRM TODO list ("Documentation/gpu/todo.rst") > > > > > was to > > > > > "use DRM_MODESET_LOCAL_ALL_* helpers instead of boilerplate". That's > > > > > what this > > > > > patch series is about. > > > > > > > > > > You will find two types of changes here: > > > > > > > > > > - Replacing "drm_modeset_lock_all_ctx()" (and surrounding > > > > > boilerplate) with > > > > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" in the remaining places (as > > > > > it has > > > > > already been done in previous commits such as b7ea04d2) > > > > > > > > > > - Replacing "drm_modeset_lock_all()" with > > > > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" > > > > > in the remaining places (as it has already been done in previous > > > > > commits > > > > > such as 57037094) > > > > > > > > > > Most of the changes are straight forward, except for a few cases in > > > > > the "amd" > > > > > and "i915" drivers where some extra dancing was needed to overcome the > > > > > limitation that the DRM_MODESET_LOCK_ALL_BEGIN()/END() macros can > > > > > only be used > > > > > once inside the same function (the reason being that the macro > > > > > expansion > > > > > includes *labels*, and you can not have two labels named the same > > > > > inside one > > > > > function) > > > > > > > > > > Notice that, even after this patch series, some places remain where > > > > > "drm_modeset_lock_all()" and "drm_modeset_lock_all_ctx()" are still > > > > > present, > > > > > all inside drm core (which makes sense), except for two (in "amd" and > > > > > "i915") > > > > > which cannot be replaced due to the way they are being used. > > > > > > > > > > Changes in v2: > > > > > > > > > > - Fix commit message typo > > > > > - Use the value returned by DRM_MODESET_LOCK_ALL_END when possible > > > > > - Split drm/i915 patch into two simpler ones > > > > > - Remove drm_modeset_(un)lock_all() > > > > > - Fix build problems in non-x86 platforms > > > > > > > > > > Fernando Ramos (17): > > > > > drm: cleanup: drm_modeset_lock_all_ctx() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/i915: cleanup: drm_modeset_lock_all_ctx() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/msm: cleanup: drm_modeset_lock_all_ctx() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() drm/vmwgfx: cleanup: > > > > > drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/tegra: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/shmobile: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/radeon: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/omapdrm: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/nouveau: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/msm: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/i915: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/i915: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() part 2 > > > > > drm/gma500: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm/amd: cleanup: drm_modeset_lock_all() --> > > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > > drm: cleanup: remove drm_modeset_(un)lock_all() > > > > > doc: drm: remove TODO entry regarding DRM_MODSET_LOCK_ALL cleanup > > > > > > > > > > > > > Thank you for revising, Fernando! I've pushed the set to drm-misc-next > > > > (along > > > > with the necessary drm-tip conflict resolutions). > > > > > > Ugh. Did anyone actually review the locking changes this does? > > > I shot the previous i915 stuff down because the commit messages > > > did not address any of it. > > > > I reviewed the set on 9/17, I didn't see your feedback on that thread. > > It was much earlir than that. > https://lists.freedesktop.org/archives/dri-devel/2021-June/313193.html > > And I think I might have also shot down a similar thing earlier. > > I was actually half considering sending a patch to nuke that > misleading TODO item. I don't think anything which changes > which locks are taken should be considred a starter level task. > And the commit messages here don't seem to address any of it. And i915 is now broken :( https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_10680/fi-bwr-2160/boot.html -- Ville
Re: [Freedreno] [PATCH v3] drm/msm/dsi: do not enable irq handler before powering up the host
On 2021-10-01 18:08, Dmitry Baryshkov wrote: The DSI host might be left in some state by the bootloader. If this state generates an IRQ, it might hang the system by holding the interrupt line before the driver sets up the DSI host to the known state. Move the request_irq into msm_dsi_host_init and pass IRQF_NO_AUTOEN to it. Call enable/disable_irq after msm_dsi_host_power_on/_off() functions, so that we can be sure that the interrupt is delivered when the host is in the known state. It is not possible to defer the interrupt enablement to a later point, because drm_panel_prepare might need to communicate with the panel over the DSI link and that requires working interrupt. Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Signed-off-by: Dmitry Baryshkov Reviewed-by: Abhinav Kumar --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_host.c| 48 +-- drivers/gpu/drm/msm/dsi/dsi_manager.c | 16 + 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index b50db91cb8a7..569c8ff062ba 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -107,6 +107,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 dma_base, u32 len); int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); +void msm_dsi_host_enable_irq(struct mipi_dsi_host *host); +void msm_dsi_host_disable_irq(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host, struct msm_dsi_phy_shared_timings *phy_shared_timings, bool is_bonded_dsi, struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..ce26eb78cb6c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1898,6 +1898,23 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) return ret; } + msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (msm_host->irq < 0) { + ret = msm_host->irq; + dev_err(&pdev->dev, "failed to get irq: %d\n", ret); + return ret; + } + + /* do not autoenable, will be enabled later */ + ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + "dsi_isr", msm_host); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", + msm_host->irq, ret); + return ret; + } + init_completion(&msm_host->dma_comp); init_completion(&msm_host->video_comp); mutex_init(&msm_host->dev_mutex); @@ -1941,25 +1958,8 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; - struct platform_device *pdev = msm_host->pdev; int ret; - msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - if (msm_host->irq < 0) { - ret = msm_host->irq; - DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret); - return ret; - } - - ret = devm_request_irq(&pdev->dev, msm_host->irq, - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "dsi_isr", msm_host); - if (ret < 0) { - DRM_DEV_ERROR(&pdev->dev, "failed to request IRQ%u: %d\n", - msm_host->irq, ret); - return ret; - } - msm_host->dev = dev; ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { @@ -2315,6 +2315,20 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, clk_req->escclk_rate = msm_host->esc_clk_rate; } +void msm_dsi_host_enable_irq(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + enable_irq(msm_host->irq); +} + +void msm_dsi_host_disable_irq(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + disable_irq(msm_host->irq); +} + int msm_dsi_host_enable(struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c41d39f5b7cf..fb4ccffdcfe1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -377,6 +377,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) } } + /* +* Enable before preparing the panel, disable after unpreparing, so +* that th
[PATCH] drm/msm/dsi: use bulk clk API
Use clk_bulk_* API instead of hand-coding them. Note, this drops support for legacy clk naming (e.g. "iface_clk" instead of just "iface"), however all in-kernel device trees were converted long long ago. The warning is present there since 2017. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi_host.c | 59 ++ 1 file changed, 12 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..3b81f40bba2e 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -106,7 +106,8 @@ struct msm_dsi_host { phys_addr_t ctrl_size; struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX]; - struct clk *bus_clks[DSI_BUS_CLK_MAX]; + int num_bus_clks; + struct clk_bulk_data bus_clks[DSI_BUS_CLK_MAX]; struct clk *byte_clk; struct clk *esc_clk; @@ -374,15 +375,14 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) int i, ret = 0; /* get bus clocks */ - for (i = 0; i < cfg->num_bus_clks; i++) { - msm_host->bus_clks[i] = msm_clk_get(pdev, - cfg->bus_clk_names[i]); - if (IS_ERR(msm_host->bus_clks[i])) { - ret = PTR_ERR(msm_host->bus_clks[i]); - pr_err("%s: Unable to get %s clock, ret = %d\n", - __func__, cfg->bus_clk_names[i], ret); - goto exit; - } + for (i = 0; i < cfg->num_bus_clks; i++) + msm_host->bus_clks[i].id = cfg->bus_clk_names[i]; + msm_host->num_bus_clks = cfg->num_bus_clks; + + ret = devm_clk_bulk_get(&pdev->dev, msm_host->num_bus_clks, msm_host->bus_clks); + if (ret < 0) { + dev_err(&pdev->dev, "Unable to get clocks, ret = %d\n", ret); + goto exit; } /* get link and source clocks */ @@ -433,41 +433,6 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) return ret; } -static int dsi_bus_clk_enable(struct msm_dsi_host *msm_host) -{ - const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg; - int i, ret; - - DBG("id=%d", msm_host->id); - - for (i = 0; i < cfg->num_bus_clks; i++) { - ret = clk_prepare_enable(msm_host->bus_clks[i]); - if (ret) { - pr_err("%s: failed to enable bus clock %d ret %d\n", - __func__, i, ret); - goto err; - } - } - - return 0; -err: - for (; i > 0; i--) - clk_disable_unprepare(msm_host->bus_clks[i]); - - return ret; -} - -static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host) -{ - const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg; - int i; - - DBG(""); - - for (i = cfg->num_bus_clks - 1; i >= 0; i--) - clk_disable_unprepare(msm_host->bus_clks[i]); -} - int msm_dsi_runtime_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -478,7 +443,7 @@ int msm_dsi_runtime_suspend(struct device *dev) if (!msm_host->cfg_hnd) return 0; - dsi_bus_clk_disable(msm_host); + clk_bulk_disable_unprepare(msm_host->num_bus_clks, msm_host->bus_clks); return 0; } @@ -493,7 +458,7 @@ int msm_dsi_runtime_resume(struct device *dev) if (!msm_host->cfg_hnd) return 0; - return dsi_bus_clk_enable(msm_host); + return clk_bulk_prepare_enable(msm_host->num_bus_clks, msm_host->bus_clks); } int dsi_link_clk_set_rate_6g(struct msm_dsi_host *msm_host) -- 2.33.0
Re: [Freedreno] [PATCH] drm/msm/dsi: do not install irq handler before power up the host
On 28/09/2021 04:40, Dmitry Baryshkov wrote: On 28/09/2021 04:33, abhin...@codeaurora.org wrote: On 2021-09-27 18:29, Dmitry Baryshkov wrote: On 28/09/2021 04:19, abhin...@codeaurora.org wrote: On 2021-09-27 18:06, Dmitry Baryshkov wrote: On Tue, 28 Sept 2021 at 03:22, wrote: On 2021-09-25 12:43, Dmitry Baryshkov wrote: > On 21/09/2021 23:52, abhin...@codeaurora.org wrote: >> On 2021-09-21 10:47, Dmitry Baryshkov wrote: >>> Hi, >>> >>> On Tue, 21 Sept 2021 at 20:01, wrote: On 2021-09-21 09:22, Dmitry Baryshkov wrote: > The DSI host might be left in some state by the bootloader. If this > state generates an IRQ, it might hang the system by holding the > interrupt line before the driver sets up the DSI host to the known > state. > > Move the request/free_irq calls into msm_dsi_host_power_on/_off calls, > so that we can be sure that the interrupt is delivered when the host is > in the known state. > > Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") > Signed-off-by: Dmitry Baryshkov This is a valid change and we have seen interrupt storms in downstream happening when like you said the bootloader leaves the DSI host in unknown state. Just one question below. > --- > drivers/gpu/drm/msm/dsi/dsi_host.c | 21 - > 1 file changed, 12 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c > b/drivers/gpu/drm/msm/dsi/dsi_host.c > index e269df285136..cd842347a6b1 100644 > --- a/drivers/gpu/drm/msm/dsi/dsi_host.c > +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c > @@ -1951,15 +1951,6 @@ int msm_dsi_host_modeset_init(struct > mipi_dsi_host *host, > return ret; > } > > - ret = devm_request_irq(&pdev->dev, msm_host->irq, > - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > - "dsi_isr", msm_host); > - if (ret < 0) { > - DRM_DEV_ERROR(&pdev->dev, "failed to request IRQ%u: %d\n", > - msm_host->irq, ret); > - return ret; > - } > - > msm_host->dev = dev; > ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); > if (ret) { > @@ -2413,6 +2404,16 @@ int msm_dsi_host_power_on(struct mipi_dsi_host > *host, > if (msm_host->disp_en_gpio) > gpiod_set_value(msm_host->disp_en_gpio, 1); > > + ret = devm_request_irq(&msm_host->pdev->dev, msm_host->irq, > + dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, > + "dsi_isr", msm_host); > + if (ret < 0) { > + DRM_DEV_ERROR(&msm_host->pdev->dev, "failed to request IRQ%u: %d\n", > + msm_host->irq, ret); > + return ret; > + } > + > + Do you want to move this to msm_dsi_host_enable()? So without the controller being enabled it is still in unknown state? >>> >>> msm_dsi_host_power_on() reconfigures the host registers, so the state >>> is known at the end of the power_on(). >>> Also do you want to do this after dsi0 and dsi1 are initialized to account for dual dsi cases? >>> >>> I don't think this should matter. The host won't generate 'extra' >>> interrupts in such case, will it? >>> >> We have seen cases where misconfiguration has caused interrupts to >> storm only >> on one DSI in some cases. So yes, I would prefer this is done after >> both are >> configured. > > I've checked. The power_on is called from dsi_mgr_bridge_pre_enable() > when both DSI hosts should be bound. DSI being bound is enough? I thought the issue we are trying to address is that we need to have called msm_dsi_host_power_on() for both the hosts so that both are put in the known state before requesting the irq. OR in other words move the irq_enable() to below location. 341 static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) 342 { 364 ret = msm_dsi_host_power_on(host, &phy_shared_timings[id], is_bonded_dsi, msm_dsi->phy); 365 if (ret) { 366 pr_err("%s: power on host %d failed, %d\n", __func__, id, ret); 367 goto host_on_fail; 368 } 369 370 if (is_bonded_dsi && msm_dsi1) { 371 ret = msm_dsi_host_power_on(msm_dsi1->host, 372 &phy_shared_timings[DSI_1], is_bonded_dsi, msm_dsi1->phy); 373 if (ret) { 374 pr_err("%s: power on host1 failed, %d\n", 375 __func__, ret); 376 goto host1_on_fail; 377 } 378 } < move the irq enable here > ** Ah, I see your point. Wha
Re: [PATCH 1/3] mfd: qcom-pm8xxx: switch away from using chained IRQ handlers
On 02/10/2021 04:08, Dmitry Baryshkov wrote: PM8xxx PMIC family uses GPIO as parent IRQ. Using it together with the irq_set_chained_handler_and_data() results in warnings from the GPIOLIB as in this path the IRQ resources are not allocated (and thus the corresponding GPIO is not marked as used for the IRQ. Use request_irq so that the IRQ resources are proprely setup. Signed-off-by: Dmitry Baryshkov Please ignore this duplicate, it was sent by mistake. -- With best wishes Dmitry
[PATCH v3] drm/msm/dsi: do not enable irq handler before powering up the host
The DSI host might be left in some state by the bootloader. If this state generates an IRQ, it might hang the system by holding the interrupt line before the driver sets up the DSI host to the known state. Move the request_irq into msm_dsi_host_init and pass IRQF_NO_AUTOEN to it. Call enable/disable_irq after msm_dsi_host_power_on/_off() functions, so that we can be sure that the interrupt is delivered when the host is in the known state. It is not possible to defer the interrupt enablement to a later point, because drm_panel_prepare might need to communicate with the panel over the DSI link and that requires working interrupt. Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_host.c| 48 +-- drivers/gpu/drm/msm/dsi/dsi_manager.c | 16 + 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index b50db91cb8a7..569c8ff062ba 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -107,6 +107,8 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 dma_base, u32 len); int msm_dsi_host_enable(struct mipi_dsi_host *host); int msm_dsi_host_disable(struct mipi_dsi_host *host); +void msm_dsi_host_enable_irq(struct mipi_dsi_host *host); +void msm_dsi_host_disable_irq(struct mipi_dsi_host *host); int msm_dsi_host_power_on(struct mipi_dsi_host *host, struct msm_dsi_phy_shared_timings *phy_shared_timings, bool is_bonded_dsi, struct msm_dsi_phy *phy); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..ce26eb78cb6c 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -1898,6 +1898,23 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi) return ret; } + msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (msm_host->irq < 0) { + ret = msm_host->irq; + dev_err(&pdev->dev, "failed to get irq: %d\n", ret); + return ret; + } + + /* do not autoenable, will be enabled later */ + ret = devm_request_irq(&pdev->dev, msm_host->irq, dsi_host_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT | IRQF_NO_AUTOEN, + "dsi_isr", msm_host); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request IRQ%u: %d\n", + msm_host->irq, ret); + return ret; + } + init_completion(&msm_host->dma_comp); init_completion(&msm_host->video_comp); mutex_init(&msm_host->dev_mutex); @@ -1941,25 +1958,8 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host *host, { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; - struct platform_device *pdev = msm_host->pdev; int ret; - msm_host->irq = irq_of_parse_and_map(pdev->dev.of_node, 0); - if (msm_host->irq < 0) { - ret = msm_host->irq; - DRM_DEV_ERROR(dev->dev, "failed to get irq: %d\n", ret); - return ret; - } - - ret = devm_request_irq(&pdev->dev, msm_host->irq, - dsi_host_irq, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, - "dsi_isr", msm_host); - if (ret < 0) { - DRM_DEV_ERROR(&pdev->dev, "failed to request IRQ%u: %d\n", - msm_host->irq, ret); - return ret; - } - msm_host->dev = dev; ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K); if (ret) { @@ -2315,6 +2315,20 @@ void msm_dsi_host_get_phy_clk_req(struct mipi_dsi_host *host, clk_req->escclk_rate = msm_host->esc_clk_rate; } +void msm_dsi_host_enable_irq(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + enable_irq(msm_host->irq); +} + +void msm_dsi_host_disable_irq(struct mipi_dsi_host *host) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + disable_irq(msm_host->irq); +} + int msm_dsi_host_enable(struct mipi_dsi_host *host) { struct msm_dsi_host *msm_host = to_msm_dsi_host(host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c41d39f5b7cf..fb4ccffdcfe1 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -377,6 +377,14 @@ static void dsi_mgr_bridge_pre_enable(struct drm_bridge *bridge) } } + /* +* Enable before preparing the panel, disable after unpreparing, so +* that the panel can communicate over the DSI link. +*/ + msm_dsi_h
[PATCH 1/3] mfd: qcom-pm8xxx: switch away from using chained IRQ handlers
PM8xxx PMIC family uses GPIO as parent IRQ. Using it together with the irq_set_chained_handler_and_data() results in warnings from the GPIOLIB as in this path the IRQ resources are not allocated (and thus the corresponding GPIO is not marked as used for the IRQ. Use request_irq so that the IRQ resources are proprely setup. Signed-off-by: Dmitry Baryshkov --- drivers/mfd/qcom-pm8xxx.c | 39 --- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/drivers/mfd/qcom-pm8xxx.c b/drivers/mfd/qcom-pm8xxx.c index ec18a04de355..2f2734ba5273 100644 --- a/drivers/mfd/qcom-pm8xxx.c +++ b/drivers/mfd/qcom-pm8xxx.c @@ -65,7 +65,7 @@ struct pm_irq_data { int num_irqs; struct irq_chip *irq_chip; - void (*irq_handler)(struct irq_desc *desc); + irq_handler_t irq_handler; }; struct pm_irq_chip { @@ -169,19 +169,16 @@ static int pm8xxx_irq_master_handler(struct pm_irq_chip *chip, int master) return ret; } -static void pm8xxx_irq_handler(struct irq_desc *desc) +static irqreturn_t pm8xxx_irq_handler(int irq, void *data) { - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); + struct pm_irq_chip *chip = data; unsigned int root; int i, ret, masters = 0; - chained_irq_enter(irq_chip, desc); - ret = regmap_read(chip->regmap, SSBI_REG_ADDR_IRQ_ROOT, &root); if (ret) { pr_err("Can't read root status ret=%d\n", ret); - return; + return IRQ_NONE; } /* on pm8xxx series masters start from bit 1 of the root */ @@ -192,7 +189,7 @@ static void pm8xxx_irq_handler(struct irq_desc *desc) if (masters & (1 << i)) pm8xxx_irq_master_handler(chip, i); - chained_irq_exit(irq_chip, desc); + return IRQ_HANDLED; } static void pm8821_irq_block_handler(struct pm_irq_chip *chip, @@ -230,19 +227,17 @@ static inline void pm8821_irq_master_handler(struct pm_irq_chip *chip, pm8821_irq_block_handler(chip, master, block); } -static void pm8821_irq_handler(struct irq_desc *desc) +static irqreturn_t pm8821_irq_handler(int irq, void *data) { - struct pm_irq_chip *chip = irq_desc_get_handler_data(desc); - struct irq_chip *irq_chip = irq_desc_get_chip(desc); + struct pm_irq_chip *chip = data; unsigned int master; int ret; - chained_irq_enter(irq_chip, desc); ret = regmap_read(chip->regmap, PM8821_SSBI_REG_ADDR_IRQ_MASTER0, &master); if (ret) { pr_err("Failed to read master 0 ret=%d\n", ret); - goto done; + return IRQ_NONE; } /* bits 1 through 7 marks the first 7 blocks in master 0 */ @@ -251,19 +246,18 @@ static void pm8821_irq_handler(struct irq_desc *desc) /* bit 0 marks if master 1 contains any bits */ if (!(master & BIT(0))) - goto done; + return IRQ_NONE; ret = regmap_read(chip->regmap, PM8821_SSBI_REG_ADDR_IRQ_MASTER1, &master); if (ret) { pr_err("Failed to read master 1 ret=%d\n", ret); - goto done; + return IRQ_NONE; } pm8821_irq_master_handler(chip, 1, master); -done: - chained_irq_exit(irq_chip, desc); + return IRQ_HANDLED; } static void pm8xxx_irq_mask_ack(struct irq_data *d) @@ -574,14 +568,15 @@ static int pm8xxx_probe(struct platform_device *pdev) if (!chip->irqdomain) return -ENODEV; - irq_set_chained_handler_and_data(irq, data->irq_handler, chip); + rc = devm_request_irq(&pdev->dev, irq, data->irq_handler, 0, dev_name(&pdev->dev), chip); + if (rc) + return rc; + irq_set_irq_wake(irq, 1); rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - if (rc) { - irq_set_chained_handler_and_data(irq, NULL, NULL); + if (rc) irq_domain_remove(chip->irqdomain); - } return rc; } @@ -594,11 +589,9 @@ static int pm8xxx_remove_child(struct device *dev, void *unused) static int pm8xxx_remove(struct platform_device *pdev) { - int irq = platform_get_irq(pdev, 0); struct pm_irq_chip *chip = platform_get_drvdata(pdev); device_for_each_child(&pdev->dev, NULL, pm8xxx_remove_child); - irq_set_chained_handler_and_data(irq, NULL, NULL); irq_domain_remove(chip->irqdomain); return 0; -- 2.33.0
Re: [PATCH 3/3] drm/msm/dsi: fix signedness bug in msm_dsi_host_cmd_rx()
On 01/10/2021 15:36, Dan Carpenter wrote: The "msg->tx_len" variable is type size_t so if dsi_cmds2buf_tx() returns a negative error code that it type promoted to a high positive value and treat as a success. The second problem with this code is that it can return meaningless positive values on error. It looks to me that this piece of code is not fully correct at all. dsi_cmds2bus_tx would return the size of DSI packet, not the size of the DSI buffer. Could you please be more specific, which 'meaningless positive values' were you receiving? Fixes: a689554ba6ed ("drm/msm: Initial add DSI connector support") Signed-off-by: Dan Carpenter --- drivers/gpu/drm/msm/dsi/dsi_host.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index c86b5090fae6..42073a562072 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2133,8 +2133,10 @@ int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host, } ret = dsi_cmds2buf_tx(msm_host, msg); - if (ret < msg->tx_len) { + if (ret < 0 || ret < msg->tx_len) { pr_err("%s: Read cmd Tx failed, %d\n", __func__, ret); + if (ret >= 0) + ret = -EIO; return ret; } -- With best wishes Dmitry
[PATCH v2 4/4] drm/i915: Clarify probing order in intel_dp_aux_init_backlight_funcs()
Hooray! We've managed to hit enough bugs upstream that I've been able to come up with a pretty solid explanation for how backlight controls are actually supposed to be detected and used these days. As well, having the rest of the PWM bits in VESA's backlight interface implemented seems to have fixed all of the problematic brightness controls laptop panels that we've hit so far. So, let's actually document this instead of just calling the laptop panels liars. As well, I would like to formally apologize to all of the laptop panels I called liars. I'm sorry laptop panels, hopefully you can all forgive me and we can move past this~ Signed-off-by: Lyude Paul --- .../drm/i915/display/intel_dp_aux_backlight.c| 16 +++- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 91daf9ab50e8..04a52d6a74ed 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -455,11 +455,17 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) } /* -* A lot of eDP panels in the wild will report supporting both the -* Intel proprietary backlight control interface, and the VESA -* backlight control interface. Many of these panels are liars though, -* and will only work with the Intel interface. So, always probe for -* that first. +* Since Intel has their own backlight control interface, the majority of machines out there +* using DPCD backlight controls with Intel GPUs will be using this interface as opposed to +* the VESA interface. However, other GPUs (such as Nvidia's) will always use the VESA +* interface. This means that there's quite a number of panels out there that will advertise +* support for both interfaces, primarily systems with Intel/Nvidia hybrid GPU setups. +* +* There's a catch to this though: on many panels that advertise support for both +* interfaces, the VESA backlight interface will stop working once we've programmed the +* panel with Intel's OUI - which is also required for us to be able to detect Intel's +* backlight interface at all. This means that the only sensible way for us to detect both +* interfaces is to probe for Intel's first, and VESA's second. */ if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector)) { drm_dbg_kms(dev, "Using Intel proprietary eDP backlight controls\n"); -- 2.31.1
[PATCH v2 3/4] drm/dp, drm/i915: Add support for VESA backlights using PWM for brightness control
Now that we've added support to i915 for controlling panel backlights that need PWM to be enabled/disabled, let's finalize this and add support for controlling brightness levels via PWM as well. This should hopefully put us towards the path of supporting _ALL_ backlights via VESA's DPCD interface which would allow us to finally start trusting the DPCD again. Note however that we still don't enable using this by default on i915 when it's not needed, primarily because I haven't yet had a chance to confirm if it's safe to do this on the one machine in Intel's CI that had an issue with this: samus-fi-bdw. I have done basic testing of this on other machines though, by manually patching i915 to force it into PWM-only mode on some of my laptops. v2: * Correct documentation (thanks Doug!) * Get rid of backlight caps Signed-off-by: Lyude Paul Cc: Rajeev Nandan Cc: Doug Anderson Cc: Satadru Pramanik --- drivers/gpu/drm/drm_dp_helper.c | 75 +-- .../drm/i915/display/intel_dp_aux_backlight.c | 48 +--- include/drm/drm_dp_helper.h | 7 +- 3 files changed, 93 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 4d0d1e8e51fa..f350e17a80e7 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -3173,6 +3173,10 @@ int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_bac int ret; u8 buf[2] = { 0 }; + /* The panel uses the PWM for controlling brightness levels */ + if (!bl->aux_set) + return 0; + if (bl->lsb_reg_used) { buf[0] = (level & 0xff00) >> 8; buf[1] = (level & 0x00ff); @@ -3199,7 +3203,7 @@ drm_edp_backlight_set_enable(struct drm_dp_aux *aux, const struct drm_edp_backli int ret; u8 buf; - /* The panel uses something other then DPCD for enabling its backlight */ + /* This panel uses the EDP_BL_PWR GPIO for enablement */ if (!bl->aux_enable) return 0; @@ -3234,11 +3238,11 @@ drm_edp_backlight_set_enable(struct drm_dp_aux *aux, const struct drm_edp_backli * restoring any important backlight state such as the given backlight level, the brightness byte * count, backlight frequency, etc. * - * Note that certain panels, while supporting brightness level controls over DPCD, may not support - * having their backlights enabled via the standard %DP_EDP_DISPLAY_CONTROL_REGISTER. On such panels - * &drm_edp_backlight_info.aux_enable will be set to %false, this function will skip the step of - * programming the %DP_EDP_DISPLAY_CONTROL_REGISTER, and the driver must perform the required - * implementation specific step for enabling the backlight after calling this function. + * Note that certain panels do not support being enabled or disabled via DPCD, but instead require + * that the driver handle enabling/disabling the panel through implementation-specific means using + * the EDP_BL_PWR GPIO. For such panels, &drm_edp_backlight_info.aux_enable will be set to %false, + * this function becomes a no-op, and the driver is expected to handle powering the panel on using + * the EDP_BL_PWR GPIO. * * Returns: %0 on success, negative error code on failure. */ @@ -3246,7 +3250,7 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli const u16 level) { int ret; - u8 dpcd_buf, new_dpcd_buf; + u8 dpcd_buf, new_dpcd_buf, new_mode; ret = drm_dp_dpcd_readb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf); if (ret != 1) { @@ -3256,10 +3260,14 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli } new_dpcd_buf = dpcd_buf; + if (bl->aux_set) + new_mode = DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; + else + new_mode = DP_EDP_BACKLIGHT_CONTROL_MODE_PWM; - if ((dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) != DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { + if ((dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) != new_mode) { new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; - new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; + new_dpcd_buf |= new_mode; if (bl->pwmgen_bit_count) { ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); @@ -3304,12 +3312,13 @@ EXPORT_SYMBOL(drm_edp_backlight_enable); * @aux: The DP AUX channel to use * @bl: Backlight capability info from drm_edp_backlight_init() * - * This function handles disabling DPCD backlight controls on a panel over AUX. Note that some - * panels have backlights that are enabled/disabled by other means, despite having their brightness - * values controlled through DPCD. On such panels &drm_edp_backlight_info.aux_enable will be set to - * %false, th
[PATCH v2 1/4] drm/i915: Add support for panels with VESA backlights with PWM enable/disable
This simply adds proper support for panel backlights that can be controlled via VESA's backlight control protocol, but which also require that we enable and disable the backlight via PWM instead of via the DPCD interface. We also enable this by default, in order to fix some people's backlights that were broken by not having this enabled. For reference, backlights that require this and use VESA's backlight interface tend to be laptops with hybrid GPUs, but this very well may change in the future. Signed-off-by: Lyude Paul Link: https://gitlab.freedesktop.org/drm/intel/-/issues/3680 Fixes: fe7d52bccab6 ("drm/i915/dp: Don't use DPCD backlights that need PWM enable/disable") Cc: # v5.12+ --- .../drm/i915/display/intel_dp_aux_backlight.c | 24 ++- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 569d17b4d00f..594fdc7453ca 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -293,6 +293,10 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, struct intel_panel *panel = &connector->panel; struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); + if (!panel->backlight.edp.vesa.info.aux_enable) + panel->backlight.pwm_funcs->enable(crtc_state, conn_state, + panel->backlight.pwm_level_max); + drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level); } @@ -304,6 +308,10 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info); + + if (!panel->backlight.edp.vesa.info.aux_enable) + panel->backlight.pwm_funcs->disable(old_conn_state, + intel_backlight_invert_pwm_level(connector, 0)); } static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe) @@ -321,6 +329,15 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, if (ret < 0) return ret; + if (!panel->backlight.edp.vesa.info.aux_enable) { + ret = panel->backlight.pwm_funcs->setup(connector, pipe); + if (ret < 0) { + drm_err(&i915->drm, + "Failed to setup PWM backlight controls for eDP backlight: %d\n", + ret); + return ret; + } + } panel->backlight.max = panel->backlight.edp.vesa.info.max; panel->backlight.min = 0; if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { @@ -340,12 +357,7 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector) struct intel_dp *intel_dp = intel_attached_dp(connector); struct drm_i915_private *i915 = dp_to_i915(intel_dp); - /* TODO: We currently only support AUX only backlight configurations, not backlights which -* require a mix of PWM and AUX controls to work. In the mean time, these machines typically -* work just fine using normal PWM controls anyway. -*/ - if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && - drm_edp_backlight_supported(intel_dp->edp_dpcd)) { + if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) { drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n"); return true; } -- 2.31.1
[PATCH v2 2/4] drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux enable/brightness
Since we don't support hybrid AUX/PWM backlights in nouveau right now, let's add some explicit checks so that we don't break nouveau once we enable support for these backlights in other drivers. Signed-off-by: Lyude Paul --- drivers/gpu/drm/nouveau/nouveau_backlight.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index 1cbd71abc80a..ae2f2abc8f5a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -308,7 +308,10 @@ nv50_backlight_init(struct nouveau_backlight *bl, if (ret < 0) return ret; - if (drm_edp_backlight_supported(edp_dpcd)) { + /* TODO: Add support for hybrid PWM/DPCD panels */ + if (drm_edp_backlight_supported(edp_dpcd) && + (edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && + (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) { NV_DEBUG(drm, "DPCD backlight controls supported on %s\n", nv_conn->base.name); -- 2.31.1
[PATCH v2 0/4] drm/dp, drm/i915: Finish basic PWM support for VESA backlight helpers
When I originally moved all of the VESA backlight code in i915 into DRM helpers, one of the things I didn't have the hardware or time for testing was machines that used a combination of PWM and DPCD in order to control their backlights. This has since then caused some breakages and resulted in us disabling DPCD backlight support on such machines. This works fine, unless you have a machine that actually needs this functionality for backlight controls to work at all. Additionally, we will need to support PWM for when we start adding support for VESA's product (as in the product of multiplication) control mode for better brightness ranges. So - let's finally finish up implementing basic support for these types of backlights to solve these problems in our DP helpers, along with implementing support for this in i915. And since digging into this issue solved the last questions we really had about probing backlights in i915 for the most part, let's update some of the comments around that as well! Changes: * Fixup docs * Add patch to stop us from breaking nouveau Lyude Paul (4): drm/i915: Add support for panels with VESA backlights with PWM enable/disable drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux enable/brightness drm/dp, drm/i915: Add support for VESA backlights using PWM for brightness control drm/i915: Clarify probing order in intel_dp_aux_init_backlight_funcs() drivers/gpu/drm/drm_dp_helper.c | 75 +++-- .../drm/i915/display/intel_dp_aux_backlight.c | 80 ++- drivers/gpu/drm/nouveau/nouveau_backlight.c | 5 +- include/drm/drm_dp_helper.h | 7 +- 4 files changed, 122 insertions(+), 45 deletions(-) -- 2.31.1
Re: [PATCH 2/3] drm/msm/dsi: fix off by one in dsi_bus_clk_enable error handling
On 01/10/2021 15:34, Dan Carpenter wrote: This disables a lock which wasn't enabled and it does not disable the first lock in the array. Fixes: 6e0eb52eba9e ("drm/msm/dsi: Parse bus clocks from a list") Signed-off-by: Dan Carpenter Reviewed-by: Dmitry Baryshkov We should probably switch this to bulk clk api. --- drivers/gpu/drm/msm/dsi/dsi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..c86b5090fae6 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -451,7 +451,7 @@ static int dsi_bus_clk_enable(struct msm_dsi_host *msm_host) return 0; err: - for (; i > 0; i--) + while (--i >= 0) clk_disable_unprepare(msm_host->bus_clks[i]); return ret; -- With best wishes Dmitry
Re: [PATCH 1/3] drm/msm/dsi: Fix an error code in msm_dsi_modeset_init()
On 01/10/2021 15:33, Dan Carpenter wrote: Return an error code if msm_dsi_manager_validate_current_config(). Don't return success. Fixes: 8b03ad30e314 ("drm/msm/dsi: Use one connector for dual DSI mode") Signed-off-by: Dan Carpenter Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c index 614dc7f26f2c..75ae3008b68f 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.c +++ b/drivers/gpu/drm/msm/dsi/dsi.c @@ -215,8 +215,10 @@ int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev, goto fail; } - if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) + if (!msm_dsi_manager_validate_current_config(msm_dsi->id)) { + ret = -EINVAL; goto fail; + } msm_dsi->encoder = encoder; -- With best wishes Dmitry
Re: [PATCH] drm/msm/dsi: prevent unintentional integer overflow in dsi_pll_28nm_clk_recalc_rate()
On 29/09/2021 20:51, Tim Gardner wrote: Coverity warns of an unintentional integer overflow CID 120715 (#1 of 1): Unintentional integer overflow (OVERFLOW_BEFORE_WIDEN) overflow_before_widen: Potentially overflowing expression ref_clk * sdm_byp_div with type unsigned int (32 bits, unsigned) is evaluated using 32-bit arithmetic, and then used in a context that expects an expression of type unsigned long (64 bits, unsigned). To avoid overflow, cast either ref_clk or sdm_byp_div to type unsigned long. 263vco_rate = ref_clk * sdm_byp_div; Fix this and another possible overflow by casting ref_clk to unsigned long. Changing ref_clk from u32 to unsigned long would be a more simple and elegant way of fixing this issue. Could you please update your patch? Cc: Rob Clark Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: Dmitry Baryshkov Cc: Abhinav Kumar Cc: linux-arm-...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: freedr...@lists.freedesktop.org Cc: linux-ker...@vger.kernel.org Signed-off-by: Tim Gardner --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c index 2da673a2add6..cfe4b30eb96d 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c @@ -260,7 +260,7 @@ static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw, sdm_byp_div = FIELD( dsi_phy_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0), DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1; - vco_rate = ref_clk * sdm_byp_div; + vco_rate = (unsigned long)ref_clk * sdm_byp_div; } else { /* sdm mode */ sdm_dc_off = FIELD( @@ -274,7 +274,7 @@ static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw, sdm_freq_seed = (sdm3 << 8) | sdm2; DBG("sdm_freq_seed = %d", sdm_freq_seed); - vco_rate = (ref_clk * (sdm_dc_off + 1)) + + vco_rate = ((unsigned long)ref_clk * (sdm_dc_off + 1)) + mult_frac(ref_clk, sdm_freq_seed, BIT(16)); DBG("vco rate = %lu", vco_rate); } -- With best wishes Dmitry
Re: [PATCH] drm/msm: prevent NULL dereference in msm_gpu_crashstate_capture()
On 29/09/2021 19:25, Tim Gardner wrote: Coverity complains of a possible NULL dereference: CID 120718 (#1 of 1): Dereference null return value (NULL_RETURNS) 23. dereference: Dereferencing a pointer that might be NULL state->bos when calling msm_gpu_crashstate_get_bo. [show details] 301msm_gpu_crashstate_get_bo(state, submit->bos[i].obj, 302submit->bos[i].iova, submit->bos[i].flags); Fix this by employing the same state->bos NULL check as is used in the next for loop. Cc: Rob Clark Cc: Sean Paul Cc: David Airlie Cc: Daniel Vetter Cc: linux-arm-...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: freedr...@lists.freedesktop.org Cc: linux-ker...@vger.kernel.org Signed-off-by: Tim Gardner Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/msm_gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 8a3a592da3a4..2c46cd968ac4 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -296,7 +296,7 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu, state->bos = kcalloc(nr, sizeof(struct msm_gpu_state_bo), GFP_KERNEL); - for (i = 0; i < submit->nr_bos; i++) { + for (i = 0; state->bos && i < submit->nr_bos; i++) { if (should_dump(submit, i)) { msm_gpu_crashstate_get_bo(state, submit->bos[i].obj, submit->bos[i].iova, submit->bos[i].flags); -- With best wishes Dmitry
Re: [PATCH v2] drm: msm: adreno_gpu.c: Add and use pr_fmt(fmt)
On 26/08/2021 05:23, zhaoxiao wrote: Use a more common logging style. Signed-off-by: zhaoxiao Your subject tells about pr_fmt(), while the patch itself changs printk()s to pr_info(). Could you please fix the commit subject and expand/correct commit message? --- v2:Remove the line: #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt drivers/gpu/drm/msm/adreno/adreno_gpu.c:23:9: warning: 'pr_fmt' macro redefined [-Wmacro-redefined] #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt ^ include/linux/printk.h:348:9: note: previous definition is here #define pr_fmt(fmt) fmt drivers/gpu/drm/msm/adreno/adreno_gpu.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index 9f5a30234b33..f10e9e04c13b 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -753,7 +753,7 @@ void adreno_dump_info(struct msm_gpu *gpu) struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); int i; - printk("revision: %d (%d.%d.%d.%d)\n", + pr_info("revision: %d (%d.%d.%d.%d)\n", adreno_gpu->info->revn, adreno_gpu->rev.core, adreno_gpu->rev.major, adreno_gpu->rev.minor, adreno_gpu->rev.patchid); @@ -761,12 +761,12 @@ void adreno_dump_info(struct msm_gpu *gpu) for (i = 0; i < gpu->nr_rings; i++) { struct msm_ringbuffer *ring = gpu->rb[i]; - printk("rb %d: fence:%d/%d\n", i, + pr_info("rb %d: fence:%d/%d\n", i, ring->memptrs->fence, ring->seqno); - printk("rptr: %d\n", get_rptr(adreno_gpu, ring)); - printk("rb wptr: %d\n", get_wptr(ring)); + pr_info("rptr: %d\n", get_rptr(adreno_gpu, ring)); + pr_info("rb wptr: %d\n", get_wptr(ring)); } } @@ -780,7 +780,7 @@ void adreno_dump(struct msm_gpu *gpu) return; /* dump these out in a form that can be parsed by demsm: */ - printk("IO:region %s 0002\n", gpu->name); + pr_info("IO:region %s 0002\n", gpu->name); for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) { uint32_t start = adreno_gpu->registers[i]; uint32_t end = adreno_gpu->registers[i+1]; @@ -788,7 +788,7 @@ void adreno_dump(struct msm_gpu *gpu) for (addr = start; addr <= end; addr++) { uint32_t val = gpu_read(gpu, addr); - printk("IO:R %08x %08x\n", addr<<2, val); + pr_info("IO:R %08x %08x\n", addr<<2, val); } } } -- With best wishes Dmitry
Re: [PATCH v2 2/2] drm/msm/dpu: Fix timeout issues on command mode panels
On 11/09/2021 19:39, AngeloGioacchino Del Regno wrote: In function dpu_encoder_phys_cmd_wait_for_commit_done we are always checking if the relative CTL is started by waiting for an interrupt to fire: it is fine to do that, but then sometimes we call this function while the CTL is up and has never been put down, but that interrupt gets raised only when the CTL gets a state change from 0 to 1 (disabled to enabled), so we're going to wait for something that will never happen on its own. Solving this while avoiding to restart the CTL is actually possible and can be done by just checking if it is already up and running when the wait_for_commit_done function is called: in this case, so, if the CTL was already running, we can say that the commit is done if the command transmission is complete (in other terms, if the interface has been flushed). I've compared this with the MDP5 driver, where we always wait for PP_DONE interrupt. Would it be enough to always wait for it (= always call dpu_encoder_phys_cmd_wait_for_tx_complete())? Signed-off-by: AngeloGioacchino Del Regno --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 3 +++ 1 file changed, 3 insertions(+) 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 aa01698d6b25..aa5d3b3cef15 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 @@ -682,6 +682,9 @@ static int dpu_encoder_phys_cmd_wait_for_commit_done( if (!dpu_encoder_phys_cmd_is_master(phys_enc)) return 0; + if (phys_enc->hw_ctl->ops.is_started(phys_enc->hw_ctl)) + return dpu_encoder_phys_cmd_wait_for_tx_complete(phys_enc); + return _dpu_encoder_phys_cmd_wait_for_ctl_start(phys_enc); } -- With best wishes Dmitry
Re: [PATCH v2 00/17] drm: cleanup: Use DRM_MODESET_LOCK_ALL_* helpers where possible
On Fri, Oct 01, 2021 at 04:48:15PM -0400, Sean Paul wrote: > On Fri, Oct 01, 2021 at 10:00:50PM +0300, Ville Syrjälä wrote: > > On Fri, Oct 01, 2021 at 02:36:55PM -0400, Sean Paul wrote: > > > On Fri, Sep 24, 2021 at 08:43:07AM +0200, Fernando Ramos wrote: > > > > Hi all, > > > > > > > > One of the things in the DRM TODO list ("Documentation/gpu/todo.rst") > > > > was to > > > > "use DRM_MODESET_LOCAL_ALL_* helpers instead of boilerplate". That's > > > > what this > > > > patch series is about. > > > > > > > > You will find two types of changes here: > > > > > > > > - Replacing "drm_modeset_lock_all_ctx()" (and surrounding > > > > boilerplate) with > > > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" in the remaining places (as it > > > > has > > > > already been done in previous commits such as b7ea04d2) > > > > > > > > - Replacing "drm_modeset_lock_all()" with > > > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" > > > > in the remaining places (as it has already been done in previous > > > > commits > > > > such as 57037094) > > > > > > > > Most of the changes are straight forward, except for a few cases in the > > > > "amd" > > > > and "i915" drivers where some extra dancing was needed to overcome the > > > > limitation that the DRM_MODESET_LOCK_ALL_BEGIN()/END() macros can only > > > > be used > > > > once inside the same function (the reason being that the macro expansion > > > > includes *labels*, and you can not have two labels named the same > > > > inside one > > > > function) > > > > > > > > Notice that, even after this patch series, some places remain where > > > > "drm_modeset_lock_all()" and "drm_modeset_lock_all_ctx()" are still > > > > present, > > > > all inside drm core (which makes sense), except for two (in "amd" and > > > > "i915") > > > > which cannot be replaced due to the way they are being used. > > > > > > > > Changes in v2: > > > > > > > > - Fix commit message typo > > > > - Use the value returned by DRM_MODESET_LOCK_ALL_END when possible > > > > - Split drm/i915 patch into two simpler ones > > > > - Remove drm_modeset_(un)lock_all() > > > > - Fix build problems in non-x86 platforms > > > > > > > > Fernando Ramos (17): > > > > drm: cleanup: drm_modeset_lock_all_ctx() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/i915: cleanup: drm_modeset_lock_all_ctx() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/msm: cleanup: drm_modeset_lock_all_ctx() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/vmwgfx: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/tegra: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/shmobile: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/radeon: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/omapdrm: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/nouveau: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/msm: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/i915: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/i915: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() part 2 > > > > drm/gma500: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm/amd: cleanup: drm_modeset_lock_all() --> > > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > > drm: cleanup: remove drm_modeset_(un)lock_all() > > > > doc: drm: remove TODO entry regarding DRM_MODSET_LOCK_ALL cleanup > > > > > > > > > > Thank you for revising, Fernando! I've pushed the set to drm-misc-next > > > (along > > > with the necessary drm-tip conflict resolutions). > > > > Ugh. Did anyone actually review the locking changes this does? > > I shot the previous i915 stuff down because the commit messages > > did not address any of it. > > I reviewed the set on 9/17, I didn't see your feedback on that thread. It was much earlir than that. https://lists.freedesktop.org/archives/dri-devel/2021-June/313193.html And I think I might have also shot down a similar thing earlier. I was actually half considering sending a patch to nuke that misleading TODO item. I don't think anything which changes which locks are taken should be considred a starter level task. And the commit messages here don't seem to address any of it. -- Ville Syrjälä Intel
[PATCH v2] drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX
If the display is not enable()d, then we aren't holding a runtime PM reference here. Thus, it's easy to accidentally cause a hang, if user space is poking around at /dev/drm_dp_aux0 at the "wrong" time. Let's get the panel and PM state right before trying to talk AUX. Fixes: 0d97ad03f422 ("drm/bridge: analogix_dp: Remove duplicated code") Cc: Cc: Tomeu Vizoso Signed-off-by: Brian Norris --- Changes in v2: - Fix spelling in Subject - DRM_DEV_ERROR() -> drm_err() - Propagate errors from un-analogix_dp_prepare_panel() .../drm/bridge/analogix/analogix_dp_core.c| 21 ++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index b7d2e4449cfa..6fc46ac93ef8 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1632,8 +1632,27 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { struct analogix_dp_device *dp = to_dp(aux); + int ret, ret2; - return analogix_dp_transfer(dp, msg); + ret = analogix_dp_prepare_panel(dp, true, false); + if (ret) { + drm_err(dp->drm_dev, "Failed to prepare panel (%d)\n", ret); + return ret; + } + + pm_runtime_get_sync(dp->dev); + ret = analogix_dp_transfer(dp, msg); + pm_runtime_put(dp->dev); + + ret2 = analogix_dp_prepare_panel(dp, false, false); + if (ret2) { + drm_err(dp->drm_dev, "Failed to unprepare panel (%d)\n", ret2); + /* Prefer the analogix_dp_transfer() error, if it exists. */ + if (!ret) + ret = ret2; + } + + return ret; } struct analogix_dp_device * -- 2.33.0.800.g4c38ced690-goog
Re: [PATCH][V2] drm/msm: Fix potential integer overflow on 32 bit multiply
On 29/09/2021 14:53, Colin King wrote: From: Colin Ian King In the case where clock is 2147485 or greater the 32 bit multiplication by 1000 will cause an integer overflow. Fix this by making the constant 1000 an unsigned long to ensure a long multiply occurs to avoid the You are talking about 'unsigned long' here, however in the patch you've used just 'unsigned' suffix. So, which one should be used? I suspect that wanted to use UL here, since mode->clock is int, so it is int * unsigned. Also I'd suggest to define a helper function macro in the drm_modes.h(?) that would take struct drm_display_mode pointer and return proper clock. See icc_units_to_bps() for the inspiration. overflow before assigning the result to the long result in variable requested. Most probably a theoretical overflow issue, but worth fixing to clear up static analysis warnings. Addresses-Coverity: ("Unintentional integer overflow") Fixes: c8afe684c95c ("drm/msm: basic KMS driver for snapdragon") Fixes: 3e87599b68e7 ("drm/msm/mdp4: add LVDS panel support") Fixes: 937f941ca06f ("drm/msm/dp: Use qmp phy for DP PLL and PHY") Fixes: ab5b0107ccf3 ("drm/msm: Initial add eDP support in msm drm driver (v5)") Fixes: a3376e3ec81c ("drm/msm: convert to drm_bridge") Signed-off-by: Colin Ian King --- V2: Find and fix all unintentional integer overflows that match this overflow pattern. --- drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c| 2 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 2 +- drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c | 2 +- drivers/gpu/drm/msm/dp/dp_ctrl.c| 4 ++-- drivers/gpu/drm/msm/edp/edp_connector.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 2 +- drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c index 88645dbc3785..83140066441e 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c @@ -50,7 +50,7 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder, DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode)); - mdp4_dtv_encoder->pixclock = mode->clock * 1000; + mdp4_dtv_encoder->pixclock = mode->clock * 1000U; DBG("pixclock=%lu", mdp4_dtv_encoder->pixclock); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c index 10eb3e5b218e..d90dc0a39855 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c @@ -225,7 +225,7 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder *encoder, DBG("set mode: " DRM_MODE_FMT, DRM_MODE_ARG(mode)); - mdp4_lcdc_encoder->pixclock = mode->clock * 1000; + mdp4_lcdc_encoder->pixclock = mode->clock * 1000U; DBG("pixclock=%lu", mdp4_lcdc_encoder->pixclock); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c index 7288041dd86a..a965e7962a7f 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lvds_connector.c @@ -64,7 +64,7 @@ static int mdp4_lvds_connector_mode_valid(struct drm_connector *connector, struct drm_encoder *encoder = mdp4_lvds_connector->encoder; long actual, requested; - requested = 1000 * mode->clock; + requested = 1000U * mode->clock; actual = mdp4_lcdc_round_pixclk(encoder, requested); DBG("requested=%ld, actual=%ld", requested, actual); diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 62e75dc8afc6..6babeb79aeb0 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1316,7 +1316,7 @@ static int dp_ctrl_enable_mainlink_clocks(struct dp_ctrl_private *ctrl) opts_dp->lanes = ctrl->link->link_params.num_lanes; opts_dp->link_rate = ctrl->link->link_params.rate / 100; dp_ctrl_set_clock_rate(ctrl, DP_CTRL_PM, "ctrl_link", - ctrl->link->link_params.rate * 1000); + ctrl->link->link_params.rate * 1000U); phy_configure(phy, &dp_io->phy_opts); phy_power_on(phy); @@ -1336,7 +1336,7 @@ static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) int ret = 0; dp_ctrl_set_clock_rate(ctrl, DP_STREAM_PM, "stream_pixel", - ctrl->dp_ctrl.pixel_rate * 1000); + ctrl->dp_ctrl.pixel_rate * 1000U); ret = dp_power_clk_enable(ctrl->power, DP_STREAM_PM, true); if (ret) diff --git a/drivers/gpu/drm/msm/edp/edp_connector.c b/drivers/gpu/drm/msm/edp/edp_connector.c index 73cb5fd97a5a..837e7873141f 100644 --- a/drivers/gpu/drm/msm/
Re: [PATCH v13 14/35] drm/tegra: gr3d: Support generic power domain and runtime PM
01.10.2021 17:06, Ulf Hansson пишет: > On Mon, 27 Sept 2021 at 00:42, Dmitry Osipenko wrote: >> Add runtime power management and support generic power domains. >> >> Tested-by: Peter Geis # Ouya T30 >> Tested-by: Paul Fertser # PAZ00 T20 >> Tested-by: Nicolas Chauvet # PAZ00 T20 and TK1 T124 >> Tested-by: Matt Merhar # Ouya T30 >> Signed-off-by: Dmitry Osipenko >> --- >> drivers/gpu/drm/tegra/gr3d.c | 388 ++- > [...] > > I was looking for a call to dev_pm_opp_set_rate(), but couldn't find > it. Isn't that needed when changing the rate of the clock? That is another good catch! Previous versions of this patch were changing the rate, while the current version not. So the set_opp_helper() isn't needed for this patch anymore. It may become needed sometime later, but not for this series. I'll remove it in the next version, thanks!
Re: [PATCH] drm/brdige: analogix_dp: Grab runtime PM reference for DP-AUX
On Fri, Oct 1, 2021 at 1:37 PM Sean Paul wrote: > On Wed, Sep 29, 2021 at 02:41:03PM -0700, Brian Norris wrote: > > --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > > +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > > @@ -1632,8 +1632,23 @@ static ssize_t analogix_dpaux_transfer(struct > > drm_dp_aux *aux, > > struct drm_dp_aux_msg *msg) > > { > > struct analogix_dp_device *dp = to_dp(aux); > > + int ret, ret2; > > > > - return analogix_dp_transfer(dp, msg); > > + ret = analogix_dp_prepare_panel(dp, true, false); > > + if (ret) { > > + DRM_DEV_ERROR(dp->dev, "Failed to prepare panel (%d)\n", ret); > > s/DRM_DEV_ERROR/drm_err/ Sure. Now that I'm looking a second time, I see the header recommends this. > > + return ret; > > + } > > + > > + pm_runtime_get_sync(dp->dev); > > + ret = analogix_dp_transfer(dp, msg); > > + pm_runtime_put(dp->dev); > > + > > + ret2 = analogix_dp_prepare_panel(dp, false, false); > > + if (ret2) > > + DRM_DEV_ERROR(dp->dev, "Failed to unprepare panel (%d)\n", > > ret2); > > What's the reasoning for not propagating unprepare failures? I feel like that > should be fair game. I suppose the underlying reason is laziness, sorry. But a related reason is the we probably should prefer propagating the analogix_dp_transfer() error, if it's non-zero, rather than the unprepare error. That's not too hard to do though, even if it's slightly more awkward. > > + > > + return ret; > > } > > > > struct analogix_dp_device * v2 coming. Regards, Brian
Re: [PATCH v3 3/3] drm/msm/mdp5: Add configuration for MDP v1.16
On 28/09/2021 16:19, Sireesh Kodali wrote: From: Vladimir Lypak MDP version v1.16 is almost identical to v1.15 with most significant difference being presence of second DSI interface. MDP v1.16 is found on SoCs such as MSM8x53, SDM450, SDM632 (All with Adreno 506). Signed-off-by: Vladimir Lypak Signed-off-by: Sireesh Kodali Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 89 1 file changed, 89 insertions(+) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c index 9741544ffc35..0d28c8ff4009 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c @@ -752,6 +752,94 @@ const struct mdp5_cfg_hw msm8x76_config = { .max_clk = 36000, }; +static const struct mdp5_cfg_hw msm8x53_config = { + .name = "msm8x53", + .mdp = { + .count = 1, + .caps = MDP_CAP_CDM | + MDP_CAP_SRC_SPLIT, + }, + .ctl = { + .count = 3, + .base = { 0x01000, 0x01200, 0x01400 }, + .flush_hw_mask = 0x, + }, + .pipe_vig = { + .count = 1, + .base = { 0x04000 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SCALE | + MDP_PIPE_CAP_CSC| + MDP_PIPE_CAP_DECIMATION | + MDP_PIPE_CAP_SW_PIX_EXT | + 0, + }, + .pipe_rgb = { + .count = 2, + .base = { 0x14000, 0x16000 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_DECIMATION | + MDP_PIPE_CAP_SW_PIX_EXT | + 0, + }, + .pipe_dma = { + .count = 1, + .base = { 0x24000 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SW_PIX_EXT | + 0, + }, + .pipe_cursor = { + .count = 1, + .base = { 0x34000 }, + .caps = MDP_PIPE_CAP_HFLIP | + MDP_PIPE_CAP_VFLIP | + MDP_PIPE_CAP_SW_PIX_EXT | + MDP_PIPE_CAP_CURSOR | + 0, + }, + + .lm = { + .count = 3, + .base = { 0x44000, 0x45000 }, + .instances = { + { .id = 0, .pp = 0, .dspp = 0, + .caps = MDP_LM_CAP_DISPLAY | + MDP_LM_CAP_PAIR }, + { .id = 1, .pp = 1, .dspp = -1, + .caps = MDP_LM_CAP_DISPLAY }, +}, + .nb_stages = 5, + .max_width = 2048, + .max_height = 0x, + }, + .dspp = { + .count = 1, + .base = { 0x54000 }, + + }, + .pp = { + .count = 2, + .base = { 0x7, 0x70800 }, + }, + .cdm = { + .count = 1, + .base = { 0x79200 }, + }, + .intf = { + .base = { 0x6a000, 0x6a800, 0x6b000 }, + .connect = { + [0] = INTF_DISABLED, + [1] = INTF_DSI, + [2] = INTF_DSI, + }, + }, + .max_clk = 4, +}; + static const struct mdp5_cfg_hw msm8917_config = { .name = "msm8917", .mdp = { @@ -1151,6 +1239,7 @@ static const struct mdp5_cfg_handler cfg_handlers_v1[] = { { .revision = 7, .config = { .hw = &msm8x96_config } }, { .revision = 11, .config = { .hw = &msm8x76_config } }, { .revision = 15, .config = { .hw = &msm8917_config } }, + { .revision = 16, .config = { .hw = &msm8x53_config } }, }; static const struct mdp5_cfg_handler cfg_handlers_v3[] = { -- With best wishes Dmitry
Re: [RFC] drm/msm/dp: Allow attaching a drm_panel
On Fri 27 Aug 13:52 PDT 2021, Doug Anderson wrote: > Hi, > > On Mon, Jul 26, 2021 at 4:15 PM Bjorn Andersson > wrote: > > > > +static int dp_parser_find_panel(struct dp_parser *parser) > > +{ > > + struct device_node *np = parser->pdev->dev.of_node; > > + int rc; > > + > > + rc = drm_of_find_panel_or_bridge(np, 2, 0, &parser->drm_panel, > > NULL); > > Why port 2? Shouldn't this just be port 1 always? The yaml says that > port 1 is "Output endpoint of the controller". We should just use port > 1 here, right? > Finally got back to this, changed it to 1 and figured out why I left it at 2. drm_of_find_panel_or_bridge() on a DP controller will find the of_graph reference to the USB-C controller, scan through the registered panels and conclude that the of_node of the USB-C controller isn't a registered panel and return -EPROBE_DEFER. So I picked 2, because I'm not able to figure out a way to distinguish between a not yet probed panel and the USB-C controller... Any suggestions? Regards, Bjorn
Re: [PATCH v2 00/17] drm: cleanup: Use DRM_MODESET_LOCK_ALL_* helpers where possible
On Fri, Oct 01, 2021 at 10:00:50PM +0300, Ville Syrjälä wrote: > On Fri, Oct 01, 2021 at 02:36:55PM -0400, Sean Paul wrote: > > On Fri, Sep 24, 2021 at 08:43:07AM +0200, Fernando Ramos wrote: > > > Hi all, > > > > > > One of the things in the DRM TODO list ("Documentation/gpu/todo.rst") was > > > to > > > "use DRM_MODESET_LOCAL_ALL_* helpers instead of boilerplate". That's what > > > this > > > patch series is about. > > > > > > You will find two types of changes here: > > > > > > - Replacing "drm_modeset_lock_all_ctx()" (and surrounding boilerplate) > > > with > > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" in the remaining places (as it > > > has > > > already been done in previous commits such as b7ea04d2) > > > > > > - Replacing "drm_modeset_lock_all()" with > > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" > > > in the remaining places (as it has already been done in previous > > > commits > > > such as 57037094) > > > > > > Most of the changes are straight forward, except for a few cases in the > > > "amd" > > > and "i915" drivers where some extra dancing was needed to overcome the > > > limitation that the DRM_MODESET_LOCK_ALL_BEGIN()/END() macros can only be > > > used > > > once inside the same function (the reason being that the macro expansion > > > includes *labels*, and you can not have two labels named the same inside > > > one > > > function) > > > > > > Notice that, even after this patch series, some places remain where > > > "drm_modeset_lock_all()" and "drm_modeset_lock_all_ctx()" are still > > > present, > > > all inside drm core (which makes sense), except for two (in "amd" and > > > "i915") > > > which cannot be replaced due to the way they are being used. > > > > > > Changes in v2: > > > > > > - Fix commit message typo > > > - Use the value returned by DRM_MODESET_LOCK_ALL_END when possible > > > - Split drm/i915 patch into two simpler ones > > > - Remove drm_modeset_(un)lock_all() > > > - Fix build problems in non-x86 platforms > > > > > > Fernando Ramos (17): > > > drm: cleanup: drm_modeset_lock_all_ctx() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/i915: cleanup: drm_modeset_lock_all_ctx() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/msm: cleanup: drm_modeset_lock_all_ctx() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/vmwgfx: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/tegra: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/shmobile: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/radeon: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/omapdrm: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/nouveau: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/msm: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/i915: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/i915: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() part 2 > > > drm/gma500: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm/amd: cleanup: drm_modeset_lock_all() --> > > > DRM_MODESET_LOCK_ALL_BEGIN() > > > drm: cleanup: remove drm_modeset_(un)lock_all() > > > doc: drm: remove TODO entry regarding DRM_MODSET_LOCK_ALL cleanup > > > > > > > Thank you for revising, Fernando! I've pushed the set to drm-misc-next > > (along > > with the necessary drm-tip conflict resolutions). > > Ugh. Did anyone actually review the locking changes this does? > I shot the previous i915 stuff down because the commit messages > did not address any of it. I reviewed the set on 9/17, I didn't see your feedback on that thread. Sean > > -- > Ville Syrjälä > Intel -- Sean Paul, Software Engineer, Google / Chromium OS
Re: [PATCH] drm/brdige: analogix_dp: Grab runtime PM reference for DP-AUX
On Wed, Sep 29, 2021 at 02:41:03PM -0700, Brian Norris wrote: > If the display is not enable()d, then we aren't holding a runtime PM > reference here. Thus, it's easy to accidentally cause a hang, if user > space is poking around at /dev/drm_dp_aux0 at the "wrong" time. > > Let's get the panel and PM state right before trying to talk AUX. > > Fixes: 0d97ad03f422 ("drm/bridge: analogix_dp: Remove duplicated code") > Cc: > Cc: Tomeu Vizoso > Signed-off-by: Brian Norris > --- > > .../gpu/drm/bridge/analogix/analogix_dp_core.c | 17 - > 1 file changed, 16 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > index b7d2e4449cfa..a1b553904b85 100644 > --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c > @@ -1632,8 +1632,23 @@ static ssize_t analogix_dpaux_transfer(struct > drm_dp_aux *aux, > struct drm_dp_aux_msg *msg) > { > struct analogix_dp_device *dp = to_dp(aux); > + int ret, ret2; > > - return analogix_dp_transfer(dp, msg); > + ret = analogix_dp_prepare_panel(dp, true, false); > + if (ret) { > + DRM_DEV_ERROR(dp->dev, "Failed to prepare panel (%d)\n", ret); s/DRM_DEV_ERROR/drm_err/ > + return ret; > + } > + > + pm_runtime_get_sync(dp->dev); > + ret = analogix_dp_transfer(dp, msg); > + pm_runtime_put(dp->dev); > + > + ret2 = analogix_dp_prepare_panel(dp, false, false); > + if (ret2) > + DRM_DEV_ERROR(dp->dev, "Failed to unprepare panel (%d)\n", > ret2); What's the reasoning for not propagating unprepare failures? I feel like that should be fair game. > + > + return ret; > } > > struct analogix_dp_device * > -- > 2.33.0.685.g46640cef36-goog > -- Sean Paul, Software Engineer, Google / Chromium OS
Re: [PATCH 1/2] drm: Add Gamma and Degamma LUT sizes props to drm_crtc to validate.
On Wed, Sep 29, 2021 at 03:39:25PM -0400, Mark Yacoub wrote: > From: Mark Yacoub > > [Why] > 1. drm_atomic_helper_check doesn't check for the LUT sizes of either Gamma > or Degamma props in the new CRTC state, allowing any invalid size to > be passed on. > 2. Each driver has its own LUT size, which could also be different for > legacy users. > > [How] > 1. Create |degamma_lut_size| and |gamma_lut_size| to save the LUT sizes > assigned by the driver when it's initializing its color and CTM > management. > 2. Create drm_atomic_helper_check_crtc which is called by > drm_atomic_helper_check to check the LUT sizes saved in drm_crtc that > they match the sizes in the new CRTC state. > Did you consider extending drm_color_lut_check() with the size checks? > Fixes: igt@kms_color@pipe-A-invalid-gamma-lut-sizes on MTK > Tested on Zork(amdgpu) and Jacuzzi(mediatek) > > Signed-off-by: Mark Yacoub nit: missing a space between name and email > --- > drivers/gpu/drm/drm_atomic_helper.c | 56 + > drivers/gpu/drm/drm_color_mgmt.c| 2 ++ > include/drm/drm_atomic_helper.h | 1 + > include/drm/drm_crtc.h | 11 ++ > 4 files changed, 70 insertions(+) > > diff --git a/drivers/gpu/drm/drm_atomic_helper.c > b/drivers/gpu/drm/drm_atomic_helper.c > index 2c0c6ec928200..265b9747250d1 100644 > --- a/drivers/gpu/drm/drm_atomic_helper.c > +++ b/drivers/gpu/drm/drm_atomic_helper.c > @@ -930,6 +930,58 @@ drm_atomic_helper_check_planes(struct drm_device *dev, > } > EXPORT_SYMBOL(drm_atomic_helper_check_planes); > > +/** > + * drm_atomic_helper_check_planes - validate state object for CRTC changes Ctrl+c/Ctrl+v error here > + * @state: the driver state object > + * > + * Check the CRTC state object such as the Gamma/Degamma LUT sizes if the new Are there missing words between "object" and "such"? > + * state holds them. > + * > + * RETURNS: > + * Zero for success or -errno > + */ > +int drm_atomic_helper_check_crtc(struct drm_atomic_state *state) drm_atomic_helper_check_crtcs to be consistent with drm_atomic_helper_check_planes > +{ > + struct drm_crtc *crtc; > + struct drm_crtc_state *new_crtc_state; > + int i; > + > + for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) { no space before ( > + if (new_crtc_state->gamma_lut) { Perhaps gate these with a check of state->color_mgmt_changed first? > + uint64_t supported_lut_size = crtc->gamma_lut_size; > + uint32_t supported_legacy_lut_size = crtc->gamma_size; > + uint32_t new_state_lut_size = > + drm_color_lut_size(new_crtc_state->gamma_lut); nit: new_state_lut_size and supported_lut_size can be pulled out to top level scope to avoid re-instantiation on each iteration > + > + if (new_state_lut_size != supported_lut_size && > + new_state_lut_size != supported_legacy_lut_size) { According to the docbook, "If drivers support multiple LUT sizes then they should publish the largest size, and sub-sample smaller sized LUTs". So should this check be > instead of != ? > + DRM_DEBUG_DRIVER( drm_dbg_state() is probably more appropriate > + "Invalid Gamma LUT size. Should be %u > (or %u for legacy) but got %u.\n", > + supported_lut_size, > + supported_legacy_lut_size, > + new_state_lut_size); > + return -EINVAL; > + } > + } > + > + if (new_crtc_state->degamma_lut) { > + uint32_t new_state_lut_size = > + drm_color_lut_size(new_crtc_state->degamma_lut); > + uint64_t supported_lut_size = crtc->degamma_lut_size; > + > + if (new_state_lut_size != supported_lut_size) { > + DRM_DEBUG_DRIVER( drm_dbg_state() > + "Invalid Degamma LUT size. Should be %u > but got %u.\n", > + supported_lut_size, new_state_lut_size); > + return -EINVAL; > + } > + } > + } > + > + return 0; > +} > +EXPORT_SYMBOL(drm_atomic_helper_check_crtc); > + > /** > * drm_atomic_helper_check - validate state object > * @dev: DRM device > @@ -975,6 +1027,10 @@ int drm_atomic_helper_check(struct drm_device *dev, > if (ret) > return ret; > > + ret = drm_atomic_helper_check_crtc(state); > + if (ret) > + return ret; > + > if (state->legacy_cursor_update) > state->async_update = !drm_atomic_helper_async_check(dev, > state); > > diff --git a/drivers/gpu/drm/drm_color_mgmt.c > b/drivers/gpu/drm/drm_color_mgmt.c > index bb14f488c8f6c..72a1b
Re: [PATCH 2/2] amd/amdgpu_dm: Verify Gamma and Degamma LUT sizes using DRM Core check
On Wed, Sep 29, 2021 at 03:39:26PM -0400, Mark Yacoub wrote: > From: Mark Yacoub > > [Why] > drm_atomic_helper_check_crtc now verifies both legacy and non-legacy LUT > sizes. There is no need to check it within amdgpu_dm_atomic_check. > > [How] > Remove the local call to verify LUT sizes and use DRM Core function > instead. > > Tested on ChromeOS Zork. > > Signed-off-by: Mark Yacoub > --- > drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 > 1 file changed, 4 insertions(+), 4 deletions(-) > > 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 07adac1a8c42b..96a1d006b777e 100644 > --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c > @@ -10683,6 +10683,10 @@ static int amdgpu_dm_atomic_check(struct drm_device > *dev, > } > } > #endif > + ret = drm_atomic_helper_check_crtc(state); > + if (ret) > + return ret; > + > for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, > new_crtc_state, i) { > dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); > > @@ -10692,10 +10696,6 @@ static int amdgpu_dm_atomic_check(struct drm_device > *dev, > dm_old_crtc_state->dsc_force_changed == false) > continue; > > - ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); >From a quick glance, I think you can now delete this function. It's called from amdgpu_dm_update_crtc_color_mgmt() which is part of the commit, so the lut sizes should have already been checked. If the call from amdgpu_dm_update_crtc_color_mgmt() is not possible to remove, you could replace it with a call to the new helper function. And if _that_ is not possible, please make amdgpu_dm_verify_lut_sizes() static :-) Sean > - if (ret) > - goto fail; > - > if (!new_crtc_state->enable) > continue; > > -- > 2.33.0.685.g46640cef36-goog > -- Sean Paul, Software Engineer, Google / Chromium OS
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
01.10.2021 15:32, Ulf Hansson пишет: >> +static int tegra_clock_sync_pd_state(struct tegra_clk_device *clk_dev) >> +{ >> + unsigned long rate; >> + int ret = 0; >> + >> + mutex_lock(&clk_dev->lock); >> + >> + if (!pm_runtime_status_suspended(clk_dev->dev)) { >> + rate = clk_hw_get_rate(clk_dev->hw); >> + ret = tegra_clock_set_pd_state(clk_dev, rate); > Don't we need to sync the performance state even when the device is > runtime suspended? > > Perhaps the clock, via a child-clock for example, can get > prepared/enabled (hence its device gets runtime resumed) before there > is a clock rate update for it. Then there is no performance state set > for it, right? Or maybe that isn't a problem? > Good catch! Older versions of this patch had a special handling for clk enable/disable. I just forgot to update this function, it's now not a problem to change performance state of a suspended device and it actually needs to be done. I'll correct it, thanks!
[PATCH] drm/msm/a6xx: Serialize GMU communication
From: Rob Clark I've seen some crashes in our crash reporting that *look* like multiple threads stomping on each other while communicating with GMU. So wrap all those paths in a lock. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 3 ++ drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 40 +++ 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index a7c58018959f..8b73f70766a4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) u32 val; int request, ack; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return -EINVAL; @@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { int bit; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return; @@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (!pdev) return -ENODEV; + mutex_init(&gmu->lock); + gmu->dev = &pdev->dev; of_dma_configure(gmu->dev, node, true); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 3c74f64e3126..84bd516f01e8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -44,6 +44,9 @@ struct a6xx_gmu_bo { struct a6xx_gmu { struct device *dev; + /* For serializing communication with the GMU: */ + struct mutex lock; + struct msm_gem_address_space *aspace; void * __iomem mmio; diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index f6a4dbef796b..bd7bdeff5d6f 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -881,7 +881,7 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu) A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) -static int a6xx_hw_init(struct msm_gpu *gpu) +static int hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); @@ -1135,6 +1135,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu) return ret; } +static int a6xx_hw_init(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + int ret; + + mutex_lock(&a6xx_gpu->gmu.lock); + ret = hw_init(gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); + + return ret; +} + static void a6xx_dump(struct msm_gpu *gpu) { DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", @@ -1509,7 +1522,9 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) trace_msm_gpu_resume(0); + mutex_lock(&a6xx_gpu->gmu.lock); ret = a6xx_gmu_resume(a6xx_gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); if (ret) return ret; @@ -1532,7 +1547,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) msm_devfreq_suspend(gpu); + mutex_lock(&a6xx_gpu->gmu.lock); ret = a6xx_gmu_stop(a6xx_gpu); + mutex_unlock(&a6xx_gpu->gmu.lock); if (ret) return ret; @@ -1547,18 +1564,19 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); - static DEFINE_MUTEX(perfcounter_oob); - mutex_lock(&perfcounter_oob); + mutex_lock(&a6xx_gpu->gmu.lock); /* Force the GPU power on so we can read this register */ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, - REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); + REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); - mutex_unlock(&perfcounter_oob); + + mutex_unlock(&a6xx_gpu->gmu.lock); + return 0; } @@ -1622,6 +1640,16 @@ static unsigned long a6xx_gpu_busy(struct msm_gpu *gpu) return (unsigned long)busy_time; } +void a6xx_gpu_set_freq(struct msm_gpu *gpu, struct dev_pm_opp *opp) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + + mutex_lock(&a6xx_gpu->gmu.lock); + a6xx_gmu_set_freq(gpu, opp); + mutex_unlock(&a6xx_gpu->gmu.lock); +} + static struct msm_gem_address_space * a6xx_create_address_space(struct msm_gpu *gpu, struct platfo
Re: [PATCH v13 02/35] soc/tegra: Add devm_tegra_core_dev_init_opp_table_common()
01.10.2021 15:50, Ulf Hansson пишет: > On Mon, 27 Sept 2021 at 00:42, Dmitry Osipenko wrote: >> >> Only couple drivers need to get the -ENODEV error code and majority of >> drivers need to explicitly initialize the performance state. Add new >> common helper which sets up OPP table for these drivers. >> >> Signed-off-by: Dmitry Osipenko >> --- >> include/soc/tegra/common.h | 24 >> 1 file changed, 24 insertions(+) >> >> diff --git a/include/soc/tegra/common.h b/include/soc/tegra/common.h >> index af41ad80ec21..5b4a042f60fb 100644 >> --- a/include/soc/tegra/common.h >> +++ b/include/soc/tegra/common.h >> @@ -39,4 +39,28 @@ devm_tegra_core_dev_init_opp_table(struct device *dev, >> } >> #endif >> >> +/* >> + * This function should be invoked with the enabled runtime PM of the device >> + * in order to initialize performance state properly. Most of Tegra devices >> + * are assumed to be suspended at a probe time and GENPD require RPM to be >> + * enabled to set up the rpm-resume state, otherwise device is active and >> + * performance state is applied immediately. Note that it will initialize >> + * OPP bandwidth if it's wired in a device-tree for this device, which is >> + * undesirable for a suspended device. >> + */ >> +static inline int >> +devm_tegra_core_dev_init_opp_table_common(struct device *dev) >> +{ >> + struct tegra_core_opp_params opp_params = {}; >> + int err; >> + >> + opp_params.init_state = true; >> + >> + err = devm_tegra_core_dev_init_opp_table(dev, &opp_params); >> + if (err != -ENODEV) >> + return err; >> + >> + return 0; >> +} > > Just want to share a few thoughts around these functions. > > So, I assume it's fine to call > devm_tegra_core_dev_init_opp_table_common() or > devm_tegra_core_dev_init_opp_table() from consumer drivers during > ->probe(), as long as those drivers are tegra specific, which I assume > all are in the series!? That is correct, all drivers are tegra-specific in this series. External devices are attached to the internal SoC devices and this series is about the SoC power management. > My point is, a cross SoC consumer driver that needs to initiate OPP > tables can get rather messy, if it would need to make one specific > function call per SoC. > > That said, I hope we can tackle this as a separate/future problem, so > the series can get merged as is. Yes, as we already have seen, it's not an easy problem to make PD core to handle it in a generic way. If there will be a similar demand from other SoCs, then we may try to solve that problem again.
Re: [bug report] drm/msm: Add SDM845 DPU support
Hey Dan, Thanks for the heads up, will take care of it. On 2021-10-01 05:28, Dan Carpenter wrote: Hello Jeykumar Sankaran, The patch 25fdd5933e4c: "drm/msm: Add SDM845 DPU support" from Jun 27, 2018, leads to the following Smatch static checker warning: drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c:1679 dpu_plane_init() warn: '&pdpu->mplane_list' not removed from list drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 1567 struct drm_plane *dpu_plane_init(struct drm_device *dev, 1568 uint32_t pipe, enum drm_plane_type type, 1569 unsigned long possible_crtcs, u32 master_plane_id) 1570 { 1571 struct drm_plane *plane = NULL, *master_plane = NULL; 1572 const uint32_t *format_list; 1573 struct dpu_plane *pdpu; 1574 struct msm_drm_private *priv = dev->dev_private; 1575 struct dpu_kms *kms = to_dpu_kms(priv->kms); 1576 int zpos_max = DPU_ZPOS_MAX; 1577 uint32_t num_formats; 1578 int ret = -EINVAL; 1579 1580 /* create and zero local structure */ 1581 pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL); 1582 if (!pdpu) { 1583 DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe); 1584 ret = -ENOMEM; 1585 return ERR_PTR(ret); 1586 } 1587 1588 /* cache local stuff for later */ 1589 plane = &pdpu->base; 1590 pdpu->pipe = pipe; 1591 pdpu->is_virtual = (master_plane_id != 0); 1592 INIT_LIST_HEAD(&pdpu->mplane_list); 1593 master_plane = drm_plane_find(dev, NULL, master_plane_id); 1594 if (master_plane) { 1595 struct dpu_plane *mpdpu = to_dpu_plane(master_plane); 1596 1597 list_add_tail(&pdpu->mplane_list, &mpdpu->mplane_list); ^ This is not removed from the list in the error handling code so it will lead to a Use After Free. 1598 } 1599 1600 /* initialize underlying h/w driver */ 1601 pdpu->pipe_hw = dpu_hw_sspp_init(pipe, kms->mmio, kms->catalog, 1602 master_plane_id != 0); 1603 if (IS_ERR(pdpu->pipe_hw)) { 1604 DPU_ERROR("[%u]SSPP init failed\n", pipe); 1605 ret = PTR_ERR(pdpu->pipe_hw); 1606 goto clean_plane; 1607 } else if (!pdpu->pipe_hw->cap || !pdpu->pipe_hw->cap->sblk) { 1608 DPU_ERROR("[%u]SSPP init returned invalid cfg\n", pipe); 1609 goto clean_sspp; 1610 } 1611 1612 /* cache features mask for later */ 1613 pdpu->features = pdpu->pipe_hw->cap->features; 1614 pdpu->pipe_sblk = pdpu->pipe_hw->cap->sblk; 1615 if (!pdpu->pipe_sblk) { 1616 DPU_ERROR("[%u]invalid sblk\n", pipe); 1617 goto clean_sspp; 1618 } 1619 1620 if (pdpu->is_virtual) { 1621 format_list = pdpu->pipe_sblk->virt_format_list; 1622 num_formats = pdpu->pipe_sblk->virt_num_formats; 1623 } 1624 else { 1625 format_list = pdpu->pipe_sblk->format_list; 1626 num_formats = pdpu->pipe_sblk->num_formats; 1627 } 1628 1629 ret = drm_universal_plane_init(dev, plane, 0xff, &dpu_plane_funcs, 1630 format_list, num_formats, 1631 supported_format_modifiers, type, NULL); 1632 if (ret) 1633 goto clean_sspp; 1634 1635 pdpu->catalog = kms->catalog; 1636 1637 if (kms->catalog->mixer_count && 1638 kms->catalog->mixer[0].sblk->maxblendstages) { 1639 zpos_max = kms->catalog->mixer[0].sblk->maxblendstages - 1; 1640 if (zpos_max > DPU_STAGE_MAX - DPU_STAGE_0 - 1) 1641 zpos_max = DPU_STAGE_MAX - DPU_STAGE_0 - 1; 1642 } 1643 1644 ret = drm_plane_create_zpos_property(plane, 0, 0, zpos_max); 1645 if (ret) 1646 DPU_ERROR("failed to install zpos property, rc = %d\n", ret); 1647 1648 drm_plane_create_alpha_property(plane); 1649 drm_plane_create_blend_mode_property(plane, 1650 BIT(DRM_MODE_BLEND_PIXEL_NONE) | 1651 BIT(DRM_MODE_BLEND_PREMULTI) | 1652 BIT(DRM_MODE_BLEND_COVERAGE)); 1653 1654 drm_plane_create_rotation_property(plane, 1655 DRM_MODE_ROTATE_0, 1656 DRM_MODE_ROTATE_0 | 1657 DRM_MODE_ROTATE_180 |
Re: [bug report] drm/msm: Add SDM845 DPU support
Hey Dan, Thanks for the report, will take care of it. On 2021-10-01 06:50, Dan Carpenter wrote: On Fri, Oct 01, 2021 at 04:49:12PM +0300, Dan Carpenter wrote: Hello Jeykumar Sankaran, This is a semi-automatic email about new static checker warnings. The patch 25fdd5933e4c: "drm/msm: Add SDM845 DPU support" from Jun 27, 2018, leads to the following Smatch complaint: drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c:422 _dpu_hw_sspp_setup_scaler3() warn: variable dereferenced before check 'ctx->cap->sblk' (see line 421) drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 420 (void)pe; ^ You should file a bug report with your compiler devs instead of adding these sorts of statements to your code. This function is used as a function pointer so unused parameters are normal. 421 if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, &idx) || !sspp The _sspp_subblk_offset() dereferenced "ctx" before it is checked and then it also derefereces "ctx->cap->sblk" without checking. 422 || !scaler3_cfg || !ctx || !ctx->cap || !ctx->cap->sblk) So these will have already crashed before we reach this point. Same thing later as well. drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c:591 dpu_hw_sspp_setup_creq_lut() warn: variable dereferenced before check 'ctx->cap' (see line 588) regards, dan carpenter Best, Jessica Zhang
Re: [PATCH v3 12/14] dt-bindings: msm/dp: Add bindings for HDCP registers
On Fri, 01 Oct 2021 11:11:41 -0400, Sean Paul wrote: > From: Sean Paul > > This patch adds the bindings for the MSM DisplayPort HDCP registers > which are required to write the HDCP key into the display controller as > well as the registers to enable HDCP authentication/key > exchange/encryption. > > We'll use a new compatible string for this since the fields are optional. > > Cc: Rob Herring > Cc: Stephen Boyd > Signed-off-by: Sean Paul > Link: > https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-13-s...@poorly.run > #v1 > Link: > https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-13-s...@poorly.run > #v2 > > Changes in v2: > -Drop register range names (Stephen) > -Fix yaml errors (Rob) > Changes in v3: > -Add new compatible string for dp-hdcp > -Add descriptions to reg > -Add minItems/maxItems to reg > -Make reg depend on the new hdcp compatible string > --- > > Disclaimer: I really don't know if this is the right way to approach > this. I tried using examples from other bindings, but feedback would be > very much welcome on how I could add the optional register ranges. > > > .../bindings/display/msm/dp-controller.yaml | 34 --- > 1 file changed, 30 insertions(+), 4 deletions(-) > My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13): yamllint warnings/errors: dtschema/dtc warnings/errors: /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/msm/dp-controller.example.dt.yaml: example-0: displayport-controller@ae9:reg:0: [0, 183042048, 0, 5120] is too long From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/msm/dp-controller.example.dt.yaml: example-0: displayport-controller@ae9:reg:1: [0, 183308288, 0, 372] is too long From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml /builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/msm/dp-controller.example.dt.yaml: example-0: displayport-controller@ae9:reg:2: [0, 183373824, 0, 44] is too long From schema: /usr/local/lib/python3.8/dist-packages/dtschema/schemas/reg.yaml doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/patch/1535361 This check can fail if there are any dependencies. The base for a patch series is generally the most recent rc1. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit.
Re: [PATCH v2 00/17] drm: cleanup: Use DRM_MODESET_LOCK_ALL_* helpers where possible
On Fri, Oct 01, 2021 at 02:36:55PM -0400, Sean Paul wrote: > On Fri, Sep 24, 2021 at 08:43:07AM +0200, Fernando Ramos wrote: > > Hi all, > > > > One of the things in the DRM TODO list ("Documentation/gpu/todo.rst") was to > > "use DRM_MODESET_LOCAL_ALL_* helpers instead of boilerplate". That's what > > this > > patch series is about. > > > > You will find two types of changes here: > > > > - Replacing "drm_modeset_lock_all_ctx()" (and surrounding boilerplate) > > with > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" in the remaining places (as it has > > already been done in previous commits such as b7ea04d2) > > > > - Replacing "drm_modeset_lock_all()" with > > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" > > in the remaining places (as it has already been done in previous commits > > such as 57037094) > > > > Most of the changes are straight forward, except for a few cases in the > > "amd" > > and "i915" drivers where some extra dancing was needed to overcome the > > limitation that the DRM_MODESET_LOCK_ALL_BEGIN()/END() macros can only be > > used > > once inside the same function (the reason being that the macro expansion > > includes *labels*, and you can not have two labels named the same inside one > > function) > > > > Notice that, even after this patch series, some places remain where > > "drm_modeset_lock_all()" and "drm_modeset_lock_all_ctx()" are still present, > > all inside drm core (which makes sense), except for two (in "amd" and > > "i915") > > which cannot be replaced due to the way they are being used. > > > > Changes in v2: > > > > - Fix commit message typo > > - Use the value returned by DRM_MODESET_LOCK_ALL_END when possible > > - Split drm/i915 patch into two simpler ones > > - Remove drm_modeset_(un)lock_all() > > - Fix build problems in non-x86 platforms > > > > Fernando Ramos (17): > > drm: cleanup: drm_modeset_lock_all_ctx() --> DRM_MODESET_LOCK_ALL_BEGIN() > > drm/i915: cleanup: drm_modeset_lock_all_ctx() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/msm: cleanup: drm_modeset_lock_all_ctx() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > drm/vmwgfx: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > drm/tegra: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/shmobile: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/radeon: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/omapdrm: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/nouveau: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/msm: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > drm/i915: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > drm/i915: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() part 2 > > drm/gma500: cleanup: drm_modeset_lock_all() --> > > DRM_MODESET_LOCK_ALL_BEGIN() > > drm/amd: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > > drm: cleanup: remove drm_modeset_(un)lock_all() > > doc: drm: remove TODO entry regarding DRM_MODSET_LOCK_ALL cleanup > > > > Thank you for revising, Fernando! I've pushed the set to drm-misc-next (along > with the necessary drm-tip conflict resolutions). Ugh. Did anyone actually review the locking changes this does? I shot the previous i915 stuff down because the commit messages did not address any of it. -- Ville Syrjälä Intel
Re: [bug report] drm/msm/dp: add debugfs support to DP driver
Hey Dan, Thanks for the heads up, will take care of it. On 2021-10-01 06:59, Dan Carpenter wrote: Hello Abhinav Kumar, The patch d11a93690df7: "drm/msm/dp: add debugfs support to DP driver" from Sep 12, 2020, leads to the following Smatch static checker warning: drivers/gpu/drm/msm/dp/dp_debug.c:194 dp_debug_read_info() warn: userbuf overflow? is 'len' <= 'count' drivers/gpu/drm/msm/dp/dp_debug.c 46 static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, 47 size_t count, loff_t *ppos) 48 { 49 struct dp_debug_private *debug = file->private_data; 50 char *buf; 51 u32 len = 0, rc = 0; 52 u64 lclk = 0; 53 u32 max_size = SZ_4K; 54 u32 link_params_rate; 55 struct drm_display_mode *drm_mode; 56 57 if (!debug) 58 return -ENODEV; 59 60 if (*ppos) 61 return 0; 62 63 buf = kzalloc(SZ_4K, GFP_KERNEL); 64 if (!buf) 65 return -ENOMEM; 66 67 drm_mode = &debug->panel->dp_mode.drm_mode; 68 69 rc = snprintf(buf + len, max_size, "\tname = %s\n", DEBUG_NAME); 70 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 71 goto error; 72 73 rc = snprintf(buf + len, max_size, 74 "\tdp_panel\n\t\tmax_pclk_khz = %d\n", 75 debug->panel->max_pclk_khz); 76 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 77 goto error; 78 79 rc = snprintf(buf + len, max_size, 80 "\tdrm_dp_link\n\t\trate = %u\n", 81 debug->panel->link_info.rate); 82 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 83 goto error; 84 85 rc = snprintf(buf + len, max_size, 86 "\t\tnum_lanes = %u\n", 87 debug->panel->link_info.num_lanes); 88 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 89 goto error; 90 91 rc = snprintf(buf + len, max_size, 92 "\t\tcapabilities = %lu\n", 93 debug->panel->link_info.capabilities); 94 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 95 goto error; 96 97 rc = snprintf(buf + len, max_size, 98 "\tdp_panel_info:\n\t\tactive = %dx%d\n", 99 drm_mode->hdisplay, 100 drm_mode->vdisplay); 101 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 102 goto error; 103 104 rc = snprintf(buf + len, max_size, 105 "\t\tback_porch = %dx%d\n", 106 drm_mode->htotal - drm_mode->hsync_end, 107 drm_mode->vtotal - drm_mode->vsync_end); 108 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 109 goto error; 110 111 rc = snprintf(buf + len, max_size, 112 "\t\tfront_porch = %dx%d\n", 113 drm_mode->hsync_start - drm_mode->hdisplay, 114 drm_mode->vsync_start - drm_mode->vdisplay); 115 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 116 goto error; 117 118 rc = snprintf(buf + len, max_size, 119 "\t\tsync_width = %dx%d\n", 120 drm_mode->hsync_end - drm_mode->hsync_start, 121 drm_mode->vsync_end - drm_mode->vsync_start); 122 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 123 goto error; 124 125 rc = snprintf(buf + len, max_size, 126 "\t\tactive_low = %dx%d\n", 127 debug->panel->dp_mode.h_active_low, 128 debug->panel->dp_mode.v_active_low); 129 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 130 goto error; 131 132 rc = snprintf(buf + len, max_size, 133 "\t\th_skew = %d\n", 134 drm_mode->hskew); 135 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 136 goto error; 137 138 rc = snprintf(buf + len, max_size, 139 "\t\trefresh rate = %d\n", 140 drm_mode_vrefresh(drm_mode)); 141 if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) 142 goto error; 143 144 rc = snprint
Re: [PATCH v13 13/35] drm/tegra: gr2d: Support generic power domain and runtime PM
01.10.2021 17:55, Ulf Hansson пишет: > On Fri, 1 Oct 2021 at 16:29, Dmitry Osipenko wrote: >> >> 01.10.2021 16:39, Ulf Hansson пишет: >>> On Mon, 27 Sept 2021 at 00:42, Dmitry Osipenko wrote: Add runtime power management and support generic power domains. Tested-by: Peter Geis # Ouya T30 Tested-by: Paul Fertser # PAZ00 T20 Tested-by: Nicolas Chauvet # PAZ00 T20 and TK1 T124 Tested-by: Matt Merhar # Ouya T30 Signed-off-by: Dmitry Osipenko --- drivers/gpu/drm/tegra/gr2d.c | 155 +-- >>> >>> [...] >>> static int gr2d_remove(struct platform_device *pdev) @@ -259,15 +312,101 @@ static int gr2d_remove(struct platform_device *pdev) return err; } + pm_runtime_dont_use_autosuspend(&pdev->dev); + pm_runtime_disable(&pdev->dev); >>> >>> There is no guarantee that the ->runtime_suspend() has been invoked >>> here, which means that clock may be left prepared/enabled beyond this >>> point. >>> >>> I suggest you call pm_runtime_force_suspend(), instead of >>> pm_runtime_disable(), to make sure that gets done. >> >> The pm_runtime_disable() performs the final synchronization, please see [1]. >> >> [1] >> https://elixir.bootlin.com/linux/v5.15-rc3/source/drivers/base/power/runtime.c#L1412 > > pm_runtime_disable() end up calling _pm_runtime_barrier(), which calls > cancel_work_sync() if dev->power.request_pending has been set. > > If the work that was punted to the pm_wq in rpm_idle() has not been > started yet, we end up just canceling it. In other words, there are no > guarantees it runs to completion. You're right. Although, in a case of this particular patch, the syncing is actually implicitly done by pm_runtime_dont_use_autosuspend(). But for drivers which don't use auto-suspend, there is no sync. This looks like a disaster, it's a very common pattern for drivers to 'put+disable'. > Moreover, use space may have bumped the usage count via sysfs for the > device (pm_runtime_forbid()) to keep the device runtime resumed. Right, this is also a disaster in a case of driver removal. >> Calling pm_runtime_force_suspend() isn't correct because each 'enable' >> must have the corresponding 'disable'. Hence there is no problem here. > > pm_runtime_force_suspend() calls pm_runtime_disable(), so I think that > should be fine. No? [adding Rafael] Rafael, could you please explain how drivers are supposed to properly suspend and disable RPM to cut off power and reset state that was altered by the driver's resume callback? What we're missing? Is Ulf's suggestion acceptable? The RPM state of a device is getting reset on driver's removal, hence all refcounts that were bumped by the rpm-resume callback of the device driver will be screwed up if device is kept resumed after removal. I just verified that it's true in practice.
Re: [bug report] drm/msm: dsi: Handle dual-channel for 6G as well
Hey Dan, Thanks for the report, will take care of it. On 2021-10-01 05:31, Dan Carpenter wrote: Hello Sean Paul, The patch a6bcddbc2ee1: "drm/msm: dsi: Handle dual-channel for 6G as well" from Jul 25, 2018, leads to the following Smatch static checker warning: drivers/gpu/drm/msm/dsi/dsi_host.c:729 dsi_calc_clk_rate_6g() warn: wrong type for 'msm_host->esc_clk_rate' (should be 'ulong') drivers/gpu/drm/msm/dsi/dsi_host.c 721 int dsi_calc_clk_rate_6g(struct msm_dsi_host *msm_host, bool is_bonded_dsi) 722 { 723 if (!msm_host->mode) { 724 pr_err("%s: mode not set\n", __func__); 725 return -EINVAL; 726 } 727 728 dsi_calc_pclk(msm_host, is_bonded_dsi); --> 729 msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk); ^^ I don't know why Smatch is suddenly warning about ancient msm code, but clock rates should be unsigned long. (I don't remember why). 730 return 0; 731 } regards, dan carpenter Thanks, Jessica Zhang
Re: linux-next: Tree for Oct 1 [drivers/gpu/drm/amd/amdgpu/amdgpu.ko]
On 10/1/21 12:09 AM, Stephen Rothwell wrote: Hi all, News: there will be no linux-next release on Monday. Changes since 20210930: on i386: ERROR: modpost: "dm_ip_block" [drivers/gpu/drm/amd/amdgpu/amdgpu.ko] undefined! Full randconfig file is attached. -- ~Randy config-r5146.gz Description: application/gzip
Re: [PATCH v2 00/17] drm: cleanup: Use DRM_MODESET_LOCK_ALL_* helpers where possible
On Fri, Sep 24, 2021 at 08:43:07AM +0200, Fernando Ramos wrote: > Hi all, > > One of the things in the DRM TODO list ("Documentation/gpu/todo.rst") was to > "use DRM_MODESET_LOCAL_ALL_* helpers instead of boilerplate". That's what this > patch series is about. > > You will find two types of changes here: > > - Replacing "drm_modeset_lock_all_ctx()" (and surrounding boilerplate) with > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" in the remaining places (as it has > already been done in previous commits such as b7ea04d2) > > - Replacing "drm_modeset_lock_all()" with > "DRM_MODESET_LOCK_ALL_BEGIN()/END()" > in the remaining places (as it has already been done in previous commits > such as 57037094) > > Most of the changes are straight forward, except for a few cases in the "amd" > and "i915" drivers where some extra dancing was needed to overcome the > limitation that the DRM_MODESET_LOCK_ALL_BEGIN()/END() macros can only be used > once inside the same function (the reason being that the macro expansion > includes *labels*, and you can not have two labels named the same inside one > function) > > Notice that, even after this patch series, some places remain where > "drm_modeset_lock_all()" and "drm_modeset_lock_all_ctx()" are still present, > all inside drm core (which makes sense), except for two (in "amd" and "i915") > which cannot be replaced due to the way they are being used. > > Changes in v2: > > - Fix commit message typo > - Use the value returned by DRM_MODESET_LOCK_ALL_END when possible > - Split drm/i915 patch into two simpler ones > - Remove drm_modeset_(un)lock_all() > - Fix build problems in non-x86 platforms > > Fernando Ramos (17): > drm: cleanup: drm_modeset_lock_all_ctx() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/i915: cleanup: drm_modeset_lock_all_ctx() --> > DRM_MODESET_LOCK_ALL_BEGIN() > drm/msm: cleanup: drm_modeset_lock_all_ctx() --> > DRM_MODESET_LOCK_ALL_BEGIN() > drm: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/vmwgfx: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/tegra: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/shmobile: cleanup: drm_modeset_lock_all() --> > DRM_MODESET_LOCK_ALL_BEGIN() > drm/radeon: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/omapdrm: cleanup: drm_modeset_lock_all() --> > DRM_MODESET_LOCK_ALL_BEGIN() > drm/nouveau: cleanup: drm_modeset_lock_all() --> > DRM_MODESET_LOCK_ALL_BEGIN() > drm/msm: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/i915: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/i915: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > part 2 > drm/gma500: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm/amd: cleanup: drm_modeset_lock_all() --> DRM_MODESET_LOCK_ALL_BEGIN() > drm: cleanup: remove drm_modeset_(un)lock_all() > doc: drm: remove TODO entry regarding DRM_MODSET_LOCK_ALL cleanup > Thank you for revising, Fernando! I've pushed the set to drm-misc-next (along with the necessary drm-tip conflict resolutions). Sean > Documentation/gpu/todo.rst| 17 > Documentation/locking/ww-mutex-design.rst | 2 +- > drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 21 +++-- > .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 50 +- > .../amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 25 ++--- > drivers/gpu/drm/drm_client_modeset.c | 14 ++- > drivers/gpu/drm/drm_crtc_helper.c | 18 ++-- > drivers/gpu/drm/drm_fb_helper.c | 10 +- > drivers/gpu/drm/drm_framebuffer.c | 6 +- > drivers/gpu/drm/drm_modeset_lock.c| 94 +-- > drivers/gpu/drm/gma500/psb_device.c | 18 ++-- > drivers/gpu/drm/i915/display/intel_audio.c| 16 ++-- > drivers/gpu/drm/i915/display/intel_display.c | 23 ++--- > .../drm/i915/display/intel_display_debugfs.c | 46 + > drivers/gpu/drm/i915/display/intel_overlay.c | 46 - > drivers/gpu/drm/i915/display/intel_pipe_crc.c | 7 +- > drivers/gpu/drm/i915/i915_drv.c | 13 ++- > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 10 +- > .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 12 +-- > drivers/gpu/drm/nouveau/dispnv50/disp.c | 15 ++- > drivers/gpu/drm/omapdrm/omap_fb.c | 9 +- > drivers/gpu/drm/radeon/radeon_device.c| 21 +++-- > drivers/gpu/drm/radeon/radeon_dp_mst.c| 10 +- > drivers/gpu/drm/shmobile/shmob_drm_drv.c | 6 +- > drivers/gpu/drm/tegra/dsi.c | 6 +- > drivers/gpu/drm/tegra/hdmi.c | 6 +- > drivers/gpu/drm/tegra/sor.c | 11 ++- > drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 11 ++- > drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 12 ++- > include/drm/drm_modeset_lock.h| 2 - > 30 files changed, 265 ins
Re: [PATCH] drm/msm: Fix null pointer dereference on pointer edp
On 29/09/2021 15:18, Colin King wrote: From: Colin Ian King The initialization of pointer dev dereferences pointer edp before edp is null checked, so there is a potential null pointer deference issue. Fix this by only dereferencing edp after edp has been null checked. Addresses-Coverity: ("Dereference before null check") Fixes: ab5b0107ccf3 ("drm/msm: Initial add eDP support in msm drm driver (v5)") Signed-off-by: Colin Ian King Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/edp/edp_ctrl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c index 4fb397ee7c84..fe1366b4c49f 100644 --- a/drivers/gpu/drm/msm/edp/edp_ctrl.c +++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c @@ -1116,7 +1116,7 @@ void msm_edp_ctrl_power(struct edp_ctrl *ctrl, bool on) int msm_edp_ctrl_init(struct msm_edp *edp) { struct edp_ctrl *ctrl = NULL; - struct device *dev = &edp->pdev->dev; + struct device *dev; int ret; if (!edp) { @@ -1124,6 +1124,7 @@ int msm_edp_ctrl_init(struct msm_edp *edp) return -EINVAL; } + dev = &edp->pdev->dev; ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); if (!ctrl) return -ENOMEM; -- With best wishes Dmitry
Re: [PATCH] drm/i915: Use fixed offset for PTEs location
On Thu, Sep 30, 2021 at 03:01:19PM -0700, Matt Roper wrote: > On Sun, Sep 26, 2021 at 10:10:05PM +0200, Michal Wajdeczko wrote: > > We assumed that for all modern GENs the PTEs and register space are > > split in the GTTMMADR BAR, but while it is true, we should rather use > > fixed offset as it is defined in the specification. > > > > Bspec: 4409, 4457, 4604, 11181, 9027, 13246, 13321, 44980 > > > > Signed-off-by: Michal Wajdeczko > > Cc: CQ Tang > > Cc: Matt Roper > > Matches the descriptions on all the various bspec pages. > > Reviewed-by: Matt Roper And applied to drm-intel-gt-next. Thanks for the patch. Matt > > > --- > > drivers/gpu/drm/i915/gt/intel_ggtt.c | 19 +-- > > 1 file changed, 17 insertions(+), 2 deletions(-) > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c > > b/drivers/gpu/drm/i915/gt/intel_ggtt.c > > index ba7c7ed89fa8..f17383e76eb7 100644 > > --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c > > +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c > > @@ -813,6 +813,21 @@ static unsigned int chv_get_total_gtt_size(u16 > > gmch_ctrl) > > return 0; > > } > > > > +static unsigned int gen6_gttmmadr_size(struct drm_i915_private *i915) > > +{ > > + /* > > +* GEN6: GTTMMADR size is 4MB and GTTADR starts at 2MB offset > > +* GEN8: GTTMMADR size is 16MB and GTTADR starts at 8MB offset > > +*/ > > + GEM_BUG_ON(GRAPHICS_VER(i915) < 6); > > + return (GRAPHICS_VER(i915) < 8) ? SZ_4M : SZ_16M; > > +} > > + > > +static unsigned int gen6_gttadr_offset(struct drm_i915_private *i915) > > +{ > > + return gen6_gttmmadr_size(i915) / 2; > > +} > > + > > static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) > > { > > struct drm_i915_private *i915 = ggtt->vm.i915; > > @@ -821,8 +836,8 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, > > u64 size) > > u32 pte_flags; > > int ret; > > > > - /* For Modern GENs the PTEs and register space are split in the BAR */ > > - phys_addr = pci_resource_start(pdev, 0) + pci_resource_len(pdev, 0) / 2; > > + GEM_WARN_ON(pci_resource_len(pdev, 0) != gen6_gttmmadr_size(i915)); > > + phys_addr = pci_resource_start(pdev, 0) + gen6_gttadr_offset(i915); > > > > /* > > * On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range > > -- > > 2.25.1 > > > > -- > Matt Roper > Graphics Software Engineer > VTT-OSGC Platform Enablement > Intel Corporation > (916) 356-2795 -- Matt Roper Graphics Software Engineer VTT-OSGC Platform Enablement Intel Corporation (916) 356-2795
Re: [PATCH v2 3/3] drm/bridge: ti-sn65dsi86: Add NO_CONNECTOR support
Hi, On Thu, Sep 23, 2021 at 7:26 PM Laurent Pinchart wrote: > > > > > err_conn_init: > > > > drm_dp_aux_unregister(&pdata->aux); > > > > return ret; > > > > @@ -792,9 +790,30 @@ static void ti_sn_bridge_set_dsi_rate(struct > > > > ti_sn65dsi86 *pdata) > > > > regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val); > > > > } > > > > > > > > +/* > > > > + * Find the connector and fish out the bpc from display_info. It would > > > > + * be nice if we could get this instead from drm_bridge_state, but that > > > > + * doesn't yet appear to be the case. > > > > > > You already have a bus format in the bridge state, from which you can > > > derive the bpp. Could you give it a try ? > > > > Possibly the bridge should be converted to ->atomic_enable(), etc.. > > I'll leave that for another time > > It should be fairly straightforward, and would avoid the hack below. Given this point of controversy, my inclination is to wait and not apply this patch now. I don't think there's anything urgent here, right? Worst case eventually Laurent might pick it up in his patch series? At least we know it will work with the MSM driver once patch #1 lands. :-) -Doug
Re: [RFC] drm/msm/a6xx: Serialize GMU communication
On 01/10/2021 21:05, Rob Clark wrote: On Fri, Oct 1, 2021 at 10:39 AM Dmitry Baryshkov wrote: On 27/09/2021 21:03, Rob Clark wrote: From: Rob Clark I've seen some crashes in our crash reporting that *look* like multiple threads stomping on each other while communicating with GMU. So wrap all those paths in a lock. Signed-off-by: Rob Clark --- Are we allowed to use c99/gnu99 yet? drivers/gpu/drm/msm/Makefile | 2 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 9 + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 50 --- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 904535eda0c4..57283bbad3f0 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -ccflags-y := -I $(srctree)/$(src) +ccflags-y := -I $(srctree)/$(src) -std=gnu99 ccflags-y += -I $(srctree)/$(src)/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -I $(srctree)/$(src)/dsi ccflags-$(CONFIG_DRM_MSM_DP) += -I $(srctree)/$(src)/dp diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index a7c58018959f..8b73f70766a4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) u32 val; int request, ack; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return -EINVAL; @@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { int bit; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return; @@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (!pdev) return -ENODEV; + mutex_init(&gmu->lock); + gmu->dev = &pdev->dev; of_dma_configure(gmu->dev, node, true); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 3c74f64e3126..f05a00c0afd0 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -44,6 +44,9 @@ struct a6xx_gmu_bo { struct a6xx_gmu { struct device *dev; + /* For serializing communication with the GMU: */ + struct mutex lock; + struct msm_gem_address_space *aspace; void * __iomem mmio; @@ -88,6 +91,12 @@ struct a6xx_gmu { bool legacy; /* a618 or a630 */ }; +/* Helper macro for serializing GMU access: */ +#define with_gmu_lock(gmu) \ + for (bool done = ({ mutex_lock(&(gmu)->lock); false; }); \ + !done; \ + done = ({ mutex_unlock(&(gmu)->lock); true; })) The intent is good, but I'm not sure this kind of syntax sugar would be a good approach. What about calling lock/unlock explicitly, like we typically do? Then we won't have to use c99. Yeah, I was planning to resend without the sugar.. but it was a good excuse to bring up c99. Ie. I want c99 regardless ;-) (The sugar was useful initially before I'd sorted thru all the code paths and settled on using a mutex vs spinlock) We can always have GMU_LOCK/GMU_UNLOCK macros. BR, -R + static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) { return msm_readl(gmu->mmio + (offset << 2)); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index f6a4dbef796b..5e1ae3df42ba 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -881,7 +881,7 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu) A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) -static int a6xx_hw_init(struct msm_gpu *gpu) +static int hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); @@ -1135,6 +1135,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu) return ret; } +static int a6xx_hw_init(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + int ret; + + with_gmu_lock(&a6xx_gpu->gmu) { + ret = hw_init(gpu); + } + + return ret; +} + static void a6xx_dump(struct msm_gpu *gpu) { DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", @@ -1509,7 +1522,9 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) trace_msm_gpu_resume(0); - ret = a6xx_gmu_resume(a6xx_gpu); + with_gmu_lock(&a6xx_gpu->gmu) { + ret = a6xx_gmu_resume(a6xx_gpu); + } if (ret) return ret; @@ -1532,7 +1547,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) msm_devfr
Re: [PATCH v2 2/3] drm/bridge: ti-sn65dsi86: Implement bridge->mode_valid()
Hi, On Wed, Sep 22, 2021 at 5:31 PM Laurent Pinchart wrote: > > Hi Rob, > > Thank you for the patch. > > On Mon, Sep 20, 2021 at 03:57:59PM -0700, Rob Clark wrote: > > From: Rob Clark > > > > For the brave new world of bridges not creating their own connectors, we > > need to implement the max clock limitation via bridge->mode_valid() > > instead of connector->mode_valid(). > > > > v2: Drop unneeded connector->mode_valid() > > > > Signed-off-by: Rob Clark > > Reviewed-by: Douglas Anderson > > Reviewed-by: Laurent Pinchart > > > --- > > drivers/gpu/drm/bridge/ti-sn65dsi86.c | 25 + > > 1 file changed, 13 insertions(+), 12 deletions(-) There's no reason to wait on this patch. Landed to drm-misc-next. 77d40e0176a5 drm/bridge: ti-sn65dsi86: Implement bridge->mode_valid() -Doug
Re: [RFC] drm/msm/a6xx: Serialize GMU communication
On Fri, Oct 1, 2021 at 10:39 AM Dmitry Baryshkov wrote: > > On 27/09/2021 21:03, Rob Clark wrote: > > From: Rob Clark > > > > I've seen some crashes in our crash reporting that *look* like multiple > > threads stomping on each other while communicating with GMU. So wrap > > all those paths in a lock. > > > > Signed-off-by: Rob Clark > > --- > > Are we allowed to use c99/gnu99 yet? > > > > drivers/gpu/drm/msm/Makefile | 2 +- > > drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 > > drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 9 + > > drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 50 --- > > 4 files changed, 54 insertions(+), 13 deletions(-) > > > > diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile > > index 904535eda0c4..57283bbad3f0 100644 > > --- a/drivers/gpu/drm/msm/Makefile > > +++ b/drivers/gpu/drm/msm/Makefile > > @@ -1,5 +1,5 @@ > > # SPDX-License-Identifier: GPL-2.0 > > -ccflags-y := -I $(srctree)/$(src) > > +ccflags-y := -I $(srctree)/$(src) -std=gnu99 > > ccflags-y += -I $(srctree)/$(src)/disp/dpu1 > > ccflags-$(CONFIG_DRM_MSM_DSI) += -I $(srctree)/$(src)/dsi > > ccflags-$(CONFIG_DRM_MSM_DP) += -I $(srctree)/$(src)/dp > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > > b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > > index a7c58018959f..8b73f70766a4 100644 > > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c > > @@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum > > a6xx_gmu_oob_state state) > > u32 val; > > int request, ack; > > > > + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); > > + > > if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) > > return -EINVAL; > > > > @@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum > > a6xx_gmu_oob_state state) > > { > > int bit; > > > > + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); > > + > > if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) > > return; > > > > @@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct > > device_node *node) > > if (!pdev) > > return -ENODEV; > > > > + mutex_init(&gmu->lock); > > + > > gmu->dev = &pdev->dev; > > > > of_dma_configure(gmu->dev, node, true); > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > > b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > > index 3c74f64e3126..f05a00c0afd0 100644 > > --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h > > @@ -44,6 +44,9 @@ struct a6xx_gmu_bo { > > struct a6xx_gmu { > > struct device *dev; > > > > + /* For serializing communication with the GMU: */ > > + struct mutex lock; > > + > > struct msm_gem_address_space *aspace; > > > > void * __iomem mmio; > > @@ -88,6 +91,12 @@ struct a6xx_gmu { > > bool legacy; /* a618 or a630 */ > > }; > > > > +/* Helper macro for serializing GMU access: */ > > +#define with_gmu_lock(gmu) \ > > + for (bool done = ({ mutex_lock(&(gmu)->lock); false; }); \ > > + !done; \ > > + done = ({ mutex_unlock(&(gmu)->lock); true; })) > > The intent is good, but I'm not sure this kind of syntax sugar would be > a good approach. What about calling lock/unlock explicitly, like we > typically do? Then we won't have to use c99. Yeah, I was planning to resend without the sugar.. but it was a good excuse to bring up c99. Ie. I want c99 regardless ;-) (The sugar was useful initially before I'd sorted thru all the code paths and settled on using a mutex vs spinlock) BR, -R > > + > > static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) > > { > > return msm_readl(gmu->mmio + (offset << 2)); > > diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > > b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > > index f6a4dbef796b..5e1ae3df42ba 100644 > > --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > > +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c > > @@ -881,7 +881,7 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu) > > A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ > > A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) > > > > -static int a6xx_hw_init(struct msm_gpu *gpu) > > +static int hw_init(struct msm_gpu *gpu) > > { > > struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); > > struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); > > @@ -1135,6 +1135,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu) > > return ret; > > } > > > > +static int a6xx_hw_init(struct msm_gpu *gpu) > > +{ > > + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); > > + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); > > + int ret; > > + > > + with_gmu_lock(&a6xx_gpu->gmu) { > > + ret = hw_init(gpu); > > + } > > + > > + return ret; > > +} > > + > > static void a6xx_dump(struct msm_gpu *gpu) > > { > > DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", > > @@ -150
[PATCH v3 2/5] drm/msm/dp: Modify prototype of encoder based API
Functions in the DisplayPort code that relates to individual instances (encoders) are passed both the struct msm_dp and the struct drm_encoder. But in a situation where multiple DP instances would exist this means that the caller need to resolve which struct msm_dp relates to the struct drm_encoder at hand. Store a reference to the struct msm_dp associated with each dpu_encoder_virt to allow the particular instance to be associate with the encoder in the following patch. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- Changes since v2: - None drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23 - 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 0e9d3fa1544b..b7f33da2799c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -168,6 +168,7 @@ enum dpu_enc_rc_states { * @vsync_event_work: worker to handle vsync event for autorefresh * @topology: topology of the display * @idle_timeout: idle timeout duration in milliseconds + * @dp:msm_dp pointer, for DP encoders */ struct dpu_encoder_virt { struct drm_encoder base; @@ -206,6 +207,8 @@ struct dpu_encoder_virt { struct msm_display_topology topology; u32 idle_timeout; + + struct msm_dp *dp; }; #define to_dpu_encoder_virt(x) container_of(x, struct dpu_encoder_virt, base) @@ -1000,8 +1003,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder *drm_enc, trace_dpu_enc_mode_set(DRMID(drm_enc)); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) - msm_dp_display_mode_set(priv->dp, drm_enc, mode, adj_mode); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) + msm_dp_display_mode_set(dpu_enc->dp, drm_enc, mode, adj_mode); list_for_each_entry(conn_iter, connector_list, head) if (conn_iter->encoder == drm_enc) @@ -1182,9 +1185,8 @@ static void dpu_encoder_virt_enable(struct drm_encoder *drm_enc) _dpu_encoder_virt_enable_helper(drm_enc); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { - ret = msm_dp_display_enable(priv->dp, - drm_enc); + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { + ret = msm_dp_display_enable(dpu_enc->dp, drm_enc); if (ret) { DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n", ret); @@ -1224,8 +1226,8 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) /* wait for idle */ dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { - if (msm_dp_display_pre_disable(priv->dp, drm_enc)) + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { + if (msm_dp_display_pre_disable(dpu_enc->dp, drm_enc)) DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n"); } @@ -1253,8 +1255,8 @@ static void dpu_encoder_virt_disable(struct drm_encoder *drm_enc) DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n"); - if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS && priv->dp) { - if (msm_dp_display_disable(priv->dp, drm_enc)) + if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) { + if (msm_dp_display_disable(dpu_enc->dp, drm_enc)) DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n"); } @@ -2170,7 +2172,8 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, timer_setup(&dpu_enc->vsync_event_timer, dpu_encoder_vsync_event_handler, 0); - + else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) + dpu_enc->dp = priv->dp; INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, dpu_encoder_off_work); -- 2.29.2
[PATCH v3 3/5] drm/msm/dp: Support up to 3 DP controllers
Based on the removal of the g_dp_display and the movement of the priv->dp lookup into the DP code it's now possible to have multiple DP instances. In line with the other controllers in the MSM driver, introduce a per-compatible list of base addresses which is used to resolve the "instance id" for the given DP controller. This instance id is used as index in the priv->dp[] array. Then extend the initialization code to initialize struct drm_encoder for each of the registered priv->dp[] and update the logic for associating each struct msm_dp with the struct dpu_encoder_virt. Lastly, bump the number of struct msm_dp instances carries by priv->dp to 3, the currently known maximum number of controllers found in a Qualcomm SoC. Signed-off-by: Bjorn Andersson --- Changes since v2: - Added MSM_DRM_DP_COUNT to link the two 3s - Moved NULL check for msm_dp_debugfs_init() to the call site - Made struct dp_display_private->id unsigned I also implemented added connector_type to each of the DP instances and propagated this to dp_drm_connector_init() but later dropped this again per Doug's suggestion that we'll base this on the presence/absence of a associated drm bridge or panel. drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++ .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 8 ++- drivers/gpu/drm/msm/dp/dp_display.c | 44 - drivers/gpu/drm/msm/msm_drv.h | 4 +- 5 files changed, 90 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index b7f33da2799c..9cd9539a1504 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2173,7 +2173,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct drm_encoder *enc, dpu_encoder_vsync_event_handler, 0); else if (disp_info->intf_type == DRM_MODE_ENCODER_TMDS) - dpu_enc->dp = priv->dp; + dpu_enc->dp = priv->dp[disp_info->h_tile_instance[0]]; INIT_DELAYED_WORK(&dpu_enc->delayed_off_work, dpu_encoder_off_work); diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c index f655adbc2421..875b07e7183d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c @@ -188,6 +188,7 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) struct dentry *entry; struct drm_device *dev; struct msm_drm_private *priv; + int i; if (!p) return -EINVAL; @@ -203,8 +204,10 @@ static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor) dpu_debugfs_vbif_init(dpu_kms, entry); dpu_debugfs_core_irq_init(dpu_kms, entry); - if (priv->dp) - msm_dp_debugfs_init(priv->dp, minor); + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (priv->dp[i]) + msm_dp_debugfs_init(priv->dp[i], minor); + } return dpu_core_perf_debugfs_init(dpu_kms, entry); } @@ -544,35 +547,42 @@ static int _dpu_kms_initialize_displayport(struct drm_device *dev, { struct drm_encoder *encoder = NULL; struct msm_display_info info; - int rc = 0; + int rc; + int i; - if (!priv->dp) - return rc; + for (i = 0; i < ARRAY_SIZE(priv->dp); i++) { + if (!priv->dp[i]) + continue; - encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); - if (IS_ERR(encoder)) { - DPU_ERROR("encoder init failed for dsi display\n"); - return PTR_ERR(encoder); - } + encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS); + if (IS_ERR(encoder)) { + DPU_ERROR("encoder init failed for dsi display\n"); + return PTR_ERR(encoder); + } - memset(&info, 0, sizeof(info)); - rc = msm_dp_modeset_init(priv->dp, dev, encoder); - if (rc) { - DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); - drm_encoder_cleanup(encoder); - return rc; - } + memset(&info, 0, sizeof(info)); + rc = msm_dp_modeset_init(priv->dp[i], dev, encoder); + if (rc) { + DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc); + drm_encoder_cleanup(encoder); + return rc; + } - priv->encoders[priv->num_encoders++] = encoder; + priv->encoders[priv->num_encoders++] = encoder; - info.num_of_h_tiles = 1; - info.capabilities = MSM_DISPLAY_CAP_VID_MODE; - info.intf_type = encoder->encoder_type; - r
[PATCH v3 5/5] drm/msm/dp: Add sc8180x DP controllers
The sc8180x has 2 DP and 1 eDP controllers, add support for these to the DP driver. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- Changes since v2: - None drivers/gpu/drm/msm/dp/dp_display.c | 7 +++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index ff3477474c5d..56a79aeffed4 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -127,8 +127,15 @@ static const struct msm_dp_config sc7180_dp_cfg = { .num_descs = 1, }; +static const struct msm_dp_config sc8180x_dp_cfg = { + .io_start = { 0xae9, 0xae98000, 0xae9a000 }, + .num_descs = 3, +}; + static const struct of_device_id dp_dt_match[] = { { .compatible = "qcom,sc7180-dp", .data = &sc7180_dp_cfg }, + { .compatible = "qcom,sc8180x-dp", .data = &sc8180x_dp_cfg }, + { .compatible = "qcom,sc8180x-edp", .data = &sc8180x_dp_cfg }, {} }; -- 2.29.2
[PATCH v3 4/5] dt-bindings: msm/dp: Add SC8180x compatibles
The Qualcomm SC8180x has 2 DP controllers and 1 eDP controller, add compatibles for these to the msm/dp binding. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- Changes since v2: - None .../devicetree/bindings/display/msm/dp-controller.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index 6bb424c21340..63e585f48789 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -17,6 +17,8 @@ properties: compatible: enum: - qcom,sc7180-dp + - qcom,sc8180x-dp + - qcom,sc8180x-edp reg: items: -- 2.29.2
[PATCH v3 1/5] drm/msm/dp: Remove global g_dp_display variable
As the Qualcomm DisplayPort driver only supports a single instance of the driver the commonly used struct dp_display is kept in a global variable. As we introduce additional instances this obviously doesn't work. Replace this with a combination of existing references to adjacent objects and drvdata. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- Changes since v2: - None drivers/gpu/drm/msm/dp/dp_display.c | 80 - 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index fbe4c2cd52a3..5d3ee5ef07c2 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -27,7 +27,6 @@ #include "dp_audio.h" #include "dp_debug.h" -static struct msm_dp *g_dp_display; #define HPD_STRING_SIZE 30 enum { @@ -121,6 +120,13 @@ static const struct of_device_id dp_dt_match[] = { {} }; +static struct dp_display_private *dev_get_dp_display_private(struct device *dev) +{ + struct msm_dp *dp = dev_get_drvdata(dev); + + return container_of(dp, struct dp_display_private, dp_display); +} + static int dp_add_event(struct dp_display_private *dp_priv, u32 event, u32 data, u32 delay) { @@ -197,15 +203,12 @@ static int dp_display_bind(struct device *dev, struct device *master, void *data) { int rc = 0; - struct dp_display_private *dp; - struct drm_device *drm; + struct dp_display_private *dp = dev_get_dp_display_private(dev); struct msm_drm_private *priv; + struct drm_device *drm; drm = dev_get_drvdata(master); - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); - dp->dp_display.drm_dev = drm; priv = drm->dev_private; priv->dp = &(dp->dp_display); @@ -240,13 +243,10 @@ static int dp_display_bind(struct device *dev, struct device *master, static void dp_display_unbind(struct device *dev, struct device *master, void *data) { - struct dp_display_private *dp; + struct dp_display_private *dp = dev_get_dp_display_private(dev); struct drm_device *drm = dev_get_drvdata(master); struct msm_drm_private *priv = drm->dev_private; - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); - dp_power_client_deinit(dp->power); dp_aux_unregister(dp->aux); priv->dp = NULL; @@ -379,38 +379,17 @@ static void dp_display_host_deinit(struct dp_display_private *dp) static int dp_display_usbpd_configure_cb(struct device *dev) { - int rc = 0; - struct dp_display_private *dp; - - if (!dev) { - DRM_ERROR("invalid dev\n"); - rc = -EINVAL; - goto end; - } - - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp = dev_get_dp_display_private(dev); dp_display_host_init(dp, false); - rc = dp_display_process_hpd_high(dp); -end: - return rc; + return dp_display_process_hpd_high(dp); } static int dp_display_usbpd_disconnect_cb(struct device *dev) { int rc = 0; - struct dp_display_private *dp; - - if (!dev) { - DRM_ERROR("invalid dev\n"); - rc = -EINVAL; - return rc; - } - - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp = dev_get_dp_display_private(dev); dp_add_event(dp, EV_USER_NOTIFICATION, false, 0); @@ -472,15 +451,7 @@ static int dp_display_usbpd_attention_cb(struct device *dev) { int rc = 0; u32 sink_request; - struct dp_display_private *dp; - - if (!dev) { - DRM_ERROR("invalid dev\n"); - return -EINVAL; - } - - dp = container_of(g_dp_display, - struct dp_display_private, dp_display); + struct dp_display_private *dp = dev_get_dp_display_private(dev); /* check for any test request issued by sink */ rc = dp_link_process_request(dp->link); @@ -647,7 +618,7 @@ static int dp_hpd_unplug_handle(struct dp_display_private *dp, u32 data) DRM_DEBUG_DP("hpd_state=%d\n", state); /* signal the disconnect event early to ensure proper teardown */ - dp_display_handle_plugged_change(g_dp_display, false); + dp_display_handle_plugged_change(&dp->dp_display, false); /* enable HDP plug interrupt to prepare for next plugin */ dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_PLUG_INT_MASK, true); @@ -842,9 +813,7 @@ static int dp_display_prepare(struct msm_dp *dp) static int dp_display_enable(struct dp_display_private *dp, u32 data) {
[PATCH v3 0/5] drm/msm/dp: Support multiple DP instances and add sc8180x
The current implementation supports a single DP instance and the DPU code will only match it against INTF_DP instance 0. These patches extends this to allow multiple DP instances and support for matching against DP instances beyond 0. With that in place add SC8180x DP and eDP controllers. Bjorn Andersson (5): drm/msm/dp: Remove global g_dp_display variable drm/msm/dp: Modify prototype of encoder based API drm/msm/dp: Support up to 3 DP controllers dt-bindings: msm/dp: Add SC8180x compatibles drm/msm/dp: Add sc8180x DP controllers .../bindings/display/msm/dp-controller.yaml | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 23 +-- drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 + .../gpu/drm/msm/disp/msm_disp_snapshot_util.c | 8 +- drivers/gpu/drm/msm/dp/dp_display.c | 131 +- drivers/gpu/drm/msm/msm_drv.h | 4 +- 6 files changed, 132 insertions(+), 102 deletions(-) -- 2.29.2
Re: [PATCH v2 1/3] drm/msm/dsi: Support NO_CONNECTOR bridges
On Fri, Oct 1, 2021 at 10:28 AM Dmitry Baryshkov wrote: > > On 21/09/2021 01:57, Rob Clark wrote: > > From: Rob Clark > > > > For now, since we have a mix of bridges which support this flag, which > > which do *not* support this flag, or work both ways, try it once with > > NO_CONNECTOR and then fall back to the old way if that doesn't work. > > Eventually we can drop the fallback path. > > > > v2: Add missing drm_connector_attach_encoder() so display actually comes > > up when the bridge properly handles the NO_CONNECTOR flag > > > > Signed-off-by: Rob Clark > > Reviewed-by: Laurent Pinchart > > Reviewed-by: Dmitry Baryshkov > > I think this patch can go through the drm/msm, while two other patches > would need to through the drm-misc. Is it correct? Correct, I made sure things worked in either order (ie. with msm patch but without bridge patches, and visa versa), so they can land through different trees BR, -R > > > --- > > drivers/gpu/drm/msm/Kconfig | 2 ++ > > drivers/gpu/drm/msm/dsi/dsi_manager.c | 50 --- > > 2 files changed, 39 insertions(+), 13 deletions(-) > > > > diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig > > index e9c6af78b1d7..36e5ba3ccc28 100644 > > --- a/drivers/gpu/drm/msm/Kconfig > > +++ b/drivers/gpu/drm/msm/Kconfig > > @@ -14,6 +14,8 @@ config DRM_MSM > > select REGULATOR > > select DRM_KMS_HELPER > > select DRM_PANEL > > + select DRM_BRIDGE > > + select DRM_PANEL_BRIDGE > > select DRM_SCHED > > select SHMEM > > select TMPFS > > diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c > > b/drivers/gpu/drm/msm/dsi/dsi_manager.c > > index c41d39f5b7cf..e25877073d31 100644 > > --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c > > +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c > > @@ -3,6 +3,8 @@ > >* Copyright (c) 2015, The Linux Foundation. All rights reserved. > >*/ > > > > +#include "drm/drm_bridge_connector.h" > > + > > #include "msm_kms.h" > > #include "dsi.h" > > > > @@ -688,10 +690,10 @@ struct drm_connector > > *msm_dsi_manager_ext_bridge_init(u8 id) > > { > > struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); > > struct drm_device *dev = msm_dsi->dev; > > + struct drm_connector *connector; > > struct drm_encoder *encoder; > > struct drm_bridge *int_bridge, *ext_bridge; > > - struct drm_connector *connector; > > - struct list_head *connector_list; > > + int ret; > > > > int_bridge = msm_dsi->bridge; > > ext_bridge = msm_dsi->external_bridge = > > @@ -699,22 +701,44 @@ struct drm_connector > > *msm_dsi_manager_ext_bridge_init(u8 id) > > > > encoder = msm_dsi->encoder; > > > > - /* link the internal dsi bridge to the external bridge */ > > - drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); > > - > > /* > > - * we need the drm_connector created by the external bridge > > - * driver (or someone else) to feed it to our driver's > > - * priv->connector[] list, mainly for msm_fbdev_init() > > + * Try first to create the bridge without it creating its own > > + * connector.. currently some bridges support this, and others > > + * do not (and some support both modes) > >*/ > > - connector_list = &dev->mode_config.connector_list; > > + ret = drm_bridge_attach(encoder, ext_bridge, int_bridge, > > + DRM_BRIDGE_ATTACH_NO_CONNECTOR); > > + if (ret == -EINVAL) { > > + struct drm_connector *connector; > > + struct list_head *connector_list; > > + > > + /* link the internal dsi bridge to the external bridge */ > > + drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); > > + > > + /* > > + * we need the drm_connector created by the external bridge > > + * driver (or someone else) to feed it to our driver's > > + * priv->connector[] list, mainly for msm_fbdev_init() > > + */ > > + connector_list = &dev->mode_config.connector_list; > > > > - list_for_each_entry(connector, connector_list, head) { > > - if (drm_connector_has_possible_encoder(connector, encoder)) > > - return connector; > > + list_for_each_entry(connector, connector_list, head) { > > + if (drm_connector_has_possible_encoder(connector, > > encoder)) > > + return connector; > > + } > > + > > + return ERR_PTR(-ENODEV); > > + } > > + > > + connector = drm_bridge_connector_init(dev, encoder); > > + if (IS_ERR(connector)) { > > + DRM_ERROR("Unable to create bridge connector\n"); > > + return ERR_CAST(connector); > > } > > > > - return ERR_PTR(-ENODEV); > > + drm_connector_attach_encoder(connector, encoder); > > + > > + return connector; > > } > > > > void msm_dsi_manager_bridge_d
[PATCH 2/2] drm/msm: One sched entity per process per priority
From: Rob Clark Some userspace apps make assumptions that rendering against multiple contexts within the same process (from the same thread, with appropriate MakeCurrent() calls) provides sufficient synchronization without any external synchronization (ie. glFenceSync()/glWaitSync()). Since a submitqueue maps to a gl/vk context, having multiple sched entities of the same priority only works with implicit sync enabled. To fix this, limit things to a single sched entity per priority level per process. An alternative would be sharing submitqueues between contexts in userspace, but tracking of per-context faults (ie. GL_EXT_robustness) is already done at the submitqueue level, so this is not an option. Signed-off-by: Rob Clark --- Unfortunately, due to a finch experiment (a sort of A/B experiment) all my testing of the drm/scheduler with chrome(ium) was using SkiaRenderer which does not trigger this bug. It wasn't until folks started reporting misrendering on dev channel, and I tracked it down to legacy GLRenderer vs SkiaRenderer, that I realized the problem :-( drivers/gpu/drm/msm/msm_gem_submit.c | 2 +- drivers/gpu/drm/msm/msm_gpu.h | 24 ++ drivers/gpu/drm/msm/msm_submitqueue.c | 68 +++ 3 files changed, 74 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 924b01b9c105..34ed56b24224 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -46,7 +46,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, if (!submit) return ERR_PTR(-ENOMEM); - ret = drm_sched_job_init(&submit->base, &queue->entity, queue); + ret = drm_sched_job_init(&submit->base, queue->entity, queue); if (ret) { kfree(submit); return ERR_PTR(ret); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 592334cb9a0b..d72b1de3cb1f 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -290,6 +290,19 @@ struct msm_file_private { struct msm_gem_address_space *aspace; struct kref ref; int seqno; + + /** +* entities: +* +* Table of per-priority-level sched entities used by submitqueues +* associated with this &drm_file. Because some userspace apps +* make assumptions about rendering from multiple gl contexts +* (of the same priority) within the process happening in FIFO +* order without requiring any fencing beyond MakeCurrent(), we +* create at most one &drm_sched_entity per-process per-priority- +* level. +*/ + struct drm_sched_entity *entities[NR_SCHED_PRIORITIES * MSM_GPU_MAX_RINGS]; }; /** @@ -370,7 +383,7 @@ struct msm_gpu_submitqueue { struct idr fence_idr; struct mutex lock; struct kref ref; - struct drm_sched_entity entity; + struct drm_sched_entity *entity; }; struct msm_gpu_state_bo { @@ -471,14 +484,7 @@ void msm_submitqueue_close(struct msm_file_private *ctx); void msm_submitqueue_destroy(struct kref *kref); -static inline void __msm_file_private_destroy(struct kref *kref) -{ - struct msm_file_private *ctx = container_of(kref, - struct msm_file_private, ref); - - msm_gem_address_space_put(ctx->aspace); - kfree(ctx); -} +void __msm_file_private_destroy(struct kref *kref); static inline void msm_file_private_put(struct msm_file_private *ctx) { diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c index 7ce0771b5582..b8621c6e0554 100644 --- a/drivers/gpu/drm/msm/msm_submitqueue.c +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -7,6 +7,24 @@ #include "msm_gpu.h" +void __msm_file_private_destroy(struct kref *kref) +{ + struct msm_file_private *ctx = container_of(kref, + struct msm_file_private, ref); + int i; + + for (i = 0; i < ARRAY_SIZE(ctx->entities); i++) { + if (!ctx->entities[i]) + continue; + + drm_sched_entity_destroy(ctx->entities[i]); + kfree(ctx->entities[i]); + } + + msm_gem_address_space_put(ctx->aspace); + kfree(ctx); +} + void msm_submitqueue_destroy(struct kref *kref) { struct msm_gpu_submitqueue *queue = container_of(kref, @@ -14,8 +32,6 @@ void msm_submitqueue_destroy(struct kref *kref) idr_destroy(&queue->fence_idr); - drm_sched_entity_destroy(&queue->entity); - msm_file_private_put(queue->ctx); kfree(queue); @@ -61,13 +77,47 @@ void msm_submitqueue_close(struct msm_file_private *ctx) } } +static struct drm_sched_entity * +get_sched_entity(struct msm_file_private *ctx, struct msm_ringbuffer *ring, +unsigned ring_nr, enum drm_sched_priority sched_prio) +{ + static DEFINE_MUTEX(
[PATCH 1/2] drm/msm: A bit more docs + cleanup
From: Rob Clark msm_file_private is more gpu related, and in the next commit it will need access to other GPU specific #defines. While we're at it, add some comments. Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.h | 44 -- drivers/gpu/drm/msm/msm_gpu.h | 58 ++- 2 files changed, 57 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 8633d0059a3e..31b39c27156d 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -53,15 +53,6 @@ struct msm_disp_state; #define FRAC_16_16(mult, div)(((mult) << 16) / (div)) -struct msm_file_private { - rwlock_t queuelock; - struct list_head submitqueues; - int queueid; - struct msm_gem_address_space *aspace; - struct kref ref; - int seqno; -}; - enum msm_mdp_plane_property { PLANE_PROP_ZPOS, PLANE_PROP_ALPHA, @@ -511,41 +502,6 @@ void msm_hrtimer_work_init(struct msm_hrtimer_work *work, clockid_t clock_id, enum hrtimer_mode mode); -struct msm_gpu_submitqueue; -int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); -struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, - u32 id); -int msm_submitqueue_create(struct drm_device *drm, - struct msm_file_private *ctx, - u32 prio, u32 flags, u32 *id); -int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, - struct drm_msm_submitqueue_query *args); -int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); -void msm_submitqueue_close(struct msm_file_private *ctx); - -void msm_submitqueue_destroy(struct kref *kref); - -static inline void __msm_file_private_destroy(struct kref *kref) -{ - struct msm_file_private *ctx = container_of(kref, - struct msm_file_private, ref); - - msm_gem_address_space_put(ctx->aspace); - kfree(ctx); -} - -static inline void msm_file_private_put(struct msm_file_private *ctx) -{ - kref_put(&ctx->ref, __msm_file_private_destroy); -} - -static inline struct msm_file_private *msm_file_private_get( - struct msm_file_private *ctx) -{ - kref_get(&ctx->ref); - return ctx; -} - #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index 2fcb6c195865..592334cb9a0b 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -272,6 +272,26 @@ struct msm_gpu_perfcntr { */ #define NR_SCHED_PRIORITIES (1 + DRM_SCHED_PRIORITY_HIGH - DRM_SCHED_PRIORITY_MIN) +/** + * struct msm_file_private - per-drm_file context + * + * @queuelock:synchronizes access to submitqueues list + * @submitqueues: list of &msm_gpu_submitqueue created by userspace + * @queueid: counter incremented each time a submitqueue is created, + *used to assign &msm_gpu_submitqueue.id + * @aspace: the per-process GPU address-space + * @ref: reference count + * @seqno:unique per process seqno + */ +struct msm_file_private { + rwlock_t queuelock; + struct list_head submitqueues; + int queueid; + struct msm_gem_address_space *aspace; + struct kref ref; + int seqno; +}; + /** * msm_gpu_convert_priority - Map userspace priority to ring # and sched priority * @@ -319,6 +339,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, } /** + * struct msm_gpu_submitqueues - Userspace created context. + * * A submitqueue is associated with a gl context or vk queue (or equiv) * in userspace. * @@ -336,7 +358,7 @@ static inline int msm_gpu_convert_priority(struct msm_gpu *gpu, int prio, * seqno, protected by submitqueue lock * @lock: submitqueue lock * @ref: reference count - * @entity: the submit job-queue + * @entity:the submit job-queue */ struct msm_gpu_submitqueue { int id; @@ -436,6 +458,40 @@ 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); +int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, + u32 id); +int msm_submitqueue_create(struct drm_device *drm, + struct msm_file_private *ctx, + u32 prio, u32 flags, u32 *id); +int msm_submitqueue_query(struct drm_device *drm, struct msm_file_private *ctx, + struct drm_msm_submitqueue_query *args); +int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); +void msm_submitqueue_close(struct msm_file_private *ctx); + +void msm_s
[PATCH 0/2] drm/msm: Un-break multi-context gl
From: Rob Clark Userspace is expecting that a single thread doing rendering against multiple contexts does not need additional synchronization between those contexts beyond ensuring work is flushed to the kernel in the correct order. But if we have a sched-entity per-context, and are not using implicit sync, GPU jobs from different contexts can execute in a different order than they were flushed to the kernel. To solve that, share sched-entities for a given priority level between submitqueues (which map to gl contexts). Rob Clark (2): drm/msm: A bit more docs + cleanup drm/msm: One sched entity per process per priority drivers/gpu/drm/msm/msm_drv.h | 44 - drivers/gpu/drm/msm/msm_gem_submit.c | 2 +- drivers/gpu/drm/msm/msm_gpu.h | 66 +- drivers/gpu/drm/msm/msm_submitqueue.c | 68 +++ 4 files changed, 123 insertions(+), 57 deletions(-) -- 2.31.1
[PATCH v3 09/10] vfio: Export vfio_device_try_get()
vfio_ccw will need it. Signed-off-by: Jason Gunthorpe --- drivers/vfio/vfio.c | 3 ++- include/linux/vfio.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c index 08b27b64f0f935..44adf112e3b5dd 100644 --- a/drivers/vfio/vfio.c +++ b/drivers/vfio/vfio.c @@ -554,10 +554,11 @@ void vfio_device_put(struct vfio_device *device) } EXPORT_SYMBOL_GPL(vfio_device_put); -static bool vfio_device_try_get(struct vfio_device *device) +bool vfio_device_try_get(struct vfio_device *device) { return refcount_inc_not_zero(&device->refcount); } +EXPORT_SYMBOL_GPL(vfio_device_try_get); static struct vfio_device *vfio_group_get_device(struct vfio_group *group, struct device *dev) diff --git a/include/linux/vfio.h b/include/linux/vfio.h index 76191d7abed185..f99e4b2d9b45f0 100644 --- a/include/linux/vfio.h +++ b/include/linux/vfio.h @@ -78,6 +78,7 @@ int vfio_register_group_dev(struct vfio_device *device); int vfio_register_emulated_iommu_dev(struct vfio_device *device); void vfio_unregister_group_dev(struct vfio_device *device); extern struct vfio_device *vfio_device_get_from_dev(struct device *dev); +bool vfio_device_try_get(struct vfio_device *device); extern void vfio_device_put(struct vfio_device *device); int vfio_assign_device_set(struct vfio_device *device, void *set_id); -- 2.33.0
[PATCH v3 10/10] vfio/ccw: Move the lifecycle of the struct vfio_ccw_private to the mdev
The css_driver's main purpose is to create/destroy the mdev and relay the shutdown, irq, sch_event, and chp_event css_driver ops to the single created vfio_device, if it exists. Reframe the boundary where the css_driver domain switches to the vfio domain by using rcu to read and refcount the vfio_device out of the sch's drvdata. The mdev probe/remove will manage the drvdata of the parent. The vfio core code refcounting thus guarantees that when a css_driver callback is running the vfio_device is registered, simplifying the understanding of the whole lifecycle. Finally the vfio_ccw_private is allocated/freed during probe/remove of the mdev like any other vfio_device struct. Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_drv.c | 67 ++--- drivers/s390/cio/vfio_ccw_ops.c | 40 +++-- drivers/s390/cio/vfio_ccw_private.h | 23 +- 3 files changed, 69 insertions(+), 61 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 18ad047811d111..c5582fc9c46c9e 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -86,13 +86,19 @@ static void vfio_ccw_crw_todo(struct work_struct *work) */ static void vfio_ccw_sch_irq(struct subchannel *sch) { - struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); + struct vfio_ccw_private *private = vfio_ccw_get_priv(sch); + + /* IRQ should not be delivered after the mdev is destroyed */ + if (WARN_ON(!private)) + return; inc_irq_stat(IRQIO_CIO); vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); + vfio_device_put(&private->vdev); } -static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) +struct vfio_ccw_private *vfio_ccw_alloc_private(struct mdev_device *mdev, + struct subchannel *sch) { struct vfio_ccw_private *private; @@ -100,6 +106,8 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) if (!private) return ERR_PTR(-ENOMEM); + vfio_init_group_dev(&private->vdev, &mdev->dev, + &vfio_ccw_dev_ops); private->sch = sch; mutex_init(&private->io_mutex); private->state = VFIO_CCW_STATE_CLOSED; @@ -145,11 +153,12 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) kfree(private->cp.guest_cp); out_free_private: mutex_destroy(&private->io_mutex); + vfio_uninit_group_dev(&private->vdev); kfree(private); return ERR_PTR(-ENOMEM); } -static void vfio_ccw_free_private(struct vfio_ccw_private *private) +void vfio_ccw_free_private(struct vfio_ccw_private *private) { struct vfio_ccw_crw *crw, *temp; @@ -164,14 +173,14 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private) kmem_cache_free(vfio_ccw_io_region, private->io_region); kfree(private->cp.guest_cp); mutex_destroy(&private->io_mutex); - kfree(private); + vfio_uninit_group_dev(&private->vdev); + kfree_rcu(private, rcu); } static int vfio_ccw_sch_probe(struct subchannel *sch) { struct pmcw *pmcw = &sch->schib.pmcw; - struct vfio_ccw_private *private; - int ret = -ENOMEM; + int ret; if (pmcw->qf) { dev_warn(&sch->dev, "vfio: ccw: does not support QDIO: %s\n", @@ -179,15 +188,9 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) return -ENODEV; } - private = vfio_ccw_alloc_private(sch); - if (IS_ERR(private)) - return PTR_ERR(private); - - dev_set_drvdata(&sch->dev, private); - - ret = vfio_ccw_mdev_reg(sch); + ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_ops); if (ret) - goto out_free; + return ret; if (dev_get_uevent_suppress(&sch->dev)) { dev_set_uevent_suppress(&sch->dev, 0); @@ -198,22 +201,11 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) sch->schid.cssid, sch->schid.ssid, sch->schid.sch_no); return 0; - -out_free: - dev_set_drvdata(&sch->dev, NULL); - vfio_ccw_free_private(private); - return ret; } static void vfio_ccw_sch_remove(struct subchannel *sch) { - struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); - - vfio_ccw_mdev_unreg(sch); - - dev_set_drvdata(&sch->dev, NULL); - - vfio_ccw_free_private(private); + mdev_unregister_device(&sch->dev); VFIO_CCW_MSG_EVENT(4, "unbound from subchannel %x.%x.%04x\n", sch->schid.cssid, sch->schid.ssid, @@ -222,10 +214,14 @@ static void vfio_ccw_sch_remove(struct subchannel *sch) static void vfio_ccw_sch_shutdown(struct subchannel *sch) { - struct vfio_ccw_private *private
[PATCH v3 06/10] vfio/mdev: Consolidate all the device_api sysfs into the core code
Every driver just emits a static string, simply feed it through the ops and provide a standard sysfs show function. Signed-off-by: Jason Gunthorpe --- .../driver-api/vfio-mediated-device.rst | 4 ++- drivers/gpu/drm/i915/gvt/kvmgt.c | 9 +-- drivers/s390/cio/vfio_ccw_ops.c | 9 +-- drivers/s390/crypto/vfio_ap_ops.c | 9 +-- drivers/vfio/mdev/mdev_core.c | 2 +- drivers/vfio/mdev/mdev_sysfs.c| 27 --- include/linux/mdev.h | 7 ++--- samples/vfio-mdev/mbochs.c| 9 +-- samples/vfio-mdev/mdpy.c | 9 +-- samples/vfio-mdev/mtty.c | 10 +-- 10 files changed, 36 insertions(+), 59 deletions(-) diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst index 9f26079cacae35..f410a1cd98bb06 100644 --- a/Documentation/driver-api/vfio-mediated-device.rst +++ b/Documentation/driver-api/vfio-mediated-device.rst @@ -137,6 +137,7 @@ The structures in the mdev_parent_ops structure are as follows: * mdev_attr_groups: attributes of the mediated device * supported_config: attributes to define supported configurations * device_driver: device driver to bind for mediated device instances +* device_api: String to pass through the sysfs file below The mdev_parent_ops also still has various functions pointers. Theses exist for historical reasons only and shall not be used for new drivers. @@ -225,7 +226,8 @@ Directories and files under the sysfs for Each Physical Device * device_api This attribute should show which device API is being created, for example, - "vfio-pci" for a PCI device. + "vfio-pci" for a PCI device. The core code maintins this sysfs using the + device_api member of mdev_parent_ops. * available_instances diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 7efa386449d104..d198cc3d132277 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -161,12 +161,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype, return sprintf(buf, "%u\n", num); } -static ssize_t device_api_show(struct mdev_type *mtype, - struct mdev_type_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING); -} - static ssize_t description_show(struct mdev_type *mtype, struct mdev_type_attribute *attr, char *buf) { @@ -187,12 +181,10 @@ static ssize_t description_show(struct mdev_type *mtype, } static MDEV_TYPE_ATTR_RO(available_instances); -static MDEV_TYPE_ATTR_RO(device_api); static MDEV_TYPE_ATTR_RO(description); static struct attribute *gvt_type_attrs[] = { &mdev_type_attr_available_instances.attr, - &mdev_type_attr_device_api.attr, &mdev_type_attr_description.attr, NULL, }; @@ -1750,6 +1742,7 @@ static const struct attribute_group *intel_vgpu_groups[] = { static struct mdev_parent_ops intel_vgpu_ops = { .mdev_attr_groups = intel_vgpu_groups, + .device_api = VFIO_DEVICE_API_PCI_STRING, .create = intel_vgpu_create, .remove = intel_vgpu_remove, diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index bd4d08afa3e4dc..a7f642be9c8898 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -70,13 +70,6 @@ static ssize_t name_show(struct mdev_type *mtype, } static MDEV_TYPE_ATTR_RO(name); -static ssize_t device_api_show(struct mdev_type *mtype, - struct mdev_type_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING); -} -static MDEV_TYPE_ATTR_RO(device_api); - static ssize_t available_instances_show(struct mdev_type *mtype, struct mdev_type_attribute *attr, char *buf) @@ -90,7 +83,6 @@ static MDEV_TYPE_ATTR_RO(available_instances); static struct attribute *mdev_types_attrs[] = { &mdev_type_attr_name.attr, - &mdev_type_attr_device_api.attr, &mdev_type_attr_available_instances.attr, NULL, }; @@ -640,6 +632,7 @@ struct mdev_driver vfio_ccw_mdev_driver = { static const struct mdev_parent_ops vfio_ccw_mdev_ops = { .owner = THIS_MODULE, .device_driver = &vfio_ccw_mdev_driver, + .device_api = VFIO_DEVICE_API_CCW_STRING, .supported_type_groups = mdev_type_groups, }; diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c index 2341425f69675a..f80246b30aff30 100644 --- a/drivers/s390/crypto/vfio_ap_ops.c +++ b/drivers/s390/crypto/vfio_ap_ops.c @@ -401,17 +401,9 @@ static ssize_t available_instances_show(struct mdev_
[PATCH v3 07/10] vfio/mdev: Add mdev available instance checking to the core
Many of the mdev drivers use a simple counter for keeping track of the available instances. Move this code to the core code and store the counter in the mdev_type. Implement it using correct locking, fixing mdpy. Drivers provide a get_available() callback to set the number of available instances for their mtypes which is fixed at registration time. The core provides a standard sysfs attribute to return the available_instances. Reviewed-by: Christoph Hellwig Signed-off-by: Jason Gunthorpe --- .../driver-api/vfio-mediated-device.rst | 4 +- drivers/s390/cio/vfio_ccw_drv.c | 1 - drivers/s390/cio/vfio_ccw_ops.c | 26 - drivers/s390/cio/vfio_ccw_private.h | 2 - drivers/s390/crypto/vfio_ap_ops.c | 32 drivers/s390/crypto/vfio_ap_private.h | 2 - drivers/vfio/mdev/mdev_core.c | 11 +- drivers/vfio/mdev/mdev_private.h | 2 + drivers/vfio/mdev/mdev_sysfs.c| 37 +++ include/linux/mdev.h | 2 + samples/vfio-mdev/mdpy.c | 22 +++ 11 files changed, 76 insertions(+), 65 deletions(-) diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst index f410a1cd98bb06..a4f7f1362fa8a5 100644 --- a/Documentation/driver-api/vfio-mediated-device.rst +++ b/Documentation/driver-api/vfio-mediated-device.rst @@ -106,6 +106,7 @@ structure to represent a mediated device's driver:: int (*probe) (struct mdev_device *dev); void (*remove) (struct mdev_device *dev); struct device_driverdriver; +unsigned int (*get_available)(struct mdev_type *mtype); }; A mediated bus driver for mdev should use this structure in the function calls @@ -232,7 +233,8 @@ Directories and files under the sysfs for Each Physical Device * available_instances This attribute should show the number of devices of type that can be - created. + created. Drivers can supply a get_available() function pointer to have the + core code create and maintain this sysfs automatically. * [device] diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 769edbbd164313..df9e1e265bca1a 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -106,7 +106,6 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) INIT_LIST_HEAD(&private->crw); INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); - atomic_set(&private->avail, 1); private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), GFP_KERNEL); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index a7f642be9c8898..97df5c711736c4 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -70,20 +70,9 @@ static ssize_t name_show(struct mdev_type *mtype, } static MDEV_TYPE_ATTR_RO(name); -static ssize_t available_instances_show(struct mdev_type *mtype, - struct mdev_type_attribute *attr, - char *buf) -{ - struct vfio_ccw_private *private = - dev_get_drvdata(mtype_get_parent_dev(mtype)); - - return sprintf(buf, "%d\n", atomic_read(&private->avail)); -} -static MDEV_TYPE_ATTR_RO(available_instances); static struct attribute *mdev_types_attrs[] = { &mdev_type_attr_name.attr, - &mdev_type_attr_available_instances.attr, NULL, }; @@ -102,9 +91,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent); int ret; - if (atomic_dec_if_positive(&private->avail) < 0) - return -EPERM; - memset(&private->vdev, 0, sizeof(private->vdev)); vfio_init_group_dev(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops); @@ -118,13 +104,12 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev) ret = vfio_register_emulated_iommu_dev(&private->vdev); if (ret) - goto err_atomic; + goto err_init; dev_set_drvdata(&mdev->dev, private); return 0; -err_atomic: +err_init: vfio_uninit_group_dev(&private->vdev); - atomic_inc(&private->avail); private->mdev = NULL; return ret; } @@ -141,7 +126,6 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev) vfio_unregister_group_dev(&private->vdev); vfio_uninit_group_dev(&private->vdev); private->mdev = NULL; - atomic_inc(&private->avail); } static int vfio_ccw_mdev_open_device(struct vfio_device *vdev) @@ -610,6 +594,11 @@ static void vfio_ccw_mdev_request(struct vfio_device *vdev,
[PATCH v3 03/10] vfio/ccw: Pass vfio_ccw_private not mdev_device to various functions
mdev_device should only be used in functions assigned to ops callbacks, interior functions should use the struct vfio_ccw_private instead of repeatedly trying to get it from the mdev. Reviewed-by: Christoph Hellwig Reviewed-by: Cornelia Huck Reviewed-by: Eric Farman Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_ops.c | 37 + 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index 7f540ad0b568bc..1edbea9de0ec42 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -17,13 +17,11 @@ #include "vfio_ccw_private.h" -static int vfio_ccw_mdev_reset(struct mdev_device *mdev) +static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private) { - struct vfio_ccw_private *private; struct subchannel *sch; int ret; - private = dev_get_drvdata(mdev_parent_dev(mdev)); sch = private->sch; /* * TODO: @@ -61,7 +59,7 @@ static int vfio_ccw_mdev_notifier(struct notifier_block *nb, if (!cp_iova_pinned(&private->cp, unmap->iova)) return NOTIFY_OK; - if (vfio_ccw_mdev_reset(private->mdev)) + if (vfio_ccw_mdev_reset(private)) return NOTIFY_BAD; cp_free(&private->cp); @@ -201,7 +199,7 @@ static void vfio_ccw_mdev_close_device(struct mdev_device *mdev) if ((private->state != VFIO_CCW_STATE_NOT_OPER) && (private->state != VFIO_CCW_STATE_STANDBY)) { - if (!vfio_ccw_mdev_reset(mdev)) + if (!vfio_ccw_mdev_reset(private)) private->state = VFIO_CCW_STATE_STANDBY; /* The state will be NOT_OPER on error. */ } @@ -311,12 +309,9 @@ static ssize_t vfio_ccw_mdev_write(struct mdev_device *mdev, return -EINVAL; } -static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, -struct mdev_device *mdev) +static int vfio_ccw_mdev_get_device_info(struct vfio_ccw_private *private, +struct vfio_device_info *info) { - struct vfio_ccw_private *private; - - private = dev_get_drvdata(mdev_parent_dev(mdev)); info->flags = VFIO_DEVICE_FLAGS_CCW | VFIO_DEVICE_FLAGS_RESET; info->num_regions = VFIO_CCW_NUM_REGIONS + private->num_regions; info->num_irqs = VFIO_CCW_NUM_IRQS; @@ -324,14 +319,12 @@ static int vfio_ccw_mdev_get_device_info(struct vfio_device_info *info, return 0; } -static int vfio_ccw_mdev_get_region_info(struct vfio_region_info *info, -struct mdev_device *mdev, +static int vfio_ccw_mdev_get_region_info(struct vfio_ccw_private *private, +struct vfio_region_info *info, unsigned long arg) { - struct vfio_ccw_private *private; int i; - private = dev_get_drvdata(mdev_parent_dev(mdev)); switch (info->index) { case VFIO_CCW_CONFIG_REGION_INDEX: info->offset = 0; @@ -406,19 +399,16 @@ static int vfio_ccw_mdev_get_irq_info(struct vfio_irq_info *info) return 0; } -static int vfio_ccw_mdev_set_irqs(struct mdev_device *mdev, +static int vfio_ccw_mdev_set_irqs(struct vfio_ccw_private *private, uint32_t flags, uint32_t index, void __user *data) { - struct vfio_ccw_private *private; struct eventfd_ctx **ctx; if (!(flags & VFIO_IRQ_SET_ACTION_TRIGGER)) return -EINVAL; - private = dev_get_drvdata(mdev_parent_dev(mdev)); - switch (index) { case VFIO_CCW_IO_IRQ_INDEX: ctx = &private->io_trigger; @@ -524,6 +514,8 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, unsigned int cmd, unsigned long arg) { + struct vfio_ccw_private *private = + dev_get_drvdata(mdev_parent_dev(mdev)); int ret = 0; unsigned long minsz; @@ -540,7 +532,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, if (info.argsz < minsz) return -EINVAL; - ret = vfio_ccw_mdev_get_device_info(&info, mdev); + ret = vfio_ccw_mdev_get_device_info(private, &info); if (ret) return ret; @@ -558,7 +550,7 @@ static ssize_t vfio_ccw_mdev_ioctl(struct mdev_device *mdev, if (info.argsz < minsz) return -EINVAL; - ret = vfio_ccw_mdev_get_region_info(&info, mdev, arg); + ret = vfio_ccw_mdev_get_region_info(private, &info, arg); if (ret)
[PATCH v3 05/10] vfio/ccw: Make the FSM complete and synchronize it to the mdev
The subchannel should be left in a quiescent state unless the VFIO device FD is opened. When the FD is opened bring the chanel to active and allow the VFIO device to operate. When the device FD is closed then quiesce the channel. To make this work the FSM needs to handle the transitions to/from open and closed so everything is sequenced. Rename state NOT_OPER to BROKEN and use it wheneven the driver has malfunctioned. STANDBY becomes CLOSED. The normal case FSM looks like: CLOSED -> IDLE -> PROCESS/PENDING* -> IDLE -> CLOSED With a possible branch off to BROKEN from any state. Once the device is in BROKEN it cannot be recovered other than be reloading the driver. Delete the triply redundant calls to vfio_ccw_sch_quiesce(). vfio_ccw_mdev_close_device() always leaves the subchannel quiescent. vfio_ccw_mdev_remove() cannot return until vfio_ccw_mdev_close_device() completes and vfio_ccw_sch_remove() cannot return until vfio_ccw_mdev_remove() completes. Have the FSM code take care of calling cp_free() when appropriate. Device reset becomes a CLOSE/OPEN sequence which now properly handles the situation if the device becomes BROKEN. Machine shutdown via vfio_ccw_sch_shutdown() now simply tries to close and leaves the device BROKEN (though arguably the bus should take care to quiet down the subchannel HW during shutdown, not the drivers) Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_drv.c | 74 ++- drivers/s390/cio/vfio_ccw_fsm.c | 110 +--- drivers/s390/cio/vfio_ccw_ops.c | 49 - drivers/s390/cio/vfio_ccw_private.h | 12 +-- 4 files changed, 125 insertions(+), 120 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 0407427770955d..769edbbd164313 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -36,51 +36,6 @@ debug_info_t *vfio_ccw_debug_trace_id; /* * Helpers */ -int vfio_ccw_sch_quiesce(struct subchannel *sch) -{ - struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); - DECLARE_COMPLETION_ONSTACK(completion); - int iretry, ret = 0; - - spin_lock_irq(sch->lock); - if (!sch->schib.pmcw.ena) - goto out_unlock; - ret = cio_disable_subchannel(sch); - if (ret != -EBUSY) - goto out_unlock; - - iretry = 255; - do { - - ret = cio_cancel_halt_clear(sch, &iretry); - - if (ret == -EIO) { - pr_err("vfio_ccw: could not quiesce subchannel 0.%x.%04x!\n", - sch->schid.ssid, sch->schid.sch_no); - break; - } - - /* -* Flush all I/O and wait for -* cancel/halt/clear completion. -*/ - private->completion = &completion; - spin_unlock_irq(sch->lock); - - if (ret == -EBUSY) - wait_for_completion_timeout(&completion, 3*HZ); - - private->completion = NULL; - flush_workqueue(vfio_ccw_work_q); - spin_lock_irq(sch->lock); - ret = cio_disable_subchannel(sch); - } while (ret == -EBUSY); -out_unlock: - private->state = VFIO_CCW_STATE_NOT_OPER; - spin_unlock_irq(sch->lock); - return ret; -} - static void vfio_ccw_sch_io_todo(struct work_struct *work) { struct vfio_ccw_private *private; @@ -147,7 +102,7 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) private->sch = sch; mutex_init(&private->io_mutex); - private->state = VFIO_CCW_STATE_NOT_OPER; + private->state = VFIO_CCW_STATE_CLOSED; INIT_LIST_HEAD(&private->crw); INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); @@ -231,18 +186,9 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) dev_set_drvdata(&sch->dev, private); - spin_lock_irq(sch->lock); - sch->isc = VFIO_CCW_ISC; - ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch); - spin_unlock_irq(sch->lock); - if (ret) - goto out_free; - - private->state = VFIO_CCW_STATE_STANDBY; - ret = vfio_ccw_mdev_reg(sch); if (ret) - goto out_disable; + goto out_free; if (dev_get_uevent_suppress(&sch->dev)) { dev_set_uevent_suppress(&sch->dev, 0); @@ -254,8 +200,6 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) sch->schid.sch_no); return 0; -out_disable: - cio_disable_subchannel(sch); out_free: dev_set_drvdata(&sch->dev, NULL); vfio_ccw_free_private(private); @@ -266,7 +210,6 @@ static void vfio_ccw_sch_remove(struct subchannel *sch) { struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev); -
[PATCH v3 02/10] vfio/ccw: Use functions for alloc/free of the vfio_ccw_private
Makes the code easier to understand what is memory lifecycle and what is other stuff. Reviewed-by: Eric Farman Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_drv.c | 137 ++-- 1 file changed, 78 insertions(+), 59 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 371558ec92045d..e32678a71644fb 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -137,16 +137,80 @@ static void vfio_ccw_sch_irq(struct subchannel *sch) vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_INTERRUPT); } -static void vfio_ccw_free_regions(struct vfio_ccw_private *private) +static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch) { - if (private->crw_region) - kmem_cache_free(vfio_ccw_crw_region, private->crw_region); - if (private->schib_region) - kmem_cache_free(vfio_ccw_schib_region, private->schib_region); - if (private->cmd_region) - kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); - if (private->io_region) - kmem_cache_free(vfio_ccw_io_region, private->io_region); + struct vfio_ccw_private *private; + + private = kzalloc(sizeof(*private), GFP_KERNEL); + if (!private) + return ERR_PTR(-ENOMEM); + + private->sch = sch; + mutex_init(&private->io_mutex); + private->state = VFIO_CCW_STATE_NOT_OPER; + INIT_LIST_HEAD(&private->crw); + INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo); + INIT_WORK(&private->crw_work, vfio_ccw_crw_todo); + atomic_set(&private->avail, 1); + + private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), + GFP_KERNEL); + if (!private->cp.guest_cp) + goto out_free_private; + + private->io_region = kmem_cache_zalloc(vfio_ccw_io_region, + GFP_KERNEL | GFP_DMA); + if (!private->io_region) + goto out_free_cp; + + private->cmd_region = kmem_cache_zalloc(vfio_ccw_cmd_region, + GFP_KERNEL | GFP_DMA); + if (!private->cmd_region) + goto out_free_io; + + private->schib_region = kmem_cache_zalloc(vfio_ccw_schib_region, + GFP_KERNEL | GFP_DMA); + + if (!private->schib_region) + goto out_free_cmd; + + private->crw_region = kmem_cache_zalloc(vfio_ccw_crw_region, + GFP_KERNEL | GFP_DMA); + + if (!private->crw_region) + goto out_free_schib; + return private; + +out_free_schib: + kmem_cache_free(vfio_ccw_schib_region, private->schib_region); +out_free_cmd: + kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); +out_free_io: + kmem_cache_free(vfio_ccw_io_region, private->io_region); +out_free_cp: + kfree(private->cp.guest_cp); +out_free_private: + mutex_destroy(&private->io_mutex); + kfree(private); + return ERR_PTR(-ENOMEM); +} + +static void vfio_ccw_free_private(struct vfio_ccw_private *private) +{ + struct vfio_ccw_crw *crw, *temp; + + list_for_each_entry_safe(crw, temp, &private->crw, next) { + list_del(&crw->next); + kfree(crw); + } + + kmem_cache_free(vfio_ccw_crw_region, private->crw_region); + kmem_cache_free(vfio_ccw_schib_region, private->schib_region); + kmem_cache_free(vfio_ccw_cmd_region, private->cmd_region); + kmem_cache_free(vfio_ccw_io_region, private->io_region); + kfree(private->cp.guest_cp); + mutex_destroy(&private->io_mutex); + kfree(private); } static int vfio_ccw_sch_probe(struct subchannel *sch) @@ -161,53 +225,19 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) return -ENODEV; } - private = kzalloc(sizeof(*private), GFP_KERNEL); - if (!private) - return -ENOMEM; + private = vfio_ccw_alloc_private(sch); + if (IS_ERR(private)) + return PTR_ERR(private); - private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1), - GFP_KERNEL); - if (!private->cp.guest_cp) - goto out_free; - - private->io_region = kmem_cache_zalloc(vfio_ccw_io_region, - GFP_KERNEL | GFP_DMA); - if (!private->io_region) - goto out_free; - - private->cmd_region = kmem_cache_zalloc(vfio_ccw_cmd_region, - GFP_KERNEL | GFP_DMA); - if (!private->cmd_region) - goto out_free; - - private->schib_region = kmem_cache_zalloc(vfio_ccw_schib_region, - GFP_KERNEL | GFP_DMA); - -
[PATCH v3 08/10] vfio/ccw: Remove private->mdev
Having a mdev pointer floating about in addition to a struct vfio_device is confusing. It is only used for three things: - Getting the mdev 'struct device *' - this is the same as private->vdev.dev - Printing the uuid of the mdev in logging. The uuid is also the dev_name of the mdev so this is the same string as dev_name(private->vdev.dev) - A weird attempt to fence the vfio_ccw_sch_io_todo() work. This work is only queued during states IDLE/PROCESSING/PENDING and flushed when entering CLOSED. Thus the work already cannot run when the mdev is NULL. Remove it. Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_drv.c | 6 ++-- drivers/s390/cio/vfio_ccw_fsm.c | 48 + drivers/s390/cio/vfio_ccw_ops.c | 16 -- drivers/s390/cio/vfio_ccw_private.h | 2 -- include/linux/mdev.h| 4 --- 5 files changed, 30 insertions(+), 46 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index df9e1e265bca1a..18ad047811d111 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -64,7 +64,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work) * has finished. Do not overwrite a possible processing * state if the final interrupt was for HSCH or CSCH. */ - if (private->mdev && cp_is_finished) + if (cp_is_finished) private->state = VFIO_CCW_STATE_IDLE; if (private->io_trigger) @@ -302,8 +302,8 @@ static int vfio_ccw_chp_event(struct subchannel *sch, return 0; trace_vfio_ccw_chp_event(private->sch->schid, mask, event); - VFIO_CCW_MSG_EVENT(2, "%pUl (%x.%x.%04x): mask=0x%x event=%d\n", - mdev_uuid(private->mdev), sch->schid.cssid, + VFIO_CCW_MSG_EVENT(2, "%s (%x.%x.%04x): mask=0x%x event=%d\n", + dev_name(private->vdev.dev), sch->schid.cssid, sch->schid.ssid, sch->schid.sch_no, mask, event); diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c index 64ff1a5e3cb475..0d4d4f425befac 100644 --- a/drivers/s390/cio/vfio_ccw_fsm.c +++ b/drivers/s390/cio/vfio_ccw_fsm.c @@ -245,7 +245,6 @@ static void fsm_io_request(struct vfio_ccw_private *private, union orb *orb; union scsw *scsw = &private->scsw; struct ccw_io_region *io_region = private->io_region; - struct mdev_device *mdev = private->mdev; char *errstr = "request"; struct subchannel_id schid = get_schid(private); @@ -258,32 +257,30 @@ static void fsm_io_request(struct vfio_ccw_private *private, /* Don't try to build a cp if transport mode is specified. */ if (orb->tm.b) { io_region->ret_code = -EOPNOTSUPP; - VFIO_CCW_MSG_EVENT(2, - "%pUl (%x.%x.%04x): transport mode\n", - mdev_uuid(mdev), schid.cssid, - schid.ssid, schid.sch_no); + VFIO_CCW_MSG_EVENT( + 2, "%s (%x.%x.%04x): transport mode\n", + dev_name(private->vdev.dev), schid.cssid, + schid.ssid, schid.sch_no); errstr = "transport mode"; goto err_out; } - io_region->ret_code = cp_init(&private->cp, mdev_dev(mdev), + io_region->ret_code = cp_init(&private->cp, private->vdev.dev, orb); if (io_region->ret_code) { - VFIO_CCW_MSG_EVENT(2, - "%pUl (%x.%x.%04x): cp_init=%d\n", - mdev_uuid(mdev), schid.cssid, - schid.ssid, schid.sch_no, - io_region->ret_code); + VFIO_CCW_MSG_EVENT(2, "%s (%x.%x.%04x): cp_init=%d\n", + dev_name(private->vdev.dev), + schid.cssid, schid.ssid, + schid.sch_no, io_region->ret_code); errstr = "cp init"; goto err_out; } io_region->ret_code = cp_prefetch(&private->cp); if (io_region->ret_code) { - VFIO_CCW_MSG_EVENT(2, - "%pUl (%x.%x.%04x): cp_prefetch=%d\n", - mdev_uuid(mdev), schid.cssid, - schid.ssid, schid.sch_no, - io_region->ret_code); + VFIO_CCW_MSG_EVENT( +
[PATCH v3 04/10] vfio/ccw: Convert to use vfio_register_emulated_iommu_dev()
This is a more complicated conversion because vfio_ccw is sharing the vfio_device between both the mdev_device, its vfio_device and the css_driver. The mdev is a singleton, and the reason for this sharing is so the extra css_driver function callbacks to be delivered to the vfio_device implementation. This keeps things as they are, with the css_driver allocating the singleton, not the mdev_driver. Following patches work to clean this further. Embed the vfio_device in the vfio_ccw_private and instantiate it as a vfio_device when the mdev probes. The drvdata of both the css_device and the mdev_device point at the private, and container_of is used to get it back from the vfio_device. Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_drv.c | 21 -- drivers/s390/cio/vfio_ccw_ops.c | 107 +--- drivers/s390/cio/vfio_ccw_private.h | 5 ++ 3 files changed, 85 insertions(+), 48 deletions(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index e32678a71644fb..0407427770955d 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -468,7 +468,7 @@ static int __init vfio_ccw_sch_init(void) vfio_ccw_work_q = create_singlethread_workqueue("vfio-ccw"); if (!vfio_ccw_work_q) { ret = -ENOMEM; - goto out_err; + goto out_regions; } vfio_ccw_io_region = kmem_cache_create_usercopy("vfio_ccw_io_region", @@ -477,7 +477,7 @@ static int __init vfio_ccw_sch_init(void) sizeof(struct ccw_io_region), NULL); if (!vfio_ccw_io_region) { ret = -ENOMEM; - goto out_err; + goto out_regions; } vfio_ccw_cmd_region = kmem_cache_create_usercopy("vfio_ccw_cmd_region", @@ -486,7 +486,7 @@ static int __init vfio_ccw_sch_init(void) sizeof(struct ccw_cmd_region), NULL); if (!vfio_ccw_cmd_region) { ret = -ENOMEM; - goto out_err; + goto out_regions; } vfio_ccw_schib_region = kmem_cache_create_usercopy("vfio_ccw_schib_region", @@ -496,7 +496,7 @@ static int __init vfio_ccw_sch_init(void) if (!vfio_ccw_schib_region) { ret = -ENOMEM; - goto out_err; + goto out_regions; } vfio_ccw_crw_region = kmem_cache_create_usercopy("vfio_ccw_crw_region", @@ -506,19 +506,25 @@ static int __init vfio_ccw_sch_init(void) if (!vfio_ccw_crw_region) { ret = -ENOMEM; - goto out_err; + goto out_regions; } + ret = mdev_register_driver(&vfio_ccw_mdev_driver); + if (ret) + goto out_regions; + isc_register(VFIO_CCW_ISC); ret = css_driver_register(&vfio_ccw_sch_driver); if (ret) { isc_unregister(VFIO_CCW_ISC); - goto out_err; + goto out_driver; } return ret; -out_err: +out_driver: + mdev_unregister_driver(&vfio_ccw_mdev_driver); +out_regions: vfio_ccw_destroy_regions(); destroy_workqueue(vfio_ccw_work_q); vfio_ccw_debug_exit(); @@ -528,6 +534,7 @@ static int __init vfio_ccw_sch_init(void) static void __exit vfio_ccw_sch_exit(void) { css_driver_unregister(&vfio_ccw_sch_driver); + mdev_unregister_driver(&vfio_ccw_mdev_driver); isc_unregister(VFIO_CCW_ISC); vfio_ccw_destroy_regions(); destroy_workqueue(vfio_ccw_work_q); diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c index 1edbea9de0ec42..d8589afac272f1 100644 --- a/drivers/s390/cio/vfio_ccw_ops.c +++ b/drivers/s390/cio/vfio_ccw_ops.c @@ -17,6 +17,8 @@ #include "vfio_ccw_private.h" +static const struct vfio_device_ops vfio_ccw_dev_ops; + static int vfio_ccw_mdev_reset(struct vfio_ccw_private *private) { struct subchannel *sch; @@ -111,10 +113,10 @@ static struct attribute_group *mdev_type_groups[] = { NULL, }; -static int vfio_ccw_mdev_create(struct mdev_device *mdev) +static int vfio_ccw_mdev_probe(struct mdev_device *mdev) { - struct vfio_ccw_private *private = - dev_get_drvdata(mdev_parent_dev(mdev)); + struct vfio_ccw_private *private = dev_get_drvdata(mdev->dev.parent); + int ret; if (private->state == VFIO_CCW_STATE_NOT_OPER) return -ENODEV; @@ -122,6 +124,10 @@ static int vfio_ccw_mdev_create(struct mdev_device *mdev) if (atomic_dec_if_positive(&private->avail) < 0) return -EPERM; + memset(&private->vdev, 0, sizeof(private->vdev)); + vfio_init_group_dev(&private->vdev, &mdev->dev, + &vfio_ccw_dev_ops); + private->mdev = mdev; private->state = VFIO_CCW_STATE_IDLE; @@ -130,19 +136,31 @@ static int vfio_ccw_mdev_cre
[PATCH v3 00/10] Move vfio_ccw to the new mdev API
This addresses Cornelia's remark on the earlier patch that ccw has a confusing lifecycle. While it doesn't seem like the original attempt was functionally wrong, the result can be made better with a lot of further work. Reorganize the driver so that the mdev owns the private memory and controls the lifecycle, not the css_driver. The memory associated with the css_driver lifecycle is only the mdev_parent/mdev_type registration. Along the way we change when the sch is quiescent or not to be linked to the open/close_device lifetime of the vfio_device, which is sort of what it was tring to do already, just not completely. The troublesome racey lifecycle of the css_driver callbacks is made clear with simple vfio_device refcounting so a callback is only delivered into a registered vfio_device and has obvious correctness. Move the only per-css_driver state, the "available instance" counter, into the core code and share that logic with many of the other drivers. The value is kept in the mdev_type memory. This is on github: https://github.com/jgunthorpe/linux/commits/vfio_ccw v3: - Rebase to Christoph's group work & rc3; use vfio_register_emulated_iommu_dev() - Remove GFP_DMA - Order mdev_unregister_driver() symmetrically with init - Rework what is considered a BROKEN event in fsm_close() - NOP both CCW_EVENT_OPEN/CLOSE - Documentation updates - Remane goto label to err_init vfio_ccw_mdev_probe() - Fix NULL pointer deref in mdev_device_create() v2: https://lore.kernel.org/r/0-v2-7d3a384024cf+2060-ccw_mdev_...@nvidia.com - Clean up the lifecycle in ccw with 7 new patches - Rebase v1: https://lore.kernel.org/all/7-v2-7667f42c9bad+935-vfio3_...@nvidia.com Jason Gunthorpe (10): vfio/ccw: Remove unneeded GFP_DMA vfio/ccw: Use functions for alloc/free of the vfio_ccw_private vfio/ccw: Pass vfio_ccw_private not mdev_device to various functions vfio/ccw: Convert to use vfio_register_emulated_iommu_dev() vfio/ccw: Make the FSM complete and synchronize it to the mdev vfio/mdev: Consolidate all the device_api sysfs into the core code vfio/mdev: Add mdev available instance checking to the core vfio/ccw: Remove private->mdev vfio: Export vfio_device_try_get() vfio/ccw: Move the lifecycle of the struct vfio_ccw_private to the mdev .../driver-api/vfio-mediated-device.rst | 8 +- drivers/gpu/drm/i915/gvt/kvmgt.c | 9 +- drivers/s390/cio/vfio_ccw_drv.c | 282 -- drivers/s390/cio/vfio_ccw_fsm.c | 158 +++--- drivers/s390/cio/vfio_ccw_ops.c | 240 +++ drivers/s390/cio/vfio_ccw_private.h | 42 ++- drivers/s390/crypto/vfio_ap_ops.c | 41 +-- drivers/s390/crypto/vfio_ap_private.h | 2 - drivers/vfio/mdev/mdev_core.c | 13 +- drivers/vfio/mdev/mdev_private.h | 2 + drivers/vfio/mdev/mdev_sysfs.c| 64 +++- drivers/vfio/vfio.c | 3 +- include/linux/mdev.h | 13 +- include/linux/vfio.h | 1 + samples/vfio-mdev/mbochs.c| 9 +- samples/vfio-mdev/mdpy.c | 31 +- samples/vfio-mdev/mtty.c | 10 +- 17 files changed, 482 insertions(+), 446 deletions(-) base-commit: d9a0cd510c3383b61db6f70a84e0c3487f836a63 -- 2.33.0
[PATCH v3 01/10] vfio/ccw: Remove unneeded GFP_DMA
Since the ccw_io_region was split out of the private the allocation no longer needs the GFP_DMA. Remove it. Reported-by: Christoph Hellwig Fixes: c98e16b2fa12 ("s390/cio: Convert ccw_io_region to pointer") Signed-off-by: Jason Gunthorpe --- drivers/s390/cio/vfio_ccw_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index 76099bcb765b45..371558ec92045d 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -161,7 +161,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch) return -ENODEV; } - private = kzalloc(sizeof(*private), GFP_KERNEL | GFP_DMA); + private = kzalloc(sizeof(*private), GFP_KERNEL); if (!private) return -ENOMEM; -- 2.33.0
Re: [PULL] drm-fixes
The pull request you sent on Fri, 1 Oct 2021 18:57:06 +0200: > git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2021-10-01 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/24f67d82c43c9c594821ee1bc4367a23d89d9f8b Thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html
Re: [PATCH] drm/msm/dp: Remove redundant initialization of variable bpp
On 29/09/2021 13:54, Colin King wrote: From: Colin Ian King The variable bpp is being initialized with a value that is never read, it is being updated later on in both paths of an if statement. The assignment is redundant and can be removed. Addresses-Coverity: ("Unused value") Signed-off-by: Colin Ian King Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dp/dp_panel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c index 2181b60e1d1d..71db10c0f262 100644 --- a/drivers/gpu/drm/msm/dp/dp_panel.c +++ b/drivers/gpu/drm/msm/dp/dp_panel.c @@ -234,7 +234,7 @@ u32 dp_panel_get_mode_bpp(struct dp_panel *dp_panel, u32 mode_edid_bpp, u32 mode_pclk_khz) { struct dp_panel_private *panel; - u32 bpp = mode_edid_bpp; + u32 bpp; if (!dp_panel || !mode_edid_bpp || !mode_pclk_khz) { DRM_ERROR("invalid input\n"); -- With best wishes Dmitry
[PATCH v3 5/5] drm/msm/dp: Allow sub-regions to be specified in DT
Not all platforms has P0 at an offset of 0x1000 from the base address, so add support for specifying each sub-region in DT. The code falls back to the predefined offsets in the case that only a single reg is specified, in order to support existing DT. Reviewed-by: Stephen Boyd Reviewed-by: Abhinav Kumar Signed-off-by: Bjorn Andersson --- Changes since v2: - None drivers/gpu/drm/msm/dp/dp_parser.c | 49 +++--- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 1f084b2b5bd3..4d6e047f803d 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -50,18 +50,45 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) if (IS_ERR(dss->ahb.base)) return PTR_ERR(dss->ahb.base); - if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { - DRM_ERROR("legacy memory region not large enough\n"); - return -EINVAL; - } + dss->aux.base = dp_ioremap(pdev, 1, &dss->aux.len); + if (IS_ERR(dss->aux.base)) { + /* +* The initial binding had a single reg, but in order to +* support variation in the sub-region sizes this was split. +* dp_ioremap() will fail with -ENODEV here if only a single +* reg is specified, so fill in the sub-region offsets and +* lengths based on this single region. +*/ + if (PTR_ERR(dss->aux.base) == -ENODEV) { + if (dss->ahb.len < DP_DEFAULT_P0_OFFSET + DP_DEFAULT_P0_SIZE) { + DRM_ERROR("legacy memory region not large enough\n"); + return -EINVAL; + } + + dss->ahb.len = DP_DEFAULT_AHB_SIZE; + dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET; + dss->aux.len = DP_DEFAULT_AUX_SIZE; + dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET; + dss->link.len = DP_DEFAULT_LINK_SIZE; + dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET; + dss->p0.len = DP_DEFAULT_P0_SIZE; + } else { + DRM_ERROR("unable to remap aux region: %pe\n", dss->aux.base); + return PTR_ERR(dss->aux.base); + } + } else { + dss->link.base = dp_ioremap(pdev, 2, &dss->link.len); + if (IS_ERR(dss->link.base)) { + DRM_ERROR("unable to remap link region: %pe\n", dss->link.base); + return PTR_ERR(dss->link.base); + } - dss->ahb.len = DP_DEFAULT_AHB_SIZE; - dss->aux.base = dss->ahb.base + DP_DEFAULT_AUX_OFFSET; - dss->aux.len = DP_DEFAULT_AUX_SIZE; - dss->link.base = dss->ahb.base + DP_DEFAULT_LINK_OFFSET; - dss->link.len = DP_DEFAULT_LINK_SIZE; - dss->p0.base = dss->ahb.base + DP_DEFAULT_P0_OFFSET; - dss->p0.len = DP_DEFAULT_P0_SIZE; + dss->p0.base = dp_ioremap(pdev, 3, &dss->p0.len); + if (IS_ERR(dss->p0.base)) { + DRM_ERROR("unable to remap p0 region: %pe\n", dss->p0.base); + return PTR_ERR(dss->p0.base); + } + } io->phy = devm_phy_get(&pdev->dev, "dp"); if (IS_ERR(io->phy)) -- 2.29.2
[PATCH v3 3/5] drm/msm/dp: Refactor ioremap wrapper
In order to deal with multiple memory ranges in the following commit change the ioremap wrapper to not poke directly into the dss_io_data struct. While at it, devm_ioremap_resource() already prints useful error messages on failure, so omit the unnecessary prints from the caller. Signed-off-by: Bjorn Andersson --- Changes since v2: - Switched to devm_platform_get_and_ioremap_resource() drivers/gpu/drm/msm/dp/dp_parser.c | 35 ++ drivers/gpu/drm/msm/dp/dp_parser.h | 2 +- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index c064ced78278..c05ba1990218 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -19,40 +19,27 @@ static const struct dp_regulator_cfg sdm845_dp_reg_cfg = { }, }; -static int msm_dss_ioremap(struct platform_device *pdev, - struct dss_io_data *io_data) +static void __iomem *dp_ioremap(struct platform_device *pdev, int idx, size_t *len) { - struct resource *res = NULL; + struct resource *res; + void __iomem *base; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - DRM_ERROR("%pS->%s: msm_dss_get_res failed\n", - __builtin_return_address(0), __func__); - return -ENODEV; - } - - io_data->len = (u32)resource_size(res); - io_data->base = devm_ioremap(&pdev->dev, res->start, io_data->len); - if (!io_data->base) { - DRM_ERROR("%pS->%s: ioremap failed\n", - __builtin_return_address(0), __func__); - return -EIO; - } + base = devm_platform_get_and_ioremap_resource(pdev, idx, &res); + if (!IS_ERR(base)) + *len = resource_size(res); - return 0; + return base; } static int dp_parser_ctrl_res(struct dp_parser *parser) { - int rc = 0; struct platform_device *pdev = parser->pdev; struct dp_io *io = &parser->io; + struct dss_io_data *dss = &io->dp_controller; - rc = msm_dss_ioremap(pdev, &io->dp_controller); - if (rc) { - DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc); - return rc; - } + dss->base = dp_ioremap(pdev, 0, &dss->len); + if (IS_ERR(dss->base)) + return PTR_ERR(dss->base); io->phy = devm_phy_get(&pdev->dev, "dp"); if (IS_ERR(io->phy)) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.h b/drivers/gpu/drm/msm/dp/dp_parser.h index 34b49628bbaf..dc62e70b1640 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.h +++ b/drivers/gpu/drm/msm/dp/dp_parser.h @@ -26,7 +26,7 @@ enum dp_pm_type { }; struct dss_io_data { - u32 len; + size_t len; void __iomem *base; }; -- 2.29.2
[PATCH v3 4/5] drm/msm/dp: Store each subblock in the io region
Not all platforms has DP_P0 at offset 0x1000 from the beginning of the DP block. So split the dss_io_data memory region into a set of sub-regions, to make it possible in the next patch to specify each of the sub-regions individually. Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- Changes since v2: - Skipped the unnecessary reorder in struct dss_io_region drivers/gpu/drm/msm/dp/dp_catalog.c | 64 + drivers/gpu/drm/msm/dp/dp_parser.c | 28 +++-- drivers/gpu/drm/msm/dp/dp_parser.h | 9 +++- 3 files changed, 53 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c index cc2bb8295329..6ae9b29044b6 100644 --- a/drivers/gpu/drm/msm/dp/dp_catalog.c +++ b/drivers/gpu/drm/msm/dp/dp_catalog.c @@ -24,15 +24,6 @@ #define DP_INTERRUPT_STATUS_ACK_SHIFT 1 #define DP_INTERRUPT_STATUS_MASK_SHIFT 2 -#define MSM_DP_CONTROLLER_AHB_OFFSET 0x -#define MSM_DP_CONTROLLER_AHB_SIZE 0x0200 -#define MSM_DP_CONTROLLER_AUX_OFFSET 0x0200 -#define MSM_DP_CONTROLLER_AUX_SIZE 0x0200 -#define MSM_DP_CONTROLLER_LINK_OFFSET 0x0400 -#define MSM_DP_CONTROLLER_LINK_SIZE0x0C00 -#define MSM_DP_CONTROLLER_P0_OFFSET0x1000 -#define MSM_DP_CONTROLLER_P0_SIZE 0x0400 - #define DP_INTERRUPT_STATUS1 \ (DP_INTR_AUX_I2C_DONE| \ DP_INTR_WRONG_ADDR | DP_INTR_TIMEOUT | \ @@ -66,82 +57,77 @@ void dp_catalog_snapshot(struct dp_catalog *dp_catalog, struct msm_disp_state *d { struct dp_catalog_private *catalog = container_of(dp_catalog, struct dp_catalog_private, dp_catalog); + struct dss_io_data *dss = &catalog->io->dp_controller; - msm_disp_snapshot_add_block(disp_state, catalog->io->dp_controller.len, - catalog->io->dp_controller.base, "dp_ctrl"); + msm_disp_snapshot_add_block(disp_state, dss->ahb.len, dss->ahb.base, "dp_ahb"); + msm_disp_snapshot_add_block(disp_state, dss->aux.len, dss->aux.base, "dp_aux"); + msm_disp_snapshot_add_block(disp_state, dss->link.len, dss->link.base, "dp_link"); + msm_disp_snapshot_add_block(disp_state, dss->p0.len, dss->p0.base, "dp_p0"); } static inline u32 dp_read_aux(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_AUX_OFFSET; - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.aux.base + offset); } static inline void dp_write_aux(struct dp_catalog_private *catalog, u32 offset, u32 data) { - offset += MSM_DP_CONTROLLER_AUX_OFFSET; /* * To make sure aux reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.base + offset); + writel(data, catalog->io->dp_controller.aux.base + offset); } static inline u32 dp_read_ahb(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_AHB_OFFSET; - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.ahb.base + offset); } static inline void dp_write_ahb(struct dp_catalog_private *catalog, u32 offset, u32 data) { - offset += MSM_DP_CONTROLLER_AHB_OFFSET; /* * To make sure phy reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.base + offset); + writel(data, catalog->io->dp_controller.ahb.base + offset); } static inline void dp_write_p0(struct dp_catalog_private *catalog, u32 offset, u32 data) { - offset += MSM_DP_CONTROLLER_P0_OFFSET; /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - writel(data, catalog->io->dp_controller.base + offset); + writel(data, catalog->io->dp_controller.p0.base + offset); } static inline u32 dp_read_p0(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_P0_OFFSET; /* * To make sure interface reg writes happens before any other operation, * this function uses writel() instread of writel_relaxed() */ - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.p0.base + offset); } static inline u32 dp_read_link(struct dp_catalog_private *catalog, u32 offset) { - offset += MSM_DP_CONTROLLER_LINK_OFFSET; - return readl_relaxed(catalog->io->dp_controller.base + offset); + return readl_relaxed(catalog->io->dp_controller.link.base + offset); } stat
[PATCH v3 1/5] dt-bindings: msm/dp: Change reg definition
reg was defined as one region covering the entire DP block, but the memory map is actually split in 4 regions and obviously the size of these regions differs between platforms. Switch the reg to require that all four regions are specified instead. It is expected that the implementation will handle existing DTBs, even though the schema defines the new layout. Reviewed-by: Stephen Boyd Reviewed-by: Rob Herring Signed-off-by: Bjorn Andersson --- Changes since v2: - None .../bindings/display/msm/dp-controller.yaml | 13 +++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml index d89b3c510c27..6bb424c21340 100644 --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml @@ -19,7 +19,12 @@ properties: - qcom,sc7180-dp reg: -maxItems: 1 +items: + - description: ahb register block + - description: aux register block + - description: link register block + - description: p0 register block + - description: p1 register block interrupts: maxItems: 1 @@ -99,7 +104,11 @@ examples: displayport-controller@ae9 { compatible = "qcom,sc7180-dp"; -reg = <0xae9 0x1400>; +reg = <0xae9 0x200>, + <0xae90200 0x200>, + <0xae90400 0xc00>, + <0xae91000 0x400>, + <0xae91400 0x400>; interrupt-parent = <&mdss>; interrupts = <12>; clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, -- 2.29.2
[PATCH v3 2/5] drm/msm/dp: Use devres for ioremap()
The non-devres version of ioremap is used, which requires manual cleanup. But the code paths leading here is mixed with other devres users, so rely on this for ioremap as well to simplify the code. Reviewed-by: Abhinav Kumar Reviewed-by: Stephen Boyd Signed-off-by: Bjorn Andersson --- Changes since v2: - None drivers/gpu/drm/msm/dp/dp_parser.c | 29 - 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_parser.c b/drivers/gpu/drm/msm/dp/dp_parser.c index 0519dd3ac3c3..c064ced78278 100644 --- a/drivers/gpu/drm/msm/dp/dp_parser.c +++ b/drivers/gpu/drm/msm/dp/dp_parser.c @@ -32,7 +32,7 @@ static int msm_dss_ioremap(struct platform_device *pdev, } io_data->len = (u32)resource_size(res); - io_data->base = ioremap(res->start, io_data->len); + io_data->base = devm_ioremap(&pdev->dev, res->start, io_data->len); if (!io_data->base) { DRM_ERROR("%pS->%s: ioremap failed\n", __builtin_return_address(0), __func__); @@ -42,22 +42,6 @@ static int msm_dss_ioremap(struct platform_device *pdev, return 0; } -static void msm_dss_iounmap(struct dss_io_data *io_data) -{ - if (io_data->base) { - iounmap(io_data->base); - io_data->base = NULL; - } - io_data->len = 0; -} - -static void dp_parser_unmap_io_resources(struct dp_parser *parser) -{ - struct dp_io *io = &parser->io; - - msm_dss_iounmap(&io->dp_controller); -} - static int dp_parser_ctrl_res(struct dp_parser *parser) { int rc = 0; @@ -67,19 +51,14 @@ static int dp_parser_ctrl_res(struct dp_parser *parser) rc = msm_dss_ioremap(pdev, &io->dp_controller); if (rc) { DRM_ERROR("unable to remap dp io resources, rc=%d\n", rc); - goto err; + return rc; } io->phy = devm_phy_get(&pdev->dev, "dp"); - if (IS_ERR(io->phy)) { - rc = PTR_ERR(io->phy); - goto err; - } + if (IS_ERR(io->phy)) + return PTR_ERR(io->phy); return 0; -err: - dp_parser_unmap_io_resources(parser); - return rc; } static int dp_parser_misc(struct dp_parser *parser) -- 2.29.2
[PATCH v3 0/5] drm/msm/dp: Allow variation in register regions
It turns out that sc8180x (among others) doesn't have the same internal layout of the 4 subblocks. This series therefor modifies the binding to require all four regions to be described individually and then extends the driver to read these four regions. The driver will fall back to read the old single-reg format and apply the original offsets and sizes. Bjorn Andersson (5): dt-bindings: msm/dp: Change reg definition drm/msm/dp: Use devres for ioremap() drm/msm/dp: Refactor ioremap wrapper drm/msm/dp: Store each subblock in the io region drm/msm/dp: Allow sub-regions to be specified in DT .../bindings/display/msm/dp-controller.yaml | 13 ++- drivers/gpu/drm/msm/dp/dp_catalog.c | 64 --- drivers/gpu/drm/msm/dp/dp_parser.c| 102 ++ drivers/gpu/drm/msm/dp/dp_parser.h| 11 +- 4 files changed, 100 insertions(+), 90 deletions(-) -- 2.29.2
Re: [RFC] drm/msm/a6xx: Serialize GMU communication
On 27/09/2021 21:03, Rob Clark wrote: From: Rob Clark I've seen some crashes in our crash reporting that *look* like multiple threads stomping on each other while communicating with GMU. So wrap all those paths in a lock. Signed-off-by: Rob Clark --- Are we allowed to use c99/gnu99 yet? drivers/gpu/drm/msm/Makefile | 2 +- drivers/gpu/drm/msm/adreno/a6xx_gmu.c | 6 drivers/gpu/drm/msm/adreno/a6xx_gmu.h | 9 + drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 50 --- 4 files changed, 54 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 904535eda0c4..57283bbad3f0 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -ccflags-y := -I $(srctree)/$(src) +ccflags-y := -I $(srctree)/$(src) -std=gnu99 ccflags-y += -I $(srctree)/$(src)/disp/dpu1 ccflags-$(CONFIG_DRM_MSM_DSI) += -I $(srctree)/$(src)/dsi ccflags-$(CONFIG_DRM_MSM_DP) += -I $(srctree)/$(src)/dp diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c index a7c58018959f..8b73f70766a4 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c @@ -296,6 +296,8 @@ int a6xx_gmu_set_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) u32 val; int request, ack; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return -EINVAL; @@ -337,6 +339,8 @@ void a6xx_gmu_clear_oob(struct a6xx_gmu *gmu, enum a6xx_gmu_oob_state state) { int bit; + WARN_ON_ONCE(!mutex_is_locked(&gmu->lock)); + if (state >= ARRAY_SIZE(a6xx_gmu_oob_bits)) return; @@ -1482,6 +1486,8 @@ int a6xx_gmu_init(struct a6xx_gpu *a6xx_gpu, struct device_node *node) if (!pdev) return -ENODEV; + mutex_init(&gmu->lock); + gmu->dev = &pdev->dev; of_dma_configure(gmu->dev, node, true); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h index 3c74f64e3126..f05a00c0afd0 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.h +++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.h @@ -44,6 +44,9 @@ struct a6xx_gmu_bo { struct a6xx_gmu { struct device *dev; + /* For serializing communication with the GMU: */ + struct mutex lock; + struct msm_gem_address_space *aspace; void * __iomem mmio; @@ -88,6 +91,12 @@ struct a6xx_gmu { bool legacy; /* a618 or a630 */ }; +/* Helper macro for serializing GMU access: */ +#define with_gmu_lock(gmu) \ + for (bool done = ({ mutex_lock(&(gmu)->lock); false; }); \ + !done; \ + done = ({ mutex_unlock(&(gmu)->lock); true; })) The intent is good, but I'm not sure this kind of syntax sugar would be a good approach. What about calling lock/unlock explicitly, like we typically do? Then we won't have to use c99. + static inline u32 gmu_read(struct a6xx_gmu *gmu, u32 offset) { return msm_readl(gmu->mmio + (offset << 2)); diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index f6a4dbef796b..5e1ae3df42ba 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -881,7 +881,7 @@ static int a6xx_zap_shader_init(struct msm_gpu *gpu) A6XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A6XX_RBBM_INT_0_MASK_UCHE_TRAP_INTR) -static int a6xx_hw_init(struct msm_gpu *gpu) +static int hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); @@ -1135,6 +1135,19 @@ static int a6xx_hw_init(struct msm_gpu *gpu) return ret; } +static int a6xx_hw_init(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); + int ret; + + with_gmu_lock(&a6xx_gpu->gmu) { + ret = hw_init(gpu); + } + + return ret; +} + static void a6xx_dump(struct msm_gpu *gpu) { DRM_DEV_INFO(&gpu->pdev->dev, "status: %08x\n", @@ -1509,7 +1522,9 @@ static int a6xx_pm_resume(struct msm_gpu *gpu) trace_msm_gpu_resume(0); - ret = a6xx_gmu_resume(a6xx_gpu); + with_gmu_lock(&a6xx_gpu->gmu) { + ret = a6xx_gmu_resume(a6xx_gpu); + } if (ret) return ret; @@ -1532,7 +1547,9 @@ static int a6xx_pm_suspend(struct msm_gpu *gpu) msm_devfreq_suspend(gpu); - ret = a6xx_gmu_stop(a6xx_gpu); + with_gmu_lock(&a6xx_gpu->gmu) { + ret = a6xx_gmu_stop(a6xx_gpu); + } if (ret) return ret; @@ -1547,18 +1564,17 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
Re: [PATCH v2 1/5] [RFC]iommu: Add a IOMMU_DEVONLY protection flag
> The IOMMU_DEVONLY flag allows the caller to flag a mappings backed by > device-private buffers. That means other devices or CPUs are not > expected to access the physical memory region pointed by the mapping, > and the MMU driver can safely restrict the shareability domain to the > device itself. > > Will be used by the ARM MMU driver to flag Mali mappings accessed only > by the GPU as Inner-shareable. > > Signed-off-by: Boris Brezillon > --- > include/linux/iommu.h | 7 +++ > 1 file changed, 7 insertions(+) > > diff --git a/include/linux/iommu.h b/include/linux/iommu.h > index d2f3435e7d17..db14781b522f 100644 > --- a/include/linux/iommu.h > +++ b/include/linux/iommu.h > @@ -31,6 +31,13 @@ > * if the IOMMU page table format is equivalent. > */ > #define IOMMU_PRIV (1 << 5) > +/* > + * Mapping is only accessed by the device behind the iommu. That means other > + * devices or CPUs are not expected to access this physical memory region, > + * and the MMU driver can safely restrict the shareability domain to the > + * device itself. > + */ > +#define IOMMU_DEVONLY(1 << 6) > > struct iommu_ops; > struct iommu_group; This seems totally reasonable to me, but it is well-known that I'm not on good terms with the iommu subsystem. Let's wait for Robin to NAK :-P
Re: [PATCH v2 4/5] drm/panfrost: Add a PANFROST_BO_GPUONLY flag
> > This seems reasonable to me - it matches the kbase > > BASE_MEM_COHERENT_SYSTEM (only backwards obviously) and it worked > > reasonably well for the blob. Oh, is that what that was for? I remember seeing it set on Midgard for varyings. Good to go full circle now. > > But I'm wondering if we need to do anything special to deal with the > > fact we will now have some non-coherent mappings on an otherwise > > coherent device. > > > > There are certainly some oddities around how these buffers will be > > mapped into user space if requested, e.g. panfrost_gem_create_object() > > sets 'map_wc' based on pfdev->coherent which is arguably wrong for > > GPUONLY. So there are two things we could consider: > > > > a) Actually prevent user space mapping GPUONLY flagged buffers. Which > > matches the intention of the name. > > I intended to do that, just forgot to add wrappers around > drm_gem_shmem_{mmap,vmap}() to forbid CPU-mappings on gpuonly buffers. This feels like the cleaner solution to me. > > b) Attempt to provide user space with the tools to safely interact with > > the buffers (this is the kbase approach). This does have the benefit of > > allowing *mostly* GPU access. An example here is the tiler heap where > > the CPU could zero out as necessary but mostly the GPU has ownership and > > the CPU never reads the contents. GPUONLY/DEVONLY might not be the best > > name in that case. > > Uh, right, I forgot we had to zero the tiler heap on Midgard (most of > the time done with a WRITE_VALUE job, but there's an exception on some > old Midgard GPUs IIRC). "Attempt" is the key word here :| We indeed only touch the tiler heap from the CPU on v4, and life's too short to care about new optimizations for v4. Unless the patch is trivial, my vote is for a) preventing the mappings and only setting GPUONLY on the tiler_heap starting with v5.
Re: [PATCH v2 1/3] drm/msm/dsi: Support NO_CONNECTOR bridges
On 21/09/2021 01:57, Rob Clark wrote: From: Rob Clark For now, since we have a mix of bridges which support this flag, which which do *not* support this flag, or work both ways, try it once with NO_CONNECTOR and then fall back to the old way if that doesn't work. Eventually we can drop the fallback path. v2: Add missing drm_connector_attach_encoder() so display actually comes up when the bridge properly handles the NO_CONNECTOR flag Signed-off-by: Rob Clark Reviewed-by: Laurent Pinchart Reviewed-by: Dmitry Baryshkov I think this patch can go through the drm/msm, while two other patches would need to through the drm-misc. Is it correct? --- drivers/gpu/drm/msm/Kconfig | 2 ++ drivers/gpu/drm/msm/dsi/dsi_manager.c | 50 --- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index e9c6af78b1d7..36e5ba3ccc28 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -14,6 +14,8 @@ config DRM_MSM select REGULATOR select DRM_KMS_HELPER select DRM_PANEL + select DRM_BRIDGE + select DRM_PANEL_BRIDGE select DRM_SCHED select SHMEM select TMPFS diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c41d39f5b7cf..e25877073d31 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -3,6 +3,8 @@ * Copyright (c) 2015, The Linux Foundation. All rights reserved. */ +#include "drm/drm_bridge_connector.h" + #include "msm_kms.h" #include "dsi.h" @@ -688,10 +690,10 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id) { struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id); struct drm_device *dev = msm_dsi->dev; + struct drm_connector *connector; struct drm_encoder *encoder; struct drm_bridge *int_bridge, *ext_bridge; - struct drm_connector *connector; - struct list_head *connector_list; + int ret; int_bridge = msm_dsi->bridge; ext_bridge = msm_dsi->external_bridge = @@ -699,22 +701,44 @@ struct drm_connector *msm_dsi_manager_ext_bridge_init(u8 id) encoder = msm_dsi->encoder; - /* link the internal dsi bridge to the external bridge */ - drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); - /* -* we need the drm_connector created by the external bridge -* driver (or someone else) to feed it to our driver's -* priv->connector[] list, mainly for msm_fbdev_init() +* Try first to create the bridge without it creating its own +* connector.. currently some bridges support this, and others +* do not (and some support both modes) */ - connector_list = &dev->mode_config.connector_list; + ret = drm_bridge_attach(encoder, ext_bridge, int_bridge, + DRM_BRIDGE_ATTACH_NO_CONNECTOR); + if (ret == -EINVAL) { + struct drm_connector *connector; + struct list_head *connector_list; + + /* link the internal dsi bridge to the external bridge */ + drm_bridge_attach(encoder, ext_bridge, int_bridge, 0); + + /* +* we need the drm_connector created by the external bridge +* driver (or someone else) to feed it to our driver's +* priv->connector[] list, mainly for msm_fbdev_init() +*/ + connector_list = &dev->mode_config.connector_list; - list_for_each_entry(connector, connector_list, head) { - if (drm_connector_has_possible_encoder(connector, encoder)) - return connector; + list_for_each_entry(connector, connector_list, head) { + if (drm_connector_has_possible_encoder(connector, encoder)) + return connector; + } + + return ERR_PTR(-ENODEV); + } + + connector = drm_bridge_connector_init(dev, encoder); + if (IS_ERR(connector)) { + DRM_ERROR("Unable to create bridge connector\n"); + return ERR_CAST(connector); } - return ERR_PTR(-ENODEV); + drm_connector_attach_encoder(connector, encoder); + + return connector; } void msm_dsi_manager_bridge_destroy(struct drm_bridge *bridge) -- With best wishes Dmitry
Re: [PATCH] drm: msm: hdmi: Constify static structs
On 21/09/2021 00:20, Rikard Falkeborn wrote: The only usage of hdmi_8996_pll_ops is to assign its address to the ops field in the clk_init_data struct, and the only usage of pll_init is to assign its address to the init field in the clk_hw struct, both which are pointers to const. Make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c index a8f3b2cbfdc5..99c7853353fd 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c @@ -682,7 +682,7 @@ static int hdmi_8996_pll_is_enabled(struct clk_hw *hw) return pll_locked; } -static struct clk_ops hdmi_8996_pll_ops = { +static const struct clk_ops hdmi_8996_pll_ops = { .set_rate = hdmi_8996_pll_set_clk_rate, .round_rate = hdmi_8996_pll_round_rate, .recalc_rate = hdmi_8996_pll_recalc_rate, @@ -695,7 +695,7 @@ static const char * const hdmi_pll_parents[] = { "xo", }; -static struct clk_init_data pll_init = { +static const struct clk_init_data pll_init = { .name = "hdmipll", .ops = &hdmi_8996_pll_ops, .parent_names = hdmi_pll_parents, -- With best wishes Dmitry
Re: [PATCH] drm/msm: Avoid potential overflow in timeout_to_jiffies()
On 17/09/2021 03:59, Marek Vasut wrote: The return type of ktime_divns() is s64. The timeout_to_jiffies() currently assigns the result of this ktime_divns() to unsigned long, which on 32 bit systems may overflow. Furthermore, the result of this function is sometimes also passed to functions which expect signed long, dma_fence_wait_timeout() is one such example. Fix this by adjusting the type of remaining_jiffies to s64, so we do not suffer overflow there, and return a value limited to range of 0..INT_MAX, which is safe for all usecases of this timeout. The above overflow can be triggered if userspace passes in too large timeout value, larger than INT_MAX / HZ seconds. The kernel detects it and complains about "schedule_timeout: wrong timeout value %lx" and generates a warning backtrace. Note that this fixes commit 6cedb8b377bb ("drm/msm: avoid using 'timespec'"), because the previously used timespec_to_jiffies() function returned unsigned long instead of s64: static inline unsigned long timespec_to_jiffies(const struct timespec *value) Fixes: 6cedb8b377bb ("drm/msm: avoid using 'timespec'") Signed-off-by: Marek Vasut Cc: Arnd Bergmann Cc: Jordan Crouse Cc: Rob Clark Cc: sta...@vger.kernel.org # 5.6+ Reviewed-by: Dmitry Baryshkov --- NOTE: This is related to Mesa MR https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12886 --- drivers/gpu/drm/msm/msm_drv.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 0b2686b060c73..d96b254b8aa46 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -543,7 +543,7 @@ static inline int align_pitch(int width, int bpp) static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) { ktime_t now = ktime_get(); - unsigned long remaining_jiffies; + s64 remaining_jiffies; if (ktime_compare(*timeout, now) < 0) { remaining_jiffies = 0; @@ -552,7 +552,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); } - return remaining_jiffies; + return clamp(remaining_jiffies, 0LL, (s64)INT_MAX); } #endif /* __MSM_DRV_H__ */ -- With best wishes Dmitry
Re: [PATCH] drm/msm/dsi: dsi_phy_14nm: Take ready-bit into account in poll_for_ready
On 06/09/2021 23:25, Marijn Suijten wrote: The downstream driver models this PLL lock check as an if-elseif-else. The only way to reach the else case where pll_locked=true [1] is by succeeding both readl_poll_timeout_atomic calls (which return zero on success) in the if _and_ elseif condition. Hence both the "lock" and "ready" bit need to be tested in the SM_READY_STATUS register before considering the PLL locked and ready to go. Tested on the Sony Xperia XA2 Ultra (nile-discovery, sdm630). [1]: https://source.codeaurora.org/quic/la/kernel/msm-4.19/tree/drivers/clk/qcom/mdss/mdss-dsi-pll-14nm-util.c?h=LA.UM.9.2.1.r1-08000-sdm660.0#n302 Fixes: f079f6d999cb ("drm/msm/dsi: Add PHY/PLL for 8x96") Signed-off-by: Marijn Suijten Reviewed-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c | 30 +++--- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c index 8905f365c932..789b08c24d25 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c @@ -110,14 +110,13 @@ static struct dsi_pll_14nm *pll_14nm_list[DSI_MAX]; static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm, u32 nb_tries, u32 timeout_us) { - bool pll_locked = false; + bool pll_locked = false, pll_ready = false; void __iomem *base = pll_14nm->phy->pll_base; u32 tries, val; tries = nb_tries; while (tries--) { - val = dsi_phy_read(base + - REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); + val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); pll_locked = !!(val & BIT(5)); if (pll_locked) @@ -126,23 +125,24 @@ static bool pll_14nm_poll_for_ready(struct dsi_pll_14nm *pll_14nm, udelay(timeout_us); } - if (!pll_locked) { - tries = nb_tries; - while (tries--) { - val = dsi_phy_read(base + - REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); - pll_locked = !!(val & BIT(0)); + if (!pll_locked) + goto out; - if (pll_locked) - break; + tries = nb_tries; + while (tries--) { + val = dsi_phy_read(base + REG_DSI_14nm_PHY_PLL_RESET_SM_READY_STATUS); + pll_ready = !!(val & BIT(0)); - udelay(timeout_us); - } + if (pll_ready) + break; + + udelay(timeout_us); } - DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* "); +out: + DBG("DSI PLL is %slocked, %sready", pll_locked ? "" : "*not* ", pll_ready ? "" : "*not* "); - return pll_locked; + return pll_locked && pll_ready; } static void dsi_pll_14nm_config_init(struct dsi_pll_config *pconf) -- With best wishes Dmitry
Re: [PATCH 0/3] drm/msm: drop old eDP support
On Fri 01 Oct 09:50 PDT 2021, Dmitry Baryshkov wrote: > MSM DRM driver has support for eDP block present on MSM 8x74/8x84 SoC > families. However since addition back in 2015 this driver received only > generic fixes. No actual devices with these SoCs supported upstream (or > by the community) seem to support eDP panels. Judging from downstream > kernels the eDP was present only on MSM8974 LIQUID or on APQ8084 CDP. > Remove this driver. > Nice! Reviewed-by: Bjorn Andersson Regards, Bjorn > > Dmitry Baryshkov (3): > drm/msm/mdp5: drop eDP support > drm/msm/edp: drop old eDP support > dt-bindings: display/msm: remove edp.txt > > .../devicetree/bindings/display/msm/edp.txt| 56 - > drivers/gpu/drm/msm/Makefile |6 - > drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 17 +- > drivers/gpu/drm/msm/edp/edp.c | 198 --- > drivers/gpu/drm/msm/edp/edp.h | 77 -- > drivers/gpu/drm/msm/edp/edp.xml.h | 388 -- > drivers/gpu/drm/msm/edp/edp_aux.c | 265 > drivers/gpu/drm/msm/edp/edp_bridge.c | 111 -- > drivers/gpu/drm/msm/edp/edp_connector.c| 132 -- > drivers/gpu/drm/msm/edp/edp_ctrl.c | 1375 > > drivers/gpu/drm/msm/edp/edp_phy.c | 98 -- > drivers/gpu/drm/msm/msm_drv.c |2 - > drivers/gpu/drm/msm/msm_drv.h | 12 - > 13 files changed, 1 insertion(+), 2736 deletions(-) > delete mode 100644 Documentation/devicetree/bindings/display/msm/edp.txt > delete mode 100644 drivers/gpu/drm/msm/edp/edp.c > delete mode 100644 drivers/gpu/drm/msm/edp/edp.h > delete mode 100644 drivers/gpu/drm/msm/edp/edp.xml.h > delete mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c > delete mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c > delete mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c > delete mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c > delete mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c >
[PULL] drm-fixes
Hi Linus, Dave is out on a long w/e, should be back next week. Nothing nefarious, just a bunch of driver fixes. Cheers, Daniel drm-fixes-2021-10-01: drm fixes for -rc4: amdgpu, i915, tegra, and one exynos driver fix Cheers, Daniel The following changes since commit 5816b3e6577eaa676ceb00a848f0fd65fe2adc29: Linux 5.15-rc3 (2021-09-26 14:08:19 -0700) are available in the Git repository at: git://anongit.freedesktop.org/drm/drm tags/drm-fixes-2021-10-01 for you to fetch changes up to 78ea81417944fe03f48648eddeb8e8a8e513c4ad: Merge tag 'exynos-drm-fixes-for-v5.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-fixes (2021-10-01 18:14:39 +0200) drm fixes for -rc4: amdgpu, i915, tegra, and one exynos driver fix Akira Yokosawa (1): drm/i915/guc, docs: Fix pdfdocs build error by removing nested grid Cai Huoqing (1): drm/exynos: Make use of the helper function devm_platform_ioremap_resource() Charlene Liu (1): drm/amd/display: Pass PCI deviceid into DC Daniel Vetter (3): Merge tag 'drm-intel-fixes-2021-09-30' of git://anongit.freedesktop.org/drm/drm-intel into drm-fixes Merge tag 'amd-drm-fixes-5.15-2021-09-29' of https://gitlab.freedesktop.org/agd5f/linux into drm-fixes Merge tag 'exynos-drm-fixes-for-v5.15-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-fixes Dave Airlie (1): Merge tag 'drm/tegra/for-5.15-rc3' of ssh://git.freedesktop.org/git/tegra/linux into drm-fixes Dmitry Osipenko (3): drm/tegra: dc: Remove unused variables drm/tegra: uapi: Fix wrong mapping end address in case of disabled IOMMU gpu/host1x: fence: Make spinlock static Hawking Zhang (1): drm/amdgpu: correct initial cp_hqd_quantum for gfx9 Jani Nikula (1): Merge tag 'gvt-fixes-2021-09-18' of https://github.com/intel/gvt-linux into drm-intel-fixes Josip Pavic (1): drm/amd/display: initialize backlight_ramping_override to false Leslie Shi (1): drm/amdgpu: fix gart.bo pin_count leak Matthew Auld (1): drm/i915/request: fix early tracepoints Praful Swarnakar (1): drm/amd/display: Fix Display Flicker on embedded panels Prike Liang (1): drm/amdgpu: force exit gfxoff on sdma resume for rmb s0ix Simon Ser (1): drm/amdgpu: check tiling flags when creating FB on GFX8- Tejas Upadhyay (1): drm/i915: Remove warning from the rps worker Thierry Reding (1): gpu: host1x: Plug potential memory leak Zhi A Wang (1): drm/i915/gvt: fix the usage of ww lock in gvt scheduler. drivers/gpu/drm/amd/amdgpu/amdgpu_display.c| 31 ++ drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c | 3 ++- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 8 ++ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 2 ++ drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 15 +-- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 4 +-- drivers/gpu/drm/exynos/exynos_drm_dsi.c| 4 +-- drivers/gpu/drm/exynos/exynos_drm_fimc.c | 5 +--- drivers/gpu/drm/exynos/exynos_drm_fimd.c | 4 +-- drivers/gpu/drm/exynos/exynos_drm_g2d.c| 5 +--- drivers/gpu/drm/exynos/exynos_drm_gsc.c| 6 + drivers/gpu/drm/exynos/exynos_drm_rotator.c| 4 +-- drivers/gpu/drm/exynos/exynos_drm_scaler.c | 4 +-- drivers/gpu/drm/exynos/exynos_hdmi.c | 4 +-- drivers/gpu/drm/i915/gt/intel_rps.c| 2 -- .../drm/i915/gt/uc/abi/guc_communication_ctb_abi.h | 10 +++ .../i915/gt/uc/abi/guc_communication_mmio_abi.h| 10 +++ drivers/gpu/drm/i915/gvt/scheduler.c | 4 +-- drivers/gpu/drm/i915/i915_request.c| 11 ++-- drivers/gpu/drm/tegra/dc.c | 3 --- drivers/gpu/drm/tegra/dc.h | 6 - drivers/gpu/drm/tegra/uapi.c | 2 +- drivers/gpu/host1x/fence.c | 6 +++-- 25 files changed, 81 insertions(+), 77 deletions(-) -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
Re: [GIT PULL] exynos-drm-fixes
On Tue, Sep 28, 2021 at 04:41:58PM +0900, Inki Dae wrote: > Hi Dave, > >Just one clean up to use helper function. > > Please kindly let me know if there is any problem. > > Thanks, > Inki Dae > > The following changes since commit 6880fa6c56601bb8ed59df6c30fd390cc5f6dd8f: > > Linux 5.15-rc1 (2021-09-12 16:28:37 -0700) > > are available in the Git repository at: > > git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos > tags/exynos-drm-fixes-for-v5.15-rc4 > > for you to fetch changes up to 17ac76e050c51497e75871a43aa3328ba54cdafd: > > drm/exynos: Make use of the helper function > devm_platform_ioremap_resource() (2021-09-16 14:05:07 +0900) > > > One cleanup > - Use devm_platform_ioremap_resource() helper function instead of old > one. Pulled into drm-fixes, thanks. -Daniel > > > Cai Huoqing (1): > drm/exynos: Make use of the helper function > devm_platform_ioremap_resource() > > drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 4 +--- > drivers/gpu/drm/exynos/exynos_drm_dsi.c | 4 +--- > drivers/gpu/drm/exynos/exynos_drm_fimc.c | 5 + > drivers/gpu/drm/exynos/exynos_drm_fimd.c | 4 +--- > drivers/gpu/drm/exynos/exynos_drm_g2d.c | 5 + > drivers/gpu/drm/exynos/exynos_drm_gsc.c | 6 +- > drivers/gpu/drm/exynos/exynos_drm_rotator.c | 4 +--- > drivers/gpu/drm/exynos/exynos_drm_scaler.c| 4 +--- > drivers/gpu/drm/exynos/exynos_hdmi.c | 4 +--- > 9 files changed, 9 insertions(+), 31 deletions(-) -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
[PATCH 2/3] drm/msm/edp: drop old eDP support
MSM DRM driver has support for eDP block present on MSM 8x74/8x84 SoC families. However since addition back in 2015 this driver received only generic fixes. No actual devices with these SoCs supported upstream (or by the community) seem to support eDP panels. Judging from downstream kernels the eDP was present only on MSM8974 LIQUID or on APQ8084 CDP. Remove this driver. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile|6 - drivers/gpu/drm/msm/edp/edp.c | 198 drivers/gpu/drm/msm/edp/edp.h | 77 -- drivers/gpu/drm/msm/edp/edp.xml.h | 388 --- drivers/gpu/drm/msm/edp/edp_aux.c | 265 - drivers/gpu/drm/msm/edp/edp_bridge.c| 111 -- drivers/gpu/drm/msm/edp/edp_connector.c | 132 --- drivers/gpu/drm/msm/edp/edp_ctrl.c | 1375 --- drivers/gpu/drm/msm/edp/edp_phy.c | 98 -- drivers/gpu/drm/msm/msm_drv.c |2 - drivers/gpu/drm/msm/msm_drv.h | 12 - 11 files changed, 2664 deletions(-) delete mode 100644 drivers/gpu/drm/msm/edp/edp.c delete mode 100644 drivers/gpu/drm/msm/edp/edp.h delete mode 100644 drivers/gpu/drm/msm/edp/edp.xml.h delete mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 904535eda0c4..a6f67c8a5105 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -25,12 +25,6 @@ msm-y := \ hdmi/hdmi_phy_8960.o \ hdmi/hdmi_phy_8x60.o \ hdmi/hdmi_phy_8x74.o \ - edp/edp.o \ - edp/edp_aux.o \ - edp/edp_bridge.o \ - edp/edp_connector.o \ - edp/edp_ctrl.o \ - edp/edp_phy.o \ disp/mdp_format.o \ disp/mdp_kms.o \ disp/mdp4/mdp4_crtc.o \ diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c deleted file mode 100644 index 106a67473af5.. --- a/drivers/gpu/drm/msm/edp/edp.c +++ /dev/null @@ -1,198 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. - */ - -#include -#include "edp.h" - -static irqreturn_t edp_irq(int irq, void *dev_id) -{ - struct msm_edp *edp = dev_id; - - /* Process eDP irq */ - return msm_edp_ctrl_irq(edp->ctrl); -} - -static void edp_destroy(struct platform_device *pdev) -{ - struct msm_edp *edp = platform_get_drvdata(pdev); - - if (!edp) - return; - - if (edp->ctrl) { - msm_edp_ctrl_destroy(edp->ctrl); - edp->ctrl = NULL; - } - - platform_set_drvdata(pdev, NULL); -} - -/* construct eDP at bind/probe time, grab all the resources. */ -static struct msm_edp *edp_init(struct platform_device *pdev) -{ - struct msm_edp *edp = NULL; - int ret; - - if (!pdev) { - pr_err("no eDP device\n"); - ret = -ENXIO; - goto fail; - } - - edp = devm_kzalloc(&pdev->dev, sizeof(*edp), GFP_KERNEL); - if (!edp) { - ret = -ENOMEM; - goto fail; - } - DBG("eDP probed=%p", edp); - - edp->pdev = pdev; - platform_set_drvdata(pdev, edp); - - ret = msm_edp_ctrl_init(edp); - if (ret) - goto fail; - - return edp; - -fail: - if (edp) - edp_destroy(pdev); - - return ERR_PTR(ret); -} - -static int edp_bind(struct device *dev, struct device *master, void *data) -{ - struct drm_device *drm = dev_get_drvdata(master); - struct msm_drm_private *priv = drm->dev_private; - struct msm_edp *edp; - - DBG(""); - edp = edp_init(to_platform_device(dev)); - if (IS_ERR(edp)) - return PTR_ERR(edp); - priv->edp = edp; - - return 0; -} - -static void edp_unbind(struct device *dev, struct device *master, void *data) -{ - struct drm_device *drm = dev_get_drvdata(master); - struct msm_drm_private *priv = drm->dev_private; - - DBG(""); - if (priv->edp) { - edp_destroy(to_platform_device(dev)); - priv->edp = NULL; - } -} - -static const struct component_ops edp_ops = { - .bind = edp_bind, - .unbind = edp_unbind, -}; - -static int edp_dev_probe(struct platform_device *pdev) -{ - DBG(""); - return component_add(&pdev->dev, &edp_ops); -} - -static int edp_dev_remove(struct platform_device *pdev) -{ - DBG(""); - component_del(&pdev->dev, &edp_ops); - return 0; -} - -static const struct of_device_id dt_match[] = { - { .compatible = "qcom,mdss-edp" }, - {} -}; - -static struct platform_driver edp_driver = { - .probe = edp_dev_probe, -
[PATCH 3/3] dt-bindings: display/msm: remove edp.txt
eDP driver is being removed, so drop bindings description. Signed-off-by: Dmitry Baryshkov --- .../devicetree/bindings/display/msm/edp.txt | 56 --- 1 file changed, 56 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/msm/edp.txt diff --git a/Documentation/devicetree/bindings/display/msm/edp.txt b/Documentation/devicetree/bindings/display/msm/edp.txt deleted file mode 100644 index eff9daff418c.. --- a/Documentation/devicetree/bindings/display/msm/edp.txt +++ /dev/null @@ -1,56 +0,0 @@ -Qualcomm Technologies Inc. adreno/snapdragon eDP output - -Required properties: -- compatible: - * "qcom,mdss-edp" -- reg: Physical base address and length of the registers of controller and PLL -- reg-names: The names of register regions. The following regions are required: - * "edp" - * "pll_base" -- interrupts: The interrupt signal from the eDP block. -- power-domains: Should be <&mmcc MDSS_GDSC>. -- clocks: device clocks - See Documentation/devicetree/bindings/clock/clock-bindings.txt for details. -- clock-names: the following clocks are required: - * "core" - * "iface" - * "mdp_core" - * "pixel" - * "link" -- #clock-cells: The value should be 1. -- vdda-supply: phandle to vdda regulator device node -- lvl-vdd-supply: phandle to regulator device node which is used to supply power - to HPD receiving chip -- panel-en-gpios: GPIO pin to supply power to panel. -- panel-hpd-gpios: GPIO pin used for eDP hpd. - - -Example: - mdss_edp: qcom,mdss_edp@fd923400 { - compatible = "qcom,mdss-edp"; - reg-names = - "edp", - "pll_base"; - reg = <0xfd923400 0x700>, - <0xfd923a00 0xd4>; - interrupt-parent = <&mdss_mdp>; - interrupts = <12 0>; - power-domains = <&mmcc MDSS_GDSC>; - clock-names = - "core", - "pixel", - "iface", - "link", - "mdp_core"; - clocks = - <&mmcc MDSS_EDPAUX_CLK>, - <&mmcc MDSS_EDPPIXEL_CLK>, - <&mmcc MDSS_AHB_CLK>, - <&mmcc MDSS_EDPLINK_CLK>, - <&mmcc MDSS_MDP_CLK>; - #clock-cells = <1>; - vdda-supply = <&pma8084_l12>; - lvl-vdd-supply = <&lvl_vreg>; - panel-en-gpios = <&tlmm 137 0>; - panel-hpd-gpios = <&tlmm 103 0>; - }; -- 2.33.0
[PATCH 1/3] drm/msm/mdp5: drop eDP support
Prepare for removing old eDP support present in 8x74/8x84 SoC families. No devices present in mainline support eDP ports. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 17 + 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c index b3b42672b2d4..21707fcd883d 100644 --- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c @@ -376,22 +376,7 @@ static int modeset_init_intf(struct mdp5_kms *mdp5_kms, switch (intf->type) { case INTF_eDP: - if (!priv->edp) - break; - - ctl = mdp5_ctlm_request(ctlm, intf->num); - if (!ctl) { - ret = -EINVAL; - break; - } - - encoder = construct_encoder(mdp5_kms, intf, ctl); - if (IS_ERR(encoder)) { - ret = PTR_ERR(encoder); - break; - } - - ret = msm_edp_modeset_init(priv->edp, dev, encoder); + DRM_DEV_INFO(dev->dev, "Skipping eDP interface %d\n", intf->num); break; case INTF_HDMI: if (!priv->hdmi) -- 2.33.0
[PATCH 0/3] drm/msm: drop old eDP support
MSM DRM driver has support for eDP block present on MSM 8x74/8x84 SoC families. However since addition back in 2015 this driver received only generic fixes. No actual devices with these SoCs supported upstream (or by the community) seem to support eDP panels. Judging from downstream kernels the eDP was present only on MSM8974 LIQUID or on APQ8084 CDP. Remove this driver. Dmitry Baryshkov (3): drm/msm/mdp5: drop eDP support drm/msm/edp: drop old eDP support dt-bindings: display/msm: remove edp.txt .../devicetree/bindings/display/msm/edp.txt| 56 - drivers/gpu/drm/msm/Makefile |6 - drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 17 +- drivers/gpu/drm/msm/edp/edp.c | 198 --- drivers/gpu/drm/msm/edp/edp.h | 77 -- drivers/gpu/drm/msm/edp/edp.xml.h | 388 -- drivers/gpu/drm/msm/edp/edp_aux.c | 265 drivers/gpu/drm/msm/edp/edp_bridge.c | 111 -- drivers/gpu/drm/msm/edp/edp_connector.c| 132 -- drivers/gpu/drm/msm/edp/edp_ctrl.c | 1375 drivers/gpu/drm/msm/edp/edp_phy.c | 98 -- drivers/gpu/drm/msm/msm_drv.c |2 - drivers/gpu/drm/msm/msm_drv.h | 12 - 13 files changed, 1 insertion(+), 2736 deletions(-) delete mode 100644 Documentation/devicetree/bindings/display/msm/edp.txt delete mode 100644 drivers/gpu/drm/msm/edp/edp.c delete mode 100644 drivers/gpu/drm/msm/edp/edp.h delete mode 100644 drivers/gpu/drm/msm/edp/edp.xml.h delete mode 100644 drivers/gpu/drm/msm/edp/edp_aux.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_bridge.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_connector.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_ctrl.c delete mode 100644 drivers/gpu/drm/msm/edp/edp_phy.c
Re: Handling DRM master transitions cooperatively
On Wednesday, September 22nd, 2021 at 11:21, Hans de Goede wrote: > I would be happy to work on the plymouth side of this, so that we > have at least one consumer of such a flag lined up for merging. Do you have plans to work on the kernel side part of this? If so, feel free to CC me for a review. If not, let me know if you'd like to switch roles, I could work on a patch. Simon
Re: [Intel-gfx] [PATCH] drm/i915: remove IS_ACTIVE
On Fri, Oct 01, 2021 at 12:57:13PM +0300, Jani Nikula wrote: On Fri, 01 Oct 2021, Chris Wilson wrote: Quoting Lucas De Marchi (2021-10-01 08:40:41) When trying to bring IS_ACTIVE to linux/kconfig.h I thought it wouldn't provide much value just encapsulating it in a boolean context. So I also added the support for handling undefined macros as the IS_ENABLED() counterpart. However the feedback received from Masahiro Yamada was that it is too ugly, not providing much value. And just wrapping in a boolean context is too dumb - we could simply open code it. As detailed in commit babaab2f4738 ("drm/i915: Encapsulate kconfig constant values inside boolean predicates"), the IS_ACTIVE macro was added to workaround a compilation warning. However after checking again our current uses of IS_ACTIVE it turned out there is only 1 case in which it would potentially trigger a warning. All the others can simply use the shorter version, without wrapping it in any macro. And even that single one didn't trigger any warning in gcc 10.3. So here I'm dialing all the way back to simply removing the macro. If it triggers warnings in future we may change the few cases to check for > 0 or != 0. Another possibility would be to use the great "not not operator" for all positive checks, which would allow us to maintain consistency. However let's try first the simplest form though, hopefully we don't hit broken compilers spitting a warning: You didn't prevent the compilation warning this re-introduces. drivers/gpu/drm/i915/i915_config.c:11 i915_fence_context_timeout() warn: should this be a bitwise op? drivers/gpu/drm/i915/i915_request.c:1679 i915_request_wait() warn: should this be a bitwise op? Looks like that's a Smatch warning. The immediate fix would be to just add the != 0 in the relevant places. But this is stuff that's just going to get broken again unless we add Smatch to CI. Most people aren't running it on a regular basis. it looks like the warning is also triggered with clang an as per 0day test. What if we change all the positive caes to use !!? That would make it consistent and IMO not as ugly as the != 0. what about this? -8< diff --git a/drivers/gpu/drm/i915/i915_config.c b/drivers/gpu/drm/i915/i915_config.c index ad228dd96a0b..0df3efa2e72d 100644 --- a/drivers/gpu/drm/i915/i915_config.c +++ b/drivers/gpu/drm/i915/i915_config.c @@ -8,7 +8,7 @@ unsigned long i915_fence_context_timeout(const struct drm_i915_private *i915, u64 context) { - if (context && CONFIG_DRM_I915_FENCE_TIMEOUT) + if (context && !!CONFIG_DRM_I915_FENCE_TIMEOUT) return msecs_to_jiffies_timeout(CONFIG_DRM_I915_FENCE_TIMEOUT); return 0; -8< Lucas De Marchi
Re: [PATCH v2 4/5] drm/panfrost: Add a PANFROST_BO_GPUONLY flag
On Fri, 1 Oct 2021 16:13:42 +0100 Steven Price wrote: > On 01/10/2021 15:34, Boris Brezillon wrote: > > This lets the driver reduce shareability domain of the MMU mapping, > > which can in turn reduce access time and save power on cache-coherent > > systems. > > > > Signed-off-by: Boris Brezillon > > This seems reasonable to me - it matches the kbase > BASE_MEM_COHERENT_SYSTEM (only backwards obviously) and it worked > reasonably well for the blob. > > But I'm wondering if we need to do anything special to deal with the > fact we will now have some non-coherent mappings on an otherwise > coherent device. > > There are certainly some oddities around how these buffers will be > mapped into user space if requested, e.g. panfrost_gem_create_object() > sets 'map_wc' based on pfdev->coherent which is arguably wrong for > GPUONLY. So there are two things we could consider: > > a) Actually prevent user space mapping GPUONLY flagged buffers. Which > matches the intention of the name. I intended to do that, just forgot to add wrappers around drm_gem_shmem_{mmap,vmap}() to forbid CPU-mappings on gpuonly buffers. > > b) Attempt to provide user space with the tools to safely interact with > the buffers (this is the kbase approach). This does have the benefit of > allowing *mostly* GPU access. An example here is the tiler heap where > the CPU could zero out as necessary but mostly the GPU has ownership and > the CPU never reads the contents. GPUONLY/DEVONLY might not be the best > name in that case. Uh, right, I forgot we had to zero the tiler heap on Midgard (most of the time done with a WRITE_VALUE job, but there's an exception on some old Midgard GPUs IIRC).
Re: [PATCH v3 6/6] drm/mediatek: Add mt8195 DisplayPort driver
Hi, Markus: Markus Schneider-Pargmann 於 2021年10月1日 週五 下午5:44寫道: > > This patch adds a DisplayPort driver for the Mediatek mt8195 SoC and a > according phy driver mediatek-dp-phy. > > It supports both functional units on the mt8195, the embedded > DisplayPort as well as the external DisplayPort units. It offers > hot-plug-detection, audio up to 8 channels, and DisplayPort 1.4 with up > to 4 lanes. > > The driver creates a child device for the phy. The child device will > never exist without the parent being active. As they are sharing a > register range, the parent passes a regmap pointer to the child so that > both can work with the same register range. The phy driver sets device > data that is read by the parent to get the phy device that can be used > to control the phy properties. > > This driver is based on an initial version by > Jason-JH.Lin . > > Signed-off-by: Markus Schneider-Pargmann > --- > > Notes: > Changes v2 -> v3: > - Solve TODOs and add defines for undescribed registers > - Remove TODOs that were irrelevant > > Changes v1 -> v2: > - Fix checkpatch --strict suggestions > - General cleanups of the code. > - Remove all remaining non-atomic functions. > - Remove unused includes and sort them. > - Remove unused select GENERIC_PHY > - Rename phy registers DP_PHY -> MTK_DP_PHY > - Replace usage of delays with usleep_range. > - Split the phy register accesses into a separate phy driver. > - Use a lock to guard access to mtk_dp->edid as it can be > allocated/used/freed > in different threads > - use struct dp_sdp for sdp packets. > > Changes RFC -> v1: > - Removed unused register definitions. > - Replaced workqueue with threaded irq. > - Removed connector code. > - Move to atomic_* drm functions. > - General cleanups of the code. > - Remove unused select GENERIC_PHY. > > drivers/gpu/drm/mediatek/Kconfig |7 + > drivers/gpu/drm/mediatek/Makefile |2 + > drivers/gpu/drm/mediatek/mtk_dp.c | 2825 > drivers/gpu/drm/mediatek/mtk_dp_reg.h | 535 + > drivers/gpu/drm/mediatek/mtk_drm_drv.c |1 + > drivers/gpu/drm/mediatek/mtk_drm_drv.h |1 + > drivers/phy/mediatek/Kconfig |8 + > drivers/phy/mediatek/Makefile |1 + > drivers/phy/mediatek/phy-mtk-dp.c | 218 ++ Separate the phy driver to another patch because phy driver would go into different maintainer's tree. Regards, Chun-Kuang. > include/linux/soc/mediatek/mtk-mmsys.h |2 + > 10 files changed, 3600 insertions(+) > create mode 100644 drivers/gpu/drm/mediatek/mtk_dp.c > create mode 100644 drivers/gpu/drm/mediatek/mtk_dp_reg.h > create mode 100644 drivers/phy/mediatek/phy-mtk-dp.c >
[PATCH] drm/i915: Fix bug in user proto-context creation that leaked contexts
Set number of engines before attempting to create contexts so the function free_engines can clean up properly. Also check return of alloc_engines for NULL. v2: (Tvrtko) - Send as stand alone patch (John Harrison) - Check for alloc_engines returning NULL v3: (Checkpatch / Tvrtko) - Remove braces around single line if statement Cc: Jason Ekstrand Fixes: d4433c7600f7 ("drm/i915/gem: Use the proto-context to handle create parameters (v5)") Reviewed-by: Tvrtko Ursulin Signed-off-by: Matthew Brost Cc: --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 8208fd5b72c3..8c7ea6e56262 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -898,6 +898,10 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx, unsigned int n; e = alloc_engines(num_engines); + if (!e) + return ERR_PTR(-ENOMEM); + e->num_engines = num_engines; + for (n = 0; n < num_engines; n++) { struct intel_context *ce; int ret; @@ -931,7 +935,6 @@ static struct i915_gem_engines *user_engines(struct i915_gem_context *ctx, goto free_engines; } } - e->num_engines = num_engines; return e; -- 2.32.0
Re: [Intel-gfx] [PATCH] drm/i915: Fix bug in user proto-context creation that leaked contexts
On Fri, Oct 01, 2021 at 09:40:19AM +0100, Tvrtko Ursulin wrote: > > + Daniel as reviewer and maybe merge, avoid falling through cracks at least. > Ty, working on push rights myself. > On 22/09/2021 20:43, Matthew Brost wrote: > > Set number of engines before attempting to create contexts so the > > function free_engines can clean up properly. Also check return of > > alloc_engines for NULL. > > > > v2: > > (Tvrtko) > >- Send as stand alone patch > > (John Harrison) > >- Check for alloc_engines returning NULL > > > > Cc: Jason Ekstrand > > Fixes: d4433c7600f7 ("drm/i915/gem: Use the proto-context to handle create > > parameters (v5)") > > Signed-off-by: Matthew Brost > > Cc: > > --- > > drivers/gpu/drm/i915/gem/i915_gem_context.c | 6 +- > > 1 file changed, 5 insertions(+), 1 deletion(-) > > > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > index c2ab0e22db0a..9627c7aac6a3 100644 > > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c > > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c > > @@ -898,6 +898,11 @@ static struct i915_gem_engines *user_engines(struct > > i915_gem_context *ctx, > > unsigned int n; > > e = alloc_engines(num_engines); > > + if (!e) { > > + return ERR_PTR(-ENOMEM); > > + } > > Ideally remove the braces and respin. > Yep, checkpatch didn't like this. Will respin. > > + e->num_engines = num_engines; > > Theoretically you could have put it next to "e->engines[n] = ce" assignment > so the pattern is the same as in default_engines(). Kind of makes more sense > that the number is not set before anything is created, but as it doesn't > really matter since free_engines handles sparse arrays so there is argument > to have a simpler single assignment as well. > I like a single assignment, let's not overthink this. > > + > > for (n = 0; n < num_engines; n++) { > > struct intel_context *ce; > > int ret; > > @@ -931,7 +936,6 @@ static struct i915_gem_engines *user_engines(struct > > i915_gem_context *ctx, > > goto free_engines; > > } > > } > > - e->num_engines = num_engines; > > return e; > > > > Fix looks good to me. I did not want to butt in but since more than a week > has passed without it getting noticed: > Again, ty. Matt > Reviewed-by: Tvrtko Ursulin > > Regards, > > Tvrtko
Re: [v2 PATCH 1/3] drm/mediatek: Fix crash at using pkt->cl->chan in cmdq_pkt_finalize
Hi, Enric: Enric Balletbo Serra 於 2021年9月30日 週四 下午9:48寫道: > > Hi Chun-Kuang, > > Missatge de Chun-Kuang Hu del dia dj., 30 de > set. 2021 a les 15:11: > > > > Hi, Enric: > > > > Enric Balletbo Serra 於 2021年9月30日 週四 下午3:12寫道: > > > > > > Hi Jason, > > > > > > > > > Missatge de jason-jh.lin del dia dj., 30 > > > de set. 2021 a les 4:47: > > > > > > > > Because mtk_drm_crtc_create_pkt didn't assign pkt->cl, it will > > > > crash at using pkt->cl->chan in cmdq_pkt_finalize. > > > > > > > > So add struct cmdq_client and let mtk_drm_crtc instance define > > > > cmdq_client as: > > > > > > > > struct mtk_drm_crtc { > > > > /* client instance data */ > > > > struct cmdq_client cmdq_client; > > > > }; > > > > > > > > and in rx_callback function can use pkt->cl to get > > > > struct cmdq_client. > > > > > > > > Fixes: f4be17cd5b14 ("drm/mediatek: Remove struct cmdq_client") > > > > > > Looking at this patchset looks like you're fixing the above commit by > > > reintroducing the 'struct cmdq_client' again, which makes the above > > > commit as a non-sense commit. That's confusing and not clear. I'm > > > wondering if it wouldn't be more clear if you can just revert that > > > patch. Then if there are more changes that need to be done do it with > > > a follow up patch and really explain why these changes are needed. > > > > The patch f4be17cd5b14 ("drm/mediatek: Remove struct cmdq_client") > > does two things. One is to remove struct cmdq_client, another one is > > to embed cmdq_cl > > Then it should have been two patches, one thing for patch really > helps, specially when something breaks and you try to bisect it. > > > in mtk_drm_crtc (This means the pointer of cmdq_cl could be used to > > find the pointer of mtk_drm_crtc). The correct way to fix that patch > > is to remove the access to cmdq_client in cmdq_pkt_finalize(), but > > that would be a long term process. The simple way is to revert that > > patch, but the other patches depend on embedding cmdq_cl in > > mtk_drm_crtc. So this patch just revert the removing of struct > > cmdq_client but keep embedding cmdq_cl in mtk_drm_crtc. > > > > Yes, I know and I suffered that when bisecting and I ended to revert > the full series in my local tree, although I figured out that the > problem was this specific patch. > > The following series landed during -rc1 cycle and break the Acer Chromebook > R13 > > 9efb16c2fdd6 ("drm/mediatek: Clear pending flag when cmdq packet is done") > bc9241be73d9 ("drm/mediatek: Add cmdq_handle in mtk_crtc") > 8cdcb3653424 ("drm/mediatek: Detect CMDQ execution timeout") > f4be17cd5b14 ("drm/mediatek: Remove struct cmdq_client") > c1ec54b7b5af ("drm/mediatek: Use mailbox rx_callback instead of > cmdq_task_cb") > > Apart from that it was a pain bisecting and introduced different > behaviours between patches, all the above commits have a follow-up > patch (see [1] and [2]) as a fix for the landed series. That makes me > think that were no stable enough. As we're in the rc, and as you said > this is not the correct way to fix it, and the landed patches seems > more a cleanup that really solving a real problem I'd consider to just > revert the full series and resubmit again for next release with these > fixes squashed. IMO that will also help to no miss anything when > someone would backport all this to the stable versions and understand > better the history. > > Just my 5 cents. In any case, I can confirm that applying the full > series solves the current problems that I have with my Acer Chromebook > R13. OK, that series depend on an WARN_ON fixes in mailbox driver, and need a better solution in cmdq helper, so let's revert that series first. Would you like to send the revert patches? Or I send the revert patches and let you test? Regards, Chun-Kuang. > > Thanks, > Enric > > [1] https://patchwork.kernel.org/project/linux-mediatek/list/?series=555383 > [2] https://patchwork.kernel.org/project/linux-mediatek/list/?series=554767 > > > > > Regards, > > Chun-Kuang. > > > > > > > > Thanks, > > > Enric > > > > > > > > > > Signed-off-by: jason-jh.lin > > > > --- > > > > drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 73 + > > > > 1 file changed, 38 insertions(+), 35 deletions(-) > > > > > > > > diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > > b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > > index 5f81489fc60c..411d99fcbb8f 100644 > > > > --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > > +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c > > > > @@ -52,8 +52,7 @@ struct mtk_drm_crtc { > > > > boolpending_async_planes; > > > > > > > > #if IS_REACHABLE(CONFIG_MTK_CMDQ) > > > > - struct mbox_client cmdq_cl; > > > > - struct mbox_chan*cmdq_chan; > > > > + struct cmdq_client cmdq_client; > > > > struct cmdq_pkt cmdq_handle; > > > > u32