[PATCH 33/45] tty: vt: make types around consw::con_blank() bool
Both the mode_switch parameter and the return value (a redraw needed) are true/false. So switch them to bool, so that users won't return -Eerrors or anything else. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/video/console/dummycon.c| 12 ++-- drivers/video/console/mdacon.c | 8 drivers/video/console/newport_con.c | 7 --- drivers/video/console/sticon.c | 9 + drivers/video/console/vgacon.c | 4 ++-- drivers/video/fbdev/core/fbcon.c| 6 +++--- include/linux/console.h | 7 +-- 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index d86c1d798690..139049368fdc 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -79,21 +79,21 @@ static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); } -static int dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, - int mode_switch) +static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, + bool mode_switch) { /* Redraw, so that we get putc(s) for output done while blanked */ - return 1; + return true; } #else static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, unsigned int x) { } static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, unsigned int ypos, unsigned int xpos) { } -static int dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, - int mode_switch) +static bool dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, + bool mode_switch) { - return 0; + return false; } #endif diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 63e3ce678aab..c0e1f4554a44 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -451,8 +451,8 @@ static bool mdacon_switch(struct vc_data *c) return true;/* redrawing needed */ } -static int mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank, - int mode_switch) +static bool mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank, +bool mode_switch) { if (mda_type == TYPE_MDA) { if (blank) @@ -460,14 +460,14 @@ static int mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank, mda_convert_attr(c->vc_video_erase_char), c->vc_screenbuf_size); /* Tell console.c that it has to restore the screen itself */ - return 1; + return true; } else { if (blank) outb_p(0x00, mda_mode_port);/* disable video */ else outb_p(MDA_MODE_VIDEO_EN | MDA_MODE_BLINK_EN, mda_mode_port); - return 0; + return false; } } diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 38437a53b7f1..dbb31bf87bf1 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -476,8 +476,8 @@ static bool newport_switch(struct vc_data *vc) return true; } -static int newport_blank(struct vc_data *c, enum vesa_blank_mode blank, -int mode_switch) +static bool newport_blank(struct vc_data *c, enum vesa_blank_mode blank, + bool mode_switch) { unsigned short treg; @@ -492,7 +492,8 @@ static int newport_blank(struct vc_data *c, enum vesa_blank_mode blank, newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_EDISP))); } - return 1; + + return true; } static int newport_set_font(int unit, struct console_font *op, unsigned int vpitch) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index e9d5d1f92883..cbb9ef438214 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -298,19 +298,20 @@ static bool sticon_switch(struct vc_data *conp) return true; /* needs refreshing */ } -static int sticon_blank(struct vc_data *c, enum vesa_blank_mode blank, - int mode_switch) +static bool sticon_blank(struct vc_data *c, enum vesa_blank_mode blank, +bool mode_switch) { if (blank == VESA_NO_BLANKING) { if (mode_switch) vga_is_gfx = 0; - return 1; + return true; }
[PATCH 32/45] tty: vt: use enum for VESA blanking modes
Switch VESA macros to an enum and add and use VESA_BLANK_MAX. This improves type checking in consw::con_blank(). There is a downside of this. The macros were defined twice: in linux/console.h and uapi/linux/fb.h. We cannot remove the latter (uapi header), but nor we want to expand them in the kernel too. So protect them using __KERNEL__. In the kernel case, include linux/console.h instead. This header dependency is preexisting. Alternatively, we could create a vesa.h header with that sole enum and include it. If it turns out linux/console.h is too much for fb.h. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/tty/vt/vt.c | 4 ++-- drivers/video/console/dummycon.c| 6 -- drivers/video/console/mdacon.c | 3 ++- drivers/video/console/newport_con.c | 3 ++- drivers/video/console/sticon.c | 3 ++- drivers/video/console/vgacon.c | 7 --- drivers/video/fbdev/core/fbcon.c| 3 ++- include/linux/console.h | 18 +++--- include/uapi/linux/fb.h | 5 - 9 files changed, 33 insertions(+), 19 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 6f46fefedcfb..756291f37d47 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -175,7 +175,7 @@ int do_poke_blanked_console; int console_blanked; EXPORT_SYMBOL(console_blanked); -static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */ +static enum vesa_blank_mode vesa_blank_mode; static int vesa_off_interval; static int blankinterval; core_param(consoleblank, blankinterval, int, 0444); @@ -4334,7 +4334,7 @@ static int set_vesa_blanking(u8 __user *mode_user) return -EFAULT; console_lock(); - vesa_blank_mode = (mode < 4) ? mode : VESA_NO_BLANKING; + vesa_blank_mode = (mode <= VESA_BLANK_MAX) ? mode : VESA_NO_BLANKING; console_unlock(); return 0; diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index c8d5aa0e3ed0..d86c1d798690 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -79,7 +79,8 @@ static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, raw_notifier_call_chain(&dummycon_output_nh, 0, NULL); } -static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) +static int dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, + int mode_switch) { /* Redraw, so that we get putc(s) for output done while blanked */ return 1; @@ -89,7 +90,8 @@ static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, unsigned int x) { } static void dummycon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, unsigned int ypos, unsigned int xpos) { } -static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) +static int dummycon_blank(struct vc_data *vc, enum vesa_blank_mode blank, + int mode_switch) { return 0; } diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 4485ef923bb3..63e3ce678aab 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -451,7 +451,8 @@ static bool mdacon_switch(struct vc_data *c) return true;/* redrawing needed */ } -static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) +static int mdacon_blank(struct vc_data *c, enum vesa_blank_mode blank, + int mode_switch) { if (mda_type == TYPE_MDA) { if (blank) diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index ad3a09142770..38437a53b7f1 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -476,7 +476,8 @@ static bool newport_switch(struct vc_data *vc) return true; } -static int newport_blank(struct vc_data *c, int blank, int mode_switch) +static int newport_blank(struct vc_data *c, enum vesa_blank_mode blank, +int mode_switch) { unsigned short treg; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 817b89c45e81..e9d5d1f92883 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -298,7 +298,8 @@ static bool sticon_switch(struct vc_data *conp) return true; /* needs refreshing */ } -static int sticon_blank(struct vc_data *c, int blank, int mode_switch) +static int sticon_blank(struct vc_data *c, enum vesa_blank_mode blank, + int mode_switch) { if (blank == VESA_NO_BLANKING) { if (mode_switch) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 910dc73874b7..a4bd97ab502d 100644 -
[PATCH 31/45] tty: vt: use VESA blanking constants
There are VESA blanking constants defined in console.h already. So use them in the console code instead of constant values. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/tty/vt/vt.c | 9 + drivers/video/console/newport_con.c | 2 +- drivers/video/console/sticon.c | 2 +- drivers/video/console/vgacon.c | 6 +++--- 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 279f802aa222..6f46fefedcfb 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4334,7 +4334,7 @@ static int set_vesa_blanking(u8 __user *mode_user) return -EFAULT; console_lock(); - vesa_blank_mode = (mode < 4) ? mode : 0; + vesa_blank_mode = (mode < 4) ? mode : VESA_NO_BLANKING; console_unlock(); return 0; @@ -4361,7 +4361,7 @@ void do_blank_screen(int entering_gfx) if (entering_gfx) { hide_cursor(vc); save_screen(vc); - vc->vc_sw->con_blank(vc, 1, 1); + vc->vc_sw->con_blank(vc, VESA_VSYNC_SUSPEND, 1); console_blanked = fg_console + 1; blank_state = blank_off; set_origin(vc); @@ -4382,7 +4382,8 @@ void do_blank_screen(int entering_gfx) save_screen(vc); /* In case we need to reset origin, blanking hook returns 1 */ - i = vc->vc_sw->con_blank(vc, vesa_off_interval ? 1 : (vesa_blank_mode + 1), 0); + i = vc->vc_sw->con_blank(vc, vesa_off_interval ? VESA_VSYNC_SUSPEND : +(vesa_blank_mode + 1), 0); console_blanked = fg_console + 1; if (i) set_origin(vc); @@ -4433,7 +4434,7 @@ void do_unblank_screen(int leaving_gfx) } console_blanked = 0; - if (vc->vc_sw->con_blank(vc, 0, leaving_gfx)) + if (vc->vc_sw->con_blank(vc, VESA_NO_BLANKING, leaving_gfx)) /* Low-level driver cannot restore -> do it ourselves */ update_screen(vc); if (console_blank_hook) diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 039d1c9937d2..ad3a09142770 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -480,7 +480,7 @@ static int newport_blank(struct vc_data *c, int blank, int mode_switch) { unsigned short treg; - if (blank == 0) { + if (blank == VESA_NO_BLANKING) { /* unblank console */ treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); newport_vc2_set(npregs, VC2_IREG_CONTROL, diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index f3bb48a0e980..817b89c45e81 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -300,7 +300,7 @@ static bool sticon_switch(struct vc_data *conp) static int sticon_blank(struct vc_data *c, int blank, int mode_switch) { -if (blank == 0) { +if (blank == VESA_NO_BLANKING) { if (mode_switch) vga_is_gfx = 0; return 1; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 5025ab501f02..910dc73874b7 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -800,10 +800,10 @@ static void vga_pal_blank(struct vgastate *state) static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) { switch (blank) { - case 0: /* Unblank */ + case VESA_NO_BLANKING: /* Unblank */ if (vga_vesa_blanked) { vga_vesa_unblank(&vgastate); - vga_vesa_blanked = 0; + vga_vesa_blanked = VESA_NO_BLANKING; } if (vga_palette_blanked) { vga_set_palette(c, color_table); @@ -813,7 +813,7 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) vga_is_gfx = false; /* Tell console.c that it has to restore the screen itself */ return 1; - case 1: /* Normal blanking */ + case VESA_VSYNC_SUSPEND:/* Normal blanking */ if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { vga_pal_blank(&vgastate); vga_palette_blanked = true; -- 2.43.0
[PATCH 30/45] tty: vt: stop using -1 for blank mode in consw::con_blank()
-1 is the same as VESA_VSYNC_SUSPEND in all con_blank() implementations. So we can remove this special case from vgacon now too. Despite con_blank() of fbcon looks complicated, the "if (!fbcon_is_inactive(vc, info))" branch is not taken as we set "ops->graphics = 1;" few lines above. So what matters there (as in all other blank implementations except vgacon) is if 'blank' is zero or not. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/tty/vt/vt.c| 2 +- drivers/video/console/vgacon.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 88d7b48871fb..279f802aa222 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4361,7 +4361,7 @@ void do_blank_screen(int entering_gfx) if (entering_gfx) { hide_cursor(vc); save_screen(vc); - vc->vc_sw->con_blank(vc, -1, 1); + vc->vc_sw->con_blank(vc, 1, 1); console_blanked = fg_console + 1; blank_state = blank_off; set_origin(vc); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index e303098aabab..5025ab501f02 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -814,7 +814,6 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) /* Tell console.c that it has to restore the screen itself */ return 1; case 1: /* Normal blanking */ - case -1:/* Obsolete */ if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { vga_pal_blank(&vgastate); vga_palette_blanked = true; -- 2.43.0
[PATCH 40/45] fbcon: remove fbcon_getxy()
Again, fbcon_getxy() is the same as the default implementation since the softscroll removal in commit 50145474f6ef (fbcon: remove soft scrollback code). Drop that. Signed-off-by: Jiri Slaby (SUSE) Cc: Daniel Vetter Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/fbdev/core/fbcon.c | 25 - 1 file changed, 25 deletions(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 2166ea1a5430..9c2962900d13 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2593,30 +2593,6 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table) fb_set_cmap(&palette_cmap, info); } -static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos, -int *px, int *py) -{ - unsigned long ret; - int x, y; - - if (pos >= vc->vc_origin && pos < vc->vc_scr_end) { - unsigned long offset = (pos - vc->vc_origin) / 2; - - x = offset % vc->vc_cols; - y = offset / vc->vc_cols; - ret = pos + (vc->vc_cols - x) * 2; - } else { - /* Should not happen */ - x = y = 0; - ret = vc->vc_origin; - } - if (px) - *px = x; - if (py) - *py = y; - return ret; -} - /* As we might be inside of softback, we may work with non-contiguous buffer, that's why we have to use a separate routine. */ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) @@ -3157,7 +3133,6 @@ static const struct consw fb_con = { .con_font_default = fbcon_set_def_font, .con_set_palette= fbcon_set_palette, .con_invert_region = fbcon_invert_region, - .con_getxy = fbcon_getxy, .con_resize = fbcon_resize, .con_debug_enter= fbcon_debug_enter, .con_debug_leave= fbcon_debug_leave, -- 2.43.0
[PATCH 27/45] fbdev/core: simplify cursor_state setting in fbcon_ops::cursor()
There is a switch decicing if cursor should be drawn or not. The whole switch can be simplified to one line. Do this cleanup as a preparatory work for the next patch. There, all the CM_* constants are removed. Signed-off-by: Jiri Slaby (SUSE) Cc: Daniel Vetter Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/fbdev/core/bitblit.c | 11 +-- drivers/video/fbdev/core/fbcon_ccw.c | 11 +-- drivers/video/fbdev/core/fbcon_cw.c | 11 +-- drivers/video/fbdev/core/fbcon_ud.c | 11 +-- 4 files changed, 4 insertions(+), 40 deletions(-) diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index 8587c9da0670..daff152f4c22 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -348,16 +348,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, mask[i++] = msk; } - switch (mode) { - case CM_ERASE: - ops->cursor_state.enable = 0; - break; - case CM_DRAW: - case CM_MOVE: - default: - ops->cursor_state.enable = (use_sw) ? 0 : 1; - break; - } + ops->cursor_state.enable = (mode != CM_ERASE) && !use_sw; cursor.image.data = src; cursor.image.fg_color = ops->cursor_state.image.fg_color; diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index 2789ace79634..889423d580bc 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -349,16 +349,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, kfree(tmp); } - switch (mode) { - case CM_ERASE: - ops->cursor_state.enable = 0; - break; - case CM_DRAW: - case CM_MOVE: - default: - ops->cursor_state.enable = (use_sw) ? 0 : 1; - break; - } + ops->cursor_state.enable = (mode != CM_ERASE) && !use_sw; cursor.image.data = src; cursor.image.fg_color = ops->cursor_state.image.fg_color; diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index 86a254c1b2b7..a306ca5802e8 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -332,16 +332,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, kfree(tmp); } - switch (mode) { - case CM_ERASE: - ops->cursor_state.enable = 0; - break; - case CM_DRAW: - case CM_MOVE: - default: - ops->cursor_state.enable = (use_sw) ? 0 : 1; - break; - } + ops->cursor_state.enable = (mode != CM_ERASE) && !use_sw; cursor.image.data = src; cursor.image.fg_color = ops->cursor_state.image.fg_color; diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 23bc045769d0..f6fc458b46c7 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -372,16 +372,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, mask[i++] = ~msk; } - switch (mode) { - case CM_ERASE: - ops->cursor_state.enable = 0; - break; - case CM_DRAW: - case CM_MOVE: - default: - ops->cursor_state.enable = (use_sw) ? 0 : 1; - break; - } + ops->cursor_state.enable = (mode != CM_ERASE) && !use_sw; cursor.image.data = src; cursor.image.fg_color = ops->cursor_state.image.fg_color; -- 2.43.0
[PATCH 37/45] fbcon: remove consw::con_screen_pos()
fbcon_screen_pos() performs the same as the default implementation. The only difference in the default implementation is that is considers both vc->vc_origin and vc->vc_visible_origin. But given fbcon's softscroll code was already removed in commit 50145474f6ef (fbcon: remove soft scrollback code), both are always the same. So remove fbcon_screen_pos() too. Signed-off-by: Jiri Slaby (SUSE) Cc: Daniel Vetter Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/fbdev/core/fbcon.c | 6 -- 1 file changed, 6 deletions(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 657160eec0a5..2166ea1a5430 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2593,11 +2593,6 @@ static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table) fb_set_cmap(&palette_cmap, info); } -static u16 *fbcon_screen_pos(const struct vc_data *vc, int offset) -{ - return (u16 *) (vc->vc_origin + offset); -} - static unsigned long fbcon_getxy(struct vc_data *vc, unsigned long pos, int *px, int *py) { @@ -3162,7 +3157,6 @@ static const struct consw fb_con = { .con_font_default = fbcon_set_def_font, .con_set_palette= fbcon_set_palette, .con_invert_region = fbcon_invert_region, - .con_screen_pos = fbcon_screen_pos, .con_getxy = fbcon_getxy, .con_resize = fbcon_resize, .con_debug_enter= fbcon_debug_enter, -- 2.43.0
[PATCH 36/45] tty: vt: change consw::con_set_origin() return type
The return value of consw::con_set_origin() is only true/false, meaining if vc->vc_origin is set to vc->vc_screenbuf or not. So switch the type and returned values accordingly. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/console/vgacon.c | 8 include/linux/console.h| 5 - 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index ea086b39c6f5..4a40da81990d 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -65,7 +65,7 @@ static struct vgastate vgastate; * Interface used by the world */ -static int vgacon_set_origin(struct vc_data *c); +static bool vgacon_set_origin(struct vc_data *c); static struct uni_pagedict *vgacon_uni_pagedir; static int vgacon_refcount; @@ -1100,15 +1100,15 @@ static int vgacon_resize(struct vc_data *c, unsigned int width, return 0; } -static int vgacon_set_origin(struct vc_data *c) +static bool vgacon_set_origin(struct vc_data *c) { if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ - return 0; + return false; c->vc_origin = c->vc_visible_origin = vga_vram_base; vga_set_mem_top(c); vga_rolled_over = 0; - return 1; + return true; } static void vgacon_save_screen(struct vc_data *c) diff --git a/include/linux/console.h b/include/linux/console.h index 543de22a3f23..c07e1ce6bd14 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -63,6 +63,9 @@ enum vc_intensity; * @con_set_palette: sets the palette of the console to @table (optional) * @con_scrolldelta: the contents of the console should be scrolled by @lines. * Invoked by user. (optional) + * @con_set_origin: set origin (see &vc_data::vc_origin) of the @vc. If not + * provided or returns false, the origin is set to + * @vc->vc_screenbuf. (optional) */ struct consw { struct module *owner; @@ -95,7 +98,7 @@ struct consw { void(*con_set_palette)(struct vc_data *vc, const unsigned char *table); void(*con_scrolldelta)(struct vc_data *vc, int lines); - int (*con_set_origin)(struct vc_data *vc); + bool(*con_set_origin)(struct vc_data *vc); void(*con_save_screen)(struct vc_data *vc); u8 (*con_build_attr)(struct vc_data *vc, u8 color, enum vc_intensity intensity, -- 2.43.0
[PATCH 24/45] tty: vt: sanitize consw::con_putc() parameters
Make parameters of consw::con_putc() saner: * x and y are unsigned now, as they cannot be negative, and * ca is made u16, as it is composed of two 8bit values (character and attribute). See the con_putcs() hook, u16/ushort is worked on there. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/console/dummycon.c| 6 -- drivers/video/console/newport_con.c | 4 ++-- include/linux/console.h | 5 - 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index 0a69d5c216ee..1874beed0325 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -50,7 +50,8 @@ void dummycon_unregister_output_notifier(struct notifier_block *nb) raw_notifier_chain_unregister(&dummycon_output_nh, nb); } -static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) +static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, + unsigned int x) { WARN_CONSOLE_UNLOCKED(); @@ -84,7 +85,8 @@ static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) return 1; } #else -static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } +static void dummycon_putc(struct vc_data *vc, u16 c, unsigned int y, + unsigned int x) { } static void dummycon_putcs(struct vc_data *vc, const unsigned short *s, int count, int ypos, int xpos) { } static int dummycon_blank(struct vc_data *vc, int blank, int mode_switch) diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 55c6106b3507..9b5c0118873e 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -367,8 +367,8 @@ static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, } } -static void newport_putc(struct vc_data *vc, int charattr, int ypos, -int xpos) +static void newport_putc(struct vc_data *vc, u16 charattr, unsigned int ypos, +unsigned int xpos) { unsigned char *p; diff --git a/include/linux/console.h b/include/linux/console.h index 8fd96a5fca5f..92d57e5b3009 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -39,6 +39,8 @@ enum vc_intensity; * @con_init: initialize the console on @vc. @init is true for the very first * call on this @vc. * @con_clear: erase @count characters at [@x, @y] on @vc. @count >= 1. + * @con_putc: emit one character with attributes @ca to [@x, @y] on @vc. + * (optional -- @con_putcs would be called instead) * @con_scroll: move lines from @top to @bottom in direction @dir by @lines. * Return true if no generic handling should be done. * Invoked by csi_M and printing to the console. @@ -53,7 +55,8 @@ struct consw { void(*con_deinit)(struct vc_data *vc); void(*con_clear)(struct vc_data *vc, unsigned int y, unsigned int x, unsigned int count); - void(*con_putc)(struct vc_data *vc, int c, int ypos, int xpos); + void(*con_putc)(struct vc_data *vc, u16 ca, unsigned int y, + unsigned int x); void(*con_putcs)(struct vc_data *vc, const unsigned short *s, int count, int ypos, int xpos); void(*con_cursor)(struct vc_data *vc, int mode); -- 2.43.0
[PATCH 35/45] tty: vt: make consw::con_font_default()'s name const
It's a name after all and that is not supposed to be changed. So make it const to make this obvious. Signed-off-by: Jiri Slaby (SUSE) Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/video/console/newport_con.c | 3 ++- drivers/video/console/sticon.c | 3 ++- drivers/video/fbdev/core/fbcon.c| 3 ++- include/linux/console.h | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 4203bd5fd0a1..a51cfc1d560e 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -564,7 +564,8 @@ static int newport_set_def_font(int unit, struct console_font *op) return 0; } -static int newport_font_default(struct vc_data *vc, struct console_font *op, char *name) +static int newport_font_default(struct vc_data *vc, struct console_font *op, + const char *name) { return newport_set_def_font(vc->vc_num, op); } diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 710201fb8ce4..4c7b4959a1aa 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -246,7 +246,8 @@ static int sticon_set_font(struct vc_data *vc, const struct console_font *op, return 0; } -static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name) +static int sticon_font_default(struct vc_data *vc, struct console_font *op, + const char *name) { sticon_set_def_font(vc->vc_num); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 62474630c4d4..657160eec0a5 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2533,7 +2533,8 @@ static int fbcon_set_font(struct vc_data *vc, const struct console_font *font, return fbcon_do_set_font(vc, font->width, font->height, charcount, new_data, 1); } -static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, char *name) +static int fbcon_set_def_font(struct vc_data *vc, struct console_font *font, + const char *name) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); const struct font_desc *f; diff --git a/include/linux/console.h b/include/linux/console.h index a500caadbad0..543de22a3f23 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -89,7 +89,7 @@ struct consw { int (*con_font_get)(struct vc_data *vc, struct console_font *font, unsigned int vpitch); int (*con_font_default)(struct vc_data *vc, - struct console_font *font, char *name); + struct console_font *font, const char *name); int (*con_resize)(struct vc_data *vc, unsigned int width, unsigned int height, bool from_user); void(*con_set_palette)(struct vc_data *vc, -- 2.43.0
[PATCH 18/45] tty: vt: make consw::con_debug_*() return void
The return value of con_debug_enter() and con_debug_leave() is ignored on many fronts. So just don't propagate errors (the current implementations return 0 anyway) and make the return type a void. Signed-off-by: Jiri Slaby (SUSE) Cc: Daniel Vetter Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/tty/vt/vt.c | 21 - drivers/video/fbdev/core/fbcon.c | 6 ++ include/linux/console.h | 18 ++ 3 files changed, 12 insertions(+), 33 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 7006889c920d..a953c3f262a5 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4026,15 +4026,9 @@ EXPORT_SYMBOL(con_is_visible); * Called when the console is taken over by the kernel debugger, this * function needs to save the current console state, then put the console * into a state suitable for the kernel debugger. - * - * RETURNS: - * Zero on success, nonzero if a failure occurred when trying to prepare - * the console for the debugger. */ -int con_debug_enter(struct vc_data *vc) +void con_debug_enter(struct vc_data *vc) { - int ret = 0; - saved_fg_console = fg_console; saved_last_console = last_console; saved_want_console = want_console; @@ -4043,7 +4037,7 @@ int con_debug_enter(struct vc_data *vc) vc->vc_mode = KD_TEXT; console_blanked = 0; if (vc->vc_sw->con_debug_enter) - ret = vc->vc_sw->con_debug_enter(vc); + vc->vc_sw->con_debug_enter(vc); #ifdef CONFIG_KGDB_KDB /* Set the initial LINES variable if it is not already set */ if (vc->vc_rows < 999) { @@ -4073,7 +4067,6 @@ int con_debug_enter(struct vc_data *vc) } } #endif /* CONFIG_KGDB_KDB */ - return ret; } EXPORT_SYMBOL_GPL(con_debug_enter); @@ -4082,15 +4075,10 @@ EXPORT_SYMBOL_GPL(con_debug_enter); * * Restore the console state to what it was before the kernel debugger * was invoked. - * - * RETURNS: - * Zero on success, nonzero if a failure occurred when trying to restore - * the console. */ -int con_debug_leave(void) +void con_debug_leave(void) { struct vc_data *vc; - int ret = 0; fg_console = saved_fg_console; last_console = saved_last_console; @@ -4100,8 +4088,7 @@ int con_debug_leave(void) vc = vc_cons[fg_console].d; if (vc->vc_sw->con_debug_leave) - ret = vc->vc_sw->con_debug_leave(vc); - return ret; + vc->vc_sw->con_debug_leave(vc); } EXPORT_SYMBOL_GPL(con_debug_leave); diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index dd2f4617485c..d3fb98084eda 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2243,7 +2243,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) return 0; } -static int fbcon_debug_enter(struct vc_data *vc) +static void fbcon_debug_enter(struct vc_data *vc) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); struct fbcon_ops *ops = info->fbcon_par; @@ -2253,10 +2253,9 @@ static int fbcon_debug_enter(struct vc_data *vc) if (info->fbops->fb_debug_enter) info->fbops->fb_debug_enter(info); fbcon_set_palette(vc, color_table); - return 0; } -static int fbcon_debug_leave(struct vc_data *vc) +static void fbcon_debug_leave(struct vc_data *vc) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); struct fbcon_ops *ops = info->fbcon_par; @@ -2264,7 +2263,6 @@ static int fbcon_debug_leave(struct vc_data *vc) ops->graphics = ops->save_graphics; if (info->fbops->fb_debug_leave) info->fbops->fb_debug_leave(info); - return 0; } static int fbcon_get_font(struct vc_data *vc, struct console_font *font, unsigned int vpitch) diff --git a/include/linux/console.h b/include/linux/console.h index 38b379d6c624..93a1db5bf3b5 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -88,11 +88,11 @@ struct consw { * limited to, unblanking the console, loading an appropriate * palette, and allowing debugger generated output. */ - int (*con_debug_enter)(struct vc_data *vc); + void(*con_debug_enter)(struct vc_data *vc); /* * Restore the console to its pre-debug state as closely as possible. */ - int (*con_debug_leave)(struct vc_data *vc); + void(*con_debug_leave)(struct vc_data *vc); }; extern const struct consw *conswitchp; @@ -113,17 +113,11 @@ int do_unregister_con_driver(const struct consw *csw); int do_take_over_console(const struct consw *sw, int first, int last, int deflt); void give_up_console(const struct consw *sw); #ifdef CONFIG_HW_CONSOLE -int con_debug_enter(struct vc_data *vc); -int con_debug_leave(void); +void con_debug_enter(struct
[PATCH 29/45] tty: vt: make consw::con_switch() return a bool
The non-zero (true) return value from consw::con_switch() means a redraw is needed. So make this return type a bool explicitly instead of int. The latter might imply that -Eerrors are expected. They are not. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/tty/vt/vt.c | 2 +- drivers/video/console/dummycon.c| 4 ++-- drivers/video/console/mdacon.c | 4 ++-- drivers/video/console/newport_con.c | 4 ++-- drivers/video/console/sticon.c | 4 ++-- drivers/video/console/vgacon.c | 4 ++-- drivers/video/fbdev/core/fbcon.c| 6 +++--- include/linux/console.h | 4 +++- 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2df306922b4e..88d7b48871fb 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -970,7 +970,7 @@ void redraw_screen(struct vc_data *vc, int is_switch) } if (redraw) { - int update; + bool update; int old_was_color = vc->vc_can_do_color; set_origin(vc); diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index 1171e27edef7..c8d5aa0e3ed0 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -122,9 +122,9 @@ static bool dummycon_scroll(struct vc_data *vc, unsigned int top, return false; } -static int dummycon_switch(struct vc_data *vc) +static bool dummycon_switch(struct vc_data *vc) { - return 0; + return false; } /* diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index bc851a1d9f4d..4485ef923bb3 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -446,9 +446,9 @@ static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x, scr_memsetw(dest, eattr, width * 2); } -static int mdacon_switch(struct vc_data *c) +static bool mdacon_switch(struct vc_data *c) { - return 1; /* redrawing needed */ + return true;/* redrawing needed */ } static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e35406dea7c7..039d1c9937d2 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -459,7 +459,7 @@ static void newport_cursor(struct vc_data *vc, bool enable) newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); } -static int newport_switch(struct vc_data *vc) +static bool newport_switch(struct vc_data *vc) { static int logo_drawn = 0; @@ -473,7 +473,7 @@ static int newport_switch(struct vc_data *vc) } } - return 1; + return true; } static int newport_blank(struct vc_data *c, int blank, int mode_switch) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 786e1b3a98ea..f3bb48a0e980 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -293,9 +293,9 @@ static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx, conp->vc_video_erase_char, font_data[conp->vc_num]); } -static int sticon_switch(struct vc_data *conp) +static bool sticon_switch(struct vc_data *conp) { -return 1; /* needs refreshing */ +return true; /* needs refreshing */ } static int sticon_blank(struct vc_data *c, int blank, int mode_switch) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index c81723ad4dc1..e303098aabab 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -614,7 +614,7 @@ static void vgacon_doresize(struct vc_data *c, raw_spin_unlock_irqrestore(&vga_lock, flags); } -static int vgacon_switch(struct vc_data *c) +static bool vgacon_switch(struct vc_data *c) { int x = c->vc_cols * VGA_FONTWIDTH; int y = c->vc_rows * c->vc_cell_height; @@ -643,7 +643,7 @@ static int vgacon_switch(struct vc_data *c) vgacon_doresize(c, c->vc_cols, c->vc_rows); } - return 0; /* Redrawing not needed */ + return false; /* Redrawing not needed */ } static void vga_set_palette(struct vc_data *vc, const unsigned char *table) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index c1765a6ef490..d5d924225209 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -2056,7 +2056,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, return 0; } -static int fbcon_switch(struct vc_data *vc) +static bool fbcon_switch(struct vc_data *vc) { struct fb_info *info, *old_info = NULL; struct fbcon_ops *ops; @@ -2178,9 +217
[PATCH 28/45] tty: vt: remove CM_* constants
There is no difference between CM_MOVE and CM_DRAW. Either of them enables the cursor. CM_ERASE then disables cursor. So get rid of all of them and use simple "bool enable". Note that this propagates down to the fbcon code. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/tty/vt/vt.c | 4 ++-- drivers/video/console/dummycon.c | 2 +- drivers/video/console/mdacon.c | 4 ++-- drivers/video/console/newport_con.c | 4 ++-- drivers/video/console/sticon.c | 6 +++--- drivers/video/console/vgacon.c | 6 +++--- drivers/video/fbdev/core/bitblit.c | 4 ++-- drivers/video/fbdev/core/fbcon.c | 19 +-- drivers/video/fbdev/core/fbcon.h | 4 ++-- drivers/video/fbdev/core/fbcon_ccw.c | 4 ++-- drivers/video/fbdev/core/fbcon_cw.c | 4 ++-- drivers/video/fbdev/core/fbcon_ud.c | 4 ++-- drivers/video/fbdev/core/tileblit.c | 4 ++-- include/linux/console.h | 8 ++-- 14 files changed, 36 insertions(+), 41 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 73e48a53dc31..2df306922b4e 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -860,7 +860,7 @@ static void hide_cursor(struct vc_data *vc) if (vc_is_sel(vc)) clear_selection(); - vc->vc_sw->con_cursor(vc, CM_ERASE); + vc->vc_sw->con_cursor(vc, false); hide_softcursor(vc); } @@ -873,7 +873,7 @@ static void set_cursor(struct vc_data *vc) clear_selection(); add_softcursor(vc); if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE) - vc->vc_sw->con_cursor(vc, CM_DRAW); + vc->vc_sw->con_cursor(vc, true); } else hide_cursor(vc); } diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index 188d9f3e201c..1171e27edef7 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -113,7 +113,7 @@ static void dummycon_init(struct vc_data *vc, bool init) static void dummycon_deinit(struct vc_data *vc) { } static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, unsigned int width) { } -static void dummycon_cursor(struct vc_data *vc, int mode) { } +static void dummycon_cursor(struct vc_data *vc, bool enable) { } static bool dummycon_scroll(struct vc_data *vc, unsigned int top, unsigned int bottom, enum con_scroll dir, diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index b8822b615b2f..bc851a1d9f4d 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -470,9 +470,9 @@ static int mdacon_blank(struct vc_data *c, int blank, int mode_switch) } } -static void mdacon_cursor(struct vc_data *c, int mode) +static void mdacon_cursor(struct vc_data *c, bool enable) { - if (mode == CM_ERASE) { + if (!enable) { mda_set_cursor(mda_vram_len - 1); return; } diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index f852717b88f0..e35406dea7c7 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -438,14 +438,14 @@ static void newport_putcs(struct vc_data *vc, const u16 *s, } } -static void newport_cursor(struct vc_data *vc, int mode) +static void newport_cursor(struct vc_data *vc, bool enable) { unsigned short treg; int xcurs, ycurs; treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - if (mode == CM_ERASE) { + if (!enable) { newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg & ~(VC2_CTRL_ECDISP))); return; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 42480874db00..786e1b3a98ea 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -86,7 +86,7 @@ static void sticon_putcs(struct vc_data *conp, const u16 *s, unsigned int count, } } -static void sticon_cursor(struct vc_data *conp, int mode) +static void sticon_cursor(struct vc_data *conp, bool enable) { unsigned short car1; @@ -95,7 +95,7 @@ static void sticon_cursor(struct vc_data *conp, int mode) return; car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; -if (mode == CM_ERASE) { +if (!enable) { sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, font_data[conp->vc_num]); return; @@ -121,7 +121,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t, if (vga_is_gfx) return false; -sticon_cursor(conp, CM_ERASE); +sticon_cursor(conp, fa
[PATCH 26/45] consoles: use if instead of switch-case in consw::con_cursor()
This is only a preparation for the following cleanup patch to make it easier. Provided CM_ERASE is the only different, use 'if' instead of 'switch+case' in all those. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/console/newport_con.c | 26 +--- drivers/video/console/sticon.c | 27 ++-- drivers/video/console/vgacon.c | 66 + 3 files changed, 53 insertions(+), 66 deletions(-) diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 5e65ee0b7c07..f852717b88f0 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -443,24 +443,20 @@ static void newport_cursor(struct vc_data *vc, int mode) unsigned short treg; int xcurs, ycurs; - switch (mode) { - case CM_ERASE: - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - newport_vc2_set(npregs, VC2_IREG_CONTROL, - (treg & ~(VC2_CTRL_ECDISP))); - break; + treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); - case CM_MOVE: - case CM_DRAW: - treg = newport_vc2_get(npregs, VC2_IREG_CONTROL); + if (mode == CM_ERASE) { newport_vc2_set(npregs, VC2_IREG_CONTROL, - (treg | VC2_CTRL_ECDISP)); - xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; - ycurs = ((xcurs / vc->vc_cols) << 4) + 31; - xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; - newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); - newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); + (treg & ~(VC2_CTRL_ECDISP))); + return; } + + newport_vc2_set(npregs, VC2_IREG_CONTROL, (treg | VC2_CTRL_ECDISP)); + xcurs = (vc->vc_pos - vc->vc_visible_origin) / 2; + ycurs = ((xcurs / vc->vc_cols) << 4) + 31; + xcurs = ((xcurs % vc->vc_cols) << 3) + xcurs_correction; + newport_vc2_set(npregs, VC2_IREG_CURSX, xcurs); + newport_vc2_set(npregs, VC2_IREG_CURSY, ycurs); } static int newport_switch(struct vc_data *vc) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 906da1fde7c8..42480874db00 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -95,23 +95,20 @@ static void sticon_cursor(struct vc_data *conp, int mode) return; car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; -switch (mode) { -case CM_ERASE: +if (mode == CM_ERASE) { sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, font_data[conp->vc_num]); - break; -case CM_MOVE: -case CM_DRAW: - switch (CUR_SIZE(conp->vc_cursor_type)) { - case CUR_UNDERLINE: - case CUR_LOWER_THIRD: - case CUR_LOWER_HALF: - case CUR_TWO_THIRDS: - case CUR_BLOCK: - sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), -conp->state.y, conp->state.x, font_data[conp->vc_num]); - break; - } + return; +} + +switch (CUR_SIZE(conp->vc_cursor_type)) { +case CUR_UNDERLINE: +case CUR_LOWER_THIRD: +case CUR_LOWER_HALF: +case CUR_TWO_THIRDS: +case CUR_BLOCK: + sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), +conp->state.y, conp->state.x, font_data[conp->vc_num]); break; } } diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 558076462b0d..3bf7f46a8998 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -514,47 +514,41 @@ static void vgacon_cursor(struct vc_data *c, int mode) c_height = c->vc_cell_height; - switch (mode) { - case CM_ERASE: - write_vga(14, (c->vc_pos - vga_vram_base) / 2); + write_vga(14, (c->vc_pos - vga_vram_base) / 2); + + if (mode == CM_ERASE) { if (vga_video_type >= VIDEO_TYPE_VGAC) vgacon_set_cursor_size(31, 30); else vgacon_set_cursor_size(31, 31); - break; + return; + } - case CM_MOVE: - case CM_DRAW: - write_vga(14, (c->vc_pos - vga_vram_base) / 2); - switch (CUR_SIZE(c->vc_cursor_type)) { - case CUR_UNDERLINE: - vgacon_set_cursor_size(c_height - - (c_height < 10 ? 2 : 3), - c_height - - (c_height < 10 ? 1 : 2)); - break; - case CUR_TWO_THIRDS: - vgacon_set_cursor_size(c_height / 3, c_height - -
[PATCH 23/45] tty: vt: eliminate unneeded consw::con_putc() implementations
All these consw::con_putc() implementations do the same as consw::con_putcs() (only for one charattr) or even call consw::con_putcs() on their own. Drop them, as thanks to the new con_putc() helper in the previous patch, the console code performs this already -- exactly if consw::con_putc() is missing (NULL). Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/video/console/mdacon.c | 6 -- drivers/video/console/sticon.c | 12 drivers/video/console/vgacon.c | 2 -- drivers/video/fbdev/core/fbcon.c | 9 - 4 files changed, 29 deletions(-) diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 2ff2c9394d40..01e779943c00 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -427,11 +427,6 @@ static inline u16 *mda_addr(unsigned int x, unsigned int y) return mda_vram_base + y * mda_num_columns + x; } -static void mdacon_putc(struct vc_data *c, int ch, int y, int x) -{ - scr_writew(mda_convert_attr(ch), mda_addr(x, y)); -} - static void mdacon_putcs(struct vc_data *c, const unsigned short *s, int count, int y, int x) { @@ -536,7 +531,6 @@ static const struct consw mda_con = { .con_init = mdacon_init, .con_deinit = mdacon_deinit, .con_clear =mdacon_clear, - .con_putc = mdacon_putc, .con_putcs =mdacon_putcs, .con_cursor = mdacon_cursor, .con_scroll = mdacon_scroll, diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index b1d972d9a31c..2f87b5909d0d 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -71,17 +71,6 @@ static const char *sticon_startup(void) return "STI console"; } -static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) -{ -if (vga_is_gfx || console_blanked) - return; - -if (conp->vc_mode != KD_TEXT) - return; - -sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]); -} - static void sticon_putcs(struct vc_data *conp, const unsigned short *s, int count, int ypos, int xpos) { @@ -362,7 +351,6 @@ static const struct consw sti_con = { .con_init = sticon_init, .con_deinit = sticon_deinit, .con_clear = sticon_clear, - .con_putc = sticon_putc, .con_putcs = sticon_putcs, .con_cursor = sticon_cursor, .con_scroll = sticon_scroll, diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index c6bd4acbe1d2..2cb75be74c38 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1193,7 +1193,6 @@ static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, static void vgacon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, unsigned int width) { } -static void vgacon_putc(struct vc_data *vc, int c, int ypos, int xpos) { } static void vgacon_putcs(struct vc_data *vc, const unsigned short *s, int count, int ypos, int xpos) { } @@ -1203,7 +1202,6 @@ const struct consw vga_con = { .con_init = vgacon_init, .con_deinit = vgacon_deinit, .con_clear = vgacon_clear, - .con_putc = vgacon_putc, .con_putcs = vgacon_putcs, .con_cursor = vgacon_cursor, .con_scroll = vgacon_scroll, diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 8a31a36483ea..38de0f8723aa 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1292,14 +1292,6 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, get_color(vc, info, scr_readw(s), 0)); } -static void fbcon_putc(struct vc_data *vc, int c, int ypos, int xpos) -{ - unsigned short chr; - - scr_writew(c, &chr); - fbcon_putcs(vc, &chr, 1, ypos, xpos); -} - static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); @@ -3159,7 +3151,6 @@ static const struct consw fb_con = { .con_init = fbcon_init, .con_deinit = fbcon_deinit, .con_clear = fbcon_clear, - .con_putc = fbcon_putc, .con_putcs = fbcon_putcs, .con_cursor = fbcon_cursor, .con_scroll = fbcon_scroll, -- 2.43.0
[PATCH 21/45] tty: vt: remove checks for count in consw::con_clear() implementations
'count' in consw::con_clear() is guaranteed to be positive. csi_X() (the only caller) takes the minimum of the vc parameter (which is at least 1) and count of characters till the end of the line. The latter is computed as a subtraction of vc->vc_cols (count) and vc->state.x (offset). So for the worst case, full line, it is 1. Therefore, there is no point in checking zero or negative values (width is now unsigned anyway). Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/video/console/mdacon.c | 3 --- drivers/video/console/sticon.c | 3 --- 2 files changed, 6 deletions(-) diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index 1ddbb6cd5b0c..2ff2c9394d40 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -448,9 +448,6 @@ static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x, u16 *dest = mda_addr(x, y); u16 eattr = mda_convert_attr(c->vc_video_erase_char); - if (width <= 0) - return; - scr_memsetw(dest, eattr, width * 2); } diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index d99c2a659bfd..b1d972d9a31c 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -303,9 +303,6 @@ static void sticon_deinit(struct vc_data *c) static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx, unsigned int width) { -if (!width) - return; - sti_clear(sticon_sti, sy, sx, 1, width, conp->vc_video_erase_char, font_data[conp->vc_num]); } -- 2.43.0
[PATCH 20/45] tty: vt: sanitize arguments of consw::con_clear()
In consw::con_clear(): * Height is always 1, so drop it. * Offsets and width are always unsigned values, so re-type them as such. This needs a new __fbcon_clear() in the fbcon code to still handle height which might not be 1 when called internally. Note that tests for negative count/width are left in place -- they are taken care of in the next patches. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/tty/vt/vt.c | 2 +- drivers/video/console/dummycon.c| 4 ++-- drivers/video/console/mdacon.c | 15 +- drivers/video/console/newport_con.c | 6 +++--- drivers/video/console/sticon.c | 8 drivers/video/console/vgacon.c | 4 ++-- drivers/video/fbdev/core/fbcon.c| 32 + include/linux/console.h | 5 +++-- 8 files changed, 39 insertions(+), 37 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index eada45683594..a4ee983824d5 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1590,7 +1590,7 @@ static void csi_X(struct vc_data *vc, unsigned int vpar) vc_uniscr_clear_line(vc, vc->state.x, count); scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); if (con_should_update(vc)) - vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count); + vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, count); vc->vc_need_wrap = 0; } diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index f2cef9d9a4b5..0a69d5c216ee 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -109,8 +109,8 @@ static void dummycon_init(struct vc_data *vc, bool init) } static void dummycon_deinit(struct vc_data *vc) { } -static void dummycon_clear(struct vc_data *vc, int sy, int sx, int height, - int width) { } +static void dummycon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, + unsigned int width) { } static void dummycon_cursor(struct vc_data *vc, int mode) { } static bool dummycon_scroll(struct vc_data *vc, unsigned int top, diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index c5b255c96879..1ddbb6cd5b0c 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -442,23 +442,18 @@ static void mdacon_putcs(struct vc_data *c, const unsigned short *s, } } -static void mdacon_clear(struct vc_data *c, int y, int x, - int height, int width) +static void mdacon_clear(struct vc_data *c, unsigned int y, unsigned int x, +unsigned int width) { u16 *dest = mda_addr(x, y); u16 eattr = mda_convert_attr(c->vc_video_erase_char); - if (width <= 0 || height <= 0) + if (width <= 0) return; - if (x==0 && width==mda_num_columns) { - scr_memsetw(dest, eattr, height*width*2); - } else { - for (; height > 0; height--, dest+=mda_num_columns) - scr_memsetw(dest, eattr, width*2); - } + scr_memsetw(dest, eattr, width * 2); } - + static int mdacon_switch(struct vc_data *c) { return 1; /* redrawing needed */ diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 12c64ef47087..55c6106b3507 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -346,12 +346,12 @@ static void newport_deinit(struct vc_data *c) } } -static void newport_clear(struct vc_data *vc, int sy, int sx, int height, - int width) +static void newport_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, + unsigned int width) { int xend = ((sx + width) << 3) - 1; int ystart = ((sy << 4) + topscan) & 0x3ff; - int yend = (((sy + height) << 4) + topscan - 1) & 0x3ff; + int yend = (((sy + 1) << 4) + topscan - 1) & 0x3ff; if (logo_active) return; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 0bfeabc3f7c7..d99c2a659bfd 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -300,13 +300,13 @@ static void sticon_deinit(struct vc_data *c) sticon_set_def_font(i); } -static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, -int width) +static void sticon_clear(struct vc_data *conp, unsigned int sy, unsigned int sx, +unsigned int width) { -if (!height || !width) +if (!width) return; -sti_clear(sticon_sti, sy, sx, height, width, +sti_clear(sticon_sti
[PATCH 19/45] tty: vt: make init parameter of consw::con_init() a bool
The 'init' parameter of consw::con_init() is true for the first call of the hook on a particular console. So make the parameter a bool. And document the hook. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org Cc: linux-par...@vger.kernel.org --- drivers/tty/vt/vt.c | 8 drivers/video/console/dummycon.c| 2 +- drivers/video/console/mdacon.c | 2 +- drivers/video/console/newport_con.c | 2 +- drivers/video/console/sticon.c | 2 +- drivers/video/console/vgacon.c | 2 +- drivers/video/fbdev/core/fbcon.c| 2 +- include/linux/console.h | 4 +++- 8 files changed, 13 insertions(+), 11 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index a953c3f262a5..eada45683594 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -999,7 +999,7 @@ int vc_cons_allocated(unsigned int i) return (i < MAX_NR_CONSOLES && vc_cons[i].d); } -static void visual_init(struct vc_data *vc, int num, int init) +static void visual_init(struct vc_data *vc, int num, bool init) { /* ++Geert: vc->vc_sw->con_init determines console size */ if (vc->vc_sw) @@ -1083,7 +1083,7 @@ int vc_allocate(unsigned int currcons)/* return 0 on success */ vc->port.ops = &vc_port_ops; INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); - visual_init(vc, currcons, 1); + visual_init(vc, currcons, true); if (!*vc->uni_pagedict_loc) con_set_default_unimap(vc); @@ -3527,7 +3527,7 @@ static int __init con_init(void) vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); tty_port_init(&vc->port); - visual_init(vc, currcons, 1); + visual_init(vc, currcons, true); /* Assuming vc->vc_{cols,rows,screenbuf_size} are sane here. */ vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); vc_init(vc, currcons || !vc->vc_sw->con_save_screen); @@ -3696,7 +3696,7 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last, old_was_color = vc->vc_can_do_color; vc->vc_sw->con_deinit(vc); vc->vc_origin = (unsigned long)vc->vc_screenbuf; - visual_init(vc, i, 0); + visual_init(vc, i, false); set_origin(vc); update_attr(vc); diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c index 14af5d9e13b0..f2cef9d9a4b5 100644 --- a/drivers/video/console/dummycon.c +++ b/drivers/video/console/dummycon.c @@ -98,7 +98,7 @@ static const char *dummycon_startup(void) return "dummy device"; } -static void dummycon_init(struct vc_data *vc, int init) +static void dummycon_init(struct vc_data *vc, bool init) { vc->vc_can_do_color = 1; if (init) { diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index ef29b321967f..c5b255c96879 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -352,7 +352,7 @@ static const char *mdacon_startup(void) return "MDA-2"; } -static void mdacon_init(struct vc_data *c, int init) +static void mdacon_init(struct vc_data *c, bool init) { c->vc_complement_mask = 0x0800; /* reverse video */ c->vc_display_fg = &mda_display_fg; diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e8e4f82cd4a1..12c64ef47087 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -324,7 +324,7 @@ static const char *newport_startup(void) return NULL; } -static void newport_init(struct vc_data *vc, int init) +static void newport_init(struct vc_data *vc, bool init) { int cols, rows; diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 992a4fa431aa..0bfeabc3f7c7 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -273,7 +273,7 @@ static int sticon_font_set(struct vc_data *vc, struct console_font *font, return sticon_set_font(vc, font, vpitch); } -static void sticon_init(struct vc_data *c, int init) +static void sticon_init(struct vc_data *c, bool init) { struct sti_struct *sti = sticon_sti; int vc_cols, vc_rows; diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0c76e2817b49..2c0a952ee51a 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -367,7 +367,7 @@ static const char *vgacon_startup(void) return display_desc; } -static void vgacon_init(struct vc_data *c, int init) +static void vgacon_init(struct vc_data *c, bool init) { struct uni_pagedict *p; diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/v
[PATCH 00/45] tty: vt: cleanup and documentation
Push the console code (vt.c, vt.h, console.h, ...) into a bit more maintainable state. Especially all around consw structure and document it. CSI parser is also a bit cleaned up. More to follow some time in the next round. Cc: Daniel Vetter Cc: dri-devel@lists.freedesktop.org Cc: Helge Deller Cc: "James E.J. Bottomley" Cc: Jonathan Corbet Cc: linux-...@vger.kernel.org Cc: linux-fb...@vger.kernel.org Cc: linux-par...@vger.kernel.org Cc: Martin Hostettler Jiri Slaby (SUSE) (45): vgacon: inline vc_scrolldelta_helper() into vgacon_scrolldelta() fbcon: make display_desc a static array in fbcon_startup() tty: vt: fix 20 vs 0x20 typo in EScsiignore tty: vt: expect valid vc when in tty ops tty: vt: pass proper pointers from tioclinux() tty: vt: push console lock from tioclinux() down to 2 functions tty: vt: pass vc_resize_user as a parameter tty: vt: make vc_is_sel()'s vc const tty: vt: define an enum for CSI+m codes tty: vt: use case ranges for CSI+m fg/bg colors tty: vt: define an enum for CSI+J codes tty: vt: reflow csi_J() tty: vt: define an enum for CSI+K codes tty: vt: reflow csi_K() tty: vt: pass vpar as unsigned to csi_J() and csi_K() tty: vt: define an enum for ascii characters tty: vt: remove extern from functions in selection.h tty: vt: make consw::con_debug_*() return void tty: vt: make init parameter of consw::con_init() a bool tty: vt: sanitize arguments of consw::con_clear() tty: vt: remove checks for count in consw::con_clear() implementations tty: vt: add con_putc() helper tty: vt: eliminate unneeded consw::con_putc() implementations tty: vt: sanitize consw::con_putc() parameters tty: vt: sanitize consw::con_putcs() parameters consoles: use if instead of switch-case in consw::con_cursor() fbdev/core: simplify cursor_state setting in fbcon_ops::cursor() tty: vt: remove CM_* constants tty: vt: make consw::con_switch() return a bool tty: vt: stop using -1 for blank mode in consw::con_blank() tty: vt: use VESA blanking constants tty: vt: use enum for VESA blanking modes tty: vt: make types around consw::con_blank() bool tty: vt: make font of consw::con_font_set() const tty: vt: make consw::con_font_default()'s name const tty: vt: change consw::con_set_origin() return type fbcon: remove consw::con_screen_pos() tty: vt: remove consw::con_screen_pos() tty: vt: make types of screenpos() more consistent fbcon: remove fbcon_getxy() tty: vt: remove consw::con_getxy() tty: vt: remove unused consw::con_flush_scrollback() tty: vt: document the rest of struct consw tty: vt: fix up kernel-doc Documentation: add console.rst Documentation/driver-api/tty/console.rst | 45 ++ Documentation/driver-api/tty/index.rst | 1 + drivers/tty/vt/selection.c | 43 +- drivers/tty/vt/vt.c | 587 +++ drivers/tty/vt/vt_ioctl.c| 6 +- drivers/video/console/dummycon.c | 38 +- drivers/video/console/mdacon.c | 43 +- drivers/video/console/newport_con.c | 69 +-- drivers/video/console/sticon.c | 79 ++- drivers/video/console/vgacon.c | 150 +++--- drivers/video/fbdev/core/bitblit.c | 13 +- drivers/video/fbdev/core/fbcon.c | 123 ++--- drivers/video/fbdev/core/fbcon.h | 4 +- drivers/video/fbdev/core/fbcon_ccw.c | 13 +- drivers/video/fbdev/core/fbcon_cw.c | 13 +- drivers/video/fbdev/core/fbcon_ud.c | 13 +- drivers/video/fbdev/core/tileblit.c | 4 +- include/linux/console.h | 132 ++--- include/linux/console_struct.h | 1 - include/linux/selection.h| 56 +-- include/linux/vt_kern.h | 12 +- include/uapi/linux/fb.h | 5 +- 22 files changed, 725 insertions(+), 725 deletions(-) create mode 100644 Documentation/driver-api/tty/console.rst -- 2.43.0
[PATCH 01/45] vgacon: inline vc_scrolldelta_helper() into vgacon_scrolldelta()
Since commit 74d58cd48a8f ("USB: sisusbvga: remove console support"), vgacon_scrolldelta() is the only user of vc_scrolldelta_helper(). Inline the helper into vgacon_scrolldelta() and drop it. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/tty/vt/vt.c| 40 -- drivers/video/console/vgacon.c | 36 -- include/linux/vt_kern.h| 3 --- 3 files changed, 34 insertions(+), 45 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 156efda7c80d..3f3f7c216819 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -4748,43 +4748,3 @@ void vcs_scr_updated(struct vc_data *vc) { notify_update(vc); } - -void vc_scrolldelta_helper(struct vc_data *c, int lines, - unsigned int rolled_over, void *base, unsigned int size) -{ - unsigned long ubase = (unsigned long)base; - ptrdiff_t scr_end = (void *)c->vc_scr_end - base; - ptrdiff_t vorigin = (void *)c->vc_visible_origin - base; - ptrdiff_t origin = (void *)c->vc_origin - base; - int margin = c->vc_size_row * 4; - int from, wrap, from_off, avail; - - /* Turn scrollback off */ - if (!lines) { - c->vc_visible_origin = c->vc_origin; - return; - } - - /* Do we have already enough to allow jumping from 0 to the end? */ - if (rolled_over > scr_end + margin) { - from = scr_end; - wrap = rolled_over + c->vc_size_row; - } else { - from = 0; - wrap = size; - } - - from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row; - avail = (origin - from + wrap) % wrap; - - /* Only a little piece would be left? Show all incl. the piece! */ - if (avail < 2 * margin) - margin = 0; - if (from_off < margin) - from_off = 0; - if (from_off > avail - margin) - from_off = avail; - - c->vc_visible_origin = ubase + (from + from_off) % wrap; -} -EXPORT_SYMBOL_GPL(vc_scrolldelta_helper); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 8ef1579fa57f..9176fff9ce6e 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -138,8 +138,40 @@ static inline void vga_set_mem_top(struct vc_data *c) static void vgacon_scrolldelta(struct vc_data *c, int lines) { - vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base, - vga_vram_size); + unsigned long scr_end = c->vc_scr_end - vga_vram_base; + unsigned long vorigin = c->vc_visible_origin - vga_vram_base; + unsigned long origin = c->vc_origin - vga_vram_base; + int margin = c->vc_size_row * 4; + int from, wrap, from_off, avail; + + /* Turn scrollback off */ + if (!lines) { + c->vc_visible_origin = c->vc_origin; + return; + } + + /* Do we have already enough to allow jumping from 0 to the end? */ + if (vga_rolled_over > scr_end + margin) { + from = scr_end; + wrap = vga_rolled_over + c->vc_size_row; + } else { + from = 0; + wrap = vga_vram_size; + } + + from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row; + avail = (origin - from + wrap) % wrap; + + /* Only a little piece would be left? Show all incl. the piece! */ + if (avail < 2 * margin) + margin = 0; + if (from_off < margin) + from_off = 0; + if (from_off > avail - margin) + from_off = avail; + + c->vc_visible_origin = vga_vram_base + (from + from_off) % wrap; + vga_set_mem_top(c); } diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index c1f5aebef170..a789ea3ed2a0 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -168,7 +168,4 @@ void vt_set_led_state(unsigned int console, int leds); void vt_kbd_con_start(unsigned int console); void vt_kbd_con_stop(unsigned int console); -void vc_scrolldelta_helper(struct vc_data *c, int lines, - unsigned int rolled_over, void *_base, unsigned int size); - #endif /* _VT_KERN_H */ -- 2.43.0
[PATCH 07/45] tty: vt: pass vc_resize_user as a parameter
It is pretty unfortunate to set vc_data::vc_resize_user in two callers of vc_do_resize(). vc_resize_user is immediately reset there (while remembering it). So instead of this back and forth, pass 'from_user' as a parameter. Notes on 'int user': * The name changes from 'user' to 'from_user' on some places to be consistent. * The type is bool now as 'int user' might evoke user's uid or whatever. Provided vc_resize() is called on many places and they need not to care about this parameter, its prototype is kept unchanged. Instead, it is now an inline calling a new __vc_resize() which implements the above. This patch makes the situation much more obvious. Signed-off-by: Jiri Slaby (SUSE) Cc: Helge Deller Cc: Daniel Vetter Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/tty/vt/vt.c | 28 +--- drivers/tty/vt/vt_ioctl.c| 6 ++ drivers/video/console/vgacon.c | 4 ++-- drivers/video/fbdev/core/fbcon.c | 2 +- include/linux/console.h | 2 +- include/linux/console_struct.h | 1 - include/linux/vt_kern.h | 9 - 7 files changed, 27 insertions(+), 25 deletions(-) diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 3a6f60ad2224..c87837306074 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1115,13 +1115,13 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ } static inline int resize_screen(struct vc_data *vc, int width, int height, - int user) + bool from_user) { /* Resizes the resolution of the display adapater */ int err = 0; if (vc->vc_sw->con_resize) - err = vc->vc_sw->con_resize(vc, width, height, user); + err = vc->vc_sw->con_resize(vc, width, height, from_user); return err; } @@ -1132,6 +1132,7 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, * @vc: virtual console private data * @cols: columns * @lines: lines + * @from_user: invoked by a user? * * Resize a virtual console, clipping according to the actual constraints. * If the caller passes a tty structure then update the termios winsize @@ -1142,21 +1143,17 @@ static inline int resize_screen(struct vc_data *vc, int width, int height, */ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, - unsigned int cols, unsigned int lines) + unsigned int cols, unsigned int lines, bool from_user) { unsigned long old_origin, new_origin, new_scr_end, rlth, rrem, err = 0; unsigned long end; unsigned int old_rows, old_row_size, first_copied_row; unsigned int new_cols, new_rows, new_row_size, new_screen_size; - unsigned int user; unsigned short *oldscreen, *newscreen; u32 **new_uniscr = NULL; WARN_CONSOLE_UNLOCKED(); - user = vc->vc_resize_user; - vc->vc_resize_user = 0; - if (cols > VC_MAXCOL || lines > VC_MAXROW) return -EINVAL; @@ -1182,7 +1179,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, * to deal with possible errors from the code below, we call * the resize_screen here as well. */ - return resize_screen(vc, new_cols, new_rows, user); + return resize_screen(vc, new_cols, new_rows, from_user); } if (new_screen_size > KMALLOC_MAX_SIZE || !new_screen_size) @@ -1205,7 +1202,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, old_rows = vc->vc_rows; old_row_size = vc->vc_size_row; - err = resize_screen(vc, new_cols, new_rows, user); + err = resize_screen(vc, new_cols, new_rows, from_user); if (err) { kfree(newscreen); vc_uniscr_free(new_uniscr); @@ -1292,22 +1289,23 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, } /** - * vc_resize - resize a VT + * __vc_resize - resize a VT * @vc: virtual console * @cols: columns * @rows: rows + * @from_user: invoked by a user? * * Resize a virtual console as seen from the console end of things. We * use the common vc_do_resize methods to update the structures. The * caller must hold the console sem to protect console internals and * vc->port.tty */ - -int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) +int __vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows, + bool from_user) { - return vc_do_resize(vc->port.tty, vc, cols, rows); + return vc_do_resize(vc->port.tty, vc, cols, rows, from_user); } -EXPORT_SYMBOL(vc_resize); +EXPORT_SYMBOL(__vc_resize); /** * vt_resize - resize a VT @@
[PATCH 02/45] fbcon: make display_desc a static array in fbcon_startup()
display_desc is a pointer to a RO string. Instead, switch display_desc to a static array as we are used to. It BTW saves unnecessary 8B on the stack. Signed-off-by: Jiri Slaby (SUSE) Cc: Daniel Vetter Cc: Helge Deller Cc: linux-fb...@vger.kernel.org Cc: dri-devel@lists.freedesktop.org --- drivers/video/fbdev/core/fbcon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 63af6ab034b5..a8c32cb4c878 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -921,7 +921,7 @@ static void display_to_var(struct fb_var_screeninfo *var, static const char *fbcon_startup(void) { - const char *display_desc = "frame buffer device"; + static const char display_desc[] = "frame buffer device"; struct fbcon_display *p = &fb_display[fg_console]; struct vc_data *vc = vc_cons[fg_console].d; const struct font_desc *font = NULL; -- 2.43.0
Re: [BUG][BISECTED] Freeze at loading init ramdisk
Hello Mirsad, On Wed, Jan 17, 2024 at 07:47:49PM +0100, Mirsad Todorovac wrote: > On 1/16/24 01:32, Mirsad Todorovac wrote: > > On the Ubuntu 22.04 LTS Jammy platform, on a mainline vanilla torvalds tree > > kernel, the boot > > freezes upon first two lines and before any systemd messages. > > > > (Please find the config attached.) > > > > Bisecting the bug led to this result: > > > > marvin@defiant:~/linux/kernel/linux_torvalds$ git bisect good > > d97a78423c33f68ca6543de510a409167baed6f5 is the first bad commit > > commit d97a78423c33f68ca6543de510a409167baed6f5 > > Merge: 61da593f4458 689237ab37c5 > > Author: Linus Torvalds > > Date: Fri Jan 12 14:38:08 2024 -0800 > > > > [...] > > > > Hope this helps. > > P.S. > > As I see that this is a larger merge commit, with 5K+ lines changed, I don't > think I can > bisect further to determine the culprit. Actually it's not that hard. If a merge commit is the first bad commit for a bisection, either the merge wasn't done correctly (less likely, looking at d97a78423c33f68ca6543de510a409167baed6f5 I'd bet this isn't the problem); or changes on different sides conflict or you did something wrong during bisection. To rule out the third option, you can just retest d97a78423c33, 61da593f4458 and 689237ab37c5. If d97a78423c33 is the only bad one, you did it right. Then to further debug the second option you can find out the offending commit on each side with a bisection as follows, here for the RHS (i.e. 689237ab37c5): git bisect start 689237ab37c5 $(git merge-base 61da593f4458 689237ab37c5) and then in each bisection step do: git merge --no-commit 61da593f4458 test if the problem is present git reset --hard git bisect good/bad In this case you get merge conflicts in drivers/video/fbdev/amba-clcd.c and drivers/video/fbdev/vermilion/vermilion.c. In the assumption that you don't have these enabled in your .config, you can just ignore these. Side note: A problem during bisection can be that the .config changes along the process. You should put your config into (say) arch/x86/configs/lala_defconfig and do make lala_defconfig before building each step to prevent this. Best regards Uwe -- Pengutronix e.K. | Uwe Kleine-König| Industrial Linux Solutions | https://www.pengutronix.de/ | signature.asc Description: PGP signature
Re: [PATCH 2/3] dt-bindings: mfd: atmel,hlcdc: Convert to DT schema format
On 17/01/24 1:07 pm, Krzysztof Kozlowski wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you know the > content is safe > > On 17/01/2024 03:22, dharm...@microchip.com wrote: >> Hi Krzysztof, >> On 10/01/24 11:31 pm, Krzysztof Kozlowski wrote: >>> EXTERNAL EMAIL: Do not click links or open attachments unless you know the >>> content is safe >>> >>> On 10/01/2024 11:25, Dharma Balasubiramani wrote: Convert the atmel,hlcdc binding to DT schema format. Signed-off-by: Dharma Balasubiramani --- .../devicetree/bindings/mfd/atmel,hlcdc.yaml | 106 ++ .../devicetree/bindings/mfd/atmel-hlcdc.txt | 56 - 2 files changed, 106 insertions(+), 56 deletions(-) create mode 100644 Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml delete mode 100644 Documentation/devicetree/bindings/mfd/atmel-hlcdc.txt diff --git a/Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml b/Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml new file mode 100644 index ..555d6faa9104 --- /dev/null +++ b/Documentation/devicetree/bindings/mfd/atmel,hlcdc.yaml >>> >>> This looks not tested, so limited review follows: >> I acknowledge that I didn't test the patches individually. I appreciate >> your understanding. Taken care in v2. >>> @@ -0,0 +1,106 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# Copyright (C) 2024 Microchip Technology, Inc. and its subsidiaries +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mfd/atmel,hlcdc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Atmel's HLCDC (High LCD Controller) MFD driver >>> >>> Drop "MFD driver" and rather describe/name the hardware. MFD is Linux >>> term, so I really doubt that's how this was called. >> Done. >>> + +maintainers: + - Nicolas Ferre + - Alexandre Belloni + - Claudiu Beznea + +description: | + Device-Tree bindings for Atmel's HLCDC (High LCD Controller) MFD driver. >>> >>> Drop >> Done. >>> + The HLCDC IP exposes two subdevices: + # a PWM chip: see ../pwm/atmel,hlcdc-pwm.yaml + # a Display Controller: see ../display/atmel/atmel,hlcdc-dc.yaml >>> >>> Rephrase to describe hardware. Drop redundant paths. >> Sure, I will truncate this to "subdevices: a PWM chip and a display >> controller." & drop the |. >> >> I added description about those two subdevices below. > > Then why do you still keep there comments? # is a comment. Sure, I will drop the comments here. > ... > >> in v3. >>> + + hlcdc-display-controller: >>> >>> Does anything depend on the name? If not, then just display-controller >> Got an error "'hlcdc-display-controller' does not match any of the >> regexes: 'pinctrl-[0-9]+'" so I retained it in v2,but as conor advised >> to have node names generic and we can easily adopt, I will modify it in v3. > > That's not a dependency. I was talking about any users of the binding. > User of a binding is for example: Linux kernel driver, other open-source > projects, out-of-tree projects. Sure, I will go with generic names 'display-controller' and 'pwm'. -- With Best Regards, Dharma B. > > > Best regards, > Krzysztof >
[linux-next:master] BUILD REGRESSION 943b9f0ab2cfbaea148dd6ac279957eb08b96904
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master branch HEAD: 943b9f0ab2cfbaea148dd6ac279957eb08b96904 Add linux-next specific files for 20240117 Error/Warning reports: https://lore.kernel.org/oe-kbuild-all/202401172119.fc2ic3l9-...@intel.com https://lore.kernel.org/oe-kbuild-all/202401172139.xsfsnhrj-...@intel.com Error/Warning: (recently discovered and may have been fixed) drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_crtc.c:100: warning: This comment starts with '/**', but isn't a kernel-doc comment. Refer Documentation/doc-guide/kernel-doc.rst fs/bcachefs/btree_write_buffer.c:128:24: warning: unused variable 'c' [-Wunused-variable] Error/Warning ids grouped by kconfigs: gcc_recent_errors |-- alpha-allyesconfig | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-dst_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-filled_descs_num-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-size-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-src_addr-not-described-in-xdma_fill_descs | `-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-sw_desc-not-described-in-xdma_fill_descs |-- arc-allmodconfig | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-dst_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-filled_descs_num-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-size-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-src_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-sw_desc-not-described-in-xdma_fill_descs | `-- drivers-gpu-drm-msm-disp-dpu1-dpu_encoder.c:warning:Excess-struct-member-debugfs_root-description-in-dpu_encoder_virt |-- arc-allyesconfig | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-dst_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-filled_descs_num-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-size-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-src_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-sw_desc-not-described-in-xdma_fill_descs | `-- drivers-gpu-drm-msm-disp-dpu1-dpu_encoder.c:warning:Excess-struct-member-debugfs_root-description-in-dpu_encoder_virt |-- arm-allmodconfig | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-dst_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-filled_descs_num-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-size-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-src_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-sw_desc-not-described-in-xdma_fill_descs | `-- drivers-gpu-drm-msm-disp-dpu1-dpu_encoder.c:warning:Excess-struct-member-debugfs_root-description-in-dpu_encoder_virt |-- arm-allyesconfig | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-dst_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-filled_descs_num-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-size-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-src_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-sw_desc-not-described-in-xdma_fill_descs | `-- drivers-gpu-drm-msm-disp-dpu1-dpu_encoder.c:warning:Excess-struct-member-debugfs_root-description-in-dpu_encoder_virt |-- arm-randconfig-002-20240117 | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-dst_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-filled_descs_num-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-size-not-described-in-xdma_fill_descs | |-- drivers-dma-xilinx-xdma.c:warning:Function-parameter-or-struct-member-src_addr-not-described-in-xdma_fill_descs | |-- drivers-dma-xilin
Re: [PATCH] drm/bridge: anx7625: Ensure bridge is suspended in disable()
Hi Hsin-Yi, On Thu, Jan 18, 2024 at 9:59 AM Hsin-Yi Wang wrote: > > Similar to commit 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge > is suspended in .post_disable()"). Add a mutex to ensure that aux transfer > won't race with atomic_disable by holding the PM reference and prevent > the bridge from suspend. > > Also we need to use pm_runtime_put_sync_suspend() to suspend the bridge > instead of idle with pm_runtime_put_sync(). > > Fixes: 3203e497eb76 ("drm/bridge: anx7625: Synchronously run runtime > suspend.") > Fixes: adca62ec370c ("drm/bridge: anx7625: Support reading edid through aux > channel") > Signed-off-by: Hsin-Yi Wang > Tested-by: Xuxin Xiong > --- > drivers/gpu/drm/bridge/analogix/anx7625.c | 7 ++- > drivers/gpu/drm/bridge/analogix/anx7625.h | 2 ++ > 2 files changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c > b/drivers/gpu/drm/bridge/analogix/anx7625.c > index ef31033439bc..29d91493b101 100644 > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c > @@ -1762,6 +1762,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux > *aux, > u8 request = msg->request & ~DP_AUX_I2C_MOT; > int ret = 0; > > + mutex_lock(&ctx->aux_lock); > pm_runtime_get_sync(dev); > msg->reply = 0; > switch (request) { > @@ -1778,6 +1779,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux > *aux, > msg->size, msg->buffer); > pm_runtime_mark_last_busy(dev); > pm_runtime_put_autosuspend(dev); > + mutex_unlock(&ctx->aux_lock); > > return ret; > } > @@ -2474,7 +2476,9 @@ static void anx7625_bridge_atomic_disable(struct > drm_bridge *bridge, > ctx->connector = NULL; > anx7625_dp_stop(ctx); > > - pm_runtime_put_sync(dev); > + mutex_lock(&ctx->aux_lock); > + pm_runtime_put_sync_suspend(dev); > + mutex_unlock(&ctx->aux_lock); > } > > static enum drm_connector_status > @@ -2668,6 +2672,7 @@ static int anx7625_i2c_probe(struct i2c_client *client) > > mutex_init(&platform->lock); > mutex_init(&platform->hdcp_wq_lock); > + mutex_init(&platform->aux_lock); > > INIT_DELAYED_WORK(&platform->hdcp_work, hdcp_check_work_func); > platform->hdcp_workqueue = create_workqueue("hdcp workqueue"); > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h > b/drivers/gpu/drm/bridge/analogix/anx7625.h > index 66ebee7f3d83..39ed35d33836 100644 > --- a/drivers/gpu/drm/bridge/analogix/anx7625.h > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h > @@ -475,6 +475,8 @@ struct anx7625_data { > struct workqueue_struct *hdcp_workqueue; > /* Lock for hdcp work queue */ > struct mutex hdcp_wq_lock; > + /* Lock for aux transfer and disable */ > + struct mutex aux_lock; > char edid_block; > struct display_timing dt; > u8 display_timing_valid; > -- > 2.43.0.381.gb435a96ce8-goog > Reviewed-by: Pin-yen Lin
Re: [PATCH v2] drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()
Hi Doug, On Thu, Jan 18, 2024 at 2:37 AM Doug Anderson wrote: > > Hi, > > On Wed, Jan 17, 2024 at 9:34 AM Doug Anderson wrote: > > > > Hi, > > > > On Tue, Jan 9, 2024 at 8:52 AM Doug Anderson wrote: > > > > > > Hi, > > > > > > On Tue, Jan 9, 2024 at 4:05 AM Pin-yen Lin wrote: > > > > > > > > The ps8640 bridge seems to expect everything to be power cycled at the > > > > disable process, but sometimes ps8640_aux_transfer() holds the runtime > > > > PM reference and prevents the bridge from suspend. > > > > > > > > Prevent that by introducing a mutex lock between ps8640_aux_transfer() > > > > and .post_disable() to make sure the bridge is really powered off. > > > > > > > > Fixes: 826cff3f7ebb ("drm/bridge: parade-ps8640: Enable runtime power > > > > management") > > > > Signed-off-by: Pin-yen Lin > > > > --- > > > > > > > > Changes in v2: > > > > - Use mutex instead of the completion and autosuspend hack > > > > > > > > drivers/gpu/drm/bridge/parade-ps8640.c | 16 > > > > 1 file changed, 16 insertions(+) > > > > > > This looks OK to me now. > > > > > > Reviewed-by: Douglas Anderson > > > > > > I'll let it stew on the mailing list for ~1 week and then land it in > > > drm-misc-fixes unless there are additional comments. > > > > Pushed to drm-misc-fixes: > > > > 26db46bc9c67 drm/bridge: parade-ps8640: Ensure bridge is suspended in > > .post_disable() > > Crud. I landed this and then almost immediately hit a bug with it. :( > I've posted up the fix: > > https://lore.kernel.org/r/20240117103502.1.Ib726a0184913925efc7e99c4d4fc801982e1bc24@changeid > > -Doug Sorry, I missed this because the patch was based on drm-misc-next, so it did not include commit 024b32db43a3 ("drm/bridge: parade-ps8640: Wait for HPD when doing an AUX transfer"). I also forgot to apply that commit when I did my testing. Pin-yen
Re: [PATCH v1 4/6] drm/lima: handle spurious timeouts due to high irq latency
On Wed, Jan 17, 2024 at 11:12 AM Erico Nunes wrote: > > There are several unexplained and unreproduced cases of rendering > timeouts with lima, for which one theory is high IRQ latency coming from > somewhere else in the system. > This kind of occurrence may cause applications to trigger unnecessary > resets of the GPU or even applications to hang if it hits an issue in > the recovery path. > Panfrost already does some special handling to account for such > "spurious timeouts", it makes sense to have this in lima too to reduce > the chance that it hit users. > > Signed-off-by: Erico Nunes > --- > drivers/gpu/drm/lima/lima_sched.c | 32 ++- > drivers/gpu/drm/lima/lima_sched.h | 2 ++ > 2 files changed, 29 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > b/drivers/gpu/drm/lima/lima_sched.c > index 66317296d831..9449b81bcd5b 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0 OR MIT > /* Copyright 2017-2019 Qiang Yu */ > > +#include > #include > #include > #include > @@ -223,10 +224,7 @@ static struct dma_fence *lima_sched_run_job(struct > drm_sched_job *job) > > task->fence = &fence->base; > > - /* for caller usage of the fence, otherwise irq handler > -* may consume the fence before caller use it > -*/ > - dma_fence_get(task->fence); > + task->done_fence = dma_fence_get(task->fence); > > pipe->current_task = task; > > @@ -401,9 +399,33 @@ static enum drm_gpu_sched_stat > lima_sched_timedout_job(struct drm_sched_job *job > struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); > struct lima_sched_task *task = to_lima_task(job); > struct lima_device *ldev = pipe->ldev; > + struct lima_ip *ip = pipe->processor[0]; > + > + /* > +* If the GPU managed to complete this jobs fence, the timeout is > +* spurious. Bail out. > +*/ > + if (dma_fence_is_signaled(task->done_fence)) { > + DRM_WARN("%s spurious timeout\n", lima_ip_name(ip)); > + return DRM_GPU_SCHED_STAT_NOMINAL; > + } > + > + /* > +* Lima IRQ handler may take a long time to process an interrupt > +* if there is another IRQ handler hogging the processing. > +* In order to catch such cases and not report spurious Lima job > +* timeouts, synchronize the IRQ handler and re-check the fence > +* status. > +*/ > + synchronize_irq(ip->irq); > + > + if (dma_fence_is_signaled(task->done_fence)) { > + DRM_WARN("%s unexpectedly high interrupt latency\n", > lima_ip_name(ip)); > + return DRM_GPU_SCHED_STAT_NOMINAL; > + } > > if (!pipe->error) > - DRM_ERROR("lima job timeout\n"); > + DRM_ERROR("%s lima job timeout\n", lima_ip_name(ip)); > > drm_sched_stop(&pipe->base, &task->base); > > diff --git a/drivers/gpu/drm/lima/lima_sched.h > b/drivers/gpu/drm/lima/lima_sched.h > index 6a11764d87b3..34050facb110 100644 > --- a/drivers/gpu/drm/lima/lima_sched.h > +++ b/drivers/gpu/drm/lima/lima_sched.h > @@ -29,6 +29,8 @@ struct lima_sched_task { > bool recoverable; > struct lima_bo *heap; > > + struct dma_fence *done_fence; This is same as the following fence, do we really need a duplicated one? > + > /* pipe fence */ > struct dma_fence *fence; > }; > -- > 2.43.0 >
[PATCH] drm/amd/display: Simplify the calculation of variables
./drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c:703:47-49: WARNING !A || A && B is equivalent to !A || B. Reported-by: Abaci Robot Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=7931 Signed-off-by: Jiapeng Chong --- drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c index a0ce681b26c6..118aaf4389bc 100644 --- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c +++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c @@ -700,9 +700,9 @@ static void free_unused_pipes_for_plane(struct dml2_context *ctx, struct dc_stat for (i = 0; i < ctx->config.dcn_pipe_count; i++) { if (state->res_ctx.pipe_ctx[i].plane_state == plane && state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id && - (!is_plane_duplicate || (is_plane_duplicate && + (!is_plane_duplicate || ctx->v20.scratch.dml_to_dc_pipe_mapping.dml_pipe_idx_to_plane_index[state->res_ctx.pipe_ctx[i].pipe_idx] == plane_index)) && - !is_pipe_used(pool, state->res_ctx.pipe_ctx[i].pipe_idx)) { + !is_pipe_used(pool, state->res_ctx.pipe_ctx[i].pipe_idx) { free_pipe(&state->res_ctx.pipe_ctx[i]); } } -- 2.20.1.7.g153144c
Re: [PATCH] drm/msm/adreno: Add a null pointer check in zap_shader_load_mdt()
On 2024/1/18 02:50, Markus Elfring wrote: kasprintf() returns a pointer to dynamically allocated memory which can be NULL upon failure. Ensure the allocation was successful by checking the pointer validity. … +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -144,6 +144,10 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname, char *newname; newname = kasprintf(GFP_KERNEL, "qcom/%s", fwname); + if (!newname) { + ret = -ENOMEM; + goto out; + } … How do you think about to avoid the repetition of the pointer check for the variable “mem_region”? "mem_region"? Is this a clerical error, do you mean 'newname'? No check found in __qcom_mdt_load for 'newname'. 'newname' is used for printing in '__qcom_mdt_load' in some cases, which is a bit dangerous. So it's necessary check it before using it. Can the usage of other labels become more appropriate? Regards, Markus -- Thanks, Kunwu
Re: [PATCH v1 3/6] drm/lima: set bus_stop bit before hard reset
Do we need same for GP? Regards, Qiang On Wed, Jan 17, 2024 at 11:12 AM Erico Nunes wrote: > > This is required for reliable hard resets. Otherwise, doing a hard reset > while a task is still running (such as a task which is being stopped by > the drm_sched timeout handler) may result in random mmu write timeouts > or lockups which cause the entire gpu to hang. > > Signed-off-by: Erico Nunes > --- > drivers/gpu/drm/lima/lima_pp.c | 13 + > 1 file changed, 13 insertions(+) > > diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c > index a8f8f63b8295..ac097dd75072 100644 > --- a/drivers/gpu/drm/lima/lima_pp.c > +++ b/drivers/gpu/drm/lima/lima_pp.c > @@ -168,6 +168,11 @@ static void lima_pp_write_frame(struct lima_ip *ip, u32 > *frame, u32 *wb) > } > } > > +static int lima_pp_bus_stop_poll(struct lima_ip *ip) > +{ > + return !!(pp_read(LIMA_PP_STATUS) & LIMA_PP_STATUS_BUS_STOPPED); > +} > + > static int lima_pp_hard_reset_poll(struct lima_ip *ip) > { > pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC01A); > @@ -181,6 +186,14 @@ static int lima_pp_hard_reset(struct lima_ip *ip) > > pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC0FFE000); > pp_write(LIMA_PP_INT_MASK, 0); > + > + pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_STOP_BUS); > + ret = lima_poll_timeout(ip, lima_pp_bus_stop_poll, 10, 100); > + if (ret) { > + dev_err(dev->dev, "pp %s bus stop timeout\n", > lima_ip_name(ip)); > + return ret; > + } > + > pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_FORCE_RESET); > ret = lima_poll_timeout(ip, lima_pp_hard_reset_poll, 10, 100); > if (ret) { > -- > 2.43.0 >
[PATCH] drm/bridge: anx7625: Ensure bridge is suspended in disable()
Similar to commit 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()"). Add a mutex to ensure that aux transfer won't race with atomic_disable by holding the PM reference and prevent the bridge from suspend. Also we need to use pm_runtime_put_sync_suspend() to suspend the bridge instead of idle with pm_runtime_put_sync(). Fixes: 3203e497eb76 ("drm/bridge: anx7625: Synchronously run runtime suspend.") Fixes: adca62ec370c ("drm/bridge: anx7625: Support reading edid through aux channel") Signed-off-by: Hsin-Yi Wang Tested-by: Xuxin Xiong --- drivers/gpu/drm/bridge/analogix/anx7625.c | 7 ++- drivers/gpu/drm/bridge/analogix/anx7625.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index ef31033439bc..29d91493b101 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1762,6 +1762,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, u8 request = msg->request & ~DP_AUX_I2C_MOT; int ret = 0; + mutex_lock(&ctx->aux_lock); pm_runtime_get_sync(dev); msg->reply = 0; switch (request) { @@ -1778,6 +1779,7 @@ static ssize_t anx7625_aux_transfer(struct drm_dp_aux *aux, msg->size, msg->buffer); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); + mutex_unlock(&ctx->aux_lock); return ret; } @@ -2474,7 +2476,9 @@ static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge, ctx->connector = NULL; anx7625_dp_stop(ctx); - pm_runtime_put_sync(dev); + mutex_lock(&ctx->aux_lock); + pm_runtime_put_sync_suspend(dev); + mutex_unlock(&ctx->aux_lock); } static enum drm_connector_status @@ -2668,6 +2672,7 @@ static int anx7625_i2c_probe(struct i2c_client *client) mutex_init(&platform->lock); mutex_init(&platform->hdcp_wq_lock); + mutex_init(&platform->aux_lock); INIT_DELAYED_WORK(&platform->hdcp_work, hdcp_check_work_func); platform->hdcp_workqueue = create_workqueue("hdcp workqueue"); diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h b/drivers/gpu/drm/bridge/analogix/anx7625.h index 66ebee7f3d83..39ed35d33836 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.h +++ b/drivers/gpu/drm/bridge/analogix/anx7625.h @@ -475,6 +475,8 @@ struct anx7625_data { struct workqueue_struct *hdcp_workqueue; /* Lock for hdcp work queue */ struct mutex hdcp_wq_lock; + /* Lock for aux transfer and disable */ + struct mutex aux_lock; char edid_block; struct display_timing dt; u8 display_timing_valid; -- 2.43.0.381.gb435a96ce8-goog
Re: [PATCH v1 2/6] drm/lima: reset async_reset on pp hard reset
GP should also need this. Regards, Qiang On Wed, Jan 17, 2024 at 11:12 AM Erico Nunes wrote: > > Lima pp jobs use an async reset to avoid having to wait for the soft > reset right after a job. The soft reset is done at the end of a job and > a reset_complete flag is expected to be set at the next job. > However, in case the user runs into a job timeout from any application, > a hard reset is issued to the hardware. This hard reset clears the > reset_complete flag, which causes an error message to show up before the > next job. > This is probably harmless for the execution but can be very confusing to > debug, as it blames a reset timeout on the next application to submit a > job. > Reset the async_reset flag when doing the hard reset so that we don't > get that message. > > Signed-off-by: Erico Nunes > --- > drivers/gpu/drm/lima/lima_pp.c | 7 +++ > 1 file changed, 7 insertions(+) > > diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c > index a5c95bed08c0..a8f8f63b8295 100644 > --- a/drivers/gpu/drm/lima/lima_pp.c > +++ b/drivers/gpu/drm/lima/lima_pp.c > @@ -191,6 +191,13 @@ static int lima_pp_hard_reset(struct lima_ip *ip) > pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0); > pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL); > pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED); > + > + /* > +* if there was an async soft reset queued, > +* don't wait for it in the next job > +*/ > + ip->data.async_reset = false; > + > return 0; > } > > -- > 2.43.0 >
Re: [PATCH v1 1/6] drm/lima: fix devfreq refcount imbalance for job timeouts
So this is caused by same job trigger both done and timeout handling? I think a better way to solve this is to make sure only one handler (done or timeout) process the job instead of just making lima_pm_idle() unique. Regards, Qiang On Wed, Jan 17, 2024 at 11:12 AM Erico Nunes wrote: > > In case a task manages to complete but it took just long enough to also > trigger the timeout handler, the current code results in a refcount > imbalance on lima_pm_idle. > > While this can be a rare occurrence, when it happens it may fill user > logs with stack traces such as: > > [10136.669170] WARNING: CPU: 0 PID: 0 at > drivers/gpu/drm/lima/lima_devfreq.c:205 lima_devfreq_record_idle+0xa0/0xb0 > ... > [10136.669459] pc : lima_devfreq_record_idle+0xa0/0xb0 > ... > [10136.669628] Call trace: > [10136.669634] lima_devfreq_record_idle+0xa0/0xb0 > [10136.669646] lima_sched_pipe_task_done+0x5c/0xb0 > [10136.669656] lima_gp_irq_handler+0xa8/0x120 > [10136.669666] __handle_irq_event_percpu+0x48/0x160 > [10136.669679] handle_irq_event+0x4c/0xc0 > > The imbalance happens because lima_sched_pipe_task_done() already calls > lima_pm_idle for this case if there was no error. > Check the error flag in the timeout handler to ensure we can never run > into this case. > > Signed-off-by: Erico Nunes > --- > drivers/gpu/drm/lima/lima_sched.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > b/drivers/gpu/drm/lima/lima_sched.c > index c3bf8cda8498..66317296d831 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -427,7 +427,8 @@ static enum drm_gpu_sched_stat > lima_sched_timedout_job(struct drm_sched_job *job > pipe->current_vm = NULL; > pipe->current_task = NULL; > > - lima_pm_idle(ldev); > + if (pipe->error) > + lima_pm_idle(ldev); > > drm_sched_resubmit_jobs(&pipe->base); > drm_sched_start(&pipe->base, true); > -- > 2.43.0 >
Re: Userspace API for per key backlight for non HID (no hidraw) keyboards
Hi Hans and Armin, Am 17.01.24 um 20:03 schrieb Armin Wolf: Am 17.01.24 um 17:50 schrieb Hans de Goede: Hi All, On 11/27/23 11:59, Werner Sembach wrote: I also stumbled across a new Problem: We have an upcoming device that has a per-key keyboard backlight, but does the control completely via a wmi/acpi interface. So no usable hidraw here for a potential userspace driver implementation ... So a quick summary for the ideas floating in this thread so far: 1. Expand leds interface allowing arbitrary modes with semi arbitrary optional attributes: - Pro: - Still offers all default attributes for use with UPower - Fairly simple to implement from the preexisting codebase - Could be implemented for all (to me) known internal keyboard backlights - Con: - Violates the simplicity paradigm of the leds interface (e.g. with this one leds entry controls possible multiple leds) So what you are suggesting here is having some way (a-z + other sysfs attr?) to use a single LED class device and then extend that to allow setting all keys ? This does not seem like a good idea to me and this will also cause issues when doing animations in software, since this API will likely be slow. And if the API is not slow, then it will likely involve some sort of binary sysfs file for setting multiple keys rather then 1 file per key which would break the normal 1 file per setting sysfs paradigm. 2. Implement per-key keyboards as auxdisplay - Pro: - Already has a concept for led positions With a "concept" you mean simple x,y positioning or is there something more advanced here that I'm aware of ? - Is conceptually closer to "multiple leds forming a singular entity" - Con: - No preexisting UPower support - No concept for special hardware lightning modes - No support for arbitrary led outlines yet (e.g. ISO style enter-key) Hmm, so there is very little documentation on this and what docs there is: Documentation/admin-guide/auxdisplay/cfag12864b.rst as well as the example program how to uses this suggests that this is using the old /dev/fb# interface which we are sorta trying to retire. 3. Implement in input subsystem - Pro: - Preexisting concept for keys and key purpose - Con: - Not in scope for subsystem - No other preexisting light infrastructure Dmitry actually recently nacked the addition of a LED_MIC_MUTE define to include/uapi/linux/input-event-codes.h which was intended to be able to allow the input LED support with standard HID mic-mute leds (spk-mute is already supported this way). Dmitry was very clear that no new LEDs must be added and that any new LED support should be done through the LED subsytem, so I do not think that something like this is going to fly. 4. Implement a simple leds driver only supporting a small subset of the capabilities and make it disable-able for a userspace driver to take over - Pro: - Most simple to implement basic support - In scope for led subsystem simplicity paradigm - Con: - Not all built in keyboard backlights can be implemented in a userspace only driver Right, so this is basically what we have been discussing in the other part of the thread with the: /sys/bus/hid/devices/0003::./disable_kbd_backlight_support proposal to unregister the kernel's LED class device and then allow userspace to do whatever it wants through /dev/hidraw without the kernel also trying to access the backlight functionality at the same time. AFAIK there already is a bunch of userspace support for per key addressable kbd RGB backlights using hidraw support, so this way we can use the momentum / code of these existing projects, at least for existing hidraw keyboards and adding support for: /sys/bus/hid/devices/0003::./disable_kbd_backlight_support to these existing projects should be simple. Yet this will not work for your mentioned "control completely via a wmi/acpi interface". Still I think we should go the same route for those adding a misc-char device or something like that to allow making WMI calls from userspace (like Windows can do). Maybe with an allow list per GUID to only allow specific calls, so that we can avoid possible dangerous calls. Armin Wolf recently became the WMI bus maintainer. Armin, we are discussing how to deal with (laptop) keyboards which have a separate RGB LED per key and how to control those LEDs. So far per key addressable keyboard backlighting has always been HID based, so any existing support is just userspace based using /dev/hidraw. In my experience the problem with supporting gaming peripherals is that there is interest in it, but not really enough interest to keep a sustained momentum behind projects, especially not when it comes to taking code from a fun weekend hack to upstreaming them into bigger projects like the kernel. So
Re: [PATCH v2 5/5] drm/xe: Enable 32bits build
On Tue, Jan 16, 2024 at 09:40:50AM -0800, Lucas De Marchi wrote: > Now that all the issues with 32bits are fixed, enable it again. > > Signed-off-by: Lucas De Marchi I didn't test locally, but assuming you confirmed all the warnings are gone now, Reviewed-by: Matt Roper > --- > drivers/gpu/drm/xe/Kconfig | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig > index 1b57ae38210d..1b0ef91a5d2c 100644 > --- a/drivers/gpu/drm/xe/Kconfig > +++ b/drivers/gpu/drm/xe/Kconfig > @@ -1,7 +1,7 @@ > # SPDX-License-Identifier: GPL-2.0-only > config DRM_XE > tristate "Intel Xe Graphics" > - depends on DRM && PCI && MMU && (m || (y && KUNIT=y)) && 64BIT > + depends on DRM && PCI && MMU && (m || (y && KUNIT=y)) > select INTERVAL_TREE > # we need shmfs for the swappable backing store, and in particular > # the shmem_readpage() which depends upon tmpfs > -- > 2.40.1 > -- Matt Roper Graphics Software Engineer Linux GPU Platform Enablement Intel Corporation
Re: [PATCH v2 4/5] drm/xe: Fix cast on trace variable
On Tue, Jan 16, 2024 at 09:40:49AM -0800, Lucas De Marchi wrote: > Cast the pointer to unsigned long and let it be implicitly extended to > u64. This fixes the build on 32bits arch. > > Cc: Matthew Brost > Cc: Niranjana Vishwanathapura > Cc: Rodrigo Vivi > Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper > --- > drivers/gpu/drm/xe/xe_trace.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h > index 95163c303f3e..e4e7262191ad 100644 > --- a/drivers/gpu/drm/xe/xe_trace.h > +++ b/drivers/gpu/drm/xe/xe_trace.h > @@ -31,7 +31,7 @@ DECLARE_EVENT_CLASS(xe_gt_tlb_invalidation_fence, >), > > TP_fast_assign( > -__entry->fence = (u64)fence; > +__entry->fence = (unsigned long)fence; > __entry->seqno = fence->seqno; > ), > > -- > 2.40.1 > -- Matt Roper Graphics Software Engineer Linux GPU Platform Enablement Intel Corporation
Re: [PATCH v2 3/5] drm/xe/display: Avoid calling readq()
On Tue, Jan 16, 2024 at 09:40:48AM -0800, Lucas De Marchi wrote: > readq() is not available in 32bits. iosys-map already has the logic in > place to use read u64 in all cases, so simply add a helper variable for > using that. > > Fixes: 44e694958b95 ("drm/xe/display: Implement display support") > Signed-off-by: Lucas De Marchi > --- > .../gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h | 7 +-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h > b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h > index 5f19550cc845..6739dadaf1a9 100644 > --- a/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h > +++ b/drivers/gpu/drm/xe/compat-i915-headers/gem/i915_gem_object.h > @@ -7,6 +7,7 @@ > #define _I915_GEM_OBJECT_H_ > > #include > +#include > > #include "xe_bo.h" > > @@ -36,6 +37,7 @@ static inline int i915_gem_object_read_from_page(struct > xe_bo *bo, > { > struct ttm_bo_kmap_obj map; > void *virtual; > + struct iosys_map vaddr; > bool is_iomem; > int ret; > > @@ -52,10 +54,11 @@ static inline int i915_gem_object_read_from_page(struct > xe_bo *bo, > ofs &= ~PAGE_MASK; > virtual = ttm_kmap_obj_virtual(&map, &is_iomem); > if (is_iomem) > - *ptr = readq((void __iomem *)(virtual + ofs)); > + iosys_map_set_vaddr_iomem(&vaddr, (void __iomem *)(virtual)); Should we just use a memcpy_fromio (and memcpy in the else branch) and pass the size actually requested rather than hardcoding it to a u64? At the moment the only callsite happens to want a u64, and thus the Xe compat header has an XE_WARN_ON that complains if any other size is requested, but in theory this function is supposed to be general purpose and take any size. Matt > else > - *ptr = *(u64 *)(virtual + ofs); > + iosys_map_set_vaddr(&vaddr, virtual); > > + *ptr = iosys_map_rd(&vaddr, ofs, u64); > ttm_bo_kunmap(&map); > out_unlock: > xe_bo_unlock(bo); > -- > 2.40.1 > -- Matt Roper Graphics Software Engineer Linux GPU Platform Enablement Intel Corporation
Re: [git pull] drm fixes for 6.8-rc1
The pull request you sent on Mon, 15 Jan 2024 16:18:01 +1000: > git://anongit.freedesktop.org/drm/drm tags/drm-next-2024-01-15-1 has been merged into torvalds/linux.git: https://git.kernel.org/torvalds/c/8893a6bfff312ea6fee89bfaa8761f0b9456199b Thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/prtracker.html
Re: [PATCH v2 2/5] drm/xe/mmio: Cast to u64 when printing
On Tue, Jan 16, 2024 at 09:40:47AM -0800, Lucas De Marchi wrote: > resource_size_t uses %pa format in printk since the size varies > depending on build options. However to keep the io_size/physical_size > addition in the same call we can't pass the address without adding yet > another variable in these function. Simply cast it to u64 and keep using > %llx. > > Fixes: 286089ce6929 ("drm/xe: Improve vram info debug printing") > Cc: Oak Zeng > Cc: Michael J. Ruhl > Cc: Matthew Brost > Cc: Rodrigo Vivi > Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper > --- > drivers/gpu/drm/xe/xe_mmio.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c > index c8c5d74b6e90..5f6b53ea5528 100644 > --- a/drivers/gpu/drm/xe/xe_mmio.c > +++ b/drivers/gpu/drm/xe/xe_mmio.c > @@ -272,8 +272,8 @@ int xe_mmio_probe_vram(struct xe_device *xe) > drm_info(&xe->drm, "VRAM[%u, %u]: Actual physical size %pa, > usable size exclude stolen %pa, CPU accessible size %pa\n", id, >tile->id, &tile->mem.vram.actual_physical_size, > &tile->mem.vram.usable_size, &tile->mem.vram.io_size); > drm_info(&xe->drm, "VRAM[%u, %u]: DPA range: [%pa-%llx], io > range: [%pa-%llx]\n", id, tile->id, > - &tile->mem.vram.dpa_base, tile->mem.vram.dpa_base + > tile->mem.vram.actual_physical_size, > - &tile->mem.vram.io_start, tile->mem.vram.io_start + > tile->mem.vram.io_size); > + &tile->mem.vram.dpa_base, tile->mem.vram.dpa_base + > (u64)tile->mem.vram.actual_physical_size, > + &tile->mem.vram.io_start, tile->mem.vram.io_start + > (u64)tile->mem.vram.io_size); > > /* calculate total size using tile size to get the correct HW > sizing */ > total_size += tile_size; > -- > 2.40.1 > -- Matt Roper Graphics Software Engineer Linux GPU Platform Enablement Intel Corporation
Re: [PATCH v2 1/5] drm/xe: Use _ULL for u64 division
On Tue, Jan 16, 2024 at 09:40:46AM -0800, Lucas De Marchi wrote: > Use DIV_ROUND_UP_ULL() so it also works on 32bit build. > > Fixes: dd08ebf6c352 ("drm/xe: Introduce a new DRM driver for Intel GPUs") > Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper > --- > drivers/gpu/drm/xe/xe_device.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c > index a94c0b27f04e..5f5e3c7132d3 100644 > --- a/drivers/gpu/drm/xe/xe_device.c > +++ b/drivers/gpu/drm/xe/xe_device.c > @@ -624,7 +624,7 @@ void xe_device_wmb(struct xe_device *xe) > u32 xe_device_ccs_bytes(struct xe_device *xe, u64 size) > { > return xe_device_has_flat_ccs(xe) ? > - DIV_ROUND_UP(size, NUM_BYTES_PER_CCS_BYTE(xe)) : 0; > + DIV_ROUND_UP_ULL(size, NUM_BYTES_PER_CCS_BYTE(xe)) : 0; > } > > bool xe_device_mem_access_ongoing(struct xe_device *xe) > -- > 2.40.1 > -- Matt Roper Graphics Software Engineer Linux GPU Platform Enablement Intel Corporation
Re: [RFC PATCH 1/3] dt-bindings: display: ti,am65x-dss: Add support for display sharing mode
On Wed, Jan 17, 2024 at 02:13:42PM -0600, Rob Herring wrote: > On Tue, Jan 16, 2024 at 07:11:40PM +0530, Devarsh Thakkar wrote: > > Add support for using TI Keystone DSS hardware present in display > > sharing mode. > > > > TI Keystone DSS hardware supports partitioning of resources between > > multiple hosts as it provides separate register space and unique > > interrupt line to each host. > > > > The DSS hardware can be used in shared mode in such a way that one or > > more of video planes can be owned by Linux wherease other planes can be > > owned by remote cores. > > > > One or more of the video ports can be dedicated exclusively to a > > processing core, wherease some of the video ports can be shared between > > two hosts too with only one of them having write access. > > > > Signed-off-by: Devarsh Thakkar > > --- > > .../bindings/display/ti/ti,am65x-dss.yaml | 82 +++ > > 1 file changed, 82 insertions(+) > > > > diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > > b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > > index 55e3e490d0e6..d9bc69fbf1fb 100644 > > --- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > > +++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > > @@ -112,6 +112,86 @@ properties: > >Input memory (from main memory to dispc) bandwidth limit in > >bytes per second > > > > + ti,dss-shared-mode: > > +type: boolean > > +description: > > + TI DSS7 supports sharing of display between multiple hosts > > + as it provides separate register space for display configuration and > > + unique interrupt line to each host. > > If you care about line breaks, you need '|'. > > > + One of the host is provided access to the global display > > + configuration labelled as "common" region of DSS allows that host > > + exclusive access to global registers of DSS while other host can > > + configure the display for it's usage using a separate register > > + space labelled as "common1". > > + The DSS resources can be partitioned in such a way that one or more > > + of the video planes are owned by Linux whereas other video planes > > Your h/w can only run Linux? > > What if you want to use this same binding to define the configuration to > the 'remote processor'? You can easily s/Linux/the OS/, but it all > should be reworded to describe things in terms of the local processor. > > > + can be owned by a remote core. > > + The video port controlling these planes acts as a shared video port > > + and it can be configured with write access either by Linux or the > > + remote core in which case Linux only has read-only access to that > > + video port. > > What is the purpose of this property when all the other properties are > required? > > > + > > + ti,dss-shared-mode-planes: > > +description: > > + The video layer that is owned by processing core running Linux. > > + The display driver running from Linux has exclusive write access to > > + this video layer. > > +$ref: /schemas/types.yaml#/definitions/string > > +enum: [vidl, vid] > > + > > + ti,dss-shared-mode-vp: > > +description: > > + The video port that is being used in context of processing core > > + running Linux with display susbsytem being used in shared mode. > > + This can be owned either by the processing core running Linux in > > + which case Linux has the write access and the responsibility to > > + configure this video port and the associated overlay manager or > > + it can be shared between core running Linux and a remote core > > + with remote core provided with write access to this video port and > > + associated overlay managers and remote core configures and drives > > + this video port also feeding data from one or more of the > > + video planes owned by Linux, with Linux only having read-only access > > + to this video port and associated overlay managers. > > + > > +$ref: /schemas/types.yaml#/definitions/string > > +enum: [vp1, vp2] > > + > > + ti,dss-shared-mode-common: > > +description: > > + The DSS register region owned by processing core running Linux. > > +$ref: /schemas/types.yaml#/definitions/string > > +enum: [common, common1] > > + > > + ti,dss-shared-mode-vp-owned: > > +description: > > + This tells whether processing core running Linux has write access to > > + the video ports enlisted in ti,dss-shared-mode-vps. > > +$ref: /schemas/types.yaml#/definitions/uint32 > > +enum: [0, 1] > > This can be boolean. Do writes abort or just get ignored? The latter can > be probed and doesn't need a property. > > > + > > + ti,dss-shared-mode-plane-zorder: > > +description: > > + The zorder of the planes owned by Linux. > > + For the scenario where Linux is not having writ
[PATCH 21/23] drm/xe/svm: GPU page fault support
On gpu page fault of a virtual address, try to fault in the virtual address range to gpu page table and let HW to retry on the faulty address. Right now, we always migrate the whole vma which contains the fault address to GPU. This is subject to change of a more sophisticated migration policy: decide whether to migrate memory to GPU or map in place with CPU memory; migration granularity. There is rather complicated locking strategy in this patch. See more details in xe_svm_doc.h, lock design section. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_gt_pagefault.c | 7 ++ drivers/gpu/drm/xe/xe_svm.c | 116 +++ drivers/gpu/drm/xe/xe_svm.h | 6 ++ drivers/gpu/drm/xe/xe_svm_range.c| 43 ++ 4 files changed, 172 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index 467d68f8332e..462603abab8a 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -22,6 +22,7 @@ #include "xe_pt.h" #include "xe_trace.h" #include "xe_vm.h" +#include "xe_svm.h" enum fault_type { NOT_PRESENT = 0, @@ -131,6 +132,11 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) if (!vm || !xe_vm_in_fault_mode(vm)) return -EINVAL; + if (vm->svm) { + ret = xe_svm_handle_gpu_fault(vm, gt, pf); + goto put_vm; + } + retry_userptr: /* * TODO: Avoid exclusive lock if VM doesn't have userptrs, or @@ -219,6 +225,7 @@ static int handle_pagefault(struct xe_gt *gt, struct pagefault *pf) if (ret >= 0) ret = 0; } +put_vm: xe_vm_put(vm); return ret; diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 0c13690a19f5..1ade8d7f0ab2 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -12,6 +12,7 @@ #include "xe_svm.h" #include #include +#include #include "xe_pt.h" #include "xe_assert.h" #include "xe_vm_types.h" @@ -206,3 +207,118 @@ static int svm_populate_range(struct xe_svm_range *svm_range, kvfree(pfns); return ret; } + +/** + * svm_access_allowed() - Determine whether read or/and write to vma is allowed + * + * @write: true means a read and write access; false: read only access + */ +static bool svm_access_allowed(struct vm_area_struct *vma, bool write) +{ + unsigned long access = VM_READ; + + if (write) + access |= VM_WRITE; + + return (vma->vm_flags & access) == access; +} + +/** + * svm_should_migrate() - Determine whether we should migrate a range to + * a destination memory region + * + * @range: The svm memory range to consider + * @dst_region: target destination memory region + * @is_atomic_fault: Is the intended migration triggered by a atomic access? + * On some platform, we have to migrate memory to guarantee atomic correctness. + */ +static bool svm_should_migrate(struct xe_svm_range *range, + struct xe_mem_region *dst_region, bool is_atomic_fault) +{ + return true; +} + +/** + * xe_svm_handle_gpu_fault() - gpu page fault handler for svm subsystem + * + * @vm: The vm of the fault. + * @gt: The gt hardware on which the fault happens. + * @pf: page fault descriptor + * + * Workout a backing memory for the fault address, migrate memory from + * system memory to gpu vram if nessary, and map the fault address to + * GPU so GPU HW can retry the last operation which has caused the GPU + * page fault. + */ +int xe_svm_handle_gpu_fault(struct xe_vm *vm, + struct xe_gt *gt, + struct pagefault *pf) +{ + u8 access_type = pf->access_type; + u64 page_addr = pf->page_addr; + struct hmm_range hmm_range; + struct vm_area_struct *vma; + struct xe_svm_range *range; + struct mm_struct *mm; + struct xe_svm *svm; + int ret = 0; + + svm = vm->svm; + if (!svm) + return -EINVAL; + + mm = svm->mm; + mmap_read_lock(mm); + vma = find_vma_intersection(mm, page_addr, page_addr + 4); + if (!vma) { + mmap_read_unlock(mm); + return -ENOENT; + } + + if (!svm_access_allowed (vma, access_type != ACCESS_TYPE_READ)) { + mmap_read_unlock(mm); + return -EPERM; + } + + range = xe_svm_range_from_addr(svm, page_addr); + if (!range) { + range = xe_svm_range_create(svm, vma); + if (!range) { + mmap_read_unlock(mm); + return -ENOMEM; + } + } + + if (svm_should_migrate(range, >->tile->mem.vram, + access_type == ACCESS_TYPE_ATOMIC)) +
[PATCH 17/23] drm/xe/svm: clean up svm range during process exit
Clean up svm range during process exit: Zap GPU page table of the svm process on process exit; unregister all the mmu interval notifiers which are registered before; free svm range and svm data structure. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.c | 24 drivers/gpu/drm/xe/xe_svm.h | 1 + drivers/gpu/drm/xe/xe_svm_range.c | 17 + 3 files changed, 42 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 6393251c0051..5772bfcf7da4 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -9,6 +9,8 @@ #include #include #include "xe_pt.h" +#include "xe_assert.h" +#include "xe_vm_types.h" DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); @@ -19,9 +21,31 @@ DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); */ void xe_destroy_svm(struct xe_svm *svm) { +#define MAX_SVM_RANGE (1024*1024) + struct xe_svm_range **range_array; + struct interval_tree_node *node; + struct xe_svm_range *range; + int i = 0; + + range_array = kzalloc(sizeof(struct xe_svm_range *) * MAX_SVM_RANGE, + GFP_KERNEL); + node = interval_tree_iter_first(&svm->range_tree, 0, ~0ULL); + while (node) { + range = container_of(node, struct xe_svm_range, inode); + xe_svm_range_prepare_destroy(range); + node = interval_tree_iter_next(node, 0, ~0ULL); + xe_assert(svm->vm->xe, i < MAX_SVM_RANGE); + range_array[i++] = range; + } + + /** Free range (thus range->inode) while traversing above is not safe */ + for(; i >= 0; i--) + kfree(range_array[i]); + hash_del_rcu(&svm->hnode); mutex_destroy(&svm->mutex); kfree(svm); + kfree(range_array); } /** diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 0038f98c0cc7..5b3bd2c064f5 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -90,6 +90,7 @@ bool xe_svm_range_belongs_to_vma(struct mm_struct *mm, struct vm_area_struct *vma); void xe_svm_range_unregister_mmu_notifier(struct xe_svm_range *range); int xe_svm_range_register_mmu_notifier(struct xe_svm_range *range); +void xe_svm_range_prepare_destroy(struct xe_svm_range *range); int xe_svm_build_sg(struct hmm_range *range, struct sg_table *st); int xe_svm_devm_add(struct xe_tile *tile, struct xe_mem_region *mem); diff --git a/drivers/gpu/drm/xe/xe_svm_range.c b/drivers/gpu/drm/xe/xe_svm_range.c index 53dd3be7ab9f..dfb4660dc26f 100644 --- a/drivers/gpu/drm/xe/xe_svm_range.c +++ b/drivers/gpu/drm/xe/xe_svm_range.c @@ -165,3 +165,20 @@ int xe_svm_range_register_mmu_notifier(struct xe_svm_range *range) range->mmu_notifier_registered = true; return ret; } + +/** + * xe_svm_range_prepare_destroy() - prepare work to destroy a svm range + * + * @range: the svm range to destroy + * + * prepare for a svm range destroy: Zap this range from GPU, unregister mmu + * notifier. + */ +void xe_svm_range_prepare_destroy(struct xe_svm_range *range) +{ + struct xe_vm *vm = range->svm->vm; + unsigned long length = range->end - range->start; + + xe_invalidate_svm_range(vm, range->start, length); + xe_svm_range_unregister_mmu_notifier(range); +} -- 2.26.3
[PATCH 19/23] drm/xe/svm: migrate svm range to vram
Since the source pages of the svm range can be physically none contiguous, and the destination vram pages can also be none contiguous, there is no easy way to migrate multiple pages per blitter command. We do page by page migration for now. Migration is best effort. Even if we fail to migrate some pages, we will try to migrate the rest pages. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.c | 7 ++ drivers/gpu/drm/xe/xe_svm.h | 3 + drivers/gpu/drm/xe/xe_svm_migrate.c | 114 3 files changed, 124 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 5772bfcf7da4..44d4f4216a93 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -5,12 +5,19 @@ #include #include +#include +#include +#include +#include #include "xe_svm.h" #include #include #include "xe_pt.h" #include "xe_assert.h" #include "xe_vm_types.h" +#include "xe_gt.h" +#include "xe_migrate.h" +#include "xe_trace.h" DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 5b3bd2c064f5..659bcb7927d6 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -80,6 +80,9 @@ struct xe_svm_range { }; vm_fault_t xe_devm_migrate_to_ram(struct vm_fault *vmf); +int svm_migrate_range_to_vram(struct xe_svm_range *range, + struct vm_area_struct *vma, + struct xe_tile *tile); void xe_destroy_svm(struct xe_svm *svm); struct xe_svm *xe_create_svm(struct xe_vm *vm); struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm); diff --git a/drivers/gpu/drm/xe/xe_svm_migrate.c b/drivers/gpu/drm/xe/xe_svm_migrate.c index b4df411e04f3..3724ad6c7aea 100644 --- a/drivers/gpu/drm/xe/xe_svm_migrate.c +++ b/drivers/gpu/drm/xe/xe_svm_migrate.c @@ -229,3 +229,117 @@ vm_fault_t xe_devm_migrate_to_ram(struct vm_fault *vmf) kvfree(buf); return 0; } + + +/** + * svm_migrate_range_to_vram() - migrate backing store of a va range to vram + * Must be called with mmap_read_lock(mm) held. + * @range: the va range to migrate. Range should only belong to one vma. + * @vma: the vma that this range belongs to. @range can cover whole @vma + * or a sub-range of @vma. + * @tile: the destination tile which holds the new backing store of the range + * + * Returns: negative errno on faiure, 0 on success + */ +int svm_migrate_range_to_vram(struct xe_svm_range *range, + struct vm_area_struct *vma, + struct xe_tile *tile) +{ + struct mm_struct *mm = range->svm->mm; + unsigned long start = range->start; + unsigned long end = range->end; + unsigned long npages = (end - start) >> PAGE_SHIFT; + struct xe_mem_region *mr = &tile->mem.vram; + struct migrate_vma migrate = { + .vma= vma, + .start = start, + .end= end, + .pgmap_owner= tile->xe->drm.dev, + .flags = MIGRATE_VMA_SELECT_SYSTEM, + }; + struct device *dev = tile->xe->drm.dev; + dma_addr_t *src_dma_addr; + struct dma_fence *fence; + struct page *src_page; + LIST_HEAD(blocks); + int ret = 0, i; + u64 dst_dpa; + void *buf; + + mmap_assert_locked(mm); + xe_assert(tile->xe, xe_svm_range_belongs_to_vma(mm, range, vma)); + + buf = kvcalloc(npages, 2* sizeof(*migrate.src) + sizeof(*src_dma_addr), + GFP_KERNEL); + if(!buf) + return -ENOMEM; + migrate.src = buf; + migrate.dst = migrate.src + npages; + src_dma_addr = (dma_addr_t *) (migrate.dst + npages); + ret = xe_devm_alloc_pages(tile, npages, &blocks, migrate.dst); + if (ret) + goto kfree_buf; + + ret = migrate_vma_setup(&migrate); + if (ret) { + drm_err(&tile->xe->drm, "vma setup returned %d for range [%lx - %lx]\n", + ret, start, end); + goto free_dst_pages; + } + + trace_xe_svm_migrate_sram_to_vram(range); + /**FIXME: partial migration of a range +* print a warning for now. If this message +* is printed, we need to fall back to page by page +* migration: only migrate pages with MIGRATE_PFN_MIGRATE +*/ + if (migrate.cpages != npages) + drm_warn(&tile->xe->drm, "Partial migration for range [%lx - %lx], range is %ld pages, migrate only %ld pages\n", + start, end, npages, migrate.cpages); + + /**Migrate page
[PATCH 11/23] drm/xe/svm: implement functions to allocate and free device memory
Function xe_devm_alloc_pages allocate pages from drm buddy and perform house keeping work for all the pages allocated, such as get a page refcount, keep a bitmap of all pages to denote whether a page is in use, put pages to a drm lru list for eviction purpose. Function xe_devm_free_blocks return all memory blocks to drm buddy allocator. Function xe_devm_free_page is a call back function from hmm layer. It is called whenever a page's refcount reaches to 1. This function clears the bit of this page in the bitmap. If all the bits in the bitmap is cleared, it means all the pages have been freed, we return all the pages in this memory block back to drm buddy. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.h| 9 ++ drivers/gpu/drm/xe/xe_svm_devmem.c | 146 - 2 files changed, 154 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index b54f7714a1fc..8551df2b9780 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -74,4 +74,13 @@ struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, int xe_svm_build_sg(struct hmm_range *range, struct sg_table *st); int xe_svm_devm_add(struct xe_tile *tile, struct xe_mem_region *mem); void xe_svm_devm_remove(struct xe_device *xe, struct xe_mem_region *mem); + + +int xe_devm_alloc_pages(struct xe_tile *tile, + unsigned long npages, + struct list_head *blocks, + unsigned long *pfn); + +void xe_devm_free_blocks(struct list_head *blocks); +void xe_devm_page_free(struct page *page); #endif diff --git a/drivers/gpu/drm/xe/xe_svm_devmem.c b/drivers/gpu/drm/xe/xe_svm_devmem.c index cf7882830247..445e0e1bc3b4 100644 --- a/drivers/gpu/drm/xe/xe_svm_devmem.c +++ b/drivers/gpu/drm/xe/xe_svm_devmem.c @@ -5,18 +5,162 @@ #include #include +#include +#include +#include +#include +#include +#include +#include #include "xe_device_types.h" #include "xe_trace.h" +#include "xe_migrate.h" +#include "xe_ttm_vram_mgr_types.h" +#include "xe_assert.h" +/** + * struct xe_svm_block_meta - svm uses this data structure to manage each + * block allocated from drm buddy. This will be set to the drm_buddy_block's + * private field. + * + * @lru: used to link this block to drm's lru lists. This will be replace + * with struct drm_lru_entity later. + * @tile: tile from which we allocated this block + * @bitmap: A bitmap of each page in this block. 1 means this page is used, + * 0 means this page is idle. When all bits of this block are 0, it is time + * to return this block to drm buddy subsystem. + */ +struct xe_svm_block_meta { + struct list_head lru; + struct xe_tile *tile; + unsigned long bitmap[]; +}; + +static u64 block_offset_to_pfn(struct xe_mem_region *mr, u64 offset) +{ + /** DRM buddy's block offset is 0-based*/ + offset += mr->hpa_base; + + return PHYS_PFN(offset); +} + +/** + * xe_devm_alloc_pages() - allocate device pages from buddy allocator + * + * @xe_tile: which tile to allocate device memory from + * @npages: how many pages to allocate + * @blocks: used to return the allocated blocks + * @pfn: used to return the pfn of all allocated pages. Must be big enough + * to hold at @npages entries. + * + * This function allocate blocks of memory from drm buddy allocator, and + * performs initialization work: set struct page::zone_device_data to point + * to the memory block; set/initialize drm_buddy_block::private field; + * lock_page for each page allocated; add memory block to lru managers lru + * list - this is TBD. + * + * return: 0 on success + * error code otherwise + */ +int xe_devm_alloc_pages(struct xe_tile *tile, + unsigned long npages, + struct list_head *blocks, + unsigned long *pfn) +{ + struct drm_buddy *mm = &tile->mem.vram_mgr->mm; + struct drm_buddy_block *block, *tmp; + u64 size = npages << PAGE_SHIFT; + int ret = 0, i, j = 0; + + ret = drm_buddy_alloc_blocks(mm, 0, mm->size, size, PAGE_SIZE, + blocks, DRM_BUDDY_TOPDOWN_ALLOCATION); + + if (unlikely(ret)) + return ret; + + list_for_each_entry_safe(block, tmp, blocks, link) { + struct xe_mem_region *mr = &tile->mem.vram; + u64 block_pfn_first, pages_per_block; + struct xe_svm_block_meta *meta; + u32 meta_size; + + size = drm_buddy_block_size(mm, block); + pages_per_block = size >> PAGE_SHIFT; + meta_size = BITS_TO_BYTES(pages_per_block)
[PATCH 20/23] drm/xe/svm: Populate svm range
Add a helper function svm_populate_range to populate a svm range. This functions calls hmm_range_fault to read CPU page tables and populate all pfns of this virtual address range into an array, saved in hmm_range:: hmm_pfns. This is prepare work to bind a svm range to GPU. The hmm_pfns array will be used for the GPU binding. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.c | 61 + 1 file changed, 61 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 44d4f4216a93..0c13690a19f5 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -145,3 +145,64 @@ int xe_svm_build_sg(struct hmm_range *range, sg_mark_end(sg); return 0; } + +/** Populate physical pages of a virtual address range + * This function also read mmu notifier sequence # ( + * mmu_interval_read_begin), for the purpose of later + * comparison (through mmu_interval_read_retry). + * This must be called with mmap read or write lock held. + * + * This function alloates hmm_range->hmm_pfns, it is caller's + * responsibility to free it. + * + * @svm_range: The svm range to populate + * @hmm_range: pointer to hmm_range struct. hmm_rang->hmm_pfns + * will hold the populated pfns. + * @write: populate pages with write permission + * + * returns: 0 for succuss; negative error no on failure + */ +static int svm_populate_range(struct xe_svm_range *svm_range, + struct hmm_range *hmm_range, bool write) +{ + unsigned long timeout = + jiffies + msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); + unsigned long *pfns, flags = HMM_PFN_REQ_FAULT; + u64 npages; + int ret; + + mmap_assert_locked(svm_range->svm->mm); + + npages = ((svm_range->end - 1) >> PAGE_SHIFT) - + (svm_range->start >> PAGE_SHIFT) + 1; + pfns = kvmalloc_array(npages, sizeof(*pfns), GFP_KERNEL); + if (unlikely(!pfns)) + return -ENOMEM; + + if (write) + flags |= HMM_PFN_REQ_WRITE; + + memset64((u64 *)pfns, (u64)flags, npages); + hmm_range->hmm_pfns = pfns; + hmm_range->notifier_seq = mmu_interval_read_begin(&svm_range->notifier); + hmm_range->notifier = &svm_range->notifier; + hmm_range->start = svm_range->start; + hmm_range->end = svm_range->end; + hmm_range->pfn_flags_mask = HMM_PFN_REQ_FAULT | HMM_PFN_REQ_WRITE; + hmm_range->dev_private_owner = svm_range->svm->vm->xe->drm.dev; + + while (true) { + ret = hmm_range_fault(hmm_range); + if (time_after(jiffies, timeout)) + goto free_pfns; + + if (ret == -EBUSY) + continue; + break; + } + +free_pfns: + if (ret) + kvfree(pfns); + return ret; +} -- 2.26.3
[PATCH 23/23] drm/xe/svm: Add svm memory hints interface
Signed-off-by: Oak Zeng --- include/uapi/drm/xe_drm.h | 40 +++ 1 file changed, 40 insertions(+) diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h index 50bbea0992d9..551ed8706097 100644 --- a/include/uapi/drm/xe_drm.h +++ b/include/uapi/drm/xe_drm.h @@ -80,6 +80,7 @@ extern "C" { * - &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY * - &DRM_IOCTL_XE_EXEC * - &DRM_IOCTL_XE_WAIT_USER_FENCE + * - &DRM_IOCTL_XE_SVM */ /* @@ -100,6 +101,7 @@ extern "C" { #define DRM_XE_EXEC_QUEUE_GET_PROPERTY 0x08 #define DRM_XE_EXEC0x09 #define DRM_XE_WAIT_USER_FENCE 0x0a +#define DRM_XE_SVM 0x0b /* Must be kept compact -- no holes */ #define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query) @@ -113,6 +115,7 @@ extern "C" { #define DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_GET_PROPERTY, struct drm_xe_exec_queue_get_property) #define DRM_IOCTL_XE_EXEC DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec) #define DRM_IOCTL_XE_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence) +#define DRM_IOCTL_XE_SVM DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_SVM, struct drm_xe_svm_args) /** * DOC: Xe IOCTL Extensions @@ -1339,6 +1342,43 @@ struct drm_xe_wait_user_fence { __u64 reserved[2]; }; +enum drm_xe_svm_attr_type { + DRM_XE_SVM_ATTR_PREFERRED_LOC, + DRM_XE_SVM_ATTR_MIGRATION_GRANULARITY, + DRM_XE_SVM_ATTR_ATOMIC, + DRM_XE_SVM_ATTR_CACHE, + DRM_XE_SVM_ATTR_PREFETCH_LOC, + DRM_XE_SVM_ATTR_ACCESS_PATTERN, +}; + +struct drm_xe_svm_attr { + __u32 type; + __u32 value; +}; + +enum drm_xe_svm_op { + DRM_XE_SVM_OP_SET_ATTR, + DRM_XE_SVM_OP_GET_ATTR, +}; + +/** + * struct drm_xe_svm_args - Input of &DRM_IOCTL_XE_SVM + * + * Set or get memory attributes to a virtual address range + */ +struct drm_xe_svm_args { + /** @start: start of the virtual address range */ + __u64 start; + /** @size: size of the virtual address range */ + __u64 size; + /** @op: operation, either set or get */ + __u32 op; + /** @nattr: number of attributes */ + __u32 nattr; + /** @attrs: An array of attributes */ + struct drm_xe_svm_attr attrs[]; +}; + #if defined(__cplusplus) } #endif -- 2.26.3
[PATCH 13/23] drm/xe/svm: Handle CPU page fault
Under the picture of svm, CPU and GPU program share one same virtual address space. The backing store of this virtual address space can be either in system memory or device memory. Since GPU device memory is remaped as DEVICE_PRIVATE, CPU can't access it. Any CPU access to device memory causes a page fault. Implement a page fault handler to migrate memory back to system memory and map it to CPU page table so the CPU program can proceed. Also unbind this page from GPU side, and free the original GPU device page Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_device_types.h | 12 ++ drivers/gpu/drm/xe/xe_svm.h | 8 +- drivers/gpu/drm/xe/xe_svm_devmem.c | 10 +- drivers/gpu/drm/xe/xe_svm_migrate.c | 230 +++ drivers/gpu/drm/xe/xe_svm_range.c| 27 5 files changed, 280 insertions(+), 7 deletions(-) create mode 100644 drivers/gpu/drm/xe/xe_svm_migrate.c diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 6dba5b0ab481..c08e41cb3229 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -573,4 +573,16 @@ struct xe_file { struct xe_drm_client *client; }; +static inline struct xe_tile *mem_region_to_tile(struct xe_mem_region *mr) +{ + return container_of(mr, struct xe_tile, mem.vram); +} + +static inline u64 vram_pfn_to_dpa(struct xe_mem_region *mr, u64 pfn) +{ + u64 dpa; + u64 offset = (pfn << PAGE_SHIFT) - mr->hpa_base; + dpa = mr->dpa_base + offset; + return dpa; +} #endif diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 8551df2b9780..6b93055934f8 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include "xe_device_types.h" struct xe_vm; @@ -66,16 +68,20 @@ struct xe_svm_range { struct interval_tree_node inode; }; +vm_fault_t xe_devm_migrate_to_ram(struct vm_fault *vmf); void xe_destroy_svm(struct xe_svm *svm); struct xe_svm *xe_create_svm(struct xe_vm *vm); struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm); struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, unsigned long addr); +bool xe_svm_range_belongs_to_vma(struct mm_struct *mm, + struct xe_svm_range *range, + struct vm_area_struct *vma); + int xe_svm_build_sg(struct hmm_range *range, struct sg_table *st); int xe_svm_devm_add(struct xe_tile *tile, struct xe_mem_region *mem); void xe_svm_devm_remove(struct xe_device *xe, struct xe_mem_region *mem); - int xe_devm_alloc_pages(struct xe_tile *tile, unsigned long npages, struct list_head *blocks, diff --git a/drivers/gpu/drm/xe/xe_svm_devmem.c b/drivers/gpu/drm/xe/xe_svm_devmem.c index 5cd54dde4a9d..01f8385ebb5b 100644 --- a/drivers/gpu/drm/xe/xe_svm_devmem.c +++ b/drivers/gpu/drm/xe/xe_svm_devmem.c @@ -11,13 +11,16 @@ #include #include #include +#include +#include #include - #include "xe_device_types.h" #include "xe_trace.h" #include "xe_migrate.h" #include "xe_ttm_vram_mgr_types.h" #include "xe_assert.h" +#include "xe_pt.h" +#include "xe_svm.h" /** * struct xe_svm_block_meta - svm uses this data structure to manage each @@ -137,11 +140,6 @@ void xe_devm_free_blocks(struct list_head *blocks) free_block(block); } -static vm_fault_t xe_devm_migrate_to_ram(struct vm_fault *vmf) -{ - return 0; -} - void xe_devm_page_free(struct page *page) { struct drm_buddy_block *block = diff --git a/drivers/gpu/drm/xe/xe_svm_migrate.c b/drivers/gpu/drm/xe/xe_svm_migrate.c new file mode 100644 index ..3be26da33aa3 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_svm_migrate.c @@ -0,0 +1,230 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "xe_device_types.h" +#include "xe_trace.h" +#include "xe_migrate.h" +#include "xe_ttm_vram_mgr_types.h" +#include "xe_assert.h" +#include "xe_pt.h" +#include "xe_svm.h" + + +/** + * alloc_host_page() - allocate one host page for the fault vma + * + * @dev: (GPU) device that will access the allocated page + * @vma: the fault vma that we need allocate page for + * @addr: the fault address. The allocated page is for this address + * @dma_addr: used to output the dma address of the allocated page. + * This dma address will be used for gpu to access this page. GPU + * access host page through a dma map
[PATCH 07/23] drm/xe/svm: Add helper for binding hmm range to gpu
Add helper function xe_bind_svm_range to bind a svm range to gpu. A temporary xe_vma is created locally to re-use existing page table update functions which are vma-based. The svm page table update lock design is different from userptr and bo page table update. A xe_pt_svm_pre_commit function is introduced for svm range pre-commitment. A hmm_range pointer is added to xe_vma struct. v1: Make userptr member to be the last member of xe_vma struct Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_pt.c | 114 +-- drivers/gpu/drm/xe/xe_pt.h | 4 ++ drivers/gpu/drm/xe/xe_vm_types.h | 13 +++- 3 files changed, 126 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index de1030a47588..f1e479fa3001 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -17,6 +17,7 @@ #include "xe_trace.h" #include "xe_ttm_stolen_mgr.h" #include "xe_vm.h" +#include "xe_svm.h" struct xe_pt_dir { struct xe_pt pt; @@ -582,8 +583,15 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma, { struct xe_device *xe = tile_to_xe(tile); struct xe_bo *bo = xe_vma_bo(vma); - bool is_devmem = !xe_vma_is_userptr(vma) && bo && - (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo)); + /* +* FIXME: Right now assume all svm ranges bound to GPU is backed +* by device memory. This assumption will change once migration +* policy is implemented. A svm range's backing store can be a +* mixture of device memory and system memory, page by page based. +* We probably need a separate stage_bind function for svm. +*/ + bool is_devmem = vma->svm_sg || (!xe_vma_is_userptr(vma) && bo && + (xe_bo_is_vram(bo) || xe_bo_is_stolen_devmem(bo))); struct xe_res_cursor curs; struct xe_pt_stage_bind_walk xe_walk = { .base = { @@ -617,7 +625,10 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma, xe_bo_assert_held(bo); if (!xe_vma_is_null(vma)) { - if (xe_vma_is_userptr(vma)) + if (vma->svm_sg) + xe_res_first_sg(vma->svm_sg, 0, xe_vma_size(vma), + &curs); + else if (xe_vma_is_userptr(vma)) xe_res_first_sg(vma->userptr.sg, 0, xe_vma_size(vma), &curs); else if (xe_bo_is_vram(bo) || xe_bo_is_stolen(bo)) @@ -1046,6 +1057,28 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update) return 0; } +static int xe_pt_svm_pre_commit(struct xe_migrate_pt_update *pt_update) +{ + struct xe_vma *vma = pt_update->vma; + struct hmm_range *range = vma->hmm_range; + + if (mmu_interval_read_retry(range->notifier, + range->notifier_seq)) { + /* +* FIXME: is this really necessary? We didn't update GPU +* page table yet... +*/ + xe_vm_invalidate_vma(vma); + return -EAGAIN; + } + return 0; +} + +static const struct xe_migrate_pt_update_ops svm_bind_ops = { + .populate = xe_vm_populate_pgtable, + .pre_commit = xe_pt_svm_pre_commit, +}; + static const struct xe_migrate_pt_update_ops bind_ops = { .populate = xe_vm_populate_pgtable, .pre_commit = xe_pt_pre_commit, @@ -1197,7 +1230,8 @@ __xe_pt_bind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queue struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1]; struct xe_pt_migrate_pt_update bind_pt_update = { .base = { - .ops = xe_vma_is_userptr(vma) ? &userptr_bind_ops : &bind_ops, + .ops = vma->svm_sg ? &svm_bind_ops : + (xe_vma_is_userptr(vma) ? &userptr_bind_ops : &bind_ops), .vma = vma, .tile_id = tile->id, }, @@ -1651,3 +1685,75 @@ __xe_pt_unbind_vma(struct xe_tile *tile, struct xe_vma *vma, struct xe_exec_queu return fence; } + +/** + * xe_bind_svm_range() - bind an address range to vm + * + * @vm: the vm to bind this address range + * @tile: the tile to bind this address range to + * @range: a hmm_range which includes all the information + * needed for binding: virtual address range and physical + * pfns to back up this virtual address range. + * @flags: the binding flags to set in pte + * + * This is a helper function used by svm sub-system + * to bind a svm range to gpu vm. svm sub-system + * doesn't have xe_vma, thus helpers such as + * __xe_pt_bind_vma can't be used directly. So this + * helper is written for svm sub-system to use. + * + * This is a synchronous function. When t
[PATCH 02/23] drm/xe/svm: Add svm key data structures
Add xe_svm and xe_svm_range data structure. Each xe_svm represents a svm address space and it maps 1:1 to the process's mm_struct. It also maps 1:1 to the gpu xe_vm struct. Each xe_svm_range represent a virtual address range inside a svm address space. It is similar to CPU's vm_area_struct, or to the GPU xe_vma struct. It contains data to synchronize this address range to CPU's virtual address range, using mmu notifier mechanism. It can also hold this range's memory attributes set by user, such as preferred memory location etc - this is TBD. Each svm address space is made of many svm virtual address range. All address ranges are maintained in xe_svm's interval tree. Also add a xe_svm pointer to xe_vm data structure. So we have a 1:1 mapping b/t xe_svm and xe_vm. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.h | 59 drivers/gpu/drm/xe/xe_vm_types.h | 2 ++ 2 files changed, 61 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_svm.h diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h new file mode 100644 index ..ba301a331f59 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef __XE_SVM_H +#define __XE_SVM_H +#include +#include +#include +#include +#include +#include + +struct xe_vm; +struct mm_struct; + +/** + * struct xe_svm - data structure to represent a shared + * virtual address space from device side. xe_svm, xe_vm + * and mm_struct has a 1:1:1 relationship. + */ +struct xe_svm { + /** @vm: The xe_vm address space corresponding to this xe_svm */ + struct xe_vm *vm; + /** @mm: The mm_struct corresponding to this xe_svm */ + struct mm_struct *mm; + /** +* @mutex: A lock used by svm subsystem. It protects: +* 1. below range_tree +* 2. GPU page table update. Serialize all SVM GPU page table updates +*/ + struct mutex mutex; + /** +* @range_tree: Interval tree of all svm ranges in this svm +*/ + struct rb_root_cached range_tree; +}; + +/** + * struct xe_svm_range - Represents a shared virtual address range. + */ +struct xe_svm_range { + /** @notifier: The mmu interval notifer used to keep track of CPU +* side address range change. Driver will get a callback with this +* notifier if anything changed from CPU side, such as range is +* unmapped from CPU +*/ + struct mmu_interval_notifier notifier; + /** @start: start address of this range, inclusive */ + u64 start; + /** @end: end address of this range, exclusive */ + u64 end; + /** @unregister_notifier_work: A worker used to unregister this notifier */ + struct work_struct unregister_notifier_work; + /** @inode: used to link this range to svm's range_tree */ + struct interval_tree_node inode; +}; +#endif diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h index 63e8a50b88e9..037fb7168c63 100644 --- a/drivers/gpu/drm/xe/xe_vm_types.h +++ b/drivers/gpu/drm/xe/xe_vm_types.h @@ -17,6 +17,7 @@ #include "xe_pt_types.h" #include "xe_range_fence.h" +struct xe_svm; struct xe_bo; struct xe_sync_entry; struct xe_vm; @@ -279,6 +280,7 @@ struct xe_vm { bool batch_invalidate_tlb; /** @xef: XE file handle for tracking this VM's drm client */ struct xe_file *xef; + struct xe_svm *svm; }; /** struct xe_vma_op_map - VMA map operation */ -- 2.26.3
[PATCH 22/23] drm/xe/svm: Add DRM_XE_SVM kernel config entry
DRM_XE_SVM kernel config entry is added so xe svm feature can be configured before kernel compilation. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/Kconfig | 22 ++ drivers/gpu/drm/xe/Makefile | 5 + drivers/gpu/drm/xe/xe_mmio.c | 5 + drivers/gpu/drm/xe/xe_vm.c | 2 ++ 4 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/xe/Kconfig b/drivers/gpu/drm/xe/Kconfig index 1b57ae38210d..6f498095a915 100644 --- a/drivers/gpu/drm/xe/Kconfig +++ b/drivers/gpu/drm/xe/Kconfig @@ -83,6 +83,28 @@ config DRM_XE_FORCE_PROBE Use "!*" to block the probe of the driver for all known devices. +config DRM_XE_SVM +bool "Enable Shared Virtual Memory support in xe" +depends on DRM_XE +depends on ARCH_ENABLE_MEMORY_HOTPLUG +depends on ARCH_ENABLE_MEMORY_HOTREMOVE +depends on MEMORY_HOTPLUG +depends on MEMORY_HOTREMOVE +depends on ARCH_HAS_PTE_DEVMAP +depends on SPARSEMEM_VMEMMAP +depends on ZONE_DEVICE +depends on DEVICE_PRIVATE +depends on MMU +select HMM_MIRROR +select MMU_NOTIFIER +default y +help + Choose this option if you want Shared Virtual Memory (SVM) + support in xe. With SVM, virtual address space is shared + between CPU and GPU. This means any virtual address such + as malloc or mmap returns, variables on stack, or global + memory pointers, can be used for GPU transparently. + menu "drm/Xe Debugging" depends on DRM_XE depends on EXPERT diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index e16b84f79ddf..ae503f7c1f94 100644 --- a/drivers/gpu/drm/xe/Makefile +++ b/drivers/gpu/drm/xe/Makefile @@ -283,6 +283,11 @@ xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/skl_universal_plane.o \ i915-display/skl_watermark.o +xe-$(CONFIG_DRM_XE_SVM) += xe_svm.o \ + xe_svm_devmem.o \ + xe_svm_range.o \ + xe_svm_migrate.o + ifeq ($(CONFIG_ACPI),y) xe-$(CONFIG_DRM_XE_DISPLAY) += \ i915-display/intel_acpi.o \ diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index 3d34dcfa3b3a..99810794bd94 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -286,7 +286,9 @@ int xe_mmio_probe_vram(struct xe_device *xe) } io_size -= min_t(u64, tile_size, io_size); +#if IS_ENABLED(CONFIG_DRM_XE_SVM) xe_svm_devm_add(tile, &tile->mem.vram); +#endif } xe->mem.vram.actual_physical_size = total_size; @@ -361,8 +363,11 @@ static void mmio_fini(struct drm_device *drm, void *arg) pci_iounmap(to_pci_dev(xe->drm.dev), xe->mmio.regs); if (xe->mem.vram.mapping) iounmap(xe->mem.vram.mapping); + +#if IS_ENABLED(CONFIG_DRM_XE_SVM) for_each_tile(tile, xe, id) { xe_svm_devm_remove(xe, &tile->mem.vram); +#endif } } diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index 712fe49d8fb2..3bf19c92e01f 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -1377,7 +1377,9 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) xe->usm.num_vm_in_non_fault_mode++; mutex_unlock(&xe->usm.lock); +#if IS_ENABLED(CONFIG_DRM_XE_SVM) vm->svm = xe_create_svm(vm); +#endif trace_xe_vm_create(vm); return vm; -- 2.26.3
[PATCH 12/23] drm/xe/svm: Trace buddy block allocation and free
Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm_devmem.c | 5 - drivers/gpu/drm/xe/xe_trace.h | 35 ++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_svm_devmem.c b/drivers/gpu/drm/xe/xe_svm_devmem.c index 445e0e1bc3b4..5cd54dde4a9d 100644 --- a/drivers/gpu/drm/xe/xe_svm_devmem.c +++ b/drivers/gpu/drm/xe/xe_svm_devmem.c @@ -95,6 +95,7 @@ int xe_devm_alloc_pages(struct xe_tile *tile, block->private = meta; block_pfn_first = block_offset_to_pfn(mr, drm_buddy_block_offset(block)); + trace_xe_buddy_block_alloc(block, size, block_pfn_first); for(i = 0; i < pages_per_block; i++) { struct page *page; @@ -159,8 +160,10 @@ void xe_devm_page_free(struct page *page) xe_assert(tile->xe, i < pages_per_block); clear_bit(i, meta->bitmap); - if (bitmap_empty(meta->bitmap, pages_per_block)) + if (bitmap_empty(meta->bitmap, pages_per_block)) { free_block(block); + trace_xe_buddy_block_free(block, size, block_pfn_first); + } } static const struct dev_pagemap_ops xe_devm_pagemap_ops = { diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h index 63867c0fa848..50380f5173ca 100644 --- a/drivers/gpu/drm/xe/xe_trace.h +++ b/drivers/gpu/drm/xe/xe_trace.h @@ -11,6 +11,7 @@ #include #include +#include #include "xe_bo_types.h" #include "xe_exec_queue_types.h" @@ -600,6 +601,40 @@ DEFINE_EVENT_PRINT(xe_guc_ctb, xe_guc_ctb_g2h, ); +DECLARE_EVENT_CLASS(xe_buddy_block, + TP_PROTO(struct drm_buddy_block *block, u64 size, u64 pfn), + TP_ARGS(block, size, pfn), + + TP_STRUCT__entry( + __field(u64, block) + __field(u64, header) + __field(u64, size) + __field(u64, pfn) + ), + + TP_fast_assign( + __entry->block = (u64)block; + __entry->header = block->header; + __entry->size = size; + __entry->pfn = pfn; + ), + + TP_printk("xe svm: allocated block %llx, block header %llx, size %llx, pfn %llx\n", + __entry->block, __entry->header, __entry->size, __entry->pfn) +); + + +DEFINE_EVENT(xe_buddy_block, xe_buddy_block_alloc, + TP_PROTO(struct drm_buddy_block *block, u64 size, u64 pfn), + TP_ARGS(block, size, pfn) +); + + +DEFINE_EVENT(xe_buddy_block, xe_buddy_block_free, + TP_PROTO(struct drm_buddy_block *block, u64 size, u64 pfn), + TP_ARGS(block, size, pfn) +); + #endif /* This part must be outside protection */ -- 2.26.3
[PATCH 16/23] drm/xe/svm: Implement the mmu notifier range invalidate callback
To mirror the CPU page table from GPU side, we register a mmu interval notifier (in the coming patch of this series). Core mm call back to GPU driver whenever there is a change to certain virtual address range, i.e., range is released or unmapped by user etc. This patch implemented the GPU driver callback function for such mmu interval notifier. In the callback function we unbind the address range from GPU if it is unmapped from CPU side, thus we mirror the CPU page table change. We also unregister the mmu interval notifier from core mm in the case of munmap event. But we can't unregister mmu notifier directly from the mmu notifier range invalidation callback function. The reason is, during a munmap (see kernel function vm_munmap), a mmap_write_lock is held, but unregister mmu notifier (calling mmu_interval_notifier_remove) also requires a mmap_write_lock of the current process. Thus, we start a kernel worker to unregister mmu interval notifier on a MMU_NOTIFY_UNMAP event. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.c | 1 + drivers/gpu/drm/xe/xe_svm.h | 1 - drivers/gpu/drm/xe/xe_svm_range.c | 37 ++- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index ab3cc2121869..6393251c0051 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -8,6 +8,7 @@ #include "xe_svm.h" #include #include +#include "xe_pt.h" DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 90e665f2bfc6..0038f98c0cc7 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -54,7 +54,6 @@ struct xe_svm { struct xe_svm_range { /** @svm: pointer of the xe_svm that this range belongs to */ struct xe_svm *svm; - /** @notifier: The mmu interval notifer used to keep track of CPU * side address range change. Driver will get a callback with this * notifier if anything changed from CPU side, such as range is diff --git a/drivers/gpu/drm/xe/xe_svm_range.c b/drivers/gpu/drm/xe/xe_svm_range.c index 286d5f7d6ecd..53dd3be7ab9f 100644 --- a/drivers/gpu/drm/xe/xe_svm_range.c +++ b/drivers/gpu/drm/xe/xe_svm_range.c @@ -10,6 +10,7 @@ #include #include #include "xe_svm.h" +#include "xe_pt.h" /** * xe_svm_range_from_addr() - retrieve svm_range contains a virtual address @@ -59,8 +60,42 @@ bool xe_svm_range_belongs_to_vma(struct mm_struct *mm, return (vma1 == vma) && (vma2 == vma); } +static bool xe_svm_range_invalidate(struct mmu_interval_notifier *mni, + const struct mmu_notifier_range *range, + unsigned long cur_seq) +{ + struct xe_svm_range *svm_range = + container_of(mni, struct xe_svm_range, notifier); + struct xe_svm *svm = svm_range->svm; + unsigned long length = range->end - range->start; + + /* +* MMU_NOTIFY_RELEASE is called upon process exit to notify driver +* to release any process resources, such as zap GPU page table +* mapping or unregister mmu notifier etc. We already clear GPU +* page table and unregister mmu notifier in in xe_destroy_svm, +* upon process exit. So just simply return here. +*/ + if (range->event == MMU_NOTIFY_RELEASE) + return true; + + if (mmu_notifier_range_blockable(range)) + mutex_lock(&svm->mutex); + else if (!mutex_trylock(&svm->mutex)) + return false; + + mmu_interval_set_seq(mni, cur_seq); + xe_invalidate_svm_range(svm->vm, range->start, length); + mutex_unlock(&svm->mutex); + + if (range->event == MMU_NOTIFY_UNMAP) + queue_work(system_unbound_wq, &svm_range->unregister_notifier_work); + + return true; +} + static const struct mmu_interval_notifier_ops xe_svm_mni_ops = { - .invalidate = NULL, + .invalidate = xe_svm_range_invalidate, }; /** -- 2.26.3
[PATCH 15/23] drm/xe/svm: Implement functions to register and unregister mmu notifier
xe driver register mmu interval notifier to core mm to monitor vma change. We register mmu interval notifier for each svm range. mmu interval notifier should be unregistered in a worker (see next patch in this series), so also initialize kernel worker to unregister mmu interval notifier. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.h | 14 ++ drivers/gpu/drm/xe/xe_svm_range.c | 73 +++ 2 files changed, 87 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 6b93055934f8..90e665f2bfc6 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -52,16 +52,28 @@ struct xe_svm { * struct xe_svm_range - Represents a shared virtual address range. */ struct xe_svm_range { + /** @svm: pointer of the xe_svm that this range belongs to */ + struct xe_svm *svm; + /** @notifier: The mmu interval notifer used to keep track of CPU * side address range change. Driver will get a callback with this * notifier if anything changed from CPU side, such as range is * unmapped from CPU */ struct mmu_interval_notifier notifier; + bool mmu_notifier_registered; /** @start: start address of this range, inclusive */ u64 start; /** @end: end address of this range, exclusive */ u64 end; + /** @vma: the corresponding vma of this svm range +* The relationship b/t vma and svm range is 1:N, +* which means one vma can be splitted into multiple +* @xe_svm_range while one @xe_svm_range can have +* only one vma. A N:N mapping means some complication +* in codes. Lets assume 1:N for now. +*/ + struct vm_area_struct *vma; /** @unregister_notifier_work: A worker used to unregister this notifier */ struct work_struct unregister_notifier_work; /** @inode: used to link this range to svm's range_tree */ @@ -77,6 +89,8 @@ struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, bool xe_svm_range_belongs_to_vma(struct mm_struct *mm, struct xe_svm_range *range, struct vm_area_struct *vma); +void xe_svm_range_unregister_mmu_notifier(struct xe_svm_range *range); +int xe_svm_range_register_mmu_notifier(struct xe_svm_range *range); int xe_svm_build_sg(struct hmm_range *range, struct sg_table *st); int xe_svm_devm_add(struct xe_tile *tile, struct xe_mem_region *mem); diff --git a/drivers/gpu/drm/xe/xe_svm_range.c b/drivers/gpu/drm/xe/xe_svm_range.c index b32c32f60315..286d5f7d6ecd 100644 --- a/drivers/gpu/drm/xe/xe_svm_range.c +++ b/drivers/gpu/drm/xe/xe_svm_range.c @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -57,3 +58,75 @@ bool xe_svm_range_belongs_to_vma(struct mm_struct *mm, return (vma1 == vma) && (vma2 == vma); } + +static const struct mmu_interval_notifier_ops xe_svm_mni_ops = { + .invalidate = NULL, +}; + +/** + * unregister a mmu interval notifier for a svm range + * + * @range: svm range + * + */ +void xe_svm_range_unregister_mmu_notifier(struct xe_svm_range *range) +{ + if (!range->mmu_notifier_registered) + return; + + mmu_interval_notifier_remove(&range->notifier); + range->mmu_notifier_registered = false; +} + +static void xe_svm_unregister_notifier_work(struct work_struct *work) +{ + struct xe_svm_range *range; + + range = container_of(work, struct xe_svm_range, unregister_notifier_work); + + xe_svm_range_unregister_mmu_notifier(range); + + /** +* This is called from mmu notifier MUNMAP event. When munmap is called, +* this range is not valid any more. Remove it. +*/ + mutex_lock(&range->svm->mutex); + interval_tree_remove(&range->inode, &range->svm->range_tree); + mutex_unlock(&range->svm->mutex); + kfree(range); +} + +/** + * register a mmu interval notifier to monitor vma change + * + * @range: svm range to monitor + * + * This has to be called inside a mmap_read_lock + */ +int xe_svm_range_register_mmu_notifier(struct xe_svm_range *range) +{ + struct vm_area_struct *vma = range->vma; + struct mm_struct *mm = range->svm->mm; + u64 start, length; + int ret = 0; + + if (range->mmu_notifier_registered) + return 0; + + start = range->start; + length = range->end - start; + /** We are inside a mmap_read_lock, but it requires a mmap_write_lock +* to register mmu notifier. +*/ + mmap_read_unlock(mm); + mmap_write_lock(mm); + ret = mmu_interval_notifier_insert_locked(&range->notifier, vma->vm_mm, + start, length, &xe_svm_mni_
[PATCH 18/23] drm/xe/svm: Move a few structures to xe_gt.h
Move access_type and pagefault struct to header file so it can be shared with svm sub-system. This is preparation work for enabling page fault for svm. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_gt.h | 20 drivers/gpu/drm/xe/xe_gt_pagefault.c | 21 - 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_gt.h b/drivers/gpu/drm/xe/xe_gt.h index 4486e083f5ef..51dd288cf1cf 100644 --- a/drivers/gpu/drm/xe/xe_gt.h +++ b/drivers/gpu/drm/xe/xe_gt.h @@ -17,6 +17,26 @@ xe_hw_engine_is_valid((hwe__))) #define CCS_MASK(gt) (((gt)->info.engine_mask & XE_HW_ENGINE_CCS_MASK) >> XE_HW_ENGINE_CCS0) +enum access_type { + ACCESS_TYPE_READ = 0, + ACCESS_TYPE_WRITE = 1, + ACCESS_TYPE_ATOMIC = 2, + ACCESS_TYPE_RESERVED = 3, +}; + +struct pagefault { + u64 page_addr; + u32 asid; + u16 pdata; + u8 vfid; + u8 access_type; + u8 fault_type; + u8 fault_level; + u8 engine_class; + u8 engine_instance; + u8 fault_unsuccessful; + bool trva_fault; +}; #ifdef CONFIG_FAULT_INJECTION #include /* XXX: fault-inject.h is broken */ diff --git a/drivers/gpu/drm/xe/xe_gt_pagefault.c b/drivers/gpu/drm/xe/xe_gt_pagefault.c index 5c2603075af9..467d68f8332e 100644 --- a/drivers/gpu/drm/xe/xe_gt_pagefault.c +++ b/drivers/gpu/drm/xe/xe_gt_pagefault.c @@ -23,27 +23,6 @@ #include "xe_trace.h" #include "xe_vm.h" -struct pagefault { - u64 page_addr; - u32 asid; - u16 pdata; - u8 vfid; - u8 access_type; - u8 fault_type; - u8 fault_level; - u8 engine_class; - u8 engine_instance; - u8 fault_unsuccessful; - bool trva_fault; -}; - -enum access_type { - ACCESS_TYPE_READ = 0, - ACCESS_TYPE_WRITE = 1, - ACCESS_TYPE_ATOMIC = 2, - ACCESS_TYPE_RESERVED = 3, -}; - enum fault_type { NOT_PRESENT = 0, WRITE_ACCESS_VIOLATION = 1, -- 2.26.3
[PATCH 14/23] drm/xe/svm: trace svm range migration
Add function to trace svm range migration, either from vram to sram, or sram to vram Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm_migrate.c | 1 + drivers/gpu/drm/xe/xe_trace.h | 30 + 2 files changed, 31 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm_migrate.c b/drivers/gpu/drm/xe/xe_svm_migrate.c index 3be26da33aa3..b4df411e04f3 100644 --- a/drivers/gpu/drm/xe/xe_svm_migrate.c +++ b/drivers/gpu/drm/xe/xe_svm_migrate.c @@ -201,6 +201,7 @@ vm_fault_t xe_devm_migrate_to_ram(struct vm_fault *vmf) if (!migrate_vma.cpages) goto free_buf; + trace_xe_svm_migrate_vram_to_sram(range); for (i = 0; i < npages; i++) { ret = migrate_page_vram_to_ram(vma, addr, migrate_vma.src[i], migrate_vma.dst + i); diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h index 50380f5173ca..960eec38aee5 100644 --- a/drivers/gpu/drm/xe/xe_trace.h +++ b/drivers/gpu/drm/xe/xe_trace.h @@ -21,6 +21,7 @@ #include "xe_guc_exec_queue_types.h" #include "xe_sched_job.h" #include "xe_vm.h" +#include "xe_svm.h" DECLARE_EVENT_CLASS(xe_gt_tlb_invalidation_fence, TP_PROTO(struct xe_gt_tlb_invalidation_fence *fence), @@ -601,6 +602,35 @@ DEFINE_EVENT_PRINT(xe_guc_ctb, xe_guc_ctb_g2h, ); +DECLARE_EVENT_CLASS(xe_svm_migrate, + TP_PROTO(struct xe_svm_range *range), + TP_ARGS(range), + + TP_STRUCT__entry( +__field(u64, start) +__field(u64, end) +), + + TP_fast_assign( + __entry->start = range->start; + __entry->end = range->end; + ), + + TP_printk("Migrate svm range [0x%016llx,0x%016llx)", __entry->start, + __entry->end) +); + +DEFINE_EVENT(xe_svm_migrate, xe_svm_migrate_vram_to_sram, + TP_PROTO(struct xe_svm_range *range), + TP_ARGS(range) +); + + +DEFINE_EVENT(xe_svm_migrate, xe_svm_migrate_sram_to_vram, + TP_PROTO(struct xe_svm_range *range), + TP_ARGS(range) +); + DECLARE_EVENT_CLASS(xe_buddy_block, TP_PROTO(struct drm_buddy_block *block, u64 size, u64 pfn), TP_ARGS(block, size, pfn), -- 2.26.3
[PATCH 10/23] drm/xe/svm: Introduce svm migration function
Introduce xe_migrate_svm function for data migration. This function is similar to xe_migrate_copy function but has different parameters. Instead of BO and ttm resource parameters, it has source and destination buffer's dpa address as parameter. This function is intended to be used by svm sub-system which doesn't have BO and TTM concept. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_migrate.c | 213 drivers/gpu/drm/xe/xe_migrate.h | 7 ++ 2 files changed, 220 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c index 44725f978f3e..5bd9fd40f93f 100644 --- a/drivers/gpu/drm/xe/xe_migrate.c +++ b/drivers/gpu/drm/xe/xe_migrate.c @@ -429,6 +429,37 @@ static bool xe_migrate_allow_identity(u64 size, const struct xe_res_cursor *cur) return cur->size >= size; } +/** + * pte_update_cmd_size() - calculate the batch buffer command size + * to update a flat page table. + * + * @size: The virtual address range size of the page table to update + * + * The page table to update is supposed to be a flat 1 level page + * table with all entries pointing to 4k pages. + * + * Return the number of dwords of the update command + */ +static u32 pte_update_cmd_size(u64 size) +{ + u32 dword; + u64 entries = DIV_ROUND_UP(size, XE_PAGE_SIZE); + + XE_WARN_ON(size > MAX_PREEMPTDISABLE_TRANSFER); + /* +* MI_STORE_DATA_IMM command is used to update page table. Each +* instruction can update maximumly 0x1ff pte entries. To update +* n (n <= 0x1ff) pte entries, we need: +* 1 dword for the MI_STORE_DATA_IMM command header (opcode etc) +* 2 dword for the page table's physical location +* 2*n dword for value of pte to fill (each pte entry is 2 dwords) +*/ + dword = (1 + 2) * DIV_ROUND_UP(entries, 0x1ff); + dword += entries * 2; + + return dword; +} + static u32 pte_update_size(struct xe_migrate *m, bool is_vram, struct ttm_resource *res, @@ -529,6 +560,48 @@ static void emit_pte(struct xe_migrate *m, } } +/** + * build_pt_update_batch_sram() - build batch buffer commands to update + * migration vm page table for system memory + * + * @m: The migration context + * @bb: The batch buffer which hold the page table update commands + * @pt_offset: The offset of page table to update, in byte + * @dpa: device physical address you want the page table to point to + * @size: size of the virtual address space you want the page table to cover + */ +static void build_pt_update_batch_sram(struct xe_migrate *m, +struct xe_bb *bb, u32 pt_offset, +u64 dpa, u32 size) +{ + u16 pat_index = tile_to_xe(m->tile)->pat.idx[XE_CACHE_WB]; + u32 ptes; + + ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE); + while (ptes) { + u32 chunk = min(0x1ffU, ptes); + + bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_NUM_QW(chunk); + bb->cs[bb->len++] = pt_offset; + bb->cs[bb->len++] = 0; + + pt_offset += chunk * 8; + ptes -= chunk; + + while (chunk--) { + u64 addr; + + addr = dpa & PAGE_MASK; + addr = m->q->vm->pt_ops->pte_encode_addr(m->tile->xe, +addr, pat_index, +0, false, 0); + bb->cs[bb->len++] = lower_32_bits(addr); + bb->cs[bb->len++] = upper_32_bits(addr); + dpa += XE_PAGE_SIZE; + } + } +} + #define EMIT_COPY_CCS_DW 5 static void emit_copy_ccs(struct xe_gt *gt, struct xe_bb *bb, u64 dst_ofs, bool dst_is_indirect, @@ -846,6 +919,146 @@ struct dma_fence *xe_migrate_copy(struct xe_migrate *m, return fence; } +/** + * xe_migrate_svm() - A migrate function used by SVM subsystem + * + * @m: The migration context + * @src_dpa: device physical start address of source, from GPU's point of view + * @src_is_vram: True if source buffer is in vram. + * @dst_dpa: device physical start address of destination, from GPU's point of view + * @dst_is_vram: True if destination buffer is in vram. + * @size: The size of data to copy. + * + * Copy @size bytes of data from @src_dpa to @dst_dpa. The functionality + * and behavior of this function is similar to xe_migrate_copy function, but + * the interface is different. This function is a helper function supposed to + * be used by SVM subsytem. Since in SVM subsystem there is no buffer object + * and ttm, there is no src/dst bo as function input. Instead, we directly use + * src/dst's physical address as function input. + * + * Since the back sto
[PATCH 09/23] drm/xe/svm: Remap and provide memmap backing for GPU vram
Memory remap GPU vram using devm_memremap_pages, so each GPU vram page is backed by a struct page. Those struct pages are created to allow hmm migrate buffer b/t GPU vram and CPU system memory using existing Linux migration mechanism (i.e., migrating b/t CPU system memory and hard disk). This is prepare work to enable svm (shared virtual memory) through Linux kernel hmm framework. The memory remap's page map type is set to MEMORY_DEVICE_PRIVATE for now. This means even though each GPU vram page get a struct page and can be mapped in CPU page table, but such pages are treated as GPU's private resource, so CPU can't access them. If CPU access such page, a page fault is triggered and page will be migrate to system memory. For GPU device which supports coherent memory protocol b/t CPU and GPU (such as CXL and CAPI protocol), we can remap device memory as MEMORY_DEVICE_COHERENT. This is TBD. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_device_types.h | 8 +++ drivers/gpu/drm/xe/xe_mmio.c | 7 +++ drivers/gpu/drm/xe/xe_svm.h | 2 + drivers/gpu/drm/xe/xe_svm_devmem.c | 87 4 files changed, 104 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_svm_devmem.c diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h index 7eda86bd4c2a..6dba5b0ab481 100644 --- a/drivers/gpu/drm/xe/xe_device_types.h +++ b/drivers/gpu/drm/xe/xe_device_types.h @@ -99,6 +99,14 @@ struct xe_mem_region { resource_size_t actual_physical_size; /** @mapping: pointer to VRAM mappable space */ void __iomem *mapping; + /** @pagemap: Used to remap device memory as ZONE_DEVICE */ + struct dev_pagemap pagemap; + /** +* @hpa_base: base host physical address +* +* This is generated when remap device memory as ZONE_DEVICE +*/ + resource_size_t hpa_base; }; /** diff --git a/drivers/gpu/drm/xe/xe_mmio.c b/drivers/gpu/drm/xe/xe_mmio.c index c8c5d74b6e90..3d34dcfa3b3a 100644 --- a/drivers/gpu/drm/xe/xe_mmio.c +++ b/drivers/gpu/drm/xe/xe_mmio.c @@ -21,6 +21,7 @@ #include "xe_macros.h" #include "xe_module.h" #include "xe_tile.h" +#include "xe_svm.h" #define XEHP_MTCFG_ADDRXE_REG(0x101800) #define TILE_COUNT REG_GENMASK(15, 8) @@ -285,6 +286,7 @@ int xe_mmio_probe_vram(struct xe_device *xe) } io_size -= min_t(u64, tile_size, io_size); + xe_svm_devm_add(tile, &tile->mem.vram); } xe->mem.vram.actual_physical_size = total_size; @@ -353,10 +355,15 @@ void xe_mmio_probe_tiles(struct xe_device *xe) static void mmio_fini(struct drm_device *drm, void *arg) { struct xe_device *xe = arg; + struct xe_tile *tile; + u8 id; pci_iounmap(to_pci_dev(xe->drm.dev), xe->mmio.regs); if (xe->mem.vram.mapping) iounmap(xe->mem.vram.mapping); + for_each_tile(tile, xe, id) { + xe_svm_devm_remove(xe, &tile->mem.vram); + } } static int xe_verify_lmem_ready(struct xe_device *xe) diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 191bce6425db..b54f7714a1fc 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -72,4 +72,6 @@ struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm); struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, unsigned long addr); int xe_svm_build_sg(struct hmm_range *range, struct sg_table *st); +int xe_svm_devm_add(struct xe_tile *tile, struct xe_mem_region *mem); +void xe_svm_devm_remove(struct xe_device *xe, struct xe_mem_region *mem); #endif diff --git a/drivers/gpu/drm/xe/xe_svm_devmem.c b/drivers/gpu/drm/xe/xe_svm_devmem.c new file mode 100644 index ..cf7882830247 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_svm_devmem.c @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include + +#include "xe_device_types.h" +#include "xe_trace.h" + + +static vm_fault_t xe_devm_migrate_to_ram(struct vm_fault *vmf) +{ + return 0; +} + +static void xe_devm_page_free(struct page *page) +{ +} + +static const struct dev_pagemap_ops xe_devm_pagemap_ops = { + .page_free = xe_devm_page_free, + .migrate_to_ram = xe_devm_migrate_to_ram, +}; + +/** + * xe_svm_devm_add: Remap and provide memmap backing for device memory + * @tile: tile that the memory region blongs to + * @mr: memory region to remap + * + * This remap device memory to host physical address space and create + * struct page to back device memory + * + * Return: 0 on success standard error code otherwise + */ +int xe_svm_devm_add(struct xe_tile *tile, struct xe_mem_region *mr) +{ + struct devic
[PATCH 08/23] drm/xe/svm: Add helper to invalidate svm range from GPU
A svm subsystem friendly function is added for svm range invalidation purpose. svm subsystem doesn't maintain xe_vma, so a temporary xe_vma is used to call function xe_vma_invalidate_vma Not sure whether this works or not. Will have to test. if a temporary vma doesn't work, we will have to call the zap_pte/tlb_inv functions directly. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_pt.c | 33 + drivers/gpu/drm/xe/xe_pt.h | 1 + 2 files changed, 34 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index f1e479fa3001..7ae8954be041 100644 --- a/drivers/gpu/drm/xe/xe_pt.c +++ b/drivers/gpu/drm/xe/xe_pt.c @@ -1757,3 +1757,36 @@ int xe_bind_svm_range(struct xe_vm *vm, struct xe_tile *tile, dma_fence_put(fence); return ret; } + +/** + * xe_invalidate_svm_range() - a helper to invalidate a svm address range + * + * @vm: The vm that the address range belongs to + * @start: start of the virtual address range + * @size: size of the virtual address range + * + * This is a helper function supposed to be used by svm subsystem. + * svm subsystem doesn't maintain xe_vma, so we create a temporary + * xe_vma structure so we can reuse xe_vm_invalidate_vma(). + */ +void xe_invalidate_svm_range(struct xe_vm *vm, u64 start, u64 size) +{ + struct xe_vma vma = { + .gpuva = { + .va = { + .addr = start, + .range = size, + }, + .vm = &vm->gpuvm, + }, + /** invalidate from all tiles +* FIXME: We used temporary vma in xe_bind_svm_range, so +* we lost track of which tile we are bound to. Does +* setting tile_present to all tiles cause a problem +* in xe_vm_invalidate_vma()? +*/ + .tile_present = BIT(vm->xe->info.tile_count) - 1, + }; + + xe_vm_invalidate_vma(&vma); +} diff --git a/drivers/gpu/drm/xe/xe_pt.h b/drivers/gpu/drm/xe/xe_pt.h index 775d08707466..42d495997635 100644 --- a/drivers/gpu/drm/xe/xe_pt.h +++ b/drivers/gpu/drm/xe/xe_pt.h @@ -49,4 +49,5 @@ bool xe_pt_zap_ptes(struct xe_tile *tile, struct xe_vma *vma); int xe_bind_svm_range(struct xe_vm *vm, struct xe_tile *tile, struct hmm_range *range, u64 flags); +void xe_invalidate_svm_range(struct xe_vm *vm, u64 start, u64 size); #endif -- 2.26.3
[PATCH 03/23] drm/xe/svm: create xe svm during vm creation
Create the xe_svm struct during xe_vm creation. Add xe_svm to a global hash table so later on we can retrieve xe_svm using mm_struct (the key). Destroy svm process during xe_vm close. Also add a helper function to retrieve svm struct from mm struct Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.c | 63 + drivers/gpu/drm/xe/xe_svm.h | 11 +++ drivers/gpu/drm/xe/xe_vm.c | 5 +++ 3 files changed, 79 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_svm.c diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c new file mode 100644 index ..559188471949 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include "xe_svm.h" + +DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); + +/** + * xe_destroy_svm() - destroy a svm process + * + * @svm: the xe_svm to destroy + */ +void xe_destroy_svm(struct xe_svm *svm) +{ + hash_del_rcu(&svm->hnode); + mutex_destroy(&svm->mutex); + kfree(svm); +} + +/** + * xe_create_svm() - create a svm process + * + * @vm: the xe_vm that we create svm process for + * + * Return the created xe svm struct + */ +struct xe_svm *xe_create_svm(struct xe_vm *vm) +{ + struct mm_struct *mm = current->mm; + struct xe_svm *svm; + + svm = kzalloc(sizeof(struct xe_svm), GFP_KERNEL); + svm->mm = mm; + svm->vm = vm; + mutex_init(&svm->mutex); + /** Add svm to global xe_svm_table hash table +* use mm as key so later we can retrieve svm using mm +*/ + hash_add_rcu(xe_svm_table, &svm->hnode, (uintptr_t)mm); + return svm; +} + +/** + * xe_lookup_svm_by_mm() - retrieve xe_svm from mm struct + * + * @mm: the mm struct of the svm to retrieve + * + * Return the xe_svm struct pointer, or NULL if fail + */ +struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm) +{ + struct xe_svm *svm; + + hash_for_each_possible_rcu(xe_svm_table, svm, hnode, (uintptr_t)mm) + if (svm->mm == mm) + return svm; + + return NULL; +} diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index ba301a331f59..cd3cf92f3784 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -11,10 +11,15 @@ #include #include #include +#include +#include struct xe_vm; struct mm_struct; +#define XE_MAX_SVM_PROCESS 5 /* Maximumly support 32 SVM process*/ +extern DECLARE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); + /** * struct xe_svm - data structure to represent a shared * virtual address space from device side. xe_svm, xe_vm @@ -35,6 +40,8 @@ struct xe_svm { * @range_tree: Interval tree of all svm ranges in this svm */ struct rb_root_cached range_tree; + /** @hnode: used to add this svm to a global xe_svm_hash table*/ + struct hlist_node hnode; }; /** @@ -56,4 +63,8 @@ struct xe_svm_range { /** @inode: used to link this range to svm's range_tree */ struct interval_tree_node inode; }; + +void xe_destroy_svm(struct xe_svm *svm); +struct xe_svm *xe_create_svm(struct xe_vm *vm); +struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm); #endif diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c index a7e7a0b24099..712fe49d8fb2 100644 --- a/drivers/gpu/drm/xe/xe_vm.c +++ b/drivers/gpu/drm/xe/xe_vm.c @@ -36,6 +36,7 @@ #include "xe_trace.h" #include "generated/xe_wa_oob.h" #include "xe_wa.h" +#include "xe_svm.h" #define TEST_VM_ASYNC_OPS_ERROR @@ -1376,6 +1377,7 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags) xe->usm.num_vm_in_non_fault_mode++; mutex_unlock(&xe->usm.lock); + vm->svm = xe_create_svm(vm); trace_xe_vm_create(vm); return vm; @@ -1496,6 +1498,9 @@ void xe_vm_close_and_put(struct xe_vm *vm) for_each_tile(tile, xe, id) xe_range_fence_tree_fini(&vm->rftree[id]); + if (vm->svm) + xe_destroy_svm(vm->svm); + xe_vm_put(vm); } -- 2.26.3
[PATCH 05/23] drm/xe/svm: add helper to retrieve svm range from address
All valid virtual address range are maintained in svm's range_tree. This functions iterate svm's range tree and return the svm range that contains specific address. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.h | 2 ++ drivers/gpu/drm/xe/xe_svm_range.c | 32 +++ 2 files changed, 34 insertions(+) create mode 100644 drivers/gpu/drm/xe/xe_svm_range.c diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index cd3cf92f3784..3ed106ecc02b 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -67,4 +67,6 @@ struct xe_svm_range { void xe_destroy_svm(struct xe_svm *svm); struct xe_svm *xe_create_svm(struct xe_vm *vm); struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm); +struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, + unsigned long addr); #endif diff --git a/drivers/gpu/drm/xe/xe_svm_range.c b/drivers/gpu/drm/xe/xe_svm_range.c new file mode 100644 index ..d8251d38f65e --- /dev/null +++ b/drivers/gpu/drm/xe/xe_svm_range.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2023 Intel Corporation + */ + +#include +#include +#include +#include "xe_svm.h" + +/** + * xe_svm_range_from_addr() - retrieve svm_range contains a virtual address + * + * @svm: svm that the virtual address belongs to + * @addr: the virtual address to retrieve svm_range for + * + * return the svm range found, + * or NULL if no range found + */ +struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, + unsigned long addr) +{ + struct interval_tree_node *node; + + mutex_lock(&svm->mutex); + node = interval_tree_iter_first(&svm->range_tree, addr, addr); + mutex_unlock(&svm->mutex); + if (!node) + return NULL; + + return container_of(node, struct xe_svm_range, inode); +} -- 2.26.3
[PATCH 04/23] drm/xe/svm: Trace svm creation
xe_vm tracepoint is extended to also print svm. Signed-off-by: Oak Zeng Cc: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_trace.h | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xe/xe_trace.h b/drivers/gpu/drm/xe/xe_trace.h index 95163c303f3e..63867c0fa848 100644 --- a/drivers/gpu/drm/xe/xe_trace.h +++ b/drivers/gpu/drm/xe/xe_trace.h @@ -467,15 +467,17 @@ DECLARE_EVENT_CLASS(xe_vm, TP_STRUCT__entry( __field(u64, vm) __field(u32, asid) +__field(u64, svm) ), TP_fast_assign( __entry->vm = (unsigned long)vm; __entry->asid = vm->usm.asid; + __entry->svm = (unsigned long)vm->svm; ), - TP_printk("vm=0x%016llx, asid=0x%05x", __entry->vm, - __entry->asid) + TP_printk("vm=0x%016llx, asid=0x%05x, svm=0x%016llx", __entry->vm, + __entry->asid, __entry->svm) ); DEFINE_EVENT(xe_vm, xe_vm_kill, -- 2.26.3
[PATCH 06/23] drm/xe/svm: Introduce a helper to build sg table from hmm range
Introduce xe_svm_build_sg helper function to build a scatter gather table from a hmm_range struct. This is prepare work for binding hmm range to gpu. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- drivers/gpu/drm/xe/xe_svm.c | 52 + drivers/gpu/drm/xe/xe_svm.h | 3 +++ 2 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/xe/xe_svm.c b/drivers/gpu/drm/xe/xe_svm.c index 559188471949..ab3cc2121869 100644 --- a/drivers/gpu/drm/xe/xe_svm.c +++ b/drivers/gpu/drm/xe/xe_svm.c @@ -6,6 +6,8 @@ #include #include #include "xe_svm.h" +#include +#include DEFINE_HASHTABLE(xe_svm_table, XE_MAX_SVM_PROCESS); @@ -61,3 +63,53 @@ struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm) return NULL; } + +/** + * xe_svm_build_sg() - build a scatter gather table for all the physical pages/pfn + * in a hmm_range. + * + * @range: the hmm range that we build the sg table from. range->hmm_pfns[] + * has the pfn numbers of pages that back up this hmm address range. + * @st: pointer to the sg table. + * + * All the contiguous pfns will be collapsed into one entry in + * the scatter gather table. This is for the convenience of + * later on operations to bind address range to GPU page table. + * + * This function allocates the storage of the sg table. It is + * caller's responsibility to free it calling sg_free_table. + * + * Returns 0 if successful; -ENOMEM if fails to allocate memory + */ +int xe_svm_build_sg(struct hmm_range *range, +struct sg_table *st) +{ + struct scatterlist *sg; + u64 i, npages; + + sg = NULL; + st->nents = 0; + npages = ((range->end - 1) >> PAGE_SHIFT) - (range->start >> PAGE_SHIFT) + 1; + + if (unlikely(sg_alloc_table(st, npages, GFP_KERNEL))) + return -ENOMEM; + + for (i = 0; i < npages; i++) { + unsigned long addr = range->hmm_pfns[i]; + + if (sg && (addr == (sg_dma_address(sg) + sg->length))) { + sg->length += PAGE_SIZE; + sg_dma_len(sg) += PAGE_SIZE; + continue; + } + + sg = sg ? sg_next(sg) : st->sgl; + sg_dma_address(sg) = addr; + sg_dma_len(sg) = PAGE_SIZE; + sg->length = PAGE_SIZE; + st->nents++; + } + + sg_mark_end(sg); + return 0; +} diff --git a/drivers/gpu/drm/xe/xe_svm.h b/drivers/gpu/drm/xe/xe_svm.h index 3ed106ecc02b..191bce6425db 100644 --- a/drivers/gpu/drm/xe/xe_svm.h +++ b/drivers/gpu/drm/xe/xe_svm.h @@ -13,6 +13,8 @@ #include #include #include +#include +#include "xe_device_types.h" struct xe_vm; struct mm_struct; @@ -69,4 +71,5 @@ struct xe_svm *xe_create_svm(struct xe_vm *vm); struct xe_svm *xe_lookup_svm_by_mm(struct mm_struct *mm); struct xe_svm_range *xe_svm_range_from_addr(struct xe_svm *svm, unsigned long addr); +int xe_svm_build_sg(struct hmm_range *range, struct sg_table *st); #endif -- 2.26.3
[PATCH 01/23] drm/xe/svm: Add SVM document
Add shared virtual memory document. Signed-off-by: Oak Zeng Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Cc: Matthew Brost Cc: Thomas Hellström Cc: Brian Welty --- Documentation/gpu/xe/index.rst | 1 + Documentation/gpu/xe/xe_svm.rst | 8 +++ drivers/gpu/drm/xe/xe_svm_doc.h | 121 3 files changed, 130 insertions(+) create mode 100644 Documentation/gpu/xe/xe_svm.rst create mode 100644 drivers/gpu/drm/xe/xe_svm_doc.h diff --git a/Documentation/gpu/xe/index.rst b/Documentation/gpu/xe/index.rst index c224ecaee81e..106b60aba1f0 100644 --- a/Documentation/gpu/xe/index.rst +++ b/Documentation/gpu/xe/index.rst @@ -23,3 +23,4 @@ DG2, etc is provided to prototype the driver. xe_firmware xe_tile xe_debugging + xe_svm diff --git a/Documentation/gpu/xe/xe_svm.rst b/Documentation/gpu/xe/xe_svm.rst new file mode 100644 index ..62954ba1c6f8 --- /dev/null +++ b/Documentation/gpu/xe/xe_svm.rst @@ -0,0 +1,8 @@ +.. SPDX-License-Identifier: (GPL-2.0+ OR MIT) + += +Shared virtual memory += + +.. kernel-doc:: drivers/gpu/drm/xe/xe_svm_doc.h + :doc: Shared virtual memory diff --git a/drivers/gpu/drm/xe/xe_svm_doc.h b/drivers/gpu/drm/xe/xe_svm_doc.h new file mode 100644 index ..de38ee3585e4 --- /dev/null +++ b/drivers/gpu/drm/xe/xe_svm_doc.h @@ -0,0 +1,121 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef _XE_SVM_DOC_H_ +#define _XE_SVM_DOC_H_ + +/** + * DOC: Shared virtual memory + * + * Shared Virtual Memory (SVM) allows the programmer to use a single virtual + * address space shared between threads executing on CPUs and GPUs. It abstracts + * away from the user the location of the backing memory, and hence simplifies + * the user programming model. In a non-SVM memory model, user need to explicitly + * decide memory placement such as device or system memory, also user need to + * explicitly migrate memory b/t device and system memory. + * + * Interface + * = + * + * SVM makes use of default OS memory allocation and mapping interface such as + * malloc() and mmap(). The pointer returned from malloc() and mmap() can be + * directly used on both CPU and GPU program. + * + * SVM also provides API to set virtual address range based memory attributes + * such as preferred memory location, memory migration granularity, and memory + * atomic attributes etc. This is similar to Linux madvise API. + * + * Basic implementation + * == + * + * XeKMD implementation is based on Linux kernel Heterogeneous Memory Management + * (HMM) framework. HMM’s address space mirroring support allows sharing of the + * address space by duplicating sections of CPU page tables in the device page + * tables. This enables both CPU and GPU access a physical memory location using + * the same virtual address. + * + * Linux kernel also provides the ability to plugin device memory to the system + * (as a special ZONE_DEVICE type) and allocates struct page for each device memory + * page. + * + * HMM also provides a mechanism to migrate pages from host to device memory and + * vice versa. + * + * More information on HMM can be found here. + * https://www.kernel.org/doc/Documentation/vm/hmm.rst + * + * Unlike the non-SVM memory allocator (such as gem_create, vm_bind etc), there + * is no buffer object (BO, such as struct ttm_buffer_object, struct drm_gem_object), + * in our SVM implementation. We delibrately choose this implementation option + * to achieve page granularity memory placement, validation, eviction and migration. + * + * The SVM layer directly allocate device memory from drm buddy subsystem. The + * memory is organized as many blocks each of which has 2^n pages. SVM subsystem + * then mark the usage of each page using a simple bitmap. When all pages in a + * block are not used anymore, SVM return this block back to drm buddy subsystem. + * + * There are 3 events which can trigger SVM subsystem in actions: + * + * 1. A mmu notifier callback + * + * Since SVM need to mirror the program's CPU virtual address space from GPU side, + * when program's CPU address space changes, SVM need to make an identical change + * from GPU side. SVM/hmm use mmu interval notifier to achieve this. SVM register + * a mmu interval notifier call back function to core mm, and whenever a CPU side + * virtual address space is changed (i.e., when a virtual address range is unmapped + * from CPU calling munmap), the registered callback function will be called from + * core mm. SVM then mirror the CPU address space change from GPU side, i.e., unmap + * or invalidate the virtual address range from GPU page table. + * + * 2. A GPU page fault + * + * At the very beginning of a process's life, no virtual address of the process + * is mapped on GPU page table. So when GPU access any virtual address of the process + * a GPU page fault is triggered. SVM then
[PATCH 00/23] XeKmd basic SVM support
This is the very basic SVM (shared virtual memory) support in XeKmd driver. SVM allows the programmer to use a shaed virtual address space between CPU program and GPU program. It abstracts away from the user the location of the backing memory in a mixed CPU and GPU programming environment. This work is based on previous I915 SVM implementation mainly from Niranjana Vishwanathapura and Oak Zeng, which has never been upstreamed before. This is our first attempt to upstream this work. This implementation depends on Linux kernel HMM support. See some key designs in patch #1. We are aware there are currently some effort to implement SVM using GMEM(generalized memory management, see https://lore.kernel.org/dri-devel/20231128125025.4449-1-weixi@huawei.com/) We are open to this new method if it can be merged to upstream kernel. Before that, we think it is still safer to support SVM through HMM. This series only has basic SVM support. We think it is better to post this series earlier so we can get more eyes on it. Below are the works that is planned or ongoing: *Testing: We are working on the igt test right now. Some part of this series, especially the gpu page table update(patch #7, #8) and migration function (patch #10) need some debug to make it work. *Virtual address range based memory attributes and hints: We plan to expose uAPI for user to set memory attributes such as preferred location or migration granularity etc to a virtual address range. This is important to tune SVM performance. *GPU vram eviction: One key design choice of this series is, SVM layer allocate GPU memory directly from drm buddy allocator, instead of from xe vram manager. There is no BO (buffer object) concept in this implementation. The key benefit of this approach is we can migrate memory at page granularity easily. This also means SVM bypasses TTM's memory eviction logic. But we want the SVM memory and BO driver memory can mutually evicted each other. We have some prove of concept work to rework TTM resource manager for this purpose, see https://lore.kernel.org/dri-devel/20231102043306.2931989-1-oak.z...@intel.com/ We will continue work on that series then implement SVM's eviction function based on the concept of shared drm LRU list b/t SVM and TTM/BO driver. Oak Zeng (23): drm/xe/svm: Add SVM document drm/xe/svm: Add svm key data structures drm/xe/svm: create xe svm during vm creation drm/xe/svm: Trace svm creation drm/xe/svm: add helper to retrieve svm range from address drm/xe/svm: Introduce a helper to build sg table from hmm range drm/xe/svm: Add helper for binding hmm range to gpu drm/xe/svm: Add helper to invalidate svm range from GPU drm/xe/svm: Remap and provide memmap backing for GPU vram drm/xe/svm: Introduce svm migration function drm/xe/svm: implement functions to allocate and free device memory drm/xe/svm: Trace buddy block allocation and free drm/xe/svm: Handle CPU page fault drm/xe/svm: trace svm range migration drm/xe/svm: Implement functions to register and unregister mmu notifier drm/xe/svm: Implement the mmu notifier range invalidate callback drm/xe/svm: clean up svm range during process exit drm/xe/svm: Move a few structures to xe_gt.h drm/xe/svm: migrate svm range to vram drm/xe/svm: Populate svm range drm/xe/svm: GPU page fault support drm/xe/svm: Add DRM_XE_SVM kernel config entry drm/xe/svm: Add svm memory hints interface Documentation/gpu/xe/index.rst | 1 + Documentation/gpu/xe/xe_svm.rst | 8 + drivers/gpu/drm/xe/Kconfig | 22 ++ drivers/gpu/drm/xe/Makefile | 5 + drivers/gpu/drm/xe/xe_device_types.h | 20 ++ drivers/gpu/drm/xe/xe_gt.h | 20 ++ drivers/gpu/drm/xe/xe_gt_pagefault.c | 28 +-- drivers/gpu/drm/xe/xe_migrate.c | 213 + drivers/gpu/drm/xe/xe_migrate.h | 7 + drivers/gpu/drm/xe/xe_mmio.c | 12 + drivers/gpu/drm/xe/xe_pt.c | 147 +++- drivers/gpu/drm/xe/xe_pt.h | 5 + drivers/gpu/drm/xe/xe_svm.c | 324 + drivers/gpu/drm/xe/xe_svm.h | 115 + drivers/gpu/drm/xe/xe_svm_devmem.c | 232 ++ drivers/gpu/drm/xe/xe_svm_doc.h | 121 ++ drivers/gpu/drm/xe/xe_svm_migrate.c | 345 +++ drivers/gpu/drm/xe/xe_svm_range.c| 227 ++ drivers/gpu/drm/xe/xe_trace.h| 71 +- drivers/gpu/drm/xe/xe_vm.c | 7 + drivers/gpu/drm/xe/xe_vm_types.h | 15 +- include/uapi/drm/xe_drm.h| 40 22 files changed, 1957 insertions(+), 28 deletions(-) create mode 100644 Documentation/gpu/xe/xe_svm.rst create mode 100644 drivers/gpu/drm/xe/xe_svm.c create mode 100644 drivers/gpu/drm/xe/xe_svm.h create mode 100644 drivers/gpu/drm/xe/xe_svm_devmem.c create mode 100644 drivers/gpu/drm/xe/xe_svm_doc.h create mode 100644 drivers/gpu/drm/xe/xe_svm_migrate.c create mode 100644 drivers/gpu/drm/x
Re: [PATCH 2/3] video/cmdline: Hide __video_get_options() behind CONFIG_FB_CORE
Hi Thomas, kernel test robot noticed the following build errors: [auto build test ERROR on 05b317e8457c8e2bd1a797c9440ec07b7f341584] url: https://github.com/intel-lab-lkp/linux/commits/Thomas-Zimmermann/video-cmdline-Introduce-CONFIG_VIDEO-for-video-parameter/20240115-181419 base: 05b317e8457c8e2bd1a797c9440ec07b7f341584 patch link: https://lore.kernel.org/r/20240115100939.21562-3-tzimmermann%40suse.de patch subject: [PATCH 2/3] video/cmdline: Hide __video_get_options() behind CONFIG_FB_CORE config: i386-randconfig-011-20240118 (https://download.01.org/0day-ci/archive/20240118/202401180531.k8mdbrau-...@intel.com/config) compiler: gcc-11 (Debian 11.3.0-12) 11.3.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240118/202401180531.k8mdbrau-...@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-kbuild-all/202401180531.k8mdbrau-...@intel.com/ All errors (new ones prefixed by >>): drivers/video/fbdev/core/fb_cmdline.c: In function 'fb_get_options': >> drivers/video/fbdev/core/fb_cmdline.c:45:19: error: implicit declaration of >> function '__video_get_options'; did you mean 'video_get_options'? >> [-Werror=implicit-function-declaration] 45 | enabled = __video_get_options(name, &options, is_of); | ^~~ | video_get_options cc1: some warnings being treated as errors vim +45 drivers/video/fbdev/core/fb_cmdline.c 367221793d4796 Thomas Zimmermann 2023-02-09 23 ea6763c104c93a Daniel Vetter 2014-08-06 24 /** ea6763c104c93a Daniel Vetter 2014-08-06 25 * fb_get_options - get kernel boot parameters ea6763c104c93a Daniel Vetter 2014-08-06 26 * @name: framebuffer name as it would appear in ea6763c104c93a Daniel Vetter 2014-08-06 27 * the boot parameter line ea6763c104c93a Daniel Vetter 2014-08-06 28 * (video=:) ea6763c104c93a Daniel Vetter 2014-08-06 29 * @option: the option will be stored here ea6763c104c93a Daniel Vetter 2014-08-06 30 * 73ce73c30ba9ae Thomas Zimmermann 2023-02-09 31 * The caller owns the string returned in @option and is 73ce73c30ba9ae Thomas Zimmermann 2023-02-09 32 * responsible for releasing the memory. 73ce73c30ba9ae Thomas Zimmermann 2023-02-09 33 * ea6763c104c93a Daniel Vetter 2014-08-06 34 * NOTE: Needed to maintain backwards compatibility ea6763c104c93a Daniel Vetter 2014-08-06 35 */ ea6763c104c93a Daniel Vetter 2014-08-06 36 int fb_get_options(const char *name, char **option) ea6763c104c93a Daniel Vetter 2014-08-06 37 { 93604a5ade3a02 Thomas Zimmermann 2023-02-09 38 const char *options = NULL; 93604a5ade3a02 Thomas Zimmermann 2023-02-09 39 bool is_of = false; 93604a5ade3a02 Thomas Zimmermann 2023-02-09 40 bool enabled; cedaf7cddd7339 Thomas Zimmermann 2023-02-09 41 93604a5ade3a02 Thomas Zimmermann 2023-02-09 42 if (name) 93604a5ade3a02 Thomas Zimmermann 2023-02-09 43 is_of = strncmp(name, "offb", 4); ea6763c104c93a Daniel Vetter 2014-08-06 44 93604a5ade3a02 Thomas Zimmermann 2023-02-09 @45 enabled = __video_get_options(name, &options, is_of); -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
[PATCH] nouveau/vmm: don't set addr on the fail path to avoid warning
From: Dave Airlie nvif_vmm_put gets called if addr is set, but if the allocation fails we don't need to call put, otherwise we get a warning like [523232.435671] [ cut here ] [523232.435674] WARNING: CPU: 8 PID: 1505697 at drivers/gpu/drm/nouveau/nvif/vmm.c:68 nvif_vmm_put+0x72/0x80 [nouveau] [523232.435795] Modules linked in: uinput rfcomm snd_seq_dummy snd_hrtimer nf_conntrack_netbios_ns nf_conntrack_broadcast nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nf_tables nfnetlink qrtr bnep sunrpc binfmt_misc intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common isst_if_common iwlmvm nfit libnvdimm vfat fat x86_pkg_temp_thermal intel_powerclamp mac80211 snd_soc_avs snd_soc_hda_codec coretemp snd_hda_ext_core snd_soc_core snd_hda_codec_realtek kvm_intel snd_hda_codec_hdmi snd_compress snd_hda_codec_generic ac97_bus snd_pcm_dmaengine snd_hda_intel libarc4 snd_intel_dspcfg snd_intel_sdw_acpi snd_hda_codec kvm iwlwifi snd_hda_core btusb snd_hwdep btrtl snd_seq btintel irqbypass btbcm rapl snd_seq_device eeepc_wmi btmtk intel_cstate iTCO_wdt cfg80211 snd_pcm asus_wmi bluetooth intel_pmc_bxt iTCO_vendor_support snd_timer ledtrig_audio pktcdvd snd mei_me [523232.435828] sparse_keymap intel_uncore i2c_i801 platform_profile wmi_bmof mei pcspkr ioatdma soundcore i2c_smbus rfkill idma64 dca joydev acpi_tad loop zram nouveau drm_ttm_helper ttm video drm_exec drm_gpuvm gpu_sched crct10dif_pclmul i2c_algo_bit nvme crc32_pclmul crc32c_intel drm_display_helper polyval_clmulni nvme_core polyval_generic e1000e mxm_wmi cec ghash_clmulni_intel r8169 sha512_ssse3 nvme_common wmi pinctrl_sunrisepoint uas usb_storage ip6_tables ip_tables fuse [523232.435849] CPU: 8 PID: 1505697 Comm: gnome-shell Tainted: GW 6.6.0-rc7-nvk-uapi+ #12 [523232.435851] Hardware name: System manufacturer System Product Name/ROG STRIX X299-E GAMING II, BIOS 1301 09/24/2021 [523232.435852] RIP: 0010:nvif_vmm_put+0x72/0x80 [nouveau] [523232.435934] Code: 00 00 48 89 e2 be 02 00 00 00 48 c7 04 24 00 00 00 00 48 89 44 24 08 e8 fc bf ff ff 85 c0 75 0a 48 c7 43 08 00 00 00 00 eb b3 <0f> 0b eb f2 e8 f5 c9 b2 e6 0f 1f 44 00 00 90 90 90 90 90 90 90 90 [523232.435936] RSP: 0018:c900077ffbd8 EFLAGS: 00010282 [523232.435937] RAX: fffe RBX: c900077ffc00 RCX: 0010 [523232.435938] RDX: 0010 RSI: c900077ffb38 RDI: c900077ffbd8 [523232.435940] RBP: 888e1c4f2140 R08: R09: [523232.435940] R10: R11: R12: 888503811800 [523232.435941] R13: c900077ffca0 R14: 888e1c4f2140 R15: 88810317e1e0 [523232.435942] FS: 7f933a769640() GS:88905fa0() knlGS: [523232.435943] CS: 0010 DS: ES: CR0: 80050033 [523232.435944] CR2: 7f930bef7000 CR3: 0005d0322001 CR4: 003706e0 [523232.435945] DR0: DR1: DR2: [523232.435946] DR3: DR6: fffe0ff0 DR7: 0400 [523232.435964] Call Trace: [523232.435965] [523232.435966] ? nvif_vmm_put+0x72/0x80 [nouveau] [523232.436051] ? __warn+0x81/0x130 [523232.436055] ? nvif_vmm_put+0x72/0x80 [nouveau] [523232.436138] ? report_bug+0x171/0x1a0 [523232.436142] ? handle_bug+0x3c/0x80 [523232.436144] ? exc_invalid_op+0x17/0x70 [523232.436145] ? asm_exc_invalid_op+0x1a/0x20 [523232.436149] ? nvif_vmm_put+0x72/0x80 [nouveau] [523232.436230] ? nvif_vmm_put+0x64/0x80 [nouveau] [523232.436342] nouveau_vma_del+0x80/0xd0 [nouveau] [523232.436506] nouveau_vma_new+0x1a0/0x210 [nouveau] [523232.436671] nouveau_gem_object_open+0x1d0/0x1f0 [nouveau] [523232.436835] drm_gem_handle_create_tail+0xd1/0x180 [523232.436840] drm_prime_fd_to_handle_ioctl+0x12e/0x200 [523232.436844] ? __pfx_drm_prime_fd_to_handle_ioctl+0x10/0x10 [523232.436847] drm_ioctl_kernel+0xd3/0x180 [523232.436849] drm_ioctl+0x26d/0x4b0 [523232.436851] ? __pfx_drm_prime_fd_to_handle_ioctl+0x10/0x10 [523232.436855] nouveau_drm_ioctl+0x5a/0xb0 [nouveau] [523232.437032] __x64_sys_ioctl+0x94/0xd0 [523232.437036] do_syscall_64+0x5d/0x90 [523232.437040] ? syscall_exit_to_user_mode+0x2b/0x40 [523232.437044] ? do_syscall_64+0x6c/0x90 [523232.437046] entry_SYSCALL_64_after_hwframe+0x6e/0xd8 Signed-off-by: Dave Airlie --- drivers/gpu/drm/nouveau/nouveau_vmm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.c b/drivers/gpu/drm/nouveau/nouveau_vmm.c index a6602c012671..3dda885df5b2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_vmm.c +++ b/drivers/gpu/drm/nouveau/nouveau_vmm.c @@ -108,6 +108,9 @@ nouveau_vma_new(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm, } else { ret = nvif_vmm_get(&vmm->vmm, PTES, fa
[PATCH v3] drm/msm/dp: return correct Colorimetry for DP_TEST_DYNAMIC_RANGE_CEA case
MSA MISC0 bit 1 to 7 contains Colorimetry Indicator Field. dp_link_get_colorimetry_config() returns wrong colorimetry value in the DP_TEST_DYNAMIC_RANGE_CEA case in the current implementation. Hence fix this problem by having dp_link_get_colorimetry_config() return defined CEA RGB colorimetry value in the case of DP_TEST_DYNAMIC_RANGE_CEA. Changes in V2: -- drop retrieving colorimetry from colorspace -- drop dr = link->dp_link.test_video.test_dyn_range assignment Changes in V3: -- move defined MISCr0a Colorimetry vale to dp_reg.h -- rewording commit title -- rewording commit text to more precise describe this patch Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_link.c | 12 +++- drivers/gpu/drm/msm/dp/dp_reg.h | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 98427d4..5284e48 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -7,6 +7,7 @@ #include +#include "dp_reg.h" #include "dp_link.h" #include "dp_panel.h" @@ -1082,7 +1083,7 @@ int dp_link_process_request(struct dp_link *dp_link) int dp_link_get_colorimetry_config(struct dp_link *dp_link) { - u32 cc; + u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB; struct dp_link_private *link; if (!dp_link) { @@ -1096,10 +1097,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) * Unless a video pattern CTS test is ongoing, use RGB_VESA * Only RGB_VESA and RGB_CEA supported for now */ - if (dp_link_is_video_pattern_requested(link)) - cc = link->dp_link.test_video.test_dyn_range; - else - cc = DP_TEST_DYNAMIC_RANGE_VESA; + if (dp_link_is_video_pattern_requested(link)) { + if (link->dp_link.test_video.test_dyn_range & + DP_TEST_DYNAMIC_RANGE_CEA) + cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB; + } return cc; } diff --git a/drivers/gpu/drm/msm/dp/dp_reg.h b/drivers/gpu/drm/msm/dp/dp_reg.h index ea85a69..78785ed 100644 --- a/drivers/gpu/drm/msm/dp/dp_reg.h +++ b/drivers/gpu/drm/msm/dp/dp_reg.h @@ -143,6 +143,9 @@ #define DP_MISC0_COLORIMETRY_CFG_SHIFT (0x0001) #define DP_MISC0_TEST_BITS_DEPTH_SHIFT (0x0005) +#define DP_MISC0_COLORIMERY_CFG_LEGACY_RGB (0) +#define DP_MISC0_COLORIMERY_CFG_CEA_RGB(0x04) + #define REG_DP_VALID_BOUNDARY (0x0030) #define REG_DP_VALID_BOUNDARY_2(0x0034) -- 2.7.4
Re: Userspace API for per key backlight for non HID (no hidraw) keyboards
Am 17.01.24 um 17:50 schrieb Hans de Goede: Hi All, On 11/27/23 11:59, Werner Sembach wrote: I also stumbled across a new Problem: We have an upcoming device that has a per-key keyboard backlight, but does the control completely via a wmi/acpi interface. So no usable hidraw here for a potential userspace driver implementation ... So a quick summary for the ideas floating in this thread so far: 1. Expand leds interface allowing arbitrary modes with semi arbitrary optional attributes: - Pro: - Still offers all default attributes for use with UPower - Fairly simple to implement from the preexisting codebase - Could be implemented for all (to me) known internal keyboard backlights - Con: - Violates the simplicity paradigm of the leds interface (e.g. with this one leds entry controls possible multiple leds) So what you are suggesting here is having some way (a-z + other sysfs attr?) to use a single LED class device and then extend that to allow setting all keys ? This does not seem like a good idea to me and this will also cause issues when doing animations in software, since this API will likely be slow. And if the API is not slow, then it will likely involve some sort of binary sysfs file for setting multiple keys rather then 1 file per key which would break the normal 1 file per setting sysfs paradigm. 2. Implement per-key keyboards as auxdisplay - Pro: - Already has a concept for led positions With a "concept" you mean simple x,y positioning or is there something more advanced here that I'm aware of ? - Is conceptually closer to "multiple leds forming a singular entity" - Con: - No preexisting UPower support - No concept for special hardware lightning modes - No support for arbitrary led outlines yet (e.g. ISO style enter-key) Hmm, so there is very little documentation on this and what docs there is: Documentation/admin-guide/auxdisplay/cfag12864b.rst as well as the example program how to uses this suggests that this is using the old /dev/fb# interface which we are sorta trying to retire. 3. Implement in input subsystem - Pro: - Preexisting concept for keys and key purpose - Con: - Not in scope for subsystem - No other preexisting light infrastructure Dmitry actually recently nacked the addition of a LED_MIC_MUTE define to include/uapi/linux/input-event-codes.h which was intended to be able to allow the input LED support with standard HID mic-mute leds (spk-mute is already supported this way). Dmitry was very clear that no new LEDs must be added and that any new LED support should be done through the LED subsytem, so I do not think that something like this is going to fly. 4. Implement a simple leds driver only supporting a small subset of the capabilities and make it disable-able for a userspace driver to take over - Pro: - Most simple to implement basic support - In scope for led subsystem simplicity paradigm - Con: - Not all built in keyboard backlights can be implemented in a userspace only driver Right, so this is basically what we have been discussing in the other part of the thread with the: /sys/bus/hid/devices/0003::./disable_kbd_backlight_support proposal to unregister the kernel's LED class device and then allow userspace to do whatever it wants through /dev/hidraw without the kernel also trying to access the backlight functionality at the same time. AFAIK there already is a bunch of userspace support for per key addressable kbd RGB backlights using hidraw support, so this way we can use the momentum / code of these existing projects, at least for existing hidraw keyboards and adding support for: /sys/bus/hid/devices/0003::./disable_kbd_backlight_support to these existing projects should be simple. Yet this will not work for your mentioned "control completely via a wmi/acpi interface". Still I think we should go the same route for those adding a misc-char device or something like that to allow making WMI calls from userspace (like Windows can do). Maybe with an allow list per GUID to only allow specific calls, so that we can avoid possible dangerous calls. Armin Wolf recently became the WMI bus maintainer. Armin, we are discussing how to deal with (laptop) keyboards which have a separate RGB LED per key and how to control those LEDs. So far per key addressable keyboard backlighting has always been HID based, so any existing support is just userspace based using /dev/hidraw. In my experience the problem with supporting gaming peripherals is that there is interest in it, but not really enough interest to keep a sustained momentum behind projects, especially not when it comes to taking code from a fun weekend hack to upstreaming them into bigger projects like the kernel. So I would like to offer some sort of easy accessible API to usersp
Re: [PATCH] drm/msm/dpu: check for valid hw_pp in dpu_encoder_helper_phys_cleanup
On Wed, 17 Jan 2024 at 21:41, Abhinav Kumar wrote: > > The commit 8b45a26f2ba9 ("drm/msm/dpu: reserve cdm blocks for writeback > in case of YUV output") introduced a smatch warning about another > conditional block in dpu_encoder_helper_phys_cleanup() which had assumed > hw_pp will always be valid which may not necessarily be true. > > Lets fix the other conditional block by making sure hw_pp is valid > before dereferencing it. > > Reported-by: Dan Carpenter > Fixes: ae4d721ce100 ("drm/msm/dpu: add an API to reset the encoder related hw > blocks") > Signed-off-by: Abhinav Kumar > --- > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) Reviewed-by: Dmitry Baryshkov -- With best wishes Dmitry
Re: [RFC PATCH 1/3] dt-bindings: display: ti,am65x-dss: Add support for display sharing mode
On Tue, Jan 16, 2024 at 07:11:40PM +0530, Devarsh Thakkar wrote: > Add support for using TI Keystone DSS hardware present in display > sharing mode. > > TI Keystone DSS hardware supports partitioning of resources between > multiple hosts as it provides separate register space and unique > interrupt line to each host. > > The DSS hardware can be used in shared mode in such a way that one or > more of video planes can be owned by Linux wherease other planes can be > owned by remote cores. > > One or more of the video ports can be dedicated exclusively to a > processing core, wherease some of the video ports can be shared between > two hosts too with only one of them having write access. > > Signed-off-by: Devarsh Thakkar > --- > .../bindings/display/ti/ti,am65x-dss.yaml | 82 +++ > 1 file changed, 82 insertions(+) > > diff --git a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > index 55e3e490d0e6..d9bc69fbf1fb 100644 > --- a/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > +++ b/Documentation/devicetree/bindings/display/ti/ti,am65x-dss.yaml > @@ -112,6 +112,86 @@ properties: >Input memory (from main memory to dispc) bandwidth limit in >bytes per second > > + ti,dss-shared-mode: > +type: boolean > +description: > + TI DSS7 supports sharing of display between multiple hosts > + as it provides separate register space for display configuration and > + unique interrupt line to each host. If you care about line breaks, you need '|'. > + One of the host is provided access to the global display > + configuration labelled as "common" region of DSS allows that host > + exclusive access to global registers of DSS while other host can > + configure the display for it's usage using a separate register > + space labelled as "common1". > + The DSS resources can be partitioned in such a way that one or more > + of the video planes are owned by Linux whereas other video planes Your h/w can only run Linux? What if you want to use this same binding to define the configuration to the 'remote processor'? You can easily s/Linux/the OS/, but it all should be reworded to describe things in terms of the local processor. > + can be owned by a remote core. > + The video port controlling these planes acts as a shared video port > + and it can be configured with write access either by Linux or the > + remote core in which case Linux only has read-only access to that > + video port. What is the purpose of this property when all the other properties are required? > + > + ti,dss-shared-mode-planes: > +description: > + The video layer that is owned by processing core running Linux. > + The display driver running from Linux has exclusive write access to > + this video layer. > +$ref: /schemas/types.yaml#/definitions/string > +enum: [vidl, vid] > + > + ti,dss-shared-mode-vp: > +description: > + The video port that is being used in context of processing core > + running Linux with display susbsytem being used in shared mode. > + This can be owned either by the processing core running Linux in > + which case Linux has the write access and the responsibility to > + configure this video port and the associated overlay manager or > + it can be shared between core running Linux and a remote core > + with remote core provided with write access to this video port and > + associated overlay managers and remote core configures and drives > + this video port also feeding data from one or more of the > + video planes owned by Linux, with Linux only having read-only access > + to this video port and associated overlay managers. > + > +$ref: /schemas/types.yaml#/definitions/string > +enum: [vp1, vp2] > + > + ti,dss-shared-mode-common: > +description: > + The DSS register region owned by processing core running Linux. > +$ref: /schemas/types.yaml#/definitions/string > +enum: [common, common1] > + > + ti,dss-shared-mode-vp-owned: > +description: > + This tells whether processing core running Linux has write access to > + the video ports enlisted in ti,dss-shared-mode-vps. > +$ref: /schemas/types.yaml#/definitions/uint32 > +enum: [0, 1] This can be boolean. Do writes abort or just get ignored? The latter can be probed and doesn't need a property. > + > + ti,dss-shared-mode-plane-zorder: > +description: > + The zorder of the planes owned by Linux. > + For the scenario where Linux is not having write access to associated > + video port, this field is just for > + informational purpose to enumerate the zorder configuration > + being used by remote core. > + > +$ref: /schemas/types.yaml#/definitions/uint32 > +enum: [0, 1] I don't understand how 0 or 1
Re: [PATCH] drm/bridge: parade-ps8640: Make sure we drop the AUX mutex in the error case
Hi, On Wed, Jan 17, 2024 at 11:39 AM Hsin-Yi Wang wrote: > > On Wed, Jan 17, 2024 at 10:35 AM Douglas Anderson > wrote: > > > > After commit 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge > > is suspended in .post_disable()"), if we hit the error case in > > ps8640_aux_transfer() then we return without dropping the mutex. Fix > > this oversight. > > > > Fixes: 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge is suspended > > in .post_disable()") > > Signed-off-by: Douglas Anderson > > --- > > Sorry for missing this in my review! :( Given that this is really > > simple and I'd rather the buggy commit not be there for long, if I can > > get a quick Reviewed-by tag on this patch I'll land it without the > > typical stewing period. > > > > Reviewed-by: Hsin-Yi Wang Thanks! I've pushed this to avoid the breakage. If any additional follow up comes up I'm happy to post additional patches. a20f1b02bafc drm/bridge: parade-ps8640: Make sure we drop the AUX mutex in the error case -Doug
Re: [PATCH v3,04/21] v4l: add documentation for secure memory flag
Hi, Le mercredi 06 décembre 2023 à 16:15 +0800, Yunfei Dong a écrit : > From: Jeffrey Kardatzke > > Adds documentation for V4L2_MEMORY_FLAG_SECURE. As I noticed from DMA Heap discussions, shall this also be renamed SECURE -> RESTRICTED ? regards, Nicolas > > Signed-off-by: Jeffrey Kardatzke > Signed-off-by: Yunfei Dong > --- > Documentation/userspace-api/media/v4l/buffer.rst | 8 +++- > 1 file changed, 7 insertions(+), 1 deletion(-) > > diff --git a/Documentation/userspace-api/media/v4l/buffer.rst > b/Documentation/userspace-api/media/v4l/buffer.rst > index 52bbee81c080..a5a7d1c72d53 100644 > --- a/Documentation/userspace-api/media/v4l/buffer.rst > +++ b/Documentation/userspace-api/media/v4l/buffer.rst > @@ -696,7 +696,7 @@ enum v4l2_memory > > .. _memory-flags: > > -Memory Consistency Flags > +Memory Flags > > > .. raw:: latex > @@ -728,6 +728,12 @@ Memory Consistency Flags > only if the buffer is used for :ref:`memory mapping ` I/O and the > queue reports the :ref:`V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS > ` capability. > +* .. _`V4L2-MEMORY-FLAG-SECURE`: > + > + - ``V4L2_MEMORY_FLAG_SECURE`` > + - 0x0002 > + - DMA bufs passed into the queue will be validated to ensure they were > + allocated from a secure dma-heap. > > .. raw:: latex >
[PATCH] drm/msm/dpu: check for valid hw_pp in dpu_encoder_helper_phys_cleanup
The commit 8b45a26f2ba9 ("drm/msm/dpu: reserve cdm blocks for writeback in case of YUV output") introduced a smatch warning about another conditional block in dpu_encoder_helper_phys_cleanup() which had assumed hw_pp will always be valid which may not necessarily be true. Lets fix the other conditional block by making sure hw_pp is valid before dereferencing it. Reported-by: Dan Carpenter Fixes: ae4d721ce100 ("drm/msm/dpu: add an API to reset the encoder related hw blocks") Signed-off-by: Abhinav Kumar --- drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c index 83380bc92a00..282d84c872f2 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c @@ -2072,7 +2072,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) } /* reset the merge 3D HW block */ - if (phys_enc->hw_pp->merge_3d) { + if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) { phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d, BLEND_3D_NONE); if (phys_enc->hw_ctl->ops.update_pending_flush_merge_3d) @@ -2103,7 +2103,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc) if (phys_enc->hw_wb) intf_cfg.wb = phys_enc->hw_wb->idx; - if (phys_enc->hw_pp->merge_3d) + if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx; if (ctl->ops.reset_intf_cfg) -- 2.40.1
Re: [PATCH] drm/bridge: parade-ps8640: Make sure we drop the AUX mutex in the error case
On Wed, Jan 17, 2024 at 10:35 AM Douglas Anderson wrote: > > After commit 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge > is suspended in .post_disable()"), if we hit the error case in > ps8640_aux_transfer() then we return without dropping the mutex. Fix > this oversight. > > Fixes: 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge is suspended > in .post_disable()") > Signed-off-by: Douglas Anderson > --- > Sorry for missing this in my review! :( Given that this is really > simple and I'd rather the buggy commit not be there for long, if I can > get a quick Reviewed-by tag on this patch I'll land it without the > typical stewing period. > Reviewed-by: Hsin-Yi Wang > drivers/gpu/drm/bridge/parade-ps8640.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c > b/drivers/gpu/drm/bridge/parade-ps8640.c > index 166bfc725ef4..14d4dcf239da 100644 > --- a/drivers/gpu/drm/bridge/parade-ps8640.c > +++ b/drivers/gpu/drm/bridge/parade-ps8640.c > @@ -351,11 +351,13 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux > *aux, > ret = _ps8640_wait_hpd_asserted(ps_bridge, 200 * 1000); > if (ret) { > pm_runtime_put_sync_suspend(dev); > - return ret; > + goto exit; > } > ret = ps8640_aux_transfer_msg(aux, msg); > pm_runtime_mark_last_busy(dev); > pm_runtime_put_autosuspend(dev); > + > +exit: > mutex_unlock(&ps_bridge->aux_lock); > > return ret; > -- > 2.43.0.381.gb435a96ce8-goog >
Re: [PATCH] drm/msm/adreno: Add a null pointer check in zap_shader_load_mdt()
> kasprintf() returns a pointer to dynamically allocated memory > which can be NULL upon failure. Ensure the allocation was successful > by checking the pointer validity. … > +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c > @@ -144,6 +144,10 @@ static int zap_shader_load_mdt(struct msm_gpu *gpu, > const char *fwname, > char *newname; > > newname = kasprintf(GFP_KERNEL, "qcom/%s", fwname); > + if (!newname) { > + ret = -ENOMEM; > + goto out; > + } … How do you think about to avoid the repetition of the pointer check for the variable “mem_region”? Can the usage of other labels become more appropriate? Regards, Markus
Re: [PATCH v2] drm/msm/dp: correct configure Colorimetry Indicator Field at MISC0
On 1/17/2024 10:40 AM, Dmitry Baryshkov wrote: On Wed, 17 Jan 2024 at 20:29, Kuogee Hsieh wrote: On 1/17/2024 10:12 AM, Dmitry Baryshkov wrote: On Wed, 17 Jan 2024 at 19:54, Kuogee Hsieh wrote: MSA MISC0 bit 1 to 7 contains Colorimetry Indicator Field. At current implementation, at DP_TEST_DYNAMIC_RANGE_CEA case the In the current implementation, in the ... case Colorimetry Indicator Field is mistakenly left shifted one extra bit. This doesn't make sense. You say that the value is mistakenly shifted, but the shift is still in place in dp_catalog_ctrl_config_misc(). The problem is at link->dp_link.test_video.test_dyn_range = (bp & DP_TEST_DYNAMIC_RANGE_CEA); <== this from reading dpcd directly where ==> DP_TEST_DYNAMIC_RANGE_CEA is (1 << 3) within dp_catalog_ctrl_config_misc(), cc will be left shift one more bit. so that cc is totally is left shifted 4 bits (bit 4). at misc0, it should be bit 3 set only for CEA_RGB. Yes. But your patch doesn't fix the shift (which is correct). You patch fixes the value being written to that field. ok, i will rewording the commit test This patch return correct value of colorimetry at dp_link_get_colorimetry_config() to fix this problem. See Documentation/process/submitting-patches.rst#_describe_changes Changes in V2: -- drop retrieving colorimetry from colorspace -- drop dr = link->dp_link.test_video.test_dyn_range assignment Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_link.c | 11 ++- drivers/gpu/drm/msm/dp/dp_link.h | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 98427d4..2e1bdaf 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -1082,7 +1082,7 @@ int dp_link_process_request(struct dp_link *dp_link) int dp_link_get_colorimetry_config(struct dp_link *dp_link) { - u32 cc; + u32 cc = DP_MISC0_LEGACY_RGB; struct dp_link_private *link; if (!dp_link) { @@ -1096,10 +1096,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) * Unless a video pattern CTS test is ongoing, use RGB_VESA * Only RGB_VESA and RGB_CEA supported for now */ - if (dp_link_is_video_pattern_requested(link)) - cc = link->dp_link.test_video.test_dyn_range; - else - cc = DP_TEST_DYNAMIC_RANGE_VESA; + if (dp_link_is_video_pattern_requested(link)) { + if (link->dp_link.test_video.test_dyn_range & + DP_TEST_DYNAMIC_RANGE_CEA) + cc = DP_MISC0_CEA_RGB; + } return cc; } diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 9dd4dd9..fe8f716 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -12,6 +12,9 @@ #define DP_TEST_BIT_DEPTH_UNKNOWN 0x #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) +#define DP_MISC0_LEGACY_RGB0 +#define DP_MISC0_CEA_RGB 0x04 These should go to dp_reg.h and should start with DP_MISC0_COLORIMETRY_CFG + struct dp_link_info { unsigned char revision; unsigned int rate; -- 2.7.4
[PATCH 2/2] amdgpu: use trace_dma_fence_sync_to in amdgpu_fence_sync
This makes it possible to understand the dependencies between jobs. Possible usage of this trace: * stuttering issues like Mesa !9189 * incorrect synchronization: I don't have a link for this one, but having these events was very useful to debug a virtio-gpu / native-context / radeonsi sync issue I have prototype code using this in UMR, as can be see here: https://gitlab.freedesktop.org/tomstdenis/umr/-/merge_requests/37 The 'reason' param currently uses __func__ but I didn't add a macro for this because it'd be interesting to use more descriptive names for each use of amdgpu_fence_sync. Signed-off-by: Pierre-Eric Pelloux-Prayer --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 8 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 14 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 8 +++- drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c | 4 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 11 --- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 3 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_umsch_mm.c | 4 ++-- 7 files changed, 28 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index d17b2452cb1f..fde98e48c84b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -491,7 +491,7 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync) if (ret) return ret; - return amdgpu_sync_fence(sync, vm->last_update); + return amdgpu_sync_fence(sync, vm->last_update, __func__); } static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem) @@ -1251,7 +1251,7 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem, amdgpu_vm_clear_freed(adev, vm, &bo_va->last_pt_update); - amdgpu_sync_fence(sync, bo_va->last_pt_update); + amdgpu_sync_fence(sync, bo_va->last_pt_update, __func__); } static int update_gpuvm_pte(struct kgd_mem *mem, @@ -1273,7 +1273,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, return ret; } - return amdgpu_sync_fence(sync, bo_va->last_pt_update); + return amdgpu_sync_fence(sync, bo_va->last_pt_update, __func__); } static int map_bo_to_gpuvm(struct kgd_mem *mem, @@ -2910,7 +2910,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) } dma_resv_for_each_fence(&cursor, bo->tbo.base.resv, DMA_RESV_USAGE_KERNEL, fence) { - ret = amdgpu_sync_fence(&sync_obj, fence); + ret = amdgpu_sync_fence(&sync_obj, fence, __func__); if (ret) { pr_debug("Memory eviction: Sync BO fence failed. Try again\n"); goto validate_map_fail; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 6adeddfb3d56..6830892383c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -423,7 +423,7 @@ static int amdgpu_cs_p2_dependencies(struct amdgpu_cs_parser *p, dma_fence_put(old); } - r = amdgpu_sync_fence(&p->sync, fence); + r = amdgpu_sync_fence(&p->sync, fence, __func__); dma_fence_put(fence); if (r) return r; @@ -445,7 +445,7 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p, return r; } - r = amdgpu_sync_fence(&p->sync, fence); + r = amdgpu_sync_fence(&p->sync, fence, __func__); dma_fence_put(fence); return r; } @@ -1101,7 +1101,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_fence(&p->sync, fpriv->prt_va->last_pt_update); + r = amdgpu_sync_fence(&p->sync, fpriv->prt_va->last_pt_update, __func__); if (r) return r; @@ -1112,7 +1112,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update); + r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update, __func__); if (r) return r; } @@ -1131,7 +1131,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update); + r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update, __func__); if (r) return r; } @@ -1144,7 +1144,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
[PATCH 1/2] tracing, dma-buf: add a trace_dma_fence_sync_to event
This new event can be used to trace where a given dma_fence is added as a dependency of some other work. I plan to use it in amdgpu. Signed-off-by: Pierre-Eric Pelloux-Prayer --- drivers/dma-buf/dma-fence.c | 1 + include/trace/events/dma_fence.h | 34 2 files changed, 35 insertions(+) diff --git a/drivers/dma-buf/dma-fence.c b/drivers/dma-buf/dma-fence.c index e0fd99e61a2d..671a499a5ccd 100644 --- a/drivers/dma-buf/dma-fence.c +++ b/drivers/dma-buf/dma-fence.c @@ -23,6 +23,7 @@ EXPORT_TRACEPOINT_SYMBOL(dma_fence_emit); EXPORT_TRACEPOINT_SYMBOL(dma_fence_enable_signal); EXPORT_TRACEPOINT_SYMBOL(dma_fence_signaled); +EXPORT_TRACEPOINT_SYMBOL(dma_fence_sync_to); static DEFINE_SPINLOCK(dma_fence_stub_lock); static struct dma_fence dma_fence_stub; diff --git a/include/trace/events/dma_fence.h b/include/trace/events/dma_fence.h index 3963e79ca7b4..9b3875f7aa79 100644 --- a/include/trace/events/dma_fence.h +++ b/include/trace/events/dma_fence.h @@ -83,6 +83,40 @@ DEFINE_EVENT(dma_fence, dma_fence_wait_end, TP_ARGS(fence) ); +DECLARE_EVENT_CLASS(dma_fence_from, + + TP_PROTO(struct dma_fence *fence, const char *reason), + + TP_ARGS(fence, reason), + + TP_STRUCT__entry( + __string(driver, fence->ops->get_driver_name(fence)) + __string(timeline, fence->ops->get_timeline_name(fence)) + __field(unsigned int, context) + __field(unsigned int, seqno) + __string(reason, reason) + ), + + TP_fast_assign( + __assign_str(driver, fence->ops->get_driver_name(fence)); + __assign_str(timeline, fence->ops->get_timeline_name(fence)); + __entry->context = fence->context; + __entry->seqno = fence->seqno; + __assign_str(reason, reason); + ), + + TP_printk("driver=%s timeline=%s context=%u seqno=%u reason=%s", + __get_str(driver), __get_str(timeline), __entry->context, + __entry->seqno, __get_str(reason)) +); + +DEFINE_EVENT(dma_fence_from, dma_fence_sync_to, + + TP_PROTO(struct dma_fence *fence, const char *reason), + + TP_ARGS(fence, reason) +); + #endif /* _TRACE_DMA_FENCE_H */ /* This part must be outside protection */ -- 2.40.1
Re: [PATCH v2] drm/msm/dp: correct configure Colorimetry Indicator Field at MISC0
On Wed, 17 Jan 2024 at 20:29, Kuogee Hsieh wrote: > > > On 1/17/2024 10:12 AM, Dmitry Baryshkov wrote: > > On Wed, 17 Jan 2024 at 19:54, Kuogee Hsieh wrote: > >> MSA MISC0 bit 1 to 7 contains Colorimetry Indicator Field. At > >> current implementation, at DP_TEST_DYNAMIC_RANGE_CEA case the > > In the current implementation, in the ... case > > > >> Colorimetry Indicator Field is mistakenly left shifted one extra > >> bit. > > This doesn't make sense. You say that the value is mistakenly shifted, > > but the shift is still in place in dp_catalog_ctrl_config_misc(). > > The problem is at > > link->dp_link.test_video.test_dyn_range = (bp & > DP_TEST_DYNAMIC_RANGE_CEA); <== this from reading dpcd directly where > ==> DP_TEST_DYNAMIC_RANGE_CEA is (1 << 3) > > within dp_catalog_ctrl_config_misc(), cc will be left shift one more bit. > so that cc is totally is left shifted 4 bits (bit 4). > > at misc0, it should be bit 3 set only for CEA_RGB. Yes. But your patch doesn't fix the shift (which is correct). You patch fixes the value being written to that field. > > > > >> This patch return correct value of colorimetry at > >> dp_link_get_colorimetry_config() to fix this problem. > > See Documentation/process/submitting-patches.rst#_describe_changes > > > >> Changes in V2: > >> -- drop retrieving colorimetry from colorspace > >> -- drop dr = link->dp_link.test_video.test_dyn_range assignment > >> > >> Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") > >> Signed-off-by: Kuogee Hsieh > >> --- > >> drivers/gpu/drm/msm/dp/dp_link.c | 11 ++- > >> drivers/gpu/drm/msm/dp/dp_link.h | 3 +++ > >> 2 files changed, 9 insertions(+), 5 deletions(-) > >> > >> diff --git a/drivers/gpu/drm/msm/dp/dp_link.c > >> b/drivers/gpu/drm/msm/dp/dp_link.c > >> index 98427d4..2e1bdaf 100644 > >> --- a/drivers/gpu/drm/msm/dp/dp_link.c > >> +++ b/drivers/gpu/drm/msm/dp/dp_link.c > >> @@ -1082,7 +1082,7 @@ int dp_link_process_request(struct dp_link *dp_link) > >> > >> int dp_link_get_colorimetry_config(struct dp_link *dp_link) > >> { > >> - u32 cc; > >> + u32 cc = DP_MISC0_LEGACY_RGB; > >> struct dp_link_private *link; > >> > >> if (!dp_link) { > >> @@ -1096,10 +1096,11 @@ int dp_link_get_colorimetry_config(struct dp_link > >> *dp_link) > >> * Unless a video pattern CTS test is ongoing, use RGB_VESA > >> * Only RGB_VESA and RGB_CEA supported for now > >> */ > >> - if (dp_link_is_video_pattern_requested(link)) > >> - cc = link->dp_link.test_video.test_dyn_range; > >> - else > >> - cc = DP_TEST_DYNAMIC_RANGE_VESA; > >> + if (dp_link_is_video_pattern_requested(link)) { > >> + if (link->dp_link.test_video.test_dyn_range & > >> + DP_TEST_DYNAMIC_RANGE_CEA) > >> + cc = DP_MISC0_CEA_RGB; > >> + } > >> > >> return cc; > >> } > >> diff --git a/drivers/gpu/drm/msm/dp/dp_link.h > >> b/drivers/gpu/drm/msm/dp/dp_link.h > >> index 9dd4dd9..fe8f716 100644 > >> --- a/drivers/gpu/drm/msm/dp/dp_link.h > >> +++ b/drivers/gpu/drm/msm/dp/dp_link.h > >> @@ -12,6 +12,9 @@ > >> #define DP_TEST_BIT_DEPTH_UNKNOWN 0x > >> #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) > >> > >> +#define DP_MISC0_LEGACY_RGB0 > >> +#define DP_MISC0_CEA_RGB 0x04 > > These should go to dp_reg.h and should start with DP_MISC0_COLORIMETRY_CFG > > > >> + > >> struct dp_link_info { > >> unsigned char revision; > >> unsigned int rate; > >> -- > >> 2.7.4 > >> > > -- With best wishes Dmitry
Re: [PATCH v2] drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()
Hi, On Wed, Jan 17, 2024 at 9:34 AM Doug Anderson wrote: > > Hi, > > On Tue, Jan 9, 2024 at 8:52 AM Doug Anderson wrote: > > > > Hi, > > > > On Tue, Jan 9, 2024 at 4:05 AM Pin-yen Lin wrote: > > > > > > The ps8640 bridge seems to expect everything to be power cycled at the > > > disable process, but sometimes ps8640_aux_transfer() holds the runtime > > > PM reference and prevents the bridge from suspend. > > > > > > Prevent that by introducing a mutex lock between ps8640_aux_transfer() > > > and .post_disable() to make sure the bridge is really powered off. > > > > > > Fixes: 826cff3f7ebb ("drm/bridge: parade-ps8640: Enable runtime power > > > management") > > > Signed-off-by: Pin-yen Lin > > > --- > > > > > > Changes in v2: > > > - Use mutex instead of the completion and autosuspend hack > > > > > > drivers/gpu/drm/bridge/parade-ps8640.c | 16 > > > 1 file changed, 16 insertions(+) > > > > This looks OK to me now. > > > > Reviewed-by: Douglas Anderson > > > > I'll let it stew on the mailing list for ~1 week and then land it in > > drm-misc-fixes unless there are additional comments. > > Pushed to drm-misc-fixes: > > 26db46bc9c67 drm/bridge: parade-ps8640: Ensure bridge is suspended in > .post_disable() Crud. I landed this and then almost immediately hit a bug with it. :( I've posted up the fix: https://lore.kernel.org/r/20240117103502.1.Ib726a0184913925efc7e99c4d4fc801982e1bc24@changeid -Doug
[PATCH] drm/bridge: parade-ps8640: Make sure we drop the AUX mutex in the error case
After commit 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()"), if we hit the error case in ps8640_aux_transfer() then we return without dropping the mutex. Fix this oversight. Fixes: 26db46bc9c67 ("drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()") Signed-off-by: Douglas Anderson --- Sorry for missing this in my review! :( Given that this is really simple and I'd rather the buggy commit not be there for long, if I can get a quick Reviewed-by tag on this patch I'll land it without the typical stewing period. drivers/gpu/drm/bridge/parade-ps8640.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 166bfc725ef4..14d4dcf239da 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -351,11 +351,13 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux, ret = _ps8640_wait_hpd_asserted(ps_bridge, 200 * 1000); if (ret) { pm_runtime_put_sync_suspend(dev); - return ret; + goto exit; } ret = ps8640_aux_transfer_msg(aux, msg); pm_runtime_mark_last_busy(dev); pm_runtime_put_autosuspend(dev); + +exit: mutex_unlock(&ps_bridge->aux_lock); return ret; -- 2.43.0.381.gb435a96ce8-goog
Re: [PATCH v1 6/6] drm/lima: improve some pp debug messages
On Tue, Jan 16, 2024 at 7:12 PM Erico Nunes wrote: > > Make the messages more consistent by showing the pp name. > > Signed-off-by: Erico Nunes Reviewed-by: Vasily Khoruzhick > --- > drivers/gpu/drm/lima/lima_pp.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c > index ac097dd75072..d9e178d6645d 100644 > --- a/drivers/gpu/drm/lima/lima_pp.c > +++ b/drivers/gpu/drm/lima/lima_pp.c > @@ -197,7 +197,7 @@ static int lima_pp_hard_reset(struct lima_ip *ip) > pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_FORCE_RESET); > ret = lima_poll_timeout(ip, lima_pp_hard_reset_poll, 10, 100); > if (ret) { > - dev_err(dev->dev, "pp hard reset timeout\n"); > + dev_err(dev->dev, "pp %s hard reset timeout\n", > lima_ip_name(ip)); > return ret; > } > > @@ -423,8 +423,8 @@ static void lima_pp_task_error(struct lima_sched_pipe > *pipe) > for (i = 0; i < pipe->num_processor; i++) { > struct lima_ip *ip = pipe->processor[i]; > > - dev_err(ip->dev->dev, "pp task error %d int_state=%x > status=%x\n", > - i, pp_read(LIMA_PP_INT_STATUS), > pp_read(LIMA_PP_STATUS)); > + dev_err(ip->dev->dev, "pp %s task error int_state=%x > status=%x\n", > + lima_ip_name(ip), pp_read(LIMA_PP_INT_STATUS), > pp_read(LIMA_PP_STATUS)); > > lima_pp_hard_reset(ip); > } > -- > 2.43.0 >
Re: [PATCH v1 5/6] drm/lima: remove guilty drm_sched context handling
On Tue, Jan 16, 2024 at 7:12 PM Erico Nunes wrote: > > Marking the context as guilty currently only makes the application which > hits a single timeout problem to stop its rendering context entirely. > All jobs submitted later are dropped from the guilty context. > > Lima runs on fairly underpowered hardware for modern standards and it is > not entirely unreasonable that a rendering job may time out occasionally > due to high system load or too demanding application stack. In this case > it would be generally preferred to report the error but try to keep the > application going. > > Other similar embedded GPU drivers don't make use of the guilty context > flag. Now that there are reliability improvements to the lima timeout > recovery handling, drop the guilty contexts to let the application keep > running in this case. > > Signed-off-by: Erico Nunes Reviewed-by: Vasily Khoruzhick > --- > drivers/gpu/drm/lima/lima_ctx.c | 2 +- > drivers/gpu/drm/lima/lima_ctx.h | 1 - > drivers/gpu/drm/lima/lima_sched.c | 5 ++--- > drivers/gpu/drm/lima/lima_sched.h | 3 +-- > 4 files changed, 4 insertions(+), 7 deletions(-) > > diff --git a/drivers/gpu/drm/lima/lima_ctx.c b/drivers/gpu/drm/lima/lima_ctx.c > index 8389f2d7d021..0e668fc1e0f9 100644 > --- a/drivers/gpu/drm/lima/lima_ctx.c > +++ b/drivers/gpu/drm/lima/lima_ctx.c > @@ -19,7 +19,7 @@ int lima_ctx_create(struct lima_device *dev, struct > lima_ctx_mgr *mgr, u32 *id) > kref_init(&ctx->refcnt); > > for (i = 0; i < lima_pipe_num; i++) { > - err = lima_sched_context_init(dev->pipe + i, ctx->context + > i, &ctx->guilty); > + err = lima_sched_context_init(dev->pipe + i, ctx->context + > i); > if (err) > goto err_out0; > } > diff --git a/drivers/gpu/drm/lima/lima_ctx.h b/drivers/gpu/drm/lima/lima_ctx.h > index 74e2be09090f..5b1063ce968b 100644 > --- a/drivers/gpu/drm/lima/lima_ctx.h > +++ b/drivers/gpu/drm/lima/lima_ctx.h > @@ -13,7 +13,6 @@ struct lima_ctx { > struct kref refcnt; > struct lima_device *dev; > struct lima_sched_context context[lima_pipe_num]; > - atomic_t guilty; > > /* debug info */ > char pname[TASK_COMM_LEN]; > diff --git a/drivers/gpu/drm/lima/lima_sched.c > b/drivers/gpu/drm/lima/lima_sched.c > index 9449b81bcd5b..496c79713fe8 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -154,13 +154,12 @@ void lima_sched_task_fini(struct lima_sched_task *task) > } > > int lima_sched_context_init(struct lima_sched_pipe *pipe, > - struct lima_sched_context *context, > - atomic_t *guilty) > + struct lima_sched_context *context) > { > struct drm_gpu_scheduler *sched = &pipe->base; > > return drm_sched_entity_init(&context->base, > DRM_SCHED_PRIORITY_NORMAL, > -&sched, 1, guilty); > +&sched, 1, NULL); > } > > void lima_sched_context_fini(struct lima_sched_pipe *pipe, > diff --git a/drivers/gpu/drm/lima/lima_sched.h > b/drivers/gpu/drm/lima/lima_sched.h > index 34050facb110..677e908b53f8 100644 > --- a/drivers/gpu/drm/lima/lima_sched.h > +++ b/drivers/gpu/drm/lima/lima_sched.h > @@ -93,8 +93,7 @@ int lima_sched_task_init(struct lima_sched_task *task, > void lima_sched_task_fini(struct lima_sched_task *task); > > int lima_sched_context_init(struct lima_sched_pipe *pipe, > - struct lima_sched_context *context, > - atomic_t *guilty); > + struct lima_sched_context *context); > void lima_sched_context_fini(struct lima_sched_pipe *pipe, > struct lima_sched_context *context); > struct dma_fence *lima_sched_context_queue_task(struct lima_sched_task > *task); > -- > 2.43.0 >
Re: [PATCH v2] drm/msm/dp: correct configure Colorimetry Indicator Field at MISC0
On 1/17/2024 10:12 AM, Dmitry Baryshkov wrote: On Wed, 17 Jan 2024 at 19:54, Kuogee Hsieh wrote: MSA MISC0 bit 1 to 7 contains Colorimetry Indicator Field. At current implementation, at DP_TEST_DYNAMIC_RANGE_CEA case the In the current implementation, in the ... case Colorimetry Indicator Field is mistakenly left shifted one extra bit. This doesn't make sense. You say that the value is mistakenly shifted, but the shift is still in place in dp_catalog_ctrl_config_misc(). The problem is at link->dp_link.test_video.test_dyn_range = (bp & DP_TEST_DYNAMIC_RANGE_CEA); <== this from reading dpcd directly where ==> DP_TEST_DYNAMIC_RANGE_CEA is (1 << 3) within dp_catalog_ctrl_config_misc(), cc will be left shift one more bit. so that cc is totally is left shifted 4 bits (bit 4). at misc0, it should be bit 3 set only for CEA_RGB. This patch return correct value of colorimetry at dp_link_get_colorimetry_config() to fix this problem. See Documentation/process/submitting-patches.rst#_describe_changes Changes in V2: -- drop retrieving colorimetry from colorspace -- drop dr = link->dp_link.test_video.test_dyn_range assignment Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_link.c | 11 ++- drivers/gpu/drm/msm/dp/dp_link.h | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 98427d4..2e1bdaf 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -1082,7 +1082,7 @@ int dp_link_process_request(struct dp_link *dp_link) int dp_link_get_colorimetry_config(struct dp_link *dp_link) { - u32 cc; + u32 cc = DP_MISC0_LEGACY_RGB; struct dp_link_private *link; if (!dp_link) { @@ -1096,10 +1096,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) * Unless a video pattern CTS test is ongoing, use RGB_VESA * Only RGB_VESA and RGB_CEA supported for now */ - if (dp_link_is_video_pattern_requested(link)) - cc = link->dp_link.test_video.test_dyn_range; - else - cc = DP_TEST_DYNAMIC_RANGE_VESA; + if (dp_link_is_video_pattern_requested(link)) { + if (link->dp_link.test_video.test_dyn_range & + DP_TEST_DYNAMIC_RANGE_CEA) + cc = DP_MISC0_CEA_RGB; + } return cc; } diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 9dd4dd9..fe8f716 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -12,6 +12,9 @@ #define DP_TEST_BIT_DEPTH_UNKNOWN 0x #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) +#define DP_MISC0_LEGACY_RGB0 +#define DP_MISC0_CEA_RGB 0x04 These should go to dp_reg.h and should start with DP_MISC0_COLORIMETRY_CFG + struct dp_link_info { unsigned char revision; unsigned int rate; -- 2.7.4
Re: [PATCH v1 4/6] drm/lima: handle spurious timeouts due to high irq latency
On Tue, Jan 16, 2024 at 7:12 PM Erico Nunes wrote: > > There are several unexplained and unreproduced cases of rendering > timeouts with lima, for which one theory is high IRQ latency coming from > somewhere else in the system. > This kind of occurrence may cause applications to trigger unnecessary > resets of the GPU or even applications to hang if it hits an issue in > the recovery path. > Panfrost already does some special handling to account for such > "spurious timeouts", it makes sense to have this in lima too to reduce > the chance that it hit users. > > Signed-off-by: Erico Nunes Reviewed-by: Vasily Khoruzhick > --- > drivers/gpu/drm/lima/lima_sched.c | 32 ++- > drivers/gpu/drm/lima/lima_sched.h | 2 ++ > 2 files changed, 29 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > b/drivers/gpu/drm/lima/lima_sched.c > index 66317296d831..9449b81bcd5b 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -1,6 +1,7 @@ > // SPDX-License-Identifier: GPL-2.0 OR MIT > /* Copyright 2017-2019 Qiang Yu */ > > +#include > #include > #include > #include > @@ -223,10 +224,7 @@ static struct dma_fence *lima_sched_run_job(struct > drm_sched_job *job) > > task->fence = &fence->base; > > - /* for caller usage of the fence, otherwise irq handler > -* may consume the fence before caller use it > -*/ > - dma_fence_get(task->fence); > + task->done_fence = dma_fence_get(task->fence); > > pipe->current_task = task; > > @@ -401,9 +399,33 @@ static enum drm_gpu_sched_stat > lima_sched_timedout_job(struct drm_sched_job *job > struct lima_sched_pipe *pipe = to_lima_pipe(job->sched); > struct lima_sched_task *task = to_lima_task(job); > struct lima_device *ldev = pipe->ldev; > + struct lima_ip *ip = pipe->processor[0]; > + > + /* > +* If the GPU managed to complete this jobs fence, the timeout is > +* spurious. Bail out. > +*/ > + if (dma_fence_is_signaled(task->done_fence)) { > + DRM_WARN("%s spurious timeout\n", lima_ip_name(ip)); > + return DRM_GPU_SCHED_STAT_NOMINAL; > + } > + > + /* > +* Lima IRQ handler may take a long time to process an interrupt > +* if there is another IRQ handler hogging the processing. > +* In order to catch such cases and not report spurious Lima job > +* timeouts, synchronize the IRQ handler and re-check the fence > +* status. > +*/ > + synchronize_irq(ip->irq); > + > + if (dma_fence_is_signaled(task->done_fence)) { > + DRM_WARN("%s unexpectedly high interrupt latency\n", > lima_ip_name(ip)); > + return DRM_GPU_SCHED_STAT_NOMINAL; > + } > > if (!pipe->error) > - DRM_ERROR("lima job timeout\n"); > + DRM_ERROR("%s lima job timeout\n", lima_ip_name(ip)); > > drm_sched_stop(&pipe->base, &task->base); > > diff --git a/drivers/gpu/drm/lima/lima_sched.h > b/drivers/gpu/drm/lima/lima_sched.h > index 6a11764d87b3..34050facb110 100644 > --- a/drivers/gpu/drm/lima/lima_sched.h > +++ b/drivers/gpu/drm/lima/lima_sched.h > @@ -29,6 +29,8 @@ struct lima_sched_task { > bool recoverable; > struct lima_bo *heap; > > + struct dma_fence *done_fence; > + > /* pipe fence */ > struct dma_fence *fence; > }; > -- > 2.43.0 >
Re: [PATCH v1 3/6] drm/lima: set bus_stop bit before hard reset
On Tue, Jan 16, 2024 at 7:12 PM Erico Nunes wrote: > > This is required for reliable hard resets. Otherwise, doing a hard reset > while a task is still running (such as a task which is being stopped by > the drm_sched timeout handler) may result in random mmu write timeouts > or lockups which cause the entire gpu to hang. It looks like Mali driver is doing the same, so it totally makes sense. > Signed-off-by: Erico Nunes Reviewed-by: Vasily Khoruzhick > --- > drivers/gpu/drm/lima/lima_pp.c | 13 + > 1 file changed, 13 insertions(+) > > diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c > index a8f8f63b8295..ac097dd75072 100644 > --- a/drivers/gpu/drm/lima/lima_pp.c > +++ b/drivers/gpu/drm/lima/lima_pp.c > @@ -168,6 +168,11 @@ static void lima_pp_write_frame(struct lima_ip *ip, u32 > *frame, u32 *wb) > } > } > > +static int lima_pp_bus_stop_poll(struct lima_ip *ip) > +{ > + return !!(pp_read(LIMA_PP_STATUS) & LIMA_PP_STATUS_BUS_STOPPED); > +} > + > static int lima_pp_hard_reset_poll(struct lima_ip *ip) > { > pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC01A); > @@ -181,6 +186,14 @@ static int lima_pp_hard_reset(struct lima_ip *ip) > > pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0xC0FFE000); > pp_write(LIMA_PP_INT_MASK, 0); > + > + pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_STOP_BUS); > + ret = lima_poll_timeout(ip, lima_pp_bus_stop_poll, 10, 100); > + if (ret) { > + dev_err(dev->dev, "pp %s bus stop timeout\n", > lima_ip_name(ip)); > + return ret; > + } > + > pp_write(LIMA_PP_CTRL, LIMA_PP_CTRL_FORCE_RESET); > ret = lima_poll_timeout(ip, lima_pp_hard_reset_poll, 10, 100); > if (ret) { > -- > 2.43.0 >
Re: [PATCH v1 2/6] drm/lima: reset async_reset on pp hard reset
On Tue, Jan 16, 2024 at 7:12 PM Erico Nunes wrote: > > Lima pp jobs use an async reset to avoid having to wait for the soft > reset right after a job. The soft reset is done at the end of a job and > a reset_complete flag is expected to be set at the next job. > However, in case the user runs into a job timeout from any application, > a hard reset is issued to the hardware. This hard reset clears the > reset_complete flag, which causes an error message to show up before the > next job. > This is probably harmless for the execution but can be very confusing to > debug, as it blames a reset timeout on the next application to submit a > job. > Reset the async_reset flag when doing the hard reset so that we don't > get that message. > > Signed-off-by: Erico Nunes Reviewed-by: Vasily Khoruzhick > --- > drivers/gpu/drm/lima/lima_pp.c | 7 +++ > 1 file changed, 7 insertions(+) > > diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c > index a5c95bed08c0..a8f8f63b8295 100644 > --- a/drivers/gpu/drm/lima/lima_pp.c > +++ b/drivers/gpu/drm/lima/lima_pp.c > @@ -191,6 +191,13 @@ static int lima_pp_hard_reset(struct lima_ip *ip) > pp_write(LIMA_PP_PERF_CNT_0_LIMIT, 0); > pp_write(LIMA_PP_INT_CLEAR, LIMA_PP_IRQ_MASK_ALL); > pp_write(LIMA_PP_INT_MASK, LIMA_PP_IRQ_MASK_USED); > + > + /* > +* if there was an async soft reset queued, > +* don't wait for it in the next job > +*/ > + ip->data.async_reset = false; > + > return 0; > } > > -- > 2.43.0 >
Re: [PATCH v1 1/6] drm/lima: fix devfreq refcount imbalance for job timeouts
On Tue, Jan 16, 2024 at 7:12 PM Erico Nunes wrote: > > In case a task manages to complete but it took just long enough to also > trigger the timeout handler, the current code results in a refcount > imbalance on lima_pm_idle. > > While this can be a rare occurrence, when it happens it may fill user > logs with stack traces such as: > > [10136.669170] WARNING: CPU: 0 PID: 0 at > drivers/gpu/drm/lima/lima_devfreq.c:205 lima_devfreq_record_idle+0xa0/0xb0 > ... > [10136.669459] pc : lima_devfreq_record_idle+0xa0/0xb0 > ... > [10136.669628] Call trace: > [10136.669634] lima_devfreq_record_idle+0xa0/0xb0 > [10136.669646] lima_sched_pipe_task_done+0x5c/0xb0 > [10136.669656] lima_gp_irq_handler+0xa8/0x120 > [10136.669666] __handle_irq_event_percpu+0x48/0x160 > [10136.669679] handle_irq_event+0x4c/0xc0 > > The imbalance happens because lima_sched_pipe_task_done() already calls > lima_pm_idle for this case if there was no error. > Check the error flag in the timeout handler to ensure we can never run > into this case. > > Signed-off-by: Erico Nunes Reviewed-by: Vasily Khoruzhick > --- > drivers/gpu/drm/lima/lima_sched.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/lima/lima_sched.c > b/drivers/gpu/drm/lima/lima_sched.c > index c3bf8cda8498..66317296d831 100644 > --- a/drivers/gpu/drm/lima/lima_sched.c > +++ b/drivers/gpu/drm/lima/lima_sched.c > @@ -427,7 +427,8 @@ static enum drm_gpu_sched_stat > lima_sched_timedout_job(struct drm_sched_job *job > pipe->current_vm = NULL; > pipe->current_task = NULL; > > - lima_pm_idle(ldev); > + if (pipe->error) > + lima_pm_idle(ldev); > > drm_sched_resubmit_jobs(&pipe->base); > drm_sched_start(&pipe->base, true); > -- > 2.43.0 >
Re: [PATCH v2] drm/msm/dp: correct configure Colorimetry Indicator Field at MISC0
On Wed, 17 Jan 2024 at 19:54, Kuogee Hsieh wrote: > > MSA MISC0 bit 1 to 7 contains Colorimetry Indicator Field. At > current implementation, at DP_TEST_DYNAMIC_RANGE_CEA case the In the current implementation, in the ... case > Colorimetry Indicator Field is mistakenly left shifted one extra > bit. This doesn't make sense. You say that the value is mistakenly shifted, but the shift is still in place in dp_catalog_ctrl_config_misc(). > This patch return correct value of colorimetry at > dp_link_get_colorimetry_config() to fix this problem. See Documentation/process/submitting-patches.rst#_describe_changes > > Changes in V2: > -- drop retrieving colorimetry from colorspace > -- drop dr = link->dp_link.test_video.test_dyn_range assignment > > Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") > Signed-off-by: Kuogee Hsieh > --- > drivers/gpu/drm/msm/dp/dp_link.c | 11 ++- > drivers/gpu/drm/msm/dp/dp_link.h | 3 +++ > 2 files changed, 9 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/msm/dp/dp_link.c > b/drivers/gpu/drm/msm/dp/dp_link.c > index 98427d4..2e1bdaf 100644 > --- a/drivers/gpu/drm/msm/dp/dp_link.c > +++ b/drivers/gpu/drm/msm/dp/dp_link.c > @@ -1082,7 +1082,7 @@ int dp_link_process_request(struct dp_link *dp_link) > > int dp_link_get_colorimetry_config(struct dp_link *dp_link) > { > - u32 cc; > + u32 cc = DP_MISC0_LEGACY_RGB; > struct dp_link_private *link; > > if (!dp_link) { > @@ -1096,10 +1096,11 @@ int dp_link_get_colorimetry_config(struct dp_link > *dp_link) > * Unless a video pattern CTS test is ongoing, use RGB_VESA > * Only RGB_VESA and RGB_CEA supported for now > */ > - if (dp_link_is_video_pattern_requested(link)) > - cc = link->dp_link.test_video.test_dyn_range; > - else > - cc = DP_TEST_DYNAMIC_RANGE_VESA; > + if (dp_link_is_video_pattern_requested(link)) { > + if (link->dp_link.test_video.test_dyn_range & > + DP_TEST_DYNAMIC_RANGE_CEA) > + cc = DP_MISC0_CEA_RGB; > + } > > return cc; > } > diff --git a/drivers/gpu/drm/msm/dp/dp_link.h > b/drivers/gpu/drm/msm/dp/dp_link.h > index 9dd4dd9..fe8f716 100644 > --- a/drivers/gpu/drm/msm/dp/dp_link.h > +++ b/drivers/gpu/drm/msm/dp/dp_link.h > @@ -12,6 +12,9 @@ > #define DP_TEST_BIT_DEPTH_UNKNOWN 0x > #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) > > +#define DP_MISC0_LEGACY_RGB0 > +#define DP_MISC0_CEA_RGB 0x04 These should go to dp_reg.h and should start with DP_MISC0_COLORIMETRY_CFG > + > struct dp_link_info { > unsigned char revision; > unsigned int rate; > -- > 2.7.4 > -- With best wishes Dmitry
[PATCH] dma-buf: heaps: Don't track CMA dma-buf pages under RssFile
DMA buffers allocated from the CMA dma-buf heap get counted under RssFile for processes that map them and trigger page faults. In addition to the incorrect accounting reported to userspace, reclaim behavior was influenced by the MM_FILEPAGES counter until linux 6.8, but this memory is not reclaimable. [1] Change the CMA dma-buf heap to set VM_PFNMAP on the VMA so MM does not poke at the memory managed by this dma-buf heap, and use vmf_insert_pfn to correct the RSS accounting. The system dma-buf heap does not suffer from this issue since remap_pfn_range is used during the mmap of the buffer, which also sets VM_PFNMAP on the VMA. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/mm/vmscan.c?id=fb46e22a9e3863e08aef8815df9f17d0f4b9aede Fixes: b61614ec318a ("dma-buf: heaps: Add CMA heap to dmabuf heaps") Signed-off-by: T.J. Mercier --- drivers/dma-buf/heaps/cma_heap.c | 7 +++ 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index ee899f8e6721..4a63567e93ba 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -168,10 +168,7 @@ static vm_fault_t cma_heap_vm_fault(struct vm_fault *vmf) if (vmf->pgoff > buffer->pagecount) return VM_FAULT_SIGBUS; - vmf->page = buffer->pages[vmf->pgoff]; - get_page(vmf->page); - - return 0; + return vmf_insert_pfn(vma, vmf->address, page_to_pfn(buffer->pages[vmf->pgoff])); } static const struct vm_operations_struct dma_heap_vm_ops = { @@ -185,6 +182,8 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0) return -EINVAL; + vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); + vma->vm_ops = &dma_heap_vm_ops; vma->vm_private_data = buffer; -- 2.43.0.381.gb435a96ce8-goog
[PATCH v2] drm/msm/dp: correct configure Colorimetry Indicator Field at MISC0
MSA MISC0 bit 1 to 7 contains Colorimetry Indicator Field. At current implementation, at DP_TEST_DYNAMIC_RANGE_CEA case the Colorimetry Indicator Field is mistakenly left shifted one extra bit. This patch return correct value of colorimetry at dp_link_get_colorimetry_config() to fix this problem. Changes in V2: -- drop retrieving colorimetry from colorspace -- drop dr = link->dp_link.test_video.test_dyn_range assignment Fixes: c943b4948b58 ("drm/msm/dp: add displayPort driver support") Signed-off-by: Kuogee Hsieh --- drivers/gpu/drm/msm/dp/dp_link.c | 11 ++- drivers/gpu/drm/msm/dp/dp_link.h | 3 +++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c index 98427d4..2e1bdaf 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.c +++ b/drivers/gpu/drm/msm/dp/dp_link.c @@ -1082,7 +1082,7 @@ int dp_link_process_request(struct dp_link *dp_link) int dp_link_get_colorimetry_config(struct dp_link *dp_link) { - u32 cc; + u32 cc = DP_MISC0_LEGACY_RGB; struct dp_link_private *link; if (!dp_link) { @@ -1096,10 +1096,11 @@ int dp_link_get_colorimetry_config(struct dp_link *dp_link) * Unless a video pattern CTS test is ongoing, use RGB_VESA * Only RGB_VESA and RGB_CEA supported for now */ - if (dp_link_is_video_pattern_requested(link)) - cc = link->dp_link.test_video.test_dyn_range; - else - cc = DP_TEST_DYNAMIC_RANGE_VESA; + if (dp_link_is_video_pattern_requested(link)) { + if (link->dp_link.test_video.test_dyn_range & + DP_TEST_DYNAMIC_RANGE_CEA) + cc = DP_MISC0_CEA_RGB; + } return cc; } diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h index 9dd4dd9..fe8f716 100644 --- a/drivers/gpu/drm/msm/dp/dp_link.h +++ b/drivers/gpu/drm/msm/dp/dp_link.h @@ -12,6 +12,9 @@ #define DP_TEST_BIT_DEPTH_UNKNOWN 0x #define DP_LINK_CAP_ENHANCED_FRAMING (1 << 0) +#define DP_MISC0_LEGACY_RGB0 +#define DP_MISC0_CEA_RGB 0x04 + struct dp_link_info { unsigned char revision; unsigned int rate; -- 2.7.4
Re: [PATCH RFC 0/4] Support for Simulated Panels
Hi Jani and Maxime On 1/17/2024 2:16 AM, Jani Nikula wrote: On Wed, 17 Jan 2024, Maxime Ripard wrote: Hi, On Tue, Jan 16, 2024 at 02:22:03PM -0800, Jessica Zhang wrote: This series introduces a simulated MIPI DSI panel. Currently, the only way to validate DSI connectors is with a physical panel. Since obtaining physical panels for all possible DSI configurations is logistically infeasible, introduce a way for DSI drivers to simulate a panel. This will be helpful in catching DSI misconfiguration bugs and catching performance issues for high FPS panels that might not be easily obtainable. For now, the simulated panel driver only supports setting customized modes via the panel_simlation.mode modparam. Eventually, we would like to add more customizations (such as configuring DSC, dual DSI, etc.). I think that it's more complicated than it needs to be. Both too complicated and not complicated enough! :p The end goal is to have a framework to be able to validate the display pipeline with MIPI panels of any resolution , DSC/non-DSC, different MIPI flags etc. Historically, QC has been having an in-house framework to validate the panels in a simulated way as its logistically not possible to procure every panel from every vendor. This has been working pretty well but its not upstream yet. So we would like to work with the community to work on a model which works for everyone and this RFC was initiated with that in mind. There is simulation infrastructure in place in upstream for HDMI/DP in the form of chamelium based testing in IGT but no such fwk exists for DSI displays. Different MIPI panels and resolutions test out not only the DSI controller but the entire display pipeline as based on resolution, compression and MIPI mode flags different parts of the pipeline can get exercised. Why do we need to support (and switch to) both the actual and "simulated" panel? As per my discussion on IRC with the panel/bridge maintainers and DT maintainers, a simulation panel does not qualify for its own devicetree as its not a real hardware so we needed to come up with a way to have a module which can be attached to the encoder without its own bindings and devicetree. Thats what led to this RFC. Wouldn't it be simpler if we had a vkms-like panel that we could either configure from DT or from debugfs that would just be registered the usual way and would be the only panel we register? No, we need to have validate actual hardware pipeline with the simulated panel. With vkms, actual display pipeline will not be validated. With incorrect display pipeline misconfigurations arising from different panel combinations, this can easily be caught with any existing IGT CRC testing. In addition, all performance related bugs can also be easily caught by simulating high resolution displays. I get the idea of trying to test DSI code without panels, and looking at the goals above, I think your vkms suggestion is going to fall short of those goals. However, my gut feeling is that creating a simulated panel to catch DSI misconfiguration etc. is going to be insanely complicated, and this series doesn't even scratch the surface. I guess my questions are, what's the scope here really, are those goals realistic, does more code already exist beyond this skeleton? This series is only a starting RFC to be able to validate any display mode. This would have to be extended to be able to customize different pieces of the panel. Lets talk about the customizable pieces: 1) Display resolution with timings (drm_display_mode) 2) Compression/non-compression 3) Command mode/Video mode 4) MIPI mode flags 5) DCS commands for panel enable/disable and other panel sequences 6) Power-up/Power-down sequence for the panel Without a physical panel, yes its hard to validate if anything is wrong with (4) OR (5), the display might not come up at all visually. But from our experience, thats only a small portion and the real benefit of this framework will actually be from the validation failures we will catch from (1) to (4). This RFC only provides a way to customize (1) at the moment as we wanted to get some feedback from the community about the best way which will work for everyone to customize all these parameters. We are willing to expand this series based on the generic way we agree on to customize other params. Yes, debugfs is an option too. But typically MIPI displays need some parameters configured to attach the panel to the encoder. So perhaps we can boot the simulation panel with a default resolution passed through command line and then across a modeset switch (1) to (4). Thanks Abhinav BR, Jani.
Re: [PATCH v2] drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()
Hi, On Tue, Jan 9, 2024 at 8:52 AM Doug Anderson wrote: > > Hi, > > On Tue, Jan 9, 2024 at 4:05 AM Pin-yen Lin wrote: > > > > The ps8640 bridge seems to expect everything to be power cycled at the > > disable process, but sometimes ps8640_aux_transfer() holds the runtime > > PM reference and prevents the bridge from suspend. > > > > Prevent that by introducing a mutex lock between ps8640_aux_transfer() > > and .post_disable() to make sure the bridge is really powered off. > > > > Fixes: 826cff3f7ebb ("drm/bridge: parade-ps8640: Enable runtime power > > management") > > Signed-off-by: Pin-yen Lin > > --- > > > > Changes in v2: > > - Use mutex instead of the completion and autosuspend hack > > > > drivers/gpu/drm/bridge/parade-ps8640.c | 16 > > 1 file changed, 16 insertions(+) > > This looks OK to me now. > > Reviewed-by: Douglas Anderson > > I'll let it stew on the mailing list for ~1 week and then land it in > drm-misc-fixes unless there are additional comments. Pushed to drm-misc-fixes: 26db46bc9c67 drm/bridge: parade-ps8640: Ensure bridge is suspended in .post_disable()
Re: Userspace API for per key backlight for non HID (no hidraw) keyboards
Hi All, On 11/27/23 11:59, Werner Sembach wrote: > I also stumbled across a new Problem: > > We have an upcoming device that has a per-key keyboard backlight, but does > the control completely via a wmi/acpi interface. So no usable hidraw here for > a potential userspace driver implementation ... > > So a quick summary for the ideas floating in this thread so far: > > 1. Expand leds interface allowing arbitrary modes with semi arbitrary > optional attributes: > > - Pro: > > - Still offers all default attributes for use with UPower > > - Fairly simple to implement from the preexisting codebase > > - Could be implemented for all (to me) known internal keyboard > backlights > > - Con: > > - Violates the simplicity paradigm of the leds interface (e.g. with > this one leds entry controls possible multiple leds) So what you are suggesting here is having some way (a-z + other sysfs attr?) to use a single LED class device and then extend that to allow setting all keys ? This does not seem like a good idea to me and this will also cause issues when doing animations in software, since this API will likely be slow. And if the API is not slow, then it will likely involve some sort of binary sysfs file for setting multiple keys rather then 1 file per key which would break the normal 1 file per setting sysfs paradigm. > 2. Implement per-key keyboards as auxdisplay > > - Pro: > > - Already has a concept for led positions With a "concept" you mean simple x,y positioning or is there something more advanced here that I'm aware of ? > - Is conceptually closer to "multiple leds forming a singular entity" > > - Con: > > - No preexisting UPower support > > - No concept for special hardware lightning modes > > - No support for arbitrary led outlines yet (e.g. ISO style enter-key) Hmm, so there is very little documentation on this and what docs there is: Documentation/admin-guide/auxdisplay/cfag12864b.rst as well as the example program how to uses this suggests that this is using the old /dev/fb# interface which we are sorta trying to retire. > 3. Implement in input subsystem > > - Pro: > > - Preexisting concept for keys and key purpose > > - Con: > > - Not in scope for subsystem > > - No other preexisting light infrastructure Dmitry actually recently nacked the addition of a LED_MIC_MUTE define to include/uapi/linux/input-event-codes.h which was intended to be able to allow the input LED support with standard HID mic-mute leds (spk-mute is already supported this way). Dmitry was very clear that no new LEDs must be added and that any new LED support should be done through the LED subsytem, so I do not think that something like this is going to fly. > 4. Implement a simple leds driver only supporting a small subset of the > capabilities and make it disable-able for a userspace driver to take over > > - Pro: > > - Most simple to implement basic support > > - In scope for led subsystem simplicity paradigm > > - Con: > > - Not all built in keyboard backlights can be implemented in a > userspace only driver Right, so this is basically what we have been discussing in the other part of the thread with the: /sys/bus/hid/devices/0003::./disable_kbd_backlight_support proposal to unregister the kernel's LED class device and then allow userspace to do whatever it wants through /dev/hidraw without the kernel also trying to access the backlight functionality at the same time. AFAIK there already is a bunch of userspace support for per key addressable kbd RGB backlights using hidraw support, so this way we can use the momentum / code of these existing projects, at least for existing hidraw keyboards and adding support for: /sys/bus/hid/devices/0003::./disable_kbd_backlight_support to these existing projects should be simple. Yet this will not work for your mentioned "control completely via a wmi/acpi interface". Still I think we should go the same route for those adding a misc-char device or something like that to allow making WMI calls from userspace (like Windows can do). Maybe with an allow list per GUID to only allow specific calls, so that we can avoid possible dangerous calls. Armin Wolf recently became the WMI bus maintainer. Armin, we are discussing how to deal with (laptop) keyboards which have a separate RGB LED per key and how to control those LEDs. So far per key addressable keyboard backlighting has always been HID based, so any existing support is just userspace based using /dev/hidraw. In my experience the problem with supporting gaming peripherals is that there is interest in it, but not really enough interest to keep a sustained momentum behind projects, especially not when it comes to taking code from a fun weekend hack to upstreaming them into bigger projects like the kernel. So I would like to
Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
On 17/01/2024 16:26, Jani Nikula wrote: On Thu, 04 Jan 2024, Jocelyn Falempe wrote: This is needed for drm_panic, to draw the font, and fill the background color, in multiple color format. v5: * Change the drawing API, use drm_fb_blit_from_r1() to draw the font. * Also add drm_fb_fill() to fill area with background color. v6: * fix __le32 conversion warning found by the kernel test bot Signed-off-by: Jocelyn Falempe --- drivers/gpu/drm/drm_format_helper.c | 432 ++-- include/drm/drm_format_helper.h | 9 + 2 files changed, 360 insertions(+), 81 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index b1be458ed4dd..8cbc2d747cff 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct drm_format_conv_state *state) } EXPORT_SYMBOL(drm_format_conv_state_release); +static inline __le16 drm_format_xrgb_to_rgb565(__le32 val32) Please don't use inline in C files. Just let the compiler do its job. Sure, I will remove those inline in next version. Thanks, -- Jocelyn BR, Jani. +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = ((pix & 0x00F8) >> 8) | + ((pix & 0xFC00) >> 5) | + ((pix & 0x00F8) >> 3); + return cpu_to_le16(val16); +} + +static inline __le16 drm_format_xrgb_to_rgba5551(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = ((pix & 0x00f8) >> 8) | + ((pix & 0xf800) >> 5) | + ((pix & 0x00f8) >> 2) | + BIT(0); /* set alpha bit */ + return cpu_to_le16(val16); +} + +static inline __le16 drm_format_xrgb_to_xrgb1555(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = ((pix & 0x00f8) >> 9) | + ((pix & 0xf800) >> 6) | + ((pix & 0x00f8) >> 3); + return cpu_to_le16(val16); +} + +static inline __le16 drm_format_xrgb_to_argb1555(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = BIT(15) | /* set alpha bit */ + ((pix & 0x00f8) >> 9) | + ((pix & 0xf800) >> 6) | + ((pix & 0x00f8) >> 3); + return cpu_to_le16(val16); +} + +static inline __le32 drm_format_xrgb_to_argb(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 |= GENMASK(31, 24); /* fill alpha bits */ + return cpu_to_le32(val32); +} + +static inline __le32 drm_format_xrgb_to_xbgr(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00ff) >> 16) << 0 | + ((val32 & 0xff00) >> 8) << 8 | + ((val32 & 0x00ff) >> 0) << 16 | + ((val32 & 0xff00) >> 24) << 24; + return cpu_to_le32(val32); +} + +static inline __le32 drm_format_xrgb_to_abgr(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00ff) >> 16) << 0 | + ((val32 & 0xff00) >> 8) << 8 | + ((val32 & 0x00ff) >> 0) << 16 | + GENMASK(31, 24); /* fill alpha bits */ + return cpu_to_le32(val32); +} + +static inline __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00FF) << 2) | + ((val32 & 0xFF00) << 4) | + ((val32 & 0x00FF) << 6); + return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03)); +} + +static inline __le32 drm_format_xrgb_to_argb2101010(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00FF) << 2) | + ((val32 & 0xFF00) << 4) | + ((val32 & 0x00FF) << 6); + val32 = GENMASK(31, 30) | /* set alpha bits */ + val32 | ((val32 >> 8) & 0x00300c03); + return cpu_to_le32(val32); +} + +/** + * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the desired format + * @color: input color, in xrgb format + * @format: output format + * + * Returns: + * Color in the format specified, casted to u32. + * Or 0 if the format is unknown. + */ +u32 drm_fb_convert_from_xrgb(u32 color, u32 format) +{ + __le32 pix = cpu_to_le32(color); + + switch (format) { + case DRM_FORMAT_RGB565: + return le16_to_cpu(drm_format_xrgb_to_rgb565(pix)); + case DRM_FORMAT_RGBA5551: + return le16_to_cpu(drm_format_xrgb_to_rgba5551(pix)); + case DRM_FORMAT_XRGB1555: + return le16_to_cpu(drm_format_xrgb_to_xrgb1555(pix)); + case DRM_FORMAT_ARGB1555: + return le16_to_cpu(drm_forma
Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill
On 17/01/2024 16:06, Thomas Zimmermann wrote: Hi Am 04.01.24 um 17:00 schrieb Jocelyn Falempe: This is needed for drm_panic, to draw the font, and fill the background color, in multiple color format. TBH, I don't like this patch at all. It looks like you're reimplementing existing functionality for a single use case; specifically drm_fb_blit(). What's wrong with the existing interfaces? drm_fb_blit() is good to copy a framebuffer to another, but is clearly unoptimal to draw font. It handles xrgb to any rgb format, and I need monochrome to any rgb format. I need to convert foreground and background color to the destination format, but using drm_fb_blit() to convert 1 pixel is tedious. It also requires an additional memory buffer, and do an additional memory copy that we don't need at all. It also has no way to fill a region with the background color. The last thing, is if I plan to add YUV support, with this implementation, I only need to write one function that convert one pixel. Otherwise I would need to add the drm_fb_r1_to_yuvxxx_line() and drm_fb_r1_to_yuv() boilerplate. Best regards, -- Jocelyn Best regards Thomas v5: * Change the drawing API, use drm_fb_blit_from_r1() to draw the font. * Also add drm_fb_fill() to fill area with background color. v6: * fix __le32 conversion warning found by the kernel test bot Signed-off-by: Jocelyn Falempe --- drivers/gpu/drm/drm_format_helper.c | 432 ++-- include/drm/drm_format_helper.h | 9 + 2 files changed, 360 insertions(+), 81 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index b1be458ed4dd..8cbc2d747cff 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -111,6 +111,153 @@ void drm_format_conv_state_release(struct drm_format_conv_state *state) } EXPORT_SYMBOL(drm_format_conv_state_release); +static inline __le16 drm_format_xrgb_to_rgb565(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = ((pix & 0x00F8) >> 8) | + ((pix & 0xFC00) >> 5) | + ((pix & 0x00F8) >> 3); + return cpu_to_le16(val16); +} + +static inline __le16 drm_format_xrgb_to_rgba5551(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = ((pix & 0x00f8) >> 8) | + ((pix & 0xf800) >> 5) | + ((pix & 0x00f8) >> 2) | + BIT(0); /* set alpha bit */ + return cpu_to_le16(val16); +} + +static inline __le16 drm_format_xrgb_to_xrgb1555(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = ((pix & 0x00f8) >> 9) | + ((pix & 0xf800) >> 6) | + ((pix & 0x00f8) >> 3); + return cpu_to_le16(val16); +} + +static inline __le16 drm_format_xrgb_to_argb1555(__le32 val32) +{ + u16 val16; + u32 pix; + + pix = le32_to_cpu(val32); + val16 = BIT(15) | /* set alpha bit */ + ((pix & 0x00f8) >> 9) | + ((pix & 0xf800) >> 6) | + ((pix & 0x00f8) >> 3); + return cpu_to_le16(val16); +} + +static inline __le32 drm_format_xrgb_to_argb(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 |= GENMASK(31, 24); /* fill alpha bits */ + return cpu_to_le32(val32); +} + +static inline __le32 drm_format_xrgb_to_xbgr(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00ff) >> 16) << 0 | + ((val32 & 0xff00) >> 8) << 8 | + ((val32 & 0x00ff) >> 0) << 16 | + ((val32 & 0xff00) >> 24) << 24; + return cpu_to_le32(val32); +} + +static inline __le32 drm_format_xrgb_to_abgr(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00ff) >> 16) << 0 | + ((val32 & 0xff00) >> 8) << 8 | + ((val32 & 0x00ff) >> 0) << 16 | + GENMASK(31, 24); /* fill alpha bits */ + return cpu_to_le32(val32); +} + +static inline __le32 drm_format_xrgb_to_xrgb2101010(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00FF) << 2) | + ((val32 & 0xFF00) << 4) | + ((val32 & 0x00FF) << 6); + return cpu_to_le32(val32 | ((val32 >> 8) & 0x00300C03)); +} + +static inline __le32 drm_format_xrgb_to_argb2101010(__le32 pix) +{ + u32 val32; + + val32 = le32_to_cpu(pix); + val32 = ((val32 & 0x00FF) << 2) | + ((val32 & 0xFF00) << 4) | + ((val32 & 0x00FF) << 6); + val32 = GENMASK(31, 30) | /* set alpha bits */ + val32 | ((val32 >> 8) & 0x00300c03); + return cpu_to_le32(val32); +} + +/** + * drm_fb_convert_from_xrgb - convert one pixel from xrgb to the desired format + * @color: input color, in xrgb format + * @format: output format + * + * Returns: + * Color in the format specified, casted to u32. + * Or 0 i
Re: [PATCH 08/11] ARM: dts: DRA7xx: Add device tree entry for SGX GPU
On 1/10/24 2:29 AM, Tony Lindgren wrote: * Andrew Davis [240109 17:20]: --- a/arch/arm/boot/dts/ti/omap/dra7.dtsi +++ b/arch/arm/boot/dts/ti/omap/dra7.dtsi @@ -850,12 +850,19 @@ target-module@5600 { ; ti,sysc-sidle = , , - ; + , + ; You probably checked this already.. But just in case, can you please confirm this is intentional. The documentation lists the smart wakeup capability bit as reserved for dra7, maybe the documentation is wrong. It was an intentional change, although I'm not sure it is correct :) This is how we had it in our "evil vendor tree" for years (back when it was hwmod based), so when converting these nodes to use "ti,sysc" I noticed this bit was set, but as you point out the documentation disagrees. I'd rather go with what has worked before, but it doesn't seem to break anything either way, so we could also break this change out into its own patch if you would prefer. Andrew Regards, Tony
Re: [PATCH v7 2/9] drm/panic: Add a drm panic handler
Hi Am 04.01.24 um 17:00 schrieb Jocelyn Falempe: [...] + /** +* @get_scanout_buffer: +* +* Get the current scanout buffer, to display a panic message with drm_panic. +* The driver should do the minimum changes to provide a linear buffer, that +* can be used to display the panic screen. +* It is called from a panic callback, and must follow its restrictions. +* (no locks, no memory allocation, no sleep, no thread/workqueue, ...) +* It's a best effort mode, so it's expected that in some complex cases the +* panic screen won't be displayed. +* Some hardware cannot provide a linear buffer, so there is a draw_pixel_xy() +* callback in the struct drm_scanout_buffer that can be used in this case. +* +* Returns: +* +* Zero on success, negative errno on failure. +*/ + int (*get_scanout_buffer)(struct drm_device *dev, + struct drm_scanout_buffer *sb); + After reading through Sima's comments on (try-)locking, I'd like to propose a different interface: instead of having the panic handler search for the scanout buffer, let each driver explicitly set the scanout buffer after each page flip. The algorithm for mode programming then looks like this: 1) Maybe clear the panic handler's buffer at the beginning of atomic_commit_tail, if necessary 2) Do the mode setting as usual 3) In the driver's atomic_flush or atomic_update, call something like void drm_panic_set_scanout_buffer(dev, scanout_buffer) to set the panic handler's new output. This avoids all the locking and the second guessing about the pipeline status. I don't see an easy way of reliably showing a panic screen during a modeset. But during a modeset, the old scanout buffer should (theoretically) not disappear until the new scanout buffer is in place. So if the panic happens, it would blit to the old address at worst. Well, that assumption needs to be verified per driver. Best regards Thomas /** @major: driver major number */ int major; /** @minor: driver minor number */ diff --git a/include/drm/drm_panic.h b/include/drm/drm_panic.h new file mode 100644 index ..bcf392b6fa1b --- /dev/null +++ b/include/drm/drm_panic.h @@ -0,0 +1,97 @@ +/* SPDX-License-Identifier: GPL-2.0 or MIT */ +#ifndef __DRM_PANIC_H__ +#define __DRM_PANIC_H__ + +/* + * Copyright (c) 2023 Red Hat. + * Author: Jocelyn Falempe + */ + +#include +#include +#include + +struct drm_device; + +/** + * struct drm_scanout_buffer - DRM scanout buffer + * + * This structure holds the information necessary for drm_panic to draw the + * panic screen, and display it. + * If the driver can't provide a linear buffer, it must clear @map with + * iosys_map_clear() and provide a draw_pixel_xy() function. + */ +struct drm_scanout_buffer { + /** +* @format: +* +* drm format of the scanout buffer. +*/ + const struct drm_format_info *format; + /** +* @map: +* +* Virtual address of the scanout buffer, either in memory or iomem. +* The scanout buffer should be in linear format, and can be directly +* sent to the display hardware. Tearing is not an issue for the panic +* screen. +*/ + struct iosys_map map; + /** +* @width: Width of the scanout buffer, in pixels. +*/ + unsigned int width; + /** +* @height: Height of the scanout buffer, in pixels. +*/ + unsigned int height; + /** +* @pitch: Length in bytes between the start of two consecutive lines. +*/ + unsigned int pitch; + /** +* @private: +* +* In case the driver can't provide a linear buffer, this is a pointer to +* some private data, that will be passed when calling @draw_pixel_xy() +* and @flush() +*/ + void *private; + /** +* @draw_pixel_xy: +* +* In case the driver can't provide a linear buffer, this is a function +* that drm_panic will call for each pixel to draw. +* Color will be converted to the format specified by @format. +*/ + void (*draw_pixel_xy)(unsigned int x, unsigned int y, u32 color, void *private); + /** +* @flush: +* +* This function is called after the panic screen is drawn, either using +* the iosys_map or the draw_pixel_xy path. In this function, the driver +* can send additional commands to the hardware, to make the buffer +* visible. +*/ + void (*flush)(void *private); +}; + +#ifdef CONFIG_DRM_PANIC + +void drm_panic_init(void); +void drm_panic_exit(void); + +void drm_panic_register(struct drm_device *dev); +void drm_panic_unregister(struct drm_device *dev); + +#else + +static inline void drm_panic_init(void) {} +stati