* [PATCH][LINUX] Dynamic modes support for PV xenfb
[not found] ` <4774DEFD02000018006084F9@sinclair.provo.novell.com>
@ 2007-12-28 18:33 ` Pat Campbell
2007-12-28 19:00 ` John Levon
0 siblings, 1 reply; 4+ messages in thread
From: Pat Campbell @ 2007-12-28 18:33 UTC (permalink / raw)
To: xen-devel
[-- Attachment #1: Type: text/plain, Size: 538 bytes --]
Attached patch adds multiple frame buffer resolution support to
the PV xenfb frame buffer driver.
Code is essentially the same as I sent in the previous RFC except
the frame buffer size is now 800x600 if the backend does not
support feature-resize, same memory footprint.
Corresponding backend IOEMU patch is required for functionality but
this patch is not dependent on it, preserving backwards compatibility.
Please apply to tip of linux-2.6.18-xen
Signed- off- by: Pat Campbell <plc@novell.com>
[-- Attachment #2: xen-fbfront-resize.patch --]
[-- Type: text/plain, Size: 8285 bytes --]
diff -r 61c96456a3e1 drivers/xen/fbfront/xenfb.c
--- a/drivers/xen/fbfront/xenfb.c Thu Dec 20 16:58:14 2007 +0000
+++ b/drivers/xen/fbfront/xenfb.c Fri Dec 28 03:12:41 2007 -0700
@@ -62,6 +62,9 @@ struct xenfb_info
struct xenfb_page *page;
unsigned long *mfns;
int update_wanted; /* XENFB_TYPE_UPDATE wanted */
+ int feature_resize; /* Backend has resize feature */
+ int resize_dpy;
+ int xres, yres;
struct xenbus_device *xbdev;
};
@@ -130,13 +133,18 @@ struct xenfb_info
* Oh well, we wont be updating the writes to this page anytime soon.
*/
+#define XENFB_PIXCLOCK 9025 /* Xorg "1280x1024" 110.80 to FB 1000000/110.80 */
+#define XENFB_MAX_WIDTH 1024
+#define XENFB_MAX_HEIGHT 768
+
static int xenfb_fps = 20;
-static unsigned long xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
+static unsigned long xenfb_mem_len = XENFB_MAX_WIDTH * XENFB_MAX_HEIGHT * XENFB_DEPTH / 8;
static int xenfb_remove(struct xenbus_device *);
static void xenfb_init_shared_page(struct xenfb_info *);
static int xenfb_connect_backend(struct xenbus_device *, struct xenfb_info *);
static void xenfb_disconnect_backend(struct xenfb_info *);
+static void xenfb_refresh(struct xenfb_info *info, int x1, int y1, int w, int h);
static void xenfb_do_update(struct xenfb_info *info,
int x, int y, int w, int h)
@@ -155,6 +163,25 @@ static void xenfb_do_update(struct xenfb
mb(); /* ensure ring space available */
XENFB_OUT_RING_REF(info->page, prod) = event;
wmb(); /* ensure ring contents visible */
+ info->page->out_prod = prod + 1;
+
+ notify_remote_via_irq(info->irq);
+}
+
+static void xenfb_do_resize(struct xenfb_info *info)
+{
+ union xenfb_out_event event;
+ __u32 prod;
+
+ event.type = XENFB_TYPE_RESIZE;
+ event.resize.width = info->xres;
+ event.resize.height = info->yres;
+
+ prod = info->page->out_prod;
+ /* caller ensures !xenfb_queue_full() */
+ mb(); /* ensure ring space available */
+ XENFB_OUT_RING_REF(info->page, prod) = event;
+ wmb(); /* ensure ring contents visible */
info->page->out_prod = prod + 1;
notify_remote_via_irq(info->irq);
@@ -209,6 +236,16 @@ static void xenfb_update_screen(struct x
xenfb_do_update(info, x1, y1, x2 - x1, y2 - y1);
}
+static void xenfb_resize_screen(struct xenfb_info *info)
+{
+ if (xenfb_queue_full(info))
+ return;
+
+ info->resize_dpy = 0;
+ xenfb_do_resize(info);
+ xenfb_refresh(info, 0, 0, info->xres, info->yres);
+}
+
static int xenfb_thread(void *data)
{
struct xenfb_info *info = data;
@@ -217,6 +254,9 @@ static int xenfb_thread(void *data)
if (info->dirty) {
info->dirty = 0;
xenfb_update_screen(info);
+ }
+ if (info->resize_dpy) {
+ xenfb_resize_screen(info);
}
wait_event_interruptible(info->wq,
kthread_should_stop() || info->dirty);
@@ -413,6 +453,46 @@ static int xenfb_mmap(struct fb_info *fb
return 0;
}
+static int
+xenfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+ struct xenfb_info *xenfb_info;
+
+ xenfb_info = info->par;
+
+ if (!xenfb_info->feature_resize) {
+ if (var->xres == XENFB_WIDTH && var->yres == XENFB_HEIGHT) {
+ return 0;
+ }
+ return -EINVAL;
+ }
+ if (var->xres == 1024 && var->yres == 768) {
+ return 0;
+ }
+ if (var->xres == 800 && var->yres == 600) {
+ return 0;
+ }
+ if (var->xres == 640 && var->yres == 480) {
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int xenfb_set_par(struct fb_info *info)
+{
+ struct xenfb_info *xenfb_info;
+
+ xenfb_info = info->par;
+
+ if (xenfb_info->xres != info->var.xres ||
+ xenfb_info->yres != info->var.yres) {
+ xenfb_info->xres = info->var.xres;
+ xenfb_info->yres = info->var.yres;
+ xenfb_info->resize_dpy = 1;
+ }
+ return 0;
+}
+
static struct fb_ops xenfb_fb_ops = {
.owner = THIS_MODULE,
.fb_setcolreg = xenfb_setcolreg,
@@ -420,6 +500,8 @@ static struct fb_ops xenfb_fb_ops = {
.fb_copyarea = xenfb_copyarea,
.fb_imageblit = xenfb_imageblit,
.fb_mmap = xenfb_mmap,
+ .fb_check_var = xenfb_check_var,
+ .fb_set_par = xenfb_set_par,
};
static irqreturn_t xenfb_event_handler(int rq, void *dev_id,
@@ -451,16 +533,28 @@ static int __devinit xenfb_probe(struct
struct xenfb_info *info;
struct fb_info *fb_info;
int ret;
+ int val;
info = kzalloc(sizeof(*info), GFP_KERNEL);
if (info == NULL) {
xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
return -ENOMEM;
}
+
+ if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-resize", "%d", &val) < 0)
+ val = 0;
+ info->feature_resize = val;
+ if (info->feature_resize)
+ xenfb_mem_len = XENFB_MAX_WIDTH * XENFB_MAX_HEIGHT * XENFB_DEPTH / 8;
+ else
+ xenfb_mem_len = XENFB_WIDTH * XENFB_HEIGHT * XENFB_DEPTH / 8;
+
dev->dev.driver_data = info;
info->xbdev = dev;
info->irq = -1;
info->x1 = info->y1 = INT_MAX;
+ info->xres = XENFB_WIDTH;
+ info->yres = XENFB_HEIGHT;
spin_lock_init(&info->dirty_lock);
mutex_init(&info->mm_lock);
init_waitqueue_head(&info->wq);
@@ -504,9 +598,10 @@ static int __devinit xenfb_probe(struct
fb_info->screen_base = info->fb;
fb_info->fbops = &xenfb_fb_ops;
- fb_info->var.xres_virtual = fb_info->var.xres = info->page->width;
- fb_info->var.yres_virtual = fb_info->var.yres = info->page->height;
+ fb_info->var.xres_virtual = fb_info->var.xres = info->xres;
+ fb_info->var.yres_virtual = fb_info->var.yres = info->yres;
fb_info->var.bits_per_pixel = info->page->depth;
+ fb_info->var.pixclock = XENFB_PIXCLOCK;
fb_info->var.red = (struct fb_bitfield){16, 8, 0};
fb_info->var.green = (struct fb_bitfield){8, 8, 0};
@@ -600,19 +695,30 @@ static void xenfb_init_shared_page(struc
static void xenfb_init_shared_page(struct xenfb_info *info)
{
int i;
-
+ int j;
+ int entries_per_pd;
+
+ entries_per_pd = PAGE_SIZE/sizeof(unsigned long);
+
for (i = 0; i < info->nr_pages; i++)
info->pages[i] = vmalloc_to_page(info->fb + i * PAGE_SIZE);
- for (i = 0; i < info->nr_pages; i++)
- info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
-
info->page->pd[0] = vmalloc_to_mfn(info->mfns);
info->page->pd[1] = 0;
+ for ( j = i = 0; i < info->nr_pages; i++) {
+ info->mfns[i] = vmalloc_to_mfn(info->fb + i * PAGE_SIZE);
+ if ( i && i % entries_per_pd == 0 ) {
+ j++;
+ info->page->pd[j] = vmalloc_to_mfn(&info->mfns[i]);
+ }
+ }
info->page->width = XENFB_WIDTH;
info->page->height = XENFB_HEIGHT;
info->page->depth = XENFB_DEPTH;
- info->page->line_length = (info->page->depth / 8) * info->page->width;
+ if (info->feature_resize)
+ info->page->line_length = (info->page->depth / 8) * XENFB_MAX_WIDTH;
+ else
+ info->page->line_length = (info->page->depth / 8) * XENFB_WIDTH;
info->page->mem_length = xenfb_mem_len;
info->page->in_cons = info->page->in_prod = 0;
info->page->out_cons = info->page->out_prod = 0;
diff -r 61c96456a3e1 include/xen/interface/io/fbif.h
--- a/include/xen/interface/io/fbif.h Thu Dec 20 16:58:14 2007 +0000
+++ b/include/xen/interface/io/fbif.h Fri Dec 28 01:26:50 2007 -0700
@@ -50,12 +50,26 @@ struct xenfb_update
int32_t height; /* rect height */
};
+/*
+ * Framebuffer resize notification event
+ * Capable backend sets feature-resize in xenstore.
+ */
+#define XENFB_TYPE_RESIZE 3
+
+struct xenfb_resize
+{
+ uint8_t type; /* XENFB_TYPE_RESIZE */
+ int32_t width; /* xres */
+ int32_t height; /* yres */
+};
+
#define XENFB_OUT_EVENT_SIZE 40
union xenfb_out_event
{
uint8_t type;
struct xenfb_update update;
+ struct xenfb_resize resize;
char pad[XENFB_OUT_EVENT_SIZE];
};
@@ -111,8 +125,12 @@ struct xenfb_page
* PAGE_SIZE / sizeof(*pd) bytes. With PAGE_SIZE == 4096 and
* sizeof(unsigned long) == 4, that's 4 Megs. Two directory
* pages should be enough for a while.
+ *
+ * Increased to 3 to support 1280x1024 resolution on a 64bit system
+ * (1280*1024*4)/PAGE_SIZE = 1280 pages required
+ * PAGE_SIZE/64bit long = 512 pages per page directory
*/
- unsigned long pd[2];
+ unsigned long pd[3];
};
/*
[-- Attachment #3: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH][LINUX] Dynamic modes support for PV xenfb
2007-12-28 18:33 ` Pat Campbell
@ 2007-12-28 19:00 ` John Levon
[not found] ` <4777A666.3E48.0018.0@novell.com>
0 siblings, 1 reply; 4+ messages in thread
From: John Levon @ 2007-12-28 19:00 UTC (permalink / raw)
To: Pat Campbell; +Cc: xen-devel
On Fri, Dec 28, 2007 at 11:33:17AM -0700, Pat Campbell wrote:
> Attached patch adds multiple frame buffer resolution support to
> the PV xenfb frame buffer driver.
Note this change will need an update to:
http://wiki.xensource.com/xenwiki/APIChangelog
if/when it goes in.
regards
john
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH][LINUX] Dynamic modes support for PV xenfb
@ 2007-12-31 3:16 Pat Campbell
0 siblings, 0 replies; 4+ messages in thread
From: Pat Campbell @ 2007-12-31 3:16 UTC (permalink / raw)
To: John Levon; +Cc: xen-devel
>>> On Fri, Dec 28, 2007 at 12:00 PM, in message
<20071228190018.GB8404@totally.trollied.org.uk>, John Levon
<levon@movementarian.org> wrote:
> On Fri, Dec 28, 2007 at 11:33:17AM - 0700, Pat Campbell wrote:
>
>> Attached patch adds multiple frame buffer resolution support to
>> the PV xenfb frame buffer driver.
>
> Note this change will need an update to:
>
> http://wiki.xensource.com/xenwiki/APIChangelog
>
> if/when it goes in.
>
> regards
> john
John,
I read the page at the included wiki link. This patch is backwards
compatible and "should not" present any cross-OS compatibility
issues. Resolution change, if any, is driven by the guest OS.
I am not adversed to documenting the change but not sure
it is an API change.
Pat
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH][LINUX] Dynamic modes support for PV xenfb
[not found] ` <4777A666.3E48.0018.0@novell.com>
@ 2007-12-31 3:47 ` John Levon
0 siblings, 0 replies; 4+ messages in thread
From: John Levon @ 2007-12-31 3:47 UTC (permalink / raw)
To: Pat Campbell; +Cc: xen-devel
On Sun, Dec 30, 2007 at 02:10:09PM -0700, Pat Campbell wrote:
> >> Attached patch adds multiple frame buffer resolution support to
> >> the PV xenfb frame buffer driver.
> >
> > Note this change will need an update to:
> >
> > http://wiki.xensource.com/xenwiki/APIChangelog
> >
> > if/when it goes in.
>
> John,
>
> I read the page at the included wiki link. This patch is backwards
> compatible and "should not" present any cross-OS compatibility
> issues. Resolution change, if any, is driven by the guest OS.
>
> I am not adversed to documenting the change but not sure
> it is an API change.
An addition is a change, just not an incompatible one.
regards,
john
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-12-31 3:47 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-31 3:16 [PATCH][LINUX] Dynamic modes support for PV xenfb Pat Campbell
[not found] <4774D94A02000018006084D2@sinclair.provo.novell.com>
[not found] ` <4774DEFD02000018006084F9@sinclair.provo.novell.com>
2007-12-28 18:33 ` Pat Campbell
2007-12-28 19:00 ` John Levon
[not found] ` <4777A666.3E48.0018.0@novell.com>
2007-12-31 3:47 ` John Levon
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.