1
0
Fork 0
alistair23-linux/drivers/gpu/drm/i915/display/intel_fbdev.c

634 lines
17 KiB
C
Raw Normal View History

/*
* Copyright © 2007 David Airlie
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* David Airlie
*/
#include <linux/async.h>
#include <linux/console.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
vga_switcheroo: initial implementation (v15) Many new laptops now come with 2 gpus, one to be used for low power modes and one for gaming/on-ac applications. These GPUs are typically wired to the laptop panel and VGA ports via a multiplexer unit which is controlled via ACPI methods. 4 combinations of systems typically exist - with 2 ACPI methods. Intel/ATI - Lenovo W500/T500 - use ATPX ACPI method ATI/ATI - some ASUS - use ATPX ACPI Method Intel/Nvidia - - use _DSM ACPI method Nvidia/Nvidia - - use _DSM ACPI method. TODO: This patch adds support for the ATPX method and initial bits for the _DSM methods that need to written by someone with access to the hardware. Add a proper non-debugfs interface - need to get some proper testing first. v2: add power up/down support for both devices on W500 puts i915/radeon into D3 and cuts power to radeon. v3: redo probing methods, no DMI list, drm devices call to register with switcheroo, it tries to find an ATPX method on any device and once there is two devices + ATPX it inits the switcher. v4: ATPX msg handling using buffers - should work on more machines v5: rearchitect after more mjg59 discussion - move ATPX handling to radeon driver. v6: add file headers + initial nouveau bits (to be filled out). v7: merge delayed switcher code. v8: avoid suspend/resume of gpu that is off v9: rearchitect - mjg59 is always right. - move all ATPX code to radeon, should allow simpler DSM also proper ATRM handling v10: add ATRM support for radeon BIOS, add mutex to lock vgasr_priv v11: fix bug in resuming Intel for 2nd time. v12: start fixing up nvidia code blindly. v13: blindly guess at finishing nvidia code v14: remove radeon audio hacks - fix up intel resume more like upstream v15: clean up printks + remove unnecessary igd/dis pointers mount debugfs /sys/kernel/debug/vgaswitcheroo/switch - should exist if ATPX detected + 2 cards. DIS - immediate change to discrete IGD - immediate change to IGD DDIS - delayed change to discrete DIGD - delayed change to IGD ON - turn on not in use OFF - turn off not in use Tested on W500 (Intel/ATI) and T500 (Intel/ATI) Signed-off-by: Dave Airlie <airlied@redhat.com>
2010-01-31 22:38:10 -07:00
#include <linux/vga_switcheroo.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_helper.h>
drm: Split out drm_probe_helper.h Having the probe helper stuff (which pretty much everyone needs) in the drm_crtc_helper.h file (which atomic drivers should never need) is confusing. Split them out. To make sure I actually achieved the goal here I went through all drivers. And indeed, all atomic drivers are now free of drm_crtc_helper.h includes. v2: Make it compile. There was so much compile fail on arm drivers that I figured I'll better not include any of the acks on v1. v3: Massive rebase because i915 has lost a lot of drmP.h includes, but not all: Through drm_crtc_helper.h > drm_modeset_helper.h -> drmP.h there was still one, which this patch largely removes. Which means rolling out lots more includes all over. This will also conflict with ongoing drmP.h cleanup by others I expect. v3: Rebase on top of atomic bochs. v4: Review from Laurent for bridge/rcar/omap/shmob/core bits: - (re)move some of the added includes, use the better include files in other places (all suggested from Laurent adopted unchanged). - sort alphabetically v5: Actually try to sort them, and while at it, sort all the ones I touch. v6: Rebase onto i915 changes. v7: Rebase once more. Acked-by: Harry Wentland <harry.wentland@amd.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Acked-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Acked-by: Jani Nikula <jani.nikula@intel.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Acked-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Acked-by: CK Hu <ck.hu@mediatek.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: linux-arm-kernel@lists.infradead.org Cc: virtualization@lists.linux-foundation.org Cc: etnaviv@lists.freedesktop.org Cc: linux-samsung-soc@vger.kernel.org Cc: intel-gfx@lists.freedesktop.org Cc: linux-mediatek@lists.infradead.org Cc: linux-amlogic@lists.infradead.org Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Cc: spice-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-stm32@st-md-mailman.stormreply.com Cc: linux-tegra@vger.kernel.org Cc: xen-devel@lists.xen.org Link: https://patchwork.freedesktop.org/patch/msgid/20190117210334.13234-1-daniel.vetter@ffwll.ch
2019-01-17 14:03:34 -07:00
#include <drm/drm_fourcc.h>
#include <drm/i915_drm.h>
drm: Split out drm_probe_helper.h Having the probe helper stuff (which pretty much everyone needs) in the drm_crtc_helper.h file (which atomic drivers should never need) is confusing. Split them out. To make sure I actually achieved the goal here I went through all drivers. And indeed, all atomic drivers are now free of drm_crtc_helper.h includes. v2: Make it compile. There was so much compile fail on arm drivers that I figured I'll better not include any of the acks on v1. v3: Massive rebase because i915 has lost a lot of drmP.h includes, but not all: Through drm_crtc_helper.h > drm_modeset_helper.h -> drmP.h there was still one, which this patch largely removes. Which means rolling out lots more includes all over. This will also conflict with ongoing drmP.h cleanup by others I expect. v3: Rebase on top of atomic bochs. v4: Review from Laurent for bridge/rcar/omap/shmob/core bits: - (re)move some of the added includes, use the better include files in other places (all suggested from Laurent adopted unchanged). - sort alphabetically v5: Actually try to sort them, and while at it, sort all the ones I touch. v6: Rebase onto i915 changes. v7: Rebase once more. Acked-by: Harry Wentland <harry.wentland@amd.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Cc: Sam Ravnborg <sam@ravnborg.org> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Acked-by: Benjamin Gaignard <benjamin.gaignard@linaro.org> Acked-by: Jani Nikula <jani.nikula@intel.com> Acked-by: Neil Armstrong <narmstrong@baylibre.com> Acked-by: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> Acked-by: CK Hu <ck.hu@mediatek.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Acked-by: Sam Ravnborg <sam@ravnborg.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Liviu Dudau <liviu.dudau@arm.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Cc: linux-arm-kernel@lists.infradead.org Cc: virtualization@lists.linux-foundation.org Cc: etnaviv@lists.freedesktop.org Cc: linux-samsung-soc@vger.kernel.org Cc: intel-gfx@lists.freedesktop.org Cc: linux-mediatek@lists.infradead.org Cc: linux-amlogic@lists.infradead.org Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Cc: nouveau@lists.freedesktop.org Cc: spice-devel@lists.freedesktop.org Cc: amd-gfx@lists.freedesktop.org Cc: linux-renesas-soc@vger.kernel.org Cc: linux-rockchip@lists.infradead.org Cc: linux-stm32@st-md-mailman.stormreply.com Cc: linux-tegra@vger.kernel.org Cc: xen-devel@lists.xen.org Link: https://patchwork.freedesktop.org/patch/msgid/20190117210334.13234-1-daniel.vetter@ffwll.ch
2019-01-17 14:03:34 -07:00
#include "i915_drv.h"
#include "intel_display_types.h"
#include "intel_fbdev.h"
#include "intel_frontbuffer.h"
static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
{
return ifbdev->fb->frontbuffer;
}
static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
{
intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
}
static int intel_fbdev_set_par(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct intel_fbdev *ifbdev =
container_of(fb_helper, struct intel_fbdev, helper);
int ret;
ret = drm_fb_helper_set_par(info);
if (ret == 0)
intel_fbdev_invalidate(ifbdev);
return ret;
}
static int intel_fbdev_blank(int blank, struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct intel_fbdev *ifbdev =
container_of(fb_helper, struct intel_fbdev, helper);
int ret;
ret = drm_fb_helper_blank(blank, info);
if (ret == 0)
intel_fbdev_invalidate(ifbdev);
return ret;
}
static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct intel_fbdev *ifbdev =
container_of(fb_helper, struct intel_fbdev, helper);
int ret;
ret = drm_fb_helper_pan_display(var, info);
if (ret == 0)
intel_fbdev_invalidate(ifbdev);
return ret;
}
static struct fb_ops intelfb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_set_par = intel_fbdev_set_par,
.fb_fillrect = drm_fb_helper_cfb_fillrect,
.fb_copyarea = drm_fb_helper_cfb_copyarea,
.fb_imageblit = drm_fb_helper_cfb_imageblit,
.fb_pan_display = intel_fbdev_pan_display,
.fb_blank = intel_fbdev_blank,
};
static int intelfb_alloc(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct intel_fbdev *ifbdev =
container_of(helper, struct intel_fbdev, helper);
struct drm_framebuffer *fb;
struct drm_device *dev = helper->dev;
drm/i915: don't allocate fbcon from stolen memory if it's too big Technology has evolved and now we have eDP panels with 3200x1800 resolution. In the meantime, the BIOS guys didn't change the default 32mb for stolen memory. On top of that, we can't assume our users will be able to increase the default stolen memory size to more than 32mb - I'm not even sure all BIOSes allow that. So just the fbcon buffer alone eats 22mb of my stolen memroy, and due to the BDW/SKL restriction of not using the last 8mb of stolen memory, all that's left for FBC is 2mb! Since fbcon is not the coolest feature ever, I think it's better to save our precious stolen resource to FBC and the other guys. On the other hand, we really want to use as much stolen memory as possible, since on some older systems the stolen memory may be a considerable percentage of the total available memory. This patch tries to achieve a little balance using a simple heuristic: if the fbcon wants more than half of the available stolen memory, don't use stolen memory in order to leave some for FBC and the other features. The long term plan should be to implement a way to set priorities for stolen memory allocation and then evict low priority users when the high priority ones need the memory. While we still don't have that, let's try to make FBC usable with the simple solution. Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-23 09:52:23 -06:00
struct drm_i915_private *dev_priv = to_i915(dev);
struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_i915_gem_object *obj;
int size;
/* we don't do packed 24bpp */
if (sizes->surface_bpp == 24)
sizes->surface_bpp = 32;
mode_cmd.width = sizes->surface_width;
mode_cmd.height = sizes->surface_height;
mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
sizes->surface_depth);
size = mode_cmd.pitches[0] * mode_cmd.height;
size = PAGE_ALIGN(size);
drm/i915: don't allocate fbcon from stolen memory if it's too big Technology has evolved and now we have eDP panels with 3200x1800 resolution. In the meantime, the BIOS guys didn't change the default 32mb for stolen memory. On top of that, we can't assume our users will be able to increase the default stolen memory size to more than 32mb - I'm not even sure all BIOSes allow that. So just the fbcon buffer alone eats 22mb of my stolen memroy, and due to the BDW/SKL restriction of not using the last 8mb of stolen memory, all that's left for FBC is 2mb! Since fbcon is not the coolest feature ever, I think it's better to save our precious stolen resource to FBC and the other guys. On the other hand, we really want to use as much stolen memory as possible, since on some older systems the stolen memory may be a considerable percentage of the total available memory. This patch tries to achieve a little balance using a simple heuristic: if the fbcon wants more than half of the available stolen memory, don't use stolen memory in order to leave some for FBC and the other features. The long term plan should be to implement a way to set priorities for stolen memory allocation and then evict low priority users when the high priority ones need the memory. While we still don't have that, let's try to make FBC usable with the simple solution. Cc: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-09-23 09:52:23 -06:00
/* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features. */
obj = NULL;
if (size * 2 < dev_priv->stolen_usable_size)
obj = i915_gem_object_create_stolen(dev_priv, size);
if (obj == NULL)
obj = i915_gem_object_create_shmem(dev_priv, size);
if (IS_ERR(obj)) {
DRM_ERROR("failed to allocate framebuffer\n");
return PTR_ERR(obj);
}
fb = intel_framebuffer_create(obj, &mode_cmd);
i915_gem_object_put(obj);
if (IS_ERR(fb))
return PTR_ERR(fb);
ifbdev->fb = to_intel_framebuffer(fb);
return 0;
}
static int intelfb_create(struct drm_fb_helper *helper,
struct drm_fb_helper_surface_size *sizes)
{
struct intel_fbdev *ifbdev =
container_of(helper, struct intel_fbdev, helper);
struct intel_framebuffer *intel_fb = ifbdev->fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct pci_dev *pdev = dev_priv->drm.pdev;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
const struct i915_ggtt_view view = {
.type = I915_GGTT_VIEW_NORMAL,
};
intel_wakeref_t wakeref;
struct fb_info *info;
struct i915_vma *vma;
drm/i915: Move the policy for placement of the GGTT vma into the caller Currently we make the unilateral decision inside i915_gem_object_pin_to_display() where the VMA should resided (inside the fence and mappable region or above?). This is not our decision to make as it impacts on how the display engine can use the resulting scanout object, and it would rather instruct us where to place the VMA so that it can enable the features it wants. As such, make the pin flags an argument to i915_gem_object_pin_to_display() and control them from intel_pin_and_fence_fb_obj() Whilst taking control of the mapping for ourselves, start tracking how we use it to avoid trying to free a fence we never claimed: <3>[ 227.151869] GEM_BUG_ON(vma->fence->pin_count <= 0) <4>[ 227.152064] ------------[ cut here ]------------ <2>[ 227.152068] kernel BUG at drivers/gpu/drm/i915/i915_vma.h:391! <4>[ 227.152084] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI <0>[ 227.152092] Dumping ftrace buffer: <0>[ 227.152099] (ftrace buffer empty) <4>[ 227.152102] Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich e1000e mei_me mei prime_numbers <4>[ 227.152131] CPU: 1 PID: 1587 Comm: kworker/u16:49 Tainted: G U 4.16.0-rc1-gbab67b2f6177-kasan_7+ #1 <4>[ 227.152134] Hardware name: Dell Inc. OptiPlex 755 /0PU052, BIOS A08 02/19/2008 <4>[ 227.152236] Workqueue: events_unbound intel_atomic_commit_work [i915] <4>[ 227.152292] RIP: 0010:intel_unpin_fb_vma+0x23a/0x2a0 [i915] <4>[ 227.152295] RSP: 0018:ffff88005aad7b68 EFLAGS: 00010286 <4>[ 227.152300] RAX: 0000000000000026 RBX: ffff88005c359580 RCX: 0000000000000000 <4>[ 227.152304] RDX: 0000000000000026 RSI: ffffffff8707d840 RDI: ffffed000b55af63 <4>[ 227.152307] RBP: ffff880056817e58 R08: 0000000000000001 R09: 0000000000000000 <4>[ 227.152311] R10: ffff88005aad7b88 R11: 0000000000000000 R12: ffff8800568184d0 <4>[ 227.152314] R13: ffff880065b5ab08 R14: 0000000000000000 R15: dffffc0000000000 <4>[ 227.152318] FS: 0000000000000000(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000 <4>[ 227.152322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 227.152325] CR2: 00007f5fb25550a8 CR3: 0000000068c78000 CR4: 00000000000006e0 <4>[ 227.152328] Call Trace: <4>[ 227.152385] intel_cleanup_plane_fb+0x6b/0xd0 [i915] <4>[ 227.152395] drm_atomic_helper_cleanup_planes+0x166/0x280 <4>[ 227.152452] intel_atomic_commit_tail+0x159d/0x3380 [i915] <4>[ 227.152463] ? process_one_work+0x66e/0x1460 <4>[ 227.152516] ? skl_update_crtcs+0x9c0/0x9c0 [i915] <4>[ 227.152523] ? lock_acquire+0x13d/0x390 <4>[ 227.152527] ? lock_acquire+0x13d/0x390 <4>[ 227.152534] process_one_work+0x71a/0x1460 <4>[ 227.152540] ? __schedule+0x815/0x1e20 <4>[ 227.152547] ? pwq_dec_nr_in_flight+0x2b0/0x2b0 <4>[ 227.152553] ? _raw_spin_lock_irq+0xa/0x40 <4>[ 227.152559] worker_thread+0xdf/0xf60 <4>[ 227.152569] ? process_one_work+0x1460/0x1460 <4>[ 227.152573] kthread+0x2cf/0x3c0 <4>[ 227.152578] ? _kthread_create_on_node+0xa0/0xa0 <4>[ 227.152583] ret_from_fork+0x3a/0x50 <4>[ 227.152591] Code: c6 00 11 86 c0 48 c7 c7 e0 bd 85 c0 e8 60 e7 a9 c4 0f ff e9 1f fe ff ff 48 c7 c6 40 10 86 c0 48 c7 c7 e0 ca 85 c0 e8 2b 95 bd c4 <0f> 0b 48 89 ef e8 4c 44 e8 c4 e9 ef fd ff ff e8 42 44 e8 c4 e9 <1>[ 227.152720] RIP: intel_unpin_fb_vma+0x23a/0x2a0 [i915] RSP: ffff88005aad7b68 v2: i915_vma_pin_fence() is a no-op if a fence isn't required, so check vma->fence as well. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-2-chris@chris-wilson.co.uk
2018-02-20 06:42:06 -07:00
unsigned long flags = 0;
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
bool prealloc = false;
void __iomem *vaddr;
int ret;
if (intel_fb &&
(sizes->fb_width > intel_fb->base.width ||
sizes->fb_height > intel_fb->base.height)) {
DRM_DEBUG_KMS("BIOS fb too small (%dx%d), we require (%dx%d),"
" releasing it\n",
intel_fb->base.width, intel_fb->base.height,
sizes->fb_width, sizes->fb_height);
drm_framebuffer_put(&intel_fb->base);
intel_fb = ifbdev->fb = NULL;
}
if (!intel_fb || WARN_ON(!intel_fb_obj(&intel_fb->base))) {
DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
ret = intelfb_alloc(helper, sizes);
if (ret)
drm/i915: Fix failure paths around initial fbdev allocation We had two failure modes here: 1. Deadlock in intelfb_alloc failure path where it calls drm_framebuffer_remove, which grabs the struct mutex and intelfb_create (caller of intelfb_alloc) was already holding it. 2. Deadlock in intelfb_create failure path where it calls drm_framebuffer_unreference, which grabs the struct mutex and intelfb_create was already holding it. [Daniel Vetter on why struct_mutex needs to be locked in the second half of intelfb_create: "The vma [for the fbdev] is pinned, the problem is that we re-lookup it a few times, which is racy. We should instead track the vma directly, but oh well we don't."] v2: * Reformat commit msg to 72 chars. (Lukas Wunner) * Add third failure mode. (Lukas Wunner) v5: * Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC, rephrase commit message. (Jani Nicula) v6: * In intelfb_alloc, if __intel_framebuffer_create failed, fb will be an ERR_PTR, thus not null. So in the failure path we need to check for IS_ERR_OR_NULL to avoid calling drm_framebuffer_remove on the ERR_PTR. (Lukas Wunner) * Since this is init code a drm_framebuffer_unreference should be all we need. drm_framebuffer_remove is for framebuffers that userspace has created - and is getting somewhat defeatured. (Daniel Vetter) v7: * Clarify why struct_mutex needs to be locked in the second half of intelfb_create. (Daniel Vetter) Fixes: 60a5ca015ffd ("drm/i915: Add locking around framebuffer_references--") Reported-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> [Lukas: Create v3 + v4 + v5 + v6 + v7 based on Tvrtko's v2] Signed-off-by: Lukas Wunner <lukas@wunner.de> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/47d4e88c91b3bf0f7a280cabec54c8c8cf0cf6f2.1446892879.git.lukas@wunner.de Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-06-30 03:06:27 -06:00
return ret;
intel_fb = ifbdev->fb;
} else {
DRM_DEBUG_KMS("re-using BIOS fb\n");
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
prealloc = true;
sizes->fb_width = intel_fb->base.width;
sizes->fb_height = intel_fb->base.height;
}
drm/i915: Fix failure paths around initial fbdev allocation We had two failure modes here: 1. Deadlock in intelfb_alloc failure path where it calls drm_framebuffer_remove, which grabs the struct mutex and intelfb_create (caller of intelfb_alloc) was already holding it. 2. Deadlock in intelfb_create failure path where it calls drm_framebuffer_unreference, which grabs the struct mutex and intelfb_create was already holding it. [Daniel Vetter on why struct_mutex needs to be locked in the second half of intelfb_create: "The vma [for the fbdev] is pinned, the problem is that we re-lookup it a few times, which is racy. We should instead track the vma directly, but oh well we don't."] v2: * Reformat commit msg to 72 chars. (Lukas Wunner) * Add third failure mode. (Lukas Wunner) v5: * Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC, rephrase commit message. (Jani Nicula) v6: * In intelfb_alloc, if __intel_framebuffer_create failed, fb will be an ERR_PTR, thus not null. So in the failure path we need to check for IS_ERR_OR_NULL to avoid calling drm_framebuffer_remove on the ERR_PTR. (Lukas Wunner) * Since this is init code a drm_framebuffer_unreference should be all we need. drm_framebuffer_remove is for framebuffers that userspace has created - and is getting somewhat defeatured. (Daniel Vetter) v7: * Clarify why struct_mutex needs to be locked in the second half of intelfb_create. (Daniel Vetter) Fixes: 60a5ca015ffd ("drm/i915: Add locking around framebuffer_references--") Reported-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> [Lukas: Create v3 + v4 + v5 + v6 + v7 based on Tvrtko's v2] Signed-off-by: Lukas Wunner <lukas@wunner.de> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/47d4e88c91b3bf0f7a280cabec54c8c8cf0cf6f2.1446892879.git.lukas@wunner.de Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-06-30 03:06:27 -06:00
mutex_lock(&dev->struct_mutex);
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
drm/i915: Fix failure paths around initial fbdev allocation We had two failure modes here: 1. Deadlock in intelfb_alloc failure path where it calls drm_framebuffer_remove, which grabs the struct mutex and intelfb_create (caller of intelfb_alloc) was already holding it. 2. Deadlock in intelfb_create failure path where it calls drm_framebuffer_unreference, which grabs the struct mutex and intelfb_create was already holding it. [Daniel Vetter on why struct_mutex needs to be locked in the second half of intelfb_create: "The vma [for the fbdev] is pinned, the problem is that we re-lookup it a few times, which is racy. We should instead track the vma directly, but oh well we don't."] v2: * Reformat commit msg to 72 chars. (Lukas Wunner) * Add third failure mode. (Lukas Wunner) v5: * Rebase on drm-intel-nightly 2015y-09m-01d-09h-06m-08s UTC, rephrase commit message. (Jani Nicula) v6: * In intelfb_alloc, if __intel_framebuffer_create failed, fb will be an ERR_PTR, thus not null. So in the failure path we need to check for IS_ERR_OR_NULL to avoid calling drm_framebuffer_remove on the ERR_PTR. (Lukas Wunner) * Since this is init code a drm_framebuffer_unreference should be all we need. drm_framebuffer_remove is for framebuffers that userspace has created - and is getting somewhat defeatured. (Daniel Vetter) v7: * Clarify why struct_mutex needs to be locked in the second half of intelfb_create. (Daniel Vetter) Fixes: 60a5ca015ffd ("drm/i915: Add locking around framebuffer_references--") Reported-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com> [Lukas: Create v3 + v4 + v5 + v6 + v7 based on Tvrtko's v2] Signed-off-by: Lukas Wunner <lukas@wunner.de> Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/47d4e88c91b3bf0f7a280cabec54c8c8cf0cf6f2.1446892879.git.lukas@wunner.de Signed-off-by: Jani Nikula <jani.nikula@intel.com>
2015-06-30 03:06:27 -06:00
drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping A long time ago (before 3.14) we relied on a permanent pinning of the ifbdev to lock the fb in place inside the GGTT. However, the introduction of stealing the BIOS framebuffer and reusing its address in the GGTT for the fbdev has muddied waters and we use an inherited fb. However, the inherited fb is only pinned whilst it is active and we no longer have an explicit pin for the info->system_base mmapping used by the fbdev. The result is that after some aperture pressure the fbdev may be evicted, but we continue to write the fbcon into the same GGTT address - overwriting anything else that may be put into that offset. The effect is most pronounced across suspend/resume as intel_fbdev_set_suspend() does a full clear over the whole scanout. v2: Only unpin the intel_fb is we allocate it. If we inherit the fb from the BIOS, we do not own the pinned vma (except for the reference we add in this patch for our access via info->screen_base). v3: Finish balancing the vma pinning for the normal !preallocated case. v4: Try to simplify the pinning even further. v5: Leak the VMA (cleaned up by object-free) to avoid complicated error paths. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Goel, Akash" <akash.goel@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Lukas Wunner <lukas@wunner.de> Cc: drm-intel-fixes@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/1449245126-26158-1-git-send-email-chris@chris-wilson.co.uk Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-04 09:05:26 -07:00
/* Pin the GGTT vma for our access via info->screen_base.
* This also validates that any existing fb inherited from the
* BIOS is suitable for own access.
*/
drm/i915: Move the policy for placement of the GGTT vma into the caller Currently we make the unilateral decision inside i915_gem_object_pin_to_display() where the VMA should resided (inside the fence and mappable region or above?). This is not our decision to make as it impacts on how the display engine can use the resulting scanout object, and it would rather instruct us where to place the VMA so that it can enable the features it wants. As such, make the pin flags an argument to i915_gem_object_pin_to_display() and control them from intel_pin_and_fence_fb_obj() Whilst taking control of the mapping for ourselves, start tracking how we use it to avoid trying to free a fence we never claimed: <3>[ 227.151869] GEM_BUG_ON(vma->fence->pin_count <= 0) <4>[ 227.152064] ------------[ cut here ]------------ <2>[ 227.152068] kernel BUG at drivers/gpu/drm/i915/i915_vma.h:391! <4>[ 227.152084] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI <0>[ 227.152092] Dumping ftrace buffer: <0>[ 227.152099] (ftrace buffer empty) <4>[ 227.152102] Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich e1000e mei_me mei prime_numbers <4>[ 227.152131] CPU: 1 PID: 1587 Comm: kworker/u16:49 Tainted: G U 4.16.0-rc1-gbab67b2f6177-kasan_7+ #1 <4>[ 227.152134] Hardware name: Dell Inc. OptiPlex 755 /0PU052, BIOS A08 02/19/2008 <4>[ 227.152236] Workqueue: events_unbound intel_atomic_commit_work [i915] <4>[ 227.152292] RIP: 0010:intel_unpin_fb_vma+0x23a/0x2a0 [i915] <4>[ 227.152295] RSP: 0018:ffff88005aad7b68 EFLAGS: 00010286 <4>[ 227.152300] RAX: 0000000000000026 RBX: ffff88005c359580 RCX: 0000000000000000 <4>[ 227.152304] RDX: 0000000000000026 RSI: ffffffff8707d840 RDI: ffffed000b55af63 <4>[ 227.152307] RBP: ffff880056817e58 R08: 0000000000000001 R09: 0000000000000000 <4>[ 227.152311] R10: ffff88005aad7b88 R11: 0000000000000000 R12: ffff8800568184d0 <4>[ 227.152314] R13: ffff880065b5ab08 R14: 0000000000000000 R15: dffffc0000000000 <4>[ 227.152318] FS: 0000000000000000(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000 <4>[ 227.152322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 227.152325] CR2: 00007f5fb25550a8 CR3: 0000000068c78000 CR4: 00000000000006e0 <4>[ 227.152328] Call Trace: <4>[ 227.152385] intel_cleanup_plane_fb+0x6b/0xd0 [i915] <4>[ 227.152395] drm_atomic_helper_cleanup_planes+0x166/0x280 <4>[ 227.152452] intel_atomic_commit_tail+0x159d/0x3380 [i915] <4>[ 227.152463] ? process_one_work+0x66e/0x1460 <4>[ 227.152516] ? skl_update_crtcs+0x9c0/0x9c0 [i915] <4>[ 227.152523] ? lock_acquire+0x13d/0x390 <4>[ 227.152527] ? lock_acquire+0x13d/0x390 <4>[ 227.152534] process_one_work+0x71a/0x1460 <4>[ 227.152540] ? __schedule+0x815/0x1e20 <4>[ 227.152547] ? pwq_dec_nr_in_flight+0x2b0/0x2b0 <4>[ 227.152553] ? _raw_spin_lock_irq+0xa/0x40 <4>[ 227.152559] worker_thread+0xdf/0xf60 <4>[ 227.152569] ? process_one_work+0x1460/0x1460 <4>[ 227.152573] kthread+0x2cf/0x3c0 <4>[ 227.152578] ? _kthread_create_on_node+0xa0/0xa0 <4>[ 227.152583] ret_from_fork+0x3a/0x50 <4>[ 227.152591] Code: c6 00 11 86 c0 48 c7 c7 e0 bd 85 c0 e8 60 e7 a9 c4 0f ff e9 1f fe ff ff 48 c7 c6 40 10 86 c0 48 c7 c7 e0 ca 85 c0 e8 2b 95 bd c4 <0f> 0b 48 89 ef e8 4c 44 e8 c4 e9 ef fd ff ff e8 42 44 e8 c4 e9 <1>[ 227.152720] RIP: intel_unpin_fb_vma+0x23a/0x2a0 [i915] RSP: ffff88005aad7b68 v2: i915_vma_pin_fence() is a no-op if a fence isn't required, so check vma->fence as well. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-2-chris@chris-wilson.co.uk
2018-02-20 06:42:06 -07:00
vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base,
&view, false, &flags);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping A long time ago (before 3.14) we relied on a permanent pinning of the ifbdev to lock the fb in place inside the GGTT. However, the introduction of stealing the BIOS framebuffer and reusing its address in the GGTT for the fbdev has muddied waters and we use an inherited fb. However, the inherited fb is only pinned whilst it is active and we no longer have an explicit pin for the info->system_base mmapping used by the fbdev. The result is that after some aperture pressure the fbdev may be evicted, but we continue to write the fbcon into the same GGTT address - overwriting anything else that may be put into that offset. The effect is most pronounced across suspend/resume as intel_fbdev_set_suspend() does a full clear over the whole scanout. v2: Only unpin the intel_fb is we allocate it. If we inherit the fb from the BIOS, we do not own the pinned vma (except for the reference we add in this patch for our access via info->screen_base). v3: Finish balancing the vma pinning for the normal !preallocated case. v4: Try to simplify the pinning even further. v5: Leak the VMA (cleaned up by object-free) to avoid complicated error paths. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Goel, Akash" <akash.goel@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Lukas Wunner <lukas@wunner.de> Cc: drm-intel-fixes@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/1449245126-26158-1-git-send-email-chris@chris-wilson.co.uk Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-04 09:05:26 -07:00
goto out_unlock;
}
drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping A long time ago (before 3.14) we relied on a permanent pinning of the ifbdev to lock the fb in place inside the GGTT. However, the introduction of stealing the BIOS framebuffer and reusing its address in the GGTT for the fbdev has muddied waters and we use an inherited fb. However, the inherited fb is only pinned whilst it is active and we no longer have an explicit pin for the info->system_base mmapping used by the fbdev. The result is that after some aperture pressure the fbdev may be evicted, but we continue to write the fbcon into the same GGTT address - overwriting anything else that may be put into that offset. The effect is most pronounced across suspend/resume as intel_fbdev_set_suspend() does a full clear over the whole scanout. v2: Only unpin the intel_fb is we allocate it. If we inherit the fb from the BIOS, we do not own the pinned vma (except for the reference we add in this patch for our access via info->screen_base). v3: Finish balancing the vma pinning for the normal !preallocated case. v4: Try to simplify the pinning even further. v5: Leak the VMA (cleaned up by object-free) to avoid complicated error paths. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Goel, Akash" <akash.goel@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Lukas Wunner <lukas@wunner.de> Cc: drm-intel-fixes@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/1449245126-26158-1-git-send-email-chris@chris-wilson.co.uk Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-04 09:05:26 -07:00
intel_frontbuffer_flush(to_frontbuffer(ifbdev), ORIGIN_DIRTYFB);
info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info)) {
drm/i915: Tear down fbdev if initialization fails Currently if intelfb_create() errors out, it unrefs the bo even though the fb now owns that reference. (Spotted by Ville Syrjälä.) We should unref the fb instead of the bo. However the fb was not necessarily allocated by intelfb_create(), it could be inherited from BIOS (the fb struct was then allocated by dev_priv->display.get_initial_plane_config()) and be in active use by a crtc. In this case we should call drm_framebuffer_remove() instead of _unreference() to also disable the crtc. Daniel Vetter suggested that "fbdev teardown code will take care of it. The correct approach is probably to not unref anything at all". But if fbdev initialization fails, the fbdev isn't torn down and occupies memory even though it's unusable. Therefore clobber it in intel_fbdev_initial_config(). (Currently we ignore a negative return value there.) The idea is that if fbdev initialization fails, the driver behaves as if CONFIG_DRM_FBDEV_EMULATION wasn't set. Should X11 manage to start up without errors, it will at least be able to use the memory that would otherwise be hogged by the unusable fbdev. Also, log errors in intelfb_create(). Don't call async_synchronize_full() in intel_fbdev_fini() when called from intel_fbdev_initial_config() to avoid deadlock. v2: Instead of calling drm_framebuffer_unreference() (if fb was not inherited from BIOS), call intel_fbdev_fini(). v3: Rebase on e00bf69644ba (drm/i915: Move the fbdev async_schedule() into intel_fbdev.c), call async_synchronize_full() conditionally instead of moving it into i915_driver_unload(). Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: http://patchwork.freedesktop.org/patch/msgid/49ce5f0daead24b7598ec78591731046c333c18d.1447938059.git.lukas@wunner.de Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-11-18 08:29:51 -07:00
DRM_ERROR("Failed to allocate fb_info\n");
ret = PTR_ERR(info);
goto out_unpin;
}
ifbdev->helper.fb = &ifbdev->fb->base;
info->fbops = &intelfb_ops;
/* setup aperture base/size for vesafb takeover */
info->apertures->ranges[0].base = ggtt->gmadr.start;
info->apertures->ranges[0].size = ggtt->mappable_end;
vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
drm/i915: Tear down fbdev if initialization fails Currently if intelfb_create() errors out, it unrefs the bo even though the fb now owns that reference. (Spotted by Ville Syrjälä.) We should unref the fb instead of the bo. However the fb was not necessarily allocated by intelfb_create(), it could be inherited from BIOS (the fb struct was then allocated by dev_priv->display.get_initial_plane_config()) and be in active use by a crtc. In this case we should call drm_framebuffer_remove() instead of _unreference() to also disable the crtc. Daniel Vetter suggested that "fbdev teardown code will take care of it. The correct approach is probably to not unref anything at all". But if fbdev initialization fails, the fbdev isn't torn down and occupies memory even though it's unusable. Therefore clobber it in intel_fbdev_initial_config(). (Currently we ignore a negative return value there.) The idea is that if fbdev initialization fails, the driver behaves as if CONFIG_DRM_FBDEV_EMULATION wasn't set. Should X11 manage to start up without errors, it will at least be able to use the memory that would otherwise be hogged by the unusable fbdev. Also, log errors in intelfb_create(). Don't call async_synchronize_full() in intel_fbdev_fini() when called from intel_fbdev_initial_config() to avoid deadlock. v2: Instead of calling drm_framebuffer_unreference() (if fb was not inherited from BIOS), call intel_fbdev_fini(). v3: Rebase on e00bf69644ba (drm/i915: Move the fbdev async_schedule() into intel_fbdev.c), call async_synchronize_full() conditionally instead of moving it into i915_driver_unload(). Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: http://patchwork.freedesktop.org/patch/msgid/49ce5f0daead24b7598ec78591731046c333c18d.1447938059.git.lukas@wunner.de Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-11-18 08:29:51 -07:00
DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
ret = PTR_ERR(vaddr);
goto out_unpin;
}
info->screen_base = vaddr;
info->screen_size = vma->node.size;
/* Our framebuffer is the entirety of fbdev's system memory */
info->fix.smem_start = (unsigned long)info->screen_base;
info->fix.smem_len = info->screen_size;
drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
/* If the object is shmemfs backed, it will have given us zeroed pages.
* If the object is stolen however, it will be full of whatever
* garbage was left in there.
*/
if (vma->obj->stolen && !prealloc)
memset_io(info->screen_base, 0, info->screen_size);
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x\n",
ifbdev->fb->base.width, ifbdev->fb->base.height,
i915_ggtt_offset(vma));
ifbdev->vma = vma;
drm/i915: Move the policy for placement of the GGTT vma into the caller Currently we make the unilateral decision inside i915_gem_object_pin_to_display() where the VMA should resided (inside the fence and mappable region or above?). This is not our decision to make as it impacts on how the display engine can use the resulting scanout object, and it would rather instruct us where to place the VMA so that it can enable the features it wants. As such, make the pin flags an argument to i915_gem_object_pin_to_display() and control them from intel_pin_and_fence_fb_obj() Whilst taking control of the mapping for ourselves, start tracking how we use it to avoid trying to free a fence we never claimed: <3>[ 227.151869] GEM_BUG_ON(vma->fence->pin_count <= 0) <4>[ 227.152064] ------------[ cut here ]------------ <2>[ 227.152068] kernel BUG at drivers/gpu/drm/i915/i915_vma.h:391! <4>[ 227.152084] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI <0>[ 227.152092] Dumping ftrace buffer: <0>[ 227.152099] (ftrace buffer empty) <4>[ 227.152102] Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich e1000e mei_me mei prime_numbers <4>[ 227.152131] CPU: 1 PID: 1587 Comm: kworker/u16:49 Tainted: G U 4.16.0-rc1-gbab67b2f6177-kasan_7+ #1 <4>[ 227.152134] Hardware name: Dell Inc. OptiPlex 755 /0PU052, BIOS A08 02/19/2008 <4>[ 227.152236] Workqueue: events_unbound intel_atomic_commit_work [i915] <4>[ 227.152292] RIP: 0010:intel_unpin_fb_vma+0x23a/0x2a0 [i915] <4>[ 227.152295] RSP: 0018:ffff88005aad7b68 EFLAGS: 00010286 <4>[ 227.152300] RAX: 0000000000000026 RBX: ffff88005c359580 RCX: 0000000000000000 <4>[ 227.152304] RDX: 0000000000000026 RSI: ffffffff8707d840 RDI: ffffed000b55af63 <4>[ 227.152307] RBP: ffff880056817e58 R08: 0000000000000001 R09: 0000000000000000 <4>[ 227.152311] R10: ffff88005aad7b88 R11: 0000000000000000 R12: ffff8800568184d0 <4>[ 227.152314] R13: ffff880065b5ab08 R14: 0000000000000000 R15: dffffc0000000000 <4>[ 227.152318] FS: 0000000000000000(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000 <4>[ 227.152322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 227.152325] CR2: 00007f5fb25550a8 CR3: 0000000068c78000 CR4: 00000000000006e0 <4>[ 227.152328] Call Trace: <4>[ 227.152385] intel_cleanup_plane_fb+0x6b/0xd0 [i915] <4>[ 227.152395] drm_atomic_helper_cleanup_planes+0x166/0x280 <4>[ 227.152452] intel_atomic_commit_tail+0x159d/0x3380 [i915] <4>[ 227.152463] ? process_one_work+0x66e/0x1460 <4>[ 227.152516] ? skl_update_crtcs+0x9c0/0x9c0 [i915] <4>[ 227.152523] ? lock_acquire+0x13d/0x390 <4>[ 227.152527] ? lock_acquire+0x13d/0x390 <4>[ 227.152534] process_one_work+0x71a/0x1460 <4>[ 227.152540] ? __schedule+0x815/0x1e20 <4>[ 227.152547] ? pwq_dec_nr_in_flight+0x2b0/0x2b0 <4>[ 227.152553] ? _raw_spin_lock_irq+0xa/0x40 <4>[ 227.152559] worker_thread+0xdf/0xf60 <4>[ 227.152569] ? process_one_work+0x1460/0x1460 <4>[ 227.152573] kthread+0x2cf/0x3c0 <4>[ 227.152578] ? _kthread_create_on_node+0xa0/0xa0 <4>[ 227.152583] ret_from_fork+0x3a/0x50 <4>[ 227.152591] Code: c6 00 11 86 c0 48 c7 c7 e0 bd 85 c0 e8 60 e7 a9 c4 0f ff e9 1f fe ff ff 48 c7 c6 40 10 86 c0 48 c7 c7 e0 ca 85 c0 e8 2b 95 bd c4 <0f> 0b 48 89 ef e8 4c 44 e8 c4 e9 ef fd ff ff e8 42 44 e8 c4 e9 <1>[ 227.152720] RIP: intel_unpin_fb_vma+0x23a/0x2a0 [i915] RSP: ffff88005aad7b68 v2: i915_vma_pin_fence() is a no-op if a fence isn't required, so check vma->fence as well. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-2-chris@chris-wilson.co.uk
2018-02-20 06:42:06 -07:00
ifbdev->vma_flags = flags;
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
mutex_unlock(&dev->struct_mutex);
vga_switcheroo_client_fb_set(pdev, info);
return 0;
out_unpin:
drm/i915: Move the policy for placement of the GGTT vma into the caller Currently we make the unilateral decision inside i915_gem_object_pin_to_display() where the VMA should resided (inside the fence and mappable region or above?). This is not our decision to make as it impacts on how the display engine can use the resulting scanout object, and it would rather instruct us where to place the VMA so that it can enable the features it wants. As such, make the pin flags an argument to i915_gem_object_pin_to_display() and control them from intel_pin_and_fence_fb_obj() Whilst taking control of the mapping for ourselves, start tracking how we use it to avoid trying to free a fence we never claimed: <3>[ 227.151869] GEM_BUG_ON(vma->fence->pin_count <= 0) <4>[ 227.152064] ------------[ cut here ]------------ <2>[ 227.152068] kernel BUG at drivers/gpu/drm/i915/i915_vma.h:391! <4>[ 227.152084] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI <0>[ 227.152092] Dumping ftrace buffer: <0>[ 227.152099] (ftrace buffer empty) <4>[ 227.152102] Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich e1000e mei_me mei prime_numbers <4>[ 227.152131] CPU: 1 PID: 1587 Comm: kworker/u16:49 Tainted: G U 4.16.0-rc1-gbab67b2f6177-kasan_7+ #1 <4>[ 227.152134] Hardware name: Dell Inc. OptiPlex 755 /0PU052, BIOS A08 02/19/2008 <4>[ 227.152236] Workqueue: events_unbound intel_atomic_commit_work [i915] <4>[ 227.152292] RIP: 0010:intel_unpin_fb_vma+0x23a/0x2a0 [i915] <4>[ 227.152295] RSP: 0018:ffff88005aad7b68 EFLAGS: 00010286 <4>[ 227.152300] RAX: 0000000000000026 RBX: ffff88005c359580 RCX: 0000000000000000 <4>[ 227.152304] RDX: 0000000000000026 RSI: ffffffff8707d840 RDI: ffffed000b55af63 <4>[ 227.152307] RBP: ffff880056817e58 R08: 0000000000000001 R09: 0000000000000000 <4>[ 227.152311] R10: ffff88005aad7b88 R11: 0000000000000000 R12: ffff8800568184d0 <4>[ 227.152314] R13: ffff880065b5ab08 R14: 0000000000000000 R15: dffffc0000000000 <4>[ 227.152318] FS: 0000000000000000(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000 <4>[ 227.152322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 227.152325] CR2: 00007f5fb25550a8 CR3: 0000000068c78000 CR4: 00000000000006e0 <4>[ 227.152328] Call Trace: <4>[ 227.152385] intel_cleanup_plane_fb+0x6b/0xd0 [i915] <4>[ 227.152395] drm_atomic_helper_cleanup_planes+0x166/0x280 <4>[ 227.152452] intel_atomic_commit_tail+0x159d/0x3380 [i915] <4>[ 227.152463] ? process_one_work+0x66e/0x1460 <4>[ 227.152516] ? skl_update_crtcs+0x9c0/0x9c0 [i915] <4>[ 227.152523] ? lock_acquire+0x13d/0x390 <4>[ 227.152527] ? lock_acquire+0x13d/0x390 <4>[ 227.152534] process_one_work+0x71a/0x1460 <4>[ 227.152540] ? __schedule+0x815/0x1e20 <4>[ 227.152547] ? pwq_dec_nr_in_flight+0x2b0/0x2b0 <4>[ 227.152553] ? _raw_spin_lock_irq+0xa/0x40 <4>[ 227.152559] worker_thread+0xdf/0xf60 <4>[ 227.152569] ? process_one_work+0x1460/0x1460 <4>[ 227.152573] kthread+0x2cf/0x3c0 <4>[ 227.152578] ? _kthread_create_on_node+0xa0/0xa0 <4>[ 227.152583] ret_from_fork+0x3a/0x50 <4>[ 227.152591] Code: c6 00 11 86 c0 48 c7 c7 e0 bd 85 c0 e8 60 e7 a9 c4 0f ff e9 1f fe ff ff 48 c7 c6 40 10 86 c0 48 c7 c7 e0 ca 85 c0 e8 2b 95 bd c4 <0f> 0b 48 89 ef e8 4c 44 e8 c4 e9 ef fd ff ff e8 42 44 e8 c4 e9 <1>[ 227.152720] RIP: intel_unpin_fb_vma+0x23a/0x2a0 [i915] RSP: ffff88005aad7b68 v2: i915_vma_pin_fence() is a no-op if a fence isn't required, so check vma->fence as well. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-2-chris@chris-wilson.co.uk
2018-02-20 06:42:06 -07:00
intel_unpin_fb_vma(vma, flags);
drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping A long time ago (before 3.14) we relied on a permanent pinning of the ifbdev to lock the fb in place inside the GGTT. However, the introduction of stealing the BIOS framebuffer and reusing its address in the GGTT for the fbdev has muddied waters and we use an inherited fb. However, the inherited fb is only pinned whilst it is active and we no longer have an explicit pin for the info->system_base mmapping used by the fbdev. The result is that after some aperture pressure the fbdev may be evicted, but we continue to write the fbcon into the same GGTT address - overwriting anything else that may be put into that offset. The effect is most pronounced across suspend/resume as intel_fbdev_set_suspend() does a full clear over the whole scanout. v2: Only unpin the intel_fb is we allocate it. If we inherit the fb from the BIOS, we do not own the pinned vma (except for the reference we add in this patch for our access via info->screen_base). v3: Finish balancing the vma pinning for the normal !preallocated case. v4: Try to simplify the pinning even further. v5: Leak the VMA (cleaned up by object-free) to avoid complicated error paths. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Goel, Akash" <akash.goel@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Lukas Wunner <lukas@wunner.de> Cc: drm-intel-fixes@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/1449245126-26158-1-git-send-email-chris@chris-wilson.co.uk Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-04 09:05:26 -07:00
out_unlock:
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
mutex_unlock(&dev->struct_mutex);
return ret;
}
static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
.fb_probe = intelfb_create,
};
static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
{
drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping A long time ago (before 3.14) we relied on a permanent pinning of the ifbdev to lock the fb in place inside the GGTT. However, the introduction of stealing the BIOS framebuffer and reusing its address in the GGTT for the fbdev has muddied waters and we use an inherited fb. However, the inherited fb is only pinned whilst it is active and we no longer have an explicit pin for the info->system_base mmapping used by the fbdev. The result is that after some aperture pressure the fbdev may be evicted, but we continue to write the fbcon into the same GGTT address - overwriting anything else that may be put into that offset. The effect is most pronounced across suspend/resume as intel_fbdev_set_suspend() does a full clear over the whole scanout. v2: Only unpin the intel_fb is we allocate it. If we inherit the fb from the BIOS, we do not own the pinned vma (except for the reference we add in this patch for our access via info->screen_base). v3: Finish balancing the vma pinning for the normal !preallocated case. v4: Try to simplify the pinning even further. v5: Leak the VMA (cleaned up by object-free) to avoid complicated error paths. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: "Goel, Akash" <akash.goel@intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: Jesse Barnes <jbarnes@virtuousgeek.org> Cc: Lukas Wunner <lukas@wunner.de> Cc: drm-intel-fixes@lists.freedesktop.org Link: http://patchwork.freedesktop.org/patch/msgid/1449245126-26158-1-git-send-email-chris@chris-wilson.co.uk Tested-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-12-04 09:05:26 -07:00
/* We rely on the object-free to release the VMA pinning for
* the info->screen_base mmaping. Leaking the VMA is simpler than
* trying to rectify all the possible error paths leading here.
*/
drm_fb_helper_fini(&ifbdev->helper);
if (ifbdev->vma) {
mutex_lock(&ifbdev->helper.dev->struct_mutex);
drm/i915: Move the policy for placement of the GGTT vma into the caller Currently we make the unilateral decision inside i915_gem_object_pin_to_display() where the VMA should resided (inside the fence and mappable region or above?). This is not our decision to make as it impacts on how the display engine can use the resulting scanout object, and it would rather instruct us where to place the VMA so that it can enable the features it wants. As such, make the pin flags an argument to i915_gem_object_pin_to_display() and control them from intel_pin_and_fence_fb_obj() Whilst taking control of the mapping for ourselves, start tracking how we use it to avoid trying to free a fence we never claimed: <3>[ 227.151869] GEM_BUG_ON(vma->fence->pin_count <= 0) <4>[ 227.152064] ------------[ cut here ]------------ <2>[ 227.152068] kernel BUG at drivers/gpu/drm/i915/i915_vma.h:391! <4>[ 227.152084] invalid opcode: 0000 [#1] PREEMPT SMP KASAN PTI <0>[ 227.152092] Dumping ftrace buffer: <0>[ 227.152099] (ftrace buffer empty) <4>[ 227.152102] Modules linked in: i915 snd_hda_codec_analog snd_hda_codec_generic coretemp snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm lpc_ich e1000e mei_me mei prime_numbers <4>[ 227.152131] CPU: 1 PID: 1587 Comm: kworker/u16:49 Tainted: G U 4.16.0-rc1-gbab67b2f6177-kasan_7+ #1 <4>[ 227.152134] Hardware name: Dell Inc. OptiPlex 755 /0PU052, BIOS A08 02/19/2008 <4>[ 227.152236] Workqueue: events_unbound intel_atomic_commit_work [i915] <4>[ 227.152292] RIP: 0010:intel_unpin_fb_vma+0x23a/0x2a0 [i915] <4>[ 227.152295] RSP: 0018:ffff88005aad7b68 EFLAGS: 00010286 <4>[ 227.152300] RAX: 0000000000000026 RBX: ffff88005c359580 RCX: 0000000000000000 <4>[ 227.152304] RDX: 0000000000000026 RSI: ffffffff8707d840 RDI: ffffed000b55af63 <4>[ 227.152307] RBP: ffff880056817e58 R08: 0000000000000001 R09: 0000000000000000 <4>[ 227.152311] R10: ffff88005aad7b88 R11: 0000000000000000 R12: ffff8800568184d0 <4>[ 227.152314] R13: ffff880065b5ab08 R14: 0000000000000000 R15: dffffc0000000000 <4>[ 227.152318] FS: 0000000000000000(0000) GS:ffff88006ac40000(0000) knlGS:0000000000000000 <4>[ 227.152322] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 227.152325] CR2: 00007f5fb25550a8 CR3: 0000000068c78000 CR4: 00000000000006e0 <4>[ 227.152328] Call Trace: <4>[ 227.152385] intel_cleanup_plane_fb+0x6b/0xd0 [i915] <4>[ 227.152395] drm_atomic_helper_cleanup_planes+0x166/0x280 <4>[ 227.152452] intel_atomic_commit_tail+0x159d/0x3380 [i915] <4>[ 227.152463] ? process_one_work+0x66e/0x1460 <4>[ 227.152516] ? skl_update_crtcs+0x9c0/0x9c0 [i915] <4>[ 227.152523] ? lock_acquire+0x13d/0x390 <4>[ 227.152527] ? lock_acquire+0x13d/0x390 <4>[ 227.152534] process_one_work+0x71a/0x1460 <4>[ 227.152540] ? __schedule+0x815/0x1e20 <4>[ 227.152547] ? pwq_dec_nr_in_flight+0x2b0/0x2b0 <4>[ 227.152553] ? _raw_spin_lock_irq+0xa/0x40 <4>[ 227.152559] worker_thread+0xdf/0xf60 <4>[ 227.152569] ? process_one_work+0x1460/0x1460 <4>[ 227.152573] kthread+0x2cf/0x3c0 <4>[ 227.152578] ? _kthread_create_on_node+0xa0/0xa0 <4>[ 227.152583] ret_from_fork+0x3a/0x50 <4>[ 227.152591] Code: c6 00 11 86 c0 48 c7 c7 e0 bd 85 c0 e8 60 e7 a9 c4 0f ff e9 1f fe ff ff 48 c7 c6 40 10 86 c0 48 c7 c7 e0 ca 85 c0 e8 2b 95 bd c4 <0f> 0b 48 89 ef e8 4c 44 e8 c4 e9 ef fd ff ff e8 42 44 e8 c4 e9 <1>[ 227.152720] RIP: intel_unpin_fb_vma+0x23a/0x2a0 [i915] RSP: ffff88005aad7b68 v2: i915_vma_pin_fence() is a no-op if a fence isn't required, so check vma->fence as well. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20180220134208.24988-2-chris@chris-wilson.co.uk
2018-02-20 06:42:06 -07:00
intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags);
mutex_unlock(&ifbdev->helper.dev->struct_mutex);
}
if (ifbdev->fb)
drm_framebuffer_remove(&ifbdev->fb->base);
kfree(ifbdev);
}
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
/*
* Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible.
* The core display code will have read out the current plane configuration,
* so we use that to figure out if there's an object for us to use as the
* fb, and if so, we re-use it for the fbdev configuration.
*
* Note we only support a single fb shared across pipes for boot (mostly for
* fbcon), so we just find the biggest and use that.
*/
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;
unsigned int max_size = 0;
/* Find the largest fb */
for_each_crtc(dev, crtc) {
struct drm_i915_gem_object *obj =
intel_fb_obj(crtc->primary->state->fb);
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
intel_crtc = to_intel_crtc(crtc);
if (!crtc->state->active || !obj) {
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
pipe_name(intel_crtc->pipe));
continue;
}
if (obj->base.size > max_size) {
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
DRM_DEBUG_KMS("found possible fb from plane %c\n",
pipe_name(intel_crtc->pipe));
fb = to_intel_framebuffer(crtc->primary->state->fb);
max_size = obj->base.size;
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
}
}
if (!fb) {
DRM_DEBUG_KMS("no active fbs found, not using BIOS config\n");
goto out;
}
/* Now make sure all the pipes will fit into it */
for_each_crtc(dev, crtc) {
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
unsigned int cur_size;
intel_crtc = to_intel_crtc(crtc);
if (!crtc->state->active) {
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
DRM_DEBUG_KMS("pipe %c not active, skipping\n",
pipe_name(intel_crtc->pipe));
continue;
}
DRM_DEBUG_KMS("checking plane %c for BIOS fb\n",
pipe_name(intel_crtc->pipe));
/*
* See if the plane fb we found above will fit on this
* pipe. Note we need to use the selected fb's pitch and bpp
* rather than the current pipe's, since they differ.
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
*/
cur_size = crtc->state->adjusted_mode.crtc_hdisplay;
drm: Nuke fb->bits_per_pixel Replace uses of fb->bits_per_pixel with fb->format->cpp[0]*8. Less duplicated information is a good thing. Note that I didn't put parens around the cpp*8 in the below cocci script, on account of not wanting spurious parens all over the place. Instead I did the unsafe way, and tried to look over the entire diff to spot if any dangerous expressions were produced. I didn't see any. There are some cases where previously the code did X*bpp/8, so the division happened after the multiplication. Those are now just X*cpp so the division effectively happens before the multiplication, but that is perfectly fine since bpp is always a multiple of 8. @@ struct drm_framebuffer *FB; expression E; @@ drm_helper_mode_fill_fb_struct(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ i9xx_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ ironlake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ skylake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer FB; expression E; @@ ( - E * FB.bits_per_pixel / 8 + E * FB.format->cpp[0] | - FB.bits_per_pixel / 8 + FB.format->cpp[0] | - E * FB.bits_per_pixel >> 3 + E * FB.format->cpp[0] | - FB.bits_per_pixel >> 3 + FB.format->cpp[0] | - (FB.bits_per_pixel + 7) / 8 + FB.format->cpp[0] | - FB.bits_per_pixel + FB.format->cpp[0] * 8 | - FB.format->cpp[0] * 8 != 8 + FB.format->cpp[0] != 1 ) @@ struct drm_framebuffer *FB; expression E; @@ ( - E * FB->bits_per_pixel / 8 + E * FB->format->cpp[0] | - FB->bits_per_pixel / 8 + FB->format->cpp[0] | - E * FB->bits_per_pixel >> 3 + E * FB->format->cpp[0] | - FB->bits_per_pixel >> 3 + FB->format->cpp[0] | - (FB->bits_per_pixel + 7) / 8 + FB->format->cpp[0] | - FB->bits_per_pixel + FB->format->cpp[0] * 8 | - FB->format->cpp[0] * 8 != 8 + FB->format->cpp[0] != 1 ) @@ struct drm_plane_state *state; expression E; @@ ( - E * state->fb->bits_per_pixel / 8 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel / 8 + state->fb->format->cpp[0] | - E * state->fb->bits_per_pixel >> 3 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel >> 3 + state->fb->format->cpp[0] | - (state->fb->bits_per_pixel + 7) / 8 + state->fb->format->cpp[0] | - state->fb->bits_per_pixel + state->fb->format->cpp[0] * 8 | - state->fb->format->cpp[0] * 8 != 8 + state->fb->format->cpp[0] != 1 ) @@ @@ - (8 * 8) + 8 * 8 @@ struct drm_framebuffer FB; @@ - (FB.format->cpp[0]) + FB.format->cpp[0] @@ struct drm_framebuffer *FB; @@ - (FB->format->cpp[0]) + FB->format->cpp[0] @@ @@ struct drm_framebuffer { ... - int bits_per_pixel; ... }; v2: Clean up the 'cpp*8 != 8' and '(8 * 8)' cases (Laurent) v3: Adjusted the semantic patch a bit and regenerated due to code changes Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1481751140-18352-1-git-send-email-ville.syrjala@linux.intel.com
2016-12-14 14:32:20 -07:00
cur_size = cur_size * fb->base.format->cpp[0];
if (fb->base.pitches[0] < cur_size) {
DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n",
pipe_name(intel_crtc->pipe),
cur_size, fb->base.pitches[0]);
fb = NULL;
break;
}
cur_size = crtc->state->adjusted_mode.crtc_vdisplay;
cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
cur_size *= fb->base.pitches[0];
DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n",
pipe_name(intel_crtc->pipe),
crtc->state->adjusted_mode.crtc_hdisplay,
crtc->state->adjusted_mode.crtc_vdisplay,
drm: Nuke fb->bits_per_pixel Replace uses of fb->bits_per_pixel with fb->format->cpp[0]*8. Less duplicated information is a good thing. Note that I didn't put parens around the cpp*8 in the below cocci script, on account of not wanting spurious parens all over the place. Instead I did the unsafe way, and tried to look over the entire diff to spot if any dangerous expressions were produced. I didn't see any. There are some cases where previously the code did X*bpp/8, so the division happened after the multiplication. Those are now just X*cpp so the division effectively happens before the multiplication, but that is perfectly fine since bpp is always a multiple of 8. @@ struct drm_framebuffer *FB; expression E; @@ drm_helper_mode_fill_fb_struct(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ i9xx_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ ironlake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ skylake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer FB; expression E; @@ ( - E * FB.bits_per_pixel / 8 + E * FB.format->cpp[0] | - FB.bits_per_pixel / 8 + FB.format->cpp[0] | - E * FB.bits_per_pixel >> 3 + E * FB.format->cpp[0] | - FB.bits_per_pixel >> 3 + FB.format->cpp[0] | - (FB.bits_per_pixel + 7) / 8 + FB.format->cpp[0] | - FB.bits_per_pixel + FB.format->cpp[0] * 8 | - FB.format->cpp[0] * 8 != 8 + FB.format->cpp[0] != 1 ) @@ struct drm_framebuffer *FB; expression E; @@ ( - E * FB->bits_per_pixel / 8 + E * FB->format->cpp[0] | - FB->bits_per_pixel / 8 + FB->format->cpp[0] | - E * FB->bits_per_pixel >> 3 + E * FB->format->cpp[0] | - FB->bits_per_pixel >> 3 + FB->format->cpp[0] | - (FB->bits_per_pixel + 7) / 8 + FB->format->cpp[0] | - FB->bits_per_pixel + FB->format->cpp[0] * 8 | - FB->format->cpp[0] * 8 != 8 + FB->format->cpp[0] != 1 ) @@ struct drm_plane_state *state; expression E; @@ ( - E * state->fb->bits_per_pixel / 8 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel / 8 + state->fb->format->cpp[0] | - E * state->fb->bits_per_pixel >> 3 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel >> 3 + state->fb->format->cpp[0] | - (state->fb->bits_per_pixel + 7) / 8 + state->fb->format->cpp[0] | - state->fb->bits_per_pixel + state->fb->format->cpp[0] * 8 | - state->fb->format->cpp[0] * 8 != 8 + state->fb->format->cpp[0] != 1 ) @@ @@ - (8 * 8) + 8 * 8 @@ struct drm_framebuffer FB; @@ - (FB.format->cpp[0]) + FB.format->cpp[0] @@ struct drm_framebuffer *FB; @@ - (FB->format->cpp[0]) + FB->format->cpp[0] @@ @@ struct drm_framebuffer { ... - int bits_per_pixel; ... }; v2: Clean up the 'cpp*8 != 8' and '(8 * 8)' cases (Laurent) v3: Adjusted the semantic patch a bit and regenerated due to code changes Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1481751140-18352-1-git-send-email-ville.syrjala@linux.intel.com
2016-12-14 14:32:20 -07:00
fb->base.format->cpp[0] * 8,
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
cur_size);
if (cur_size > max_size) {
DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n",
pipe_name(intel_crtc->pipe),
cur_size, max_size);
fb = NULL;
break;
}
DRM_DEBUG_KMS("fb big enough for plane %c (%d >= %d)\n",
pipe_name(intel_crtc->pipe),
max_size, cur_size);
}
if (!fb) {
DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n");
goto out;
}
drm: Nuke fb->bits_per_pixel Replace uses of fb->bits_per_pixel with fb->format->cpp[0]*8. Less duplicated information is a good thing. Note that I didn't put parens around the cpp*8 in the below cocci script, on account of not wanting spurious parens all over the place. Instead I did the unsafe way, and tried to look over the entire diff to spot if any dangerous expressions were produced. I didn't see any. There are some cases where previously the code did X*bpp/8, so the division happened after the multiplication. Those are now just X*cpp so the division effectively happens before the multiplication, but that is perfectly fine since bpp is always a multiple of 8. @@ struct drm_framebuffer *FB; expression E; @@ drm_helper_mode_fill_fb_struct(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ i9xx_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ ironlake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer *FB; expression E; @@ skylake_get_initial_plane_config(...) { ... - FB->bits_per_pixel = E; ... } @@ struct drm_framebuffer FB; expression E; @@ ( - E * FB.bits_per_pixel / 8 + E * FB.format->cpp[0] | - FB.bits_per_pixel / 8 + FB.format->cpp[0] | - E * FB.bits_per_pixel >> 3 + E * FB.format->cpp[0] | - FB.bits_per_pixel >> 3 + FB.format->cpp[0] | - (FB.bits_per_pixel + 7) / 8 + FB.format->cpp[0] | - FB.bits_per_pixel + FB.format->cpp[0] * 8 | - FB.format->cpp[0] * 8 != 8 + FB.format->cpp[0] != 1 ) @@ struct drm_framebuffer *FB; expression E; @@ ( - E * FB->bits_per_pixel / 8 + E * FB->format->cpp[0] | - FB->bits_per_pixel / 8 + FB->format->cpp[0] | - E * FB->bits_per_pixel >> 3 + E * FB->format->cpp[0] | - FB->bits_per_pixel >> 3 + FB->format->cpp[0] | - (FB->bits_per_pixel + 7) / 8 + FB->format->cpp[0] | - FB->bits_per_pixel + FB->format->cpp[0] * 8 | - FB->format->cpp[0] * 8 != 8 + FB->format->cpp[0] != 1 ) @@ struct drm_plane_state *state; expression E; @@ ( - E * state->fb->bits_per_pixel / 8 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel / 8 + state->fb->format->cpp[0] | - E * state->fb->bits_per_pixel >> 3 + E * state->fb->format->cpp[0] | - state->fb->bits_per_pixel >> 3 + state->fb->format->cpp[0] | - (state->fb->bits_per_pixel + 7) / 8 + state->fb->format->cpp[0] | - state->fb->bits_per_pixel + state->fb->format->cpp[0] * 8 | - state->fb->format->cpp[0] * 8 != 8 + state->fb->format->cpp[0] != 1 ) @@ @@ - (8 * 8) + 8 * 8 @@ struct drm_framebuffer FB; @@ - (FB.format->cpp[0]) + FB.format->cpp[0] @@ struct drm_framebuffer *FB; @@ - (FB->format->cpp[0]) + FB->format->cpp[0] @@ @@ struct drm_framebuffer { ... - int bits_per_pixel; ... }; v2: Clean up the 'cpp*8 != 8' and '(8 * 8)' cases (Laurent) v3: Adjusted the semantic patch a bit and regenerated due to code changes Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> (v1) Link: http://patchwork.freedesktop.org/patch/msgid/1481751140-18352-1-git-send-email-ville.syrjala@linux.intel.com
2016-12-14 14:32:20 -07:00
ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8;
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
ifbdev->fb = fb;
drm_framebuffer_get(&ifbdev->fb->base);
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
/* Final pass to check if any active pipes don't have fbs */
for_each_crtc(dev, crtc) {
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
intel_crtc = to_intel_crtc(crtc);
if (!crtc->state->active)
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
continue;
WARN(!crtc->primary->state->fb,
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
"re-used BIOS config but lost an fb on crtc %d\n",
crtc->base.id);
}
DRM_DEBUG_KMS("using BIOS fb for initial console\n");
return true;
out:
return false;
}
static void intel_fbdev_suspend_worker(struct work_struct *work)
{
intel_fbdev_set_suspend(&container_of(work,
struct drm_i915_private,
fbdev_suspend_work)->drm,
FBINFO_STATE_RUNNING,
true);
}
int intel_fbdev_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_fbdev *ifbdev;
int ret;
if (WARN_ON(!HAS_DISPLAY(dev_priv)))
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
return -ENODEV;
ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL);
if (ifbdev == NULL)
return -ENOMEM;
drm/i915: Block fbdev HPD processing during suspend When resuming, we check whether or not any previously connected MST topologies are still present and if so, attempt to resume them. If this fails, we disable said MST topologies and fire off a hotplug event so that userspace knows to reprobe. However, sending a hotplug event involves calling drm_fb_helper_hotplug_event(), which in turn results in fbcon doing a connector reprobe in the caller's thread - something we can't do at the point in which i915 calls drm_dp_mst_topology_mgr_resume() since hotplugging hasn't been fully initialized yet. This currently causes some rather subtle but fatal issues. For example, on my T480s the laptop dock connected to it usually disappears during a suspend cycle, and comes back up a short while after the system has been resumed. This guarantees pretty much every suspend and resume cycle, drm_dp_mst_topology_mgr_set_mst(mgr, false); will be caused and in turn, a connector hotplug will occur. Now it's Rute Goldberg time: when the connector hotplug occurs, i915 reprobes /all/ of the connectors, including eDP. However, eDP probing requires that we power on the panel VDD which in turn, grabs a wakeref to the appropriate power domain on the GPU (on my T480s, this is the PORT_DDI_A_IO domain). This is where things start breaking, since this all happens before intel_power_domains_enable() is called we end up leaking the wakeref that was acquired and never releasing it later. Come next suspend/resume cycle, this causes us to fail to shut down the GPU properly, which causes it not to resume properly and die a horrible complicated death. (as a note: this only happens when there's both an eDP panel and MST topology connected which is removed mid-suspend. One or the other seems to always be OK). We could try to fix the VDD wakeref leak, but this doesn't seem like it's worth it at all since we aren't able to handle hotplug detection while resuming anyway. So, let's go with a more robust solution inspired by nouveau: block fbdev from handling hotplug events until we resume fbdev. This allows us to still send sysfs hotplug events to be handled later by user space while we're resuming, while also preventing us from actually processing any hotplug events we receive until it's safe. This fixes the wakeref leak observed on the T480s and as such, also fixes suspend/resume with MST topologies connected on this machine. Changes since v2: * Don't call drm_fb_helper_hotplug_event() under lock, do it after lock (Chris Wilson) * Don't call drm_fb_helper_hotplug_event() in intel_fbdev_output_poll_changed() under lock (Chris Wilson) * Always set ifbdev->hpd_waiting (Chris Wilson) Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: Todd Previte <tprevite@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v3.17+ Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190129191001.442-2-lyude@redhat.com
2019-01-29 12:09:59 -07:00
mutex_init(&ifbdev->hpd_lock);
drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
if (!intel_fbdev_init_bios(dev, ifbdev))
ifbdev->preferred_bpp = 32;
drm: Rely on mode_config data for fb_helper initialization Instead of receiving the num_crts as a parameter, we can read it directly from the mode_config structure. I audited the drivers that invoke this helper and I believe all of them initialize the mode_config struct accordingly, prior to calling the fb_helper. I used the following coccinelle hack to make this transformation, except for the function headers and comment updates. The first and second rules are split because I couldn't find a way to remove the unused temporary variables at the same time I removed the parameter. // <smpl> @r@ expression A,B,D,E; identifier C; @@ ( - drm_fb_helper_init(A,B,C,D) + drm_fb_helper_init(A,B,D) | - drm_fbdev_cma_init_with_funcs(A,B,C,D,E) + drm_fbdev_cma_init_with_funcs(A,B,D,E) | - drm_fbdev_cma_init(A,B,C,D) + drm_fbdev_cma_init(A,B,D) ) @@ expression A,B,C,D,E; @@ ( - drm_fb_helper_init(A,B,C,D) + drm_fb_helper_init(A,B,D) | - drm_fbdev_cma_init_with_funcs(A,B,C,D,E) + drm_fbdev_cma_init_with_funcs(A,B,D,E) | - drm_fbdev_cma_init(A,B,C,D) + drm_fbdev_cma_init(A,B,D) ) @@ identifier r.C; type T; expression V; @@ - T C; <... when != C - C = V; ...> // </smpl> Changes since v1: - Rebased on top of the tip of drm-misc-next. - Remove mention to sti since a proper fix got merged. Suggested-by: Daniel Vetter <daniel.vetter@intel.com> Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.co.uk> Reviewed-by: Eric Anholt <eric@anholt.net> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> Link: http://patchwork.freedesktop.org/patch/msgid/20170202162640.27261-1-krisman@collabora.co.uk
2017-02-02 09:26:40 -07:00
ret = drm_fb_helper_init(dev, &ifbdev->helper, 4);
if (ret) {
kfree(ifbdev);
return ret;
}
drm/i915: Wrap the preallocated BIOS framebuffer and preserve for KMS fbcon v12 Retrieve current framebuffer config info from the regs and create an fb object for the buffer the BIOS or boot loader left us. This should allow for smooth transitions to userspace apps once we finish the initial configuration construction. v2: check for non-native modes and adjust (Jesse) fixup aperture and cmap frees (Imre) use unlocked unref if init_bios fails (Jesse) fix curly brace around DSPADDR check (Imre) comment failure path for pin_and_fence (Imre) v3: fixup fixup of aperture frees (Chris) v4: update to current bits (locking & pin_and_fence hack) (Jesse) v5: move fb config fetch to display code (Jesse) re-order hw state readout on initial load to suit fb inherit (Jesse) re-add pin_and_fence in fbdev code to make sure we refcount properly (Je v6: rename to plane_config (Daniel) check for valid object when initializing BIOS fb (Jesse) split from plane_config readout and other display changes (Jesse) drop use_bios_fb option (Chris) update comments (Jesse) rework fbdev_init_bios for clarity (Jesse) drop fb obj ref under lock (Chris) v7: use fb object from plane_config instead (Ville) take ref on fb object (Jesse) v8: put under i915_fastboot option (Jesse) fix fb ptr checking (Jesse) inform drm_fb_helper if we fail to enable a connector (Jesse) drop unnecessary enabled[] modifications in failure cases (Chris) split from BIOS connector config readout (Daniel) don't memset the fb buffer if preallocated (Chris) alloc ifbdev up front and pass to init_bios (Chris) check for bad ifbdev in restore_mode too (Chris) v9: fix up !fastboot bpp setting (Jesse) fix up !fastboot helper alloc (Jesse) make sure BIOS fb is sufficient for biggest active pipe (Jesse) v10:fix up size calculation for proposed fbs (Chris) go back to two pass pipe fb assignment (Chris) add warning for active pipes w/o fbs (Chris) clean up num_pipes checks in fbdev_init and fbdev_restore_mode (Chris) move i915.fastboot into fbdev_init (Chris) v11:make BIOS connector config usage unconditional (Daniel) v12:fix up fb vs pipe size checking (Chris) Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2014-03-07 09:57:51 -07:00
dev_priv->fbdev = ifbdev;
INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
drm/i915: Fixup hpd irq register setup ordering For GMCH platforms we set up the hpd irq registers in the irq postinstall hook. But since we only enable the irq sources we actually need in PORT_HOTPLUG_EN/STATUS, taking dev_priv->hotplug_supported_mask into account, no hpd interrupt sources is enabled since commit 52d7ecedac3f96fb562cb482c139015372728638 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat Dec 1 21:03:22 2012 +0100 drm/i915: reorder setup sequence to have irqs for output setup Wrongly set-up interrupts also lead to broken hw-based load-detection on at least GM45, resulting in ghost VGA/TV-out outputs. To fix this, delay the hotplug register setup until after all outputs are set up, by moving it into a new dev_priv->display.hpd_irq_callback. We might also move the PCH_SPLIT platforms to such a setup eventually. Another funny part is that we need to delay the fbdev initial config probing until after the hpd regs are setup, for otherwise it'll detect ghost outputs. But we can only enable the hpd interrupt handling itself (and the output polling) _after_ that initial scan, due to massive locking brain-damage in the fbdev setup code. Add a big comment to explain this cute little dragon lair. v2: Encapsulate all the fbdev handling by wrapping the move call into intel_fbdev_initial_config in intel_fb.c. Requested by Chris Wilson. v3: Applied bikeshed from Jesse Barnes. v4: Imre Deak noticed that we also need to call intel_hpd_init after the drm_irqinstall calls in the gpu reset and resume paths - otherwise hotplug will be broken. Also improve the comment a bit about why hpd_init needs to be called before we set up the initial fbdev config. Bugzilla: Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54943 Reported-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v3) Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 06:05:07 -07:00
return 0;
}
static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
drm/i915: Fixup hpd irq register setup ordering For GMCH platforms we set up the hpd irq registers in the irq postinstall hook. But since we only enable the irq sources we actually need in PORT_HOTPLUG_EN/STATUS, taking dev_priv->hotplug_supported_mask into account, no hpd interrupt sources is enabled since commit 52d7ecedac3f96fb562cb482c139015372728638 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat Dec 1 21:03:22 2012 +0100 drm/i915: reorder setup sequence to have irqs for output setup Wrongly set-up interrupts also lead to broken hw-based load-detection on at least GM45, resulting in ghost VGA/TV-out outputs. To fix this, delay the hotplug register setup until after all outputs are set up, by moving it into a new dev_priv->display.hpd_irq_callback. We might also move the PCH_SPLIT platforms to such a setup eventually. Another funny part is that we need to delay the fbdev initial config probing until after the hpd regs are setup, for otherwise it'll detect ghost outputs. But we can only enable the hpd interrupt handling itself (and the output polling) _after_ that initial scan, due to massive locking brain-damage in the fbdev setup code. Add a big comment to explain this cute little dragon lair. v2: Encapsulate all the fbdev handling by wrapping the move call into intel_fbdev_initial_config in intel_fb.c. Requested by Chris Wilson. v3: Applied bikeshed from Jesse Barnes. v4: Imre Deak noticed that we also need to call intel_hpd_init after the drm_irqinstall calls in the gpu reset and resume paths - otherwise hotplug will be broken. Also improve the comment a bit about why hpd_init needs to be called before we set up the initial fbdev config. Bugzilla: Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54943 Reported-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v3) Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 06:05:07 -07:00
{
struct intel_fbdev *ifbdev = data;
drm/i915: Fixup hpd irq register setup ordering For GMCH platforms we set up the hpd irq registers in the irq postinstall hook. But since we only enable the irq sources we actually need in PORT_HOTPLUG_EN/STATUS, taking dev_priv->hotplug_supported_mask into account, no hpd interrupt sources is enabled since commit 52d7ecedac3f96fb562cb482c139015372728638 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat Dec 1 21:03:22 2012 +0100 drm/i915: reorder setup sequence to have irqs for output setup Wrongly set-up interrupts also lead to broken hw-based load-detection on at least GM45, resulting in ghost VGA/TV-out outputs. To fix this, delay the hotplug register setup until after all outputs are set up, by moving it into a new dev_priv->display.hpd_irq_callback. We might also move the PCH_SPLIT platforms to such a setup eventually. Another funny part is that we need to delay the fbdev initial config probing until after the hpd regs are setup, for otherwise it'll detect ghost outputs. But we can only enable the hpd interrupt handling itself (and the output polling) _after_ that initial scan, due to massive locking brain-damage in the fbdev setup code. Add a big comment to explain this cute little dragon lair. v2: Encapsulate all the fbdev handling by wrapping the move call into intel_fbdev_initial_config in intel_fb.c. Requested by Chris Wilson. v3: Applied bikeshed from Jesse Barnes. v4: Imre Deak noticed that we also need to call intel_hpd_init after the drm_irqinstall calls in the gpu reset and resume paths - otherwise hotplug will be broken. Also improve the comment a bit about why hpd_init needs to be called before we set up the initial fbdev config. Bugzilla: Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54943 Reported-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v3) Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 06:05:07 -07:00
/* Due to peculiar init order wrt to hpd handling this is separate. */
drm/i915: Tear down fbdev if initialization fails Currently if intelfb_create() errors out, it unrefs the bo even though the fb now owns that reference. (Spotted by Ville Syrjälä.) We should unref the fb instead of the bo. However the fb was not necessarily allocated by intelfb_create(), it could be inherited from BIOS (the fb struct was then allocated by dev_priv->display.get_initial_plane_config()) and be in active use by a crtc. In this case we should call drm_framebuffer_remove() instead of _unreference() to also disable the crtc. Daniel Vetter suggested that "fbdev teardown code will take care of it. The correct approach is probably to not unref anything at all". But if fbdev initialization fails, the fbdev isn't torn down and occupies memory even though it's unusable. Therefore clobber it in intel_fbdev_initial_config(). (Currently we ignore a negative return value there.) The idea is that if fbdev initialization fails, the driver behaves as if CONFIG_DRM_FBDEV_EMULATION wasn't set. Should X11 manage to start up without errors, it will at least be able to use the memory that would otherwise be hogged by the unusable fbdev. Also, log errors in intelfb_create(). Don't call async_synchronize_full() in intel_fbdev_fini() when called from intel_fbdev_initial_config() to avoid deadlock. v2: Instead of calling drm_framebuffer_unreference() (if fb was not inherited from BIOS), call intel_fbdev_fini(). v3: Rebase on e00bf69644ba (drm/i915: Move the fbdev async_schedule() into intel_fbdev.c), call async_synchronize_full() conditionally instead of moving it into i915_driver_unload(). Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: http://patchwork.freedesktop.org/patch/msgid/49ce5f0daead24b7598ec78591731046c333c18d.1447938059.git.lukas@wunner.de Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-11-18 08:29:51 -07:00
if (drm_fb_helper_initial_config(&ifbdev->helper,
drm/i915/fbdev: Serialise early hotplug events with async fbdev config As both the hotplug event and fbdev configuration run asynchronously, it is possible for them to run concurrently. If configuration fails, we were freeing the fbdev causing a use-after-free in the hotplug event. <7>[ 3069.935211] [drm:intel_fb_initial_config [i915]] Not using firmware configuration <7>[ 3069.935225] [drm:drm_setup_crtcs] looking for cmdline mode on connector 77 <7>[ 3069.935229] [drm:drm_setup_crtcs] looking for preferred mode on connector 77 0 <7>[ 3069.935233] [drm:drm_setup_crtcs] found mode 3200x1800 <7>[ 3069.935236] [drm:drm_setup_crtcs] picking CRTCs for 8192x8192 config <7>[ 3069.935253] [drm:drm_setup_crtcs] desired mode 3200x1800 set on crtc 43 (0,0) <7>[ 3069.935323] [drm:intelfb_create [i915]] no BIOS fb, allocating a new one <4>[ 3069.967737] general protection fault: 0000 [#1] PREEMPT SMP <0>[ 3069.977453] --------------------------------- <4>[ 3069.977457] Modules linked in: i915(+) vgem snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm r8169 mei_me mii prime_numbers mei i2c_hid pinctrl_geminilake pinctrl_intel [last unloaded: i915] <4>[ 3069.977492] CPU: 1 PID: 15414 Comm: kworker/1:0 Tainted: G U 4.14.0-CI-CI_DRM_3388+ #1 <4>[ 3069.977497] Hardware name: Intel Corp. Geminilake/GLK RVP1 DDR4 (05), BIOS GELKRVPA.X64.0062.B30.1708222146 08/22/2017 <4>[ 3069.977508] Workqueue: events output_poll_execute <4>[ 3069.977512] task: ffff880177734e40 task.stack: ffffc90001fe4000 <4>[ 3069.977519] RIP: 0010:__lock_acquire+0x109/0x1b60 <4>[ 3069.977523] RSP: 0018:ffffc90001fe7bb0 EFLAGS: 00010002 <4>[ 3069.977526] RAX: 6b6b6b6b6b6b6b6b RBX: 0000000000000282 RCX: 0000000000000000 <4>[ 3069.977530] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880170d4efd0 <4>[ 3069.977534] RBP: ffffc90001fe7c70 R08: 0000000000000001 R09: 0000000000000000 <4>[ 3069.977538] R10: 0000000000000000 R11: ffffffff81899609 R12: ffff880170d4efd0 <4>[ 3069.977542] R13: ffff880177734e40 R14: 0000000000000001 R15: 0000000000000000 <4>[ 3069.977547] FS: 0000000000000000(0000) GS:ffff88017fc80000(0000) knlGS:0000000000000000 <4>[ 3069.977551] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 3069.977555] CR2: 00007f7e8b7bcf04 CR3: 0000000003e0f000 CR4: 00000000003406e0 <4>[ 3069.977559] Call Trace: <4>[ 3069.977565] ? mark_held_locks+0x64/0x90 <4>[ 3069.977571] ? _raw_spin_unlock_irq+0x24/0x50 <4>[ 3069.977575] ? _raw_spin_unlock_irq+0x24/0x50 <4>[ 3069.977579] ? trace_hardirqs_on_caller+0xde/0x1c0 <4>[ 3069.977583] ? _raw_spin_unlock_irq+0x2f/0x50 <4>[ 3069.977588] ? finish_task_switch+0xa5/0x210 <4>[ 3069.977592] ? lock_acquire+0xaf/0x200 <4>[ 3069.977596] lock_acquire+0xaf/0x200 <4>[ 3069.977600] ? __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977604] _raw_spin_lock+0x2a/0x40 <4>[ 3069.977608] ? __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977612] __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977616] ? drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977621] ? drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977625] drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977630] output_poll_execute+0x8d/0x180 <4>[ 3069.977635] process_one_work+0x22e/0x660 <4>[ 3069.977640] worker_thread+0x48/0x3a0 <4>[ 3069.977644] ? _raw_spin_unlock_irqrestore+0x4c/0x60 <4>[ 3069.977649] kthread+0x102/0x140 <4>[ 3069.977653] ? process_one_work+0x660/0x660 <4>[ 3069.977657] ? kthread_create_on_node+0x40/0x40 <4>[ 3069.977662] ret_from_fork+0x27/0x40 <4>[ 3069.977666] Code: 8d 62 f8 c3 49 81 3c 24 e0 fa 3c 82 41 be 00 00 00 00 45 0f 45 f0 83 fe 01 77 86 89 f0 49 8b 44 c4 08 48 85 c0 0f 84 76 ff ff ff <f0> ff 80 38 01 00 00 8b 1d 62 f9 e8 01 45 8b 85 b8 08 00 00 85 <1>[ 3069.977707] RIP: __lock_acquire+0x109/0x1b60 RSP: ffffc90001fe7bb0 <4>[ 3069.977712] ---[ end trace 4ad012eb3af62df7 ]--- In order to keep the dev_priv->ifbdev alive after failure, we have to avoid the free and leave it empty until we unload the module (which is less than ideal, but a necessary evil for simplicity). Then we can use intel_fbdev_sync() to serialise the hotplug event with the configuration. The serialisation between the two was removed in commit 934458c2c95d ("Revert "drm/i915: Fix races on fbdev""), but the use after free is much older, commit 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails") Fixes: 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails") Fixes: 934458c2c95d ("Revert "drm/i915: Fix races on fbdev"") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Lukas Wunner <lukas@wunner.de> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: stable@vger.kernel.org Reviewed-by: Lukas Wunner <lukas@wunner.de> Link: https://patchwork.freedesktop.org/patch/msgid/20171125194155.355-1-chris@chris-wilson.co.uk
2017-11-25 12:41:55 -07:00
ifbdev->preferred_bpp))
intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
drm/i915: Fixup hpd irq register setup ordering For GMCH platforms we set up the hpd irq registers in the irq postinstall hook. But since we only enable the irq sources we actually need in PORT_HOTPLUG_EN/STATUS, taking dev_priv->hotplug_supported_mask into account, no hpd interrupt sources is enabled since commit 52d7ecedac3f96fb562cb482c139015372728638 Author: Daniel Vetter <daniel.vetter@ffwll.ch> Date: Sat Dec 1 21:03:22 2012 +0100 drm/i915: reorder setup sequence to have irqs for output setup Wrongly set-up interrupts also lead to broken hw-based load-detection on at least GM45, resulting in ghost VGA/TV-out outputs. To fix this, delay the hotplug register setup until after all outputs are set up, by moving it into a new dev_priv->display.hpd_irq_callback. We might also move the PCH_SPLIT platforms to such a setup eventually. Another funny part is that we need to delay the fbdev initial config probing until after the hpd regs are setup, for otherwise it'll detect ghost outputs. But we can only enable the hpd interrupt handling itself (and the output polling) _after_ that initial scan, due to massive locking brain-damage in the fbdev setup code. Add a big comment to explain this cute little dragon lair. v2: Encapsulate all the fbdev handling by wrapping the move call into intel_fbdev_initial_config in intel_fb.c. Requested by Chris Wilson. v3: Applied bikeshed from Jesse Barnes. v4: Imre Deak noticed that we also need to call intel_hpd_init after the drm_irqinstall calls in the gpu reset and resume paths - otherwise hotplug will be broken. Also improve the comment a bit about why hpd_init needs to be called before we set up the initial fbdev config. Bugzilla: Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=54943 Reported-by: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> (v3) Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2012-12-11 06:05:07 -07:00
}
void intel_fbdev_initial_config_async(struct drm_device *dev)
{
struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
if (!ifbdev)
return;
ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
}
static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
{
if (!ifbdev->cookie)
return;
/* Only serialises with all preceding async calls, hence +1 */
async_synchronize_cookie(ifbdev->cookie + 1);
ifbdev->cookie = 0;
}
void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
{
struct intel_fbdev *ifbdev = dev_priv->fbdev;
if (!ifbdev)
return;
cancel_work_sync(&dev_priv->fbdev_suspend_work);
drm/i915: Tear down fbdev if initialization fails Currently if intelfb_create() errors out, it unrefs the bo even though the fb now owns that reference. (Spotted by Ville Syrjälä.) We should unref the fb instead of the bo. However the fb was not necessarily allocated by intelfb_create(), it could be inherited from BIOS (the fb struct was then allocated by dev_priv->display.get_initial_plane_config()) and be in active use by a crtc. In this case we should call drm_framebuffer_remove() instead of _unreference() to also disable the crtc. Daniel Vetter suggested that "fbdev teardown code will take care of it. The correct approach is probably to not unref anything at all". But if fbdev initialization fails, the fbdev isn't torn down and occupies memory even though it's unusable. Therefore clobber it in intel_fbdev_initial_config(). (Currently we ignore a negative return value there.) The idea is that if fbdev initialization fails, the driver behaves as if CONFIG_DRM_FBDEV_EMULATION wasn't set. Should X11 manage to start up without errors, it will at least be able to use the memory that would otherwise be hogged by the unusable fbdev. Also, log errors in intelfb_create(). Don't call async_synchronize_full() in intel_fbdev_fini() when called from intel_fbdev_initial_config() to avoid deadlock. v2: Instead of calling drm_framebuffer_unreference() (if fb was not inherited from BIOS), call intel_fbdev_fini(). v3: Rebase on e00bf69644ba (drm/i915: Move the fbdev async_schedule() into intel_fbdev.c), call async_synchronize_full() conditionally instead of moving it into i915_driver_unload(). Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Lukas Wunner <lukas@wunner.de> Link: http://patchwork.freedesktop.org/patch/msgid/49ce5f0daead24b7598ec78591731046c333c18d.1447938059.git.lukas@wunner.de Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-11-18 08:29:51 -07:00
if (!current_is_async())
intel_fbdev_sync(ifbdev);
drm_fb_helper_unregister_fbi(&ifbdev->helper);
}
void intel_fbdev_fini(struct drm_i915_private *dev_priv)
{
struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->fbdev);
if (!ifbdev)
return;
intel_fbdev_destroy(ifbdev);
}
drm/i915: Block fbdev HPD processing during suspend When resuming, we check whether or not any previously connected MST topologies are still present and if so, attempt to resume them. If this fails, we disable said MST topologies and fire off a hotplug event so that userspace knows to reprobe. However, sending a hotplug event involves calling drm_fb_helper_hotplug_event(), which in turn results in fbcon doing a connector reprobe in the caller's thread - something we can't do at the point in which i915 calls drm_dp_mst_topology_mgr_resume() since hotplugging hasn't been fully initialized yet. This currently causes some rather subtle but fatal issues. For example, on my T480s the laptop dock connected to it usually disappears during a suspend cycle, and comes back up a short while after the system has been resumed. This guarantees pretty much every suspend and resume cycle, drm_dp_mst_topology_mgr_set_mst(mgr, false); will be caused and in turn, a connector hotplug will occur. Now it's Rute Goldberg time: when the connector hotplug occurs, i915 reprobes /all/ of the connectors, including eDP. However, eDP probing requires that we power on the panel VDD which in turn, grabs a wakeref to the appropriate power domain on the GPU (on my T480s, this is the PORT_DDI_A_IO domain). This is where things start breaking, since this all happens before intel_power_domains_enable() is called we end up leaking the wakeref that was acquired and never releasing it later. Come next suspend/resume cycle, this causes us to fail to shut down the GPU properly, which causes it not to resume properly and die a horrible complicated death. (as a note: this only happens when there's both an eDP panel and MST topology connected which is removed mid-suspend. One or the other seems to always be OK). We could try to fix the VDD wakeref leak, but this doesn't seem like it's worth it at all since we aren't able to handle hotplug detection while resuming anyway. So, let's go with a more robust solution inspired by nouveau: block fbdev from handling hotplug events until we resume fbdev. This allows us to still send sysfs hotplug events to be handled later by user space while we're resuming, while also preventing us from actually processing any hotplug events we receive until it's safe. This fixes the wakeref leak observed on the T480s and as such, also fixes suspend/resume with MST topologies connected on this machine. Changes since v2: * Don't call drm_fb_helper_hotplug_event() under lock, do it after lock (Chris Wilson) * Don't call drm_fb_helper_hotplug_event() in intel_fbdev_output_poll_changed() under lock (Chris Wilson) * Always set ifbdev->hpd_waiting (Chris Wilson) Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: Todd Previte <tprevite@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v3.17+ Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190129191001.442-2-lyude@redhat.com
2019-01-29 12:09:59 -07:00
/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
* processing, fbdev will perform a full connector reprobe if a hotplug event
* was received while HPD was suspended.
*/
static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
{
bool send_hpd = false;
mutex_lock(&ifbdev->hpd_lock);
ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
ifbdev->hpd_waiting = false;
mutex_unlock(&ifbdev->hpd_lock);
if (send_hpd) {
DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
drm_fb_helper_hotplug_event(&ifbdev->helper);
}
}
void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct intel_fbdev *ifbdev = dev_priv->fbdev;
struct fb_info *info;
if (!ifbdev || !ifbdev->vma)
return;
info = ifbdev->helper.fbdev;
if (synchronous) {
/* Flush any pending work to turn the console on, and then
* wait to turn it off. It must be synchronous as we are
* about to suspend or unload the driver.
*
* Note that from within the work-handler, we cannot flush
* ourselves, so only flush outstanding work upon suspend!
*/
if (state != FBINFO_STATE_RUNNING)
flush_work(&dev_priv->fbdev_suspend_work);
drm/i915: Block fbdev HPD processing during suspend When resuming, we check whether or not any previously connected MST topologies are still present and if so, attempt to resume them. If this fails, we disable said MST topologies and fire off a hotplug event so that userspace knows to reprobe. However, sending a hotplug event involves calling drm_fb_helper_hotplug_event(), which in turn results in fbcon doing a connector reprobe in the caller's thread - something we can't do at the point in which i915 calls drm_dp_mst_topology_mgr_resume() since hotplugging hasn't been fully initialized yet. This currently causes some rather subtle but fatal issues. For example, on my T480s the laptop dock connected to it usually disappears during a suspend cycle, and comes back up a short while after the system has been resumed. This guarantees pretty much every suspend and resume cycle, drm_dp_mst_topology_mgr_set_mst(mgr, false); will be caused and in turn, a connector hotplug will occur. Now it's Rute Goldberg time: when the connector hotplug occurs, i915 reprobes /all/ of the connectors, including eDP. However, eDP probing requires that we power on the panel VDD which in turn, grabs a wakeref to the appropriate power domain on the GPU (on my T480s, this is the PORT_DDI_A_IO domain). This is where things start breaking, since this all happens before intel_power_domains_enable() is called we end up leaking the wakeref that was acquired and never releasing it later. Come next suspend/resume cycle, this causes us to fail to shut down the GPU properly, which causes it not to resume properly and die a horrible complicated death. (as a note: this only happens when there's both an eDP panel and MST topology connected which is removed mid-suspend. One or the other seems to always be OK). We could try to fix the VDD wakeref leak, but this doesn't seem like it's worth it at all since we aren't able to handle hotplug detection while resuming anyway. So, let's go with a more robust solution inspired by nouveau: block fbdev from handling hotplug events until we resume fbdev. This allows us to still send sysfs hotplug events to be handled later by user space while we're resuming, while also preventing us from actually processing any hotplug events we receive until it's safe. This fixes the wakeref leak observed on the T480s and as such, also fixes suspend/resume with MST topologies connected on this machine. Changes since v2: * Don't call drm_fb_helper_hotplug_event() under lock, do it after lock (Chris Wilson) * Don't call drm_fb_helper_hotplug_event() in intel_fbdev_output_poll_changed() under lock (Chris Wilson) * Always set ifbdev->hpd_waiting (Chris Wilson) Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: Todd Previte <tprevite@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v3.17+ Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190129191001.442-2-lyude@redhat.com
2019-01-29 12:09:59 -07:00
console_lock();
} else {
/*
* The console lock can be pretty contented on resume due
* to all the printk activity. Try to keep it out of the hot
* path of resume if possible.
*/
WARN_ON(state != FBINFO_STATE_RUNNING);
if (!console_trylock()) {
/* Don't block our own workqueue as this can
* be run in parallel with other i915.ko tasks.
*/
schedule_work(&dev_priv->fbdev_suspend_work);
return;
}
}
/* On resume from hibernation: If the object is shmemfs backed, it has
* been restored from swap. If the object is stolen however, it will be
* full of whatever garbage was left in there.
*/
if (state == FBINFO_STATE_RUNNING &&
intel_fb_obj(&ifbdev->fb->base)->stolen)
memset_io(info->screen_base, 0, info->screen_size);
drm_fb_helper_set_suspend(&ifbdev->helper, state);
console_unlock();
drm/i915: Block fbdev HPD processing during suspend When resuming, we check whether or not any previously connected MST topologies are still present and if so, attempt to resume them. If this fails, we disable said MST topologies and fire off a hotplug event so that userspace knows to reprobe. However, sending a hotplug event involves calling drm_fb_helper_hotplug_event(), which in turn results in fbcon doing a connector reprobe in the caller's thread - something we can't do at the point in which i915 calls drm_dp_mst_topology_mgr_resume() since hotplugging hasn't been fully initialized yet. This currently causes some rather subtle but fatal issues. For example, on my T480s the laptop dock connected to it usually disappears during a suspend cycle, and comes back up a short while after the system has been resumed. This guarantees pretty much every suspend and resume cycle, drm_dp_mst_topology_mgr_set_mst(mgr, false); will be caused and in turn, a connector hotplug will occur. Now it's Rute Goldberg time: when the connector hotplug occurs, i915 reprobes /all/ of the connectors, including eDP. However, eDP probing requires that we power on the panel VDD which in turn, grabs a wakeref to the appropriate power domain on the GPU (on my T480s, this is the PORT_DDI_A_IO domain). This is where things start breaking, since this all happens before intel_power_domains_enable() is called we end up leaking the wakeref that was acquired and never releasing it later. Come next suspend/resume cycle, this causes us to fail to shut down the GPU properly, which causes it not to resume properly and die a horrible complicated death. (as a note: this only happens when there's both an eDP panel and MST topology connected which is removed mid-suspend. One or the other seems to always be OK). We could try to fix the VDD wakeref leak, but this doesn't seem like it's worth it at all since we aren't able to handle hotplug detection while resuming anyway. So, let's go with a more robust solution inspired by nouveau: block fbdev from handling hotplug events until we resume fbdev. This allows us to still send sysfs hotplug events to be handled later by user space while we're resuming, while also preventing us from actually processing any hotplug events we receive until it's safe. This fixes the wakeref leak observed on the T480s and as such, also fixes suspend/resume with MST topologies connected on this machine. Changes since v2: * Don't call drm_fb_helper_hotplug_event() under lock, do it after lock (Chris Wilson) * Don't call drm_fb_helper_hotplug_event() in intel_fbdev_output_poll_changed() under lock (Chris Wilson) * Always set ifbdev->hpd_waiting (Chris Wilson) Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: Todd Previte <tprevite@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v3.17+ Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190129191001.442-2-lyude@redhat.com
2019-01-29 12:09:59 -07:00
intel_fbdev_hpd_set_suspend(ifbdev, state);
}
void intel_fbdev_output_poll_changed(struct drm_device *dev)
{
struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
drm/i915: Block fbdev HPD processing during suspend When resuming, we check whether or not any previously connected MST topologies are still present and if so, attempt to resume them. If this fails, we disable said MST topologies and fire off a hotplug event so that userspace knows to reprobe. However, sending a hotplug event involves calling drm_fb_helper_hotplug_event(), which in turn results in fbcon doing a connector reprobe in the caller's thread - something we can't do at the point in which i915 calls drm_dp_mst_topology_mgr_resume() since hotplugging hasn't been fully initialized yet. This currently causes some rather subtle but fatal issues. For example, on my T480s the laptop dock connected to it usually disappears during a suspend cycle, and comes back up a short while after the system has been resumed. This guarantees pretty much every suspend and resume cycle, drm_dp_mst_topology_mgr_set_mst(mgr, false); will be caused and in turn, a connector hotplug will occur. Now it's Rute Goldberg time: when the connector hotplug occurs, i915 reprobes /all/ of the connectors, including eDP. However, eDP probing requires that we power on the panel VDD which in turn, grabs a wakeref to the appropriate power domain on the GPU (on my T480s, this is the PORT_DDI_A_IO domain). This is where things start breaking, since this all happens before intel_power_domains_enable() is called we end up leaking the wakeref that was acquired and never releasing it later. Come next suspend/resume cycle, this causes us to fail to shut down the GPU properly, which causes it not to resume properly and die a horrible complicated death. (as a note: this only happens when there's both an eDP panel and MST topology connected which is removed mid-suspend. One or the other seems to always be OK). We could try to fix the VDD wakeref leak, but this doesn't seem like it's worth it at all since we aren't able to handle hotplug detection while resuming anyway. So, let's go with a more robust solution inspired by nouveau: block fbdev from handling hotplug events until we resume fbdev. This allows us to still send sysfs hotplug events to be handled later by user space while we're resuming, while also preventing us from actually processing any hotplug events we receive until it's safe. This fixes the wakeref leak observed on the T480s and as such, also fixes suspend/resume with MST topologies connected on this machine. Changes since v2: * Don't call drm_fb_helper_hotplug_event() under lock, do it after lock (Chris Wilson) * Don't call drm_fb_helper_hotplug_event() in intel_fbdev_output_poll_changed() under lock (Chris Wilson) * Always set ifbdev->hpd_waiting (Chris Wilson) Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: Todd Previte <tprevite@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v3.17+ Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190129191001.442-2-lyude@redhat.com
2019-01-29 12:09:59 -07:00
bool send_hpd;
drm/i915/fbdev: Serialise early hotplug events with async fbdev config As both the hotplug event and fbdev configuration run asynchronously, it is possible for them to run concurrently. If configuration fails, we were freeing the fbdev causing a use-after-free in the hotplug event. <7>[ 3069.935211] [drm:intel_fb_initial_config [i915]] Not using firmware configuration <7>[ 3069.935225] [drm:drm_setup_crtcs] looking for cmdline mode on connector 77 <7>[ 3069.935229] [drm:drm_setup_crtcs] looking for preferred mode on connector 77 0 <7>[ 3069.935233] [drm:drm_setup_crtcs] found mode 3200x1800 <7>[ 3069.935236] [drm:drm_setup_crtcs] picking CRTCs for 8192x8192 config <7>[ 3069.935253] [drm:drm_setup_crtcs] desired mode 3200x1800 set on crtc 43 (0,0) <7>[ 3069.935323] [drm:intelfb_create [i915]] no BIOS fb, allocating a new one <4>[ 3069.967737] general protection fault: 0000 [#1] PREEMPT SMP <0>[ 3069.977453] --------------------------------- <4>[ 3069.977457] Modules linked in: i915(+) vgem snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic x86_pkg_temp_thermal intel_powerclamp coretemp crct10dif_pclmul crc32_pclmul ghash_clmulni_intel snd_hda_codec snd_hwdep snd_hda_core snd_pcm r8169 mei_me mii prime_numbers mei i2c_hid pinctrl_geminilake pinctrl_intel [last unloaded: i915] <4>[ 3069.977492] CPU: 1 PID: 15414 Comm: kworker/1:0 Tainted: G U 4.14.0-CI-CI_DRM_3388+ #1 <4>[ 3069.977497] Hardware name: Intel Corp. Geminilake/GLK RVP1 DDR4 (05), BIOS GELKRVPA.X64.0062.B30.1708222146 08/22/2017 <4>[ 3069.977508] Workqueue: events output_poll_execute <4>[ 3069.977512] task: ffff880177734e40 task.stack: ffffc90001fe4000 <4>[ 3069.977519] RIP: 0010:__lock_acquire+0x109/0x1b60 <4>[ 3069.977523] RSP: 0018:ffffc90001fe7bb0 EFLAGS: 00010002 <4>[ 3069.977526] RAX: 6b6b6b6b6b6b6b6b RBX: 0000000000000282 RCX: 0000000000000000 <4>[ 3069.977530] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880170d4efd0 <4>[ 3069.977534] RBP: ffffc90001fe7c70 R08: 0000000000000001 R09: 0000000000000000 <4>[ 3069.977538] R10: 0000000000000000 R11: ffffffff81899609 R12: ffff880170d4efd0 <4>[ 3069.977542] R13: ffff880177734e40 R14: 0000000000000001 R15: 0000000000000000 <4>[ 3069.977547] FS: 0000000000000000(0000) GS:ffff88017fc80000(0000) knlGS:0000000000000000 <4>[ 3069.977551] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 <4>[ 3069.977555] CR2: 00007f7e8b7bcf04 CR3: 0000000003e0f000 CR4: 00000000003406e0 <4>[ 3069.977559] Call Trace: <4>[ 3069.977565] ? mark_held_locks+0x64/0x90 <4>[ 3069.977571] ? _raw_spin_unlock_irq+0x24/0x50 <4>[ 3069.977575] ? _raw_spin_unlock_irq+0x24/0x50 <4>[ 3069.977579] ? trace_hardirqs_on_caller+0xde/0x1c0 <4>[ 3069.977583] ? _raw_spin_unlock_irq+0x2f/0x50 <4>[ 3069.977588] ? finish_task_switch+0xa5/0x210 <4>[ 3069.977592] ? lock_acquire+0xaf/0x200 <4>[ 3069.977596] lock_acquire+0xaf/0x200 <4>[ 3069.977600] ? __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977604] _raw_spin_lock+0x2a/0x40 <4>[ 3069.977608] ? __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977612] __mutex_lock+0x5e9/0x9b0 <4>[ 3069.977616] ? drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977621] ? drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977625] drm_fb_helper_hotplug_event.part.19+0x16/0xa0 <4>[ 3069.977630] output_poll_execute+0x8d/0x180 <4>[ 3069.977635] process_one_work+0x22e/0x660 <4>[ 3069.977640] worker_thread+0x48/0x3a0 <4>[ 3069.977644] ? _raw_spin_unlock_irqrestore+0x4c/0x60 <4>[ 3069.977649] kthread+0x102/0x140 <4>[ 3069.977653] ? process_one_work+0x660/0x660 <4>[ 3069.977657] ? kthread_create_on_node+0x40/0x40 <4>[ 3069.977662] ret_from_fork+0x27/0x40 <4>[ 3069.977666] Code: 8d 62 f8 c3 49 81 3c 24 e0 fa 3c 82 41 be 00 00 00 00 45 0f 45 f0 83 fe 01 77 86 89 f0 49 8b 44 c4 08 48 85 c0 0f 84 76 ff ff ff <f0> ff 80 38 01 00 00 8b 1d 62 f9 e8 01 45 8b 85 b8 08 00 00 85 <1>[ 3069.977707] RIP: __lock_acquire+0x109/0x1b60 RSP: ffffc90001fe7bb0 <4>[ 3069.977712] ---[ end trace 4ad012eb3af62df7 ]--- In order to keep the dev_priv->ifbdev alive after failure, we have to avoid the free and leave it empty until we unload the module (which is less than ideal, but a necessary evil for simplicity). Then we can use intel_fbdev_sync() to serialise the hotplug event with the configuration. The serialisation between the two was removed in commit 934458c2c95d ("Revert "drm/i915: Fix races on fbdev""), but the use after free is much older, commit 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails") Fixes: 366e39b4d2c5 ("drm/i915: Tear down fbdev if initialization fails") Fixes: 934458c2c95d ("Revert "drm/i915: Fix races on fbdev"") Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Lukas Wunner <lukas@wunner.de> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Daniel Vetter <daniel.vetter@ffwll.ch> Cc: stable@vger.kernel.org Reviewed-by: Lukas Wunner <lukas@wunner.de> Link: https://patchwork.freedesktop.org/patch/msgid/20171125194155.355-1-chris@chris-wilson.co.uk
2017-11-25 12:41:55 -07:00
if (!ifbdev)
return;
intel_fbdev_sync(ifbdev);
drm/i915: Block fbdev HPD processing during suspend When resuming, we check whether or not any previously connected MST topologies are still present and if so, attempt to resume them. If this fails, we disable said MST topologies and fire off a hotplug event so that userspace knows to reprobe. However, sending a hotplug event involves calling drm_fb_helper_hotplug_event(), which in turn results in fbcon doing a connector reprobe in the caller's thread - something we can't do at the point in which i915 calls drm_dp_mst_topology_mgr_resume() since hotplugging hasn't been fully initialized yet. This currently causes some rather subtle but fatal issues. For example, on my T480s the laptop dock connected to it usually disappears during a suspend cycle, and comes back up a short while after the system has been resumed. This guarantees pretty much every suspend and resume cycle, drm_dp_mst_topology_mgr_set_mst(mgr, false); will be caused and in turn, a connector hotplug will occur. Now it's Rute Goldberg time: when the connector hotplug occurs, i915 reprobes /all/ of the connectors, including eDP. However, eDP probing requires that we power on the panel VDD which in turn, grabs a wakeref to the appropriate power domain on the GPU (on my T480s, this is the PORT_DDI_A_IO domain). This is where things start breaking, since this all happens before intel_power_domains_enable() is called we end up leaking the wakeref that was acquired and never releasing it later. Come next suspend/resume cycle, this causes us to fail to shut down the GPU properly, which causes it not to resume properly and die a horrible complicated death. (as a note: this only happens when there's both an eDP panel and MST topology connected which is removed mid-suspend. One or the other seems to always be OK). We could try to fix the VDD wakeref leak, but this doesn't seem like it's worth it at all since we aren't able to handle hotplug detection while resuming anyway. So, let's go with a more robust solution inspired by nouveau: block fbdev from handling hotplug events until we resume fbdev. This allows us to still send sysfs hotplug events to be handled later by user space while we're resuming, while also preventing us from actually processing any hotplug events we receive until it's safe. This fixes the wakeref leak observed on the T480s and as such, also fixes suspend/resume with MST topologies connected on this machine. Changes since v2: * Don't call drm_fb_helper_hotplug_event() under lock, do it after lock (Chris Wilson) * Don't call drm_fb_helper_hotplug_event() in intel_fbdev_output_poll_changed() under lock (Chris Wilson) * Always set ifbdev->hpd_waiting (Chris Wilson) Signed-off-by: Lyude Paul <lyude@redhat.com> Fixes: 0e32b39ceed6 ("drm/i915: add DP 1.2 MST support (v0.7)") Cc: Todd Previte <tprevite@gmail.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Jani Nikula <jani.nikula@linux.intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Cc: Rodrigo Vivi <rodrigo.vivi@intel.com> Cc: Imre Deak <imre.deak@intel.com> Cc: intel-gfx@lists.freedesktop.org Cc: <stable@vger.kernel.org> # v3.17+ Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Link: https://patchwork.freedesktop.org/patch/msgid/20190129191001.442-2-lyude@redhat.com
2019-01-29 12:09:59 -07:00
mutex_lock(&ifbdev->hpd_lock);
send_hpd = !ifbdev->hpd_suspended;
ifbdev->hpd_waiting = true;
mutex_unlock(&ifbdev->hpd_lock);
if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
drm_fb_helper_hotplug_event(&ifbdev->helper);
}
void intel_fbdev_restore_mode(struct drm_device *dev)
{
struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
if (!ifbdev)
return;
intel_fbdev_sync(ifbdev);
if (!ifbdev->vma)
return;
if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper) == 0)
intel_fbdev_invalidate(ifbdev);
}