Commit 1471ca9aa71cd37b6a7476bb6f06a3a8622ea1bd

Authored by Marcin Slusarz
Committed by Dave Airlie
1 parent 3da1f33e79

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
... ... @@ -80,6 +80,7 @@
80 80 */
81 81 void framebuffer_release(struct fb_info *info)
82 82 {
  83 + kfree(info->apertures);
83 84 kfree(info);
84 85 }
85 86 EXPORT_SYMBOL(framebuffer_release);
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) {
... ... @@ -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