Bug Summary

File:dev/pci/drm/i915/display/intel_fbdev.c
Warning:line 175, column 20
Value stored to 'ggtt' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name intel_fbdev.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/drm/i915/display/intel_fbdev.c
1/*
2 * Copyright © 2007 David Airlie
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * David Airlie
25 */
26
27#include <linux/async.h>
28#include <linux/console.h>
29#include <linux/delay.h>
30#include <linux/errno.h>
31#include <linux/init.h>
32#include <linux/kernel.h>
33#include <linux/mm.h>
34#include <linux/module.h>
35#include <linux/string.h>
36#include <linux/sysrq.h>
37#include <linux/tty.h>
38#include <linux/vga_switcheroo.h>
39
40#include <drm/drm_crtc.h>
41#include <drm/drm_fb_helper.h>
42#include <drm/drm_fourcc.h>
43
44#include "i915_drv.h"
45#include "intel_display_types.h"
46#include "intel_fbdev.h"
47#include "intel_frontbuffer.h"
48
49static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
50{
51 return ifbdev->fb->frontbuffer;
52}
53
54static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
55{
56 intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
57}
58
59static int intel_fbdev_set_par(struct fb_info *info)
60{
61 struct drm_fb_helper *fb_helper = info->par;
62 struct intel_fbdev *ifbdev =
63 container_of(fb_helper, struct intel_fbdev, helper)({ const __typeof( ((struct intel_fbdev *)0)->helper ) *__mptr
= (fb_helper); (struct intel_fbdev *)( (char *)__mptr - __builtin_offsetof
(struct intel_fbdev, helper) );})
;
64 int ret;
65
66 ret = drm_fb_helper_set_par(info);
67 if (ret == 0)
68 intel_fbdev_invalidate(ifbdev);
69
70 return ret;
71}
72
73static int intel_fbdev_blank(int blank, struct fb_info *info)
74{
75 struct drm_fb_helper *fb_helper = info->par;
76 struct intel_fbdev *ifbdev =
77 container_of(fb_helper, struct intel_fbdev, helper)({ const __typeof( ((struct intel_fbdev *)0)->helper ) *__mptr
= (fb_helper); (struct intel_fbdev *)( (char *)__mptr - __builtin_offsetof
(struct intel_fbdev, helper) );})
;
78 int ret;
79
80 ret = drm_fb_helper_blank(blank, info);
81 if (ret == 0)
82 intel_fbdev_invalidate(ifbdev);
83
84 return ret;
85}
86
87static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
88 struct fb_info *info)
89{
90 struct drm_fb_helper *fb_helper = info->par;
91 struct intel_fbdev *ifbdev =
92 container_of(fb_helper, struct intel_fbdev, helper)({ const __typeof( ((struct intel_fbdev *)0)->helper ) *__mptr
= (fb_helper); (struct intel_fbdev *)( (char *)__mptr - __builtin_offsetof
(struct intel_fbdev, helper) );})
;
93 int ret;
94
95 ret = drm_fb_helper_pan_display(var, info);
96 if (ret == 0)
97 intel_fbdev_invalidate(ifbdev);
98
99 return ret;
100}
101
102static const struct fb_ops intelfb_ops = {
103#ifdef notyet
104 .owner = THIS_MODULE((void *)0),
105 DRM_FB_HELPER_DEFAULT_OPS.fb_set_par = drm_fb_helper_set_par,
106#endif
107 .fb_set_par = intel_fbdev_set_par,
108#ifdef notyet
109 .fb_fillrect = drm_fb_helper_cfb_fillrect,
110 .fb_copyarea = drm_fb_helper_cfb_copyarea,
111 .fb_imageblit = drm_fb_helper_cfb_imageblit,
112 .fb_pan_display = intel_fbdev_pan_display,
113 .fb_blank = intel_fbdev_blank,
114#endif
115};
116
117static int intelfb_alloc(struct drm_fb_helper *helper,
118 struct drm_fb_helper_surface_size *sizes)
119{
120 struct intel_fbdev *ifbdev =
121 container_of(helper, struct intel_fbdev, helper)({ const __typeof( ((struct intel_fbdev *)0)->helper ) *__mptr
= (helper); (struct intel_fbdev *)( (char *)__mptr - __builtin_offsetof
(struct intel_fbdev, helper) );})
;
122 struct drm_framebuffer *fb;
123 struct drm_device *dev = helper->dev;
124 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
125 struct drm_mode_fb_cmd2 mode_cmd = {};
126 struct drm_i915_gem_object *obj;
127 int size;
128
129 /* we don't do packed 24bpp */
130 if (sizes->surface_bpp == 24)
131 sizes->surface_bpp = 32;
132
133 mode_cmd.width = sizes->surface_width;
134 mode_cmd.height = sizes->surface_height;
135
136 mode_cmd.pitches[0] = roundup2(mode_cmd.width *(((mode_cmd.width * (((sizes->surface_bpp) + ((8) - 1)) / (
8))) + ((64) - 1)) & (~((__typeof(mode_cmd.width * (((sizes
->surface_bpp) + ((8) - 1)) / (8))))(64) - 1)))
137 DIV_ROUND_UP(sizes->surface_bpp, 8), 64)(((mode_cmd.width * (((sizes->surface_bpp) + ((8) - 1)) / (
8))) + ((64) - 1)) & (~((__typeof(mode_cmd.width * (((sizes
->surface_bpp) + ((8) - 1)) / (8))))(64) - 1)))
;
138 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
139 sizes->surface_depth);
140
141 size = mode_cmd.pitches[0] * mode_cmd.height;
142 size = PAGE_ALIGN(size)(((size) + ((1 << 12) - 1)) & ~((1 << 12) - 1
))
;
143
144 /* If the FB is too big, just don't use it since fbdev is not very
145 * important and we should probably use that space with FBC or other
146 * features. */
147 obj = ERR_PTR(-ENODEV19);
148 if (size * 2 < dev_priv->stolen_usable_size)
149 obj = i915_gem_object_create_stolen(dev_priv, size);
150 if (IS_ERR(obj))
151 obj = i915_gem_object_create_shmem(dev_priv, size);
152 if (IS_ERR(obj)) {
153 drm_err(&dev_priv->drm, "failed to allocate framebuffer\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "failed to allocate framebuffer\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
154 return PTR_ERR(obj);
155 }
156
157 fb = intel_framebuffer_create(obj, &mode_cmd);
158 i915_gem_object_put(obj);
159 if (IS_ERR(fb))
160 return PTR_ERR(fb);
161
162 ifbdev->fb = to_intel_framebuffer(fb)({ const __typeof( ((struct intel_framebuffer *)0)->base )
*__mptr = (fb); (struct intel_framebuffer *)( (char *)__mptr
- __builtin_offsetof(struct intel_framebuffer, base) );})
;
163 return 0;
164}
165
166static int intelfb_create(struct drm_fb_helper *helper,
167 struct drm_fb_helper_surface_size *sizes)
168{
169 struct intel_fbdev *ifbdev =
170 container_of(helper, struct intel_fbdev, helper)({ const __typeof( ((struct intel_fbdev *)0)->helper ) *__mptr
= (helper); (struct intel_fbdev *)( (char *)__mptr - __builtin_offsetof
(struct intel_fbdev, helper) );})
;
171 struct intel_framebuffer *intel_fb = ifbdev->fb;
172 struct drm_device *dev = helper->dev;
173 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
174 struct pci_dev *pdev = dev_priv->drm.pdev;
175 struct i915_ggtt *ggtt = &dev_priv->ggtt;
Value stored to 'ggtt' during its initialization is never read
176 const struct i915_ggtt_view view = {
177 .type = I915_GGTT_VIEW_NORMAL,
178 };
179 intel_wakeref_t wakeref;
180 struct fb_info *info;
181 struct i915_vma *vma;
182 unsigned long flags = 0;
183 bool_Bool prealloc = false0;
184 void __iomem *vaddr;
185 int ret;
186
187 if (intel_fb &&
188 (sizes->fb_width > intel_fb->base.width ||
189 sizes->fb_height > intel_fb->base.height)) {
190 drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_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)
191 "BIOS fb too small (%dx%d), we require (%dx%d),"drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_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)
192 " releasing it\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_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)
193 intel_fb->base.width, intel_fb->base.height,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_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)
194 sizes->fb_width, sizes->fb_height)drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_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)
;
195 drm_framebuffer_put(&intel_fb->base);
196 intel_fb = ifbdev->fb = NULL((void *)0);
197 }
198 if (!intel_fb || drm_WARN_ON(dev, !intel_fb_obj(&intel_fb->base))({ int __ret = !!((!((&intel_fb->base) ? to_intel_bo((
&intel_fb->base)->obj[0]) : ((void *)0)))); if (__ret
) printf("%s %s: " "%s", dev_driver_string(((dev))->dev), ""
, "drm_WARN_ON(" "!((&intel_fb->base) ? to_intel_bo((&intel_fb->base)->obj[0]) : ((void *)0))"
")"); __builtin_expect(!!(__ret), 0); })
) {
199 drm_dbg_kms(&dev_priv->drm,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "no BIOS fb, allocating a new one\n"
)
200 "no BIOS fb, allocating a new one\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "no BIOS fb, allocating a new one\n"
)
;
201 ret = intelfb_alloc(helper, sizes);
202 if (ret)
203 return ret;
204 intel_fb = ifbdev->fb;
205 } else {
206 drm_dbg_kms(&dev_priv->drm, "re-using BIOS fb\n")drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "re-using BIOS fb\n"
)
;
207 prealloc = true1;
208 sizes->fb_width = intel_fb->base.width;
209 sizes->fb_height = intel_fb->base.height;
210 }
211
212 wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
213
214 /* Pin the GGTT vma for our access via info->screen_base.
215 * This also validates that any existing fb inherited from the
216 * BIOS is suitable for own access.
217 */
218 vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base,
219 &view, false0, &flags);
220 if (IS_ERR(vma)) {
221 ret = PTR_ERR(vma);
222 goto out_unlock;
223 }
224
225 intel_frontbuffer_flush(to_frontbuffer(ifbdev), ORIGIN_DIRTYFB);
226
227 info = drm_fb_helper_alloc_fbi(helper);
228 if (IS_ERR(info)) {
229 drm_err(&dev_priv->drm, "Failed to allocate fb_info\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to allocate fb_info\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
230 ret = PTR_ERR(info);
231 goto out_unpin;
232 }
233
234 ifbdev->helper.fb = &ifbdev->fb->base;
235
236 info->fbops = &intelfb_ops;
237
238#ifdef __linux__
239 /* setup aperture base/size for vesafb takeover */
240 info->apertures->ranges[0].base = ggtt->gmadr.start;
241 info->apertures->ranges[0].size = ggtt->mappable_end;
242
243 /* Our framebuffer is the entirety of fbdev's system memory */
244 info->fix.smem_start =
245 (unsigned long)(ggtt->gmadr.start + vma->node.start);
246 info->fix.smem_len = vma->node.size;
247
248 vaddr = i915_vma_pin_iomap(vma);
249 if (IS_ERR(vaddr)) {
250 drm_err(&dev_priv->drm,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to remap framebuffer into virtual memory\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
251 "Failed to remap framebuffer into virtual memory\n")printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to remap framebuffer into virtual memory\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
252 ret = PTR_ERR(vaddr);
253 goto out_unpin;
254 }
255 info->screen_base = vaddr;
256 info->screen_size = vma->node.size;
257
258 drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
259
260 /* If the object is shmemfs backed, it will have given us zeroed pages.
261 * If the object is stolen however, it will be full of whatever
262 * garbage was left in there.
263 */
264 if (vma->obj->stolen && !prealloc)
265 memset_io(info->screen_base, 0, info->screen_size)__builtin_memset((info->screen_base), (0), (info->screen_size
))
;
266
267 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
268#else
269{
270 struct drm_framebuffer *fb = ifbdev->helper.fb;
271 struct rasops_info *ri = &dev_priv->ro;
272 bus_space_handle_t bsh;
273 int err;
274
275 vaddr = i915_vma_pin_iomap(vma);
276 if (IS_ERR(vaddr)) {
277 DRM_ERROR("Failed to remap framebuffer into virtual memory\n")__drm_err("Failed to remap framebuffer into virtual memory\n"
)
;
278 ret = PTR_ERR(vaddr);
279 goto out_unpin;
280 }
281
282 drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
283
284 ri->ri_bits = vaddr;
285 ri->ri_depth = fb->format->cpp[0] * 8;
286 ri->ri_stride = fb->pitches[0];
287 ri->ri_width = sizes->fb_width;
288 ri->ri_height = sizes->fb_height;
289
290 switch (fb->format->format) {
291 case DRM_FORMAT_XRGB8888((__u32)('X') | ((__u32)('R') << 8) | ((__u32)('2') <<
16) | ((__u32)('4') << 24))
:
292 ri->ri_rnum = 8;
293 ri->ri_rpos = 16;
294 ri->ri_gnum = 8;
295 ri->ri_gpos = 8;
296 ri->ri_bnum = 8;
297 ri->ri_bpos = 0;
298 break;
299 case DRM_FORMAT_RGB565((__u32)('R') | ((__u32)('G') << 8) | ((__u32)('1') <<
16) | ((__u32)('6') << 24))
:
300 ri->ri_rnum = 5;
301 ri->ri_rpos = 11;
302 ri->ri_gnum = 6;
303 ri->ri_gpos = 5;
304 ri->ri_bnum = 5;
305 ri->ri_bpos = 0;
306 break;
307 }
308
309 if (vma->obj->stolen && !prealloc)
310 memset(ri->ri_bits, 0, vma->node.size)__builtin_memset((ri->ri_bits), (0), (vma->node.size));
311}
312#endif
313
314 drm_dbg_kms(&dev_priv->drm, "allocated %dx%d fb: 0x%08x\n",drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "allocated %dx%d fb: 0x%08x\n"
, ifbdev->fb->base.width, ifbdev->fb->base.height
, i915_ggtt_offset(vma))
315 ifbdev->fb->base.width, ifbdev->fb->base.height,drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "allocated %dx%d fb: 0x%08x\n"
, ifbdev->fb->base.width, ifbdev->fb->base.height
, i915_ggtt_offset(vma))
316 i915_ggtt_offset(vma))drm_dev_dbg((&dev_priv->drm)->dev, DRM_UT_KMS, "allocated %dx%d fb: 0x%08x\n"
, ifbdev->fb->base.width, ifbdev->fb->base.height
, i915_ggtt_offset(vma))
;
317 ifbdev->vma = vma;
318 ifbdev->vma_flags = flags;
319
320 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
321 vga_switcheroo_client_fb_set(pdev, info);
322 return 0;
323
324out_unpin:
325 intel_unpin_fb_vma(vma, flags);
326out_unlock:
327 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
328 return ret;
329}
330
331static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
332 .fb_probe = intelfb_create,
333};
334
335static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
336{
337 /* We rely on the object-free to release the VMA pinning for
338 * the info->screen_base mmaping. Leaking the VMA is simpler than
339 * trying to rectify all the possible error paths leading here.
340 */
341
342 drm_fb_helper_fini(&ifbdev->helper);
343
344 if (ifbdev->vma)
345 intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags);
346
347 if (ifbdev->fb)
348 drm_framebuffer_remove(&ifbdev->fb->base);
349
350 kfree(ifbdev);
351}
352
353/*
354 * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible.
355 * The core display code will have read out the current plane configuration,
356 * so we use that to figure out if there's an object for us to use as the
357 * fb, and if so, we re-use it for the fbdev configuration.
358 *
359 * Note we only support a single fb shared across pipes for boot (mostly for
360 * fbcon), so we just find the biggest and use that.
361 */
362static bool_Bool intel_fbdev_init_bios(struct drm_device *dev,
363 struct intel_fbdev *ifbdev)
364{
365 struct drm_i915_privateinteldrm_softc *i915 = to_i915(dev);
366 struct intel_framebuffer *fb = NULL((void *)0);
367 struct drm_crtc *crtc;
368 struct intel_crtc *intel_crtc;
369 unsigned int max_size = 0;
370
371 /* Find the largest fb */
372 for_each_crtc(dev, crtc)for (crtc = ({ const __typeof( ((__typeof(*crtc) *)0)->head
) *__mptr = ((&(dev)->mode_config.crtc_list)->next
); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof(__typeof
(*crtc), head) );}); &crtc->head != (&(dev)->mode_config
.crtc_list); crtc = ({ const __typeof( ((__typeof(*crtc) *)0)
->head ) *__mptr = (crtc->head.next); (__typeof(*crtc) *
)( (char *)__mptr - __builtin_offsetof(__typeof(*crtc), head)
);}))
{
373 struct drm_i915_gem_object *obj =
374 intel_fb_obj(crtc->primary->state->fb)((crtc->primary->state->fb) ? to_intel_bo((crtc->
primary->state->fb)->obj[0]) : ((void *)0))
;
375 intel_crtc = to_intel_crtc(crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr
= (crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof
(struct intel_crtc, base) );})
;
376
377 if (!crtc->state->active || !obj) {
378 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c not active or no fb, skipping\n"
, ((intel_crtc->pipe) + 'A'))
379 "pipe %c not active or no fb, skipping\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c not active or no fb, skipping\n"
, ((intel_crtc->pipe) + 'A'))
380 pipe_name(intel_crtc->pipe))drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c not active or no fb, skipping\n"
, ((intel_crtc->pipe) + 'A'))
;
381 continue;
382 }
383
384 if (obj->base.size > max_size) {
385 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "found possible fb from plane %c\n"
, ((intel_crtc->pipe) + 'A'))
386 "found possible fb from plane %c\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "found possible fb from plane %c\n"
, ((intel_crtc->pipe) + 'A'))
387 pipe_name(intel_crtc->pipe))drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "found possible fb from plane %c\n"
, ((intel_crtc->pipe) + 'A'))
;
388 fb = to_intel_framebuffer(crtc->primary->state->fb)({ const __typeof( ((struct intel_framebuffer *)0)->base )
*__mptr = (crtc->primary->state->fb); (struct intel_framebuffer
*)( (char *)__mptr - __builtin_offsetof(struct intel_framebuffer
, base) );})
;
389 max_size = obj->base.size;
390 }
391 }
392
393 if (!fb) {
394 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "no active fbs found, not using BIOS config\n"
)
395 "no active fbs found, not using BIOS config\n")drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "no active fbs found, not using BIOS config\n"
)
;
396 goto out;
397 }
398
399 /* Now make sure all the pipes will fit into it */
400 for_each_crtc(dev, crtc)for (crtc = ({ const __typeof( ((__typeof(*crtc) *)0)->head
) *__mptr = ((&(dev)->mode_config.crtc_list)->next
); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof(__typeof
(*crtc), head) );}); &crtc->head != (&(dev)->mode_config
.crtc_list); crtc = ({ const __typeof( ((__typeof(*crtc) *)0)
->head ) *__mptr = (crtc->head.next); (__typeof(*crtc) *
)( (char *)__mptr - __builtin_offsetof(__typeof(*crtc), head)
);}))
{
401 unsigned int cur_size;
402
403 intel_crtc = to_intel_crtc(crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr
= (crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof
(struct intel_crtc, base) );})
;
404
405 if (!crtc->state->active) {
406 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c not active, skipping\n"
, ((intel_crtc->pipe) + 'A'))
407 "pipe %c not active, skipping\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c not active, skipping\n"
, ((intel_crtc->pipe) + 'A'))
408 pipe_name(intel_crtc->pipe))drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c not active, skipping\n"
, ((intel_crtc->pipe) + 'A'))
;
409 continue;
410 }
411
412 drm_dbg_kms(&i915->drm, "checking plane %c for BIOS fb\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "checking plane %c for BIOS fb\n"
, ((intel_crtc->pipe) + 'A'))
413 pipe_name(intel_crtc->pipe))drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "checking plane %c for BIOS fb\n"
, ((intel_crtc->pipe) + 'A'))
;
414
415 /*
416 * See if the plane fb we found above will fit on this
417 * pipe. Note we need to use the selected fb's pitch and bpp
418 * rather than the current pipe's, since they differ.
419 */
420 cur_size = crtc->state->adjusted_mode.crtc_hdisplay;
421 cur_size = cur_size * fb->base.format->cpp[0];
422 if (fb->base.pitches[0] < cur_size) {
423 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not wide enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, fb->base.pitches
[0])
424 "fb not wide enough for plane %c (%d vs %d)\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not wide enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, fb->base.pitches
[0])
425 pipe_name(intel_crtc->pipe),drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not wide enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, fb->base.pitches
[0])
426 cur_size, fb->base.pitches[0])drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not wide enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, fb->base.pitches
[0])
;
427 fb = NULL((void *)0);
428 break;
429 }
430
431 cur_size = crtc->state->adjusted_mode.crtc_vdisplay;
432 cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
433 cur_size *= fb->base.pitches[0];
434 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
435 "pipe %c area: %dx%d, bpp: %d, size: %d\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
436 pipe_name(intel_crtc->pipe),drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
437 crtc->state->adjusted_mode.crtc_hdisplay,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
438 crtc->state->adjusted_mode.crtc_vdisplay,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
439 fb->base.format->cpp[0] * 8,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
440 cur_size)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "pipe %c area: %dx%d, bpp: %d, size: %d\n"
, ((intel_crtc->pipe) + 'A'), crtc->state->adjusted_mode
.crtc_hdisplay, crtc->state->adjusted_mode.crtc_vdisplay
, fb->base.format->cpp[0] * 8, cur_size)
;
441
442 if (cur_size > max_size) {
443 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not big enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, max_size)
444 "fb not big enough for plane %c (%d vs %d)\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not big enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, max_size)
445 pipe_name(intel_crtc->pipe),drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not big enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, max_size)
446 cur_size, max_size)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb not big enough for plane %c (%d vs %d)\n"
, ((intel_crtc->pipe) + 'A'), cur_size, max_size)
;
447 fb = NULL((void *)0);
448 break;
449 }
450
451 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb big enough for plane %c (%d >= %d)\n"
, ((intel_crtc->pipe) + 'A'), max_size, cur_size)
452 "fb big enough for plane %c (%d >= %d)\n",drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb big enough for plane %c (%d >= %d)\n"
, ((intel_crtc->pipe) + 'A'), max_size, cur_size)
453 pipe_name(intel_crtc->pipe),drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb big enough for plane %c (%d >= %d)\n"
, ((intel_crtc->pipe) + 'A'), max_size, cur_size)
454 max_size, cur_size)drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "fb big enough for plane %c (%d >= %d)\n"
, ((intel_crtc->pipe) + 'A'), max_size, cur_size)
;
455 }
456
457 if (!fb) {
458 drm_dbg_kms(&i915->drm,drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "BIOS fb not suitable for all pipes, not using\n"
)
459 "BIOS fb not suitable for all pipes, not using\n")drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "BIOS fb not suitable for all pipes, not using\n"
)
;
460 goto out;
461 }
462
463 ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8;
464 ifbdev->fb = fb;
465
466 drm_framebuffer_get(&ifbdev->fb->base);
467
468 /* Final pass to check if any active pipes don't have fbs */
469 for_each_crtc(dev, crtc)for (crtc = ({ const __typeof( ((__typeof(*crtc) *)0)->head
) *__mptr = ((&(dev)->mode_config.crtc_list)->next
); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof(__typeof
(*crtc), head) );}); &crtc->head != (&(dev)->mode_config
.crtc_list); crtc = ({ const __typeof( ((__typeof(*crtc) *)0)
->head ) *__mptr = (crtc->head.next); (__typeof(*crtc) *
)( (char *)__mptr - __builtin_offsetof(__typeof(*crtc), head)
);}))
{
470 intel_crtc = to_intel_crtc(crtc)({ const __typeof( ((struct intel_crtc *)0)->base ) *__mptr
= (crtc); (struct intel_crtc *)( (char *)__mptr - __builtin_offsetof
(struct intel_crtc, base) );})
;
471
472 if (!crtc->state->active)
473 continue;
474
475 drm_WARN(dev, !crtc->primary->state->fb,({ int __ret = !!(!crtc->primary->state->fb); if (__ret
) printf("%s %s: " "re-used BIOS config but lost an fb on crtc %d\n"
, dev_driver_string((dev)->dev), "", crtc->base.id); __builtin_expect
(!!(__ret), 0); })
476 "re-used BIOS config but lost an fb on crtc %d\n",({ int __ret = !!(!crtc->primary->state->fb); if (__ret
) printf("%s %s: " "re-used BIOS config but lost an fb on crtc %d\n"
, dev_driver_string((dev)->dev), "", crtc->base.id); __builtin_expect
(!!(__ret), 0); })
477 crtc->base.id)({ int __ret = !!(!crtc->primary->state->fb); if (__ret
) printf("%s %s: " "re-used BIOS config but lost an fb on crtc %d\n"
, dev_driver_string((dev)->dev), "", crtc->base.id); __builtin_expect
(!!(__ret), 0); })
;
478 }
479
480
481 drm_dbg_kms(&i915->drm, "using BIOS fb for initial console\n")drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "using BIOS fb for initial console\n"
)
;
482 return true1;
483
484out:
485
486 return false0;
487}
488
489static void intel_fbdev_suspend_worker(struct work_struct *work)
490{
491 intel_fbdev_set_suspend(&container_of(work,({ const __typeof( ((struct inteldrm_softc *)0)->fbdev_suspend_work
) *__mptr = (work); (struct inteldrm_softc *)( (char *)__mptr
- __builtin_offsetof(struct inteldrm_softc, fbdev_suspend_work
) );})
492 struct drm_i915_private,({ const __typeof( ((struct inteldrm_softc *)0)->fbdev_suspend_work
) *__mptr = (work); (struct inteldrm_softc *)( (char *)__mptr
- __builtin_offsetof(struct inteldrm_softc, fbdev_suspend_work
) );})
493 fbdev_suspend_work)({ const __typeof( ((struct inteldrm_softc *)0)->fbdev_suspend_work
) *__mptr = (work); (struct inteldrm_softc *)( (char *)__mptr
- __builtin_offsetof(struct inteldrm_softc, fbdev_suspend_work
) );})
->drm,
494 FBINFO_STATE_RUNNING0,
495 true1);
496}
497
498int intel_fbdev_init(struct drm_device *dev)
499{
500 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
501 struct intel_fbdev *ifbdev;
502 int ret;
503
504 if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv))({ int __ret = !!((!((&(dev_priv)->__info)->pipe_mask
!= 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string
(((dev))->dev), "", "drm_WARN_ON(" "!((&(dev_priv)->__info)->pipe_mask != 0)"
")"); __builtin_expect(!!(__ret), 0); })
)
505 return -ENODEV19;
506
507 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL(0x0001 | 0x0004));
508 if (ifbdev == NULL((void *)0))
509 return -ENOMEM12;
510
511 rw_init(&ifbdev->hpd_lock, "hdplk")_rw_init_flags(&ifbdev->hpd_lock, "hdplk", 0, ((void *
)0))
;
512 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
513
514 if (!intel_fbdev_init_bios(dev, ifbdev))
515 ifbdev->preferred_bpp = 32;
516
517 ret = drm_fb_helper_init(dev, &ifbdev->helper);
518 if (ret) {
519 kfree(ifbdev);
520 return ret;
521 }
522
523 dev_priv->fbdev = ifbdev;
524 INIT_WORK(&dev_priv->fbdev_suspend_work, intel_fbdev_suspend_worker);
525
526 return 0;
527}
528
529static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
530{
531 struct intel_fbdev *ifbdev = data;
532
533 /* Due to peculiar init order wrt to hpd handling this is separate. */
534 if (drm_fb_helper_initial_config(&ifbdev->helper,
535 ifbdev->preferred_bpp))
536 intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
537}
538
539void intel_fbdev_initial_config_async(struct drm_device *dev)
540{
541 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
542
543 if (!ifbdev)
544 return;
545
546 ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
547}
548
549static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
550{
551#ifdef __linux__
552 if (!ifbdev->cookie)
553 return;
554
555 /* Only serialises with all preceding async calls, hence +1 */
556 async_synchronize_cookie(ifbdev->cookie + 1);
557 ifbdev->cookie = 0;
558#endif
559}
560
561void intel_fbdev_unregister(struct drm_i915_privateinteldrm_softc *dev_priv)
562{
563 struct intel_fbdev *ifbdev = dev_priv->fbdev;
564
565 if (!ifbdev)
566 return;
567
568 cancel_work_sync(&dev_priv->fbdev_suspend_work);
569#ifdef __linux__
570 if (!current_is_async())
571 intel_fbdev_sync(ifbdev);
572#endif
573
574 drm_fb_helper_unregister_fbi(&ifbdev->helper);
575}
576
577void intel_fbdev_fini(struct drm_i915_privateinteldrm_softc *dev_priv)
578{
579 struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->fbdev)({ typeof(*&dev_priv->fbdev) __T = *(&dev_priv->
fbdev); *(&dev_priv->fbdev) = (typeof(*&dev_priv->
fbdev))0; __T; })
;
580
581 if (!ifbdev)
582 return;
583
584 intel_fbdev_destroy(ifbdev);
585}
586
587/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
588 * processing, fbdev will perform a full connector reprobe if a hotplug event
589 * was received while HPD was suspended.
590 */
591static void intel_fbdev_hpd_set_suspend(struct drm_i915_privateinteldrm_softc *i915, int state)
592{
593 struct intel_fbdev *ifbdev = i915->fbdev;
594 bool_Bool send_hpd = false0;
595
596 mutex_lock(&ifbdev->hpd_lock)rw_enter_write(&ifbdev->hpd_lock);
597 ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED1;
598 send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
599 ifbdev->hpd_waiting = false0;
600 mutex_unlock(&ifbdev->hpd_lock)rw_exit_write(&ifbdev->hpd_lock);
601
602 if (send_hpd) {
603 drm_dbg_kms(&i915->drm, "Handling delayed fbcon HPD event\n")drm_dev_dbg((&i915->drm)->dev, DRM_UT_KMS, "Handling delayed fbcon HPD event\n"
)
;
604 drm_fb_helper_hotplug_event(&ifbdev->helper);
605 }
606}
607
608void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool_Bool synchronous)
609{
610#ifdef __linux__
611 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
612 struct intel_fbdev *ifbdev = dev_priv->fbdev;
613 struct fb_info *info;
614
615 if (!ifbdev || !ifbdev->vma)
616 return;
617
618 info = ifbdev->helper.fbdev;
619
620 if (synchronous) {
621 /* Flush any pending work to turn the console on, and then
622 * wait to turn it off. It must be synchronous as we are
623 * about to suspend or unload the driver.
624 *
625 * Note that from within the work-handler, we cannot flush
626 * ourselves, so only flush outstanding work upon suspend!
627 */
628 if (state != FBINFO_STATE_RUNNING0)
629 flush_work(&dev_priv->fbdev_suspend_work);
630
631 console_lock();
632 } else {
633 /*
634 * The console lock can be pretty contented on resume due
635 * to all the printk activity. Try to keep it out of the hot
636 * path of resume if possible.
637 */
638 drm_WARN_ON(dev, state != FBINFO_STATE_RUNNING)({ int __ret = !!((state != 0)); if (__ret) printf("%s %s: " "%s"
, dev_driver_string(((dev))->dev), "", "drm_WARN_ON(" "state != 0"
")"); __builtin_expect(!!(__ret), 0); })
;
639 if (!console_trylock()1) {
640 /* Don't block our own workqueue as this can
641 * be run in parallel with other i915.ko tasks.
642 */
643 schedule_work(&dev_priv->fbdev_suspend_work);
644 return;
645 }
646 }
647
648 /* On resume from hibernation: If the object is shmemfs backed, it has
649 * been restored from swap. If the object is stolen however, it will be
650 * full of whatever garbage was left in there.
651 */
652 if (state == FBINFO_STATE_RUNNING0 &&
653 intel_fb_obj(&ifbdev->fb->base)((&ifbdev->fb->base) ? to_intel_bo((&ifbdev->
fb->base)->obj[0]) : ((void *)0))
->stolen)
654 memset_io(info->screen_base, 0, info->screen_size)__builtin_memset((info->screen_base), (0), (info->screen_size
))
;
655
656 drm_fb_helper_set_suspend(&ifbdev->helper, state);
657 console_unlock();
658
659 intel_fbdev_hpd_set_suspend(dev_priv, state);
660#endif
661}
662
663void intel_fbdev_output_poll_changed(struct drm_device *dev)
664{
665 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
666 bool_Bool send_hpd;
667
668 if (!ifbdev)
669 return;
670
671 intel_fbdev_sync(ifbdev);
672
673 mutex_lock(&ifbdev->hpd_lock)rw_enter_write(&ifbdev->hpd_lock);
674 send_hpd = !ifbdev->hpd_suspended;
675 ifbdev->hpd_waiting = true1;
676 mutex_unlock(&ifbdev->hpd_lock)rw_exit_write(&ifbdev->hpd_lock);
677
678 if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
679 drm_fb_helper_hotplug_event(&ifbdev->helper);
680}
681
682void intel_fbdev_restore_mode(struct drm_device *dev)
683{
684 struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
685
686 if (!ifbdev)
687 return;
688
689 intel_fbdev_sync(ifbdev);
690 if (!ifbdev->vma)
691 return;
692
693 if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper) == 0)
694 intel_fbdev_invalidate(ifbdev);
695}