Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
On Wed, Oct 06, 2021 at 12:37:47PM -0700, Stephen Boyd wrote: > The component driver only provides 'bind' and 'unbind' callbacks to tell > the host driver that it is time to assemble the aggregate driver now > that all the components have probed. The component driver model doesn't > attempt to resolve runtime PM or suspend/resume ordering, and explicitly > mentions this in the code. This lack of support leads to some pretty > gnarly usages of the 'prepare' and 'complete' power management hooks in > drivers that host the aggregate device, and it fully breaks down when > faced with ordering shutdown between the various components, the > aggregate driver, and the host driver that registers the whole thing. > > In a concrete example, the MSM display driver at drivers/gpu/drm/msm is > using 'prepare' and 'complete' to call the drm helpers > drm_mode_config_helper_suspend() and drm_mode_config_helper_resume() > respectively, so that it can move the aggregate driver suspend/resume > callbacks to be before and after the components that make up the drm > device call any suspend/resume hooks they have. This only works as long > as the component devices don't do anything in their own 'prepare' and > 'complete' callbacks. If they did, then the ordering would be incorrect > and we would be doing something in the component drivers before the > aggregate driver could do anything. Yuck! > > Similarly, when trying to add shutdown support to the MSM driver we run > across a problem where we're trying to shutdown the drm device via > drm_atomic_helper_shutdown(), but some of the devices in the encoder > chain have already been shutdown. This time, the component devices > aren't the problem (although they could be if they did anything in their > shutdown callbacks), but there's a DSI to eDP bridge in the encoder > chain that has already been shutdown before the driver hosting the > aggregate device runs shutdown. The ordering of driver probe is like > this: > > 1. msm_pdev_probe() (host driver) > 2. DSI bridge > 3. aggregate bind > > When it comes to shutdown we have this order: > > 1. DSI bridge > 2. msm_pdev_shutdown() (host driver) > > and so the bridge is already off, but we want to communicate to it to > turn things off on the display during msm_pdev_shutdown(). Double yuck! > Unfortunately, this time we can't split shutdown into multiple phases > and swap msm_pdev_shutdown() with the DSI bridge. > > Let's make the component driver into an actual device driver that has > probe/remove/shutdown functions. The driver will only be bound to the > aggregate device once all component drivers have called component_add() > to indicate they're ready to assemble the aggregate driver. This allows > us to attach shutdown logic (and in the future runtime PM logic) to the > aggregate driver so that it runs the hooks in the correct order. Why are you creating a new bus type and not using the auxiliary bus instead? You have seen Documentation/driver-api/auxiliary_bus.rst, right? thanks, greg k-h
[tegra-drm:drm/tegra/for-next 5/12] drivers/gpu/host1x/job.c:141:30: warning: variable 'domain' set but not used
tree: git://anongit.freedesktop.org/tegra/linux.git drm/tegra/for-next head: 29e08b1e60b429c2bb30a1578db4a2db354d8a36 commit: df77f99c7c11f1cfc37ba071e7efa3ad0d46d986 [5/12] drm/tegra: Implement correct DMA-BUF semantics config: arm-randconfig-c002-20211004 (attached as .config) compiler: arm-linux-gnueabi-gcc (GCC) 11.2.0 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 git remote add tegra-drm git://anongit.freedesktop.org/tegra/linux.git git fetch --no-tags tegra-drm drm/tegra/for-next git checkout df77f99c7c11f1cfc37ba071e7efa3ad0d46d986 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross ARCH=arm If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): drivers/gpu/host1x/job.c: In function 'pin_job': >> drivers/gpu/host1x/job.c:141:30: warning: variable 'domain' set but not used >> [-Wunused-but-set-variable] 141 | struct iommu_domain *domain; | ^~ vim +/domain +141 drivers/gpu/host1x/job.c e902585fc8b639f1 Mikko Perttunen 2021-06-10 134 404bfb78daf3beda Mikko Perttunen 2016-12-14 135 static unsigned int pin_job(struct host1x *host, struct host1x_job *job) 6579324a41cc4140 Terje Bergstrom 2013-03-22 136 { df77f99c7c11f1cf Thierry Reding 2021-09-09 137unsigned long mask = HOST1X_RELOC_READ | HOST1X_RELOC_WRITE; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 138struct host1x_client *client = job->client; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 139struct device *dev = client->dev; fd323e9ef0a19112 Dmitry Osipenko 2020-06-29 140struct host1x_job_gather *g; 273da5a046965ccf Thierry Reding 2020-02-04 @141struct iommu_domain *domain; 6579324a41cc4140 Terje Bergstrom 2013-03-22 142unsigned int i; 404bfb78daf3beda Mikko Perttunen 2016-12-14 143int err; 6579324a41cc4140 Terje Bergstrom 2013-03-22 144 273da5a046965ccf Thierry Reding 2020-02-04 145domain = iommu_get_domain_for_dev(dev); 6579324a41cc4140 Terje Bergstrom 2013-03-22 146job->num_unpins = 0; 6579324a41cc4140 Terje Bergstrom 2013-03-22 147 6579324a41cc4140 Terje Bergstrom 2013-03-22 148for (i = 0; i < job->num_relocs; i++) { 06490bb99e1840ab Thierry Reding 2018-05-16 149struct host1x_reloc *reloc = >relocs[i]; df77f99c7c11f1cf Thierry Reding 2021-09-09 150enum dma_data_direction direction; df77f99c7c11f1cf Thierry Reding 2021-09-09 151struct host1x_bo_mapping *map; df77f99c7c11f1cf Thierry Reding 2021-09-09 152struct host1x_bo *bo; 6579324a41cc4140 Terje Bergstrom 2013-03-22 153 961e3beae3b29ae9 Thierry Reding 2014-06-10 154 reloc->target.bo = host1x_bo_get(reloc->target.bo); 404bfb78daf3beda Mikko Perttunen 2016-12-14 155if (!reloc->target.bo) { 404bfb78daf3beda Mikko Perttunen 2016-12-14 156err = -EINVAL; 6579324a41cc4140 Terje Bergstrom 2013-03-22 157goto unpin; 404bfb78daf3beda Mikko Perttunen 2016-12-14 158} 6579324a41cc4140 Terje Bergstrom 2013-03-22 159 df77f99c7c11f1cf Thierry Reding 2021-09-09 160bo = reloc->target.bo; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 161 af1cbfb9bf0fe079 Thierry Reding 2019-10-28 162switch (reloc->flags & mask) { af1cbfb9bf0fe079 Thierry Reding 2019-10-28 163case HOST1X_RELOC_READ: df77f99c7c11f1cf Thierry Reding 2021-09-09 164 direction = DMA_TO_DEVICE; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 165break; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 166 af1cbfb9bf0fe079 Thierry Reding 2019-10-28 167case HOST1X_RELOC_WRITE: df77f99c7c11f1cf Thierry Reding 2021-09-09 168 direction = DMA_FROM_DEVICE; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 169break; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 170 af1cbfb9bf0fe079 Thierry Reding 2019-10-28 171case HOST1X_RELOC_READ | HOST1X_RELOC_WRITE: df77f99c7c11f1cf Thierry Reding 2021-09-09 172 direction = DMA_BIDIRECTIONAL; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 173break; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 174 af1cbfb9bf0fe079 Thierry Reding 2019-10-28 175default: af1cbfb9bf0fe079 Thierry Reding 2019-10-28 176err = -EINVAL; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 177goto unpin; af1cbfb9bf0fe079 Thierry Reding 2019-10-28 178} af1cbfb9bf0fe079 Thierry
Re: [PATCH v6 3/3] drm/bridge: ti-sn65dsi86: Implement the pwm_chip
On Wed 29 Sep 20:05 PDT 2021, Bjorn Andersson wrote: > The SN65DSI86 provides the ability to supply a PWM signal on GPIO 4, > with the primary purpose of controlling the backlight of the attached > panel. Add an implementation that exposes this using the standard PWM > framework, to allow e.g. pwm-backlight to expose this to the user. > > Signed-off-by: Bjorn Andersson Any feedback on this? Thanks, Bjorn > --- > > Changes since v5: > - Make ti_sn65dsi86_read_u16() use regmap_bulk_read() > - Update the wording related to the formula for the period being wrong to not > just say I'm "assuming because it's easier". > - Updated comment related to minimum period > - Clamp duty <= period in get_state() > > drivers/gpu/drm/bridge/ti-sn65dsi86.c | 366 +- > 1 file changed, 360 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > index 412fb6f564ea..ccf6496cc9ff 100644 > --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c > +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c > @@ -4,7 +4,9 @@ > * datasheet: https://www.ti.com/lit/ds/symlink/sn65dsi86.pdf > */ > > +#include > #include > +#include > #include > #include > #include > @@ -15,6 +17,7 @@ > #include > #include > #include > +#include > #include > #include > > @@ -91,6 +94,13 @@ > #define SN_ML_TX_MODE_REG0x96 > #define ML_TX_MAIN_LINK_OFF 0 > #define ML_TX_NORMAL_MODE BIT(0) > +#define SN_PWM_PRE_DIV_REG 0xA0 > +#define SN_BACKLIGHT_SCALE_REG 0xA1 > +#define BACKLIGHT_SCALE_MAX 0x > +#define SN_BACKLIGHT_REG 0xA3 > +#define SN_PWM_EN_INV_REG0xA5 > +#define SN_PWM_INV_MASK BIT(0) > +#define SN_PWM_EN_MASK BIT(1) > #define SN_AUX_CMD_STATUS_REG0xF4 > #define AUX_IRQ_STATUS_AUX_RPLY_TOUTBIT(3) > #define AUX_IRQ_STATUS_AUX_SHORTBIT(5) > @@ -113,11 +123,14 @@ > > #define SN_LINK_TRAINING_TRIES 10 > > +#define SN_PWM_GPIO_IDX 3 /* 4th GPIO */ > + > /** > * struct ti_sn65dsi86 - Platform data for ti-sn65dsi86 driver. > * @bridge_aux: AUX-bus sub device for MIPI-to-eDP bridge functionality. > * @gpio_aux: AUX-bus sub device for GPIO controller functionality. > * @aux_aux: AUX-bus sub device for eDP AUX channel functionality. > + * @pwm_aux: AUX-bus sub device for PWM controller functionality. > * > * @dev: Pointer to the top level (i2c) device. > * @regmap: Regmap for accessing i2c. > @@ -145,11 +158,17 @@ > *bitmap so we can do atomic ops on it without an extra > *lock so concurrent users of our 4 GPIOs don't stomp on > *each other's read-modify-write. > + * > + * @pchip:pwm_chip if the PWM is exposed. > + * @pwm_enabled: Used to track if the PWM signal is currently enabled. > + * @pwm_pin_busy: Track if GPIO4 is currently requested for GPIO or PWM. > + * @pwm_refclk_freq: Cache for the reference clock input to the PWM. > */ > struct ti_sn65dsi86 { > struct auxiliary_device bridge_aux; > struct auxiliary_device gpio_aux; > struct auxiliary_device aux_aux; > + struct auxiliary_device pwm_aux; > > struct device *dev; > struct regmap *regmap; > @@ -172,6 +191,12 @@ struct ti_sn65dsi86 { > struct gpio_chipgchip; > DECLARE_BITMAP(gchip_output, SN_NUM_GPIOS); > #endif > +#if defined(CONFIG_PWM) > + struct pwm_chip pchip; > + boolpwm_enabled; > + atomic_tpwm_pin_busy; > +#endif > + unsigned intpwm_refclk_freq; > }; > > static const struct regmap_range ti_sn65dsi86_volatile_ranges[] = { > @@ -190,6 +215,21 @@ static const struct regmap_config > ti_sn65dsi86_regmap_config = { > .cache_type = REGCACHE_NONE, > }; > > +static int ti_sn65dsi86_read_u16(struct ti_sn65dsi86 *pdata, > + unsigned int reg, u16 *val) > +{ > + u8 buf[2]; > + int ret; > + > + ret = regmap_bulk_read(pdata->regmap, reg, buf, ARRAY_SIZE(buf)); > + if (ret) > + return ret; > + > + *val = buf[0] | (buf[1] << 8); > + > + return 0; > +} > + > static void ti_sn65dsi86_write_u16(struct ti_sn65dsi86 *pdata, > unsigned int reg, u16 val) > { > @@ -254,6 +294,12 @@ static void ti_sn_bridge_set_refclk_freq(struct > ti_sn65dsi86 *pdata) > > regmap_update_bits(pdata->regmap, SN_DPPLL_SRC_REG, REFCLK_FREQ_MASK, > REFCLK_FREQ(i)); > + > + /* > + * The PWM refclk is based on the value written to
Re: [PATCH 04/26] drm/i915/guc: Don't call switch_to_kernel_context with GuC submission
On 10/4/2021 15:06, Matthew Brost wrote: Calling switch_to_kernel_context isn't needed if the engine PM reference is taken while all user contexts are pinned as if don't have PM ref that guarantees that all user contexts scheduling is disabled. By not calling switch_to_kernel_context we save on issuing a request to the engine. v2: (Daniel Vetter) - Add FIXME comment about pushing switch_to_kernel_context to backend v3: (John Harrison) - Update commit message - Fix workding comment Signed-off-by: Matthew Brost Reviewed-by: Daniel Vetter Reviewed-by: John Harrison --- drivers/gpu/drm/i915/gt/intel_engine_pm.c | 13 + 1 file changed, 13 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.c b/drivers/gpu/drm/i915/gt/intel_engine_pm.c index dacd62773735..a1334b48dde7 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.c @@ -162,6 +162,19 @@ static bool switch_to_kernel_context(struct intel_engine_cs *engine) unsigned long flags; bool result = true; + /* +* This is execlist specific behaviour intended to ensure the GPU is +* idle by switching to a known 'safe' context. With GuC submission, the +* same idle guarantee is achieved by other means (disabling +* scheduling). Further, switching to a 'safe' context has no effect +* with GuC submission as the scheduler can just switch back again. +* +* FIXME: Move this backend scheduler specific behaviour into the +* scheduler backend. +*/ + if (intel_engine_uses_guc(engine)) + return true; + /* GPU is pointing to the void, as good as in the kernel context. */ if (intel_gt_is_wedged(engine->gt)) return true;
Re: [PATCH 03/26] drm/i915/guc: Take engine PM when a context is pinned with GuC submission
On 10/4/2021 15:06, Matthew Brost wrote: Taking a PM reference to prevent intel_gt_wait_for_idle from short circuiting while a scheduling of user context could be enabled. I'm not sure what 'while a scheduling of user context could be enabled' means. John. Returning GT idle when it is not can cause all sorts of issues throughout the stack. v2: (Daniel Vetter) - Add might_lock annotations to pin / unpin function v3: (CI) - Drop intel_engine_pm_might_put from unpin path as an async put is used v4: (John Harrison) - Make intel_engine_pm_might_get/put work with GuC virtual engines - Update commit message Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context.c | 2 ++ drivers/gpu/drm/i915/gt/intel_engine_pm.h | 32 + drivers/gpu/drm/i915/gt/intel_gt_pm.h | 10 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 36 +-- drivers/gpu/drm/i915/intel_wakeref.h | 12 +++ 5 files changed, 89 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 1076066f41e0..f601323b939f 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -240,6 +240,8 @@ int __intel_context_do_pin_ww(struct intel_context *ce, if (err) goto err_post_unpin; + intel_engine_pm_might_get(ce->engine); + if (unlikely(intel_context_is_closed(ce))) { err = -ENOENT; goto err_unlock; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h b/drivers/gpu/drm/i915/gt/intel_engine_pm.h index 6fdeae668e6e..d68675925b79 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h @@ -6,9 +6,11 @@ #ifndef INTEL_ENGINE_PM_H #define INTEL_ENGINE_PM_H +#include "i915_drv.h" #include "i915_request.h" #include "intel_engine_types.h" #include "intel_wakeref.h" +#include "intel_gt_pm.h" static inline bool intel_engine_pm_is_awake(const struct intel_engine_cs *engine) @@ -31,6 +33,21 @@ static inline bool intel_engine_pm_get_if_awake(struct intel_engine_cs *engine) return intel_wakeref_get_if_active(>wakeref); } +static inline void intel_engine_pm_might_get(struct intel_engine_cs *engine) +{ + if (!intel_engine_is_virtual(engine)) { + intel_wakeref_might_get(>wakeref); + } else { + struct intel_gt *gt = engine->gt; + struct intel_engine_cs *tengine; + intel_engine_mask_t tmp, mask = engine->mask; + + for_each_engine_masked(tengine, gt, mask, tmp) + intel_wakeref_might_get(>wakeref); + } + intel_gt_pm_might_get(engine->gt); +} + static inline void intel_engine_pm_put(struct intel_engine_cs *engine) { intel_wakeref_put(>wakeref); @@ -52,6 +69,21 @@ static inline void intel_engine_pm_flush(struct intel_engine_cs *engine) intel_wakeref_unlock_wait(>wakeref); } +static inline void intel_engine_pm_might_put(struct intel_engine_cs *engine) +{ + if (!intel_engine_is_virtual(engine)) { + intel_wakeref_might_put(>wakeref); + } else { + struct intel_gt *gt = engine->gt; + struct intel_engine_cs *tengine; + intel_engine_mask_t tmp, mask = engine->mask; + + for_each_engine_masked(tengine, gt, mask, tmp) + intel_wakeref_might_put(>wakeref); + } + intel_gt_pm_might_put(engine->gt); +} + static inline struct i915_request * intel_engine_create_kernel_request(struct intel_engine_cs *engine) { diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index 05de6c1af25b..bc898df7a48c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -31,6 +31,11 @@ static inline bool intel_gt_pm_get_if_awake(struct intel_gt *gt) return intel_wakeref_get_if_active(>wakeref); } +static inline void intel_gt_pm_might_get(struct intel_gt *gt) +{ + intel_wakeref_might_get(>wakeref); +} + static inline void intel_gt_pm_put(struct intel_gt *gt) { intel_wakeref_put(>wakeref); @@ -41,6 +46,11 @@ static inline void intel_gt_pm_put_async(struct intel_gt *gt) intel_wakeref_put_async(>wakeref); } +static inline void intel_gt_pm_might_put(struct intel_gt *gt) +{ + intel_wakeref_might_put(>wakeref); +} + #define with_intel_gt_pm(gt, tmp) \ for (tmp = 1, intel_gt_pm_get(gt); tmp; \ intel_gt_pm_put(gt), tmp = 0) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 17da2fea1bff..8b82da50c2bc 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -1571,7 +1571,12 @@ static int
Re: [PATCH 02/26] drm/i915/guc: Take GT PM ref when deregistering context
On 10/4/2021 15:06, Matthew Brost wrote: Taking a PM reference to prevent intel_gt_wait_for_idle from short circuiting while a deregister context H2G is in flight. To do this must issue the deregister H2G from a worker as context can be destroyed from an atomic context and taking GT PM ref blows up. Previously we took a runtime PM from this atomic context which worked but will stop working once runtime pm autosuspend in enabled. So this patch is two fold, stop intel_gt_wait_for_idle from short circuting and fix runtime pm autosuspend. v2: (John Harrison) - Split structure changes out in different patch (Tvrtko) - Don't drop lock in deregister_destroyed_contexts Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context.c | 2 + drivers/gpu/drm/i915/gt/intel_context_types.h | 7 + drivers/gpu/drm/i915/gt/intel_engine_pm.h | 5 + drivers/gpu/drm/i915/gt/intel_gt_pm.h | 4 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 11 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 146 +++--- 6 files changed, 121 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index e9a0cad5c34d..1076066f41e0 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -399,6 +399,8 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) ce->guc_id.id = GUC_INVALID_LRC_ID; INIT_LIST_HEAD(>guc_id.link); + INIT_LIST_HEAD(>destroyed_link); + /* * Initialize fence to be complete as this is expected to be complete * unless there is a pending schedule disable outstanding. diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index e7e3984aab78..4613d027cbc3 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -213,6 +213,13 @@ struct intel_context { struct list_head link; } guc_id; + /** +* @destroyed_link: link in guc->submission_state.destroyed_contexts, in +* list when context is pending to be destroyed (deregistered with the +* GuC), protected by guc->submission_state.lock +*/ + struct list_head destroyed_link; + #ifdef CONFIG_DRM_I915_SELFTEST /** * @drop_schedule_enable: Force drop of schedule enable G2H for selftest diff --git a/drivers/gpu/drm/i915/gt/intel_engine_pm.h b/drivers/gpu/drm/i915/gt/intel_engine_pm.h index 8520c595f5e1..6fdeae668e6e 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_pm.h @@ -16,6 +16,11 @@ intel_engine_pm_is_awake(const struct intel_engine_cs *engine) return intel_wakeref_is_active(>wakeref); } +static inline void __intel_engine_pm_get(struct intel_engine_cs *engine) +{ + __intel_wakeref_get(>wakeref); +} + static inline void intel_engine_pm_get(struct intel_engine_cs *engine) { intel_wakeref_get(>wakeref); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_pm.h index d0588d8aaa44..05de6c1af25b 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.h @@ -41,6 +41,10 @@ static inline void intel_gt_pm_put_async(struct intel_gt *gt) intel_wakeref_put_async(>wakeref); } +#define with_intel_gt_pm(gt, tmp) \ + for (tmp = 1, intel_gt_pm_get(gt); tmp; \ +intel_gt_pm_put(gt), tmp = 0) + static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt) { return intel_wakeref_wait_for_idle(>wakeref); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 65b5e8eeef96..25a598e2b6e8 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -84,6 +84,17 @@ struct intel_guc { * refs */ struct list_head guc_id_list; + /** +* @destroyed_contexts: list of contexts waiting to be destroyed +* (deregistered with the GuC) +*/ + struct list_head destroyed_contexts; + /** +* @destroyed_worker: worker to deregister contexts, need as we +* need to take a GT PM reference and can't from destroy +* function as it might be in an atomic context (no sleeping) +*/ + struct work_struct destroyed_worker; } submission_state; /** diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ad5c18119d92..17da2fea1bff 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -90,8 +90,8 @@ * used for all of GuC submission but that could change in
Re: [PATCH 01/26] drm/i915/guc: Move GuC guc_id allocation under submission state sub-struct
On 10/4/2021 15:06, Matthew Brost wrote: Move guc_id allocation under submission state sub-struct as a future patch will reuse the spin lock as a global submission state lock. Moving this into sub-struct makes ownership of fields / lock clear. Signed-off-by: Matthew Brost --- drivers/gpu/drm/i915/gt/intel_context_types.h | 6 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h| 26 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 56 ++- 3 files changed, 47 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index 12252c411159..e7e3984aab78 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -197,18 +197,18 @@ struct intel_context { struct { /** * @id: handle which is used to uniquely identify this context -* with the GuC, protected by guc->contexts_lock +* with the GuC, protected by guc->submission_state.lock */ u16 id; /** * @ref: the number of references to the guc_id, when * transitioning in and out of zero protected by -* guc->contexts_lock +* guc->submission_state.lock */ atomic_t ref; /** * @link: in guc->guc_id_list when the guc_id has no refs but is -* still valid, protected by guc->contexts_lock +* still valid, protected by guc->submission_state.lock */ struct list_head link; } guc_id; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index 5dd174babf7a..65b5e8eeef96 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -70,17 +70,21 @@ struct intel_guc { void (*disable)(struct intel_guc *guc); } interrupts; - /** -* @contexts_lock: protects guc_ids, guc_id_list, ce->guc_id.id, and -* ce->guc_id.ref when transitioning in and out of zero -*/ - spinlock_t contexts_lock; - /** @guc_ids: used to allocate unique ce->guc_id.id values */ - struct ida guc_ids; - /** -* @guc_id_list: list of intel_context with valid guc_ids but no refs -*/ - struct list_head guc_id_list; + struct { + /** +* @lock: protects everything in submission_state +*/ + spinlock_t lock; The old version also mentioned 'ce->guc_id.ref'. Should this not also mention that transition? Or was the old comment inaccurate. I'm not seeing any actual behaviour changes in the patch. + /** +* @guc_ids: used to allocate new guc_ids +*/ + struct ida guc_ids; + /** +* @guc_id_list: list of intel_context with valid guc_ids but no +* refs +*/ + struct list_head guc_id_list; + } submission_state; /** * @submission_supported: tracks whether we support GuC submission on diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ba0de35f6323..ad5c18119d92 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -68,16 +68,16 @@ * fence is used to stall all requests associated with this guc_id until the * corresponding G2H returns indicating the guc_id has been deregistered. * - * guc_ids: + * submission_state.guc_ids: * Unique number associated with private GuC context data passed in during * context registration / submission / deregistration. 64k available. Simple ida * is used for allocation. * - * Stealing guc_ids: - * If no guc_ids are available they can be stolen from another context at - * request creation time if that context is unpinned. If a guc_id can't be found - * we punt this problem to the user as we believe this is near impossible to hit - * during normal use cases. + * Stealing submission_state.guc_ids: + * If no submission_state.guc_ids are available they can be stolen from another I would abbreviate this instance as well, submission_state.guc_id is quite the mouthful. Unless this somehow magically links back to the structure entry in the kerneldoc output? John. + * context at request creation time if that context is unpinned. If a guc_id + * can't be found we punt this problem to the user as we believe this is near + * impossible to hit during normal use cases. * * Locking: * In the GuC submission code we have 3 basic spin locks which protect @@ -89,7 +89,7 @@ * sched_engine can be submitting at a time. Currently only one sched_engine is * used for all of
[GIT PULL FOR v5.16] R-Car DU & other misc enhancements
Hi Dave and Daniel, The following changes since commit 1e3944578b749449bd7fa6bf0bae4c3d3f5f1733: Merge tag 'amd-drm-next-5.16-2021-09-27' of https://gitlab.freedesktop.org/agd5f/linux into drm-next (2021-09-28 17:08:26 +1000) are available in the Git repository at: git://linuxtv.org/pinchartl/media.git tags/du-next-20211007 for you to fetch changes up to b291fdcf51140fef69a9734caaca704d010dd02f: drm: rcar-du: Add r8a779a0 device support (2021-10-07 05:59:54 +0300) R-Car DU improvements & enhancements to misc drivers Most notably, - Non-contiguous buffer import support for rcar-du - r8a779a0 support preparation for rcar-du - COMPILE_TEST fixes for omapdrm and sti Cai Huoqing (2): drm/shmobile: Make use of the helper function devm_platform_ioremap_resource() drm: rcar-du: Make use of the helper function devm_platform_ioremap_resource() Kieran Bingham (6): dt-bindings: display: renesas,du: Provide bindings for r8a779a0 drm: rcar-du: Sort the DU outputs drm: rcar-du: Only initialise TVM_TVSYNC mode when supported drm: rcar-du: Fix DIDSR field name drm: rcar-du: Split CRTC IRQ and Clock features drm: rcar-du: Add r8a779a0 device support Laurent Pinchart (9): drm: rcar-du: Don't create encoder for unconnected LVDS outputs drm: rcar-du: Improve kernel log messages when initializing encoders drm: rcar-du: Set the DMA coherent mask for the DU device drm: rcar-du: Allow importing non-contiguous dma-buf with VSP drm: property: Replace strncpy() with strscpy_pad() drm/omap: Use correct printk format specifiers for size_t drm/omap: Cast pointer to integer without generating warning drm/omap: Depend on CONFIG_OF drm/sti: Use correct printk format specifiers for size_t .../devicetree/bindings/display/renesas,du.yaml| 51 ++ drivers/gpu/drm/drm_property.c | 9 +- drivers/gpu/drm/omapdrm/Kconfig| 2 +- drivers/gpu/drm/omapdrm/dss/dsi.c | 4 +- drivers/gpu/drm/omapdrm/omap_drv.c | 2 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 9 +- drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 11 --- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 108 + drivers/gpu/drm/rcar-du/rcar_du_drv.h | 26 - drivers/gpu/drm/rcar-du/rcar_du_encoder.c | 28 -- drivers/gpu/drm/rcar-du/rcar_du_group.c| 6 +- drivers/gpu/drm/rcar-du/rcar_du_kms.c | 50 +- drivers/gpu/drm/rcar-du/rcar_du_kms.h | 7 ++ drivers/gpu/drm/rcar-du/rcar_du_regs.h | 9 +- drivers/gpu/drm/rcar-du/rcar_du_vsp.c | 36 ++- drivers/gpu/drm/rcar-du/rcar_lvds.c| 15 ++- drivers/gpu/drm/rcar-du/rcar_lvds.h| 5 + drivers/gpu/drm/shmobile/shmob_drm_drv.c | 4 +- drivers/gpu/drm/sti/sti_hqvdp.c| 4 +- 19 files changed, 308 insertions(+), 78 deletions(-) -- Regards, Laurent Pinchart
Re: [PATCH v8 09/12] media: mtk-vcodec: Get rid of mtk_smi_larb_get/put
On Thu, 2021-09-30 at 12:57 +0200, Dafna Hirschfeld wrote: > > On 30.09.21 05:28, Yong Wu wrote: > > Hi Dafna, > > > > Thanks very much for the review. > > > > On Wed, 2021-09-29 at 14:13 +0200, Dafna Hirschfeld wrote: > > > > > > On 29.09.21 03:37, Yong Wu wrote: > > > > MediaTek IOMMU has already added the device_link between the > > > > consumer > > > > and smi-larb device. If the vcodec device call the > > > > pm_runtime_get_sync, > > > > the smi-larb's pm_runtime_get_sync also be called > > > > automatically. > > > > > > > > CC: Tiffany Lin > > > > CC: Irui Wang > > > > Signed-off-by: Yong Wu > > > > Reviewed-by: Evan Green > > > > Acked-by: Tiffany Lin > > > > Reviewed-by: Dafna Hirschfeld > > > > --- > > > >.../platform/mtk-vcodec/mtk_vcodec_dec_pm.c | 37 +++ > > > > --- > > > > -- > > > >.../platform/mtk-vcodec/mtk_vcodec_drv.h | 3 -- > > > >.../platform/mtk-vcodec/mtk_vcodec_enc.c | 1 - > > > >.../platform/mtk-vcodec/mtk_vcodec_enc_pm.c | 44 +++ > > > > --- [snip] > > > >void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev) > > > >{ > > > > pm_runtime_disable(dev->pm.dev); > > > > - put_device(dev->pm.larbvdec); > > > >} > > > > > > Now that functions only do 'pm_runtime_disable(dev->pm.dev);' so > > > it > > > will be more > > > readable to remove the function mtk_vcodec_release_dec_pm > > > and replace with pm_runtime_disable(dev->pm.dev); > > > Same for the 'enc' equivalent. > > > > Make sense. But It may be not proper if using pm_runtime_disable > > as the symmetry with mtk_vcodec_init_dec_pm in the > > mtk_vcodec_probe. > > > > Maybe we should move pm_runtime_enable out from > > mtk_vcodec_init_dec_pm > > into mtk_vcodec_probe. I could do a new patch for this. Is this ok > > for > > you? > > yes, there is also asymettry when calling pm_runtime* in general, > I see in the decoder it is called from mtk_vcodec_dec_pm.c > but in the encoder it is called from mtk_vcodec_enc.c, > > I think all calls to pm_runtime* should be out of the *_pm.c files OK. I will try this. > since for example 'mtk_vcodec_dec_pw_on' also do just one call to > pm_runtime_resume_and_get so this function can also be removed. I guess this one should be reserved to vcodec guys. I see this function is changed at [1]. Let's keep this patchset clean. [1] https://patchwork.kernel.org/project/linux-mediatek/patch/20210901083215.25984-10-yunfei.d...@mediatek.com/ > > thanks, > Dafna > > > > > > > > > Thanks, > > > Dafna > > > > [snip] > > ___ > > Linux-mediatek mailing list > > linux-media...@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/linux-mediatek > >
Re: [PATCH v2 01/34] component: Introduce struct aggregate_device
Hi Stephen, Thank you for the patch. On Wed, Oct 06, 2021 at 12:37:46PM -0700, Stephen Boyd wrote: > Replace 'struct master' with 'struct aggregate_device' and then rename > 'master' to 'adev' everywhere in the code. While we're here, put a > struct device inside the aggregate device so that we can register it > with a bus_type in the next patch. Not "while at it" please. The signal to noise ratio is very high here. Adding the struct device in the structure is the important change that needs to be properly reviewed and discussed, the rename is noise. You're even adding an IDA and an id without mentioning it at all in the commit message. This should be split in two patches, you can decide whether to perform the rename at the bottom or top of the series (it would be more logical to group all renames together though, there's currently one in 01/34 and one in 34/34, so please group them both at the top or bottom). > The diff is large but that's because this is mostly a rename, where > sometimes 'master' is replaced with 'adev' and other times it is > replaced with 'parent' to indicate that the struct device that was being > used is actually the parent of the aggregate device and driver. > > Cc: Daniel Vetter > Cc: "Rafael J. Wysocki" > Cc: Rob Clark > Cc: Russell King > Cc: Saravana Kannan > Signed-off-by: Stephen Boyd > --- > drivers/base/component.c | 250 -- > include/linux/component.h | 2 +- > 2 files changed, 134 insertions(+), 118 deletions(-) > > diff --git a/drivers/base/component.c b/drivers/base/component.c > index 5e79299f6c3f..0a41bbe14981 100644 > --- a/drivers/base/component.c > +++ b/drivers/base/component.c > @@ -9,6 +9,7 @@ > */ > #include > #include > +#include > #include > #include > #include > @@ -58,18 +59,21 @@ struct component_match { > struct component_match_array *compare; > }; > > -struct master { > +struct aggregate_device { > struct list_head node; > bool bound; > > const struct component_master_ops *ops; > struct device *parent; > + struct device dev; > struct component_match *match; > + > + int id; > }; > > struct component { > struct list_head node; > - struct master *master; > + struct aggregate_device *adev; > bool bound; > > const struct component_ops *ops; > @@ -79,7 +83,9 @@ struct component { > > static DEFINE_MUTEX(component_mutex); > static LIST_HEAD(component_list); > -static LIST_HEAD(masters); > +static LIST_HEAD(aggregate_devices); > + > +static DEFINE_IDA(aggregate_ida); > > #ifdef CONFIG_DEBUG_FS > > @@ -87,12 +93,12 @@ static struct dentry *component_debugfs_dir; > > static int component_devices_show(struct seq_file *s, void *data) > { > - struct master *m = s->private; > + struct aggregate_device *m = s->private; > struct component_match *match = m->match; > size_t i; > > mutex_lock(_mutex); > - seq_printf(s, "%-40s %20s\n", "master name", "status"); > + seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status"); > seq_puts(s, > "-\n"); > seq_printf(s, "%-40s %20s\n\n", > dev_name(m->parent), m->bound ? "bound" : "not bound"); > @@ -122,46 +128,46 @@ static int __init component_debug_init(void) > > core_initcall(component_debug_init); > > -static void component_master_debugfs_add(struct master *m) > +static void component_master_debugfs_add(struct aggregate_device *m) > { > debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m, > _devices_fops); > } > > -static void component_master_debugfs_del(struct master *m) > +static void component_master_debugfs_del(struct aggregate_device *m) > { > debugfs_remove(debugfs_lookup(dev_name(m->parent), > component_debugfs_dir)); > } > > #else > > -static void component_master_debugfs_add(struct master *m) > +static void component_master_debugfs_add(struct aggregate_device *m) > { } > > -static void component_master_debugfs_del(struct master *m) > +static void component_master_debugfs_del(struct aggregate_device *m) > { } > > #endif > > -static struct master *__master_find(struct device *parent, > +static struct aggregate_device *__aggregate_find(struct device *parent, > const struct component_master_ops *ops) > { > - struct master *m; > + struct aggregate_device *m; > > - list_for_each_entry(m, , node) > + list_for_each_entry(m, _devices, node) > if (m->parent == parent && (!ops || m->ops == ops)) > return m; > > return NULL; > } > > -static struct component *find_component(struct master *master, > +static struct component *find_component(struct aggregate_device *adev, > struct component_match_array *mc) > { > struct component *c; > > list_for_each_entry(c, _list,
[PATCH -next] drm/connector: fix all kernel-doc warnings
Clean up all of the kernel-doc issues in drm_connector.c: drivers/gpu/drm/drm_connector.c:2611: warning: Excess function parameter 'connector' description in 'drm_connector_oob_hotplug_event' drivers/gpu/drm/drm_connector.c:2611: warning: Function parameter or member 'connector_fwnode' not described in 'drm_connector_oob_hotplug_event' drm_connector.c:630: warning: No description found for return value of 'drm_get_connector_status_name' drm_connector.c:715: warning: No description found for return value of 'drm_connector_list_iter_next' drm_connector.c:785: warning: No description found for return value of 'drm_get_subpixel_order_name' drm_connector.c:816: warning: No description found for return value of 'drm_display_info_set_bus_formats' drm_connector.c:1331: warning: No description found for return value of 'drm_mode_create_dvi_i_properties' drm_connector.c:1412: warning: No description found for return value of 'drm_connector_attach_content_type_property' drm_connector.c:1492: warning: No description found for return value of 'drm_mode_create_tv_margin_properties' drm_connector.c:1534: warning: No description found for return value of 'drm_mode_create_tv_properties' drm_connector.c:1627: warning: No description found for return value of 'drm_mode_create_scaling_mode_property' drm_connector.c:1944: warning: No description found for return value of 'drm_mode_create_suggested_offset_properties' drm_connector.c:2315: warning: missing initial short description on line: * drm_connector_set_panel_orientation_with_quirk - [The last warning listed is probably a quirk/bug in scripts/kernel-doc.] Fixes: 613051dac40d ("drm: locking iterators for connector_list") Fixes: 522171951761 ("drm: Extract drm_connector.[hc]") Fixes: b3c6c8bfe378 ("drm: document drm_display_info") Fixes: 50525c332b55 ("drm: content-type property for HDMI connector") Fixes: 6c4f52dca36f ("drm/connector: Allow creation of margin props alone") Fixes: 69654c632d80 ("drm/connector: Split out orientation quirk detection (v2)") Fixes: 72ad49682dde ("drm/connector: Add support for out-of-band hotplug notification (v3)") Signed-off-by: Randy Dunlap Cc: David Airlie Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: Stanislav Lisovskiy Cc: Ville Syrjälä Cc: Boris Brezillon Cc: Derek Basehore Cc: Hans de Goede Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann --- 72ad49682dde ("drm/connector: Add support for out-of-band hotplug notification (v3)") is only in linux-next. The others are in mainline. drivers/gpu/drm/drm_connector.c | 30 ++ 1 file changed, 26 insertions(+), 4 deletions(-) --- linux-next-20211006.orig/drivers/gpu/drm/drm_connector.c +++ linux-next-20211006/drivers/gpu/drm/drm_connector.c @@ -625,6 +625,8 @@ int drm_connector_register_all(struct dr * * In contrast to the other drm_get_*_name functions this one here returns a * const pointer and hence is threadsafe. + * + * Returns: connector status string */ const char *drm_get_connector_status_name(enum drm_connector_status status) { @@ -707,7 +709,7 @@ __drm_connector_put_safe(struct drm_conn * drm_connector_list_iter_next - return next connector * @iter: connector_list iterator * - * Returns the next connector for @iter, or NULL when the list walk has + * Returns: the next connector for @iter, or NULL when the list walk has * completed. */ struct drm_connector * @@ -780,6 +782,8 @@ static const struct drm_prop_enum_list d * * Note you could abuse this and return something out of bounds, but that * would be a caller error. No unscrubbed user data should make it here. + * + * Returns: string describing an enumerated subpixel property */ const char *drm_get_subpixel_order_name(enum subpixel_order order) { @@ -809,6 +813,9 @@ static const struct drm_prop_enum_list d * Store the supported bus formats in display info structure. * See MEDIA_BUS_FMT_* definitions in include/uapi/linux/media-bus-format.h for * a full list of available formats. + * + * Returns: + * Zero on success, negative errno on failure. */ int drm_display_info_set_bus_formats(struct drm_display_info *info, const u32 *formats, @@ -1326,6 +1333,8 @@ int drm_connector_create_standard_proper * @dev: DRM device * * Called by a driver the first time a DVI-I connector is made. + * + * Returns: %0 */ int drm_mode_create_dvi_i_properties(struct drm_device *dev) { @@ -1407,6 +1416,8 @@ EXPORT_SYMBOL(drm_connector_attach_dp_su * @connector: connector to attach content type property on. * * Called by a driver the first time a HDMI connector is made. + * + * Returns: %0 */ int drm_connector_attach_content_type_property(struct drm_connector *connector) { @@ -1487,6 +1498,9 @@ EXPORT_SYMBOL(drm_connector_attach_tv_ma * creates the TV margin properties for a given device. N
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
07.10.2021 01:01, Dmitry Osipenko пишет: > 07.10.2021 00:14, Dmitry Osipenko пишет: >> 06.10.2021 15:43, Ulf Hansson пишет: >>> On Wed, 6 Oct 2021 at 00:43, Dmitry Osipenko wrote: 06.10.2021 01:19, Dmitry Osipenko пишет: ... > I reproduced the OFF problem by removing the clk prepare/unprepare from > the suspend/resume of the clk driver and making some extra changes to > clock tree topology and etc to trigger the problem on Nexus 7. > > tegra-pmc 7000e400.pmc: failed to turn off PM domain heg: -13 > > It happens from genpd_suspend_noirq() -> tegra_genpd_power_off() -> clk > -> GENPD -> I2C -> runtime-pm. > > -13 is EACCES, it comes from the runtime PM of I2C device. RPM is > prohibited/disabled during late (NOIRQ) suspend by the drivers core. My bad, I double-checked and it's not I2C RPM that is failing now, but the clock's RPM [1], which is also unavailable during NOIRQ. >>> >>> Yes, that sounds reasonable. >>> >>> You would then need a similar patch for the tegra clock driver as I >>> suggested for tegra I2C driver. That should solve the problem, I >>> think. >>> [1] https://elixir.free-electrons.com/linux/v5.15-rc4/source/drivers/clk/clk.c#L116 Previously it was I2C RPM that was failing in a similar way, but code changed a tad since that time. >>> >>> Alright. In any case, as long as the devices gets suspended in the >>> correct order, I think it should be fine to cook a patch along the >>> lines of what I suggest for the I2C driver as well. >>> >>> It should work, I think. Although, maybe you want to avoid runtime >>> resuming the I2C device, unless it's the device belonging to the PMIC >>> interface, if there is a way to distinguish that for the driver. >> >> Ulf, thank you very much for the suggestions! I was thinking about this >> all once again and concluded that the simplest variant will be to just >> remove the suspend ops from the clk driver since neither of PLLs require >> high voltage. We now have voltage bumped to a nominal level during >> suspend by Tegra's regulator-coupler driver and it's much higher than >> voltage needed by PLLs. So the problem I was trying to work around >> doesn't really exist anymore. > > I hurried a bit with the conclusion, keep forgetting that I need to > change the clock tree in order to test it all properly :/ It's not fixed > yet. > Please let me iterate once again. The problem we currently have is that clock may be enabled during NOIRQ time. In order to enable clock, it needs to be prepared. In order to prepare clock, the clock's device needs to be runtime-resumed. The runtime PM is unavailable at the NOIRQ time. To solve this problem we need to prepare clock beforehand. The clock will stay prepared during suspend, but this is not a problem since all the clocks we care about don't require high voltage and voltage is guaranteed to be bumped high during suspend by Tegra's regulator-coupler driver anyways. So everything we need to do is to keep clocks prepared. There are two options how to do that: [1] this patch which explicitly prepares clocks using clk API. [2] Use runtime PM API, like this: static const struct dev_pm_ops tegra_clock_pm = { SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_resume_and_get, pm_runtime_put) }; Ulf, are you now okay with the current variant [1] of the patch or you prefer the second [2] option more?
Re: [PATCH v2 33/34] component: Remove component_master_ops and friends
Hi Stephen, I love your patch! Yet something to improve: [auto build test ERROR on e4e737bb5c170df6135a127739a9e6148ee3da82] url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 base: e4e737bb5c170df6135a127739a9e6148ee3da82 config: hexagon-randconfig-r045-20211006 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project c0039de2953d15815448b4b3c3bafb45607781e0) 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/b2ecd8598795ffcc3d4e766c4c4cc93865f3ff33 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 git checkout b2ecd8598795ffcc3d4e766c4c4cc93865f3ff33 # save the attached .config to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=hexagon SHELL=/bin/bash drivers/base/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): >> drivers/base/component.c:412:15: error: no member named 'ops' in 'struct >> aggregate_device' return adev->ops->bind(adev->parent); ^ drivers/base/component.c:417:8: error: no member named 'ops' in 'struct aggregate_device' adev->ops->unbind(adev->parent); ^ drivers/base/component.c:488:13: error: incompatible function pointer types initializing 'void (*)(struct device *)' with an expression of type 'int (struct device *)' [-Werror,-Wincompatible-function-pointer-types] .remove = aggregate_driver_remove, ^~~ drivers/base/component.c:540:8: error: no member named 'ops' in 'struct aggregate_device' adev->ops = ops; ^ >> drivers/base/component.c:540:14: error: use of undeclared identifier 'ops' adev->ops = ops; ^ >> drivers/base/component.c:572:50: error: too many arguments to function call, >> expected 3, have 4 adev = aggregate_device_add(parent, NULL, adrv, match); ^ drivers/base/component.c:514:33: note: 'aggregate_device_add' declared here static struct aggregate_device *aggregate_device_add(struct device *parent, ^ >> drivers/base/component.c:599:34: error: too many arguments to function call, >> expected single argument 'parent', have 2 arguments adev = __aggregate_find(parent, NULL); ^~~~ include/linux/stddef.h:8:14: note: expanded from macro 'NULL' #define NULL ((void *)0) ^~~ drivers/base/component.c:493:33: note: '__aggregate_find' declared here static struct aggregate_device *__aggregate_find(struct device *parent) ^ drivers/base/component.c:645:34: error: too many arguments to function call, expected single argument 'parent', have 2 arguments adev = __aggregate_find(parent, NULL); ^~~~ include/linux/stddef.h:8:14: note: expanded from macro 'NULL' #define NULL ((void *)0) ^~~ drivers/base/component.c:493:33: note: '__aggregate_find' declared here static struct aggregate_device *__aggregate_find(struct device *parent) ^ drivers/base/component.c:734:34: error: too many arguments to function call, expected single argument 'parent', have 2 arguments adev = __aggregate_find(parent, NULL); ^~~~ include/linux/stddef.h:8:14: note: expanded from macro 'NULL' #define NULL ((void *)0) ^~~ drivers/base/component.c:493:33: note: '__aggregate_find' declared here static struct aggregate_device *__aggregate_find(struct device *parent) ^ 9 errors generated. vim +412 drivers/base/component.c b7f12127fd97fe Stephen Boyd 2021-10-06 408 b7f12127fd97fe Stephen Boyd 2021-10-06 409 /* TODO: Remove once all aggregate drivers use component_aggregate_register() */ b7f12127fd97fe Stephen Boyd 2021-10-06 410 static int component_probe_bind(struct aggregate_device *adev) b7f12127fd97fe Stephen Boyd 2021-10-06 411 { b7f12127fd97fe Stephen Boyd 2021-10-06 @412 return adev->ops->bind(adev->parent); b7f12127fd97fe Stephen Boyd 2021-10-06 413 } b7f12127fd97fe Stephen Boyd 2021-10-06 414 b7f12127fd97fe Stephen Boyd 2021-10-06 415 s
Re: [PATCH v2] drm/edid: In connector_bad_edid() cap num_of_ext by num_blocks read
On Wed, Oct 06, 2021 at 03:45:07PM -0700, Doug Anderson wrote: > Hi, > > On Tue, Oct 5, 2021 at 7:29 PM Douglas Anderson wrote: > > > > In commit e11f5bd8228f ("drm: Add support for DP 1.4 Compliance edid > > corruption test") the function connector_bad_edid() started assuming > > that the memory for the EDID passed to it was big enough to hold > > `edid[0x7e] + 1` blocks of data (1 extra for the base block). It > > completely ignored the fact that the function was passed `num_blocks` > > which indicated how much memory had been allocated for the EDID. > > > > Let's fix this by adding a bounds check. > > > > This is important for handling the case where there's an error in the > > first block of the EDID. In that case we will call > > connector_bad_edid() without having re-allocated memory based on > > `edid[0x7e]`. > > > > Fixes: e11f5bd8228f ("drm: Add support for DP 1.4 Compliance edid > > corruption test") > > Reported-by: Ville Syrjälä > > Signed-off-by: Douglas Anderson > > Reviewed-by: Ville Syrjälä > > --- > > This problem report came up in the context of a patch I sent out [1] > > and this is my attempt at a fix. The problem predates my patch, > > though. I don't personally know anything about DP compliance testing > > and what should be happening here, nor do I apparently have any > > hardware that actually reports a bad EDID. Thus this is just compile > > tested. I'm hoping that someone here can test this and make sure it > > seems OK to them. > > > > Changes in v2: > > - Added a comment/changed math to help make it easier to grok. > > > > drivers/gpu/drm/drm_edid.c | 15 --- > > 1 file changed, 12 insertions(+), 3 deletions(-) > > Pushed this to drm-misc-fixes since the commit it fixes is fairly old. > > fdc21c35aaa1 drm/edid: In connector_bad_edid() cap num_of_ext by num_blocks > read BTW seems kasan caught this for us [1]. I didn't notice we had a bug open about it until now. Just Chris Wilson mentioned it to me in passing quite a while ago, and I totally forgot about it until I saw your other patch poking around the same code. [1] https://gitlab.freedesktop.org/drm/intel/-/issues/4106 -- Ville Syrjälä Intel
Re: [PATCH v2] drm/edid: In connector_bad_edid() cap num_of_ext by num_blocks read
Hi, On Tue, Oct 5, 2021 at 7:29 PM Douglas Anderson wrote: > > In commit e11f5bd8228f ("drm: Add support for DP 1.4 Compliance edid > corruption test") the function connector_bad_edid() started assuming > that the memory for the EDID passed to it was big enough to hold > `edid[0x7e] + 1` blocks of data (1 extra for the base block). It > completely ignored the fact that the function was passed `num_blocks` > which indicated how much memory had been allocated for the EDID. > > Let's fix this by adding a bounds check. > > This is important for handling the case where there's an error in the > first block of the EDID. In that case we will call > connector_bad_edid() without having re-allocated memory based on > `edid[0x7e]`. > > Fixes: e11f5bd8228f ("drm: Add support for DP 1.4 Compliance edid corruption > test") > Reported-by: Ville Syrjälä > Signed-off-by: Douglas Anderson > Reviewed-by: Ville Syrjälä > --- > This problem report came up in the context of a patch I sent out [1] > and this is my attempt at a fix. The problem predates my patch, > though. I don't personally know anything about DP compliance testing > and what should be happening here, nor do I apparently have any > hardware that actually reports a bad EDID. Thus this is just compile > tested. I'm hoping that someone here can test this and make sure it > seems OK to them. > > Changes in v2: > - Added a comment/changed math to help make it easier to grok. > > drivers/gpu/drm/drm_edid.c | 15 --- > 1 file changed, 12 insertions(+), 3 deletions(-) Pushed this to drm-misc-fixes since the commit it fixes is fairly old. fdc21c35aaa1 drm/edid: In connector_bad_edid() cap num_of_ext by num_blocks read -Doug
Re: [PATCH v2 02/34] component: Introduce the aggregate bus_type
Hi Stephen, I love your patch! Yet something to improve: [auto build test ERROR on e4e737bb5c170df6135a127739a9e6148ee3da82] url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 base: e4e737bb5c170df6135a127739a9e6148ee3da82 config: hexagon-randconfig-r045-20211006 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project c0039de2953d15815448b4b3c3bafb45607781e0) 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/b7f12127fd97fe811eaf9600a6677fb1cbb66554 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 git checkout b7f12127fd97fe811eaf9600a6677fb1cbb66554 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All errors (new ones prefixed by >>): >> drivers/base/component.c:509:13: error: incompatible function pointer types >> initializing 'void (*)(struct device *)' with an expression of type 'int >> (struct device *)' [-Werror,-Wincompatible-function-pointer-types] .remove = aggregate_driver_remove, ^~~ 1 error generated. vim +509 drivers/base/component.c 504 505 static struct bus_type aggregate_bus_type = { 506 .name = "aggregate", 507 .match = aggregate_device_match, 508 .probe = aggregate_driver_probe, > 509 .remove = aggregate_driver_remove, 510 .shutdown = aggregate_driver_shutdown, 511 }; 512 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API
Hi Stephen, I love your patch! Perhaps something to improve: [auto build test WARNING on e4e737bb5c170df6135a127739a9e6148ee3da82] url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 base: e4e737bb5c170df6135a127739a9e6148ee3da82 config: s390-randconfig-r044-20211006 (attached as .config) compiler: s390-linux-gcc (GCC) 11.2.0 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/8de4fafdac42c316be0fc23e4176e13043031a38 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 git checkout 8de4fafdac42c316be0fc23e4176e13043031a38 # save the attached .config to linux build tree mkdir build_dir COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=s390 SHELL=/bin/bash drivers/gpu/drm/bridge/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): In file included from drivers/gpu/drm/bridge/chipone-icn6211.c:7: >> include/drm/drm_of.h:45:35: warning: 'struct aggregate_driver' declared >> inside parameter list will not be visible outside of this definition or >> declaration 45 |struct aggregate_driver *adrv); | ^~~~ vim +45 include/drm/drm_of.h 30 31 #ifdef CONFIG_OF 32 uint32_t drm_of_crtc_port_mask(struct drm_device *dev, 33 struct device_node *port); 34 uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 35 struct device_node *port); 36 void drm_of_component_match_add(struct device *master, 37 struct component_match **matchptr, 38 int (*compare)(struct device *, void *), 39 struct device_node *node); 40 int drm_of_component_probe(struct device *dev, 41 int (*compare_of)(struct device *, void *), 42 const struct component_master_ops *m_ops); 43 int drm_of_aggregate_probe(struct device *dev, 44 int (*compare_of)(struct device *, void *), > 45 struct aggregate_driver *adrv); 46 int drm_of_encoder_active_endpoint(struct device_node *node, 47 struct drm_encoder *encoder, 48 struct of_endpoint *endpoint); 49 int drm_of_find_panel_or_bridge(const struct device_node *np, 50 int port, int endpoint, 51 struct drm_panel **panel, 52 struct drm_bridge **bridge); 53 int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, 54const struct device_node *port2); 55 #else 56 static inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev, 57struct device_node *port) 58 { 59 return 0; 60 } 61 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API
Hi Stephen, I love your patch! Perhaps something to improve: [auto build test WARNING on e4e737bb5c170df6135a127739a9e6148ee3da82] url: https://github.com/0day-ci/linux/commits/Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 base: e4e737bb5c170df6135a127739a9e6148ee3da82 config: hexagon-randconfig-r041-20211006 (attached as .config) compiler: clang version 14.0.0 (https://github.com/llvm/llvm-project c0039de2953d15815448b4b3c3bafb45607781e0) 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/8de4fafdac42c316be0fc23e4176e13043031a38 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Stephen-Boyd/component-Make-into-an-aggregate-bus/20211007-034200 git checkout 8de4fafdac42c316be0fc23e4176e13043031a38 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 ARCH=hexagon If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot All warnings (new ones prefixed by >>): In file included from drivers/gpu/drm/bridge/synopsys/dw-hdmi.c:32: >> include/drm/drm_of.h:45:14: warning: declaration of 'struct >> aggregate_driver' will not be visible outside of this function [-Wvisibility] struct aggregate_driver *adrv); ^ 1 warning generated. vim +45 include/drm/drm_of.h 30 31 #ifdef CONFIG_OF 32 uint32_t drm_of_crtc_port_mask(struct drm_device *dev, 33 struct device_node *port); 34 uint32_t drm_of_find_possible_crtcs(struct drm_device *dev, 35 struct device_node *port); 36 void drm_of_component_match_add(struct device *master, 37 struct component_match **matchptr, 38 int (*compare)(struct device *, void *), 39 struct device_node *node); 40 int drm_of_component_probe(struct device *dev, 41 int (*compare_of)(struct device *, void *), 42 const struct component_master_ops *m_ops); 43 int drm_of_aggregate_probe(struct device *dev, 44 int (*compare_of)(struct device *, void *), > 45 struct aggregate_driver *adrv); 46 int drm_of_encoder_active_endpoint(struct device_node *node, 47 struct drm_encoder *encoder, 48 struct of_endpoint *endpoint); 49 int drm_of_find_panel_or_bridge(const struct device_node *np, 50 int port, int endpoint, 51 struct drm_panel **panel, 52 struct drm_bridge **bridge); 53 int drm_of_lvds_get_dual_link_pixel_order(const struct device_node *port1, 54const struct device_node *port2); 55 #else 56 static inline uint32_t drm_of_crtc_port_mask(struct drm_device *dev, 57struct device_node *port) 58 { 59 return 0; 60 } 61 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-...@lists.01.org .config.gz Description: application/gzip
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
06.10.2021 15:38, Ulf Hansson пишет: >>> Right, so the PM domain managed in tegra_genpd_power_on|off() can >>> still be powered on/off, as long as the clock remains ungated? >> Not ungated, but prepared. > Okay, thanks for clarifying! > > In summary, it sounds like you should be able to fix this problem in > the I2C driver as I suggested above. If that works, that seems much > better. I'll try this variant, thank you. > Moreover, it would leave the clocks gated/unprepared when the system > is fully suspended, which I guess is better from an energy point of > view? The clocks are kept gated, it wasn't a problem. The problem was that clocks were needed to be enabled temporarily. In order to enable a clock, it needs to be prepared first. When clock is prepared, it resumes clock's device RPM. Keeping clocks prepared shouldn't make a noticeable difference from the energy POV since clocks are gated. It's only voltage that is kept high, but we need to keep it high during suspend anyways in order to resume successfully. The hardware is mostly gated during suspend, depending on suspend mode, so the power consumption difference is negligible. At least I haven't seen any problems, battery doesn't drain during suspend.
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
07.10.2021 00:14, Dmitry Osipenko пишет: > 06.10.2021 15:43, Ulf Hansson пишет: >> On Wed, 6 Oct 2021 at 00:43, Dmitry Osipenko wrote: >>> >>> 06.10.2021 01:19, Dmitry Osipenko пишет: >>> ... I reproduced the OFF problem by removing the clk prepare/unprepare from the suspend/resume of the clk driver and making some extra changes to clock tree topology and etc to trigger the problem on Nexus 7. tegra-pmc 7000e400.pmc: failed to turn off PM domain heg: -13 It happens from genpd_suspend_noirq() -> tegra_genpd_power_off() -> clk -> GENPD -> I2C -> runtime-pm. -13 is EACCES, it comes from the runtime PM of I2C device. RPM is prohibited/disabled during late (NOIRQ) suspend by the drivers core. >>> >>> My bad, I double-checked and it's not I2C RPM that is failing now, but >>> the clock's RPM [1], which is also unavailable during NOIRQ. >> >> Yes, that sounds reasonable. >> >> You would then need a similar patch for the tegra clock driver as I >> suggested for tegra I2C driver. That should solve the problem, I >> think. >> >>> >>> [1] >>> https://elixir.free-electrons.com/linux/v5.15-rc4/source/drivers/clk/clk.c#L116 >>> >>> Previously it was I2C RPM that was failing in a similar way, but code >>> changed a tad since that time. >> >> Alright. In any case, as long as the devices gets suspended in the >> correct order, I think it should be fine to cook a patch along the >> lines of what I suggest for the I2C driver as well. >> >> It should work, I think. Although, maybe you want to avoid runtime >> resuming the I2C device, unless it's the device belonging to the PMIC >> interface, if there is a way to distinguish that for the driver. > > Ulf, thank you very much for the suggestions! I was thinking about this > all once again and concluded that the simplest variant will be to just > remove the suspend ops from the clk driver since neither of PLLs require > high voltage. We now have voltage bumped to a nominal level during > suspend by Tegra's regulator-coupler driver and it's much higher than > voltage needed by PLLs. So the problem I was trying to work around > doesn't really exist anymore. I hurried a bit with the conclusion, keep forgetting that I need to change the clock tree in order to test it all properly :/ It's not fixed yet.
Re: [igt-dev] [PATCH i-g-t 1/1] tests/i915_pxp: Use ioctl_wrapper for DRM_IOCTL_PRIME_HANDLE_TO_FD
On Wed, Oct 06, 2021 at 05:11:02PM +, Ruhl, Michael J wrote: > >-Original Message- > >From: Teres Alexis, Alan Previn > >Sent: Wednesday, October 6, 2021 12:52 PM > >To: igt-...@lists.freedesktop.org > >Cc: Teres Alexis, Alan Previn ; dri- > >de...@lists.freedesktop.org; Ruhl; Ruhl, Michael J > >; Vivi, Rodrigo > >Subject: [PATCH i-g-t 1/1] tests/i915_pxp: Use ioctl_wrapper for > >DRM_IOCTL_PRIME_HANDLE_TO_FD > > > >Replace private helper with call to ioctl_wrapper for > >DRM_IOCTL_PRIME_HANDLE_TO_FD. > > Reviewed-by: Michael J. Ruhl pushed, thanks > > M > > >Signed-off-by: Alan Previn > >--- > > tests/i915/gem_pxp.c | 20 +--- > > 1 file changed, 1 insertion(+), 19 deletions(-) > > > >diff --git a/tests/i915/gem_pxp.c b/tests/i915/gem_pxp.c > >index 79040165..0430f4b8 100644 > >--- a/tests/i915/gem_pxp.c > >+++ b/tests/i915/gem_pxp.c > >@@ -622,23 +622,6 @@ static void test_render_pxp_protsrc_to_protdest(int > >i915) > > buf_ops_destroy(bops); > > } > > > >-static int export_handle(int fd, uint32_t handle, int *outfd) > >-{ > >-struct drm_prime_handle args; > >-int ret; > >- > >-args.handle = handle; > >-args.flags = DRM_CLOEXEC; > >-args.fd = -1; > >- > >-ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, ); > >-if (ret) > >-ret = errno; > >-*outfd = args.fd; > >- > >-return ret; > >-} > >- > > static void test_pxp_dmabuffshare_refcnt(void) > > { > > uint32_t ctx[2], sbo[2], dbo[2]; > >@@ -659,8 +642,7 @@ static void test_pxp_dmabuffshare_refcnt(void) > > dbo[0] = alloc_and_fill_dest_buff(fd[0], true, > >TSTSURF_SIZE, > > > >TSTSURF_INITCOLOR1); > > } else { > >-ret = export_handle(fd[0], dbo[0], _fd); > >-igt_assert(ret == 0); > >+dmabuf_fd = prime_handle_to_fd(fd[0], dbo[0]); > > dbo[1] = prime_fd_to_handle(fd[1], dmabuf_fd); > > igt_assert(dbo[1]); > > } > >-- > >2.25.1 >
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
06.10.2021 15:38, Ulf Hansson пишет: >> I'm also wondering if we could add some 'was_enabled' flag to GENPDs, >> setting it by genpd_suspend_noirq() for the enabled domains, and then >> powering-on GENPDs from genpd_resume_noirq() only if they were in the >> enabled state during genpd_suspend_noirq() time. It actually puzzled me >> for a quite long time why GENPD core enables domains unconditionally >> during early resume. This should solve a part of the problem and it >> makes suspend/resume a bit safer because there is a smaller chance to >> crash hardware during suspend, at least it's easier to debug. > Just because the PM domain was already off at genpd_suspend_noirq(), > doesn't mean that it can stay powered off at genpd_resume_noirq(). At > least as is today. > > The main reason why genpd_resume_noirq() powers on the PM domain, is > because it's not possible for the consumer drivers to rely on runtime > PM to do it (because runtime PM has been disabled by the PM core). At least Tegra doesn't need to have domains force-resumed. This should be a platform-specific behaviour. We may add a new flag for that, I suppose. I'll try to keep this in mind for a future improvement. Thank you for the clarification.
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
06.10.2021 15:38, Ulf Hansson пишет: > In principle what you ask for, is if we can avoid calling > __pm_runtime_disable() in __device_suspend_late() (and vice versa in > device_resume_early()). > > I think the short answer is no, at least from a generic point of view. > Maybe we can figure out a way to allow this on a per device basis, as > an opt-in solution. I am not sure what Rafael would think about this, > let's see. > > Another option to address the problem is already available to use for > these kinds of cases. This would be to add also a pair of > ->suspend|resume() callbacks to I2C driver. Along the lines of the > below. > > diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c > index c883044715f3..589bf872ab25 100644 > --- a/drivers/i2c/busses/i2c-tegra.c > +++ b/drivers/i2c/busses/i2c-tegra.c > @@ -1918,6 +1918,7 @@ static int __maybe_unused > tegra_i2c_resume(struct device *dev) > } > > static const struct dev_pm_ops tegra_i2c_pm = { > + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_put_noidle, pm_runtime_get_sync) > SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(tegra_i2c_suspend, tegra_i2c_resume) > SET_RUNTIME_PM_OPS(tegra_i2c_runtime_suspend, > tegra_i2c_runtime_resume, >NULL) > > In this way, the device would already be runtime resumed, if there is > call to pm_runtime_get_sync() from the clock framework due to the > clk_prepare|unprepare() being called. If that also turns out to happen > *after* runtime PM has been disabled for the device, the call to > pm_runtime_get_sync() would still succeed (returning 1, see > rpm_resume()), rather than a negative error code. > > Yes, we may end up runtime resuming the device during system suspend, > even if it turns out not to be needed. Although, that doesn't seem to > be the case for the Tegra I2C driver, right? Tegra I2C will turn off clocks on suspend regardless of RPM state. Overall, it's a plausible solution, thank you! As I said in the other reply, I'll simply remove the suspend ops from clk driver, they are not needed anymore. The problem is gone.
Re: [PATCH v13 06/35] clk: tegra: Support runtime PM and power domain
06.10.2021 15:43, Ulf Hansson пишет: > On Wed, 6 Oct 2021 at 00:43, Dmitry Osipenko wrote: >> >> 06.10.2021 01:19, Dmitry Osipenko пишет: >> ... >>> I reproduced the OFF problem by removing the clk prepare/unprepare from >>> the suspend/resume of the clk driver and making some extra changes to >>> clock tree topology and etc to trigger the problem on Nexus 7. >>> >>> tegra-pmc 7000e400.pmc: failed to turn off PM domain heg: -13 >>> >>> It happens from genpd_suspend_noirq() -> tegra_genpd_power_off() -> clk >>> -> GENPD -> I2C -> runtime-pm. >>> >>> -13 is EACCES, it comes from the runtime PM of I2C device. RPM is >>> prohibited/disabled during late (NOIRQ) suspend by the drivers core. >> >> My bad, I double-checked and it's not I2C RPM that is failing now, but >> the clock's RPM [1], which is also unavailable during NOIRQ. > > Yes, that sounds reasonable. > > You would then need a similar patch for the tegra clock driver as I > suggested for tegra I2C driver. That should solve the problem, I > think. > >> >> [1] >> https://elixir.free-electrons.com/linux/v5.15-rc4/source/drivers/clk/clk.c#L116 >> >> Previously it was I2C RPM that was failing in a similar way, but code >> changed a tad since that time. > > Alright. In any case, as long as the devices gets suspended in the > correct order, I think it should be fine to cook a patch along the > lines of what I suggest for the I2C driver as well. > > It should work, I think. Although, maybe you want to avoid runtime > resuming the I2C device, unless it's the device belonging to the PMIC > interface, if there is a way to distinguish that for the driver. Ulf, thank you very much for the suggestions! I was thinking about this all once again and concluded that the simplest variant will be to just remove the suspend ops from the clk driver since neither of PLLs require high voltage. We now have voltage bumped to a nominal level during suspend by Tegra's regulator-coupler driver and it's much higher than voltage needed by PLLs. So the problem I was trying to work around doesn't really exist anymore.
Re: [PATCH v1 1/3] dt-bindings: display: simple: add Innolux G070Y2-T02 panel
On Thu, 30 Sep 2021 12:04:59 +0200, Oleksij Rempel wrote: > Add binding for the Innolux G070Y2-T02 panel. It is 7" WVGA (800x480) > TFT LCD panel with TTL interface and a backlight unit. > > Signed-off-by: Oleksij Rempel > --- > .../devicetree/bindings/display/panel/panel-simple.yaml | 2 ++ > 1 file changed, 2 insertions(+) > Acked-by: Rob Herring
Re: [PATCH v1 2/2] drm/tegra: dc: rgb: Allow changing PLLD rate on Tegra30+
06.10.2021 21:27, Dmitry Osipenko пишет: > 06.10.2021 21:13, Thierry Reding пишет: >> On Thu, Sep 30, 2021 at 01:28:05AM +0300, Dmitry Osipenko wrote: >>> Asus Transformer TF700T is a Tegra30 tablet device which uses RGB->DSI >>> bridge that requires a precise clock rate in order to operate properly. >>> Tegra30 has a dedicated PLL for each display controller, hence the PLL >>> rate can be changed freely. Allow PLL rate changes on Tegra30+ for RGB >>> output. Configure the clock rate before display controller is enabled >>> since DC itself may be running off this PLL and it's not okay to change >>> the rate of the active PLL that doesn't support dynamic frequency >>> switching since hardware will hang. >>> >>> Tested-by: Maxim Schwalm #TF700T >>> Signed-off-by: Dmitry Osipenko >>> --- >>> drivers/gpu/drm/tegra/dc.c | 27 >>> drivers/gpu/drm/tegra/dc.h | 1 + >>> drivers/gpu/drm/tegra/rgb.c | 49 +++-- >>> 3 files changed, 65 insertions(+), 12 deletions(-) >> >> This seems overly complicated. I especially don't like the way how >> clocks are looked up with clk_get_sys() and then used in the comparison. >> Could this not be achieved by using assigned-clocks and friends >> properties in DT? > > Assigned-clocks have nothing to do with this patch. We need to check > whether PLLD *is* already pre-assigned as the parent. > > Adding properties for describing the clk parents is overly complicated, > clk_get_sys() is a much simpler solution that doesn't involve extra DT > changes. > > BTW, assigned-clocks can't be used for display controller because > controller is usually turned on during boot and reparenting of active DC > will hang machine. > To make it more clear, we change the DC's "parent" in TF700T device-tree to PLLD [1] to match the bootloader's configuration, otherwise it will hang on boot since default "parent" in tegra30.dtsi is PLLP, and thus, tegra_dc_rgb_probe() will try to reparent it to PLLP. Display of TF700T won't work with PLLP anyways since it needs a specific clock rate. [1] https://github.com/grate-driver/linux/blob/master/arch/arm/boot/dts/tegra30-asus-tf700t.dts#L13
Re: [Intel-gfx] [PATCH 21/26] drm/i915: Multi-BB execbuf
On Mon, Oct 04, 2021 at 03:06:32PM -0700, Matthew Brost wrote: > Allow multiple batch buffers to be submitted in a single execbuf IOCTL > after a context has been configured with the 'set_parallel' extension. > The number batches is implicit based on the contexts configuration. > > This is implemented with a series of loops. First a loop is used to find > all the batches, a loop to pin all the HW contexts, a loop to create all > the requests, a loop to submit (emit BB start, etc...) all the requests, > a loop to tie the requests to the VMAs they touch, and finally a loop to > commit the requests to the backend. > > A composite fence is also created for the generated requests to return > to the user and to stick in dma resv slots. > > No behavior from the existing IOCTL should be changed aside from when > throttling because the ring for a context is full, wait on the request > while holding the object locks. > > IGT: https://patchwork.freedesktop.org/patch/447008/?series=93071=1 > media UMD: https://github.com/intel/media-driver/pull/1252 > > v2: > (Matthew Brost) > - Return proper error value if i915_request_create fails > v3: > (John Harrison) > - Add comment explaining create / add order loops + locking > - Update commit message explaining different in IOCTL behavior > - Line wrap some comments > - eb_add_request returns void > - Return -EINVAL rather triggering BUG_ON if cmd parser used > (Checkpatch) > - Check eb->batch_len[*current_batch] > > Signed-off-by: Matthew Brost > --- > .../gpu/drm/i915/gem/i915_gem_execbuffer.c| 793 -- > drivers/gpu/drm/i915/gt/intel_context.h | 8 +- > drivers/gpu/drm/i915/gt/intel_context_types.h | 10 + > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 + > drivers/gpu/drm/i915/i915_request.h | 9 + > drivers/gpu/drm/i915/i915_vma.c | 21 +- > drivers/gpu/drm/i915/i915_vma.h | 13 +- > 7 files changed, 599 insertions(+), 257 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > index 2f2434b52317..5c7fb6f68bbb 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c > @@ -244,17 +244,25 @@ struct i915_execbuffer { > struct drm_i915_gem_exec_object2 *exec; /** ioctl execobj[] */ > struct eb_vma *vma; > > - struct intel_engine_cs *engine; /** engine to queue the request to */ > + struct intel_gt *gt; /* gt for the execbuf */ > struct intel_context *context; /* logical state for the request */ > struct i915_gem_context *gem_context; /** caller's context */ > > - struct i915_request *request; /** our request to build */ > - struct eb_vma *batch; /** identity of the batch obj/vma */ > + /** our requests to build */ > + struct i915_request *requests[MAX_ENGINE_INSTANCE + 1]; > + /** identity of the batch obj/vma */ > + struct eb_vma *batches[MAX_ENGINE_INSTANCE + 1]; > struct i915_vma *trampoline; /** trampoline used for chaining */ > > + /** used for excl fence in dma_resv objects when > 1 BB submitted */ > + struct dma_fence *composite_fence; > + > /** actual size of execobj[] as we may extend it for the cmdparser */ > unsigned int buffer_count; > > + /* number of batches in execbuf IOCTL */ > + unsigned int num_batches; > + > /** list of vma not yet bound during reservation phase */ > struct list_head unbound; > > @@ -281,7 +289,8 @@ struct i915_execbuffer { > > u64 invalid_flags; /** Set of execobj.flags that are invalid */ > > - u64 batch_len; /** Length of batch within object */ > + /** Length of batch within object */ > + u64 batch_len[MAX_ENGINE_INSTANCE + 1]; > u32 batch_start_offset; /** Location within object of batch */ > u32 batch_flags; /** Flags composed for emit_bb_start() */ > struct intel_gt_buffer_pool_node *batch_pool; /** pool node for batch > buffer */ > @@ -299,14 +308,13 @@ struct i915_execbuffer { > }; > > static int eb_parse(struct i915_execbuffer *eb); > -static struct i915_request *eb_pin_engine(struct i915_execbuffer *eb, > - bool throttle); > +static int eb_pin_engine(struct i915_execbuffer *eb, bool throttle); > static void eb_unpin_engine(struct i915_execbuffer *eb); > > static inline bool eb_use_cmdparser(const struct i915_execbuffer *eb) > { > - return intel_engine_requires_cmd_parser(eb->engine) || > - (intel_engine_using_cmd_parser(eb->engine) && > + return intel_engine_requires_cmd_parser(eb->context->engine) || > + (intel_engine_using_cmd_parser(eb->context->engine) && >eb->args->batch_len); > } > > @@ -544,11 +552,21 @@ eb_validate_vma(struct i915_execbuffer *eb, > return 0; > } > > -static void > +static inline bool > +is_batch_buffer(struct
[PATCH 2/2] drm/msm/dsi: stop setting clock parents manually
There is no reason to set clock parents manually, use device tree to assign DSI/display clock parents to DSI PHY clocks. Dropping this manual setup allows us to drop repeating code and to move registration of hw clock providers to generic place. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi.h | 2 - drivers/gpu/drm/msm/dsi/dsi_host.c| 53 --- drivers/gpu/drm/msm/dsi/dsi_manager.c | 11 +- drivers/gpu/drm/msm/dsi/phy/dsi_phy.c | 11 -- 4 files changed, 2 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index 7dfb6d198ca9..c03a8d09c764 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -173,8 +173,6 @@ int msm_dsi_phy_enable(struct msm_dsi_phy *phy, void msm_dsi_phy_disable(struct msm_dsi_phy *phy); void msm_dsi_phy_set_usecase(struct msm_dsi_phy *phy, enum msm_dsi_phy_usecase uc); -int msm_dsi_phy_get_clk_provider(struct msm_dsi_phy *phy, - struct clk **byte_clk_provider, struct clk **pixel_clk_provider); void msm_dsi_phy_pll_save_state(struct msm_dsi_phy *phy); int msm_dsi_phy_pll_restore_state(struct msm_dsi_phy *phy); void msm_dsi_phy_snapshot(struct msm_disp_state *disp_state, 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 1ffcd0577e99..9600b4fa27eb 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2232,59 +2232,6 @@ void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, msm_host->cphy_mode = src_phy->cphy_mode; } -int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, - struct msm_dsi_phy *src_phy) -{ - struct msm_dsi_host *msm_host = to_msm_dsi_host(host); - struct clk *byte_clk_provider, *pixel_clk_provider; - int ret; - - msm_host->cphy_mode = src_phy->cphy_mode; - - ret = msm_dsi_phy_get_clk_provider(src_phy, - _clk_provider, _clk_provider); - if (ret) { - pr_info("%s: can't get provider from pll, don't set parent\n", - __func__); - return 0; - } - - ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider); - if (ret) { - pr_err("%s: can't set parent to byte_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - - ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider); - if (ret) { - pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - - if (msm_host->dsi_clk_src) { - ret = clk_set_parent(msm_host->dsi_clk_src, pixel_clk_provider); - if (ret) { - pr_err("%s: can't set parent to dsi_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - } - - if (msm_host->esc_clk_src) { - ret = clk_set_parent(msm_host->esc_clk_src, byte_clk_provider); - if (ret) { - pr_err("%s: can't set parent to esc_clk_src. ret=%d\n", - __func__, ret); - goto exit; - } - } - -exit: - return ret; -} - void msm_dsi_host_reset_phy(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 49a0a0841487..9342a822ad20 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -78,10 +78,7 @@ static int dsi_mgr_setup_components(int id) msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); - ret = msm_dsi_host_set_src_pll(msm_dsi->host, msm_dsi->phy); - } else if (!other_dsi) { - ret = 0; - } else { + } else if (other_dsi) { struct msm_dsi *master_link_dsi = IS_MASTER_DSI_LINK(id) ? msm_dsi : other_dsi; struct msm_dsi *slave_link_dsi = IS_MASTER_DSI_LINK(id) ? @@ -107,13 +104,9 @@ static int dsi_mgr_setup_components(int id) MSM_DSI_PHY_SLAVE); msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); - ret = msm_dsi_host_set_src_pll(msm_dsi->host, clk_master_dsi->phy); - if (ret) - return ret; - ret = msm_dsi_host_set_src_pll(other_dsi->host, clk_master_dsi->phy); } - return ret; + return 0; } static int
[PATCH 1/2] drm/msm/dsi: untangle cphy setting from the src pll setting
Move DPHY/CPHY setting from msm_dsi_host_set_src_pll() to new function msm_dsi_host_set_phy_mode(). Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/dsi/dsi.h | 2 ++ drivers/gpu/drm/msm/dsi/dsi_host.c| 8 drivers/gpu/drm/msm/dsi/dsi_manager.c | 3 +++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h index b50db91cb8a7..7dfb6d198ca9 100644 --- a/drivers/gpu/drm/msm/dsi/dsi.h +++ b/drivers/gpu/drm/msm/dsi/dsi.h @@ -118,6 +118,8 @@ unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host); struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host); int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer); void msm_dsi_host_unregister(struct mipi_dsi_host *host); +void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, + struct msm_dsi_phy *src_phy); int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_phy *src_phy); void msm_dsi_host_reset_phy(struct mipi_dsi_host *host); diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index e269df285136..1ffcd0577e99 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -2224,6 +2224,14 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 dma_base, wmb(); } +void msm_dsi_host_set_phy_mode(struct mipi_dsi_host *host, + struct msm_dsi_phy *src_phy) +{ + struct msm_dsi_host *msm_host = to_msm_dsi_host(host); + + msm_host->cphy_mode = src_phy->cphy_mode; +} + int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host, struct msm_dsi_phy *src_phy) { diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c index c41d39f5b7cf..49a0a0841487 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_manager.c +++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c @@ -77,6 +77,7 @@ static int dsi_mgr_setup_components(int id) return ret; msm_dsi_phy_set_usecase(msm_dsi->phy, MSM_DSI_PHY_STANDALONE); + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); ret = msm_dsi_host_set_src_pll(msm_dsi->host, msm_dsi->phy); } else if (!other_dsi) { ret = 0; @@ -104,6 +105,8 @@ static int dsi_mgr_setup_components(int id) MSM_DSI_PHY_MASTER); msm_dsi_phy_set_usecase(clk_slave_dsi->phy, MSM_DSI_PHY_SLAVE); + msm_dsi_host_set_phy_mode(msm_dsi->host, msm_dsi->phy); + msm_dsi_host_set_phy_mode(other_dsi->host, other_dsi->phy); ret = msm_dsi_host_set_src_pll(msm_dsi->host, clk_master_dsi->phy); if (ret) return ret; -- 2.33.0
Re: [PATCH] drm/i915/pmu: Connect engine busyness stats from GuC to pmu
On Wed, Oct 06, 2021 at 10:11:58AM +0100, Tvrtko Ursulin wrote: On 05/10/2021 18:47, Umesh Nerlige Ramappa wrote: With GuC handling scheduling, i915 is not aware of the time that a context is scheduled in and out of the engine. Since i915 pmu relies on this info to provide engine busyness to the user, GuC shares this info with i915 for all engines using shared memory. For each engine, this info contains: - total busyness: total time that the context was running (total) - id: id of the running context (id) - start timestamp: timestamp when the context started running (start) At the time (now) of sampling the engine busyness, if the id is valid (!= ~0), and start is non-zero, then the context is considered to be active and the engine busyness is calculated using the below equation engine busyness = total + (now - start) All times are obtained from the gt clock base. For inactive contexts, engine busyness is just equal to the total. The start and total values provided by GuC are 32 bits and wrap around in a few minutes. Since perf pmu provides busyness as 64 bit monotonically increasing values, there is a need for this implementation to account for overflows and extend the time to 64 bits before returning busyness to the user. In order to do that, a worker runs periodically at frequency = 1/8th the time it takes for the timestamp to wrap. As an example, that would be once in 27 seconds for a gt clock frequency of 19.2 MHz. Opens and wip that are targeted for later patches: 1) On global gt reset the total busyness of engines resets and i915 needs to fix that so that user sees monotonically increasing busyness. 2) In runtime suspend mode, the worker may not need to be run. We could stop the worker on suspend and rerun it on resume provided that the guc pm timestamp does not tick during suspend. Second point had now been addressed, right? Both were addressed actually. For reset, I was mainly running busy-hang and after adding your suggestion of maintaining a consistent view, the busy-hang is fixed too. I will remove them from the commit msg. Note: There might be an overaccounting of busyness due to the fact that GuC may be updating the total and start values while kmd is reading them. (i.e kmd may read the updated total and the stale start). In such a case, user may see higher busyness value followed by smaller ones which would eventually catch up to the higher value. v2: (Tvrtko) - Include details in commit message - Move intel engine busyness function into execlist code - Use union inside engine->stats - Use natural type for ping delay jiffies - Drop active_work condition checks - Use for_each_engine if iterating all engines - Drop seq locking, use spinlock at guc level to update engine stats - Document worker specific details v3: (Tvrtko/Umesh) - Demarcate guc and execlist stat objects with comments - Document known over-accounting issue in commit - Provide a consistent view of guc state - Add hooks to gt park/unpark for guc busyness - Stop/start worker in gt park/unpark path - Drop inline - Move spinlock and worker inits to guc initialization - Drop helpers that are called only once Signed-off-by: John Harrison Signed-off-by: Umesh Nerlige Ramappa --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 26 +- drivers/gpu/drm/i915/gt/intel_engine_types.h | 90 +-- .../drm/i915/gt/intel_execlists_submission.c | 32 +++ drivers/gpu/drm/i915/gt/intel_gt_pm.c | 2 + .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc.h| 26 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 21 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h| 5 + drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 13 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 227 ++ .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 2 + drivers/gpu/drm/i915/i915_reg.h | 2 + 12 files changed, 398 insertions(+), 49 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 2ae57e4656a3..6fcc70a313d9 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1873,22 +1873,6 @@ void intel_engine_dump(struct intel_engine_cs *engine, intel_engine_print_breadcrumbs(engine, m); } -static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs *engine, - ktime_t *now) -{ - ktime_t total = engine->stats.total; - - /* -* If the engine is executing something at the moment -* add it to the total. -*/ - *now = ktime_get(); - if (READ_ONCE(engine->stats.active)) - total = ktime_add(total, ktime_sub(*now, engine->stats.start)); - - return total; -} - /** * intel_engine_get_busy_time() - Return current accumulated engine busyness * @engine: engine to report on @@ -1898,15 +1882,7 @@ static
[pull] amdgpu, amdkfd drm-fixes-5.15
Hi Dave, Daniel, Fixes for 5.15. The following changes since commit 9e1ff307c779ce1f0f810c7ecce3d95bbae40896: Linux 5.15-rc4 (2021-10-03 14:08:47 -0700) are available in the Git repository at: https://gitlab.freedesktop.org/agd5f/linux.git tags/amd-drm-fixes-5.15-2021-10-06 for you to fetch changes up to 5a1fef027846e7635b9d320b2cc0b416fd11a3be: drm/amd/display: Fix detection of 4 lane for DPALT (2021-10-06 16:14:17 -0400) amd-drm-fixes-5.15-2021-10-06: amdgpu: - DCN 3.1 DP alt mode fixes - S0ix gfxoff fix - Fix DRM_AMD_DC_SI dependencies - PCIe DPC handling fix - DCN 3.1 scaling fix - Documentation fix amdkfd: - Fix potential memory leak - IOMMUv2 init fixes Alex Deucher (2): Documentation/gpu: remove spurious "+" in amdgpu.rst drm/amdgpu/display: fix dependencies for DRM_AMD_DC_SI George Shen (1): drm/amd/display: Skip override for preferred link settings during link training Guchun Chen (1): drm/amdgpu: handle the case of pci_channel_io_frozen only in amdgpu_pci_resume Hansen (1): drm/amd/display: Fix detection of 4 lane for DPALT Jude Shih (1): drm/amd/display: USB4 bring up set correct address Lang Yu (1): drm/amdkfd: fix a potential ttm->sg memory leak Lijo Lazar (1): drm/amdgpu: During s0ix don't wait to signal GFXOFF Liu, Zhan (2): drm/amd/display: Fix B0 USB-C DP Alt mode drm/amd/display: Fix DCN3 B0 DP Alt Mapping Nikola Cornij (1): drm/amd/display: Limit display scaling to up to 4k for DCN 3.1 Yifan Zhang (2): drm/amdkfd: remove redundant iommu cleanup code drm/amdgpu: init iommu after amdkfd device init Documentation/gpu/amdgpu.rst | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu.h| 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 14 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c| 14 - drivers/gpu/drm/amd/amdkfd/kfd_device.c| 8 +-- drivers/gpu/drm/amd/display/Kconfig| 2 + drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 6 -- .../drm/amd/display/dc/dcn10/dcn10_link_encoder.h | 1 + .../amd/display/dc/dcn31/dcn31_dio_link_encoder.c | 66 +- .../amd/display/dc/dcn31/dcn31_dio_link_encoder.h | 14 - .../gpu/drm/amd/display/dc/dcn31/dcn31_resource.c | 8 ++- drivers/gpu/drm/amd/display/include/dal_asic_id.h | 2 +- .../amd/include/asic_reg/dpcs/dpcs_4_2_0_offset.h | 27 + 14 files changed, 142 insertions(+), 26 deletions(-)
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
On Wed 06 Oct 11:59 PDT 2021, Stephen Boyd wrote: > Quoting Bjorn Andersson (2021-10-06 11:05:09) > > On Wed 06 Oct 10:19 PDT 2021, Stephen Boyd wrote: > > > > > Quoting Bjorn Andersson (2021-10-06 10:07:17) > > > > On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > > > > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > > b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct > > > > > > > > > > platform_device *pdev) > > > > > > > > > > if (!dp) > > > > > > > > > > return -ENOMEM; > > > > > > > > > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC > > > > > > > > > specific > > > > > > > > > dpu_intf_cfg array in > > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > > > > > still. Is there any way we can avoid that? Also, notice how > > > > > > > > > those arrays > > > > > > > > > already have INTF_DP macros, which makes me think that it may > > > > > > > > > be better > > > > > > > > > to connect this to those arrays instead of making an > > > > > > > > > msm_dp_desc > > > > > > > > > structure and then make sure the 'type' member matches a > > > > > > > > > connector > > > > > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which > > > > > > > > part you > > > > > > > > consider fragile, the indices of the INTF_DP instances aren't > > > > > > > > going to > > > > > > > > move around... > > > > > > > > > > > > > > > > I have N instances of the DP driver that I need to match to N > > > > > > > > entries > > > > > > > > from the platform specific intf array, I need some stable > > > > > > > > reference > > > > > > > > between them. When I started this journey I figured I could > > > > > > > > rely on the > > > > > > > > of_graph between the DPU and the interface controllers, but the > > > > > > > > values > > > > > > > > used there today are just bogus, so that was a no go. > > > > > > > > > > > > > > > > We can use whatever, as long as > > > > > > > > _dpu_kms_initialize_displayport() can > > > > > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > > > > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > > > > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > > > ^ > > > > > > > | > > > > > > > > > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we > > > > > > > have a > > > > > > > zero, the number after INTF_DP, and that is very relevant. That > > > > > > > number > > > > > > > needs to match the dp->id. Somewhere we have a match between > > > > > > > controller_id and dp->id in the code. > > > > > > > > > > > > That number (the 0, not INTF_0) is what the code matches against > > > > > > dp->id > > > > > > in _dpu_kms_initialize_displayport(), in order to figure out that > > > > > > this > > > > > > is INTF_0 in dpu_encoder_setup_display(). > > > > > > > > > > > > I.e. look at the sc8180x patch: > > > > > > > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, > > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 26, 27), > > > > > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, > > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 28, 29), > > > > > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index > > > > > > until this is supported */ > > > > > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, > > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), > > > > > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, > > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 20, 21), > > > > > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, > > > > > > INTF_SC8180X_MASK,
Re: [PATCH v2 2/3] dt-bindings: drm/bridge: ps8640: Add aux-bus child
On Wed, 29 Sep 2021 17:34:57 -0700, Philip Chen wrote: > dp-aux-bus.yaml says we can list an eDP panel as a child of > an eDP controller node to represent the fact that the panel > is connected to the controller's DP AUX bus. > > Let's add it to the ps8640 bindings. > > Signed-off-by: Philip Chen > --- > > (no changes since v1) > > .../bindings/display/bridge/ps8640.yaml | 19 ++- > 1 file changed, 18 insertions(+), 1 deletion(-) > Reviewed-by: Rob Herring
Re: [Nouveau] [PATCH v3 2/5] drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux enable/brightness
On Wed, 2021-10-06 at 18:30 +0200, Karol Herbst wrote: > On Wed, Oct 6, 2021 at 4:41 AM Lyude Paul wrote: > > > > 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) && > > where does the DP_EDP_BACKLIGHT_AUX_ENABLE_CAP come from? afaik > drm_edp_backlight_supported checks for > DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP and > DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP so wondering if this was > intentional or a typo This is intentional - drm_edp_backlight_supported() does check for these, but in the patch after this we remove the BRIGHTNESS_AUX_SET_CAP from drm_edp_backlight_supported() in order to implement support for panels lacking BRIGHTNESS_AUX_SET_CAP in i915. Since we don't have support for this in nouveau yet but such backlights are likely to mostly work without the use of DPCD if we avoid trying to set it up, this patch is just here to make sure that the changes to drm_edp_backlight_supported() don't result in nouveau suddenly trying (and failing) to enable DPCD backlight controls on those backlights. > > > + (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 > > > -- Cheers, Lyude Paul (she/her) Software Engineer at Red Hat
Re: [PATCH v2] dt-bindings: display/bridge: sil, sii8620: Convert to YAML binding
On 06.10.2021 17:04, AngeloGioacchino Del Regno wrote: Convert the Silicon Image SiI8620 HDMI/MHL bridge documentation to YAML. Signed-off-by: AngeloGioacchino Del Regno --- .../bindings/display/bridge/sil,sii8620.yaml | 93 +++ .../bindings/display/bridge/sil-sii8620.txt | 33 --- 2 files changed, 93 insertions(+), 33 deletions(-) create mode 100644 Documentation/devicetree/bindings/display/bridge/sil,sii8620.yaml delete mode 100644 Documentation/devicetree/bindings/display/bridge/sil-sii8620.txt diff --git a/Documentation/devicetree/bindings/display/bridge/sil,sii8620.yaml b/Documentation/devicetree/bindings/display/bridge/sil,sii8620.yaml new file mode 100644 index ..5a38595b6687 --- /dev/null +++ b/Documentation/devicetree/bindings/display/bridge/sil,sii8620.yaml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/bridge/sil,sii8620.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Silicon Image SiI8620 HDMI/MHL bridge + +maintainers: + - Andrzej Hajda + +properties: + compatible: +const: sil,sii8620 + + reg: +description: I2C address of the bridge +maxItems: 1 + + clocks: +maxItems: 1 + + clock-names: +const: xtal + + cvcc10-supply: +description: Digital Core Supply Voltage, 1.0V + + iovcc18-supply: +description: I/O voltage supply, 1.8V + + interrupts: +maxItems: 1 + + reset-gpios: +description: GPIO connected to the reset pin. +maxItems: 1 + + ports: +$ref: /schemas/graph.yaml#/properties/ports + +properties: + port@0: +$ref: /schemas/graph.yaml#/properties/port +description: + Video port for HDMI input + +required: + - port@0 + +required: + - compatible + - reg + - cvcc10-supply + - iovcc18-supply + - interrupts + - ports What about gpios and other missing props. With that fixed you can add my r-b. Regards Andrzej + +additionalProperties: false + +examples: + - | +#include +#include + +i2c1 { + #address-cells = <1>; + #size-cells = <0>; + + bridge@39 { +compatible = "sil,sii8620"; +reg = <0x39>; +cvcc10-supply = <_reg>; +iovcc18-supply = <_reg>; +interrupt-parent = <>; +interrupts = <2 IRQ_TYPE_LEVEL_HIGH>; +reset-gpios = < 0 GPIO_ACTIVE_HIGH>; + +ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { +reg = <0>; +mhl_to_hdmi: endpoint { + remote-endpoint = <_to_mhl>; +}; + }; +}; + }; +}; + +... diff --git a/Documentation/devicetree/bindings/display/bridge/sil-sii8620.txt b/Documentation/devicetree/bindings/display/bridge/sil-sii8620.txt deleted file mode 100644 index b05052f7d62f.. --- a/Documentation/devicetree/bindings/display/bridge/sil-sii8620.txt +++ /dev/null @@ -1,33 +0,0 @@ -Silicon Image SiI8620 HDMI/MHL bridge bindings - -Required properties: - - compatible: "sil,sii8620" - - reg: i2c address of the bridge - - cvcc10-supply: Digital Core Supply Voltage (1.0V) - - iovcc18-supply: I/O Supply Voltage (1.8V) - - interrupts: interrupt specifier of INT pin - - reset-gpios: gpio specifier of RESET pin - - clocks, clock-names: specification and name of "xtal" clock - - video interfaces: Device node can contain video interface port - node for HDMI encoder according to [1]. - -[1]: Documentation/devicetree/bindings/media/video-interfaces.txt - -Example: - sii8620@39 { - reg = <0x39>; - compatible = "sil,sii8620"; - cvcc10-supply = <_reg>; - iovcc18-supply = <_reg>; - interrupt-parent = <>; - interrupts = <2 0>; - reset-gpio = < 0 0>; - clocks = <_system_controller 0>; - clock-names = "xtal"; - - port { - mhl_to_hdmi: endpoint { - remote-endpoint = <_to_mhl>; - }; - }; - };
[PATCH v2 30/34] sound: hdac: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Jaroslav Kysela Cc: Takashi Iwai Cc: Kai Vehmanen Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- sound/hda/hdac_component.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/sound/hda/hdac_component.c b/sound/hda/hdac_component.c index bb37e7e0bd79..9e4dab97f485 100644 --- a/sound/hda/hdac_component.c +++ b/sound/hda/hdac_component.c @@ -181,8 +181,9 @@ int snd_hdac_acomp_get_eld(struct hdac_device *codec, hda_nid_t nid, int dev_id, } EXPORT_SYMBOL_GPL(snd_hdac_acomp_get_eld); -static int hdac_component_master_bind(struct device *dev) +static int hdac_component_master_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_audio_component *acomp = hdac_get_acomp(dev); int ret; @@ -222,8 +223,9 @@ static int hdac_component_master_bind(struct device *dev) return ret; } -static void hdac_component_master_unbind(struct device *dev) +static void hdac_component_master_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_audio_component *acomp = hdac_get_acomp(dev); if (acomp->audio_ops && acomp->audio_ops->master_unbind) @@ -233,9 +235,13 @@ static void hdac_component_master_unbind(struct device *dev) WARN_ON(acomp->ops || acomp->dev); } -static const struct component_master_ops hdac_component_master_ops = { - .bind = hdac_component_master_bind, - .unbind = hdac_component_master_unbind, +static struct aggregate_driver hdac_aggregate_driver = { + .probe = hdac_component_master_bind, + .remove = hdac_component_master_unbind, + .driver = { + .name = "hdac_agg", + .owner = THIS_MODULE, + }, }; /** @@ -303,8 +309,7 @@ int snd_hdac_acomp_init(struct hdac_bus *bus, devres_add(dev, acomp); component_match_add_typed(dev, , match_master, bus); - ret = component_master_add_with_match(dev, _component_master_ops, - match); + ret = component_aggregate_register(dev, _aggregate_driver, match); if (ret < 0) goto out_err; @@ -344,7 +349,7 @@ int snd_hdac_acomp_exit(struct hdac_bus *bus) bus->display_power_active = 0; bus->display_power_status = 0; - component_master_del(dev, _component_master_ops); + component_aggregate_unregister(dev, _aggregate_driver); bus->audio_component = NULL; devres_destroy(dev, hdac_acomp_release, NULL, NULL); -- https://chromeos.dev
[PATCH v2 34/34] component: Remove all references to 'master'
Remove all references to 'master' in the code now that we've migrated all the users of the ops structure to the aggregate driver. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/base/component.c | 19 +++ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index 939862b25b10..75323d35773c 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -1,11 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* * Componentized device handling. - * - * This is work in progress. We gather up the component devices into a list, - * and bind them when instructed. At the moment, we're specific to the DRM - * subsystem, and only handles one master device, but this doesn't have to be - * the case. */ #include #include @@ -119,23 +114,23 @@ static int __init component_debug_init(void) core_initcall(component_debug_init); -static void component_master_debugfs_add(struct aggregate_device *m) +static void component_debugfs_add(struct aggregate_device *m) { debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m, _devices_fops); } -static void component_master_debugfs_del(struct aggregate_device *m) +static void component_debugfs_del(struct aggregate_device *m) { debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir)); } #else -static void component_master_debugfs_add(struct aggregate_device *m) +static void component_debugfs_add(struct aggregate_device *m) { } -static void component_master_debugfs_del(struct aggregate_device *m) +static void component_debugfs_del(struct aggregate_device *m) { } #endif @@ -343,7 +338,7 @@ EXPORT_SYMBOL(component_match_add_release); * @compare_typed: compare function to match against all typed components * @compare_data: opaque pointer passed to the @compare function * - * Adds a new component match to the list stored in @matchptr, which the @master + * Adds a new component match to the list stored in @matchptr, which the * aggregate driver needs to function. The list of component matches pointed to * by @matchptr must be initialized to NULL before adding the first match. This * only matches against components added with component_add_typed(). @@ -367,7 +362,7 @@ static void free_aggregate_device(struct aggregate_device *adev) struct component_match *match = adev->match; int i; - component_master_debugfs_del(adev); + component_debugfs_del(adev); if (match) { for (i = 0; i < match->num; i++) { @@ -548,7 +543,7 @@ static struct aggregate_device *aggregate_device_add(struct device *parent, return ERR_PTR(ret); } - component_master_debugfs_add(adev); + component_debugfs_add(adev); return adev; } -- https://chromeos.dev
[PATCH v2 28/34] power: supply: ab8500: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Sebastian Reichel Cc: Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/power/supply/ab8500_charger.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index 15eadaf46f14..52d4105e28f2 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -3312,8 +3312,9 @@ static const struct power_supply_desc ab8500_usb_chg_desc = { .get_property = ab8500_charger_usb_get_property, }; -static int ab8500_charger_bind(struct device *dev) +static int ab8500_charger_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct ab8500_charger *di = dev_get_drvdata(dev); int ch_stat; int ret; @@ -3354,8 +3355,9 @@ static int ab8500_charger_bind(struct device *dev) return 0; } -static void ab8500_charger_unbind(struct device *dev) +static void ab8500_charger_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct ab8500_charger *di = dev_get_drvdata(dev); int ret; @@ -3380,9 +3382,13 @@ static void ab8500_charger_unbind(struct device *dev) component_unbind_all(dev, di); } -static const struct component_master_ops ab8500_charger_comp_ops = { - .bind = ab8500_charger_bind, - .unbind = ab8500_charger_unbind, +static struct aggregate_driver ab8500_charger_aggregate_driver = { + .probe = ab8500_charger_bind, + .remove = ab8500_charger_unbind, + .driver = { + .name = "ab8500_charger_agg", + .owner = THIS_MODULE, + }, }; static struct platform_driver *const ab8500_charger_component_drivers[] = { @@ -3663,9 +3669,7 @@ static int ab8500_charger_probe(struct platform_device *pdev) } - ret = component_master_add_with_match(>dev, - _charger_comp_ops, - match); + ret = component_aggregate_register(>dev, _charger_aggregate_driver, match); if (ret) { dev_err(dev, "failed to add component master\n"); goto free_notifier; @@ -3688,7 +3692,7 @@ static int ab8500_charger_remove(struct platform_device *pdev) { struct ab8500_charger *di = platform_get_drvdata(pdev); - component_master_del(>dev, _charger_comp_ops); + component_aggregate_unregister(>dev, _charger_aggregate_driver); usb_unregister_notifier(di->usb_phy, >nb); usb_put_phy(di->usb_phy); -- https://chromeos.dev
[PATCH v2 25/34] drm/zte: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/zte/zx_drm_drv.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index 064056503ebb..b46f677ea51d 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -45,8 +45,9 @@ static const struct drm_driver zx_drm_driver = { .minor = 0, }; -static int zx_drm_bind(struct device *dev) +static int zx_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm; int ret; @@ -97,8 +98,9 @@ static int zx_drm_bind(struct device *dev) return ret; } -static void zx_drm_unbind(struct device *dev) +static void zx_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); drm_dev_unregister(drm); @@ -110,9 +112,13 @@ static void zx_drm_unbind(struct device *dev) drm_dev_put(drm); } -static const struct component_master_ops zx_drm_master_ops = { - .bind = zx_drm_bind, - .unbind = zx_drm_unbind, +static struct aggregate_driver zx_aggregate_driver = { + .probe = zx_drm_bind, + .remove = zx_drm_unbind, + .driver = { + .name = "zx_drm", + .owner = THIS_MODULE, + }, }; static int compare_of(struct device *dev, void *data) @@ -135,12 +141,12 @@ static int zx_drm_probe(struct platform_device *pdev) for_each_available_child_of_node(parent, child) component_match_add(dev, , compare_of, child); - return component_master_add_with_match(dev, _drm_master_ops, match); + return component_aggregate_register(dev, _aggregate_driver, match); } static int zx_drm_remove(struct platform_device *pdev) { - component_master_del(>dev, _drm_master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 29/34] fbdev: omap2: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Cc: Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/video/fbdev/omap2/omapfb/dss/dss.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss.c b/drivers/video/fbdev/omap2/omapfb/dss/dss.c index a6b1c1598040..f12663c39ceb 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.c @@ -1067,8 +1067,9 @@ static int dss_video_pll_probe(struct platform_device *pdev) } /* DSS HW IP initialisation */ -static int dss_bind(struct device *dev) +static int dss_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct platform_device *pdev = to_platform_device(dev); struct resource *dss_mem; u32 rev; @@ -1167,8 +1168,9 @@ static int dss_bind(struct device *dev) return r; } -static void dss_unbind(struct device *dev) +static void dss_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct platform_device *pdev = to_platform_device(dev); dss_initialized = false; @@ -1188,9 +1190,13 @@ static void dss_unbind(struct device *dev) dss_put_clocks(); } -static const struct component_master_ops dss_component_ops = { - .bind = dss_bind, - .unbind = dss_unbind, +static struct aggregate_driver dss_aggregate_driver = { + .probe = dss_bind, + .remove = dss_unbind, + .driver = { + .name = "dss_fbdev", + .owner = THIS_MODULE, + }, }; static int dss_component_compare(struct device *dev, void *data) @@ -1225,7 +1231,7 @@ static int dss_probe(struct platform_device *pdev) /* add all the child devices as components */ device_for_each_child(>dev, , dss_add_child_component); - r = component_master_add_with_match(>dev, _component_ops, match); + r = component_aggregate_register(>dev, _aggregate_driver, match); if (r) return r; @@ -1234,7 +1240,7 @@ static int dss_probe(struct platform_device *pdev) static int dss_remove(struct platform_device *pdev) { - component_master_del(>dev, _component_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 31/34] ASoC: codecs: wcd938x: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Mark Brown Cc: Jaroslav Kysela Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- sound/soc/codecs/wcd938x.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c index f0daf8defcf1..6033de7f57ef 100644 --- a/sound/soc/codecs/wcd938x.c +++ b/sound/soc/codecs/wcd938x.c @@ -4316,8 +4316,9 @@ static struct snd_soc_dai_driver wcd938x_dais[] = { }, }; -static int wcd938x_bind(struct device *dev) +static int wcd938x_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct wcd938x_priv *wcd938x = dev_get_drvdata(dev); int ret; @@ -4400,8 +4401,9 @@ static int wcd938x_bind(struct device *dev) } -static void wcd938x_unbind(struct device *dev) +static void wcd938x_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct wcd938x_priv *wcd938x = dev_get_drvdata(dev); device_link_remove(dev, wcd938x->txdev); @@ -4411,9 +4413,13 @@ static void wcd938x_unbind(struct device *dev) component_unbind_all(dev, wcd938x); } -static const struct component_master_ops wcd938x_comp_ops = { - .bind = wcd938x_bind, - .unbind = wcd938x_unbind, +static struct aggregate_driver wcd938x_aggregate_driver = { + .probe = wcd938x_bind, + .remove = wcd938x_unbind, + .driver = { + .name = "wcd938x_snd", + .owner = THIS_MODULE, + }, }; static int wcd938x_compare_of(struct device *dev, void *data) @@ -4482,7 +4488,7 @@ static int wcd938x_probe(struct platform_device *pdev) wcd938x_reset(wcd938x); - ret = component_master_add_with_match(dev, _comp_ops, match); + ret = component_aggregate_register(dev, _aggregate_driver, match); if (ret) return ret; @@ -4498,7 +4504,7 @@ static int wcd938x_probe(struct platform_device *pdev) static int wcd938x_remove(struct platform_device *pdev) { - component_master_del(>dev, _comp_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 32/34] component: Get rid of drm_of_component_probe()
There aren't any users anymore so drop it. Cc: Laurent Pinchart Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/drm_of.c | 87 +--- include/drm/drm_of.h | 12 -- 2 files changed, 20 insertions(+), 79 deletions(-) diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 58db65ad2770..78fe2b809872 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -99,18 +99,30 @@ void drm_of_component_match_add(struct device *master, } EXPORT_SYMBOL_GPL(drm_of_component_match_add); -static int _drm_of_component_probe(struct device *dev, - int (*compare_of)(struct device *, void *), - struct component_match **matchptr) +/** + * drm_of_aggregate_probe - Generic probe function for a component based aggregate host + * @dev: device containing the OF node + * @compare_of: compare function used for matching components + * @adrv: aggregate driver to be used + * + * Parse the platform device OF node and bind all the components associated + * with the aggregate device. Interface ports are added before the encoders in + * order to satisfy their .bind_component requirements + * See Documentation/devicetree/bindings/graph.txt for the bindings. + * + * Returns zero if successful, or one of the standard error codes if it fails. + */ +static int drm_of_aggregate_probe(struct device *dev, + int (*compare_of)(struct device *, void *), + struct aggregate_driver *adrv) { struct device_node *ep, *port, *remote; + struct component_match *match = NULL; int i; if (!dev->of_node) return -EINVAL; - *matchptr = NULL; - /* * Bind the crtc's ports first, so that drm_of_find_possible_crtcs() * called from encoder's .bind callbacks works as expected @@ -121,7 +133,7 @@ static int _drm_of_component_probe(struct device *dev, break; if (of_device_is_available(port->parent)) - drm_of_component_match_add(dev, matchptr, compare_of, + drm_of_component_match_add(dev, , compare_of, port); of_node_put(port); @@ -132,7 +144,7 @@ static int _drm_of_component_probe(struct device *dev, return -ENODEV; } - if (!*matchptr) { + if (!match) { dev_err(dev, "no available port\n"); return -ENODEV; } @@ -162,72 +174,13 @@ static int _drm_of_component_probe(struct device *dev, continue; } - drm_of_component_match_add(dev, matchptr, compare_of, + drm_of_component_match_add(dev, , compare_of, remote); of_node_put(remote); } of_node_put(port); } - return 0; -} - -/** - * drm_of_component_probe - Generic probe function for a component based master - * @dev: master device containing the OF node - * @compare_of: compare function used for matching components - * @m_ops: component master ops to be used - * - * Parse the platform device OF node and bind all the components associated - * with the master. Interface ports are added before the encoders in order to - * satisfy their .bind requirements - * See Documentation/devicetree/bindings/graph.txt for the bindings. - * - * Deprecated: Use drm_of_aggregate_probe() instead. - * - * Returns zero if successful, or one of the standard error codes if it fails. - */ -static int drm_of_component_probe(struct device *dev, - int (*compare_of)(struct device *, void *), - const struct component_master_ops *m_ops) -{ - - struct component_match *match; - int ret; - - ret = _drm_of_component_probe(dev, compare_of, ); - if (ret) - return ret; - - return component_master_add_with_match(dev, m_ops, match); -} -EXPORT_SYMBOL(drm_of_component_probe); - - -/** - * drm_of_aggregate_probe - Generic probe function for a component based aggregate host - * @dev: device containing the OF node - * @compare_of: compare function used for matching components - * @adrv: aggregate driver to be used - * - * Parse the platform device OF node and bind all the components associated - * with the aggregate device. Interface ports are added before the encoders in - * order to satisfy their .bind_component requirements - * See Documentation/devicetree/bindings/graph.txt for the bindings. - * - * Returns zero if successful, or one of the standard error codes if it fails. - */ -static int drm_of_aggregate_probe(struct device *dev, -
[PATCH v2 23/34] drm/tilcdc: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Jyri Sarha Cc: Tomi Valkeinen Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/tilcdc/tilcdc_drv.c | 28 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 6b03f89a98d4..d5c6567eec8d 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -531,13 +531,16 @@ static const struct dev_pm_ops tilcdc_pm_ops = { /* * Platform driver: */ -static int tilcdc_bind(struct device *dev) +static int tilcdc_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; + return tilcdc_init(_driver, dev); } -static void tilcdc_unbind(struct device *dev) +static void tilcdc_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *ddev = dev_get_drvdata(dev); /* Check if a subcomponent has already triggered the unloading. */ @@ -547,9 +550,13 @@ static void tilcdc_unbind(struct device *dev) tilcdc_fini(dev_get_drvdata(dev)); } -static const struct component_master_ops tilcdc_comp_ops = { - .bind = tilcdc_bind, - .unbind = tilcdc_unbind, +static struct aggregate_driver tilcdc_aggregate_driver = { + .probe = tilcdc_bind, + .remove = tilcdc_unbind, + .driver = { + .name = "tilcdc_drm", + .owner = THIS_MODULE, + }, }; static int tilcdc_pdev_probe(struct platform_device *pdev) @@ -566,12 +573,9 @@ static int tilcdc_pdev_probe(struct platform_device *pdev) ret = tilcdc_get_external_components(>dev, ); if (ret < 0) return ret; - else if (ret == 0) + if (ret == 0) return tilcdc_init(_driver, >dev); - else - return component_master_add_with_match(>dev, - _comp_ops, - match); + return component_aggregate_register(>dev, _aggregate_driver, match); } static int tilcdc_pdev_remove(struct platform_device *pdev) @@ -581,10 +585,10 @@ static int tilcdc_pdev_remove(struct platform_device *pdev) ret = tilcdc_get_external_components(>dev, NULL); if (ret < 0) return ret; - else if (ret == 0) + if (ret == 0) tilcdc_fini(platform_get_drvdata(pdev)); else - component_master_del(>dev, _comp_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 24/34] drm/vc4: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Emma Anholt Cc: Maxime Ripard Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/vc4/vc4_drv.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index f6c16c5aee68..bccbde7a2f59 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -214,8 +214,9 @@ static void vc4_match_add_drivers(struct device *dev, } } -static int vc4_drm_bind(struct device *dev) +static int vc4_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct platform_device *pdev = to_platform_device(dev); struct drm_device *drm; struct vc4_dev *vc4; @@ -286,8 +287,9 @@ static int vc4_drm_bind(struct device *dev) return ret; } -static void vc4_drm_unbind(struct device *dev) +static void vc4_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); drm_dev_unregister(drm); @@ -295,9 +297,13 @@ static void vc4_drm_unbind(struct device *dev) drm_atomic_helper_shutdown(drm); } -static const struct component_master_ops vc4_drm_ops = { - .bind = vc4_drm_bind, - .unbind = vc4_drm_unbind, +static struct aggregate_driver vc4_aggregate_driver = { + .probe = vc4_drm_bind, + .remove = vc4_drm_unbind, + .driver = { + .name = "vc4_drm", + .owner = THIS_MODULE, + }, }; /* @@ -328,12 +334,12 @@ static int vc4_platform_drm_probe(struct platform_device *pdev) vc4_match_add_drivers(dev, , component_drivers, ARRAY_SIZE(component_drivers)); - return component_master_add_with_match(dev, _drm_ops, match); + return component_aggregate_register(dev, _aggregate_driver, match); } static int vc4_platform_drm_remove(struct platform_device *pdev) { - component_master_del(>dev, _drm_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 26/34] iommu/mtk: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Yong Wu Cc: Joerg Roedel Cc: Will Deacon Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/iommu/mtk_iommu.c| 14 +- drivers/iommu/mtk_iommu.h| 6 -- drivers/iommu/mtk_iommu_v1.c | 14 +- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d837adfd1da5..8b303c388a9b 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -750,9 +750,13 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) return 0; } -static const struct component_master_ops mtk_iommu_com_ops = { - .bind = mtk_iommu_bind, - .unbind = mtk_iommu_unbind, +static struct aggregate_driver mtk_iommu_aggregate_driver = { + .probe = mtk_iommu_bind, + .remove = mtk_iommu_unbind, + .driver = { + .name = "mtk_iommu_agg", + .owner = THIS_MODULE, + }, }; static int mtk_iommu_probe(struct platform_device *pdev) @@ -893,7 +897,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) goto out_list_del; } - ret = component_master_add_with_match(dev, _iommu_com_ops, match); + ret = component_aggregate_register(dev, _iommu_aggregate_driver, match); if (ret) goto out_bus_set_null; return ret; @@ -926,7 +930,7 @@ static int mtk_iommu_remove(struct platform_device *pdev) device_link_remove(data->smicomm_dev, >dev); pm_runtime_disable(>dev); devm_free_irq(>dev, data->irq, data); - component_master_del(>dev, _iommu_com_ops); + component_aggregate_unregister(>dev, _iommu_aggregate_driver); return 0; } diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index f81fa8862ed0..064fd4f4eade 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -94,15 +94,17 @@ static inline void release_of(struct device *dev, void *data) of_node_put(data); } -static inline int mtk_iommu_bind(struct device *dev) +static inline int mtk_iommu_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct mtk_iommu_data *data = dev_get_drvdata(dev); return component_bind_all(dev, >larb_imu); } -static inline void mtk_iommu_unbind(struct device *dev) +static inline void mtk_iommu_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct mtk_iommu_data *data = dev_get_drvdata(dev); component_unbind_all(dev, >larb_imu); diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index be22fcf988ce..5fb29058a165 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -534,9 +534,13 @@ static const struct of_device_id mtk_iommu_of_ids[] = { {} }; -static const struct component_master_ops mtk_iommu_com_ops = { - .bind = mtk_iommu_bind, - .unbind = mtk_iommu_unbind, +static struct aggregate_driver mtk_iommu_aggregate_driver = { + .probe = mtk_iommu_bind, + .remove = mtk_iommu_unbind, + .driver = { + .name = "mtk_iommu_agg", + .owner = THIS_MODULE, + }, }; static int mtk_iommu_probe(struct platform_device *pdev) @@ -624,7 +628,7 @@ static int mtk_iommu_probe(struct platform_device *pdev) goto out_dev_unreg; } - ret = component_master_add_with_match(dev, _iommu_com_ops, match); + ret = component_aggregate_register(dev, _iommu_aggregate_driver, match); if (ret) goto out_bus_set_null; return ret; @@ -650,7 +654,7 @@ static int mtk_iommu_remove(struct platform_device *pdev) clk_disable_unprepare(data->bclk); devm_free_irq(>dev, data->irq, data); - component_master_del(>dev, _iommu_com_ops); + component_aggregate_unregister(>dev, _iommu_aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 33/34] component: Remove component_master_ops and friends
The struct is unused now so drop it along with the functions that use it. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/base/component.c | 109 +++--- drivers/gpu/drm/drm_drv.c | 2 +- include/linux/component.h | 45 3 files changed, 8 insertions(+), 148 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index a6dd33d0ddeb..939862b25b10 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -140,18 +140,12 @@ static void component_master_debugfs_del(struct aggregate_device *m) #endif -struct aggregate_bus_find_data { - const struct component_master_ops *ops; - struct device *parent; -}; - static int aggregate_bus_find_match(struct device *dev, const void *_data) { struct aggregate_device *adev = to_aggregate_device(dev); - const struct aggregate_bus_find_data *data = _data; + const struct device *parent = _data; - if (adev->parent == data->parent && - (!data->ops || adev->ops == data->ops)) + if (adev->parent == parent) return 1; return 0; @@ -496,16 +490,11 @@ static struct bus_type aggregate_bus_type = { }; /* Callers take ownership of return value, should call put_device() */ -static struct aggregate_device *__aggregate_find(struct device *parent, - const struct component_master_ops *ops) +static struct aggregate_device *__aggregate_find(struct device *parent) { struct device *dev; - struct aggregate_bus_find_data data = { - .ops = ops, - .parent = parent, - }; - dev = bus_find_device(_bus_type, NULL, , + dev = bus_find_device(_bus_type, NULL, parent, aggregate_bus_find_match); return dev ? to_aggregate_device(dev) : NULL; @@ -523,7 +512,7 @@ static void aggregate_driver_unregister(struct aggregate_driver *adrv) } static struct aggregate_device *aggregate_device_add(struct device *parent, - const struct component_master_ops *ops, struct aggregate_driver *adrv, + struct aggregate_driver *adrv, struct component_match *match) { struct aggregate_device *adev; @@ -564,54 +553,6 @@ static struct aggregate_device *aggregate_device_add(struct device *parent, return adev; } -/** - * component_master_add_with_match - register an aggregate driver - * @parent: parent device of the aggregate driver - * @ops: callbacks for the aggregate driver - * @match: component match list for the aggregate driver - * - * Registers a new aggregate driver consisting of the components added to @match - * by calling one of the component_match_add() functions. Once all components in - * @match are available, it will be assembled by calling - * _master_ops.bind from @ops. Must be unregistered by calling - * component_master_del(). - * - * Deprecated: Use component_aggregate_register() instead. - */ -int component_master_add_with_match(struct device *parent, - const struct component_master_ops *ops, - struct component_match *match) -{ - struct aggregate_driver *adrv; - struct aggregate_device *adev; - int ret = 0; - - adrv = kzalloc(sizeof(*adrv), GFP_KERNEL); - if (!adrv) - return -ENOMEM; - - adev = aggregate_device_add(parent, ops, adrv, match); - if (IS_ERR(adev)) { - ret = PTR_ERR(adev); - goto err; - } - - adrv->probe = component_probe_bind; - adrv->remove = component_remove_unbind; - adrv->driver.owner = THIS_MODULE; - adrv->driver.name = dev_name(>dev); - - ret = aggregate_driver_register(adrv); - if (!ret) - return 0; - - put_device(>dev); -err: - kfree(adrv); - return ret; -} -EXPORT_SYMBOL_GPL(component_master_add_with_match); - /** * component_aggregate_register - register an aggregate driver * @parent: parent device of the aggregate driver @@ -640,42 +581,6 @@ int component_aggregate_register(struct device *parent, } EXPORT_SYMBOL_GPL(component_aggregate_register); -/** - * component_master_del - unregister an aggregate driver - * @parent: parent device of the aggregate driver - * @ops: callbacks for the aggregate driver - * - * Unregisters an aggregate driver registered with - * component_master_add_with_match(). If necessary the aggregate driver is first - * disassembled by calling _master_ops.unbind from @ops. - * - * Deprecated: Use component_aggregate_unregister() instead. - */ -void component_master_del(struct device *parent, - const struct component_master_ops *ops) -{ - struct aggregate_device *adev; - struct aggregate_driver *adrv; - struct device_driver *drv; - - mutex_lock(_mutex); - adev = __aggregate_find(parent, ops); - mutex_unlock(_mutex); - - if
[PATCH v2 18/34] drm/meson: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Neil Armstrong Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/meson/meson_drv.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index bc0d60df04ae..109fb9d057e3 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -357,13 +357,16 @@ static int meson_drv_bind_master(struct device *dev, bool has_components) return ret; } -static int meson_drv_bind(struct device *dev) +static int meson_drv_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; + return meson_drv_bind_master(dev, true); } -static void meson_drv_unbind(struct device *dev) +static void meson_drv_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct meson_drm *priv = dev_get_drvdata(dev); struct drm_device *drm = priv->drm; @@ -387,9 +390,13 @@ static void meson_drv_unbind(struct device *dev) } } -static const struct component_master_ops meson_drv_master_ops = { - .bind = meson_drv_bind, - .unbind = meson_drv_unbind, +static struct aggregate_driver meson_aggregate_drv = { + .probe = meson_drv_bind, + .remove = meson_drv_unbind, + .driver = { + .name = "meson_drm", + .owner = THIS_MODULE, + }, }; static int __maybe_unused meson_drv_pm_suspend(struct device *dev) @@ -503,9 +510,7 @@ static int meson_drv_probe(struct platform_device *pdev) if (count) { dev_info(>dev, "Queued %d outputs on vpu\n", count); - return component_master_add_with_match(>dev, - _drv_master_ops, - match); + return component_aggregate_register(>dev, _aggregate_drv, match); } /* If no output endpoints were available, simply bail out */ -- https://chromeos.dev
[PATCH v2 27/34] mei: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Tomas Winkler Cc: Arnd Bergmann Cc: Greg Kroah-Hartman Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/misc/mei/hdcp/mei_hdcp.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c index ec2a4fce8581..79dcc02277d2 100644 --- a/drivers/misc/mei/hdcp/mei_hdcp.c +++ b/drivers/misc/mei/hdcp/mei_hdcp.c @@ -732,8 +732,9 @@ static const struct i915_hdcp_component_ops mei_hdcp_ops = { .close_hdcp_session = mei_hdcp_close_session, }; -static int mei_component_master_bind(struct device *dev) +static int mei_component_master_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct mei_cl_device *cldev = to_mei_cl_device(dev); struct i915_hdcp_comp_master *comp_master = mei_cldev_get_drvdata(cldev); @@ -749,8 +750,9 @@ static int mei_component_master_bind(struct device *dev) return 0; } -static void mei_component_master_unbind(struct device *dev) +static void mei_component_master_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct mei_cl_device *cldev = to_mei_cl_device(dev); struct i915_hdcp_comp_master *comp_master = mei_cldev_get_drvdata(cldev); @@ -759,9 +761,13 @@ static void mei_component_master_unbind(struct device *dev) component_unbind_all(dev, comp_master); } -static const struct component_master_ops mei_component_master_ops = { - .bind = mei_component_master_bind, - .unbind = mei_component_master_unbind, +static struct aggregate_driver mei_aggregate_driver = { + .probe = mei_component_master_bind, + .remove = mei_component_master_unbind, + .driver = { + .name = "mei_agg", + .owner = THIS_MODULE, + }, }; /** @@ -826,9 +832,7 @@ static int mei_hdcp_probe(struct mei_cl_device *cldev, } mei_cldev_set_drvdata(cldev, comp_master); - ret = component_master_add_with_match(>dev, - _component_master_ops, - master_match); + ret = component_aggregate_register(>dev, _aggregate_driver, master_match); if (ret < 0) { dev_err(>dev, "Master comp add failed %d\n", ret); goto err_exit; @@ -850,7 +854,7 @@ static void mei_hdcp_remove(struct mei_cl_device *cldev) mei_cldev_get_drvdata(cldev); int ret; - component_master_del(>dev, _component_master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); kfree(comp_master); mei_cldev_set_drvdata(cldev, NULL); -- https://chromeos.dev
[PATCH v2 15/34] drm/ingenic: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. TODO: Move the helpers to PM in aggregate driver hooks. Cc: Paul Cercueil Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 24 +-- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a5df1c8d34cd..058b7bfe5610 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -1150,8 +1150,10 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) return ret; } -static int ingenic_drm_bind_with_components(struct device *dev) +static int ingenic_drm_bind_with_components(struct aggregate_device *adev) { + struct device *dev = adev->parent; + return ingenic_drm_bind(dev, true); } @@ -1174,9 +1176,19 @@ static void ingenic_drm_unbind(struct device *dev) drm_atomic_helper_shutdown(>drm); } -static const struct component_master_ops ingenic_master_ops = { - .bind = ingenic_drm_bind_with_components, - .unbind = ingenic_drm_unbind, +static void ingenic_aggregate_remove(struct aggregate_device *adev) +{ + struct device *dev = adev->parent; + ingenic_drm_unbind(dev); +} + +static struct aggregate_driver ingenic_aggregate_driver = { + .probe = ingenic_drm_bind_with_components, + .remove = ingenic_aggregate_remove, + .driver = { + .name = "ingenic_drm", + .owner = THIS_MODULE, + }, }; static int ingenic_drm_probe(struct platform_device *pdev) @@ -1196,7 +1208,7 @@ static int ingenic_drm_probe(struct platform_device *pdev) drm_of_component_match_add(dev, , compare_of, np); of_node_put(np); - return component_master_add_with_match(dev, _master_ops, match); + return component_aggregate_register(dev, _aggregate_driver, match); } static int ingenic_drm_remove(struct platform_device *pdev) @@ -1206,7 +1218,7 @@ static int ingenic_drm_remove(struct platform_device *pdev) if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) ingenic_drm_unbind(dev); else - component_master_del(dev, _master_ops); + component_aggregate_unregister(dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 17/34] drm/mediatek: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Chun-Kuang Hu Cc: Philipp Zabel Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index aec39724ebeb..a3f27b8c9769 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -348,8 +348,9 @@ static int compare_of(struct device *dev, void *data) return dev->of_node == data; } -static int mtk_drm_bind(struct device *dev) +static int mtk_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct mtk_drm_private *private = dev_get_drvdata(dev); struct drm_device *drm; int ret; @@ -380,8 +381,9 @@ static int mtk_drm_bind(struct device *dev) return ret; } -static void mtk_drm_unbind(struct device *dev) +static void mtk_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct mtk_drm_private *private = dev_get_drvdata(dev); drm_dev_unregister(private->drm); @@ -391,9 +393,13 @@ static void mtk_drm_unbind(struct device *dev) private->drm = NULL; } -static const struct component_master_ops mtk_drm_ops = { - .bind = mtk_drm_bind, - .unbind = mtk_drm_unbind, +static struct aggregate_driver mtk_drm_aggregate_driver = { + .probe = mtk_drm_bind, + .remove = mtk_drm_unbind, + .driver = { + .name = "mtk_drm", + .owner = THIS_MODULE, + }, }; static const struct of_device_id mtk_ddp_comp_dt_ids[] = { @@ -593,7 +599,7 @@ static int mtk_drm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, private); - ret = component_master_add_with_match(dev, _drm_ops, match); + ret = component_aggregate_register(dev, _drm_aggregate_driver, match); if (ret) goto err_pm; @@ -616,7 +622,7 @@ static int mtk_drm_remove(struct platform_device *pdev) struct mtk_drm_private *private = platform_get_drvdata(pdev); int i; - component_master_del(>dev, _drm_ops); + component_aggregate_unregister(>dev, _drm_aggregate_driver); pm_runtime_disable(>dev); of_node_put(private->mutex_node); for (i = 0; i < DDP_COMPONENT_ID_MAX; i++) -- https://chromeos.dev
[PATCH v2 16/34] drm/mcde: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/mcde/mcde_drv.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index e60566a5739c..84fcfe77540e 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -215,8 +215,9 @@ static const struct drm_driver mcde_drm_driver = { DRM_GEM_CMA_DRIVER_OPS, }; -static int mcde_drm_bind(struct device *dev) +static int mcde_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); int ret; @@ -247,8 +248,9 @@ static int mcde_drm_bind(struct device *dev) return ret; } -static void mcde_drm_unbind(struct device *dev) +static void mcde_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); drm_dev_unregister(drm); @@ -256,9 +258,13 @@ static void mcde_drm_unbind(struct device *dev) component_unbind_all(drm->dev, drm); } -static const struct component_master_ops mcde_drm_comp_ops = { - .bind = mcde_drm_bind, - .unbind = mcde_drm_unbind, +static struct aggregate_driver mcde_drm_comp_driver = { + .probe = mcde_drm_bind, + .remove = mcde_drm_unbind, + .driver = { + .name = "mcde_drm", + .owner = THIS_MODULE, + }, }; static struct platform_driver *const mcde_component_drivers[] = { @@ -421,7 +427,7 @@ static int mcde_probe(struct platform_device *pdev) * Perform an invasive reset of the MCDE and all blocks by * cutting the power to the subsystem, then bring it back up * later when we enable the display as a result of -* component_master_add_with_match(). +* component_aggregate_register(). */ ret = regulator_disable(mcde->epod); if (ret) { @@ -431,8 +437,7 @@ static int mcde_probe(struct platform_device *pdev) /* Wait 50 ms so we are sure we cut the power */ usleep_range(5, 7); - ret = component_master_add_with_match(>dev, _drm_comp_ops, - match); + ret = component_aggregate_register(>dev, _drm_comp_driver, match); if (ret) { dev_err(dev, "failed to add component master\n"); /* @@ -461,7 +466,7 @@ static int mcde_remove(struct platform_device *pdev) struct drm_device *drm = platform_get_drvdata(pdev); struct mcde *mcde = to_mcde(drm); - component_master_del(>dev, _drm_comp_ops); + component_aggregate_unregister(>dev, _drm_comp_driver); clk_disable_unprepare(mcde->mcde_clk); regulator_disable(mcde->vana); regulator_disable(mcde->epod); -- https://chromeos.dev
[PATCH v2 21/34] drm/sti: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Benjamin Gaignard Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/sti/sti_drv.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index c7efb43b83ee..b277cc679154 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -182,8 +182,9 @@ static void sti_cleanup(struct drm_device *ddev) ddev->dev_private = NULL; } -static int sti_bind(struct device *dev) +static int sti_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *ddev; int ret; @@ -216,8 +217,9 @@ static int sti_bind(struct device *dev) return ret; } -static void sti_unbind(struct device *dev) +static void sti_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *ddev = dev_get_drvdata(dev); drm_dev_unregister(ddev); @@ -225,9 +227,13 @@ static void sti_unbind(struct device *dev) drm_dev_put(ddev); } -static const struct component_master_ops sti_ops = { - .bind = sti_bind, - .unbind = sti_unbind, +static struct aggregate_driver sti_aggregate_driver = { + .probe = sti_bind, + .remove = sti_unbind, + .driver = { + .name = "sti_drm", + .owner = THIS_MODULE, + }, }; static int sti_platform_probe(struct platform_device *pdev) @@ -249,12 +255,12 @@ static int sti_platform_probe(struct platform_device *pdev) child_np = of_get_next_available_child(node, child_np); } - return component_master_add_with_match(dev, _ops, match); + return component_aggregate_register(dev, _aggregate_driver, match); } static int sti_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 20/34] drm/rockchip: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Sandy Huang Cc: "Heiko Stübner" Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/rockchip/rockchip_drm_drv.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index bfba9793d238..cc63222c3ad0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -109,8 +109,9 @@ static void rockchip_iommu_cleanup(struct drm_device *drm_dev) iommu_domain_free(private->domain); } -static int rockchip_drm_bind(struct device *dev) +static int rockchip_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm_dev; struct rockchip_drm_private *private; int ret; @@ -186,8 +187,9 @@ static int rockchip_drm_bind(struct device *dev) return ret; } -static void rockchip_drm_unbind(struct device *dev) +static void rockchip_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm_dev = dev_get_drvdata(dev); drm_dev_unregister(drm_dev); @@ -342,9 +344,13 @@ static struct component_match *rockchip_drm_match_add(struct device *dev) return match ?: ERR_PTR(-ENODEV); } -static const struct component_master_ops rockchip_drm_ops = { - .bind = rockchip_drm_bind, - .unbind = rockchip_drm_unbind, +static struct aggregate_driver rockchip_aggregate_driver = { + .probe = rockchip_drm_bind, + .remove = rockchip_drm_unbind, + .driver = { + .name = "rockchip_drm", + .owner = THIS_MODULE, + }, }; static int rockchip_drm_platform_of_probe(struct device *dev) @@ -415,7 +421,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) if (IS_ERR(match)) return PTR_ERR(match); - ret = component_master_add_with_match(dev, _drm_ops, match); + ret = component_aggregate_register(dev, _aggregate_driver, match); if (ret < 0) { rockchip_drm_match_remove(dev); return ret; @@ -426,7 +432,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) static int rockchip_drm_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _drm_ops); + component_aggregate_unregister(>dev, _aggregate_driver); rockchip_drm_match_remove(>dev); -- https://chromeos.dev
[PATCH v2 22/34] drm/sun4i: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Maxime Ripard Cc: Chen-Yu Tsai Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/sun4i/sun4i_drv.c | 26 +++--- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 54dd562e294c..700f5e32eaf7 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -56,8 +56,9 @@ static const struct drm_driver sun4i_drv_driver = { DRM_GEM_CMA_DRIVER_OPS_VMAP_WITH_DUMB_CREATE(drm_sun4i_gem_dumb_create), }; -static int sun4i_drv_bind(struct device *dev) +static int sun4i_drv_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm; struct sun4i_drv *drv; int ret; @@ -125,8 +126,9 @@ static int sun4i_drv_bind(struct device *dev) return ret; } -static void sun4i_drv_unbind(struct device *dev) +static void sun4i_drv_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); drm_dev_unregister(drm); @@ -140,9 +142,13 @@ static void sun4i_drv_unbind(struct device *dev) drm_dev_put(drm); } -static const struct component_master_ops sun4i_drv_master_ops = { - .bind = sun4i_drv_bind, - .unbind = sun4i_drv_unbind, +static struct aggregate_driver sun4i_aggregate_driver = { + .probe = sun4i_drv_bind, + .remove = sun4i_drv_unbind, + .driver = { + .name = "sun4i_drm", + .owner = THIS_MODULE, + }, }; static bool sun4i_drv_node_is_connector(struct device_node *node) @@ -398,16 +404,14 @@ static int sun4i_drv_probe(struct platform_device *pdev) } if (count) - return component_master_add_with_match(>dev, - _drv_master_ops, - match); - else - return 0; + return component_aggregate_register(>dev, _aggregate_driver, match); + + return 0; } static int sun4i_drv_remove(struct platform_device *pdev) { - component_master_del(>dev, _drv_master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 19/34] drm/omap: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Tomi Valkeinen Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/omapdrm/dss/dss.c | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index d6a5862b4dbf..6a6ae2786d7a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1304,8 +1304,9 @@ static const struct soc_device_attribute dss_soc_devices[] = { { /* sentinel */ } }; -static int dss_bind(struct device *dev) +static int dss_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct dss_device *dss = dev_get_drvdata(dev); struct platform_device *drm_pdev; struct dss_pdata pdata; @@ -1339,9 +1340,13 @@ static void dss_unbind(struct device *dev) component_unbind_all(dev, NULL); } -static const struct component_master_ops dss_component_ops = { - .bind = dss_bind, - .unbind = dss_unbind, +static struct aggregate_driver dss_aggregate_driver = { + .probe = dss_bind, + .remove = dss_unbind, + .driver = { + .name = "dss_drm", + .owner = THIS_MODULE, + }, }; static int dss_component_compare(struct device *dev, void *data) @@ -1504,7 +1509,7 @@ static int dss_probe(struct platform_device *pdev) cmatch.match = device_for_each_child(>dev, , dss_add_child_component); - r = component_master_add_with_match(>dev, _component_ops, match); + r = component_aggregate_register(>dev, _aggregate_driver, match); if (r) goto err_of_depopulate; @@ -1543,7 +1548,7 @@ static int dss_remove(struct platform_device *pdev) of_platform_depopulate(>dev); - component_master_del(>dev, _component_ops); + component_aggregate_unregister(>dev, _aggregate_driver); dss_debugfs_remove_file(dss->debugfs.clk); dss_debugfs_remove_file(dss->debugfs.dss); -- https://chromeos.dev
[PATCH v2 14/34] drm/imx: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Philipp Zabel Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/imx/imx-drm-core.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 9558e9e1b431..dbf5cca5201d 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -198,8 +198,9 @@ static int compare_of(struct device *dev, void *data) return dev->of_node == np; } -static int imx_drm_bind(struct device *dev) +static int imx_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm; int ret; @@ -266,8 +267,9 @@ static int imx_drm_bind(struct device *dev) return ret; } -static void imx_drm_unbind(struct device *dev) +static void imx_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); drm_dev_unregister(drm); @@ -281,14 +283,18 @@ static void imx_drm_unbind(struct device *dev) dev_set_drvdata(dev, NULL); } -static const struct component_master_ops imx_drm_ops = { - .bind = imx_drm_bind, - .unbind = imx_drm_unbind, +static struct aggregate_driver imx_drm_aggregate_driver = { + .probe = imx_drm_bind, + .remove = imx_drm_unbind, + .driver = { + .name = "imx_drm", + .owner = THIS_MODULE, + }, }; static int imx_drm_platform_probe(struct platform_device *pdev) { - int ret = drm_of_component_probe(>dev, compare_of, _drm_ops); + int ret = drm_of_aggregate_probe(>dev, compare_of, _drm_aggregate_driver); if (!ret) ret = dma_set_coherent_mask(>dev, DMA_BIT_MASK(32)); @@ -298,7 +304,7 @@ static int imx_drm_platform_probe(struct platform_device *pdev) static int imx_drm_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _drm_ops); + component_aggregate_unregister(>dev, _drm_aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 10/34] drm/armada: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Russell King Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/armada/armada_drv.c | 23 ++- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 8e3e98f13db4..b3559363ea43 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -60,8 +60,9 @@ static const struct drm_mode_config_funcs armada_drm_mode_config_funcs = { .atomic_commit = drm_atomic_helper_commit, }; -static int armada_drm_bind(struct device *dev) +static int armada_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct armada_private *priv; struct resource *mem = NULL; int ret, n; @@ -159,8 +160,9 @@ static int armada_drm_bind(struct device *dev) return ret; } -static void armada_drm_unbind(struct device *dev) +static void armada_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); struct armada_private *priv = drm_to_armada_dev(drm); @@ -202,9 +204,13 @@ static void armada_add_endpoints(struct device *dev, } } -static const struct component_master_ops armada_master_ops = { - .bind = armada_drm_bind, - .unbind = armada_drm_unbind, +static struct aggregate_driver armada_aggregate_driver = { + .probe = armada_drm_bind, + .remove = armada_drm_unbind, + .driver = { + .name = "armada_drm", + .owner = THIS_MODULE, + }, }; static int armada_drm_probe(struct platform_device *pdev) @@ -213,7 +219,7 @@ static int armada_drm_probe(struct platform_device *pdev) struct device *dev = >dev; int ret; - ret = drm_of_component_probe(dev, compare_dev_name, _master_ops); + ret = drm_of_aggregate_probe(dev, compare_dev_name, _aggregate_driver); if (ret != -EINVAL) return ret; @@ -240,13 +246,12 @@ static int armada_drm_probe(struct platform_device *pdev) } } - return component_master_add_with_match(>dev, _master_ops, - match); + return component_aggregate_register(>dev, _aggregate_driver, match); } static int armada_drm_remove(struct platform_device *pdev) { - component_master_del(>dev, _master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 13/34] drm/exynos: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Inki Dae Cc: Joonyoung Shim Cc: Seung-Woo Kim Cc: Kyungmin Park Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/exynos/exynos_drm_drv.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index d8f1cf4d6b69..dcb52ec2bd35 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -253,8 +253,9 @@ static struct component_match *exynos_drm_match_add(struct device *dev) return match ?: ERR_PTR(-ENODEV); } -static int exynos_drm_bind(struct device *dev) +static int exynos_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct exynos_drm_private *private; struct drm_encoder *encoder; struct drm_device *drm; @@ -330,8 +331,9 @@ static int exynos_drm_bind(struct device *dev) return ret; } -static void exynos_drm_unbind(struct device *dev) +static void exynos_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); drm_dev_unregister(drm); @@ -350,9 +352,13 @@ static void exynos_drm_unbind(struct device *dev) drm_dev_put(drm); } -static const struct component_master_ops exynos_drm_ops = { - .bind = exynos_drm_bind, - .unbind = exynos_drm_unbind, +static struct aggregate_driver exynos_drm_aggregate_driver = { + .probe = exynos_drm_bind, + .remove = exynos_drm_unbind, + .driver = { + .name = "exynos_drm", + .owner = THIS_MODULE, + }, }; static int exynos_drm_platform_probe(struct platform_device *pdev) @@ -365,13 +371,12 @@ static int exynos_drm_platform_probe(struct platform_device *pdev) if (IS_ERR(match)) return PTR_ERR(match); - return component_master_add_with_match(>dev, _drm_ops, - match); + return component_aggregate_register(>dev, _drm_aggregate_driver, match); } static int exynos_drm_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _drm_ops); + component_aggregate_unregister(>dev, _drm_aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 12/34] drm/kirin: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Xinliang Liu Cc: Tian Tao Cc: John Stultz Cc: Xinwei Kong Cc: Chen Feng Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 20 --- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 98ae9a48f3fe..00d47c784cbb 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -217,8 +217,9 @@ static int kirin_drm_kms_cleanup(struct drm_device *dev) return 0; } -static int kirin_drm_bind(struct device *dev) +static int kirin_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct kirin_drm_data *driver_data; struct drm_device *drm_dev; int ret; @@ -253,8 +254,9 @@ static int kirin_drm_bind(struct device *dev) return ret; } -static void kirin_drm_unbind(struct device *dev) +static void kirin_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm_dev = dev_get_drvdata(dev); drm_dev_unregister(drm_dev); @@ -262,9 +264,13 @@ static void kirin_drm_unbind(struct device *dev) drm_dev_put(drm_dev); } -static const struct component_master_ops kirin_drm_ops = { - .bind = kirin_drm_bind, - .unbind = kirin_drm_unbind, +static struct aggregate_driver kirin_drm_aggregate_driver = { + .probe = kirin_drm_bind, + .remove = kirin_drm_unbind, + .driver = { + .name = "kirin_drm", + .owner = THIS_MODULE, + }, }; static int kirin_drm_platform_probe(struct platform_device *pdev) @@ -281,12 +287,12 @@ static int kirin_drm_platform_probe(struct platform_device *pdev) drm_of_component_match_add(dev, , compare_of, remote); of_node_put(remote); - return component_master_add_with_match(dev, _drm_ops, match); + return component_aggregate_register(dev, _drm_aggregate_driver, match); } static int kirin_drm_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _drm_ops); + component_aggregate_unregister(>dev, _drm_aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 11/34] drm/etnaviv: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Lucas Stach Cc: Russell King Cc: Christian Gmeiner Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 +--- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 7dcc6392792d..95d1e518ff13 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -494,8 +494,9 @@ static const struct drm_driver etnaviv_drm_driver = { /* * Platform driver: */ -static int etnaviv_bind(struct device *dev) +static int etnaviv_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct etnaviv_drm_private *priv; struct drm_device *drm; int ret; @@ -552,8 +553,9 @@ static int etnaviv_bind(struct device *dev) return ret; } -static void etnaviv_unbind(struct device *dev) +static void etnaviv_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); struct etnaviv_drm_private *priv = drm->dev_private; @@ -569,9 +571,13 @@ static void etnaviv_unbind(struct device *dev) drm_dev_put(drm); } -static const struct component_master_ops etnaviv_master_ops = { - .bind = etnaviv_bind, - .unbind = etnaviv_unbind, +static struct aggregate_driver etnaviv_aggregate_driver = { + .probe = etnaviv_bind, + .remove = etnaviv_unbind, + .driver = { + .name = "etnaviv_drm", + .owner = THIS_MODULE, + }, }; static int compare_of(struct device *dev, void *data) @@ -609,12 +615,12 @@ static int etnaviv_pdev_probe(struct platform_device *pdev) component_match_add(dev, , compare_str, names[i]); } - return component_master_add_with_match(dev, _master_ops, match); + return component_aggregate_register(dev, _aggregate_driver, match); } static int etnaviv_pdev_remove(struct platform_device *pdev) { - component_master_del(>dev, _master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 07/34] drm/komeda: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: James Qian Wang (Arm Technology China) Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- .../gpu/drm/arm/display/komeda/komeda_drv.c | 20 --- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index e7933930a657..0463386a6ed2 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -25,8 +25,9 @@ struct komeda_dev *dev_to_mdev(struct device *dev) return mdrv ? mdrv->mdev : NULL; } -static void komeda_unbind(struct device *dev) +static void komeda_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct komeda_drv *mdrv = dev_get_drvdata(dev); if (!mdrv) @@ -45,8 +46,9 @@ static void komeda_unbind(struct device *dev) devm_kfree(dev, mdrv); } -static int komeda_bind(struct device *dev) +static int komeda_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct komeda_drv *mdrv; int err; @@ -87,9 +89,13 @@ static int komeda_bind(struct device *dev) return err; } -static const struct component_master_ops komeda_master_ops = { - .bind = komeda_bind, - .unbind = komeda_unbind, +static struct aggregate_driver komeda_aggregate_driver = { + .probe = komeda_bind, + .remove = komeda_unbind, + .driver = { + .name = "komeda_drm", + .owner = THIS_MODULE, + }, }; static int compare_of(struct device *dev, void *data) @@ -129,12 +135,12 @@ static int komeda_platform_probe(struct platform_device *pdev) komeda_add_slave(dev, , child, KOMEDA_OF_PORT_OUTPUT, 1); } - return component_master_add_with_match(dev, _master_ops, match); + return component_aggregate_register(dev, _aggregate_driver, match); } static int komeda_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 08/34] drm/arm/hdlcd: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. Cc: Liviu Dudau Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/arm/hdlcd_drv.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 479c2422a2e0..8f3e5924042a 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -270,8 +270,9 @@ static const struct drm_driver hdlcd_driver = { .minor = 0, }; -static int hdlcd_drm_bind(struct device *dev) +static int hdlcd_drm_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm; struct hdlcd_drm_private *hdlcd; int ret; @@ -344,8 +345,9 @@ static int hdlcd_drm_bind(struct device *dev) return ret; } -static void hdlcd_drm_unbind(struct device *dev) +static void hdlcd_drm_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); struct hdlcd_drm_private *hdlcd = drm->dev_private; @@ -367,9 +369,13 @@ static void hdlcd_drm_unbind(struct device *dev) drm_dev_put(drm); } -static const struct component_master_ops hdlcd_master_ops = { - .bind = hdlcd_drm_bind, - .unbind = hdlcd_drm_unbind, +static struct aggregate_driver hdlcd_aggregate_driver = { + .probe = hdlcd_drm_bind, + .remove = hdlcd_drm_unbind, + .driver = { + .name = "hdlcd_drm", + .owner = THIS_MODULE, + }, }; static int compare_dev(struct device *dev, void *data) @@ -390,13 +396,12 @@ static int hdlcd_probe(struct platform_device *pdev) drm_of_component_match_add(>dev, , compare_dev, port); of_node_put(port); - return component_master_add_with_match(>dev, _master_ops, - match); + return component_aggregate_register(>dev, _aggregate_driver, match); } static int hdlcd_remove(struct platform_device *pdev) { - component_master_del(>dev, _master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 09/34] drm/malidp: Migrate to aggregate driver
Use an aggregate driver instead of component ops so that we can get proper driver probe ordering of the aggregate device with respect to all the component devices that make up the aggregate device. TODO: This can be updated to move the drm helper logic into the aggregate driver shutdown op. Cc: Laurent Pinchart Cc: Liviu Dudau Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/arm/malidp_drv.c | 21 + 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 78d15b04b105..e6ee4d1e3bb8 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -702,8 +702,9 @@ static int malidp_runtime_pm_resume(struct device *dev) return 0; } -static int malidp_bind(struct device *dev) +static int malidp_bind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct resource *res; struct drm_device *drm; struct malidp_drm *malidp; @@ -894,8 +895,9 @@ static int malidp_bind(struct device *dev) return ret; } -static void malidp_unbind(struct device *dev) +static void malidp_unbind(struct aggregate_device *adev) { + struct device *dev = adev->parent; struct drm_device *drm = dev_get_drvdata(dev); struct malidp_drm *malidp = drm->dev_private; struct malidp_hw_device *hwdev = malidp->dev; @@ -921,9 +923,13 @@ static void malidp_unbind(struct device *dev) of_reserved_mem_device_release(dev); } -static const struct component_master_ops malidp_master_ops = { - .bind = malidp_bind, - .unbind = malidp_unbind, +static struct aggregate_driver malidp_aggregate_driver = { + .probe = malidp_bind, + .remove = malidp_unbind, + .driver = { + .name = "malidp_drm", + .owner = THIS_MODULE, + }, }; static int malidp_compare_dev(struct device *dev, void *data) @@ -949,13 +955,12 @@ static int malidp_platform_probe(struct platform_device *pdev) drm_of_component_match_add(>dev, , malidp_compare_dev, port); of_node_put(port); - return component_master_add_with_match(>dev, _master_ops, - match); + return component_aggregate_register(>dev, _aggregate_driver, match); } static int malidp_platform_remove(struct platform_device *pdev) { - component_master_del(>dev, _master_ops); + component_aggregate_unregister(>dev, _aggregate_driver); return 0; } -- https://chromeos.dev
[PATCH v2 03/34] component: Move struct aggregate_device out to header file
This allows aggregate driver writers to use the device passed to their probe/remove/shutdown functions properly instead of treating it as an opaque pointer. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/base/component.c | 15 --- include/linux/component.h | 19 --- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index d99e99cabb99..f49b48695c8f 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -62,21 +62,6 @@ struct component_match { struct component_match_array *compare; }; -struct aggregate_device { - const struct component_master_ops *ops; - struct device *parent; - struct device dev; - struct component_match *match; - struct aggregate_driver *adrv; - - int id; -}; - -static inline struct aggregate_device *to_aggregate_device(struct device *d) -{ - return container_of(d, struct aggregate_device, dev); -} - struct component { struct list_head node; struct aggregate_device *adev; diff --git a/include/linux/component.h b/include/linux/component.h index 95d1b23ede8a..e99cf8e910f0 100644 --- a/include/linux/component.h +++ b/include/linux/component.h @@ -5,6 +5,8 @@ #include #include +struct component_match; + /** * struct component_ops - callbacks for component drivers * @@ -39,8 +41,6 @@ void component_del(struct device *, const struct component_ops *); int component_bind_all(struct device *master, void *master_data); void component_unbind_all(struct device *master, void *master_data); -struct aggregate_device; - /** * struct component_master_ops - callback for the aggregate driver * @@ -80,7 +80,20 @@ struct component_master_ops { void (*unbind)(struct device *master); }; -struct component_match; +struct aggregate_device { + const struct component_master_ops *ops; + struct device *parent; + struct device dev; + struct component_match *match; + struct aggregate_driver *adrv; + + int id; +}; + +static inline struct aggregate_device *to_aggregate_device(struct device *d) +{ + return container_of(d, struct aggregate_device, dev); +} /** * struct aggregate_driver - Aggregate driver (made up of other drivers) -- https://chromeos.dev
[PATCH v2 04/34] drm/msm: Migrate to aggregate driver
The device lists are poorly ordered when the component device code is used. This is because component_master_add_with_match() returns 0 regardless of component devices calling component_add() first. It can really only fail if an allocation fails, in which case everything is going bad and we're out of memory. The driver that registers the aggregate driver, can succeed at probe and put the attached device on the DPM lists before any of the component devices are probed and put on the lists. Within the component device framework this usually isn't that bad because the real driver work is done at bind time via component{,master}_ops::bind(). It becomes a problem when the driver core, or host driver, wants to operate on the component device outside of the bind/unbind functions, e.g. via 'remove' or 'shutdown'. The driver core doesn't understand the relationship between the host device and the component devices and could possibly try to operate on component devices when they're already removed from the system or shut down. Normally, device links or probe defer would reorder the lists and put devices that depend on other devices in the lists at the correct location, but with component devices this doesn't happen because this information isn't expressed anywhere. Drivers simply succeed at registering their component or the aggregate driver with the component framework and wait for their bind() callback to be called once the other components are ready. In summary, the drivers that make up the aggregate driver can probe in any order. This ordering problem becomes fairly obvious when shutting down the device with a DSI controller connected to a DSI bridge that is controlled via i2c. In this case, the msm display driver wants to tear down the display pipeline on shutdown via msm_pdev_shutdown() by calling drm_atomic_helper_shutdown(), and it can't do that unless the whole display chain is still probed and active in the system. When a display bridge is on i2c, the i2c device for the bridge will be created whenever the i2c controller probes, which could be before or after the msm display driver probes. If the i2c controller probes after the display driver, then the i2c controller will be shutdown before the display controller during system wide shutdown and thus i2c transactions will stop working before the display pipeline is shut down. This means we'll have the display bridge trying to access an i2c bus that's shut down because drm_atomic_helper_shutdown() is trying to disable the bridge after the bridge is off. The solution is to make the aggregate driver into a real struct driver that is bound to a device when the other component devices have all probed. Now that the component driver code is a proper bus, we can simply register an aggregate driver with that bus via component_aggregate_register() and then attach the shutdown hook to that driver to be sure that the shutdown for the display pipeline is called before any of the component device driver shutdown hooks are called. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/msm/msm_drv.c | 46 +++ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 2e6fc185e54d..efbcae6e585f 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -1324,19 +1324,35 @@ static int add_gpu_components(struct device *dev, return 0; } -static int msm_drm_bind(struct device *dev) +static int msm_drm_bind(struct aggregate_device *adev) { - return msm_drm_init(dev, _driver); + return msm_drm_init(adev->parent, _driver); } -static void msm_drm_unbind(struct device *dev) +static void msm_drm_unbind(struct aggregate_device *adev) { - msm_drm_uninit(dev); + msm_drm_uninit(adev->parent); +} + +static void msm_drm_shutdown(struct aggregate_device *adev) +{ + struct drm_device *drm = platform_get_drvdata(to_platform_device(adev->parent)); + struct msm_drm_private *priv = drm ? drm->dev_private : NULL; + + if (!priv || !priv->kms) + return; + + drm_atomic_helper_shutdown(drm); } -static const struct component_master_ops msm_drm_ops = { - .bind = msm_drm_bind, - .unbind = msm_drm_unbind, +static struct aggregate_driver msm_drm_aggregate_driver = { + .probe = msm_drm_bind, + .remove = msm_drm_unbind, + .shutdown = msm_drm_shutdown, + .driver = { + .name = "msm_drm", + .owner = THIS_MODULE, + }, }; /* @@ -1365,7 +1381,7 @@ static int msm_pdev_probe(struct platform_device *pdev) if (ret) goto fail; - ret = component_master_add_with_match(>dev, _drm_ops, match); + ret = component_aggregate_register(>dev, _drm_aggregate_driver, match); if (ret) goto
[PATCH v2 06/34] drm/of: Add a drm_of_aggregate_probe() API
Similar to drm_of_component_probe() but using the new API that registers a driver instead of an ops struct. This allows us to migrate the users of drm_of_component_probe() to the new way of doing things. Cc: Laurent Pinchart Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/gpu/drm/drm_of.c | 85 +++- include/drm/drm_of.h | 11 ++ 2 files changed, 77 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_of.c b/drivers/gpu/drm/drm_of.c index 997b8827fed2..58db65ad2770 100644 --- a/drivers/gpu/drm/drm_of.c +++ b/drivers/gpu/drm/drm_of.c @@ -99,30 +99,18 @@ void drm_of_component_match_add(struct device *master, } EXPORT_SYMBOL_GPL(drm_of_component_match_add); -/** - * drm_of_component_probe - Generic probe function for a component based master - * @dev: master device containing the OF node - * @compare_of: compare function used for matching components - * @m_ops: component master ops to be used - * - * Parse the platform device OF node and bind all the components associated - * with the master. Interface ports are added before the encoders in order to - * satisfy their .bind requirements - * See Documentation/devicetree/bindings/graph.txt for the bindings. - * - * Returns zero if successful, or one of the standard error codes if it fails. - */ -int drm_of_component_probe(struct device *dev, +static int _drm_of_component_probe(struct device *dev, int (*compare_of)(struct device *, void *), - const struct component_master_ops *m_ops) + struct component_match **matchptr) { struct device_node *ep, *port, *remote; - struct component_match *match = NULL; int i; if (!dev->of_node) return -EINVAL; + *matchptr = NULL; + /* * Bind the crtc's ports first, so that drm_of_find_possible_crtcs() * called from encoder's .bind callbacks works as expected @@ -133,7 +121,7 @@ int drm_of_component_probe(struct device *dev, break; if (of_device_is_available(port->parent)) - drm_of_component_match_add(dev, , compare_of, + drm_of_component_match_add(dev, matchptr, compare_of, port); of_node_put(port); @@ -144,7 +132,7 @@ int drm_of_component_probe(struct device *dev, return -ENODEV; } - if (!match) { + if (!*matchptr) { dev_err(dev, "no available port\n"); return -ENODEV; } @@ -174,17 +162,76 @@ int drm_of_component_probe(struct device *dev, continue; } - drm_of_component_match_add(dev, , compare_of, + drm_of_component_match_add(dev, matchptr, compare_of, remote); of_node_put(remote); } of_node_put(port); } + return 0; +} + +/** + * drm_of_component_probe - Generic probe function for a component based master + * @dev: master device containing the OF node + * @compare_of: compare function used for matching components + * @m_ops: component master ops to be used + * + * Parse the platform device OF node and bind all the components associated + * with the master. Interface ports are added before the encoders in order to + * satisfy their .bind requirements + * See Documentation/devicetree/bindings/graph.txt for the bindings. + * + * Deprecated: Use drm_of_aggregate_probe() instead. + * + * Returns zero if successful, or one of the standard error codes if it fails. + */ +static int drm_of_component_probe(struct device *dev, + int (*compare_of)(struct device *, void *), + const struct component_master_ops *m_ops) +{ + + struct component_match *match; + int ret; + + ret = _drm_of_component_probe(dev, compare_of, ); + if (ret) + return ret; + return component_master_add_with_match(dev, m_ops, match); } EXPORT_SYMBOL(drm_of_component_probe); + +/** + * drm_of_aggregate_probe - Generic probe function for a component based aggregate host + * @dev: device containing the OF node + * @compare_of: compare function used for matching components + * @adrv: aggregate driver to be used + * + * Parse the platform device OF node and bind all the components associated + * with the aggregate device. Interface ports are added before the encoders in + * order to satisfy their .bind_component requirements + * See Documentation/devicetree/bindings/graph.txt for the bindings. + * + * Returns zero if successful, or one of the standard error codes if it fails. + */ +static int drm_of_aggregate_probe(struct
[PATCH v2 05/34] component: Add {bind, unbind}_component() ops that take aggregate device
We'd like to get more device model features in the component framework so let's pass the struct aggregate_device pointer instead of the parent device pointer to the component binding functions. This will allow drivers to inspect and control things related to the aggregate device in case they need it, and they'll always be able to get back to the device they were using before by using the 'parent' member of the aggregate device struct. Suggested-by: Daniel Vetter Signed-off-by: Stephen Boyd --- drivers/base/component.c | 14 +++--- include/linux/component.h | 22 ++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index f49b48695c8f..a6dd33d0ddeb 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -707,8 +707,13 @@ static void component_unbind(struct component *component, { WARN_ON(!component->bound); - if (component->ops && component->ops->unbind) - component->ops->unbind(component->dev, adev->parent, data); + if (component->ops) { + if (component->ops->unbind) + component->ops->unbind(component->dev, adev->parent, data); + else if (component->ops->unbind_component) + component->ops->unbind_component(component->dev, adev, data); + } + component->bound = false; /* Release all resources claimed in the binding of this component */ @@ -773,7 +778,10 @@ static int component_bind(struct component *component, struct aggregate_device * dev_dbg(adev->parent, "binding %s (ops %ps)\n", dev_name(component->dev), component->ops); - ret = component->ops->bind(component->dev, adev->parent, data); + if (component->ops->bind_component) + ret = component->ops->bind_component(component->dev, adev, data); + else + ret = component->ops->bind(component->dev, adev->parent, data); if (!ret) { component->bound = true; diff --git a/include/linux/component.h b/include/linux/component.h index e99cf8e910f0..d8dcbf9733da 100644 --- a/include/linux/component.h +++ b/include/linux/component.h @@ -6,6 +6,7 @@ #include struct component_match; +struct aggregate_device; /** * struct component_ops - callbacks for component drivers @@ -19,18 +20,39 @@ struct component_ops { * * Called through component_bind_all() when the aggregate driver is * ready to bind the overall driver. +* +* Deprecated: Use bind_component() instead. */ int (*bind)(struct device *comp, struct device *master, void *master_data); + /** +* @bind_component: +* +* Called through component_bind_all() when the aggregate driver is +* ready to bind the overall driver. +*/ + int (*bind_component)(struct device *comp, struct aggregate_device *adev, + void *aggregate_data); /** * @unbind: * * Called through component_unbind_all() when the aggregate driver is * ready to bind the overall driver, or when component_bind_all() fails * part-ways through and needs to unbind some already bound components. +* +* Deprecated: Use unbind_component() instead. */ void (*unbind)(struct device *comp, struct device *master, void *master_data); + /** +* @unbind_component: +* +* Called through component_unbind_all() when the aggregate driver is +* ready to unbind the overall driver, or when component_bind_all() fails +* part-ways through and needs to unbind some already bound components. +*/ + int (*unbind_component)(struct device *comp, struct aggregate_device *adev, + void *aggregate_data); }; int component_add(struct device *, const struct component_ops *); -- https://chromeos.dev
[PATCH v2 02/34] component: Introduce the aggregate bus_type
The component driver only provides 'bind' and 'unbind' callbacks to tell the host driver that it is time to assemble the aggregate driver now that all the components have probed. The component driver model doesn't attempt to resolve runtime PM or suspend/resume ordering, and explicitly mentions this in the code. This lack of support leads to some pretty gnarly usages of the 'prepare' and 'complete' power management hooks in drivers that host the aggregate device, and it fully breaks down when faced with ordering shutdown between the various components, the aggregate driver, and the host driver that registers the whole thing. In a concrete example, the MSM display driver at drivers/gpu/drm/msm is using 'prepare' and 'complete' to call the drm helpers drm_mode_config_helper_suspend() and drm_mode_config_helper_resume() respectively, so that it can move the aggregate driver suspend/resume callbacks to be before and after the components that make up the drm device call any suspend/resume hooks they have. This only works as long as the component devices don't do anything in their own 'prepare' and 'complete' callbacks. If they did, then the ordering would be incorrect and we would be doing something in the component drivers before the aggregate driver could do anything. Yuck! Similarly, when trying to add shutdown support to the MSM driver we run across a problem where we're trying to shutdown the drm device via drm_atomic_helper_shutdown(), but some of the devices in the encoder chain have already been shutdown. This time, the component devices aren't the problem (although they could be if they did anything in their shutdown callbacks), but there's a DSI to eDP bridge in the encoder chain that has already been shutdown before the driver hosting the aggregate device runs shutdown. The ordering of driver probe is like this: 1. msm_pdev_probe() (host driver) 2. DSI bridge 3. aggregate bind When it comes to shutdown we have this order: 1. DSI bridge 2. msm_pdev_shutdown() (host driver) and so the bridge is already off, but we want to communicate to it to turn things off on the display during msm_pdev_shutdown(). Double yuck! Unfortunately, this time we can't split shutdown into multiple phases and swap msm_pdev_shutdown() with the DSI bridge. Let's make the component driver into an actual device driver that has probe/remove/shutdown functions. The driver will only be bound to the aggregate device once all component drivers have called component_add() to indicate they're ready to assemble the aggregate driver. This allows us to attach shutdown logic (and in the future runtime PM logic) to the aggregate driver so that it runs the hooks in the correct order. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/base/component.c | 454 +++--- include/linux/component.h | 62 +- 2 files changed, 381 insertions(+), 135 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index 0a41bbe14981..d99e99cabb99 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -15,6 +15,9 @@ #include #include #include +#include + +#include "base.h" /** * DOC: overview @@ -38,8 +41,8 @@ * * Aggregate drivers first assemble a component match list of what they need * using component_match_add(). This is then registered as an aggregate driver - * using component_master_add_with_match(), and unregistered using - * component_master_del(). + * using component_aggregate_register(), and unregistered using + * component_aggregate_unregister(). */ struct component; @@ -60,17 +63,20 @@ struct component_match { }; struct aggregate_device { - struct list_head node; - bool bound; - const struct component_master_ops *ops; struct device *parent; struct device dev; struct component_match *match; + struct aggregate_driver *adrv; int id; }; +static inline struct aggregate_device *to_aggregate_device(struct device *d) +{ + return container_of(d, struct aggregate_device, dev); +} + struct component { struct list_head node; struct aggregate_device *adev; @@ -79,11 +85,11 @@ struct component { const struct component_ops *ops; int subcomponent; struct device *dev; + struct device_link *link; }; static DEFINE_MUTEX(component_mutex); static LIST_HEAD(component_list); -static LIST_HEAD(aggregate_devices); static DEFINE_IDA(aggregate_ida); @@ -101,7 +107,7 @@ static int component_devices_show(struct seq_file *s, void *data) seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status"); seq_puts(s, "-\n"); seq_printf(s, "%-40s %20s\n\n", - dev_name(m->parent), m->bound ? "bound" : "not bound"); + dev_name(m->parent),
[PATCH v2 01/34] component: Introduce struct aggregate_device
Replace 'struct master' with 'struct aggregate_device' and then rename 'master' to 'adev' everywhere in the code. While we're here, put a struct device inside the aggregate device so that we can register it with a bus_type in the next patch. The diff is large but that's because this is mostly a rename, where sometimes 'master' is replaced with 'adev' and other times it is replaced with 'parent' to indicate that the struct device that was being used is actually the parent of the aggregate device and driver. Cc: Daniel Vetter Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Saravana Kannan Signed-off-by: Stephen Boyd --- drivers/base/component.c | 250 -- include/linux/component.h | 2 +- 2 files changed, 134 insertions(+), 118 deletions(-) diff --git a/drivers/base/component.c b/drivers/base/component.c index 5e79299f6c3f..0a41bbe14981 100644 --- a/drivers/base/component.c +++ b/drivers/base/component.c @@ -9,6 +9,7 @@ */ #include #include +#include #include #include #include @@ -58,18 +59,21 @@ struct component_match { struct component_match_array *compare; }; -struct master { +struct aggregate_device { struct list_head node; bool bound; const struct component_master_ops *ops; struct device *parent; + struct device dev; struct component_match *match; + + int id; }; struct component { struct list_head node; - struct master *master; + struct aggregate_device *adev; bool bound; const struct component_ops *ops; @@ -79,7 +83,9 @@ struct component { static DEFINE_MUTEX(component_mutex); static LIST_HEAD(component_list); -static LIST_HEAD(masters); +static LIST_HEAD(aggregate_devices); + +static DEFINE_IDA(aggregate_ida); #ifdef CONFIG_DEBUG_FS @@ -87,12 +93,12 @@ static struct dentry *component_debugfs_dir; static int component_devices_show(struct seq_file *s, void *data) { - struct master *m = s->private; + struct aggregate_device *m = s->private; struct component_match *match = m->match; size_t i; mutex_lock(_mutex); - seq_printf(s, "%-40s %20s\n", "master name", "status"); + seq_printf(s, "%-40s %20s\n", "aggregate_device name", "status"); seq_puts(s, "-\n"); seq_printf(s, "%-40s %20s\n\n", dev_name(m->parent), m->bound ? "bound" : "not bound"); @@ -122,46 +128,46 @@ static int __init component_debug_init(void) core_initcall(component_debug_init); -static void component_master_debugfs_add(struct master *m) +static void component_master_debugfs_add(struct aggregate_device *m) { debugfs_create_file(dev_name(m->parent), 0444, component_debugfs_dir, m, _devices_fops); } -static void component_master_debugfs_del(struct master *m) +static void component_master_debugfs_del(struct aggregate_device *m) { debugfs_remove(debugfs_lookup(dev_name(m->parent), component_debugfs_dir)); } #else -static void component_master_debugfs_add(struct master *m) +static void component_master_debugfs_add(struct aggregate_device *m) { } -static void component_master_debugfs_del(struct master *m) +static void component_master_debugfs_del(struct aggregate_device *m) { } #endif -static struct master *__master_find(struct device *parent, +static struct aggregate_device *__aggregate_find(struct device *parent, const struct component_master_ops *ops) { - struct master *m; + struct aggregate_device *m; - list_for_each_entry(m, , node) + list_for_each_entry(m, _devices, node) if (m->parent == parent && (!ops || m->ops == ops)) return m; return NULL; } -static struct component *find_component(struct master *master, +static struct component *find_component(struct aggregate_device *adev, struct component_match_array *mc) { struct component *c; list_for_each_entry(c, _list, node) { - if (c->master && c->master != master) + if (c->adev && c->adev != adev) continue; if (mc->compare && mc->compare(c->dev, mc->data)) @@ -175,101 +181,102 @@ static struct component *find_component(struct master *master, return NULL; } -static int find_components(struct master *master) +static int find_components(struct aggregate_device *adev) { - struct component_match *match = master->match; + struct component_match *match = adev->match; size_t i; int ret = 0; /* * Scan the array of match functions and attach -* any components which are found to this master. +* any components which are found to this adev. */ for (i = 0; i < match->num; i++) { struct component_match_array *mc =
[PATCH v2 00/34] component: Make into an aggregate bus
This series is from discussion we had on reordering the device lists for drm shutdown paths[1]. I've introduced an 'aggregate' bus that we put the aggregate device onto and then we probe the aggregate device once all the components are probed and call component_add(). The probe/remove hooks are where the bind/unbind calls go, and then a shutdown hook is added that can be used to shutdown the drm display pipeline at the right time. This works for me on my sc7180 board. I no longer get a warning from i2c at shutdown that we're trying to make an i2c transaction after the i2c bus has been shutdown. There's more work to do on the msm drm driver to extract component device resources like clks, regulators, etc. out of the component bind function into the driver probe but I wanted to move everything over now in other component drivers before tackling that problem. I'll definitely be sending a v3 so this is partially a request for testing to shake out any more problems. Tested-by tags would be appreciated, and Acked-by/Reviewed-by tags too. I sent this to gregkh which may be incorrect but I don't know what better tree to send it all through. Maybe drm? I'll be faster at resending this next time, sorry for the long delay! Changes since v1 (https://lore.kernel.org/r/20210520002519.3538432-1-swb...@chromium.org): - Use devlink to connect components to the aggregate device - Don't set the registering device as a parent of the aggregate device - New patch for bind_component/unbind_component ops that takes the aggregate device - Convert all drivers in the tree to use the aggregate driver approach - Allow one aggregate driver to be used for multiple aggregate devices [1] https://lore.kernel.org/r/20210508074118.1621729-1-swb...@chromium.org Stephen Boyd (34): component: Introduce struct aggregate_device component: Introduce the aggregate bus_type component: Move struct aggregate_device out to header file drm/msm: Migrate to aggregate driver component: Add {bind,unbind}_component() ops that take aggregate device drm/of: Add a drm_of_aggregate_probe() API drm/komeda: Migrate to aggregate driver drm/arm/hdlcd: Migrate to aggregate driver drm/malidp: Migrate to aggregate driver drm/armada: Migrate to aggregate driver drm/etnaviv: Migrate to aggregate driver drm/kirin: Migrate to aggregate driver drm/exynos: Migrate to aggregate driver drm/imx: Migrate to aggregate driver drm/ingenic: Migrate to aggregate driver drm/mcde: Migrate to aggregate driver drm/mediatek: Migrate to aggregate driver drm/meson: Migrate to aggregate driver drm/omap: Migrate to aggregate driver drm/rockchip: Migrate to aggregate driver drm/sti: Migrate to aggregate driver drm/sun4i: Migrate to aggregate driver drm/tilcdc: Migrate to aggregate driver drm/vc4: Migrate to aggregate driver drm/zte: Migrate to aggregate driver iommu/mtk: Migrate to aggregate driver mei: Migrate to aggregate driver power: supply: ab8500: Migrate to aggregate driver fbdev: omap2: Migrate to aggregate driver sound: hdac: Migrate to aggregate driver ASoC: codecs: wcd938x: Migrate to aggregate driver component: Get rid of drm_of_component_probe() component: Remove component_master_ops and friends component: Remove all references to 'master' Cc: Arnd Bergmann Cc: Benjamin Gaignard Cc: Chen Feng Cc: Chen-Yu Tsai Cc: Christian Gmeiner Cc: Chun-Kuang Hu Cc: Daniel Vetter Cc: Emma Anholt Cc: Greg Kroah-Hartman Cc: "Heiko Stübner" Cc: Inki Dae Cc: James Qian Wang (Arm Technology China) Cc: Jaroslav Kysela Cc: Joerg Roedel Cc: John Stultz Cc: Joonyoung Shim Cc: Jyri Sarha Cc: Kai Vehmanen Cc: Kyungmin Park Cc: Laurent Pinchart Cc: Cc: Cc: Cc: Liviu Dudau Cc: Lucas Stach Cc: Mark Brown Cc: Maxime Ripard Cc: Neil Armstrong Cc: Paul Cercueil Cc: Philipp Zabel Cc: "Rafael J. Wysocki" Cc: Rob Clark Cc: Russell King Cc: Russell King Cc: Russell King Cc: Sandy Huang Cc: Saravana Kannan Cc: Sebastian Reichel Cc: Seung-Woo Kim Cc: Takashi Iwai Cc: Tian Tao Cc: Tomas Winkler Cc: Tomi Valkeinen Cc: Will Deacon Cc: Xinliang Liu Cc: Xinwei Kong Cc: Yong Wu drivers/base/component.c | 555 +++--- .../gpu/drm/arm/display/komeda/komeda_drv.c | 20 +- drivers/gpu/drm/arm/hdlcd_drv.c | 21 +- drivers/gpu/drm/arm/malidp_drv.c | 21 +- drivers/gpu/drm/armada/armada_drv.c | 23 +- drivers/gpu/drm/drm_drv.c | 2 +- drivers/gpu/drm/drm_of.c | 20 +- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 +- drivers/gpu/drm/exynos/exynos_drm_drv.c | 21 +- .../gpu/drm/hisilicon/kirin/kirin_drm_drv.c | 20 +- drivers/gpu/drm/imx/imx-drm-core.c| 20 +- drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 24 +- drivers/gpu/drm/mcde/mcde_drv.c | 23 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c| 20 +-
Re: [PATCH RFC] drm: introduce DRM_MODE_FB_PERSIST
On Wed, Oct 6, 2021 at 5:19 PM Simon Ser wrote: > This new ADDFB2 flag allows callers to mark a framebuffer as > "persistent", and no longer have RMFB semantics when the DRM > file is closed. > > [1]: https://lore.kernel.org/dri-devel/YTJypepF1Hpc2YYT@reader/ > > Signed-off-by: Simon Ser > Cc: Hans de Goede > Cc: Dennis Filder > Cc: Daniel Vetter > Cc: Pekka Paalanen > --- > > I'm not sure this is enough, but posting this to get initial > feedback and allow to start e.g. Plymouth experiments. I'll > follow up with an IGT test soon. > > drivers/gpu/drm/drm_framebuffer.c | 6 -- > include/uapi/drm/drm_mode.h | 15 +++ > 2 files changed, 19 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/drm_framebuffer.c > b/drivers/gpu/drm/drm_framebuffer.c > index 07f5abc875e9..9b398838e1f4 100644 > --- a/drivers/gpu/drm/drm_framebuffer.c > +++ b/drivers/gpu/drm/drm_framebuffer.c > @@ -292,7 +292,8 @@ drm_internal_framebuffer_create(struct drm_device *dev, > struct drm_framebuffer *fb; > int ret; > > - if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS)) { > + if (r->flags & ~(DRM_MODE_FB_INTERLACED | DRM_MODE_FB_MODIFIERS | > +DRM_MODE_FB_PERSIST)) { > DRM_DEBUG_KMS("bad framebuffer flags 0x%08x\n", r->flags); > return ERR_PTR(-EINVAL); > } > @@ -789,7 +790,8 @@ void drm_fb_release(struct drm_file *priv) > * at it any more. > */ > list_for_each_entry_safe(fb, tfb, >fbs, filp_head) { > - if (drm_framebuffer_read_refcount(fb) > 1) { > + if (drm_framebuffer_read_refcount(fb) > 1 && > + !(fb->flags & DRM_MODE_FB_PERSIST)) { > list_move_tail(>filp_head, ); > } else { > list_del_init(>filp_head); > diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h > index e1e351682872..c7a7089ec31e 100644 > --- a/include/uapi/drm/drm_mode.h > +++ b/include/uapi/drm/drm_mode.h > @@ -662,6 +662,21 @@ struct drm_mode_fb_cmd { > > #define DRM_MODE_FB_INTERLACED (1<<0) /* for interlaced framebuffers */ > #define DRM_MODE_FB_MODIFIERS (1<<1) /* enables ->modifer[] */ > +/** > + * DRM_MODE_FB_PERSIST > + * > + * DRM framebuffers are normally implicitly removed when their owner closes > the > + * DRM FD. Passing this flag will make the framebuffer persistent: it will > not > + * be implicitly removed. This is useful to implement flicker-free > transitions > + * between two processes. > + * > + * This flag doesn't change the behavior of _IOCTL_MODE_RMFB. > + * > + * User-space should ensure the framebuffer doesn't expose any sensitive user > + * information: persistent framebuffers can be read back by the next DRM > + * master. Should probably explain here that the persistent fb stays around for as long as it's still in use by a plane, but will disappear automatically when it's no longer in active use. Also I guess there was some discussion I've missed on why we exclude rmfb from this (unlike the CLOSEFB thing robclark proposed ages ago). The nice thing about closefb is that you can give it persistent semantics retroactively, so don't need to re-wrap an gem_bo and do a page flip when you quit. -Daniel > + */ > +#define DRM_MODE_FB_PERSIST (1 << 2) > > struct drm_mode_fb_cmd2 { > __u32 fb_id; > -- > 2.33.0 > > -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch
Re: [RFC 6/8] drm/i915: Make some recently added vfuncs use full scheduling attribute
On 06/10/2021 18:12, Matthew Brost wrote: On Mon, Oct 04, 2021 at 03:36:48PM +0100, Tvrtko Ursulin wrote: From: Tvrtko Ursulin Code added in 71ed60112d5d ("drm/i915: Add kick_backend function to i915_sched_engine") and ee242ca704d3 ("drm/i915/guc: Implement GuC priority management") introduced some scheduling related vfuncs which take integer request priority as argument. Make them instead take struct i915_sched_attr, which is the type encapsulating this information, so it probably aligns with the design better. It definitely enables extending the set of scheduling attributes. Understand the motivation here but the i915_scheduler is going to disapear when we move to the DRM scheduler or at least its functionality of priority inheritance will be pushed into the DRM scheduler. I'd be very careful making any changes here as the priority in the DRM scheduler is defined as single enum: /* These are often used as an (initial) index * to an array, and as such should start at 0. */ enum drm_sched_priority { DRM_SCHED_PRIORITY_MIN, DRM_SCHED_PRIORITY_NORMAL, DRM_SCHED_PRIORITY_HIGH, DRM_SCHED_PRIORITY_KERNEL, DRM_SCHED_PRIORITY_COUNT, DRM_SCHED_PRIORITY_UNSET = -2 }; Adding a field to the i915_sched_attr is fairly easy as we already have a structure but changing the DRM scheduler might be a tougher sell. Anyway you can make this work without adding the 'nice' field to i915_sched_attr? Might be worth exploring so when we move to the DRM scheduler this feature drops in a little cleaner. /me rubs a crystal ball.. no idea how that would look. :) Idea with separate nice in sched attr is that only default priority contexts are affected by nice. Thinking being, if i915 aware userspace has explicitly requested a different priority, then let it keep that. In other words, only if it did not bother and left it at default/normal, then we inherit from process nice. I suppose to keep this idea in some future drm scheduler world it would require some work. But in general the concept is of course open to discussion. Implementation wise, not having prio and nice separate opens some other problems in how this interacts with GEM context priority, but there are probably solutions to those problems as well. I suppose I could define a "nice range" in the existing priorities and nice adjustments would only apply if within that range. That would allow max and min user priority to still be undisturbed as requested via the i915 uapi. (min) -1023 - (nice 20) - 0 -- (nice -19) -- +1023 (max) And I say if some userspace set a priority in the -20 to 19 range then it is allowed to adjust it via process nice. That would keep it a single int priority as today. Regards, Tvrtko Matt Signed-off-by: Tvrtko Ursulin Cc: Matthew Brost Cc: Daniele Ceraolo Spurio --- drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 4 +++- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c| 3 ++- drivers/gpu/drm/i915/i915_scheduler.c| 4 ++-- drivers/gpu/drm/i915/i915_scheduler_types.h | 4 ++-- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 7147fe80919e..e91d803a6453 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -3216,11 +3216,13 @@ static bool can_preempt(struct intel_engine_cs *engine) return engine->class != RENDER_CLASS; } -static void kick_execlists(const struct i915_request *rq, int prio) +static void kick_execlists(const struct i915_request *rq, + const struct i915_sched_attr *attr) { struct intel_engine_cs *engine = rq->engine; struct i915_sched_engine *sched_engine = engine->sched_engine; const struct i915_request *inflight; + const int prio = attr->priority; /* * We only need to kick the tasklet once for the high priority diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ba0de35f6323..b5883a4365ca 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2414,9 +2414,10 @@ static void guc_init_breadcrumbs(struct intel_engine_cs *engine) } static void guc_bump_inflight_request_prio(struct i915_request *rq, - int prio) + const struct i915_sched_attr *attr) { struct intel_context *ce = rq->context; + const int prio = attr->priority; u8 new_guc_prio = map_i915_prio_to_guc_prio(prio); /* Short circuit function */ diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c index 762127dd56c5..534bab99fcdc 100644 ---
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
Quoting Bjorn Andersson (2021-10-06 11:05:09) > On Wed 06 Oct 10:19 PDT 2021, Stephen Boyd wrote: > > > Quoting Bjorn Andersson (2021-10-06 10:07:17) > > > On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > > > > > > > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > > > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct > > > > > > > > > platform_device *pdev) > > > > > > > > > if (!dp) > > > > > > > > > return -ENOMEM; > > > > > > > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC specific > > > > > > > > dpu_intf_cfg array in > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > > > > still. Is there any way we can avoid that? Also, notice how > > > > > > > > those arrays > > > > > > > > already have INTF_DP macros, which makes me think that it may > > > > > > > > be better > > > > > > > > to connect this to those arrays instead of making an msm_dp_desc > > > > > > > > structure and then make sure the 'type' member matches a > > > > > > > > connector > > > > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which > > > > > > > part you > > > > > > > consider fragile, the indices of the INTF_DP instances aren't > > > > > > > going to > > > > > > > move around... > > > > > > > > > > > > > > I have N instances of the DP driver that I need to match to N > > > > > > > entries > > > > > > > from the platform specific intf array, I need some stable > > > > > > > reference > > > > > > > between them. When I started this journey I figured I could rely > > > > > > > on the > > > > > > > of_graph between the DPU and the interface controllers, but the > > > > > > > values > > > > > > > used there today are just bogus, so that was a no go. > > > > > > > > > > > > > > We can use whatever, as long as _dpu_kms_initialize_displayport() > > > > > > > can > > > > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > > ^ > > > > > > | > > > > > > > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we > > > > > > have a > > > > > > zero, the number after INTF_DP, and that is very relevant. That > > > > > > number > > > > > > needs to match the dp->id. Somewhere we have a match between > > > > > > controller_id and dp->id in the code. > > > > > > > > > > That number (the 0, not INTF_0) is what the code matches against > > > > > dp->id > > > > > in _dpu_kms_initialize_displayport(), in order to figure out that this > > > > > is INTF_0 in dpu_encoder_setup_display(). > > > > > > > > > > I.e. look at the sc8180x patch: > > > > > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 26, 27), > > > > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 28, 29), > > > > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until > > > > > this is supported */ > > > > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), > > > > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 20, 21), > > > > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, > > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 22, 23), > > > > > > > > > > Where the DP driver defines the 3 controllers with dp->id of 0, 1 and > > > > > 2, > > > > > which the DPU code will match against to INTF_0, INTF_4 and INTF_5. > > > > > > > > > > > > > Yep. I'm saying that having to make that number in this intf
RE: [PATCH v2] drm/hyperv: Fix double mouse pointers
> From: Dexuan Cui > Sent: Thursday, September 16, 2021 12:37 PM > To: drawat.fl...@gmail.com; Haiyang Zhang ; > airl...@linux.ie; dan...@ffwll.ch; tzimmerm...@suse.de; > dri-devel@lists.freedesktop.org > Cc: linux-hyp...@vger.kernel.org; linux-ker...@vger.kernel.org; Dexuan Cui > > Subject: [PATCH v2] drm/hyperv: Fix double mouse pointers > > Hyper-V supports a hardware cursor feature. It is not used by Linux VM, > but the Hyper-V host still draws a point as an extra mouse pointer, > which is unwanted, especially when Xorg is running. > > The hyperv_fb driver uses synthvid_send_ptr() to hide the unwanted pointer. > When the hyperv_drm driver was developed, the function synthvid_send_ptr() > was not copied from the hyperv_fb driver. Fix the issue by adding the > function into hyperv_drm. > > Fixes: 76c56a5affeb ("drm/hyperv: Add DRM driver for hyperv synthetic video > device") > Signed-off-by: Dexuan Cui > Reviewed-by: Haiyang Zhang > Reviewed-by: Deepak Rawat > --- > > Changes in v2: > Renamed hyperv_send_ptr() to hyperv_hide_hw_ptr(). > Improved the comments and the git commit message. > Added Reviewed-by's from Haiyang and Deepak. > > drivers/gpu/drm/hyperv/hyperv_drm.h | 1 + > drivers/gpu/drm/hyperv/hyperv_drm_modeset.c | 1 + > drivers/gpu/drm/hyperv/hyperv_drm_proto.c | 54 > - > 3 files changed, 55 insertions(+), 1 deletion(-) Hi DRM maintainers, Could you please take a look at the patch? Thanks, -- Dexuan
Re: [Intel-gfx] [RFC 7/8] drm/i915: Inherit process nice for context scheduling priority
On 06/10/2021 18:24, Matthew Brost wrote: On Mon, Oct 04, 2021 at 03:36:49PM +0100, Tvrtko Ursulin wrote: From: Tvrtko Ursulin Introduce the concept of context nice value which matches the process nice. We do this by extending the struct i915_sched_attr and add a helper (i915_sched_attr_priority) to be used to convert to effective priority when used by backend code and for priority sorting. Context nice is then inherited from the process which creates the GEM context and utilised secondary to context priority, only when the latter has been left at the default setting, in order to avoid disturbing any application made choices of low and high (batch processing and maybe latency sensitive compositing). In those cases nice value adjusts the effective priority in the narrow band of -19 to +20 around I915_CONTEXT_DEFAULT_PRIORITY. This means that in theory userspace using the context priority uapi directly has a wider range of possible adjustments (thought to be beneficial), but in practice that only applies to execlists platforms. With GuC there are only three priority buckets (less than zero is low priority, zero is normal and greater than zero is high) which therefore interact as expected with the nice adjustment. It makes the question of should the nice be a sub-range of GEM priorities, or stretched across the whole, a moot one. Opps, sorry for the double reply to this patch - for some reason I thinking the below comment would be on the next patch. The GuC + DRM scheduler actually has 4 priorities with the highest reserved for the KMD, so 3 user levels which is what I think you mean. So how would this work with only 3 levels? > > The nice value can move a normal priority value to either low or high, > right? Yes. I was thinking about three user visible levels. The kernel one is reserved for internal stuff so I did not mention it. Default, nice 0 = normal priority. Positive nice = low priority. Negative nice = high priority. Same as mapping of -1024 to 1023 range works onto those three AFAIU. So I think it works. Normal to low seems fine but would moving to high be an issue? I thought a high level was reserved for elevated user processes (e.g. a root user or a compositor)? Yes, and lowering the nice (negative nice) also needs CAP_SYS_NICE which is not available to user processes by default. So that matches i915 rules with going above default/normal. Would it be ok for a non-elevated user process to be the same priority as an elevated process? Not sure exactly what you have in mind but in principle yes. Same as it is okay for all current greater than zero priorities to map to a single priority in case of GuC. Regards, Tvrtko Matt Signed-off-by: Tvrtko Ursulin --- drivers/gpu/drm/i915/gem/i915_gem_context.c| 1 + .../gpu/drm/i915/gt/intel_execlists_submission.c | 4 ++-- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- drivers/gpu/drm/i915/i915_request.c| 2 +- drivers/gpu/drm/i915/i915_request.h| 5 + drivers/gpu/drm/i915/i915_scheduler.c | 12 drivers/gpu/drm/i915/i915_scheduler.h | 14 ++ drivers/gpu/drm/i915/i915_scheduler_types.h| 8 8 files changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 8d4d687ab1d0..fed0733cb652 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -257,6 +257,7 @@ proto_context_create(struct drm_i915_private *i915, unsigned int flags) if (i915->params.enable_hangcheck) pc->user_flags |= BIT(UCONTEXT_PERSISTENCE); pc->sched.priority = I915_PRIORITY_NORMAL; + pc->sched.nice = task_nice(current); if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) { if (!HAS_EXECLISTS(i915)) { diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index e91d803a6453..1a02c65823a7 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -250,7 +250,7 @@ static struct i915_priolist *to_priolist(struct rb_node *rb) static int rq_prio(const struct i915_request *rq) { - return READ_ONCE(rq->sched.attr.priority); + return i915_request_priority(rq); } static int effective_prio(const struct i915_request *rq) @@ -3221,8 +3221,8 @@ static void kick_execlists(const struct i915_request *rq, { struct intel_engine_cs *engine = rq->engine; struct i915_sched_engine *sched_engine = engine->sched_engine; + const int prio = i915_sched_attr_priority(attr); const struct i915_request *inflight; - const int prio = attr->priority; /* * We only need to kick the tasklet once for the high priority diff --git
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
On Wed 06 Oct 10:19 PDT 2021, Dmitry Baryshkov wrote: > On 06/10/2021 20:07, Bjorn Andersson wrote: > > On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > > > > > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct > > > > > > > > platform_device *pdev) > > > > > > > > if (!dp) > > > > > > > > return -ENOMEM; > > > > > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC specific > > > > > > > dpu_intf_cfg array in > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > > > still. Is there any way we can avoid that? Also, notice how those > > > > > > > arrays > > > > > > > already have INTF_DP macros, which makes me think that it may be > > > > > > > better > > > > > > > to connect this to those arrays instead of making an msm_dp_desc > > > > > > > structure and then make sure the 'type' member matches a connector > > > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which part > > > > > > you > > > > > > consider fragile, the indices of the INTF_DP instances aren't going > > > > > > to > > > > > > move around... > > > > > > > > > > > > I have N instances of the DP driver that I need to match to N > > > > > > entries > > > > > > from the platform specific intf array, I need some stable reference > > > > > > between them. When I started this journey I figured I could rely on > > > > > > the > > > > > > of_graph between the DPU and the interface controllers, but the > > > > > > values > > > > > > used there today are just bogus, so that was a no go. > > > > > > > > > > > > We can use whatever, as long as _dpu_kms_initialize_displayport() > > > > > > can > > > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > ^ > > > > > | > > > > > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we have > > > > > a > > > > > zero, the number after INTF_DP, and that is very relevant. That number > > > > > needs to match the dp->id. Somewhere we have a match between > > > > > controller_id and dp->id in the code. > > > > > > > > That number (the 0, not INTF_0) is what the code matches against dp->id > > > > in _dpu_kms_initialize_displayport(), in order to figure out that this > > > > is INTF_0 in dpu_encoder_setup_display(). > > > > > > > > I.e. look at the sc8180x patch: > > > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 24, 25), > > > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 26, 27), > > > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 28, 29), > > > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until > > > > this is supported */ > > > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), > > > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 20, 21), > > > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 22, 23), > > > > > > > > Where the DP driver defines the 3 controllers with dp->id of 0, 1 and 2, > > > > which the DPU code will match against to INTF_0, INTF_4 and INTF_5. > > > > > > > > > > Yep. I'm saying that having to make that number in this intf array match > > > the order of the register mapping descriptor array is fragile. Why can't > > > we indicate the interface is DP or eDP with INTF_DP or INTF_EDP and then > > > map from the descriptor array to this intf array somehow so that the > > > order of the descriptor array
Re: [PATCH v1 2/2] drm/tegra: dc: rgb: Allow changing PLLD rate on Tegra30+
06.10.2021 21:13, Thierry Reding пишет: > On Thu, Sep 30, 2021 at 01:28:05AM +0300, Dmitry Osipenko wrote: >> Asus Transformer TF700T is a Tegra30 tablet device which uses RGB->DSI >> bridge that requires a precise clock rate in order to operate properly. >> Tegra30 has a dedicated PLL for each display controller, hence the PLL >> rate can be changed freely. Allow PLL rate changes on Tegra30+ for RGB >> output. Configure the clock rate before display controller is enabled >> since DC itself may be running off this PLL and it's not okay to change >> the rate of the active PLL that doesn't support dynamic frequency >> switching since hardware will hang. >> >> Tested-by: Maxim Schwalm #TF700T >> Signed-off-by: Dmitry Osipenko >> --- >> drivers/gpu/drm/tegra/dc.c | 27 >> drivers/gpu/drm/tegra/dc.h | 1 + >> drivers/gpu/drm/tegra/rgb.c | 49 +++-- >> 3 files changed, 65 insertions(+), 12 deletions(-) > > This seems overly complicated. I especially don't like the way how > clocks are looked up with clk_get_sys() and then used in the comparison. > Could this not be achieved by using assigned-clocks and friends > properties in DT? Assigned-clocks have nothing to do with this patch. We need to check whether PLLD *is* already pre-assigned as the parent. Adding properties for describing the clk parents is overly complicated, clk_get_sys() is a much simpler solution that doesn't involve extra DT changes. BTW, assigned-clocks can't be used for display controller because controller is usually turned on during boot and reparenting of active DC will hang machine.
Re: [PATCH v6 6/6] drm/sprd: add Unisoc's drm mipi dsi driver
Sam, Thanks for your response. Sam Ravnborg 于2021年9月27日周一 上午12:33写道: > > Hi Kevin, > > > > > + reg->_0b.bits.out_sel = pll->out_sel; > > > > + reg->_0b.bits.kint_l = pll->kint & 0xf; > > > > + reg->_0e.bits.pll_pu_byp = 0; > > > > + reg->_0e.bits.pll_pu = 0; > > > > + reg->_0e.bits.stopstate_sel = 1; > > > > + reg->_0f.bits.det_delay = pll->det_delay; > > > > + > > > > + val = (u8 *) > > > > + > > > > + for (i = 0; i < sizeof(reg_addr); ++i) { > > > > + regmap_write(regmap, reg_addr[i], val[i]); > > > > + DRM_DEBUG("%02x: %02x\n", reg_addr[i], val[i]); > > > > + } > > > > +} > > > > > > It would be great to also convert this part to a pattern without > > > structures. > > I will try it, but our pll registers, all not have official name from > > aisc design owner. > > If need to convert it, our pll regiters macro define, it can only be > > named as reg_01, reg_02... > IT is better to use the stupid names provided by you asic design owner, > than just numbers. Add a comment explaining this is due to the asic > design owner the names are stupid and not your fault. The chip manual released to us by the asic designer is like this for many years ago. As for the specific reason, unable to find out now, i will try use "stupid names" rather than numbers. > > > > > + > > > > + if (dsi->panel) { > > > > + drm_panel_prepare(dsi->panel); > > > > + drm_panel_enable(dsi->panel); > > > > + } > > > > > > Please use the new devm_drm_of_get_bridge helper here, and use the > > > bridge API instead. > > We use drm_panel_init and drm_panel_add API to add panel, so here is a > > panel device, not a bridge. > > The new way to do this is to always wrap the panel in a bridge. We will > start to slowly migrate away from direct use of the panel API, and let > display drivers always wrap the panles in a bridge. > So please do as Maxime suggests. I only found a demo about the use of devm_drm_of_get_bridge in the vc4 dsi driver, i will try to follow it. > > Sam
Re: [PATCH v6 2/3] arm64: tegra: Add NVDEC to Tegra186/194 device trees
On Thu, Sep 16, 2021 at 05:55:16PM +0300, Mikko Perttunen wrote: > Add a device tree node for NVDEC on Tegra186, and > device tree nodes for NVDEC and NVDEC1 on Tegra194. > > Signed-off-by: Mikko Perttunen > --- > v5: > * Change from nvidia,instance to nvidia,host1x-class > v4: > * Add dma-coherent markers > v3: > * Change read2 to read-1 > v2: > * Add NVDECSRD1 memory client > * Add also to T194 (both NVDEC0/1) > --- > arch/arm64/boot/dts/nvidia/tegra186.dtsi | 16 ++ > arch/arm64/boot/dts/nvidia/tegra194.dtsi | 38 > 2 files changed, 54 insertions(+) The driver patch adds support for Tegra210, so could we also add NVDEC entries for that? Thierry signature.asc Description: PGP signature
Re: [PATCH v6 1/3] dt-bindings: Add YAML bindings for NVDEC
On Thu, Sep 16, 2021 at 05:55:15PM +0300, Mikko Perttunen wrote: > Add YAML device tree bindings for NVDEC, now in a more appropriate > place compared to the old textual Host1x bindings. > > Signed-off-by: Mikko Perttunen > --- > v6: > * Elaborated description for nvidia,host1x-class. > * Added default value for nvidia,host1x-class. > v5: > * Changed from nvidia,instance to nvidia,host1x-class optional > property. > * Added dma-coherent > v4: > * Fix incorrect compatibility string in 'if' condition > v3: > * Drop host1x bindings > * Change read2 to read-1 in interconnect names > v2: > * Fix issues pointed out in v1 > * Add T194 nvidia,instance property > --- > .../gpu/host1x/nvidia,tegra210-nvdec.yaml | 108 ++ > MAINTAINERS | 1 + > 2 files changed, 109 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/gpu/host1x/nvidia,tegra210-nvdec.yaml Applied with the yamllint warning fixed. Thanks, Thierry signature.asc Description: PGP signature
Re: [PATCH v1 2/2] drm/tegra: dc: rgb: Allow changing PLLD rate on Tegra30+
On Thu, Sep 30, 2021 at 01:28:05AM +0300, Dmitry Osipenko wrote: > Asus Transformer TF700T is a Tegra30 tablet device which uses RGB->DSI > bridge that requires a precise clock rate in order to operate properly. > Tegra30 has a dedicated PLL for each display controller, hence the PLL > rate can be changed freely. Allow PLL rate changes on Tegra30+ for RGB > output. Configure the clock rate before display controller is enabled > since DC itself may be running off this PLL and it's not okay to change > the rate of the active PLL that doesn't support dynamic frequency > switching since hardware will hang. > > Tested-by: Maxim Schwalm #TF700T > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/tegra/dc.c | 27 > drivers/gpu/drm/tegra/dc.h | 1 + > drivers/gpu/drm/tegra/rgb.c | 49 +++-- > 3 files changed, 65 insertions(+), 12 deletions(-) This seems overly complicated. I especially don't like the way how clocks are looked up with clk_get_sys() and then used in the comparison. Could this not be achieved by using assigned-clocks and friends properties in DT? Thierry signature.asc Description: PGP signature
Re: [PATCH v1 1/2] drm/tegra: dc: rgb: Move PCLK shifter programming to CRTC
On Thu, Sep 30, 2021 at 01:28:04AM +0300, Dmitry Osipenko wrote: > Asus TF700T tablet uses TC358768 DPI->DSI bridge that sits between Tegra's > DPI output and display panel input. Bridge requires to have stable PCLK > output before RGB encoder is enabled because it uses PCLK by itself to > clock internal logic and bridge is programmed before Tegra's encoder is > enabled. Hence the PCLK clock shifter must be programmed when CRTC is > enabled, otherwise clock is unstable and bridge hangs because of it. > Move the shifter programming from RGB encoder into CRTC. > > Tested-by: Maxim Schwalm #TF700T > Signed-off-by: Dmitry Osipenko > --- > drivers/gpu/drm/tegra/dc.c | 6 ++ > drivers/gpu/drm/tegra/rgb.c | 4 > 2 files changed, 6 insertions(+), 4 deletions(-) Applied, thanks. Thierry signature.asc Description: PGP signature
Re: [PATCH v6 3/3] drm/tegra: Add NVDEC driver
On Thu, Sep 16, 2021 at 05:55:17PM +0300, Mikko Perttunen wrote: > Add support for booting and using NVDEC on Tegra210, Tegra186 > and Tegra194 to the Host1x and TegraDRM drivers. Booting in > secure mode is not currently supported. > > Signed-off-by: Mikko Perttunen > --- > v5: > * Remove num_instances > * Change from nvidia,instance to nvidia,host1x-class > v3: > * Change num_instances to unsigned int > * Remove unnecessary '= 0' initializer > * Populate num_instances data > * Fix instance number check > v2: > * Use devm_platform_get_and_ioremap_resource > * Remove reset handling, done by power domain code > * Assume runtime PM is enabled > --- > drivers/gpu/drm/tegra/Makefile | 3 +- > drivers/gpu/drm/tegra/drm.c| 4 + > drivers/gpu/drm/tegra/drm.h| 1 + > drivers/gpu/drm/tegra/nvdec.c | 464 + > drivers/gpu/host1x/dev.c | 18 ++ > include/linux/host1x.h | 2 + > 6 files changed, 491 insertions(+), 1 deletion(-) > create mode 100644 drivers/gpu/drm/tegra/nvdec.c Applied, thanks. Thierry signature.asc Description: PGP signature
Re: [PATCH] drm/tegra: Bump VIC/NVDEC clock rates to Fmax
On Thu, Sep 16, 2021 at 06:09:20PM +0300, Mikko Perttunen wrote: > To get full performance out of these engines, bump their clock rates > to maximum. In the future we may want something smarter but this > should be fine for now. > > Signed-off-by: Mikko Perttunen > --- > drivers/gpu/drm/tegra/nvdec.c | 6 ++ > drivers/gpu/drm/tegra/vic.c | 6 ++ > 2 files changed, 12 insertions(+) Applied, thanks. Thierry signature.asc Description: PGP signature
Re: mmotm 2021-10-05-19-53 uploaded (drivers/gpu/drm/msm/hdmi/hdmi_phy.o)
On 10/6/21 12:24 AM, Christian König wrote: Am 06.10.21 um 09:20 schrieb Stephen Rothwell: Hi Randy, On Tue, 5 Oct 2021 22:48:03 -0700 Randy Dunlap wrote: on i386: ld: drivers/gpu/drm/msm/hdmi/hdmi_phy.o:(.rodata+0x3f0): undefined reference to `msm_hdmi_phy_8996_cfg' Full randconfig fle is attached. This would be because CONFIG_DRM_MSM is set but CONFIG_COMMON_CLOCK is not and has been exposed by commit b3ed524f84f5 ("drm/msm: allow compile_test on !ARM") from the drm-misc tree. Good point, how about this change: diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig index 5879f67bc88c..d9879b011fb0 100644 --- a/drivers/gpu/drm/msm/Kconfig +++ b/drivers/gpu/drm/msm/Kconfig @@ -5,7 +5,7 @@ config DRM_MSM depends on DRM depends on ARCH_QCOM || SOC_IMX5 || COMPILE_TEST depends on IOMMU_SUPPORT - depends on (OF && COMMON_CLK) || COMPILE_TEST + depends on (OF || COMPILE_TEST) && COMMON_CLK depends on QCOM_OCMEM || QCOM_OCMEM=n depends on QCOM_LLCC || QCOM_LLCC=n depends on QCOM_COMMAND_DB || QCOM_COMMAND_DB=n WorksForMe. Thanks. (other than the whitespace damage) -- ~Randy
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
On Wed 06 Oct 10:19 PDT 2021, Stephen Boyd wrote: > Quoting Bjorn Andersson (2021-10-06 10:07:17) > > On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > > > > > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct > > > > > > > > platform_device *pdev) > > > > > > > > if (!dp) > > > > > > > > return -ENOMEM; > > > > > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC specific > > > > > > > dpu_intf_cfg array in > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > > > still. Is there any way we can avoid that? Also, notice how those > > > > > > > arrays > > > > > > > already have INTF_DP macros, which makes me think that it may be > > > > > > > better > > > > > > > to connect this to those arrays instead of making an msm_dp_desc > > > > > > > structure and then make sure the 'type' member matches a connector > > > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which part > > > > > > you > > > > > > consider fragile, the indices of the INTF_DP instances aren't going > > > > > > to > > > > > > move around... > > > > > > > > > > > > I have N instances of the DP driver that I need to match to N > > > > > > entries > > > > > > from the platform specific intf array, I need some stable reference > > > > > > between them. When I started this journey I figured I could rely on > > > > > > the > > > > > > of_graph between the DPU and the interface controllers, but the > > > > > > values > > > > > > used there today are just bogus, so that was a no go. > > > > > > > > > > > > We can use whatever, as long as _dpu_kms_initialize_displayport() > > > > > > can > > > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > > ^ > > > > > | > > > > > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we have > > > > > a > > > > > zero, the number after INTF_DP, and that is very relevant. That number > > > > > needs to match the dp->id. Somewhere we have a match between > > > > > controller_id and dp->id in the code. > > > > > > > > That number (the 0, not INTF_0) is what the code matches against dp->id > > > > in _dpu_kms_initialize_displayport(), in order to figure out that this > > > > is INTF_0 in dpu_encoder_setup_display(). > > > > > > > > I.e. look at the sc8180x patch: > > > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 24, 25), > > > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 26, 27), > > > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 28, 29), > > > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until > > > > this is supported */ > > > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, > > > > INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), > > > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 20, 21), > > > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, > > > > MDP_SSPP_TOP0_INTR, 22, 23), > > > > > > > > Where the DP driver defines the 3 controllers with dp->id of 0, 1 and 2, > > > > which the DPU code will match against to INTF_0, INTF_4 and INTF_5. > > > > > > > > > > Yep. I'm saying that having to make that number in this intf array match > > > the order of the register mapping descriptor array is fragile. Why can't > > > we indicate the interface is DP or eDP with INTF_DP or INTF_EDP and then > > > map from the descriptor array to this intf array somehow so that the > > > order of the descriptor array doesn't matter? Then we
Re: [PATCH v6 6/6] drm/sprd: add Unisoc's drm mipi dsi driver
Maxime Ripard 于2021年9月28日周二 下午5:28写道: > > On Sun, Sep 26, 2021 at 10:31:53PM +0800, Kevin Tang wrote: > > Maxime Ripard 于2021年9月17日周五 下午11:40写道: > > > > +static void sprd_dsi_encoder_mode_set(struct drm_encoder *encoder, > > > > + struct drm_display_mode *mode, > > > > + struct drm_display_mode *adj_mode) > > > > +{ > > > > + struct sprd_dsi *dsi = encoder_to_dsi(encoder); > > > > + > > > > + drm_dbg(dsi->drm, "%s() set mode: %s\n", __func__, > > > > dsi->mode->name); > > > > +} > > > > > > You don't need that function? > > No need for now. need to delete it? > > Yes > > > > > +static int sprd_dsi_encoder_atomic_check(struct drm_encoder *encoder, > > > > + struct drm_crtc_state *crtc_state, > > > > + struct drm_connector_state > > > > *conn_state) > > > > +{ > > > > + return 0; > > > > +} > > > > > > Ditto > > > > No need for now. need to delete it? > > Yep > > > > > +static int sprd_dsi_find_panel(struct sprd_dsi *dsi) > > > > +{ > > > > + struct device *dev = dsi->host.dev; > > > > + struct device_node *child, *lcds_node; > > > > + struct drm_panel *panel; > > > > + > > > > + /* search /lcds child node first */ > > > > + lcds_node = of_find_node_by_path("/lcds"); > > > > + for_each_child_of_node(lcds_node, child) { > > > > + panel = of_drm_find_panel(child); > > > > + if (!IS_ERR(panel)) { > > > > + dsi->panel = panel; > > > > + return 0; > > > > + } > > > > + } > > > > + > > > > + /* > > > > + * If /lcds child node search failed, we search > > > > + * the child of dsi host node. > > > > + */ > > > > + for_each_child_of_node(dev->of_node, child) { > > > > + panel = of_drm_find_panel(child); > > > > + if (!IS_ERR(panel)) { > > > > + dsi->panel = panel; > > > > + return 0; > > > > + } > > > > + } > > > > + > > > > + drm_err(dsi->drm, "of_drm_find_panel() failed\n"); > > > > + return -ENODEV; > > > > +} > > > > > > Just use devm_drm_of_get_bridge there > > > > We use drm_panel_init and drm_panel_add API to add panel, so here is a > > panel device, not a bridge. > > Like Sam said, the panel API is on its way out and is being superseded > by bridge_panels. Ok, i will try it. > > > > > +static int sprd_dsi_host_init(struct sprd_dsi *dsi, struct device *dev) > > > > +{ > > > > + int ret; > > > > + > > > > + dsi->host.dev = dev; > > > > + dsi->host.ops = _dsi_host_ops; > > > > + > > > > + ret = mipi_dsi_host_register(>host); > > > > + if (ret) > > > > + drm_err(dsi->drm, "failed to register dsi host\n"); > > > > + > > > > + return ret; > > > > +} > > > > > > > > [...] > > > > > > > > +static int sprd_dsi_connector_init(struct drm_device *drm, struct > > > > sprd_dsi *dsi) > > > > +{ > > > > + struct drm_encoder *encoder = >encoder; > > > > + struct drm_connector *connector = >connector; > > > > + int ret; > > > > + > > > > + connector->polled = DRM_CONNECTOR_POLL_HPD; > > > > + > > > > + ret = drm_connector_init(drm, connector, > > > > + _dsi_atomic_connector_funcs, > > > > + DRM_MODE_CONNECTOR_DSI); > > > > + if (ret) { > > > > + drm_err(drm, "drm_connector_init() failed\n"); > > > > + return ret; > > > > + } > > > > + > > > > + drm_connector_helper_add(connector, > > > > + _dsi_connector_helper_funcs); > > > > + > > > > + drm_connector_attach_encoder(connector, encoder); > > > > + > > > > + return 0; > > > > +} > > > > + > > > > +static int sprd_dsi_context_init(struct sprd_dsi *dsi, > > > > + struct device *dev) > > > > +{ > > > > + struct platform_device *pdev = to_platform_device(dev); > > > > + struct dsi_context *ctx = >ctx; > > > > + struct resource *res; > > > > + > > > > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > > > > + ctx->base = devm_ioremap(dev, res->start, resource_size(res)); > > > > + if (!ctx->base) { > > > > + drm_err(dsi->drm, "failed to map dsi host registers\n"); > > > > + return -ENXIO; > > > > + } > > > > + > > > > + ctx->pll = devm_kzalloc(dev, sizeof(*ctx->pll), GFP_KERNEL); > > > > + if (!ctx->pll) > > > > + return -ENOMEM; > > > > + > > > > + ctx->regmap = devm_regmap_init(dev, _tst_io, dsi, > > > > _config); > > > > + if (IS_ERR(ctx->regmap)) { > > > > + drm_err(dsi->drm, "dphy regmap init failed\n"); > > > > + return PTR_ERR(ctx->regmap); > > > > + } > > > > + > > > > + ctx->data_hs2lp = 120; > > > > + ctx->data_lp2hs = 500; > > > > + ctx->clk_hs2lp = 4; > > > > + ctx->clk_lp2hs = 15; > > > >
Re: [PATCH] drm/msm/dp: Shorten SETUP timeout
On Wed 06 Oct 08:37 PDT 2021, khs...@codeaurora.org wrote: > On 2021-10-05 19:10, Bjorn Andersson wrote: > > On Tue 05 Oct 16:04 PDT 2021, khs...@codeaurora.org wrote: > > > > > On 2021-10-05 15:36, Stephen Boyd wrote: > > > > Quoting Bjorn Andersson (2021-10-05 14:40:38) > > > > > On Tue 05 Oct 11:45 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-04 19:37:50) > > > > > > > Found in the middle of a patch from Sankeerth was the reduction > > > > > > > of the > > > > > > > INIT_SETUP timeout from 10s to 100ms. Upon INIT_SETUP timeout the > > > > > > > host > > > > > > > is initalized and HPD interrupt start to be serviced, so in the > > > > > > > case of > > > > > > > eDP this reduction improves the user experience dramatically - > > > > > > > i.e. > > > > > > > removes 9.9s of bland screen time at boot. > > > > > > > > > > > > > > Suggested-by: Sankeerth Billakanti > > > > > > > Signed-off-by: Bjorn Andersson > > > > > > > --- > > > > > > > > > > > > Any Fixes tag? BTW, the delay design is pretty convoluted. I had to > > > > > > go > > > > > > re-read the code a couple times to understand that it's waiting > > > > > > 100ms > > > > > > times the 'delay' number. What? > > > > > > > > > > > > > > > > I assume you're happy with the current 10s delay on the current > > > > > devices, so I don't think we should push for this to be backported. > > > > > I have no need for it to be backported on my side at least. > > > > > > > > > > > > > Sure. Fixes tag != backported to stable trees but it is close. > > > > > > > > > > Reviewed-by: Stephen Boyd > > > > > > > > dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 1); <== to 100ms > > > > > > This patch will prevent usb3 from working due to dp driver > > > initialize phy > > > earlier than usb3 which cause timeout error at power up usb3 phy > > > when both > > > edp and dp are enabled. > > > > Can you please help me understand what you mean here, I use this on my > > sc8180x with both eDP and USB-C/DP right now. What is it that doesn't > > work? Or am I just lucky in some race condition? > > > > Thanks, > > Bjorn > > > The problem is seen at sc7280. > Apple dongle have both hdmi and usb port. > plug Apple dongle into type-c, then plug DP into apple's hdmi port and usb > mouse into apple's usb port. > If edp enabled at this time, then usb mouse will not work due to timeout at > phy power up. > Okay, so you're saying that if the DP driver invokes phy_power_on() before the USB driver does, USB initialization fails (or at least USB doesn't work)? Sounds like something we need to work out in the QMP phy driver. Do you have any more details about what's going wrong. Also, I've seen various references to said "Apple dongle", do you have a link to the exact one you're testing with so I can pick one up for testing purposes as well? Regards, Bjorn > > > I had prepared a patch (drm/msm/dp: do not initialize combo phy > > > until plugin > > > interrupt) to fix this problem. > > > Unfortunately, my patch is depend on Bjorn's patch (PATCH v3 3/5] > > > drm/msm/dp: Support up to 3 DP controllers). > > > I will submit my patch for review once Bjorn's patches merged in. > > > Therefore I would think this patch should go after both Bjorn's > > > patches and > > > my patch. > > > > > > > > >
Re: [Intel-gfx] [RFC 7/8] drm/i915: Inherit process nice for context scheduling priority
On Mon, Oct 04, 2021 at 03:36:49PM +0100, Tvrtko Ursulin wrote: > From: Tvrtko Ursulin > > Introduce the concept of context nice value which matches the process > nice. > > We do this by extending the struct i915_sched_attr and add a helper > (i915_sched_attr_priority) to be used to convert to effective priority > when used by backend code and for priority sorting. > > Context nice is then inherited from the process which creates the GEM > context and utilised secondary to context priority, only when the latter > has been left at the default setting, in order to avoid disturbing any > application made choices of low and high (batch processing and maybe > latency sensitive compositing). In those cases nice value adjusts the > effective priority in the narrow band of -19 to +20 around > I915_CONTEXT_DEFAULT_PRIORITY. > > This means that in theory userspace using the context priority uapi > directly has a wider range of possible adjustments (thought to be > beneficial), but in practice that only applies to execlists platforms. > With GuC there are only three priority buckets (less than zero is low > priority, zero is normal and greater than zero is high) which therefore > interact as expected with the nice adjustment. It makes the question of > should the nice be a sub-range of GEM priorities, or stretched across the > whole, a moot one. > Opps, sorry for the double reply to this patch - for some reason I thinking the below comment would be on the next patch. The GuC + DRM scheduler actually has 4 priorities with the highest reserved for the KMD, so 3 user levels which is what I think you mean. So how would this work with only 3 levels? The nice value can move a normal priority value to either low or high, right? Normal to low seems fine but would moving to high be an issue? I thought a high level was reserved for elevated user processes (e.g. a root user or a compositor)? Would it be ok for a non-elevated user process to be the same priority as an elevated process? Matt > Signed-off-by: Tvrtko Ursulin > --- > drivers/gpu/drm/i915/gem/i915_gem_context.c| 1 + > .../gpu/drm/i915/gt/intel_execlists_submission.c | 4 ++-- > drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- > drivers/gpu/drm/i915/i915_request.c| 2 +- > drivers/gpu/drm/i915/i915_request.h| 5 + > drivers/gpu/drm/i915/i915_scheduler.c | 12 > drivers/gpu/drm/i915/i915_scheduler.h | 14 ++ > drivers/gpu/drm/i915/i915_scheduler_types.h| 8 > 8 files changed, 40 insertions(+), 8 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c > b/drivers/gpu/drm/i915/gem/i915_gem_context.c > index 8d4d687ab1d0..fed0733cb652 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c > @@ -257,6 +257,7 @@ proto_context_create(struct drm_i915_private *i915, > unsigned int flags) > if (i915->params.enable_hangcheck) > pc->user_flags |= BIT(UCONTEXT_PERSISTENCE); > pc->sched.priority = I915_PRIORITY_NORMAL; > + pc->sched.nice = task_nice(current); > > if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) { > if (!HAS_EXECLISTS(i915)) { > diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > index e91d803a6453..1a02c65823a7 100644 > --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > @@ -250,7 +250,7 @@ static struct i915_priolist *to_priolist(struct rb_node > *rb) > > static int rq_prio(const struct i915_request *rq) > { > - return READ_ONCE(rq->sched.attr.priority); > + return i915_request_priority(rq); > } > > static int effective_prio(const struct i915_request *rq) > @@ -3221,8 +3221,8 @@ static void kick_execlists(const struct i915_request > *rq, > { > struct intel_engine_cs *engine = rq->engine; > struct i915_sched_engine *sched_engine = engine->sched_engine; > + const int prio = i915_sched_attr_priority(attr); > const struct i915_request *inflight; > - const int prio = attr->priority; > > /* >* We only need to kick the tasklet once for the high priority > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index b5883a4365ca..f258607685a2 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -2417,7 +2417,7 @@ static void guc_bump_inflight_request_prio(struct > i915_request *rq, > const struct i915_sched_attr *attr) > { > struct intel_context *ce = rq->context; > - const int prio = attr->priority; > + const int prio = i915_sched_attr_priority(attr); > u8 new_guc_prio =
Re: [Intel-gfx] [RFC 7/8] drm/i915: Inherit process nice for context scheduling priority
On Mon, Oct 04, 2021 at 03:36:49PM +0100, Tvrtko Ursulin wrote: > From: Tvrtko Ursulin > > Introduce the concept of context nice value which matches the process > nice. > > We do this by extending the struct i915_sched_attr and add a helper > (i915_sched_attr_priority) to be used to convert to effective priority > when used by backend code and for priority sorting. > > Context nice is then inherited from the process which creates the GEM > context and utilised secondary to context priority, only when the latter > has been left at the default setting, in order to avoid disturbing any > application made choices of low and high (batch processing and maybe > latency sensitive compositing). In those cases nice value adjusts the > effective priority in the narrow band of -19 to +20 around > I915_CONTEXT_DEFAULT_PRIORITY. > > This means that in theory userspace using the context priority uapi > directly has a wider range of possible adjustments (thought to be > beneficial), but in practice that only applies to execlists platforms. > With GuC there are only three priority buckets (less than zero is low > priority, zero is normal and greater than zero is high) which therefore > interact as expected with the nice adjustment. It makes the question of > should the nice be a sub-range of GEM priorities, or stretched across the > whole, a moot one. > > Signed-off-by: Tvrtko Ursulin > --- > drivers/gpu/drm/i915/gem/i915_gem_context.c| 1 + > .../gpu/drm/i915/gt/intel_execlists_submission.c | 4 ++-- > drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- > drivers/gpu/drm/i915/i915_request.c| 2 +- > drivers/gpu/drm/i915/i915_request.h| 5 + > drivers/gpu/drm/i915/i915_scheduler.c | 12 > drivers/gpu/drm/i915/i915_scheduler.h | 14 ++ > drivers/gpu/drm/i915/i915_scheduler_types.h| 8 > 8 files changed, 40 insertions(+), 8 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c > b/drivers/gpu/drm/i915/gem/i915_gem_context.c > index 8d4d687ab1d0..fed0733cb652 100644 > --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c > +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c > @@ -257,6 +257,7 @@ proto_context_create(struct drm_i915_private *i915, > unsigned int flags) > if (i915->params.enable_hangcheck) > pc->user_flags |= BIT(UCONTEXT_PERSISTENCE); > pc->sched.priority = I915_PRIORITY_NORMAL; > + pc->sched.nice = task_nice(current); > > if (flags & I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE) { > if (!HAS_EXECLISTS(i915)) { > diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > index e91d803a6453..1a02c65823a7 100644 > --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > @@ -250,7 +250,7 @@ static struct i915_priolist *to_priolist(struct rb_node > *rb) > > static int rq_prio(const struct i915_request *rq) > { > - return READ_ONCE(rq->sched.attr.priority); > + return i915_request_priority(rq); > } > > static int effective_prio(const struct i915_request *rq) > @@ -3221,8 +3221,8 @@ static void kick_execlists(const struct i915_request > *rq, > { > struct intel_engine_cs *engine = rq->engine; > struct i915_sched_engine *sched_engine = engine->sched_engine; > + const int prio = i915_sched_attr_priority(attr); > const struct i915_request *inflight; > - const int prio = attr->priority; > > /* >* We only need to kick the tasklet once for the high priority > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index b5883a4365ca..f258607685a2 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -2417,7 +2417,7 @@ static void guc_bump_inflight_request_prio(struct > i915_request *rq, > const struct i915_sched_attr *attr) > { > struct intel_context *ce = rq->context; > - const int prio = attr->priority; > + const int prio = i915_sched_attr_priority(attr); > u8 new_guc_prio = map_i915_prio_to_guc_prio(prio); > > /* Short circuit function */ > diff --git a/drivers/gpu/drm/i915/i915_request.c > b/drivers/gpu/drm/i915/i915_request.c > index 79da5eca60af..a8c6f3a64895 100644 > --- a/drivers/gpu/drm/i915/i915_request.c > +++ b/drivers/gpu/drm/i915/i915_request.c > @@ -1930,7 +1930,7 @@ static int print_sched_attr(const struct > i915_sched_attr *attr, > return x; > > x += snprintf(buf + x, len - x, > - " prio=%d", attr->priority); > + " prio=%d nice=%d", attr->priority, attr->nice); > > return x; > } > diff --git a/drivers/gpu/drm/i915/i915_request.h >
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
On 06/10/2021 20:07, Bjorn Andersson wrote: On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: Quoting Bjorn Andersson (2021-10-05 19:37:52) On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: Quoting Bjorn Andersson (2021-10-05 18:43:16) On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: Quoting Bjorn Andersson (2021-10-05 16:13:21) diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index bdaf227f05dc..674cddfee5b0 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct platform_device *pdev) if (!dp) return -ENOMEM; - desc = dp_display_get_desc(pdev); + desc = dp_display_get_desc(pdev, >id); I'm sad that dp->id has to match the number in the SoC specific dpu_intf_cfg array in drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c still. Is there any way we can avoid that? Also, notice how those arrays already have INTF_DP macros, which makes me think that it may be better to connect this to those arrays instead of making an msm_dp_desc structure and then make sure the 'type' member matches a connector type number. Otherwise this code is super fragile. I'm afraid I don't understand what you're proposing. Or which part you consider fragile, the indices of the INTF_DP instances aren't going to move around... I have N instances of the DP driver that I need to match to N entries from the platform specific intf array, I need some stable reference between them. When I started this journey I figured I could rely on the of_graph between the DPU and the interface controllers, but the values used there today are just bogus, so that was a no go. We can use whatever, as long as _dpu_kms_initialize_displayport() can come up with an identifier to put in h_tile_instance[0] so that dpu_encoder_setup_display() can find the relevant INTF. To make it more concrete we can look at sc7180 static const struct dpu_intf_cfg sc7180_intf[] = { INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), ^ | intf0 is irrelevant. Also the address is irrelevant. But here we have a zero, the number after INTF_DP, and that is very relevant. That number needs to match the dp->id. Somewhere we have a match between controller_id and dp->id in the code. That number (the 0, not INTF_0) is what the code matches against dp->id in _dpu_kms_initialize_displayport(), in order to figure out that this is INTF_0 in dpu_encoder_setup_display(). I.e. look at the sc8180x patch: INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 24, 25), INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 26, 27), INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 28, 29), /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this is supported */ INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 30, 31), INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 20, 21), INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, MDP_SSPP_TOP0_INTR, 22, 23), Where the DP driver defines the 3 controllers with dp->id of 0, 1 and 2, which the DPU code will match against to INTF_0, INTF_4 and INTF_5. Yep. I'm saying that having to make that number in this intf array match the order of the register mapping descriptor array is fragile. Why can't we indicate the interface is DP or eDP with INTF_DP or INTF_EDP and then map from the descriptor array to this intf array somehow so that the order of the descriptor array doesn't matter? Then we don't have to put the connector type in the descriptor array, and we don't have to keep the order of the array a certain way to match this intf descriptor. Maybe struct msm_dp_desc { phys_addr_t io_start; unsigned int id; The INTF_ constants are a property of the DPU driver and not available in the DP driver and the msm_dp struct is a property of the DP driver and can't be dereferenced in the DPU driver. The proposed way around this is that the descs array defines the order in priv->dp[N] and this N is used as controller_id. So the only thing that I don't find straight forward here is that the eDP controller is considered just a DP controller, so you have to use INTF_DP, for that, and not just INTF_EDP, 0. Would it be better if we change the DPU driver to handle INTF_EDP too? }; and then have msm_dp_desc::id equal INTF_ and then look through the intf from DPU here in the DP driver to find the id and type of connector that should be used by default? Still sort of fragile because the only connection is an unsigned int
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
Quoting Bjorn Andersson (2021-10-06 10:07:17) > On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > > > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct > > > > > > > platform_device *pdev) > > > > > > > if (!dp) > > > > > > > return -ENOMEM; > > > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC specific > > > > > > dpu_intf_cfg array in drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > > still. Is there any way we can avoid that? Also, notice how those > > > > > > arrays > > > > > > already have INTF_DP macros, which makes me think that it may be > > > > > > better > > > > > > to connect this to those arrays instead of making an msm_dp_desc > > > > > > structure and then make sure the 'type' member matches a connector > > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which part you > > > > > consider fragile, the indices of the INTF_DP instances aren't going to > > > > > move around... > > > > > > > > > > I have N instances of the DP driver that I need to match to N entries > > > > > from the platform specific intf array, I need some stable reference > > > > > between them. When I started this journey I figured I could rely on > > > > > the > > > > > of_graph between the DPU and the interface controllers, but the values > > > > > used there today are just bogus, so that was a no go. > > > > > > > > > > We can use whatever, as long as _dpu_kms_initialize_displayport() can > > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > > ^ > > > > | > > > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we have a > > > > zero, the number after INTF_DP, and that is very relevant. That number > > > > needs to match the dp->id. Somewhere we have a match between > > > > controller_id and dp->id in the code. > > > > > > That number (the 0, not INTF_0) is what the code matches against dp->id > > > in _dpu_kms_initialize_displayport(), in order to figure out that this > > > is INTF_0 in dpu_encoder_setup_display(). > > > > > > I.e. look at the sc8180x patch: > > > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, > > > MDP_SSPP_TOP0_INTR, 24, 25), > > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, > > > MDP_SSPP_TOP0_INTR, 26, 27), > > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, > > > MDP_SSPP_TOP0_INTR, 28, 29), > > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until > > > this is supported */ > > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC8180X_MASK, > > > MDP_SSPP_TOP0_INTR, 30, 31), > > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, > > > MDP_SSPP_TOP0_INTR, 20, 21), > > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, > > > MDP_SSPP_TOP0_INTR, 22, 23), > > > > > > Where the DP driver defines the 3 controllers with dp->id of 0, 1 and 2, > > > which the DPU code will match against to INTF_0, INTF_4 and INTF_5. > > > > > > > Yep. I'm saying that having to make that number in this intf array match > > the order of the register mapping descriptor array is fragile. Why can't > > we indicate the interface is DP or eDP with INTF_DP or INTF_EDP and then > > map from the descriptor array to this intf array somehow so that the > > order of the descriptor array doesn't matter? Then we don't have to put > > the connector type in the descriptor array, and we don't have to keep > > the order of the array a certain way to match this intf descriptor. > > > > Maybe > > > > struct msm_dp_desc { > > phys_addr_t io_start; > > unsigned int id; > > The INTF_ constants are a property of
Re: [RFC 6/8] drm/i915: Make some recently added vfuncs use full scheduling attribute
On Mon, Oct 04, 2021 at 03:36:48PM +0100, Tvrtko Ursulin wrote: > From: Tvrtko Ursulin > > Code added in 71ed60112d5d ("drm/i915: Add kick_backend function to > i915_sched_engine") and ee242ca704d3 ("drm/i915/guc: Implement GuC > priority management") introduced some scheduling related vfuncs which > take integer request priority as argument. > > Make them instead take struct i915_sched_attr, which is the type > encapsulating this information, so it probably aligns with the design > better. It definitely enables extending the set of scheduling attributes. > Understand the motivation here but the i915_scheduler is going to disapear when we move to the DRM scheduler or at least its functionality of priority inheritance will be pushed into the DRM scheduler. I'd be very careful making any changes here as the priority in the DRM scheduler is defined as single enum: /* These are often used as an (initial) index * to an array, and as such should start at 0. */ enum drm_sched_priority { DRM_SCHED_PRIORITY_MIN, DRM_SCHED_PRIORITY_NORMAL, DRM_SCHED_PRIORITY_HIGH, DRM_SCHED_PRIORITY_KERNEL, DRM_SCHED_PRIORITY_COUNT, DRM_SCHED_PRIORITY_UNSET = -2 }; Adding a field to the i915_sched_attr is fairly easy as we already have a structure but changing the DRM scheduler might be a tougher sell. Anyway you can make this work without adding the 'nice' field to i915_sched_attr? Might be worth exploring so when we move to the DRM scheduler this feature drops in a little cleaner. Matt > Signed-off-by: Tvrtko Ursulin > Cc: Matthew Brost > Cc: Daniele Ceraolo Spurio > --- > drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 4 +++- > drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c| 3 ++- > drivers/gpu/drm/i915/i915_scheduler.c| 4 ++-- > drivers/gpu/drm/i915/i915_scheduler_types.h | 4 ++-- > 4 files changed, 9 insertions(+), 6 deletions(-) > > diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > index 7147fe80919e..e91d803a6453 100644 > --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c > @@ -3216,11 +3216,13 @@ static bool can_preempt(struct intel_engine_cs > *engine) > return engine->class != RENDER_CLASS; > } > > -static void kick_execlists(const struct i915_request *rq, int prio) > +static void kick_execlists(const struct i915_request *rq, > +const struct i915_sched_attr *attr) > { > struct intel_engine_cs *engine = rq->engine; > struct i915_sched_engine *sched_engine = engine->sched_engine; > const struct i915_request *inflight; > + const int prio = attr->priority; > > /* >* We only need to kick the tasklet once for the high priority > diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > index ba0de35f6323..b5883a4365ca 100644 > --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c > @@ -2414,9 +2414,10 @@ static void guc_init_breadcrumbs(struct > intel_engine_cs *engine) > } > > static void guc_bump_inflight_request_prio(struct i915_request *rq, > -int prio) > +const struct i915_sched_attr *attr) > { > struct intel_context *ce = rq->context; > + const int prio = attr->priority; > u8 new_guc_prio = map_i915_prio_to_guc_prio(prio); > > /* Short circuit function */ > diff --git a/drivers/gpu/drm/i915/i915_scheduler.c > b/drivers/gpu/drm/i915/i915_scheduler.c > index 762127dd56c5..534bab99fcdc 100644 > --- a/drivers/gpu/drm/i915/i915_scheduler.c > +++ b/drivers/gpu/drm/i915/i915_scheduler.c > @@ -255,7 +255,7 @@ static void __i915_schedule(struct i915_sched_node *node, > > /* Must be called before changing the nodes priority */ > if (sched_engine->bump_inflight_request_prio) > - sched_engine->bump_inflight_request_prio(from, prio); > + sched_engine->bump_inflight_request_prio(from, attr); > > WRITE_ONCE(node->attr.priority, prio); > > @@ -280,7 +280,7 @@ static void __i915_schedule(struct i915_sched_node *node, > > /* Defer (tasklet) submission until after all of our updates. */ > if (sched_engine->kick_backend) > - sched_engine->kick_backend(node_to_request(node), prio); > + sched_engine->kick_backend(node_to_request(node), attr); > } > > spin_unlock(_engine->lock); > diff --git a/drivers/gpu/drm/i915/i915_scheduler_types.h > b/drivers/gpu/drm/i915/i915_scheduler_types.h > index b0a1b58c7893..24b9ac1c2ce2 100644 > --- a/drivers/gpu/drm/i915/i915_scheduler_types.h > +++ b/drivers/gpu/drm/i915/i915_scheduler_types.h
Re: [PATCH] drm/i915/pmu: Connect engine busyness stats from GuC to pmu
On Wed, Oct 06, 2021 at 09:22:42AM +0100, Tvrtko Ursulin wrote: > > On 06/10/2021 00:14, Matthew Brost wrote: > > On Tue, Oct 05, 2021 at 10:47:11AM -0700, Umesh Nerlige Ramappa wrote: > > > With GuC handling scheduling, i915 is not aware of the time that a > > > context is scheduled in and out of the engine. Since i915 pmu relies on > > > this info to provide engine busyness to the user, GuC shares this info > > > with i915 for all engines using shared memory. For each engine, this > > > info contains: > > > > > > - total busyness: total time that the context was running (total) > > > - id: id of the running context (id) > > > - start timestamp: timestamp when the context started running (start) > > > > > > At the time (now) of sampling the engine busyness, if the id is valid > > > (!= ~0), and start is non-zero, then the context is considered to be > > > active and the engine busyness is calculated using the below equation > > > > > > engine busyness = total + (now - start) > > > > > > All times are obtained from the gt clock base. For inactive contexts, > > > engine busyness is just equal to the total. > > > > > > The start and total values provided by GuC are 32 bits and wrap around > > > in a few minutes. Since perf pmu provides busyness as 64 bit > > > monotonically increasing values, there is a need for this implementation > > > to account for overflows and extend the time to 64 bits before returning > > > busyness to the user. In order to do that, a worker runs periodically at > > > frequency = 1/8th the time it takes for the timestamp to wrap. As an > > > example, that would be once in 27 seconds for a gt clock frequency of > > > 19.2 MHz. > > > > > > Opens and wip that are targeted for later patches: > > > > > > 1) On global gt reset the total busyness of engines resets and i915 > > > needs to fix that so that user sees monotonically increasing > > > busyness. > > > 2) In runtime suspend mode, the worker may not need to be run. We could > > > stop the worker on suspend and rerun it on resume provided that the > > > guc pm timestamp does not tick during suspend. > > > > > > Note: > > > There might be an overaccounting of busyness due to the fact that GuC > > > may be updating the total and start values while kmd is reading them. > > > (i.e kmd may read the updated total and the stale start). In such a > > > case, user may see higher busyness value followed by smaller ones which > > > would eventually catch up to the higher value. > > > > > > v2: (Tvrtko) > > > - Include details in commit message > > > - Move intel engine busyness function into execlist code > > > - Use union inside engine->stats > > > - Use natural type for ping delay jiffies > > > - Drop active_work condition checks > > > - Use for_each_engine if iterating all engines > > > - Drop seq locking, use spinlock at guc level to update engine stats > > > - Document worker specific details > > > > > > v3: (Tvrtko/Umesh) > > > - Demarcate guc and execlist stat objects with comments > > > - Document known over-accounting issue in commit > > > - Provide a consistent view of guc state > > > - Add hooks to gt park/unpark for guc busyness > > > - Stop/start worker in gt park/unpark path > > > - Drop inline > > > - Move spinlock and worker inits to guc initialization > > > - Drop helpers that are called only once > > > > > > Signed-off-by: John Harrison > > > Signed-off-by: Umesh Nerlige Ramappa > > > --- > > > drivers/gpu/drm/i915/gt/intel_engine_cs.c | 26 +- > > > drivers/gpu/drm/i915/gt/intel_engine_types.h | 90 +-- > > > .../drm/i915/gt/intel_execlists_submission.c | 32 +++ > > > drivers/gpu/drm/i915/gt/intel_gt_pm.c | 2 + > > > .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 + > > > drivers/gpu/drm/i915/gt/uc/intel_guc.h| 26 ++ > > > drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c| 21 ++ > > > drivers/gpu/drm/i915/gt/uc/intel_guc_ads.h| 5 + > > > drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 13 + > > > .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 227 ++ > > > .../gpu/drm/i915/gt/uc/intel_guc_submission.h | 2 + > > > drivers/gpu/drm/i915/i915_reg.h | 2 + > > > 12 files changed, 398 insertions(+), 49 deletions(-) > > > > > > diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > b/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > index 2ae57e4656a3..6fcc70a313d9 100644 > > > --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c > > > @@ -1873,22 +1873,6 @@ void intel_engine_dump(struct intel_engine_cs > > > *engine, > > > intel_engine_print_breadcrumbs(engine, m); > > > } > > > -static ktime_t __intel_engine_get_busy_time(struct intel_engine_cs > > > *engine, > > > - ktime_t *now) > > > -{ > > > - ktime_t total = engine->stats.total; > > > - > > > - /* > > > - * If the engine is executing something
RE: [PATCH i-g-t 1/1] tests/i915_pxp: Use ioctl_wrapper for DRM_IOCTL_PRIME_HANDLE_TO_FD
>-Original Message- >From: Teres Alexis, Alan Previn >Sent: Wednesday, October 6, 2021 12:52 PM >To: igt-...@lists.freedesktop.org >Cc: Teres Alexis, Alan Previn ; dri- >de...@lists.freedesktop.org; Ruhl; Ruhl, Michael J >; Vivi, Rodrigo >Subject: [PATCH i-g-t 1/1] tests/i915_pxp: Use ioctl_wrapper for >DRM_IOCTL_PRIME_HANDLE_TO_FD > >Replace private helper with call to ioctl_wrapper for >DRM_IOCTL_PRIME_HANDLE_TO_FD. Reviewed-by: Michael J. Ruhl M >Signed-off-by: Alan Previn >--- > tests/i915/gem_pxp.c | 20 +--- > 1 file changed, 1 insertion(+), 19 deletions(-) > >diff --git a/tests/i915/gem_pxp.c b/tests/i915/gem_pxp.c >index 79040165..0430f4b8 100644 >--- a/tests/i915/gem_pxp.c >+++ b/tests/i915/gem_pxp.c >@@ -622,23 +622,6 @@ static void test_render_pxp_protsrc_to_protdest(int >i915) > buf_ops_destroy(bops); > } > >-static int export_handle(int fd, uint32_t handle, int *outfd) >-{ >- struct drm_prime_handle args; >- int ret; >- >- args.handle = handle; >- args.flags = DRM_CLOEXEC; >- args.fd = -1; >- >- ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, ); >- if (ret) >- ret = errno; >- *outfd = args.fd; >- >- return ret; >-} >- > static void test_pxp_dmabuffshare_refcnt(void) > { > uint32_t ctx[2], sbo[2], dbo[2]; >@@ -659,8 +642,7 @@ static void test_pxp_dmabuffshare_refcnt(void) > dbo[0] = alloc_and_fill_dest_buff(fd[0], true, >TSTSURF_SIZE, > >TSTSURF_INITCOLOR1); > } else { >- ret = export_handle(fd[0], dbo[0], _fd); >- igt_assert(ret == 0); >+ dmabuf_fd = prime_handle_to_fd(fd[0], dbo[0]); > dbo[1] = prime_fd_to_handle(fd[1], dmabuf_fd); > igt_assert(dbo[1]); > } >-- >2.25.1
Re: [PATCH v4 5/7] drm/msm/dp: Support up to 3 DP controllers
On Tue 05 Oct 21:26 PDT 2021, Stephen Boyd wrote: > Quoting Bjorn Andersson (2021-10-05 19:37:52) > > On Tue 05 Oct 19:06 PDT 2021, Stephen Boyd wrote: > > > > > Quoting Bjorn Andersson (2021-10-05 18:43:16) > > > > On Tue 05 Oct 17:43 PDT 2021, Stephen Boyd wrote: > > > > > > > > > Quoting Bjorn Andersson (2021-10-05 16:13:21) > > > > > > diff --git a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > index bdaf227f05dc..674cddfee5b0 100644 > > > > > > --- a/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > +++ b/drivers/gpu/drm/msm/dp/dp_display.c > > > > > > @@ -1233,7 +1239,7 @@ static int dp_display_probe(struct > > > > > > platform_device *pdev) > > > > > > if (!dp) > > > > > > return -ENOMEM; > > > > > > > > > > > > - desc = dp_display_get_desc(pdev); > > > > > > + desc = dp_display_get_desc(pdev, >id); > > > > > > > > > > I'm sad that dp->id has to match the number in the SoC specific > > > > > dpu_intf_cfg array in drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c > > > > > still. Is there any way we can avoid that? Also, notice how those > > > > > arrays > > > > > already have INTF_DP macros, which makes me think that it may be > > > > > better > > > > > to connect this to those arrays instead of making an msm_dp_desc > > > > > structure and then make sure the 'type' member matches a connector > > > > > type number. Otherwise this code is super fragile. > > > > > > > > > > > > > I'm afraid I don't understand what you're proposing. Or which part you > > > > consider fragile, the indices of the INTF_DP instances aren't going to > > > > move around... > > > > > > > > I have N instances of the DP driver that I need to match to N entries > > > > from the platform specific intf array, I need some stable reference > > > > between them. When I started this journey I figured I could rely on the > > > > of_graph between the DPU and the interface controllers, but the values > > > > used there today are just bogus, so that was a no go. > > > > > > > > We can use whatever, as long as _dpu_kms_initialize_displayport() can > > > > come up with an identifier to put in h_tile_instance[0] so that > > > > dpu_encoder_setup_display() can find the relevant INTF. > > > > > > > > > > To make it more concrete we can look at sc7180 > > > > > > static const struct dpu_intf_cfg sc7180_intf[] = { > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, > > > INTF_SC7180_MASK, MDP_SSPP_TOP0_INTR, 24, 25), > > > ^ > > > | > > > > > > intf0 is irrelevant. Also the address is irrelevant. But here we have a > > > zero, the number after INTF_DP, and that is very relevant. That number > > > needs to match the dp->id. Somewhere we have a match between > > > controller_id and dp->id in the code. > > > > That number (the 0, not INTF_0) is what the code matches against dp->id > > in _dpu_kms_initialize_displayport(), in order to figure out that this > > is INTF_0 in dpu_encoder_setup_display(). > > > > I.e. look at the sc8180x patch: > > > > INTF_BLK("intf_0", INTF_0, 0x6A000, INTF_DP, 0, 24, INTF_SC8180X_MASK, > > MDP_SSPP_TOP0_INTR, 24, 25), > > INTF_BLK("intf_1", INTF_1, 0x6A800, INTF_DSI, 0, 24, INTF_SC8180X_MASK, > > MDP_SSPP_TOP0_INTR, 26, 27), > > INTF_BLK("intf_2", INTF_2, 0x6B000, INTF_DSI, 1, 24, INTF_SC8180X_MASK, > > MDP_SSPP_TOP0_INTR, 28, 29), > > /* INTF_3 is for MST, wired to INTF_DP 0 and 1, use dummy index until this > > is supported */ > > INTF_BLK("intf_3", INTF_3, 0x6B800, INTF_DP, 999, 24, INTF_SC8180X_MASK, > > MDP_SSPP_TOP0_INTR, 30, 31), > > INTF_BLK("intf_4", INTF_4, 0x6C000, INTF_DP, 1, 24, INTF_SC8180X_MASK, > > MDP_SSPP_TOP0_INTR, 20, 21), > > INTF_BLK("intf_5", INTF_5, 0x6C800, INTF_DP, 2, 24, INTF_SC8180X_MASK, > > MDP_SSPP_TOP0_INTR, 22, 23), > > > > Where the DP driver defines the 3 controllers with dp->id of 0, 1 and 2, > > which the DPU code will match against to INTF_0, INTF_4 and INTF_5. > > > > Yep. I'm saying that having to make that number in this intf array match > the order of the register mapping descriptor array is fragile. Why can't > we indicate the interface is DP or eDP with INTF_DP or INTF_EDP and then > map from the descriptor array to this intf array somehow so that the > order of the descriptor array doesn't matter? Then we don't have to put > the connector type in the descriptor array, and we don't have to keep > the order of the array a certain way to match this intf descriptor. > > Maybe > > struct msm_dp_desc { > phys_addr_t io_start; > unsigned int id; The INTF_ constants are a property of the DPU driver and not available in the DP driver and the msm_dp struct is a property of the DP driver and can't be dereferenced in the DPU driver. The proposed way around this is that the descs array defines the order in priv->dp[N] and this N is used
[PATCH i-g-t 1/1] tests/i915_pxp: Use ioctl_wrapper for DRM_IOCTL_PRIME_HANDLE_TO_FD
Replace private helper with call to ioctl_wrapper for DRM_IOCTL_PRIME_HANDLE_TO_FD. Signed-off-by: Alan Previn --- tests/i915/gem_pxp.c | 20 +--- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/tests/i915/gem_pxp.c b/tests/i915/gem_pxp.c index 79040165..0430f4b8 100644 --- a/tests/i915/gem_pxp.c +++ b/tests/i915/gem_pxp.c @@ -622,23 +622,6 @@ static void test_render_pxp_protsrc_to_protdest(int i915) buf_ops_destroy(bops); } -static int export_handle(int fd, uint32_t handle, int *outfd) -{ - struct drm_prime_handle args; - int ret; - - args.handle = handle; - args.flags = DRM_CLOEXEC; - args.fd = -1; - - ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, ); - if (ret) - ret = errno; - *outfd = args.fd; - - return ret; -} - static void test_pxp_dmabuffshare_refcnt(void) { uint32_t ctx[2], sbo[2], dbo[2]; @@ -659,8 +642,7 @@ static void test_pxp_dmabuffshare_refcnt(void) dbo[0] = alloc_and_fill_dest_buff(fd[0], true, TSTSURF_SIZE, TSTSURF_INITCOLOR1); } else { - ret = export_handle(fd[0], dbo[0], _fd); - igt_assert(ret == 0); + dmabuf_fd = prime_handle_to_fd(fd[0], dbo[0]); dbo[1] = prime_fd_to_handle(fd[1], dmabuf_fd); igt_assert(dbo[1]); } -- 2.25.1
Re: [PATCH 3/8] drm/i915: Disable tracing points on PREEMPT_RT
On 2021-10-06 12:15:21 [+0200], To Ville Syrjälä wrote: > On 2021-10-06 12:34:19 [+0300], Ville Syrjälä wrote: > > I think the correct answer is to make uncore.lock a raw_spinlock. > > Without the tracepoints deubgging any of this is stuff pretty much > > impossible. We also take that lock a lot. > > Let me check if that works. Turned the uncore.lock into raw_spinlock_t, the debug.lock as well because it nests inside the former. Also intel_uncore_forcewake_domain::timer fires now in hardirq since it almost only acquires the uncore.lock. What worries me a little is the fw_domain_wait_ack_clear() / wait_ack_clear() which spin-waits up a whole ms. __gen6_gt_wait_for_thread_c0() has a 5ms limit and wait_ack_clear() has 50ms as upper limit. I know that it does not usually take long and if it takes that long than it is an error most likely but still... The full patch at the end of the email. Now. Before that patch: | T: 0 ( 1179) P:90 I:250 C: 182450 Min: 2 Act:6 Avg:5 Max: 21 | T: 1 ( 1180) P:90 I:250 C: 182437 Min: 2 Act:6 Avg:5 Max: 22 | T: 2 ( 1181) P:90 I:250 C: 182423 Min: 2 Act:6 Avg:5 Max: 23 | T: 3 ( 1182) P:90 I:250 C: 182401 Min: 2 Act:6 Avg:5 Max: 21 | T: 4 ( 1183) P:90 I:250 C: 182394 Min: 2 Act:7 Avg:5 Max: 27 | T: 5 ( 1184) P:90 I:250 C: 182381 Min: 2 Act:6 Avg:5 Max: 22 | T: 6 ( 1185) P:90 I:250 C: 182368 Min: 3 Act:6 Avg:5 Max: 23 | T: 7 ( 1186) P:90 I:250 C: 182356 Min: 2 Act:8 Avg:5 Max: 22 after: | T: 0 ( 1183) P:90 I:250 C:1022143 Min: 3 Act:3 Avg:4 Max: 47 | T: 1 ( 1184) P:90 I:250 C:1022125 Min: 2 Act:3 Avg:4 Max: 51 | T: 2 ( 1185) P:90 I:250 C:1022110 Min: 2 Act:5 Avg:4 Max: 52 | T: 3 ( 1186) P:90 I:250 C:1022089 Min: 2 Act:3 Avg:4 Max: 52 | T: 4 ( 1187) P:90 I:250 C:1022083 Min: 2 Act:3 Avg:4 Max: 51 | T: 5 ( 1188) P:90 I:250 C:1022070 Min: 3 Act:3 Avg:4 Max: 50 | T: 6 ( 1189) P:90 I:250 C:1022058 Min: 3 Act:5 Avg:4 Max: 46 | T: 7 ( 1190) P:90 I:250 C:1022045 Min: 2 Act:3 Avg:4 Max: 51 This is cyclictest output. A little explanation: T: means thread number. There is one thread pinned to each CPU so I have 8 CPUs. This is an i7 SandyBridge so 4 cores + hyperthread with a built-in i915 (INTEL_SNB_D_GT1_IDS). Max: is the maximal observed latency in us. The program fires a timer every 250us and measures the latency between the programmed time and now. Since it is the thread with the highest priority in the system it should be scheduled right away. Unless there is a preempt-disable/IRQ-off section somewhere. I did the same test in both cases: started a video hoping for some HW acceleration and skipped forward / backwards in the clip a few times. As soon as I start jumping in the video the latencies rise. I don't observe it without the patch. The system is idle otherwise. If you have other tests in mind which put more / different load on the system, I'm all yours. I'm mostly curious how bad can it get. Sebastian diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index b1439ba78f67b..6f2cab95d8646 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -444,7 +444,7 @@ static void i9xx_update_plane(struct intel_plane *plane, else dspaddr_offset = linear_offset; - spin_lock_irqsave(_priv->uncore.lock, irqflags); + raw_spin_lock_irqsave(_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), plane_state->view.color_plane[0].stride); @@ -490,7 +490,7 @@ static void i9xx_update_plane(struct intel_plane *plane, intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - spin_unlock_irqrestore(_priv->uncore.lock, irqflags); + raw_spin_unlock_irqrestore(_priv->uncore.lock, irqflags); } static void i9xx_disable_plane(struct intel_plane *plane, @@ -513,7 +513,7 @@ static void i9xx_disable_plane(struct intel_plane *plane, */ dspcntr = i9xx_plane_ctl_crtc(crtc_state); - spin_lock_irqsave(_priv->uncore.lock, irqflags); + raw_spin_lock_irqsave(_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); if (DISPLAY_VER(dev_priv) >= 4) @@ -521,7 +521,7 @@ static void i9xx_disable_plane(struct intel_plane *plane, else intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); - spin_unlock_irqrestore(_priv->uncore.lock, irqflags); + raw_spin_unlock_irqrestore(_priv->uncore.lock, irqflags); } static void @@ -539,11 +539,11 @@ g4x_primary_async_flip(struct intel_plane *plane, if
Re: [Nouveau] [PATCH v3 2/5] drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for aux enable/brightness
On Wed, Oct 6, 2021 at 4:41 AM Lyude Paul wrote: > > 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) && where does the DP_EDP_BACKLIGHT_AUX_ENABLE_CAP come from? afaik drm_edp_backlight_supported checks for DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP and DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP so wondering if this was intentional or a typo > + (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] drm/msm/dp: do not initialize combo phy until plugin interrupt
Combo phy support both USB3 and DP simultaneously. USB3 is the master of combo phy so that USB3 should initialize and power on its phy before DP initialize its phy. At current implementation, DP driver initialize its phy happen earlier than USB3 initialize its phy which cause timeout error at procedure of power up USB3 phy which prevent USB3 from working. To avoid confliction of phy initialization between USB3 and DP, this patch have DP driver postpone phy initialization until plugin interrupt handler. DP driver only enable regulator, configure its HPD controller and enable interrupt so that it is able to receive HPD interrupts after completion of the initialization phase. DP driver will initialize and power up phy at plugin interrupt handler during normal operation so that both USB3 and DP are work simultaneously. Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_ctrl.c| 68 ++--- drivers/gpu/drm/msm/dp/dp_ctrl.h| 9 +++-- drivers/gpu/drm/msm/dp/dp_display.c | 51 +--- 3 files changed, 84 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c index 5551a8d..4c5d507 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c @@ -1378,7 +1378,25 @@ static int dp_ctrl_enable_stream_clocks(struct dp_ctrl_private *ctrl) return ret; } -int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset) +void dp_ctrl_irq_enable(struct dp_ctrl *dp_ctrl, bool flip) +{ + struct dp_ctrl_private *ctrl; + + if (!dp_ctrl) { + DRM_ERROR("Invalid input data\n"); + return; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + + ctrl->dp_ctrl.orientation = flip; + + dp_catalog_ctrl_reset(ctrl->catalog); + + dp_catalog_ctrl_enable_irq(ctrl->catalog, true); +} + +void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; @@ -1386,33 +1404,44 @@ int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset) if (!dp_ctrl) { DRM_ERROR("Invalid input data\n"); - return -EINVAL; + return; } ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); dp_io = >parser->io; phy = dp_io->phy; - ctrl->dp_ctrl.orientation = flip; - - if (reset) - dp_catalog_ctrl_reset(ctrl->catalog); - dp_catalog_ctrl_phy_reset(ctrl->catalog); phy_init(phy); - dp_catalog_ctrl_enable_irq(ctrl->catalog, true); +} - return 0; +void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl) +{ + struct dp_ctrl_private *ctrl; + struct dp_io *dp_io; + struct phy *phy; + + if (!dp_ctrl) { + DRM_ERROR("Invalid input data\n"); + return; + } + + ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); + dp_io = >parser->io; + phy = dp_io->phy; + + dp_catalog_ctrl_phy_reset(ctrl->catalog); + phy_exit(phy); } /** - * dp_ctrl_host_deinit() - Uninitialize DP controller + * dp_ctrl_irq_phy_exit() - disable dp irq and exit phy * @dp_ctrl: Display Port Driver data * * Perform required steps to uninitialize DP controller * and its resources. */ -void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl) +void dp_ctrl_irq_phy_exit(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; struct dp_io *dp_io; @@ -1866,23 +1895,6 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl) return ret; } -void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl) -{ - struct dp_ctrl_private *ctrl; - struct dp_io *dp_io; - struct phy *phy; - - ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl); - dp_io = >parser->io; - phy = dp_io->phy; - - dp_catalog_ctrl_reset(ctrl->catalog); - - phy_exit(phy); - - DRM_DEBUG_DP("DP off phy done\n"); -} - int dp_ctrl_off(struct dp_ctrl *dp_ctrl) { struct dp_ctrl_private *ctrl; diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h index 2363a2d..c1e4b1b 100644 --- a/drivers/gpu/drm/msm/dp/dp_ctrl.h +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h @@ -19,12 +19,9 @@ struct dp_ctrl { u32 pixel_rate; }; -int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset); -void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl); int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl); int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl); -void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl); int dp_ctrl_off(struct dp_ctrl *dp_ctrl); void dp_ctrl_push_idle(struct dp_ctrl *dp_ctrl); void dp_ctrl_isr(struct dp_ctrl *dp_ctrl); @@ -34,4 +31,10 @@ struct dp_ctrl *dp_ctrl_get(struct device *dev, struct dp_link *link, struct dp_power