Commit 1471ca9aa71cd37b6a7476bb6f06a3a8622ea1bd
Committed by
Dave Airlie
1 parent
3da1f33e79
Exists in
master
and in
39 other branches
fbdev: allow passing more than one aperture for handoff
It removes a hack from nouveau code which had to detect which region to pass to kick vesafb/efifb. Signed-off-by: Marcin Slusarz <marcin.slusarz@gmail.com> Cc: Eric Anholt <eric@anholt.net> Cc: Ben Skeggs <bskeggs@redhat.com> Cc: Thomas Hellstrom <thellstrom@vmware.com> Cc: Dave Airlie <airlied@redhat.com> Cc: Peter Jones <pjones@redhat.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Dave Airlie <airlied@redhat.com>
Showing 10 changed files with 123 additions and 88 deletions Side-by-side Diff
drivers/gpu/drm/i915/intel_fb.c
... | ... | @@ -128,11 +128,16 @@ |
128 | 128 | info->fbops = &intelfb_ops; |
129 | 129 | |
130 | 130 | /* setup aperture base/size for vesafb takeover */ |
131 | - info->aperture_base = dev->mode_config.fb_base; | |
131 | + info->apertures = alloc_apertures(1); | |
132 | + if (!info->apertures) { | |
133 | + ret = -ENOMEM; | |
134 | + goto out_unpin; | |
135 | + } | |
136 | + info->apertures->ranges[0].base = dev->mode_config.fb_base; | |
132 | 137 | if (IS_I9XX(dev)) |
133 | - info->aperture_size = pci_resource_len(dev->pdev, 2); | |
138 | + info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 2); | |
134 | 139 | else |
135 | - info->aperture_size = pci_resource_len(dev->pdev, 0); | |
140 | + info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); | |
136 | 141 | |
137 | 142 | info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; |
138 | 143 | info->fix.smem_len = size; |
drivers/gpu/drm/nouveau/nouveau_fbcon.c
... | ... | @@ -152,44 +152,6 @@ |
152 | 152 | *blue = nv_crtc->lut.b[regno]; |
153 | 153 | } |
154 | 154 | |
155 | -#if defined(__i386__) || defined(__x86_64__) | |
156 | -static bool | |
157 | -nouveau_fbcon_has_vesafb_or_efifb(struct drm_device *dev) | |
158 | -{ | |
159 | - struct pci_dev *pdev = dev->pdev; | |
160 | - int ramin; | |
161 | - | |
162 | - if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB && | |
163 | - screen_info.orig_video_isVGA != VIDEO_TYPE_EFI) | |
164 | - return false; | |
165 | - | |
166 | - if (screen_info.lfb_base < pci_resource_start(pdev, 1)) | |
167 | - goto not_fb; | |
168 | - | |
169 | - if (screen_info.lfb_base + screen_info.lfb_size >= | |
170 | - pci_resource_start(pdev, 1) + pci_resource_len(pdev, 1)) | |
171 | - goto not_fb; | |
172 | - | |
173 | - return true; | |
174 | -not_fb: | |
175 | - ramin = 2; | |
176 | - if (pci_resource_len(pdev, ramin) == 0) { | |
177 | - ramin = 3; | |
178 | - if (pci_resource_len(pdev, ramin) == 0) | |
179 | - return false; | |
180 | - } | |
181 | - | |
182 | - if (screen_info.lfb_base < pci_resource_start(pdev, ramin)) | |
183 | - return false; | |
184 | - | |
185 | - if (screen_info.lfb_base + screen_info.lfb_size >= | |
186 | - pci_resource_start(pdev, ramin) + pci_resource_len(pdev, ramin)) | |
187 | - return false; | |
188 | - | |
189 | - return true; | |
190 | -} | |
191 | -#endif | |
192 | - | |
193 | 155 | static void |
194 | 156 | nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *nfbdev) |
195 | 157 | { |
... | ... | @@ -219,7 +181,9 @@ |
219 | 181 | struct nouveau_framebuffer *nouveau_fb; |
220 | 182 | struct nouveau_bo *nvbo; |
221 | 183 | struct drm_mode_fb_cmd mode_cmd; |
222 | - struct device *device = &dev->pdev->dev; | |
184 | + struct pci_dev *pdev = dev->pdev; | |
185 | + struct device *device = &pdev->dev; | |
186 | + struct apertures_struct *aper; | |
223 | 187 | int size, ret; |
224 | 188 | |
225 | 189 | mode_cmd.width = sizes->surface_width; |
226 | 190 | |
... | ... | @@ -299,28 +263,30 @@ |
299 | 263 | drm_fb_helper_fill_var(info, &nfbdev->helper, sizes->fb_width, sizes->fb_height); |
300 | 264 | |
301 | 265 | /* FIXME: we really shouldn't expose mmio space at all */ |
302 | - info->fix.mmio_start = pci_resource_start(dev->pdev, 1); | |
303 | - info->fix.mmio_len = pci_resource_len(dev->pdev, 1); | |
266 | + info->fix.mmio_start = pci_resource_start(pdev, 1); | |
267 | + info->fix.mmio_len = pci_resource_len(pdev, 1); | |
304 | 268 | |
305 | 269 | /* Set aperture base/size for vesafb takeover */ |
306 | -#if defined(__i386__) || defined(__x86_64__) | |
307 | - if (nouveau_fbcon_has_vesafb_or_efifb(dev)) { | |
308 | - /* Some NVIDIA VBIOS' are stupid and decide to put the | |
309 | - * framebuffer in the middle of the PRAMIN BAR for | |
310 | - * whatever reason. We need to know the exact lfb_base | |
311 | - * to get vesafb kicked off, and the only reliable way | |
312 | - * we have left is to find out lfb_base the same way | |
313 | - * vesafb did. | |
314 | - */ | |
315 | - info->aperture_base = screen_info.lfb_base; | |
316 | - info->aperture_size = screen_info.lfb_size; | |
317 | - if (screen_info.orig_video_isVGA == VIDEO_TYPE_VLFB) | |
318 | - info->aperture_size *= 65536; | |
319 | - } else | |
320 | -#endif | |
321 | - { | |
322 | - info->aperture_base = info->fix.mmio_start; | |
323 | - info->aperture_size = info->fix.mmio_len; | |
270 | + aper = info->apertures = alloc_apertures(3); | |
271 | + if (!info->apertures) { | |
272 | + ret = -ENOMEM; | |
273 | + goto out_unref; | |
274 | + } | |
275 | + | |
276 | + aper->ranges[0].base = pci_resource_start(pdev, 1); | |
277 | + aper->ranges[0].size = pci_resource_len(pdev, 1); | |
278 | + aper->count = 1; | |
279 | + | |
280 | + if (pci_resource_len(pdev, 2)) { | |
281 | + aper->ranges[aper->count].base = pci_resource_start(pdev, 2); | |
282 | + aper->ranges[aper->count].size = pci_resource_len(pdev, 2); | |
283 | + aper->count++; | |
284 | + } | |
285 | + | |
286 | + if (pci_resource_len(pdev, 3)) { | |
287 | + aper->ranges[aper->count].base = pci_resource_start(pdev, 3); | |
288 | + aper->ranges[aper->count].size = pci_resource_len(pdev, 3); | |
289 | + aper->count++; | |
324 | 290 | } |
325 | 291 | |
326 | 292 | info->pixmap.size = 64*1024; |
drivers/gpu/drm/radeon/radeon_fb.c
... | ... | @@ -236,8 +236,13 @@ |
236 | 236 | drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); |
237 | 237 | |
238 | 238 | /* setup aperture base/size for vesafb takeover */ |
239 | - info->aperture_base = rdev->ddev->mode_config.fb_base; | |
240 | - info->aperture_size = rdev->mc.real_vram_size; | |
239 | + info->apertures = alloc_apertures(1); | |
240 | + if (!info->apertures) { | |
241 | + ret = -ENOMEM; | |
242 | + goto out_unref; | |
243 | + } | |
244 | + info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; | |
245 | + info->apertures->ranges[0].size = rdev->mc.real_vram_size; | |
241 | 246 | |
242 | 247 | info->fix.mmio_start = 0; |
243 | 248 | info->fix.mmio_len = 0; |
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
... | ... | @@ -559,8 +559,13 @@ |
559 | 559 | info->pixmap.scan_align = 1; |
560 | 560 | #endif |
561 | 561 | |
562 | - info->aperture_base = vmw_priv->vram_start; | |
563 | - info->aperture_size = vmw_priv->vram_size; | |
562 | + info->apertures = alloc_apertures(1); | |
563 | + if (!info->apertures) { | |
564 | + ret = -ENOMEM; | |
565 | + goto err_aper; | |
566 | + } | |
567 | + info->apertures->ranges[0].base = vmw_priv->vram_start; | |
568 | + info->apertures->ranges[0].size = vmw_priv->vram_size; | |
564 | 569 | |
565 | 570 | /* |
566 | 571 | * Dirty & Deferred IO |
... | ... | @@ -580,6 +585,7 @@ |
580 | 585 | |
581 | 586 | err_defio: |
582 | 587 | fb_deferred_io_cleanup(info); |
588 | +err_aper: | |
583 | 589 | ttm_bo_kunmap(&par->map); |
584 | 590 | err_unref: |
585 | 591 | ttm_bo_unref((struct ttm_buffer_object **)&par->vmw_bo); |
drivers/video/efifb.c
... | ... | @@ -165,7 +165,7 @@ |
165 | 165 | { |
166 | 166 | if (info->screen_base) |
167 | 167 | iounmap(info->screen_base); |
168 | - release_mem_region(info->aperture_base, info->aperture_size); | |
168 | + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); | |
169 | 169 | framebuffer_release(info); |
170 | 170 | } |
171 | 171 | |
... | ... | @@ -289,8 +289,13 @@ |
289 | 289 | info->pseudo_palette = info->par; |
290 | 290 | info->par = NULL; |
291 | 291 | |
292 | - info->aperture_base = efifb_fix.smem_start; | |
293 | - info->aperture_size = size_remap; | |
292 | + info->apertures = alloc_apertures(1); | |
293 | + if (!info->apertures) { | |
294 | + err = -ENOMEM; | |
295 | + goto err_release_fb; | |
296 | + } | |
297 | + info->apertures->ranges[0].base = efifb_fix.smem_start; | |
298 | + info->apertures->ranges[0].size = size_remap; | |
294 | 299 | |
295 | 300 | info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); |
296 | 301 | if (!info->screen_base) { |
drivers/video/fbmem.c
... | ... | @@ -1468,16 +1468,39 @@ |
1468 | 1468 | return 0; |
1469 | 1469 | } |
1470 | 1470 | |
1471 | -static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) | |
1471 | +static bool apertures_overlap(struct aperture *gen, struct aperture *hw) | |
1472 | 1472 | { |
1473 | 1473 | /* is the generic aperture base the same as the HW one */ |
1474 | - if (gen->aperture_base == hw->aperture_base) | |
1474 | + if (gen->base == hw->base) | |
1475 | 1475 | return true; |
1476 | 1476 | /* is the generic aperture base inside the hw base->hw base+size */ |
1477 | - if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) | |
1477 | + if (gen->base > hw->base && gen->base <= hw->base + hw->size) | |
1478 | 1478 | return true; |
1479 | 1479 | return false; |
1480 | 1480 | } |
1481 | + | |
1482 | +static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) | |
1483 | +{ | |
1484 | + int i, j; | |
1485 | + struct apertures_struct *hwa = hw->apertures; | |
1486 | + struct apertures_struct *gena = gen->apertures; | |
1487 | + if (!hwa || !gena) | |
1488 | + return false; | |
1489 | + | |
1490 | + for (i = 0; i < hwa->count; ++i) { | |
1491 | + struct aperture *h = &hwa->ranges[i]; | |
1492 | + for (j = 0; j < gena->count; ++j) { | |
1493 | + struct aperture *g = &gena->ranges[j]; | |
1494 | + printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n", | |
1495 | + g->base, g->size, h->base, h->size); | |
1496 | + if (apertures_overlap(g, h)) | |
1497 | + return true; | |
1498 | + } | |
1499 | + } | |
1500 | + | |
1501 | + return false; | |
1502 | +} | |
1503 | + | |
1481 | 1504 | /** |
1482 | 1505 | * register_framebuffer - registers a frame buffer device |
1483 | 1506 | * @fb_info: frame buffer info structure |
drivers/video/fbsysfs.c
drivers/video/offb.c
... | ... | @@ -285,7 +285,7 @@ |
285 | 285 | { |
286 | 286 | if (info->screen_base) |
287 | 287 | iounmap(info->screen_base); |
288 | - release_mem_region(info->aperture_base, info->aperture_size); | |
288 | + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); | |
289 | 289 | framebuffer_release(info); |
290 | 290 | } |
291 | 291 | |
... | ... | @@ -491,8 +491,11 @@ |
491 | 491 | var->vmode = FB_VMODE_NONINTERLACED; |
492 | 492 | |
493 | 493 | /* set offb aperture size for generic probing */ |
494 | - info->aperture_base = address; | |
495 | - info->aperture_size = fix->smem_len; | |
494 | + info->apertures = alloc_apertures(1); | |
495 | + if (!info->apertures) | |
496 | + goto out_aper; | |
497 | + info->apertures->ranges[0].base = address; | |
498 | + info->apertures->ranges[0].size = fix->smem_len; | |
496 | 499 | |
497 | 500 | info->fbops = &offb_ops; |
498 | 501 | info->screen_base = ioremap(address, fix->smem_len); |
499 | 502 | |
... | ... | @@ -501,17 +504,20 @@ |
501 | 504 | |
502 | 505 | fb_alloc_cmap(&info->cmap, 256, 0); |
503 | 506 | |
504 | - if (register_framebuffer(info) < 0) { | |
505 | - iounmap(par->cmap_adr); | |
506 | - par->cmap_adr = NULL; | |
507 | - iounmap(info->screen_base); | |
508 | - framebuffer_release(info); | |
509 | - release_mem_region(res_start, res_size); | |
510 | - return; | |
511 | - } | |
507 | + if (register_framebuffer(info) < 0) | |
508 | + goto out_err; | |
512 | 509 | |
513 | 510 | printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", |
514 | 511 | info->node, full_name); |
512 | + return; | |
513 | + | |
514 | +out_err: | |
515 | + iounmap(info->screen_base); | |
516 | +out_aper: | |
517 | + iounmap(par->cmap_adr); | |
518 | + par->cmap_adr = NULL; | |
519 | + framebuffer_release(info); | |
520 | + release_mem_region(res_start, res_size); | |
515 | 521 | } |
516 | 522 | |
517 | 523 |
drivers/video/vesafb.c
... | ... | @@ -177,7 +177,7 @@ |
177 | 177 | { |
178 | 178 | if (info->screen_base) |
179 | 179 | iounmap(info->screen_base); |
180 | - release_mem_region(info->aperture_base, info->aperture_size); | |
180 | + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); | |
181 | 181 | framebuffer_release(info); |
182 | 182 | } |
183 | 183 | |
... | ... | @@ -295,8 +295,13 @@ |
295 | 295 | info->par = NULL; |
296 | 296 | |
297 | 297 | /* set vesafb aperture size for generic probing */ |
298 | - info->aperture_base = screen_info.lfb_base; | |
299 | - info->aperture_size = size_total; | |
298 | + info->apertures = alloc_apertures(1); | |
299 | + if (!info->apertures) { | |
300 | + err = -ENOMEM; | |
301 | + goto err; | |
302 | + } | |
303 | + info->apertures->ranges[0].base = screen_info.lfb_base; | |
304 | + info->apertures->ranges[0].size = size_total; | |
300 | 305 | |
301 | 306 | info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); |
302 | 307 | if (!info->screen_base) { |
include/linux/fb.h
... | ... | @@ -403,6 +403,7 @@ |
403 | 403 | #include <linux/notifier.h> |
404 | 404 | #include <linux/list.h> |
405 | 405 | #include <linux/backlight.h> |
406 | +#include <linux/slab.h> | |
406 | 407 | #include <asm/io.h> |
407 | 408 | |
408 | 409 | struct vm_area_struct; |
409 | 410 | |
... | ... | @@ -862,9 +863,21 @@ |
862 | 863 | /* we need the PCI or similiar aperture base/size not |
863 | 864 | smem_start/size as smem_start may just be an object |
864 | 865 | allocated inside the aperture so may not actually overlap */ |
865 | - resource_size_t aperture_base; | |
866 | - resource_size_t aperture_size; | |
866 | + struct apertures_struct { | |
867 | + unsigned int count; | |
868 | + struct aperture { | |
869 | + resource_size_t base; | |
870 | + resource_size_t size; | |
871 | + } ranges[0]; | |
872 | + } *apertures; | |
867 | 873 | }; |
874 | + | |
875 | +static inline struct apertures_struct *alloc_apertures(unsigned int max_num) { | |
876 | + struct apertures_struct *a = kzalloc(sizeof(struct apertures_struct) | |
877 | + + max_num * sizeof(struct aperture), GFP_KERNEL); | |
878 | + a->count = max_num; | |
879 | + return a; | |
880 | +} | |
868 | 881 | |
869 | 882 | #ifdef MODULE |
870 | 883 | #define FBINFO_DEFAULT FBINFO_MODULE |