[PATCH 33/45] tty: vt: make types around consw::con_blank() bool

2024-01-17 Thread Jiri Slaby (SUSE)
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(_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

2024-01-17 Thread Jiri Slaby (SUSE)
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(_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

2024-01-17 Thread Jiri Slaby (SUSE)
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();
-   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();
vga_palette_blanked = true;
-- 
2.43.0



[PATCH 30/45] tty: vt: stop using -1 for blank mode in consw::con_blank()

2024-01-17 Thread Jiri Slaby (SUSE)
-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();
vga_palette_blanked = true;
-- 
2.43.0



[PATCH 40/45] fbcon: remove fbcon_getxy()

2024-01-17 Thread Jiri Slaby (SUSE)
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(_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()

2024-01-17 Thread Jiri Slaby (SUSE)
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()

2024-01-17 Thread Jiri Slaby (SUSE)
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(_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

2024-01-17 Thread Jiri Slaby (SUSE)
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 _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

2024-01-17 Thread Jiri Slaby (SUSE)
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(_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

2024-01-17 Thread Jiri Slaby (SUSE)
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

2024-01-17 Thread Jiri Slaby (SUSE)
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 

[PATCH 29/45] tty: vt: make consw::con_switch() return a bool

2024-01-17 Thread Jiri Slaby (SUSE)
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(_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 +2178,9 

[PATCH 28/45] tty: vt: remove CM_* constants

2024-01-17 Thread Jiri Slaby (SUSE)
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, 

[PATCH 26/45] consoles: use if instead of switch-case in consw::con_cursor()

2024-01-17 Thread Jiri Slaby (SUSE)
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

2024-01-17 Thread Jiri Slaby (SUSE)
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, );
-   fbcon_putcs(vc, , 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

2024-01-17 Thread Jiri Slaby (SUSE)
'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()

2024-01-17 Thread Jiri Slaby (SUSE)
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,
+

[PATCH 19/45] tty: vt: make init parameter of consw::con_init() a bool

2024-01-17 Thread Jiri Slaby (SUSE)
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 = _port_ops;
INIT_WORK(_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(_cons[currcons].SAK_work, vc_SAK);
tty_port_init(>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 = _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 

[PATCH 00/45] tty: vt: cleanup and documentation

2024-01-17 Thread Jiri Slaby (SUSE)
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()

2024-01-17 Thread Jiri Slaby (SUSE)
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

2024-01-17 Thread Jiri Slaby (SUSE)
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()

2024-01-17 Thread Jiri Slaby (SUSE)
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 = _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

2024-01-17 Thread Uwe Kleine-König
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

2024-01-17 Thread Dharma.B
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

2024-01-17 Thread kernel test robot
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-xilinx-xdma.c:warning:Function

Re: [PATCH] drm/bridge: anx7625: Ensure bridge is suspended in disable()

2024-01-17 Thread Pin-yen Lin
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(>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(>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(>aux_lock);
> +   pm_runtime_put_sync_suspend(dev);
> +   mutex_unlock(>aux_lock);
>  }
>
>  static enum drm_connector_status
> @@ -2668,6 +2672,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)
>
> mutex_init(>lock);
> mutex_init(>hdcp_wq_lock);
> +   mutex_init(>aux_lock);
>
> INIT_DELAYED_WORK(>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()

2024-01-17 Thread Pin-yen Lin
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

2024-01-17 Thread Qiang Yu
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 = >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(>base, >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

2024-01-17 Thread Jiapeng Chong
./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(>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()

2024-01-17 Thread Kunwu Chan

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

2024-01-17 Thread Qiang Yu
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()

2024-01-17 Thread Hsin-Yi Wang
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(>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(>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(>aux_lock);
+   pm_runtime_put_sync_suspend(dev);
+   mutex_unlock(>aux_lock);
 }
 
 static enum drm_connector_status
@@ -2668,6 +2672,7 @@ static int anx7625_i2c_probe(struct i2c_client *client)
 
mutex_init(>lock);
mutex_init(>hdcp_wq_lock);
+   mutex_init(>aux_lock);
 
INIT_DELAYED_WORK(>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

2024-01-17 Thread Qiang Yu
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

2024-01-17 Thread Qiang Yu
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(>base);
> drm_sched_start(>base, true);
> --
> 2.43.0
>


Re: Userspace API for per key backlight for non HID (no hidraw) keyboards

2024-01-17 Thread Werner Sembach

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.


Re: [PATCH v2 5/5] drm/xe: Enable 32bits build

2024-01-17 Thread Matt Roper
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

2024-01-17 Thread Matt Roper
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()

2024-01-17 Thread Matt Roper
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(, _iomem);
>   if (is_iomem)
> - *ptr = readq((void __iomem *)(virtual + ofs));
> + iosys_map_set_vaddr_iomem(, (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(, virtual);
>  
> + *ptr = iosys_map_rd(, ofs, u64);
>   ttm_bo_kunmap();
>  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

2024-01-17 Thread pr-tracker-bot
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

2024-01-17 Thread Matt Roper
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(>drm, "VRAM[%u, %u]: Actual physical size %pa, 
> usable size exclude stolen %pa, CPU accessible size %pa\n", id,
>tile->id, >mem.vram.actual_physical_size, 
> >mem.vram.usable_size, >mem.vram.io_size);
>   drm_info(>drm, "VRAM[%u, %u]: DPA range: [%pa-%llx], io 
> range: [%pa-%llx]\n", id, tile->id,
> -  >mem.vram.dpa_base, tile->mem.vram.dpa_base + 
> tile->mem.vram.actual_physical_size,
> -  >mem.vram.io_start, tile->mem.vram.io_start + 
> tile->mem.vram.io_size);
> +  >mem.vram.dpa_base, tile->mem.vram.dpa_base + 
> (u64)tile->mem.vram.actual_physical_size,
> +  >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

2024-01-17 Thread Matt Roper
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

2024-01-17 Thread Rob Herring
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 

[PATCH 21/23] drm/xe/svm: GPU page fault support

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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(>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(>hnode);
mutex_destroy(>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

2024-01-17 Thread Oak Zeng
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 = >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, , migrate.dst);
+   if (ret)
+   goto kfree_buf;
+
+   ret = migrate_vma_setup();
+   if (ret) {
+   drm_err(>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(>xe->drm, "Partial migration for range [%lx - 
%lx], range is %ld pages, migrate only %ld pages\n",
+   start, end, npages, migrate.cpages);
+
+   /**Migrate page by page for now.
+* 

[PATCH 11/23] drm/xe/svm: implement functions to allocate and free device memory

2024-01-17 Thread Oak Zeng
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 = >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 = >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

2024-01-17 Thread Oak Zeng
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(_range->notifier);
+   hmm_range->notifier = _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

2024-01-17 Thread Oak Zeng
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" {
  *  - _IOCTL_XE_EXEC_QUEUE_GET_PROPERTY
  *  - _IOCTL_XE_EXEC
  *  - _IOCTL_XE_WAIT_USER_FENCE
+ *  - _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 _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

2024-01-17 Thread Oak Zeng
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 

[PATCH 07/23] drm/xe/svm: Add helper for binding hmm range to gpu

2024-01-17 Thread Oak Zeng
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),
+   );
+   else if (xe_vma_is_userptr(vma))
xe_res_first_sg(vma->userptr.sg, 0, xe_vma_size(vma),
);
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) ? _bind_ops : 
_ops,
+   .ops = vma->svm_sg ? _bind_ops :
+   (xe_vma_is_userptr(vma) ? 
_bind_ops : _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 this function
+ * returns, either the 

[PATCH 02/23] drm/xe/svm: Add svm key data structures

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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, >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, >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(>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

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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(>mutex);
+   else if (!mutex_trylock(>mutex))
+   return false;
+
+   mmu_interval_set_seq(mni, cur_seq);
+   xe_invalidate_svm_range(svm->vm, range->start, length);
+   mutex_unlock(>mutex);
+
+   if (range->event == MMU_NOTIFY_UNMAP)
+   queue_work(system_unbound_wq, 
_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

2024-01-17 Thread Oak Zeng
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(>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(>svm->mutex);
+   interval_tree_remove(>inode, >svm->range_tree);
+   mutex_unlock(>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(>notifier, vma->vm_mm,
+   start, length, _svm_mni_ops);
+   mmap_write_downgrade(mm);
+

[PATCH 18/23] drm/xe/svm: Move a few structures to xe_gt.h

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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 

[PATCH 09/23] drm/xe/svm: Remap and provide memmap backing for GPU vram

2024-01-17 Thread Oak Zeng
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, >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, >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 device *dev = 

[PATCH 08/23] drm/xe/svm: Add helper to invalidate svm range from GPU

2024-01-17 Thread Oak Zeng
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 = >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();
+}
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

2024-01-17 Thread Oak Zeng
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(>hnode);
+   mutex_destroy(>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(>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, >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(>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(>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

2024-01-17 Thread Oak Zeng
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(>mutex);
+   node = interval_tree_iter_first(>range_tree, addr, addr);
+   mutex_unlock(>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

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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

2024-01-17 Thread Oak Zeng
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 

[PATCH 00/23] XeKmd basic SVM support

2024-01-17 Thread Oak Zeng
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 

Re: [PATCH 2/3] video/cmdline: Hide __video_get_options() behind CONFIG_FB_CORE

2024-01-17 Thread kernel test robot
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, , 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, , 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

2024-01-17 Thread Dave Airlie
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, PTES, false, 

[PATCH v3] drm/msm/dp: return correct Colorimetry for DP_TEST_DYNAMIC_RANGE_CEA case

2024-01-17 Thread Kuogee Hsieh
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

2024-01-17 Thread 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 I would like to offer some sort of easy accessible
API to 

Re: [PATCH] drm/msm/dpu: check for valid hw_pp in dpu_encoder_helper_phys_cleanup

2024-01-17 Thread Dmitry Baryshkov
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

2024-01-17 Thread Rob Herring
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 

Re: [PATCH] drm/bridge: parade-ps8640: Make sure we drop the AUX mutex in the error case

2024-01-17 Thread Doug Anderson
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

2024-01-17 Thread Nicolas Dufresne
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

2024-01-17 Thread Abhinav Kumar
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

2024-01-17 Thread Hsin-Yi Wang
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(_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()

2024-01-17 Thread Markus Elfring
> 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

2024-01-17 Thread Kuogee Hsieh



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

2024-01-17 Thread Pierre-Eric Pelloux-Prayer
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, _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(, bo->tbo.base.resv,
DMA_RESV_USAGE_KERNEL, fence) {
-   ret = amdgpu_sync_fence(_obj, fence);
+   ret = amdgpu_sync_fence(_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(>sync, fence);
+   r = amdgpu_sync_fence(>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(>sync, fence);
+   r = amdgpu_sync_fence(>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(>sync, fpriv->prt_va->last_pt_update);
+   r = amdgpu_sync_fence(>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(>sync, bo_va->last_pt_update);
+   r = amdgpu_sync_fence(>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(>sync, bo_va->last_pt_update);
+   r = amdgpu_sync_fence(>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)
if (r)
return r;
 
-   r = 

[PATCH 1/2] tracing, dma-buf: add a trace_dma_fence_sync_to event

2024-01-17 Thread Pierre-Eric Pelloux-Prayer
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

2024-01-17 Thread Dmitry Baryshkov
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()

2024-01-17 Thread Doug Anderson
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

2024-01-17 Thread Douglas Anderson
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(_bridge->aux_lock);
 
return ret;
-- 
2.43.0.381.gb435a96ce8-goog



Re: [PATCH v1 6/6] drm/lima: improve some pp debug messages

2024-01-17 Thread Vasily Khoruzhick
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

2024-01-17 Thread Vasily Khoruzhick
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(>refcnt);
>
> for (i = 0; i < lima_pipe_num; i++) {
> -   err = lima_sched_context_init(dev->pipe + i, ctx->context + 
> i, >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 = >base;
>
> return drm_sched_entity_init(>base, 
> DRM_SCHED_PRIORITY_NORMAL,
> -, 1, guilty);
> +, 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

2024-01-17 Thread Kuogee Hsieh



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

2024-01-17 Thread Vasily Khoruzhick
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 = >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(>base, >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

2024-01-17 Thread Vasily Khoruzhick
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

2024-01-17 Thread Vasily Khoruzhick
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

2024-01-17 Thread Vasily Khoruzhick
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(>base);
> drm_sched_start(>base, true);
> --
> 2.43.0
>


Re: [PATCH v2] drm/msm/dp: correct configure Colorimetry Indicator Field at MISC0

2024-01-17 Thread Dmitry Baryshkov
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

2024-01-17 Thread T.J. Mercier
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 = _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

2024-01-17 Thread Kuogee Hsieh
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

2024-01-17 Thread Abhinav Kumar

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()

2024-01-17 Thread Doug Anderson
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

2024-01-17 Thread 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 

Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-01-17 Thread Jocelyn Falempe




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 

Re: [PATCH v7 1/9] drm/format-helper: Add drm_fb_blit_from_r1 and drm_fb_fill

2024-01-17 Thread Jocelyn Falempe




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 

Re: [PATCH 08/11] ARM: dts: DRA7xx: Add device tree entry for SGX GPU

2024-01-17 Thread Andrew Davis

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

2024-01-17 Thread Thomas Zimmermann

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) {}

  1   2   >