Bug Summary

File:dev/pci/drm/i915/display/intel_fbdev.c
Warning:line 241, column 3
Value stored to 'intel_fb' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name intel_fbdev.c -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 -ffp-contract=on -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 -target-feature +retpoline-external-thunk -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/llvm16/lib/clang/16 -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/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -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/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -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/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -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 SUSPEND -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 -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 -fcf-protection=branch -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 /home/ben/Projects/scan/2024-01-11-110808-61670-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 "gem/i915_gem_lmem.h"
45
46#include "i915_drv.h"
47#include "intel_display_types.h"
48#include "intel_fb.h"
49#include "intel_fb_pin.h"
50#include "intel_fbdev.h"
51#include "intel_frontbuffer.h"
52
53struct intel_fbdev {
54 struct drm_fb_helper helper;
55 struct intel_framebuffer *fb;
56 struct i915_vma *vma;
57 unsigned long vma_flags;
58 async_cookie_t cookie;
59 int preferred_bpp;
60
61 /* Whether or not fbdev hpd processing is temporarily suspended */
62 bool_Bool hpd_suspended: 1;
63 /* Set when a hotplug was received while HPD processing was suspended */
64 bool_Bool hpd_waiting: 1;
65
66 /* Protects hpd_suspended */
67 struct rwlock hpd_lock;
68};
69
70static struct intel_frontbuffer *to_frontbuffer(struct intel_fbdev *ifbdev)
71{
72 return ifbdev->fb->frontbuffer;
73}
74
75static void intel_fbdev_invalidate(struct intel_fbdev *ifbdev)
76{
77 intel_frontbuffer_invalidate(to_frontbuffer(ifbdev), ORIGIN_CPU);
78}
79
80static int intel_fbdev_set_par(struct fb_info *info)
81{
82 struct drm_fb_helper *fb_helper = info->par;
83 struct intel_fbdev *ifbdev =
84 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) );})
;
85 int ret;
86
87 ret = drm_fb_helper_set_par(info);
88 if (ret == 0)
89 intel_fbdev_invalidate(ifbdev);
90
91 return ret;
92}
93
94static int intel_fbdev_blank(int blank, struct fb_info *info)
95{
96 struct drm_fb_helper *fb_helper = info->par;
97 struct intel_fbdev *ifbdev =
98 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) );})
;
99 int ret;
100
101 ret = drm_fb_helper_blank(blank, info);
102 if (ret == 0)
103 intel_fbdev_invalidate(ifbdev);
104
105 return ret;
106}
107
108static int intel_fbdev_pan_display(struct fb_var_screeninfo *var,
109 struct fb_info *info)
110{
111 struct drm_fb_helper *fb_helper = info->par;
112 struct intel_fbdev *ifbdev =
113 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) );})
;
114 int ret;
115
116 ret = drm_fb_helper_pan_display(var, info);
117 if (ret == 0)
118 intel_fbdev_invalidate(ifbdev);
119
120 return ret;
121}
122
123static const struct fb_ops intelfb_ops = {
124#ifdef notyet
125 .owner = THIS_MODULE((void *)0),
126 DRM_FB_HELPER_DEFAULT_OPS.fb_set_par = drm_fb_helper_set_par,
127#endif
128 .fb_set_par = intel_fbdev_set_par,
129#ifdef notyet
130 .fb_fillrect = drm_fb_helper_cfb_fillrect,
131 .fb_copyarea = drm_fb_helper_cfb_copyarea,
132 .fb_imageblit = drm_fb_helper_cfb_imageblit,
133 .fb_pan_display = intel_fbdev_pan_display,
134 .fb_blank = intel_fbdev_blank,
135#endif
136};
137
138static int intelfb_alloc(struct drm_fb_helper *helper,
139 struct drm_fb_helper_surface_size *sizes)
140{
141 struct intel_fbdev *ifbdev =
142 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) );})
;
143 struct drm_framebuffer *fb;
144 struct drm_device *dev = helper->dev;
145 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
146 struct drm_mode_fb_cmd2 mode_cmd = {};
147 struct drm_i915_gem_object *obj;
148 int size;
149
150 /* we don't do packed 24bpp */
151 if (sizes->surface_bpp == 24)
152 sizes->surface_bpp = 32;
153
154 mode_cmd.width = sizes->surface_width;
155 mode_cmd.height = sizes->surface_height;
156
157 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)))
158 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)))
;
159 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
160 sizes->surface_depth);
161
162 size = mode_cmd.pitches[0] * mode_cmd.height;
163 size = PAGE_ALIGN(size)(((size) + ((1 << 12) - 1)) & ~((1 << 12) - 1
))
;
164
165 obj = ERR_PTR(-ENODEV19);
166 if (HAS_LMEM(dev_priv)((&(dev_priv)->__runtime)->memory_regions & ((1UL
<< (INTEL_REGION_LMEM_0))))
) {
167 obj = i915_gem_object_create_lmem(dev_priv, size,
168 I915_BO_ALLOC_CONTIGUOUS(1UL << (0)));
169 } else {
170 /*
171 * If the FB is too big, just don't use it since fbdev is not very
172 * important and we should probably use that space with FBC or other
173 * features.
174 */
175 if (size * 2 < dev_priv->stolen_usable_size)
176 obj = i915_gem_object_create_stolen(dev_priv, size);
177 if (IS_ERR(obj))
178 obj = i915_gem_object_create_shmem(dev_priv, size);
179 }
180
181 if (IS_ERR(obj)) {
182 drm_err(&dev_priv->drm, "failed to allocate framebuffer (%pe)\n", obj)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "failed to allocate framebuffer (%pe)\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__ , obj)
;
183 return PTR_ERR(obj);
184 }
185
186 fb = intel_framebuffer_create(obj, &mode_cmd);
187 i915_gem_object_put(obj);
188 if (IS_ERR(fb))
189 return PTR_ERR(fb);
190
191 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) );})
;
192 return 0;
193}
194
195static int intelfb_create(struct drm_fb_helper *helper,
196 struct drm_fb_helper_surface_size *sizes)
197{
198 struct intel_fbdev *ifbdev =
199 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) );})
;
200 struct intel_framebuffer *intel_fb = ifbdev->fb;
201 struct drm_device *dev = helper->dev;
202 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
203 struct pci_dev *pdev = dev_priv->drm.pdev;
204 struct i915_ggtt *ggtt = to_gt(dev_priv)->ggtt;
205 const struct i915_gtt_view view = {
206 .type = I915_GTT_VIEW_NORMAL,
207 };
208 intel_wakeref_t wakeref;
209 struct fb_info *info;
210 struct i915_vma *vma;
211 unsigned long flags = 0;
212 bool_Bool prealloc = false0;
213 void __iomem *vaddr;
214 struct drm_i915_gem_object *obj;
215 struct i915_gem_ww_ctx ww;
216 int ret;
217
218 mutex_lock(&ifbdev->hpd_lock)rw_enter_write(&ifbdev->hpd_lock);
219 ret = ifbdev->hpd_suspended ? -EAGAIN35 : 0;
220 mutex_unlock(&ifbdev->hpd_lock)rw_exit_write(&ifbdev->hpd_lock);
221 if (ret)
222 return ret;
223
224 if (intel_fb &&
225 (sizes->fb_width > intel_fb->base.width ||
226 sizes->fb_height > intel_fb->base.height)) {
227 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), 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)
228 "BIOS fb too small (%dx%d), we require (%dx%d),"__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), 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)
229 " releasing it\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), 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)
230 intel_fb->base.width, intel_fb->base.height,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), 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)
231 sizes->fb_width, sizes->fb_height)__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), 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)
;
232 drm_framebuffer_put(&intel_fb->base);
233 intel_fb = ifbdev->fb = NULL((void *)0);
234 }
235 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); })
) {
236 drm_dbg_kms(&dev_priv->drm,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "no BIOS fb, allocating a new one\n"
)
237 "no BIOS fb, allocating a new one\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "no BIOS fb, allocating a new one\n"
)
;
238 ret = intelfb_alloc(helper, sizes);
239 if (ret)
240 return ret;
241 intel_fb = ifbdev->fb;
Value stored to 'intel_fb' is never read
242 } else {
243 drm_dbg_kms(&dev_priv->drm, "re-using BIOS fb\n")__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "re-using BIOS fb\n"
)
;
244 prealloc = true1;
245 sizes->fb_width = intel_fb->base.width;
246 sizes->fb_height = intel_fb->base.height;
247 }
248
249 wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
250
251 /* Pin the GGTT vma for our access via info->screen_base.
252 * This also validates that any existing fb inherited from the
253 * BIOS is suitable for own access.
254 */
255 vma = intel_pin_and_fence_fb_obj(&ifbdev->fb->base, false0,
256 &view, false0, &flags);
257 if (IS_ERR(vma)) {
258 ret = PTR_ERR(vma);
259 goto out_unlock;
260 }
261
262 info = drm_fb_helper_alloc_fbi(helper);
263 if (IS_ERR(info)) {
264 drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to allocate fb_info (%pe)\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__ , info)
;
265 ret = PTR_ERR(info);
266 goto out_unpin;
267 }
268
269 ifbdev->helper.fb = &ifbdev->fb->base;
270
271 info->fbops = &intelfb_ops;
272
273#ifdef __linux__
274 /* setup aperture base/size for vesafb takeover */
275 obj = intel_fb_obj(&intel_fb->base)((&intel_fb->base) ? to_intel_bo((&intel_fb->base
)->obj[0]) : ((void *)0))
;
276 if (i915_gem_object_is_lmem(obj)) {
277 struct intel_memory_region *mem = obj->mm.region;
278
279 info->apertures->ranges[0].base = mem->io_start;
280 info->apertures->ranges[0].size = mem->io_size;
281
282 /* Use fbdev's framebuffer from lmem for discrete */
283 info->fix.smem_start =
284 (unsigned long)(mem->io_start +
285 i915_gem_object_get_dma_address(obj, 0));
286 info->fix.smem_len = obj->base.size;
287 } else {
288 info->apertures->ranges[0].base = ggtt->gmadr.start;
289 info->apertures->ranges[0].size = ggtt->mappable_end;
290
291 /* Our framebuffer is the entirety of fbdev's system memory */
292 info->fix.smem_start =
293 (unsigned long)(ggtt->gmadr.start + vma->node.start);
294 info->fix.smem_len = vma->size;
295 }
296
297 for_i915_gem_ww(&ww, ret, false)for (i915_gem_ww_ctx_init(&ww, 0), (ret) = -11; (ret) == -
11; (ret) = __i915_gem_ww_fini(&ww, ret))
{
298 ret = i915_gem_object_lock(vma->obj, &ww);
299
300 if (ret)
301 continue;
302
303 vaddr = i915_vma_pin_iomap(vma);
304 if (IS_ERR(vaddr)) {
305 drm_err(&dev_priv->drm,printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to remap framebuffer into virtual memory (%pe)\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__ , vaddr)
306 "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr)printf("drm:pid%d:%s *ERROR* " "[drm] " "*ERROR* " "Failed to remap framebuffer into virtual memory (%pe)\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__ , vaddr)
;
307 ret = PTR_ERR(vaddr);
308 continue;
309 }
310 }
311
312 if (ret)
313 goto out_unpin;
314
315 info->screen_base = vaddr;
316 info->screen_size = vma->size;
317
318 drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
319
320 /* If the object is shmemfs backed, it will have given us zeroed pages.
321 * If the object is stolen however, it will be full of whatever
322 * garbage was left in there.
323 */
324 if (!i915_gem_object_is_shmem(vma->obj) && !prealloc)
325 memset_io(info->screen_base, 0, info->screen_size)__builtin_memset((info->screen_base), (0), (info->screen_size
))
;
326
327 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
328#else
329{
330 struct drm_framebuffer *fb = ifbdev->helper.fb;
331 struct rasops_info *ri = &dev_priv->ro;
332 bus_space_handle_t bsh;
333 int err;
334
335 vaddr = i915_vma_pin_iomap(vma);
336 if (IS_ERR(vaddr)) {
337 DRM_ERROR("Failed to remap framebuffer into virtual memory\n")__drm_err("Failed to remap framebuffer into virtual memory\n"
)
;
338 ret = PTR_ERR(vaddr);
339 goto out_unpin;
340 }
341
342 drm_fb_helper_fill_info(info, &ifbdev->helper, sizes);
343
344 ri->ri_bits = vaddr;
345 ri->ri_depth = fb->format->cpp[0] * 8;
346 ri->ri_stride = fb->pitches[0];
347 ri->ri_width = sizes->fb_width;
348 ri->ri_height = sizes->fb_height;
349
350 switch (fb->format->format) {
351 case DRM_FORMAT_XRGB8888((__u32)('X') | ((__u32)('R') << 8) | ((__u32)('2') <<
16) | ((__u32)('4') << 24))
:
352 ri->ri_rnum = 8;
353 ri->ri_rpos = 16;
354 ri->ri_gnum = 8;
355 ri->ri_gpos = 8;
356 ri->ri_bnum = 8;
357 ri->ri_bpos = 0;
358 break;
359 case DRM_FORMAT_RGB565((__u32)('R') | ((__u32)('G') << 8) | ((__u32)('1') <<
16) | ((__u32)('6') << 24))
:
360 ri->ri_rnum = 5;
361 ri->ri_rpos = 11;
362 ri->ri_gnum = 6;
363 ri->ri_gpos = 5;
364 ri->ri_bnum = 5;
365 ri->ri_bpos = 0;
366 break;
367 }
368
369 if (vma->obj->stolen && !prealloc)
370 memset(ri->ri_bits, 0, vma->node.size)__builtin_memset((ri->ri_bits), (0), (vma->node.size));
371}
372#endif
373
374 drm_dbg_kms(&dev_priv->drm, "allocated %dx%d fb: 0x%08x\n",__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "allocated %dx%d fb: 0x%08x\n"
, ifbdev->fb->base.width, ifbdev->fb->base.height
, i915_ggtt_offset(vma))
375 ifbdev->fb->base.width, ifbdev->fb->base.height,__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "allocated %dx%d fb: 0x%08x\n"
, ifbdev->fb->base.width, ifbdev->fb->base.height
, i915_ggtt_offset(vma))
376 i915_ggtt_offset(vma))__drm_dev_dbg(((void *)0), (&dev_priv->drm) ? (&dev_priv
->drm)->dev : ((void *)0), DRM_UT_KMS, "allocated %dx%d fb: 0x%08x\n"
, ifbdev->fb->base.width, ifbdev->fb->base.height
, i915_ggtt_offset(vma))
;
377 ifbdev->vma = vma;
378 ifbdev->vma_flags = flags;
379
380 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
381 vga_switcheroo_client_fb_set(pdev, info);
382 return 0;
383
384out_unpin:
385 intel_unpin_fb_vma(vma, flags);
386out_unlock:
387 intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
388 return ret;
389}
390
391static const struct drm_fb_helper_funcs intel_fb_helper_funcs = {
392 .fb_probe = intelfb_create,
393};
394
395static void intel_fbdev_destroy(struct intel_fbdev *ifbdev)
396{
397 /* We rely on the object-free to release the VMA pinning for
398 * the info->screen_base mmaping. Leaking the VMA is simpler than
399 * trying to rectify all the possible error paths leading here.
400 */
401
402 drm_fb_helper_fini(&ifbdev->helper);
403
404 if (ifbdev->vma)
405 intel_unpin_fb_vma(ifbdev->vma, ifbdev->vma_flags);
406
407 if (ifbdev->fb)
408 drm_framebuffer_remove(&ifbdev->fb->base);
409
410 kfree(ifbdev);
411}
412
413/*
414 * Build an intel_fbdev struct using a BIOS allocated framebuffer, if possible.
415 * The core display code will have read out the current plane configuration,
416 * so we use that to figure out if there's an object for us to use as the
417 * fb, and if so, we re-use it for the fbdev configuration.
418 *
419 * Note we only support a single fb shared across pipes for boot (mostly for
420 * fbcon), so we just find the biggest and use that.
421 */
422static bool_Bool intel_fbdev_init_bios(struct drm_device *dev,
423 struct intel_fbdev *ifbdev)
424{
425 struct drm_i915_privateinteldrm_softc *i915 = to_i915(dev);
426 struct intel_framebuffer *fb = NULL((void *)0);
427 struct intel_crtc *crtc;
428 unsigned int max_size = 0;
429
430 /* Find the largest fb */
431 for_each_intel_crtc(dev, crtc)for (crtc = ({ const __typeof( ((__typeof(*crtc) *)0)->base
.head ) *__mptr = ((&(dev)->mode_config.crtc_list)->
next); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof
(__typeof(*crtc), base.head) );}); &crtc->base.head !=
(&(dev)->mode_config.crtc_list); crtc = ({ const __typeof
( ((__typeof(*crtc) *)0)->base.head ) *__mptr = (crtc->
base.head.next); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof
(__typeof(*crtc), base.head) );}))
{
432 struct intel_crtc_state *crtc_state =
433 to_intel_crtc_state(crtc->base.state)({ const __typeof( ((struct intel_crtc_state *)0)->uapi ) *
__mptr = (crtc->base.state); (struct intel_crtc_state *)( (
char *)__mptr - __builtin_offsetof(struct intel_crtc_state, uapi
) );})
;
434 struct intel_plane *plane =
435 to_intel_plane(crtc->base.primary)({ const __typeof( ((struct intel_plane *)0)->base ) *__mptr
= (crtc->base.primary); (struct intel_plane *)( (char *)__mptr
- __builtin_offsetof(struct intel_plane, base) );})
;
436 struct intel_plane_state *plane_state =
437 to_intel_plane_state(plane->base.state)({ const __typeof( ((struct intel_plane_state *)0)->uapi )
*__mptr = (plane->base.state); (struct intel_plane_state *
)( (char *)__mptr - __builtin_offsetof(struct intel_plane_state
, uapi) );})
;
438 struct drm_i915_gem_object *obj =
439 intel_fb_obj(plane_state->uapi.fb)((plane_state->uapi.fb) ? to_intel_bo((plane_state->uapi
.fb)->obj[0]) : ((void *)0))
;
440
441 if (!crtc_state->uapi.active) {
442 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] not active, skipping\n"
, crtc->base.base.id, crtc->base.name)
443 "[CRTC:%d:%s] not active, skipping\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] not active, skipping\n"
, crtc->base.base.id, crtc->base.name)
444 crtc->base.base.id, crtc->base.name)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] not active, skipping\n"
, crtc->base.base.id, crtc->base.name)
;
445 continue;
446 }
447
448 if (!obj) {
449 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[PLANE:%d:%s] no fb, skipping\n"
, plane->base.base.id, plane->base.name)
450 "[PLANE:%d:%s] no fb, skipping\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[PLANE:%d:%s] no fb, skipping\n"
, plane->base.base.id, plane->base.name)
451 plane->base.base.id, plane->base.name)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[PLANE:%d:%s] no fb, skipping\n"
, plane->base.base.id, plane->base.name)
;
452 continue;
453 }
454
455 if (obj->base.size > max_size) {
456 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "found possible fb from [PLANE:%d:%s]\n"
, plane->base.base.id, plane->base.name)
457 "found possible fb from [PLANE:%d:%s]\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "found possible fb from [PLANE:%d:%s]\n"
, plane->base.base.id, plane->base.name)
458 plane->base.base.id, plane->base.name)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "found possible fb from [PLANE:%d:%s]\n"
, plane->base.base.id, plane->base.name)
;
459 fb = to_intel_framebuffer(plane_state->uapi.fb)({ const __typeof( ((struct intel_framebuffer *)0)->base )
*__mptr = (plane_state->uapi.fb); (struct intel_framebuffer
*)( (char *)__mptr - __builtin_offsetof(struct intel_framebuffer
, base) );})
;
460 max_size = obj->base.size;
461 }
462 }
463
464 if (!fb) {
465 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "no active fbs found, not using BIOS config\n"
)
466 "no active fbs found, not using BIOS config\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "no active fbs found, not using BIOS config\n"
)
;
467 goto out;
468 }
469
470 /* Now make sure all the pipes will fit into it */
471 for_each_intel_crtc(dev, crtc)for (crtc = ({ const __typeof( ((__typeof(*crtc) *)0)->base
.head ) *__mptr = ((&(dev)->mode_config.crtc_list)->
next); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof
(__typeof(*crtc), base.head) );}); &crtc->base.head !=
(&(dev)->mode_config.crtc_list); crtc = ({ const __typeof
( ((__typeof(*crtc) *)0)->base.head ) *__mptr = (crtc->
base.head.next); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof
(__typeof(*crtc), base.head) );}))
{
472 struct intel_crtc_state *crtc_state =
473 to_intel_crtc_state(crtc->base.state)({ const __typeof( ((struct intel_crtc_state *)0)->uapi ) *
__mptr = (crtc->base.state); (struct intel_crtc_state *)( (
char *)__mptr - __builtin_offsetof(struct intel_crtc_state, uapi
) );})
;
474 struct intel_plane *plane =
475 to_intel_plane(crtc->base.primary)({ const __typeof( ((struct intel_plane *)0)->base ) *__mptr
= (crtc->base.primary); (struct intel_plane *)( (char *)__mptr
- __builtin_offsetof(struct intel_plane, base) );})
;
476 unsigned int cur_size;
477
478 if (!crtc_state->uapi.active) {
479 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] not active, skipping\n"
, crtc->base.base.id, crtc->base.name)
480 "[CRTC:%d:%s] not active, skipping\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] not active, skipping\n"
, crtc->base.base.id, crtc->base.name)
481 crtc->base.base.id, crtc->base.name)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] not active, skipping\n"
, crtc->base.base.id, crtc->base.name)
;
482 continue;
483 }
484
485 drm_dbg_kms(&i915->drm, "checking [PLANE:%d:%s] for BIOS fb\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "checking [PLANE:%d:%s] for BIOS fb\n"
, plane->base.base.id, plane->base.name)
486 plane->base.base.id, plane->base.name)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "checking [PLANE:%d:%s] for BIOS fb\n"
, plane->base.base.id, plane->base.name)
;
487
488 /*
489 * See if the plane fb we found above will fit on this
490 * pipe. Note we need to use the selected fb's pitch and bpp
491 * rather than the current pipe's, since they differ.
492 */
493 cur_size = crtc_state->uapi.adjusted_mode.crtc_hdisplay;
494 cur_size = cur_size * fb->base.format->cpp[0];
495 if (fb->base.pitches[0] < cur_size) {
496 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, fb->
base.pitches[0])
497 "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, fb->
base.pitches[0])
498 plane->base.base.id, plane->base.name,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, fb->
base.pitches[0])
499 cur_size, fb->base.pitches[0])__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not wide enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, fb->
base.pitches[0])
;
500 fb = NULL((void *)0);
501 break;
502 }
503
504 cur_size = crtc_state->uapi.adjusted_mode.crtc_vdisplay;
505 cur_size = intel_fb_align_height(&fb->base, 0, cur_size);
506 cur_size *= fb->base.pitches[0];
507 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
508 "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
509 crtc->base.base.id, crtc->base.name,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
510 crtc_state->uapi.adjusted_mode.crtc_hdisplay,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
511 crtc_state->uapi.adjusted_mode.crtc_vdisplay,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
512 fb->base.format->cpp[0] * 8,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
513 cur_size)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "[CRTC:%d:%s] area: %dx%d, bpp: %d, size: %d\n"
, crtc->base.base.id, crtc->base.name, crtc_state->uapi
.adjusted_mode.crtc_hdisplay, crtc_state->uapi.adjusted_mode
.crtc_vdisplay, fb->base.format->cpp[0] * 8, cur_size)
;
514
515 if (cur_size > max_size) {
516 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, max_size
)
517 "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, max_size
)
518 plane->base.base.id, plane->base.name,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, max_size
)
519 cur_size, max_size)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb not big enough for [PLANE:%d:%s] (%d vs %d)\n"
, plane->base.base.id, plane->base.name, cur_size, max_size
)
;
520 fb = NULL((void *)0);
521 break;
522 }
523
524 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb big enough [PLANE:%d:%s] (%d >= %d)\n"
, plane->base.base.id, plane->base.name, max_size, cur_size
)
525 "fb big enough [PLANE:%d:%s] (%d >= %d)\n",__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb big enough [PLANE:%d:%s] (%d >= %d)\n"
, plane->base.base.id, plane->base.name, max_size, cur_size
)
526 plane->base.base.id, plane->base.name,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb big enough [PLANE:%d:%s] (%d >= %d)\n"
, plane->base.base.id, plane->base.name, max_size, cur_size
)
527 max_size, cur_size)__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "fb big enough [PLANE:%d:%s] (%d >= %d)\n"
, plane->base.base.id, plane->base.name, max_size, cur_size
)
;
528 }
529
530 if (!fb) {
531 drm_dbg_kms(&i915->drm,__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "BIOS fb not suitable for all pipes, not using\n"
)
532 "BIOS fb not suitable for all pipes, not using\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "BIOS fb not suitable for all pipes, not using\n"
)
;
533 goto out;
534 }
535
536 ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8;
537 ifbdev->fb = fb;
538
539 drm_framebuffer_get(&ifbdev->fb->base);
540
541 /* Final pass to check if any active pipes don't have fbs */
542 for_each_intel_crtc(dev, crtc)for (crtc = ({ const __typeof( ((__typeof(*crtc) *)0)->base
.head ) *__mptr = ((&(dev)->mode_config.crtc_list)->
next); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof
(__typeof(*crtc), base.head) );}); &crtc->base.head !=
(&(dev)->mode_config.crtc_list); crtc = ({ const __typeof
( ((__typeof(*crtc) *)0)->base.head ) *__mptr = (crtc->
base.head.next); (__typeof(*crtc) *)( (char *)__mptr - __builtin_offsetof
(__typeof(*crtc), base.head) );}))
{
543 struct intel_crtc_state *crtc_state =
544 to_intel_crtc_state(crtc->base.state)({ const __typeof( ((struct intel_crtc_state *)0)->uapi ) *
__mptr = (crtc->base.state); (struct intel_crtc_state *)( (
char *)__mptr - __builtin_offsetof(struct intel_crtc_state, uapi
) );})
;
545 struct intel_plane *plane =
546 to_intel_plane(crtc->base.primary)({ const __typeof( ((struct intel_plane *)0)->base ) *__mptr
= (crtc->base.primary); (struct intel_plane *)( (char *)__mptr
- __builtin_offsetof(struct intel_plane, base) );})
;
547 struct intel_plane_state *plane_state =
548 to_intel_plane_state(plane->base.state)({ const __typeof( ((struct intel_plane_state *)0)->uapi )
*__mptr = (plane->base.state); (struct intel_plane_state *
)( (char *)__mptr - __builtin_offsetof(struct intel_plane_state
, uapi) );})
;
549
550 if (!crtc_state->uapi.active)
551 continue;
552
553 drm_WARN(dev, !plane_state->uapi.fb,({ int __ret = !!(!plane_state->uapi.fb); if (__ret) printf
("%s %s: " "re-used BIOS config but lost an fb on [PLANE:%d:%s]\n"
, dev_driver_string((dev)->dev), "", plane->base.base.id
, plane->base.name); __builtin_expect(!!(__ret), 0); })
554 "re-used BIOS config but lost an fb on [PLANE:%d:%s]\n",({ int __ret = !!(!plane_state->uapi.fb); if (__ret) printf
("%s %s: " "re-used BIOS config but lost an fb on [PLANE:%d:%s]\n"
, dev_driver_string((dev)->dev), "", plane->base.base.id
, plane->base.name); __builtin_expect(!!(__ret), 0); })
555 plane->base.base.id, plane->base.name)({ int __ret = !!(!plane_state->uapi.fb); if (__ret) printf
("%s %s: " "re-used BIOS config but lost an fb on [PLANE:%d:%s]\n"
, dev_driver_string((dev)->dev), "", plane->base.base.id
, plane->base.name); __builtin_expect(!!(__ret), 0); })
;
556 }
557
558
559 drm_dbg_kms(&i915->drm, "using BIOS fb for initial console\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "using BIOS fb for initial console\n"
)
;
560 return true1;
561
562out:
563
564 return false0;
565}
566
567static void intel_fbdev_suspend_worker(struct work_struct *work)
568{
569 intel_fbdev_set_suspend(&container_of(work,({ const __typeof( ((struct inteldrm_softc *)0)->display.fbdev
.suspend_work ) *__mptr = (work); (struct inteldrm_softc *)( (
char *)__mptr - __builtin_offsetof(struct inteldrm_softc, display
.fbdev.suspend_work) );})
570 struct drm_i915_private,({ const __typeof( ((struct inteldrm_softc *)0)->display.fbdev
.suspend_work ) *__mptr = (work); (struct inteldrm_softc *)( (
char *)__mptr - __builtin_offsetof(struct inteldrm_softc, display
.fbdev.suspend_work) );})
571 display.fbdev.suspend_work)({ const __typeof( ((struct inteldrm_softc *)0)->display.fbdev
.suspend_work ) *__mptr = (work); (struct inteldrm_softc *)( (
char *)__mptr - __builtin_offsetof(struct inteldrm_softc, display
.fbdev.suspend_work) );})
->drm,
572 FBINFO_STATE_RUNNING0,
573 true1);
574}
575
576int intel_fbdev_init(struct drm_device *dev)
577{
578 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
579 struct intel_fbdev *ifbdev;
580 int ret;
581
582 if (drm_WARN_ON(dev, !HAS_DISPLAY(dev_priv))({ int __ret = !!((!((&(dev_priv)->__runtime)->pipe_mask
!= 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string
(((dev))->dev), "", "drm_WARN_ON(" "!((&(dev_priv)->__runtime)->pipe_mask != 0)"
")"); __builtin_expect(!!(__ret), 0); })
)
583 return -ENODEV19;
584
585 ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL(0x0001 | 0x0004));
586 if (ifbdev == NULL((void *)0))
587 return -ENOMEM12;
588
589 rw_init(&ifbdev->hpd_lock, "hdplk")_rw_init_flags(&ifbdev->hpd_lock, "hdplk", 0, ((void *
)0))
;
590 drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
591
592 if (!intel_fbdev_init_bios(dev, ifbdev))
593 ifbdev->preferred_bpp = 32;
594
595 ret = drm_fb_helper_init(dev, &ifbdev->helper);
596 if (ret) {
597 kfree(ifbdev);
598 return ret;
599 }
600
601 dev_priv->display.fbdev.fbdev = ifbdev;
602 INIT_WORK(&dev_priv->display.fbdev.suspend_work, intel_fbdev_suspend_worker);
603
604 return 0;
605}
606
607static void intel_fbdev_initial_config(void *data, async_cookie_t cookie)
608{
609 struct intel_fbdev *ifbdev = data;
610
611 /* Due to peculiar init order wrt to hpd handling this is separate. */
612 if (drm_fb_helper_initial_config(&ifbdev->helper,
613 ifbdev->preferred_bpp))
614 intel_fbdev_unregister(to_i915(ifbdev->helper.dev));
615}
616
617void intel_fbdev_initial_config_async(struct drm_device *dev)
618{
619 struct intel_fbdev *ifbdev = to_i915(dev)->display.fbdev.fbdev;
620
621 if (!ifbdev)
622 return;
623
624 ifbdev->cookie = async_schedule(intel_fbdev_initial_config, ifbdev);
625}
626
627static void intel_fbdev_sync(struct intel_fbdev *ifbdev)
628{
629#ifdef __linux__
630 if (!ifbdev->cookie)
631 return;
632
633 /* Only serialises with all preceding async calls, hence +1 */
634 async_synchronize_cookie(ifbdev->cookie + 1);
635 ifbdev->cookie = 0;
636#endif
637}
638
639void intel_fbdev_unregister(struct drm_i915_privateinteldrm_softc *dev_priv)
640{
641 struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
642
643 if (!ifbdev)
644 return;
645
646 intel_fbdev_set_suspend(&dev_priv->drm, FBINFO_STATE_SUSPENDED1, true1);
647
648#ifdef __linux__
649 if (!current_is_async())
650 intel_fbdev_sync(ifbdev);
651#endif
652
653 drm_fb_helper_unregister_fbi(&ifbdev->helper);
654}
655
656void intel_fbdev_fini(struct drm_i915_privateinteldrm_softc *dev_priv)
657{
658 struct intel_fbdev *ifbdev = fetch_and_zero(&dev_priv->display.fbdev.fbdev)({ typeof(*&dev_priv->display.fbdev.fbdev) __T = *(&
dev_priv->display.fbdev.fbdev); *(&dev_priv->display
.fbdev.fbdev) = (typeof(*&dev_priv->display.fbdev.fbdev
))0; __T; })
;
659
660 if (!ifbdev)
661 return;
662
663 intel_fbdev_destroy(ifbdev);
664}
665
666/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
667 * processing, fbdev will perform a full connector reprobe if a hotplug event
668 * was received while HPD was suspended.
669 */
670static void intel_fbdev_hpd_set_suspend(struct drm_i915_privateinteldrm_softc *i915, int state)
671{
672 struct intel_fbdev *ifbdev = i915->display.fbdev.fbdev;
673 bool_Bool send_hpd = false0;
674
675 mutex_lock(&ifbdev->hpd_lock)rw_enter_write(&ifbdev->hpd_lock);
676 ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED1;
677 send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
678 ifbdev->hpd_waiting = false0;
679 mutex_unlock(&ifbdev->hpd_lock)rw_exit_write(&ifbdev->hpd_lock);
680
681 if (send_hpd) {
682 drm_dbg_kms(&i915->drm, "Handling delayed fbcon HPD event\n")__drm_dev_dbg(((void *)0), (&i915->drm) ? (&i915->
drm)->dev : ((void *)0), DRM_UT_KMS, "Handling delayed fbcon HPD event\n"
)
;
683 drm_fb_helper_hotplug_event(&ifbdev->helper);
684 }
685}
686
687void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool_Bool synchronous)
688{
689#ifdef __linux__
690 struct drm_i915_privateinteldrm_softc *dev_priv = to_i915(dev);
691 struct intel_fbdev *ifbdev = dev_priv->display.fbdev.fbdev;
692 struct fb_info *info;
693
694 if (!ifbdev)
695 return;
696
697 if (drm_WARN_ON(&dev_priv->drm, !HAS_DISPLAY(dev_priv))({ int __ret = !!((!((&(dev_priv)->__runtime)->pipe_mask
!= 0))); if (__ret) printf("%s %s: " "%s", dev_driver_string
(((&dev_priv->drm))->dev), "", "drm_WARN_ON(" "!((&(dev_priv)->__runtime)->pipe_mask != 0)"
")"); __builtin_expect(!!(__ret), 0); })
)
698 return;
699
700 if (!ifbdev->vma)
701 goto set_suspend;
702
703 info = ifbdev->helper.fbdev;
704
705 if (synchronous) {
706 /* Flush any pending work to turn the console on, and then
707 * wait to turn it off. It must be synchronous as we are
708 * about to suspend or unload the driver.
709 *
710 * Note that from within the work-handler, we cannot flush
711 * ourselves, so only flush outstanding work upon suspend!
712 */
713 if (state != FBINFO_STATE_RUNNING0)
714 flush_work(&dev_priv->display.fbdev.suspend_work);
715
716 console_lock();
717 } else {
718 /*
719 * The console lock can be pretty contented on resume due
720 * to all the printk activity. Try to keep it out of the hot
721 * path of resume if possible.
722 */
723 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); })
;
724 if (!console_trylock()) {
725 /* Don't block our own workqueue as this can
726 * be run in parallel with other i915.ko tasks.
727 */
728 schedule_work(&dev_priv->display.fbdev.suspend_work);
729 return;
730 }
731 }
732
733 /* On resume from hibernation: If the object is shmemfs backed, it has
734 * been restored from swap. If the object is stolen however, it will be
735 * full of whatever garbage was left in there.
736 */
737 if (state == FBINFO_STATE_RUNNING0 &&
738 !i915_gem_object_is_shmem(intel_fb_obj(&ifbdev->fb->base)((&ifbdev->fb->base) ? to_intel_bo((&ifbdev->
fb->base)->obj[0]) : ((void *)0))
))
739 memset_io(info->screen_base, 0, info->screen_size)__builtin_memset((info->screen_base), (0), (info->screen_size
))
;
740
741 drm_fb_helper_set_suspend(&ifbdev->helper, state);
742 console_unlock();
743
744set_suspend:
745 intel_fbdev_hpd_set_suspend(dev_priv, state);
746#endif
747}
748
749void intel_fbdev_output_poll_changed(struct drm_device *dev)
750{
751 struct intel_fbdev *ifbdev = to_i915(dev)->display.fbdev.fbdev;
752 bool_Bool send_hpd;
753
754 if (!ifbdev)
755 return;
756
757 intel_fbdev_sync(ifbdev);
758
759 mutex_lock(&ifbdev->hpd_lock)rw_enter_write(&ifbdev->hpd_lock);
760 send_hpd = !ifbdev->hpd_suspended;
761 ifbdev->hpd_waiting = true1;
762 mutex_unlock(&ifbdev->hpd_lock)rw_exit_write(&ifbdev->hpd_lock);
763
764 if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
765 drm_fb_helper_hotplug_event(&ifbdev->helper);
766}
767
768void intel_fbdev_restore_mode(struct drm_device *dev)
769{
770 struct intel_fbdev *ifbdev = to_i915(dev)->display.fbdev.fbdev;
771
772 if (!ifbdev)
773 return;
774
775 intel_fbdev_sync(ifbdev);
776 if (!ifbdev->vma)
777 return;
778
779 if (drm_fb_helper_restore_fbdev_mode_unlocked(&ifbdev->helper) == 0)
780 intel_fbdev_invalidate(ifbdev);
781}
782
783struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev)
784{
785 if (!fbdev || !fbdev->helper.fb)
786 return NULL((void *)0);
787
788 return to_intel_framebuffer(fbdev->helper.fb)({ const __typeof( ((struct intel_framebuffer *)0)->base )
*__mptr = (fbdev->helper.fb); (struct intel_framebuffer *
)( (char *)__mptr - __builtin_offsetof(struct intel_framebuffer
, base) );})
;
789}