Message ID | y6eB32gmEqaxWjTJ5Xeb33BRE6M67fCwhmj06MMh6o@cp3-web-021.plabs.ch (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm: add more primary/cursor plane checks | expand |
On Fri, 11 Dec 2020, Simon Ser <contact@emersion.fr> wrote: > User-space expects to be able to pick a primary plane for each CRTC > exposed by the driver. Make sure this assumption holds in > drm_mode_config_validate. > > Use the legacy drm_crtc.primary field to check this, because it's > simpler and we require drivers to set it anyways. Accumulate a set of > primary planes which are already used for a CRTC in a bitmask. Error out > if a primary plane is re-used. > > Signed-off-by: Simon Ser <contact@emersion.fr> > Cc: Daniel Vetter <daniel@ffwll.ch> > Cc: Pekka Paalanen <ppaalanen@gmail.com> > --- > drivers/gpu/drm/drm_mode_config.c | 21 +++++++++++++++++++++ > drivers/gpu/drm/drm_plane.c | 6 ++++++ > 2 files changed, 27 insertions(+) > > diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c > index fbe680035129..f143f56f0820 100644 > --- a/drivers/gpu/drm/drm_mode_config.c > +++ b/drivers/gpu/drm/drm_mode_config.c > @@ -626,6 +626,9 @@ void drm_mode_config_validate(struct drm_device *dev) > { > struct drm_encoder *encoder; > struct drm_crtc *crtc; > + struct drm_plane *plane; > + __u64 primary_with_crtc = 0, cursor_with_crtc = 0; Why __u64 and not u64? > + unsigned num_primary = 0; I think the preference is to spell out the full type instead of using just "unsigned". BR, Jani. > > if (!drm_core_check_feature(dev, DRIVER_MODESET)) > return; > @@ -647,12 +650,30 @@ void drm_mode_config_validate(struct drm_device *dev) > "Bogus primary plane possible_crtcs: [PLANE:%d:%s] must be compatible with [CRTC:%d:%s]\n", > crtc->primary->base.id, crtc->primary->name, > crtc->base.id, crtc->name); > + WARN(primary_with_crtc & BIT(crtc->primary->index), > + "Primary plane [PLANE:%d:%s] used for two CRTCs", > + crtc->primary->base.id, crtc->primary->name); > + primary_with_crtc |= BIT(crtc->primary->index); > } > if (crtc->cursor) { > WARN(!(crtc->cursor->possible_crtcs & BIT(crtc->index)), > "Bogus cursor plane possible_crtcs: [PLANE:%d:%s] must be compatible with [CRTC:%d:%s]\n", > crtc->cursor->base.id, crtc->cursor->name, > crtc->base.id, crtc->name); > + WARN(cursor_with_crtc & BIT(crtc->cursor->index), > + "Primary plane [PLANE:%d:%s] used for two CRTCs", > + crtc->cursor->base.id, crtc->cursor->name); > + cursor_with_crtc |= BIT(crtc->cursor->index); > } > } > + > + drm_for_each_plane(plane, dev) { > + if (plane->type == DRM_PLANE_TYPE_PRIMARY) { > + num_primary++; > + } > + } > + > + WARN(num_primary != dev->mode_config.num_crtc, > + "Must have as many primary planes as there are CRTCs, but have %u primary planes and %u CRTCs", > + num_primary, dev->mode_config.num_crtc); > } > diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c > index 49b0a8b9ac02..a1f4510efa83 100644 > --- a/drivers/gpu/drm/drm_plane.c > +++ b/drivers/gpu/drm/drm_plane.c > @@ -54,6 +54,12 @@ > * enum drm_plane_type). A plane can be compatible with multiple CRTCs, see > * &drm_plane.possible_crtcs. > * > + * Each CRTC must have a unique primary plane userspace can attach to enable > + * the CRTC. In other words, userspace must be able to attach a different > + * primary plane to each CRTC at the same time. Primary planes can still be > + * compatible with multiple CRTCs. There must be exactly as many primary planes > + * as there are CRTCs. > + * > * Legacy uAPI doesn't expose the primary and cursor planes directly. DRM core > * relies on the driver to set the primary and optionally the cursor plane used > * for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). All
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index fbe680035129..f143f56f0820 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -626,6 +626,9 @@ void drm_mode_config_validate(struct drm_device *dev) { struct drm_encoder *encoder; struct drm_crtc *crtc; + struct drm_plane *plane; + __u64 primary_with_crtc = 0, cursor_with_crtc = 0; + unsigned num_primary = 0; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return; @@ -647,12 +650,30 @@ void drm_mode_config_validate(struct drm_device *dev) "Bogus primary plane possible_crtcs: [PLANE:%d:%s] must be compatible with [CRTC:%d:%s]\n", crtc->primary->base.id, crtc->primary->name, crtc->base.id, crtc->name); + WARN(primary_with_crtc & BIT(crtc->primary->index), + "Primary plane [PLANE:%d:%s] used for two CRTCs", + crtc->primary->base.id, crtc->primary->name); + primary_with_crtc |= BIT(crtc->primary->index); } if (crtc->cursor) { WARN(!(crtc->cursor->possible_crtcs & BIT(crtc->index)), "Bogus cursor plane possible_crtcs: [PLANE:%d:%s] must be compatible with [CRTC:%d:%s]\n", crtc->cursor->base.id, crtc->cursor->name, crtc->base.id, crtc->name); + WARN(cursor_with_crtc & BIT(crtc->cursor->index), + "Primary plane [PLANE:%d:%s] used for two CRTCs", + crtc->cursor->base.id, crtc->cursor->name); + cursor_with_crtc |= BIT(crtc->cursor->index); } } + + drm_for_each_plane(plane, dev) { + if (plane->type == DRM_PLANE_TYPE_PRIMARY) { + num_primary++; + } + } + + WARN(num_primary != dev->mode_config.num_crtc, + "Must have as many primary planes as there are CRTCs, but have %u primary planes and %u CRTCs", + num_primary, dev->mode_config.num_crtc); } diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 49b0a8b9ac02..a1f4510efa83 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -54,6 +54,12 @@ * enum drm_plane_type). A plane can be compatible with multiple CRTCs, see * &drm_plane.possible_crtcs. * + * Each CRTC must have a unique primary plane userspace can attach to enable + * the CRTC. In other words, userspace must be able to attach a different + * primary plane to each CRTC at the same time. Primary planes can still be + * compatible with multiple CRTCs. There must be exactly as many primary planes + * as there are CRTCs. + * * Legacy uAPI doesn't expose the primary and cursor planes directly. DRM core * relies on the driver to set the primary and optionally the cursor plane used * for legacy IOCTLs. This is done by calling drm_crtc_init_with_planes(). All
User-space expects to be able to pick a primary plane for each CRTC exposed by the driver. Make sure this assumption holds in drm_mode_config_validate. Use the legacy drm_crtc.primary field to check this, because it's simpler and we require drivers to set it anyways. Accumulate a set of primary planes which are already used for a CRTC in a bitmask. Error out if a primary plane is re-used. Signed-off-by: Simon Ser <contact@emersion.fr> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Pekka Paalanen <ppaalanen@gmail.com> --- drivers/gpu/drm/drm_mode_config.c | 21 +++++++++++++++++++++ drivers/gpu/drm/drm_plane.c | 6 ++++++ 2 files changed, 27 insertions(+)