From: Dave A. <ai...@gm...> - 2009-06-05 06:07:23
|
From: Dave Airlie <ai...@re...> With KMS we have ran into an issue where we really want the KMS fb driver to be the one running the console, so panics etc can be shown by switching out of X etc. However with vesafb/efifb built-in, we end up with those on fb0 and the KMS fb driver on fb1, driving the same piece of hw, so this adds an fb info flag to denote a firmware fbdev, and adds a new aperture base/size range which can be compared when the hw drivers are installed to see if there is a conflict with a firmware driver, and if there is the firmware driver is unregistered and the hw driver takes over. It uses new aperture_base/size members instead of comparing on the fix smem_start/length, as smem_start/length might for example only cover the first 1MB of the PCI aperture, and we could allocate the kms fb from 8MB into the aperture, thus they would never overlap. v2: add an fb_destroy callback so the firmware fb can cleanup after itself. vesafb will now remove the region it reserves and destroy its fb info. Signed-off-by: Dave Airlie <ai...@re...> --- drivers/gpu/drm/i915/intel_fb.c | 8 ++++++++ drivers/video/efifb.c | 5 ++++- drivers/video/fbmem.c | 29 +++++++++++++++++++++++++++++ drivers/video/vesafb.c | 15 ++++++++++++++- include/linux/fb.h | 12 +++++++++++- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index e4652dc..f1849d3 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c @@ -504,6 +504,14 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, info->fbops = &intelfb_ops; info->fix.line_length = fb->pitch; + + /* setup aperture base/size for vesafb takeover */ + info->aperture_base = dev->mode_config.fb_base; + if (IS_I9XX(dev)) + info->aperture_size = pci_resource_len(dev->pdev, 2); + else + info->aperture_size = pci_resource_len(dev->pdev, 0); + info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; info->fix.smem_len = size; diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index 8dea2bc..eb12182 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -280,6 +280,9 @@ static int __init efifb_probe(struct platform_device *dev) info->pseudo_palette = info->par; info->par = NULL; + info->aperture_base = efifb_fix.smem_start; + info->aperture_size = size_total; + info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); if (!info->screen_base) { printk(KERN_ERR "efifb: abort, cannot ioremap video memory " @@ -337,7 +340,7 @@ static int __init efifb_probe(struct platform_device *dev) info->fbops = &efifb_ops; info->var = efifb_defined; info->fix = efifb_fix; - info->flags = FBINFO_FLAG_DEFAULT; + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { printk(KERN_ERR "efifb: cannot allocate colormap\n"); diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d412a1d..67b8466 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1462,6 +1462,16 @@ static int fb_check_foreignness(struct fb_info *fi) return 0; } +static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) +{ + /* is the generic aperture base the same as the HW one */ + if (gen->aperture_base == hw->aperture_base) + return true; + /* is the generic aperture base inside the hw base->hw base+size */ + if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) + return true; + return false; +} /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure @@ -1485,6 +1495,21 @@ register_framebuffer(struct fb_info *fb_info) if (fb_check_foreignness(fb_info)) return -ENOSYS; + /* check all firmware fbs and kick off if the base addr overlaps */ + for (i = 0 ; i < FB_MAX; i++) { + if (!registered_fb[i]) + continue; + + if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) { + if (fb_do_apertures_overlap(registered_fb[i], fb_info)) { + printk("fb: conflicting fb hw usage %s vs %s - removing generic driver\n", + fb_info->fix.id, registered_fb[i]->fix.id); + unregister_framebuffer(registered_fb[i]); + break; + } + } + } + num_registered_fb++; for (i = 0 ; i < FB_MAX; i++) if (!registered_fb[i]) @@ -1586,6 +1611,10 @@ unregister_framebuffer(struct fb_info *fb_info) device_destroy(fb_class, MKDEV(FB_MAJOR, i)); event.info = fb_info; fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + + /* this may free fb info */ + if (fb_info->fbops->fb_destroy) + fb_info->fbops->fb_destroy(fb_info); done: return ret; } diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index d6856f4..bd37ee1 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -174,8 +174,17 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, return err; } +static void vesafb_destroy(struct fb_info *info) +{ + if (info->screen_base) + iounmap(info->screen_base); + release_mem_region(info->aperture_base, info->aperture_size); + framebuffer_release(info); +} + static struct fb_ops vesafb_ops = { .owner = THIS_MODULE, + .fb_destroy = vesafb_destroy, .fb_setcolreg = vesafb_setcolreg, .fb_pan_display = vesafb_pan_display, .fb_fillrect = cfb_fillrect, @@ -286,6 +295,10 @@ static int __init vesafb_probe(struct platform_device *dev) info->pseudo_palette = info->par; info->par = NULL; + /* set vesafb aperture size for generic probing */ + info->aperture_base = screen_info.lfb_base; + info->aperture_size = size_total; + info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); if (!info->screen_base) { printk(KERN_ERR @@ -437,7 +450,7 @@ static int __init vesafb_probe(struct platform_device *dev) info->fbops = &vesafb_ops; info->var = vesafb_defined; info->fix = vesafb_fix; - info->flags = FBINFO_FLAG_DEFAULT | + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE | (ypan ? FBINFO_HWACCEL_YPAN : 0); if (!ypan) diff --git a/include/linux/fb.h b/include/linux/fb.h index 330c4b1..01e9794 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -677,6 +677,9 @@ struct fb_ops { /* get capability given var */ void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, struct fb_var_screeninfo *var); + + /* teardown any resources to do with this framebuffer */ + void (*fb_destroy)(struct fb_info *info); }; #ifdef CONFIG_FB_TILEBLITTING @@ -786,6 +789,8 @@ struct fb_tile_ops { #define FBINFO_MISC_USEREVENT 0x10000 /* event request from userspace */ #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ +#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware + inited framebuffer */ /* A driver may set this flag to indicate that it does want a set_par to be * called every time when fbcon_switch is executed. The advantage is that with @@ -854,7 +859,12 @@ struct fb_info { u32 state; /* Hardware state i.e suspend */ void *fbcon_par; /* fbcon use-only private area */ /* From here on everything is device dependent */ - void *par; + void *par; + /* we need the PCI or similiar aperture base/size not + smem_start/size as smem_start may just be an object + allocated inside the aperture so may not actually overlap */ + resource_size_t aperture_base; + resource_size_t aperture_size; }; #ifdef MODULE -- 1.5.4.1 |
From: Peter J. <pj...@re...> - 2009-06-05 14:14:54
|
On 06/05/2009 02:07 AM, Dave Airlie wrote: > From: Dave Airlie <ai...@re...> > > With KMS we have ran into an issue where we really want the KMS fb driver > to be the one running the console, so panics etc can be shown by switching > out of X etc. > > However with vesafb/efifb built-in, we end up with those on fb0 and the > KMS fb driver on fb1, driving the same piece of hw, so this adds an fb info > flag to denote a firmware fbdev, and adds a new aperture base/size range > which can be compared when the hw drivers are installed to see if there > is a conflict with a firmware driver, and if there is the firmware driver is > unregistered and the hw driver takes over. > > It uses new aperture_base/size members instead of comparing on the fix > smem_start/length, as smem_start/length might for example only cover the > first 1MB of the PCI aperture, and we could allocate the kms fb from 8MB > into the aperture, thus they would never overlap. > > v2: add an fb_destroy callback so the firmware fb can cleanup after itself. > vesafb will now remove the region it reserves and destroy its fb info. > > Signed-off-by: Dave Airlie <ai...@re...> This version looks good to me. Acked-by: Peter Jones <pj...@re...> > --- > drivers/gpu/drm/i915/intel_fb.c | 8 ++++++++ > drivers/video/efifb.c | 5 ++++- > drivers/video/fbmem.c | 29 +++++++++++++++++++++++++++++ > drivers/video/vesafb.c | 15 ++++++++++++++- > include/linux/fb.h | 12 +++++++++++- > 5 files changed, 66 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c > index e4652dc..f1849d3 100644 > --- a/drivers/gpu/drm/i915/intel_fb.c > +++ b/drivers/gpu/drm/i915/intel_fb.c > @@ -504,6 +504,14 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, > info->fbops = &intelfb_ops; > > info->fix.line_length = fb->pitch; > + > + /* setup aperture base/size for vesafb takeover */ > + info->aperture_base = dev->mode_config.fb_base; > + if (IS_I9XX(dev)) > + info->aperture_size = pci_resource_len(dev->pdev, 2); > + else > + info->aperture_size = pci_resource_len(dev->pdev, 0); > + > info->fix.smem_start = dev->mode_config.fb_base + obj_priv->gtt_offset; > info->fix.smem_len = size; > > diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c > index 8dea2bc..eb12182 100644 > --- a/drivers/video/efifb.c > +++ b/drivers/video/efifb.c > @@ -280,6 +280,9 @@ static int __init efifb_probe(struct platform_device *dev) > info->pseudo_palette = info->par; > info->par = NULL; > > + info->aperture_base = efifb_fix.smem_start; > + info->aperture_size = size_total; > + > info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); > if (!info->screen_base) { > printk(KERN_ERR "efifb: abort, cannot ioremap video memory " > @@ -337,7 +340,7 @@ static int __init efifb_probe(struct platform_device *dev) > info->fbops = &efifb_ops; > info->var = efifb_defined; > info->fix = efifb_fix; > - info->flags = FBINFO_FLAG_DEFAULT; > + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE; > > if ((err = fb_alloc_cmap(&info->cmap, 256, 0)) < 0) { > printk(KERN_ERR "efifb: cannot allocate colormap\n"); > diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c > index d412a1d..67b8466 100644 > --- a/drivers/video/fbmem.c > +++ b/drivers/video/fbmem.c > @@ -1462,6 +1462,16 @@ static int fb_check_foreignness(struct fb_info *fi) > return 0; > } > > +static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) > +{ > + /* is the generic aperture base the same as the HW one */ > + if (gen->aperture_base == hw->aperture_base) > + return true; > + /* is the generic aperture base inside the hw base->hw base+size */ > + if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) > + return true; > + return false; > +} > /** > * register_framebuffer - registers a frame buffer device > * @fb_info: frame buffer info structure > @@ -1485,6 +1495,21 @@ register_framebuffer(struct fb_info *fb_info) > if (fb_check_foreignness(fb_info)) > return -ENOSYS; > > + /* check all firmware fbs and kick off if the base addr overlaps */ > + for (i = 0 ; i < FB_MAX; i++) { > + if (!registered_fb[i]) > + continue; > + > + if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) { > + if (fb_do_apertures_overlap(registered_fb[i], fb_info)) { > + printk("fb: conflicting fb hw usage %s vs %s - removing generic driver\n", > + fb_info->fix.id, registered_fb[i]->fix.id); > + unregister_framebuffer(registered_fb[i]); > + break; > + } > + } > + } > + > num_registered_fb++; > for (i = 0 ; i < FB_MAX; i++) > if (!registered_fb[i]) > @@ -1586,6 +1611,10 @@ unregister_framebuffer(struct fb_info *fb_info) > device_destroy(fb_class, MKDEV(FB_MAJOR, i)); > event.info = fb_info; > fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); > + > + /* this may free fb info */ > + if (fb_info->fbops->fb_destroy) > + fb_info->fbops->fb_destroy(fb_info); > done: > return ret; > } > diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c > index d6856f4..bd37ee1 100644 > --- a/drivers/video/vesafb.c > +++ b/drivers/video/vesafb.c > @@ -174,8 +174,17 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, > return err; > } > > +static void vesafb_destroy(struct fb_info *info) > +{ > + if (info->screen_base) > + iounmap(info->screen_base); > + release_mem_region(info->aperture_base, info->aperture_size); > + framebuffer_release(info); > +} > + > static struct fb_ops vesafb_ops = { > .owner = THIS_MODULE, > + .fb_destroy = vesafb_destroy, > .fb_setcolreg = vesafb_setcolreg, > .fb_pan_display = vesafb_pan_display, > .fb_fillrect = cfb_fillrect, > @@ -286,6 +295,10 @@ static int __init vesafb_probe(struct platform_device *dev) > info->pseudo_palette = info->par; > info->par = NULL; > > + /* set vesafb aperture size for generic probing */ > + info->aperture_base = screen_info.lfb_base; > + info->aperture_size = size_total; > + > info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); > if (!info->screen_base) { > printk(KERN_ERR > @@ -437,7 +450,7 @@ static int __init vesafb_probe(struct platform_device *dev) > info->fbops = &vesafb_ops; > info->var = vesafb_defined; > info->fix = vesafb_fix; > - info->flags = FBINFO_FLAG_DEFAULT | > + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE | > (ypan ? FBINFO_HWACCEL_YPAN : 0); > > if (!ypan) > diff --git a/include/linux/fb.h b/include/linux/fb.h > index 330c4b1..01e9794 100644 > --- a/include/linux/fb.h > +++ b/include/linux/fb.h > @@ -677,6 +677,9 @@ struct fb_ops { > /* get capability given var */ > void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps, > struct fb_var_screeninfo *var); > + > + /* teardown any resources to do with this framebuffer */ > + void (*fb_destroy)(struct fb_info *info); > }; > > #ifdef CONFIG_FB_TILEBLITTING > @@ -786,6 +789,8 @@ struct fb_tile_ops { > #define FBINFO_MISC_USEREVENT 0x10000 /* event request > from userspace */ > #define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */ > +#define FBINFO_MISC_FIRMWARE 0x40000 /* a replaceable firmware > + inited framebuffer */ > > /* A driver may set this flag to indicate that it does want a set_par to be > * called every time when fbcon_switch is executed. The advantage is that with > @@ -854,7 +859,12 @@ struct fb_info { > u32 state; /* Hardware state i.e suspend */ > void *fbcon_par; /* fbcon use-only private area */ > /* From here on everything is device dependent */ > - void *par; > + void *par; > + /* we need the PCI or similiar aperture base/size not > + smem_start/size as smem_start may just be an object > + allocated inside the aperture so may not actually overlap */ > + resource_size_t aperture_base; > + resource_size_t aperture_size; > }; > > #ifdef MODULE -- Peter AIX is Unix from the universe where Spock had a beard. |
From: Dave A. <ai...@gm...> - 2009-06-06 02:04:53
|
On Fri, Jun 5, 2009 at 11:51 PM, Peter Jones<pj...@re...> wrote: > On 06/05/2009 02:07 AM, Dave Airlie wrote: >> From: Dave Airlie <ai...@re...> >> >> With KMS we have ran into an issue where we really want the KMS fb driver >> to be the one running the console, so panics etc can be shown by switching >> out of X etc. >> >> However with vesafb/efifb built-in, we end up with those on fb0 and the >> KMS fb driver on fb1, driving the same piece of hw, so this adds an fb info >> flag to denote a firmware fbdev, and adds a new aperture base/size range >> which can be compared when the hw drivers are installed to see if there >> is a conflict with a firmware driver, and if there is the firmware driver is >> unregistered and the hw driver takes over. >> >> It uses new aperture_base/size members instead of comparing on the fix >> smem_start/length, as smem_start/length might for example only cover the >> first 1MB of the PCI aperture, and we could allocate the kms fb from 8MB >> into the aperture, thus they would never overlap. >> >> v2: add an fb_destroy callback so the firmware fb can cleanup after itself. >> vesafb will now remove the region it reserves and destroy its fb info. >> >> Signed-off-by: Dave Airlie <ai...@re...> > > This version looks good to me. > > Acked-by: Peter Jones <pj...@re...> > Andrew do we have an fbdev maintainer or can you pick this up for the next merge window? Dave. |
From: Andrew M. <ak...@li...> - 2009-06-06 02:13:21
|
On Sat, 6 Jun 2009 11:38:32 +1000 Dave Airlie <ai...@gm...> wrote: > On Fri, Jun 5, 2009 at 11:51 PM, Peter Jones<pj...@re...> wrote: > > On 06/05/2009 02:07 AM, Dave Airlie wrote: > >> From: Dave Airlie <ai...@re...> > >> > >> With KMS we have ran into an issue where we really want the KMS fb driver > >> to be the one running the console, so panics etc can be shown by switching > >> out of X etc. > >> > >> However with vesafb/efifb built-in, we end up with those on fb0 and the > >> KMS fb driver on fb1, driving the same piece of hw, so this adds an fb info > >> flag to denote a firmware fbdev, and adds a new aperture base/size range > >> which can be compared when the hw drivers are installed to see if there > >> is a conflict with a firmware driver, and if there is the firmware driver is > >> unregistered and the hw driver takes over. > >> > >> It uses new aperture_base/size members instead of comparing on the fix > >> smem_start/length, as smem_start/length might for example only cover the > >> first 1MB of the PCI aperture, and we could allocate the kms fb from 8MB > >> into the aperture, thus they would never overlap. > >> > >> v2: add an fb_destroy callback so the firmware fb can cleanup after itself. > >> vesafb will now remove the region it reserves and destroy its fb info. > >> > >> Signed-off-by: Dave Airlie <ai...@re...> > > > > This version looks good to me. > > > > Acked-by: Peter Jones <pj...@re...> > > > > Andrew do we have an fbdev maintainer Tony suddenly vanished nearly two years ago. He did that once before, then resurfaced after six months - he'd been working in a remote village with no net connection. Hopefully he will reappear again. In the meanwhile I'm handling fbdev patches and Geert and Krzysztof are doing the technical work when time permits. I'll occasionally troll linux-fbdev-devel looking for patches which people send. > or can you pick this up for the next merge window? No probs. |