diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-08-01 18:32:07 +0300 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com> | 2017-08-01 18:32:07 +0300 |
commit | 6104c37094e729f3d4ce65797002112735d49cd1 (patch) | |
tree | cc0c38d8d2268109ff38a156c017fe556b207ab5 /drivers/video/console/fbcon.h | |
parent | 52e2fecf6868099359f5dea2f72f8572661d4462 (diff) | |
download | linux-6104c37094e729f3d4ce65797002112735d49cd1.tar.xz |
fbcon: Make fbcon a built-time depency for fbdev
There's a bunch of folks who're trying to make printk less
contended and faster, but there's a problem: printk uses the
console_lock, and the console lock has become the BKL for all things
fbdev/fbcon, which in turn pulled in half the drm subsystem under that
lock. That's awkward.
There reasons for that is probably just a historical accident:
- fbcon is a runtime option of fbdev, i.e. at runtime you can pick
whether your fbdev driver instances are used as kernel consoles.
Unfortunately this wasn't implemented with some module option, but
through some module loading magic: As long as you don't load
fbcon.ko, there's no fbdev console support, but loading it (in any
order wrt fbdev drivers) will create console instances for all fbdev
drivers.
- This was implemented through a notifier chain. fbcon.ko enumerates
all fbdev instances at load time and also registers itself as
listener in the fbdev notifier. The fbdev core tries to register new
fbdev instances with fbcon using the notifier.
- On top of that the modifier chain is also used at runtime by the
fbdev subsystem to e.g. control backlights for panels.
- The problem is that the notifier puts a mutex locking context
between fbdev and fbcon, which mixes up the locking contexts for
both the runtime usage and the register time usage to notify fbcon.
And at runtime fbcon (through the fbdev core) might call into the
notifier from a printk critical section while console_lock is held.
- This means console_lock must be an outer lock for the entire fbdev
subsystem, which also means it must be acquired when registering a
new framebuffer driver as the outermost lock since we might call
into fbcon (through the notifier) which would result in a locking
inversion if fbcon would acquire the console_lock from its notifier
callback (which it needs to register the console).
- console_lock can be held anywhere, since printk can be called
anywhere, and through the above story, plus drm/kms being an fbdev
driver, we pull in a shocking amount of locking hiercharchy
underneath the console_lock. Which makes cleaning up printk really
hard (not even splitting console_lock into an rwsem is all that
useful due to this).
There's various ways to address this, but the cleanest would be to
make fbcon a compile-time option, where fbdev directly calls the fbcon
register functions from register_framebuffer, or dummy static inline
versions if fbcon is disabled. Maybe augmented with a runtime knob to
disable fbcon, if that's needed (for debugging perhaps).
But this could break some users who rely on the magic "loading
fbcon.ko enables/disables fbdev framebuffers at runtime" thing, even
if that's unlikely. Hence we must be careful:
1. Create a compile-time dependency between fbcon and fbdev in the
least minimal way. This is what this patch does.
2. Wait at least 1 year to give possible users time to scream about
how we broke their setup. Unlikely, since all distros make fbcon
compile-in, and embedded platforms only compile stuff they know they
need anyway. But still.
3. Convert the notifier to direct functions calls, with dummy static
inlines if fbcon is disabled. We'll still need the fb notifier for the
other uses (like backlights), but we can probably move it into the fb
core (atm it must be built-into vmlinux).
4. Push console_lock down the call-chain, until it is down in
console_register again.
5. Finally start to clean up and rework the printk/console locking.
For context of this saga see
commit 50e244cc793d511b86adea24972f3a7264cae114
Author: Alan Cox <alan@linux.intel.com>
Date: Fri Jan 25 10:28:15 2013 +1000
fb: rework locking to fix lock ordering on takeover
plus the pile of commits on top that tried to make this all work
without terminally upsetting lockdep. We've uncovered all this when
console_lock lockdep annotations where added in
commit daee779718a319ff9f83e1ba3339334ac650bb22
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date: Sat Sep 22 19:52:11 2012 +0200
console: implement lockdep support for console_lock
On the patch itself:
- Switch CONFIG_FRAMEBUFFER_CONSOLE to be a boolean, using the overall
CONFIG_FB tristate to decided whether it should be a module or
built-in.
- At first I thought I could force the build depency with just a dummy
symbol that fbcon.ko exports and fb.ko uses. But that leads to a
module depency cycle (it works fine when built-in).
Since this tight binding is the entire goal the simplest solution is
to move all the fbcon modules (and there's a bunch of optinal
source-files which are each modules of their own, for no good
reason) into the overall fb.ko core module. That's a bit more than
what I would have liked to do in this patch, but oh well.
Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Reviewed-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Diffstat (limited to 'drivers/video/console/fbcon.h')
-rw-r--r-- | drivers/video/console/fbcon.h | 265 |
1 files changed, 0 insertions, 265 deletions
diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h deleted file mode 100644 index 7aaa4eabbba0..000000000000 --- a/drivers/video/console/fbcon.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * linux/drivers/video/console/fbcon.h -- Low level frame buffer based console driver - * - * Copyright (C) 1997 Geert Uytterhoeven - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#ifndef _VIDEO_FBCON_H -#define _VIDEO_FBCON_H - -#include <linux/types.h> -#include <linux/vt_buffer.h> -#include <linux/vt_kern.h> - -#include <asm/io.h> - -#define FBCON_FLAGS_INIT 1 -#define FBCON_FLAGS_CURSOR_TIMER 2 - - /* - * This is the interface between the low-level console driver and the - * low-level frame buffer device - */ - -struct display { - /* Filled in by the low-level console driver */ - const u_char *fontdata; - int userfont; /* != 0 if fontdata kmalloc()ed */ - u_short scrollmode; /* Scroll Method */ - u_short inverse; /* != 0 text black on white as default */ - short yscroll; /* Hardware scrolling */ - int vrows; /* number of virtual rows */ - int cursor_shape; - int con_rotate; - u32 xres_virtual; - u32 yres_virtual; - u32 height; - u32 width; - u32 bits_per_pixel; - u32 grayscale; - u32 nonstd; - u32 accel_flags; - u32 rotate; - struct fb_bitfield red; - struct fb_bitfield green; - struct fb_bitfield blue; - struct fb_bitfield transp; - const struct fb_videomode *mode; -}; - -struct fbcon_ops { - void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int dy, int dx, int height, int width); - void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, - int sx, int height, int width); - void (*putcs)(struct vc_data *vc, struct fb_info *info, - const unsigned short *s, int count, int yy, int xx, - int fg, int bg); - void (*clear_margins)(struct vc_data *vc, struct fb_info *info, - int bottom_only); - void (*cursor)(struct vc_data *vc, struct fb_info *info, int mode, - int softback_lines, int fg, int bg); - int (*update_start)(struct fb_info *info); - int (*rotate_font)(struct fb_info *info, struct vc_data *vc); - struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ - struct timer_list cursor_timer; /* Cursor timer */ - struct fb_cursor cursor_state; - struct display *p; - int currcon; /* Current VC. */ - int cur_blink_jiffies; - int cursor_flash; - int cursor_reset; - int blank_state; - int graphics; - int save_graphics; /* for debug enter/leave */ - int flags; - int rotate; - int cur_rotate; - char *cursor_data; - u8 *fontbuffer; - u8 *fontdata; - u8 *cursor_src; - u32 cursor_size; - u32 fd_size; -}; - /* - * Attribute Decoding - */ - -/* Color */ -#define attr_fgcol(fgshift,s) \ - (((s) >> (fgshift)) & 0x0f) -#define attr_bgcol(bgshift,s) \ - (((s) >> (bgshift)) & 0x0f) - -/* Monochrome */ -#define attr_bold(s) \ - ((s) & 0x200) -#define attr_reverse(s) \ - ((s) & 0x800) -#define attr_underline(s) \ - ((s) & 0x400) -#define attr_blink(s) \ - ((s) & 0x8000) - - -static inline int mono_col(const struct fb_info *info) -{ - __u32 max_len; - max_len = max(info->var.green.length, info->var.red.length); - max_len = max(info->var.blue.length, max_len); - return (~(0xfff << max_len)) & 0xff; -} - -static inline int attr_col_ec(int shift, struct vc_data *vc, - struct fb_info *info, int is_fg) -{ - int is_mono01; - int col; - int fg; - int bg; - - if (!vc) - return 0; - - if (vc->vc_can_do_color) - return is_fg ? attr_fgcol(shift,vc->vc_video_erase_char) - : attr_bgcol(shift,vc->vc_video_erase_char); - - if (!info) - return 0; - - col = mono_col(info); - is_mono01 = info->fix.visual == FB_VISUAL_MONO01; - - if (attr_reverse(vc->vc_video_erase_char)) { - fg = is_mono01 ? col : 0; - bg = is_mono01 ? 0 : col; - } - else { - fg = is_mono01 ? 0 : col; - bg = is_mono01 ? col : 0; - } - - return is_fg ? fg : bg; -} - -#define attr_bgcol_ec(bgshift, vc, info) attr_col_ec(bgshift, vc, info, 0) -#define attr_fgcol_ec(fgshift, vc, info) attr_col_ec(fgshift, vc, info, 1) - -/* Font */ -#define REFCOUNT(fd) (((int *)(fd))[-1]) -#define FNTSIZE(fd) (((int *)(fd))[-2]) -#define FNTCHARCNT(fd) (((int *)(fd))[-3]) -#define FNTSUM(fd) (((int *)(fd))[-4]) -#define FONT_EXTRA_WORDS 4 - - /* - * Scroll Method - */ - -/* There are several methods fbcon can use to move text around the screen: - * - * Operation Pan Wrap - *--------------------------------------------- - * SCROLL_MOVE copyarea No No - * SCROLL_PAN_MOVE copyarea Yes No - * SCROLL_WRAP_MOVE copyarea No Yes - * SCROLL_REDRAW imageblit No No - * SCROLL_PAN_REDRAW imageblit Yes No - * SCROLL_WRAP_REDRAW imageblit No Yes - * - * (SCROLL_WRAP_REDRAW is not implemented yet) - * - * In general, fbcon will choose the best scrolling - * method based on the rule below: - * - * Pan/Wrap > accel imageblit > accel copyarea > - * soft imageblit > (soft copyarea) - * - * Exception to the rule: Pan + accel copyarea is - * preferred over Pan + accel imageblit. - * - * The above is typical for PCI/AGP cards. Unless - * overridden, fbcon will never use soft copyarea. - * - * If you need to override the above rule, set the - * appropriate flags in fb_info->flags. For example, - * to prefer copyarea over imageblit, set - * FBINFO_READS_FAST. - * - * Other notes: - * + use the hardware engine to move the text - * (hw-accelerated copyarea() and fillrect()) - * + use hardware-supported panning on a large virtual screen - * + amifb can not only pan, but also wrap the display by N lines - * (i.e. visible line i = physical line (i+N) % yres). - * + read what's already rendered on the screen and - * write it in a different place (this is cfb_copyarea()) - * + re-render the text to the screen - * - * Whether to use wrapping or panning can only be figured out at - * runtime (when we know whether our font height is a multiple - * of the pan/wrap step) - * - */ - -#define SCROLL_MOVE 0x001 -#define SCROLL_PAN_MOVE 0x002 -#define SCROLL_WRAP_MOVE 0x003 -#define SCROLL_REDRAW 0x004 -#define SCROLL_PAN_REDRAW 0x005 - -#ifdef CONFIG_FB_TILEBLITTING -extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); -#endif -extern void fbcon_set_bitops(struct fbcon_ops *ops); -extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); - -#define FBCON_ATTRIBUTE_UNDERLINE 1 -#define FBCON_ATTRIBUTE_REVERSE 2 -#define FBCON_ATTRIBUTE_BOLD 4 - -static inline int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - -static inline int get_attribute(struct fb_info *info, u16 c) -{ - int attribute = 0; - - if (fb_get_color_depth(&info->var, &info->fix) == 1) { - if (attr_underline(c)) - attribute |= FBCON_ATTRIBUTE_UNDERLINE; - if (attr_reverse(c)) - attribute |= FBCON_ATTRIBUTE_REVERSE; - if (attr_bold(c)) - attribute |= FBCON_ATTRIBUTE_BOLD; - } - - return attribute; -} - -#define FBCON_SWAP(i,r,v) ({ \ - typeof(r) _r = (r); \ - typeof(v) _v = (v); \ - (void) (&_r == &_v); \ - (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) - -#ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION -extern void fbcon_set_rotate(struct fbcon_ops *ops); -#else -#define fbcon_set_rotate(x) do {} while(0) -#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ - -#endif /* _VIDEO_FBCON_H */ - |