From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
To: James Simmons <jsimmons@infradead.org>
Cc: linux-kernel mailing list <linux-kernel@vger.kernel.org>,
Linux Fbdev development list
<linux-fbdev-devel@lists.sourceforge.net>,
Pavel Machek <pavel@ucw.cz>
Subject: [PATCH] Framebuffer: 2nd try: client notification mecanism & PM
Date: 30 Jul 2003 09:14:21 -0400 [thread overview]
Message-ID: <1059570860.2418.2.camel@gaston> (raw)
In-Reply-To: <1059567270.8545.70.camel@gaston>
(resent with proper recipients list, sorry)
So, here's a new version that removes checking for suspend field
all over fbcon. I tried it here with a modified radeonfb that sets
the fbops to some dummy functions (provided by fbmem.c in this
patch though you may want to move them around).
In theory, I could implement power management properly without the client
notification mecanism by just setting the dummy fbops and directly calling
update_screen from the low level fbdev on resume, but that doesn't smell
good. The console subsystem is a bit of a nightmare to me, James, can we
currently have several consoles on several heads ? (that currcons in
vt.c is disturbing me). It may be worth doing better than just update_screen
(fg_console) when resuming in fbcon.c... (this callback will be called for
each fbdev who is waking up).
Let me know what you think, in all cases, asap so I can push the remaining
fbdev driver bits.
Ben.
===== drivers/video/fbmem.c 1.77 vs edited =====
--- 1.77/drivers/video/fbmem.c Mon May 26 20:51:43 2003
+++ edited/drivers/video/fbmem.c Wed Jul 30 08:59:06 2003
@@ -392,6 +392,9 @@
struct fb_info *registered_fb[FB_MAX];
int num_registered_fb;
+static LIST_HEAD(fb_clients);
+static DECLARE_MUTEX(fb_clients_lock);
+
#ifdef CONFIG_FB_OF
static int ofonly __initdata = 0;
#endif
@@ -935,6 +938,8 @@
fb_pan_display(info, &info->var);
fb_set_cmap(&info->cmap, 1, info);
+
+ fb_clients_call_mode_changed(info);
}
}
return 0;
@@ -1371,6 +1376,107 @@
__setup("video=", video_setup);
+/*
+ * Dummy operations used typically when power managing
+ */
+
+int fb_dummy_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+ return 0;
+}
+
+void fb_dummy_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
+{
+}
+
+void fb_dummy_copyarea(struct fb_info *info, const struct fb_copyarea *area)
+{
+}
+
+void fb_dummy_imageblit(struct fb_info *info, const struct fb_image *image)
+{
+}
+
+/*
+ * Wrappers to client calls
+ */
+
+int
+fb_set_suspend(struct fb_info *info, int suspended)
+{
+ if (suspended == info->suspended)
+ return 0;
+
+ info->suspended = suspended;
+ if (suspended)
+ fb_clients_call_suspended(info);
+ else
+ fb_clients_call_resumed(info);
+
+ return 0;
+}
+
+int register_fb_client(struct fb_client_ops *ops, void *data)
+{
+ struct fb_client *client;
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+
+ memset(client, 0, sizeof(*client));
+ client->ops = ops;
+ client->data = data;
+
+ down(&fb_clients_lock);
+ list_add(&client->link, &fb_clients);
+ up(&fb_clients_lock);
+
+ return 0;
+}
+
+int unregister_fb_client(struct fb_client_ops *ops)
+{
+ struct fb_client *client = NULL;
+ struct list_head *pos;
+
+ down(&fb_clients_lock);
+ list_for_each(pos, &fb_clients) {
+ client = list_entry(pos, struct fb_client, link);
+ if (client->ops == ops) {
+ list_del(&client->link);
+ kfree(client);
+ break;
+ }
+ }
+ up(&fb_clients_lock);
+
+ return 0;
+}
+
+#define make_fb_client_call(name) \
+int fb_clients_call_##name(struct fb_info *info) \
+{ \
+ struct fb_client *client = NULL; \
+ struct list_head *pos; \
+\
+ down(&fb_clients_lock); \
+ list_for_each(pos, &fb_clients) { \
+ client = list_entry(pos, struct fb_client, link); \
+ if (try_module_get(client->ops->owner)) { \
+ if (client->ops->name) \
+ client->ops->name(client->data, info); \
+ module_put(client->ops->owner); \
+ } \
+ } \
+ up(&fb_clients_lock); \
+ return 0; \
+}
+
+make_fb_client_call(mode_changed)
+make_fb_client_call(suspended)
+make_fb_client_call(resumed)
+
/*
* Visible symbols for modules
*/
@@ -1387,5 +1493,15 @@
EXPORT_SYMBOL(fb_get_buffer_offset);
EXPORT_SYMBOL(move_buf_unaligned);
EXPORT_SYMBOL(move_buf_aligned);
+EXPORT_SYMBOL(fb_set_suspend);
+EXPORT_SYMBOL(register_fb_client);
+EXPORT_SYMBOL(unregister_fb_client);
+EXPORT_SYMBOL(fb_clients_call_mode_changed);
+EXPORT_SYMBOL(fb_clients_call_suspended);
+EXPORT_SYMBOL(fb_clients_call_resumed);
+EXPORT_SYMBOL(fb_dummy_fillrect);
+EXPORT_SYMBOL(fb_dummy_copyarea);
+EXPORT_SYMBOL(fb_dummy_imageblit);
+EXPORT_SYMBOL(fb_dummy_cursor);
MODULE_LICENSE("GPL");
===== drivers/video/console/fbcon.c 1.102 vs edited =====
--- 1.102/drivers/video/console/fbcon.c Tue May 6 09:50:50 2003
+++ edited/drivers/video/console/fbcon.c Wed Jul 30 08:59:44 2003
@@ -2259,6 +2259,19 @@
return 0;
}
+static void fbcon_suspended(void *data, struct fb_info *info)
+{
+ /* Here, we should do something to properly erase the
+ * cursor and synchronize with the cursor interrupt on
+ * SMP... (may not be that critical though...)
+ */
+}
+
+static void fbcon_resumed(void *data, struct fb_info *info)
+{
+ update_screen(fg_console);
+}
+
/*
* The console `switch' structure for the frame buffer based console
*/
@@ -2285,16 +2298,25 @@
.con_resize = fbcon_resize,
};
+static struct fb_client_ops fbcon_client = {
+ .owner = THIS_MODULE,
+ .mode_changed = NULL, /* TODO */
+ .suspended = fbcon_suspended,
+ .resumed = fbcon_resumed,
+};
+
int __init fb_console_init(void)
{
if (!num_registered_fb)
return -ENODEV;
take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default);
+ register_fb_client(&fbcon_client, NULL);
return 0;
}
void __exit fb_console_exit(void)
{
+ unregister_fb_client(&fbcon_client);
give_up_console(&fb_con);
}
===== include/linux/fb.h 1.53 vs edited =====
--- 1.53/include/linux/fb.h Thu Apr 24 06:30:41 2003
+++ edited/include/linux/fb.h Wed Jul 30 09:01:06 2003
@@ -352,6 +352,44 @@
struct fb_info;
struct vm_area_struct;
struct file;
+struct fb_client;
+
+ /*
+ * Framebuffer clients. Currently, this is only used
+ * by fbcon to get notified of events on the framebuffer,
+ * though that should be extended to the userland interface
+ * some way.
+ *
+ * We should also add more callbacks to better deal with
+ * hotplug displays (add/removal notification). This is
+ * not to replaced by a device class, though it could be
+ * wrapped in a device interface according to the driver
+ * model, I have to think more about it.
+ *
+ * Locking rules: The callback should not take the console
+ * semaphore explicitely (call acquire_console_sem()) as it
+ * will typically already be owned.
+ *
+ */
+struct fb_client_ops {
+ struct module *owner;
+
+ /* Userland initiated mode change */
+ void (*mode_changed)(void *data, struct fb_info *info);
+ /* The device is beeing suspended, do not access from
+ * that point
+ */
+ void (*suspended)(void *data, struct fb_info *info);
+ /* The device is back to life, refresh screen
+ */
+ void (*resumed)(void *data, struct fb_info *info);
+};
+
+struct fb_client {
+ struct list_head link;
+ struct fb_client_ops *ops;
+ void *data;
+};
/*
* Frame buffer operations
@@ -399,6 +437,7 @@
int node;
int flags;
int open; /* Has this been open already ? */
+ int suspended; /* Is this currently suspended ? */
#define FBINFO_FLAG_MODULE 1 /* Low-level driver is a module */
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
@@ -412,6 +451,7 @@
struct vc_data *display_fg; /* Console visible on this display */
int currcon; /* Current VC. */
void *pseudo_palette; /* Fake palette of 16 colors */
+
/* From here on everything is device dependent */
void *par;
};
@@ -475,6 +515,10 @@
extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area);
extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image);
+extern int fb_dummy_cursor(struct fb_info *info, struct fb_cursor *cursor);
+extern void fb_dummy_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
+extern void fb_dummy_copyarea(struct fb_info *info, const struct fb_copyarea *area);
+extern void fb_dummy_imageblit(struct fb_info *info, const struct fb_image *image);
/* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info);
@@ -574,6 +618,22 @@
const struct fb_videomode *default_mode,
unsigned int default_bpp);
#endif
+
+/* Power Management: called by low driver to notify other layers,
+ * driver should have acquired the console semaphore prior to
+ * calling this
+ */
+extern int fb_set_suspend(struct fb_info *info, int suspended);
+
+/*
+ * fb_client operations
+ */
+
+extern int register_fb_client(struct fb_client_ops *ops, void *data);
+extern int unregister_fb_client(struct fb_client_ops *ops);
+extern int fb_clients_call_mode_changed(struct fb_info *info);
+extern int fb_clients_call_suspended(struct fb_info *info);
+extern int fb_clients_call_resumed(struct fb_info *info);
#endif /* __KERNEL__ */
-------------------------------------------------------
This SF.Net email sponsored by: Free pre-built ASP.NET sites including
Data Reports, E-commerce, Portals, and Forums are available now.
Download today and enter to win an XBOX or Visual Studio .NET.
http://aspnet.click-url.com/go/psa00100003ave/direct;at.aspnet_072303_01/01
next parent reply other threads:[~2003-07-30 13:15 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1059484419.8537.19.camel@gaston>
[not found] ` <20030729174919.GC2601@openzaurus.ucw.cz>
[not found] ` <1059567270.8545.70.camel@gaston>
2003-07-30 13:14 ` Benjamin Herrenschmidt [this message]
2003-08-01 10:04 ` [PATCH] Framebuffer: 2nd try: client notification mecanism & PM Benjamin Herrenschmidt
2003-08-06 23:52 ` James Simmons
2003-08-07 9:38 ` Benjamin Herrenschmidt
2003-08-07 10:03 ` Pavel Machek
2003-08-07 13:32 ` Benjamin Herrenschmidt
2003-08-07 17:26 ` [Linux-fbdev-devel] " James Simmons
2003-08-07 21:38 ` Nigel Cunningham
2003-08-07 21:51 ` Pavel Machek
2003-08-07 14:37 ` Benjamin Herrenschmidt
2003-08-07 17:28 ` James Simmons
2003-08-07 20:29 ` [Linux-fbdev-devel] " Pavel Machek
2003-08-07 17:23 ` James Simmons
2003-08-07 20:29 ` Pavel Machek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1059570860.2418.2.camel@gaston \
--to=benh@kernel.crashing.org \
--cc=jsimmons@infradead.org \
--cc=linux-fbdev-devel@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
--cc=pavel@ucw.cz \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).