[Intel-gfx] [PATCH 6/6] drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v9

Chris Wilson chris at chris-wilson.co.uk
Wed Feb 5 19:14:15 CET 2014


On Wed, Feb 05, 2014 at 05:30:48PM +0000, Jesse Barnes wrote:
> +static bool intel_fbdev_init_bios(struct drm_device *dev,
> +				 struct intel_fbdev *ifbdev)
> +{
> +	struct intel_framebuffer *fb = NULL;
> +	struct drm_crtc *crtc;
> +	struct intel_crtc *intel_crtc;
> +	struct intel_plane_config *plane_config = NULL;
> +	unsigned int last_size = 0, max_size = 0, tmp;
> +
> +	/* Find the largest framebuffer to use, then free the others */
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> +		intel_crtc = to_intel_crtc(crtc);
> +
> +		if (!intel_crtc->active || !intel_crtc->plane_config.fb) {
> +			DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
> +				      pipe_name(intel_crtc->pipe));
> +			continue;
> +		}
> +
> +		tmp = intel_crtc->config.adjusted_mode.crtc_hdisplay *
> +			intel_crtc->config.adjusted_mode.crtc_vdisplay *
> +			intel_crtc->plane_config.fb->base.pitches[0];

This reads as width * height * stride. I presume you meant bpp/8 here,
but since we keep the fb and its pitch intact, you need height * stride.
Actually, it preserves a completely different fb, so this estimate of
size is incomplete.

> +		max_size = max(max_size, tmp);
> +
> +		/*
> +		 * Make sure the fb will fit the biggest active pipe.  If
> +		 * not, clear out any previous usage.
> +		 */
> +		if (intel_crtc->plane_config.size > last_size &&
> +		    intel_crtc->plane_config.size >= max_size) {
> +			plane_config = &intel_crtc->plane_config;
> +			last_size = plane_config->size;
> +			fb = plane_config->fb;
> +		} else {
> +			plane_config = NULL;
> +			fb = NULL;
> +		}

Two CRTCs sharing a plane_config will now end up with plane_config/fb =
NULL, and so bail out. This is confusing me. If we here just found the
largest fb and then did a second pass confirming that all CRTC and planes
fitted into it, I would find it easier to understand.

> +	}
> +
> +	/* Free unused fbs */
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> +		struct intel_framebuffer *cur_fb;
> +
> +		intel_crtc = to_intel_crtc(crtc);
> +		cur_fb = intel_crtc->plane_config.fb;
> +
> +		if (cur_fb && cur_fb != fb)
> +			intel_framebuffer_fini(cur_fb);
> +	}
> +
> +	if (!fb) {
> +		DRM_DEBUG_KMS("no active pipes found, not using BIOS config\n");
> +		goto out;
> +	}
> +
> +	ifbdev->preferred_bpp = plane_config->fb->base.bits_per_pixel;
> +	ifbdev->helper.funcs = &intel_fb_helper_funcs;
> +	ifbdev->helper.funcs->initial_config = intel_fb_initial_config;
> +	ifbdev->fb = fb;
> +
> +	/* Assuming a single fb across all pipes here */
> +	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> +		intel_crtc = to_intel_crtc(crtc);
> +
> +		if (!intel_crtc->active)
> +			continue;
> +
> +		/*
> +		 * This should only fail on the first one so we don't need
> +		 * to cleanup any secondary crtc->fbs
> +		 */
> +		if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL))
> +			goto out_unref_obj;
> +
> +		crtc->fb = &fb->base;
> +		drm_gem_object_reference(&fb->obj->base);
> +		drm_framebuffer_reference(&fb->base);
> +	}
> +
> +	DRM_DEBUG_KMS("using BIOS fb for initial console\n");
> +	return true;

Somewhere around here we must disable all CRTCs that are active and have
no fb.

> +
> +out_unref_obj:
> +	intel_framebuffer_fini(fb);
> +out:
> +
> +	return false;
> +}
> +
>  int intel_fbdev_init(struct drm_device *dev)
>  {
>  	struct intel_fbdev *ifbdev;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  	int ret;

A useful assertion here would be:

if (WARN_ON(INTEL_INFO(dev)->num_pipes == 0)) return -ENODEV;

> -	ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);
> -	if (!ifbdev)
> +	ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
> +	if (ifbdev == NULL)
>  		return -ENOMEM;
>  
> -	dev_priv->fbdev = ifbdev;
>  	ifbdev->helper.funcs = &intel_fb_helper_funcs;
> +	dev_priv->fbdev = ifbdev;
> +
> +	if (!i915.fastboot || !intel_fbdev_init_bios(dev, ifbdev))
> +		ifbdev->preferred_bpp = 32;

Bikeshed: move i915.fastboot to intel_fbdev_init_bios and rearrange like

  if (!intel_fbdev_init(intel_fbdev_init_bios(dev, ifbdev)) {
    ifbdev->helper.funcs = &intel_fb_helper_funcs;
    ifbdev->preferred_bpp = 32;
  }

  (then dev_priv->fbdev = ifbdev can be done last on success as before)

>  
>  	ret = drm_fb_helper_init(dev, &ifbdev->helper,
> -				 INTEL_INFO(dev)->num_pipes,
> -				 4);
> +				 INTEL_INFO(dev)->num_pipes, 4);
>  	if (ret) {
> +		dev_priv->fbdev = NULL;
>  		kfree(ifbdev);
>  		return ret;
>  	}

>  void intel_fbdev_restore_mode(struct drm_device *dev)
> @@ -441,7 +546,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
>  	int ret;
>  	struct drm_i915_private *dev_priv = dev->dev_private;
>  
> -	if (INTEL_INFO(dev)->num_pipes == 0)
> +	if (INTEL_INFO(dev)->num_pipes == 0 || !dev_priv->fbdev)

num_pipes == 0 => dev_priv->fbdev == NULL
ergo this can be reduced to just
if (dev_priv->fbdev == NULL)
>  		return;
>  
>  	drm_modeset_lock_all(dev);

-- 
Chris Wilson, Intel Open Source Technology Centre



More information about the Intel-gfx mailing list