diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
index 731fce6..cb19cae 100644
--- a/drivers/video/fbmem.c
+++ b/drivers/video/fbmem.c
@@ -1504,6 +1504,7 @@ static bool fb_do_apertures_overlap(struct apertures_struct *gena,
}
#define VGA_FB_PHYS 0xA0000
+#define VGA_FB_PHYS_LEN 65536
void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary)
{@@ -1532,6 +1533,17 @@ void remove_conflicting_framebuffers(struct apertures_struct *a,
}
EXPORT_SYMBOL(remove_conflicting_framebuffers);
+struct resource *request_vga_mem_region(const char *name)
+{
+ struct resource *res = request_mem_region(VGA_FB_PHYS,
+ VGA_FB_PHYS_LEN, name);
+ if (res = NULL)
+ printk(KERN_INFO "%s: other driver owns the primary card, refusing to load\n",
+ name);
+ return res;
+}
+EXPORT_SYMBOL(request_vga_mem_region);
+
/**
* register_framebuffer - registers a frame buffer device
* @fb_info: frame buffer info structure@@ -1548,6 +1560,8 @@ register_framebuffer(struct fb_info *fb_info)
int i;
struct fb_event event;
struct fb_videomode mode;
+ bool primary;
+ struct resource *res = fb_info->resource;
if (num_registered_fb = FB_MAX)
return -ENXIO;
@@ -1555,8 +1569,19 @@ register_framebuffer(struct fb_info *fb_info)
if (fb_check_foreignness(fb_info))
return -ENOSYS;
+ primary = fb_is_primary_device(fb_info);
remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id,
- fb_is_primary_device(fb_info));
+ primary);
+
+ /*
+ * if the card is primary and the resource was not already allocated
+ * by framebuffer driver then lock vga memory region
+ */
+ if (primary && res = NULL) {
+ res = request_vga_mem_region(fb_info->fix.id);
+ if (res = NULL)
+ return -EBUSY;
+ }
num_registered_fb++;
for (i = 0 ; i < FB_MAX; i++)@@ -1574,6 +1599,7 @@ register_framebuffer(struct fb_info *fb_info)
fb_info->dev = NULL;
} else
fb_init_device(fb_info);
+ fb_info->resource = res;
if (fb_info->pixmap.addr = NULL) {
fb_info->pixmap.addr = kmalloc(FBPIXMAPSIZE, GFP_KERNEL);@@ -1658,6 +1684,11 @@ unregister_framebuffer(struct fb_info *fb_info)
num_registered_fb--;
fb_cleanup_device(fb_info);
device_destroy(fb_class, MKDEV(FB_MAJOR, i));
+ if (fb_info->resource) {
+ release_mem_region(fb_info->resource->start,
+ resource_size(fb_info->resource));
+ fb_info->resource = NULL;
+ }
event.info = fb_info;
fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event);
diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
index 28ccab4..952ae43 100644
--- a/drivers/video/vga16fb.c
+++ b/drivers/video/vga16fb.c
@@ -1307,6 +1307,16 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
struct vga16fb_par *par;
int i;
int ret = 0;
+ struct resource *res;
+
+ /*
+ * We have to do it here instead of relying on register_framebuffer - it
+ * won't request that region because vga16fb won't be detected as primary
+ * driver, because it's not directly connected to pci layer.
+ */
+ res = request_vga_mem_region("vga16fb");
+ if (!res)
+ return -EBUSY;
printk(KERN_DEBUG "vga16fb: initializing\n");
info = framebuffer_alloc(sizeof(struct vga16fb_par), &dev->dev);@@ -1321,6 +1331,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
goto err_ioremap;
}
+ info->resource = res;
/* XXX share VGA_FB_PHYS and I/O region with vgacon and others */
info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0);
@@ -1390,6 +1401,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev)
err_ioremap:
framebuffer_release(info);
err_fb_alloc:
+ release_mem_region(res->start, resource_size(res));
return ret;
}
diff --git a/include/linux/fb.h b/include/linux/fb.h
index 8e5a9df..fc90804 100644
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -868,6 +868,8 @@ struct fb_info {
resource_size_t size;
} ranges[0];
} *apertures;
+
+ struct resource *resource;
};
static inline struct apertures_struct *alloc_apertures(unsigned int max_num) {@@ -971,6 +973,7 @@ extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info);
extern void remove_conflicting_framebuffers(struct apertures_struct *a,
const char *name, bool primary);
+extern struct resource *request_vga_mem_region(const char *name);
extern int fb_prepare_logo(struct fb_info *fb_info, int rotate);
extern int fb_show_logo(struct fb_info *fb_info, int rotate);
extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size);
--
1.7.1.1