[drm-tip:drm-tip 3/8] drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:512:28: error: passing argument 1 of 'mutex_lock' from incompatible pointer type

2022-07-08 Thread kernel test robot
tree:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
head:   36d2ac0e15af4dfb942279e8097ab831661859e6
commit: cf07f850c0483b3314eb69fd8c810e461cef4035 [3/8] Merge remote-tracking 
branch 'drm/drm-next' into drm-tip
config: ia64-allmodconfig 
(https://download.01.org/0day-ci/archive/20220709/202207091259.wyfc1mp6-...@intel.com/config)
compiler: ia64-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
git remote add drm-tip git://anongit.freedesktop.org/drm/drm-tip
git fetch --no-tags drm-tip drm-tip
git checkout cf07f850c0483b3314eb69fd8c810e461cef4035
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 
O=build_dir ARCH=ia64 SHELL=/bin/bash drivers/gpu/drm/amd/amdgpu/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

 | ^~
   include/linux/container_of.h:22:28: note: in expansion of macro 'offsetof'
  22 | ((type *)(__mptr - offsetof(type, member))); })
 |^~~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
 520 | container_of(ptr, type, member)
 | ^~~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:70:25: note: in expansion of 
macro 'list_entry'
  70 | block = list_entry(block->link.next, struct 
drm_buddy_block, link);
 | ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c: In function 
'amdgpu_vram_mgr_new':
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:488:13: error: 'cur_size' 
undeclared (first use in this function)
 488 | if (cur_size != size) {
 | ^~~~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:488:13: note: each undeclared 
identifier is reported only once for each function it appears in
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:488:25: error: 'size' 
undeclared (first use in this function); did you mean 'ksize'?
 488 | if (cur_size != size) {
 | ^~~~
 | ksize
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:494:30: error: 'vres' 
undeclared (first use in this function); did you mean 'res'?
 494 | trim_list = >blocks;
 |  ^~~~
 |  res
   In file included from include/linux/bits.h:22,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:25:
   include/linux/container_of.h:19:54: error: invalid use of undefined type 
'struct drm_buddy_block'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 |  ^~
   include/linux/build_bug.h:78:56: note: in definition of macro 
'__static_assert'
  78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 |^~~~
   include/linux/container_of.h:19:9: note: in expansion of macro 
'static_assert'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 | ^
   include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 |   ^~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
 520 | container_of(ptr, type, member)
 | ^~~~
   include/linux/list.h:542:9: note: in expansion of macro 'list_entry'
 542 | list_entry((ptr)->prev, type, member)
 | ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:502:33: note: in expansion of 
macro 'list_last_entry'
 502 | block = list_last_entry(>blocks, 
typeof(*block), link);
 | ^~~
   include/linux/compiler_types.h:293:27: error: expression in static assertion 
is not an integer
 293 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), 
typeof(b))
 |   ^~~~
   include/linux/build_bug.h:78:56: note: in definition of macro 
'__static_assert'
  78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 |  

Re: linux-next: Tree for Jul 8 (FRAMEBUFFER_CONSOLE without VT)

2022-07-08 Thread Randy Dunlap


On 7/8/22 03:15, Stephen Rothwell wrote:
> Hi all,
> 
> Changes since 20220707:
> 

on uml/x86_64:

WARNING: unmet direct dependencies detected for FRAMEBUFFER_CONSOLE
  Depends on [n]: VT [=n] && FB [=y] && !UML [=y]
  Selected by [y]:
  - DRM_FBDEV_EMULATION [=y] && HAS_IOMEM [=y] && DRM_KMS_HELPER [=y] && (FB 
[=y]=y || FB [=y]=DRM_KMS_HELPER [=y]) && !EXPERT [=n]

WARNING: unmet direct dependencies detected for 
FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
  Depends on [n]: VT [=n] && FRAMEBUFFER_CONSOLE [=y]
  Selected by [y]:
  - DRM_FBDEV_EMULATION [=y] && HAS_IOMEM [=y] && DRM_KMS_HELPER [=y] && (FB 
[=y]=y || FB [=y]=DRM_KMS_HELPER [=y]) && FRAMEBUFFER_CONSOLE [=y]

WARNING: unmet direct dependencies detected for VT_HW_CONSOLE_BINDING
  Depends on [n]: TTY [=y] && HW_CONSOLE [=n]
  Selected by [y]:
  - DRM_PL111 [=y] && HAS_IOMEM [=y] && DRM [=y] && (ARM || ARM64 || 
COMPILE_TEST [=y]) && (VEXPRESS_CONFIG [=n] || VEXPRESS_CONFIG [=n]=n) && 
COMMON_CLK [=y] && FRAMEBUFFER_CONSOLE [=y]

WARNING: unmet direct dependencies detected for FONT_8x16
  Depends on [n]: FONT_SUPPORT [=n]
  Selected by [y]:
  - FB_VT8623 [=y] && HAS_IOMEM [=y] && FB [=y] && PCI [=y] && 
FRAMEBUFFER_CONSOLE [=y]
  - FB_ARK [=y] && HAS_IOMEM [=y] && FB [=y] && PCI [=y] && FRAMEBUFFER_CONSOLE 
[=y]

WARNING: unmet direct dependencies detected for FRAMEBUFFER_CONSOLE
  Depends on [n]: VT [=n] && FB [=y] && !UML [=y]
  Selected by [y]:
  - DRM_FBDEV_EMULATION [=y] && HAS_IOMEM [=y] && DRM_KMS_HELPER [=y] && (FB 
[=y]=y || FB [=y]=DRM_KMS_HELPER [=y]) && !EXPERT [=n]

WARNING: unmet direct dependencies detected for VT_HW_CONSOLE_BINDING
  Depends on [n]: TTY [=y] && HW_CONSOLE [=n]
  Selected by [y]:
  - DRM_PL111 [=y] && HAS_IOMEM [=y] && DRM [=y] && (ARM || ARM64 || 
COMPILE_TEST [=y]) && (VEXPRESS_CONFIG [=n] || VEXPRESS_CONFIG [=n]=n) && 
COMMON_CLK [=y] && FRAMEBUFFER_CONSOLE [=y]

WARNING: unmet direct dependencies detected for 
FRAMEBUFFER_CONSOLE_DETECT_PRIMARY
  Depends on [n]: VT [=n] && FRAMEBUFFER_CONSOLE [=y]
  Selected by [y]:
  - DRM_FBDEV_EMULATION [=y] && HAS_IOMEM [=y] && DRM_KMS_HELPER [=y] && (FB 
[=y]=y || FB [=y]=DRM_KMS_HELPER [=y]) && FRAMEBUFFER_CONSOLE [=y]

WARNING: unmet direct dependencies detected for FONT_8x16
  Depends on [n]: FONT_SUPPORT [=n]
  Selected by [y]:
  - FB_VT8623 [=y] && HAS_IOMEM [=y] && FB [=y] && PCI [=y] && 
FRAMEBUFFER_CONSOLE [=y]
  - FB_ARK [=y] && HAS_IOMEM [=y] && FB [=y] && PCI [=y] && FRAMEBUFFER_CONSOLE 
[=y]


Full randconfig file is attached.

-- 
~Randy

config-uml-console.gz
Description: application/gzip


[drm-tip:drm-tip 3/8] include/linux/container_of.h:19:54: error: invalid use of undefined type 'struct drm_buddy_block'

2022-07-08 Thread kernel test robot
tree:   git://anongit.freedesktop.org/drm/drm-tip drm-tip
head:   36d2ac0e15af4dfb942279e8097ab831661859e6
commit: cf07f850c0483b3314eb69fd8c810e461cef4035 [3/8] Merge remote-tracking 
branch 'drm/drm-next' into drm-tip
config: microblaze-randconfig-r011-20220707 
(https://download.01.org/0day-ci/archive/20220709/202207090946.xujb0gpo-...@intel.com/config)
compiler: microblaze-linux-gcc (GCC) 11.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
git remote add drm-tip git://anongit.freedesktop.org/drm/drm-tip
git fetch --no-tags drm-tip drm-tip
git checkout cf07f850c0483b3314eb69fd8c810e461cef4035
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.3.0 make.cross W=1 
O=build_dir ARCH=microblaze SHELL=/bin/bash drivers/gpu/drm/amd/amdgpu/

If you fix the issue, kindly add following tag where applicable
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   In file included from include/linux/bits.h:22,
from include/linux/ratelimit_types.h:5,
from include/linux/ratelimit.h:5,
from include/linux/dev_printk.h:16,
from include/linux/device.h:15,
from include/linux/dma-mapping.h:7,
from drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:25:
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c: In function 
'amdgpu_vram_mgr_first_block':
>> include/linux/container_of.h:19:54: error: invalid use of undefined type 
>> 'struct drm_buddy_block'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 |  ^~
   include/linux/build_bug.h:78:56: note: in definition of macro 
'__static_assert'
  78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 |^~~~
   include/linux/container_of.h:19:9: note: in expansion of macro 
'static_assert'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 | ^
   include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 |   ^~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
 520 | container_of(ptr, type, member)
 | ^~~~
   include/linux/list.h:555:27: note: in expansion of macro 'list_entry'
 555 | pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
 |   ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:54:16: note: in expansion of 
macro 'list_first_entry_or_null'
  54 | return list_first_entry_or_null(list, struct 
drm_buddy_block, link);
 |^~~~
   include/linux/compiler_types.h:293:27: error: expression in static assertion 
is not an integer
 293 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), 
typeof(b))
 |   ^~~~
   include/linux/build_bug.h:78:56: note: in definition of macro 
'__static_assert'
  78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
 |^~~~
   include/linux/container_of.h:19:9: note: in expansion of macro 
'static_assert'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 | ^
   include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
  19 | static_assert(__same_type(*(ptr), ((type *)0)->member) ||
   \
 |   ^~~
   include/linux/list.h:520:9: note: in expansion of macro 'container_of'
 520 | container_of(ptr, type, member)
 | ^~~~
   include/linux/list.h:555:27: note: in expansion of macro 'list_entry'
 555 | pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
 |   ^~
   drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c:54:16: note: in expansion of 
macro 'list_first_entry_or_null'
  54 | return list_first_entry_or_null(list, struct 
drm_buddy_block, link);
 |^~~~
   In file included from include/uapi/linux/posix_types.h:5,
from include/uapi/linux/types.h:14,
from include/linux/types.h:6,
from include/linux/kasan-checks.h:5,
from include/asm-generic/rwonce.h:26,
from 

[PATCH v2 3/4] drm/lcdif: Clean up debug prints and comments

2022-07-08 Thread Marek Vasut
Update debug print to report bridge timings over connector ones.
Drop missed comment commit from mxsfb.

Reviewed-by: Liu Ying 
Reported-by: Liu Ying 
Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
Signed-off-by: Marek Vasut 
Cc: Alexander Stein 
Cc: Laurent Pinchart 
Cc: Liu Ying 
Cc: Lucas Stach 
Cc: Marek Vasut 
Cc: Martyn Welch 
Cc: Peng Fan 
Cc: Robby Cai 
Cc: Sam Ravnborg 
Cc: Stefan Agner 
---
V2: Add RB from Liu
---
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 829b0a6bb0d3f..9a77c631300a4 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -204,7 +204,7 @@ static void lcdif_crtc_mode_set_nofb(struct 
lcdif_drm_private *lcdif,
DRM_DEV_DEBUG_DRIVER(drm->dev, "Pixel clock: %dkHz (actual: %dkHz)\n",
 m->crtc_clock,
 (int)(clk_get_rate(lcdif->clk) / 1000));
-   DRM_DEV_DEBUG_DRIVER(drm->dev, "Connector bus_flags: 0x%08X\n",
+   DRM_DEV_DEBUG_DRIVER(drm->dev, "Bridge bus_flags: 0x%08X\n",
 bus_flags);
DRM_DEV_DEBUG_DRIVER(drm->dev, "Mode flags: 0x%08X\n", m->flags);
 
@@ -296,7 +296,6 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
 
lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format);
 
-   /* Write cur_buf as well to avoid an initial corrupt frame */
paddr = drm_fb_cma_get_gem_addr(new_pstate->fb, new_pstate, 0);
if (paddr) {
writel(lower_32_bits(paddr),
-- 
2.35.1



[PATCH v2 1/4] drm/lcdif: Clean up headers

2022-07-08 Thread Marek Vasut
Drop unneeded headers, sort rest alphabetically, no functional change.

Reviewed-by: Liu Ying 
Reported-by: Liu Ying 
Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
Signed-off-by: Marek Vasut 
Cc: Alexander Stein 
Cc: Laurent Pinchart 
Cc: Liu Ying 
Cc: Lucas Stach 
Cc: Marek Vasut 
Cc: Martyn Welch 
Cc: Peng Fan 
Cc: Robby Cai 
Cc: Sam Ravnborg 
Cc: Stefan Agner 
---
V2: Add RB from Liu
---
 drivers/gpu/drm/mxsfb/lcdif_drv.c | 3 ---
 drivers/gpu/drm/mxsfb/lcdif_drv.h | 1 +
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index befad33dcb959..1370889c6d687 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -8,7 +8,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -16,10 +15,8 @@
 
 #include 
 #include 
-#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.h 
b/drivers/gpu/drm/mxsfb/lcdif_drv.h
index cb916341e8454..6cdba6e20c02b 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.h
@@ -8,6 +8,7 @@
 #ifndef __LCDIF_DRV_H__
 #define __LCDIF_DRV_H__
 
+#include 
 #include 
 #include 
 #include 
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index 1bec1279c8b56..d7363e2b2fad0 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -17,9 +17,9 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-- 
2.35.1



[PATCH v2 2/4] drm/lcdif: Consistently use plane timings

2022-07-08 Thread Marek Vasut
Drop the crtc_ prefix from mode, consistently use the plain one.

Reviewed-by: Liu Ying 
Reported-by: Liu Ying 
Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
Signed-off-by: Marek Vasut 
Cc: Alexander Stein 
Cc: Laurent Pinchart 
Cc: Liu Ying 
Cc: Lucas Stach 
Cc: Marek Vasut 
Cc: Martyn Welch 
Cc: Peng Fan 
Cc: Robby Cai 
Cc: Sam Ravnborg 
Cc: Stefan Agner 
---
V2: Add RB from Liu
Replace plane with plain
---
 drivers/gpu/drm/mxsfb/lcdif_kms.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c 
b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index d7363e2b2fad0..829b0a6bb0d3f 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -123,8 +123,8 @@ static void lcdif_set_mode(struct lcdif_drm_private *lcdif, 
u32 bus_flags)
 
writel(ctrl, lcdif->base + LCDC_V8_CTRL);
 
-   writel(DISP_SIZE_DELTA_Y(m->crtc_vdisplay) |
-  DISP_SIZE_DELTA_X(m->crtc_hdisplay),
+   writel(DISP_SIZE_DELTA_Y(m->vdisplay) |
+  DISP_SIZE_DELTA_X(m->hdisplay),
   lcdif->base + LCDC_V8_DISP_SIZE);
 
writel(HSYN_PARA_BP_H(m->htotal - m->hsync_end) |
@@ -139,8 +139,8 @@ static void lcdif_set_mode(struct lcdif_drm_private *lcdif, 
u32 bus_flags)
   VSYN_HSYN_WIDTH_PW_H(m->hsync_end - m->hsync_start),
   lcdif->base + LCDC_V8_VSYN_HSYN_WIDTH);
 
-   writel(CTRLDESCL0_1_HEIGHT(m->crtc_vdisplay) |
-  CTRLDESCL0_1_WIDTH(m->crtc_hdisplay),
+   writel(CTRLDESCL0_1_HEIGHT(m->vdisplay) |
+  CTRLDESCL0_1_WIDTH(m->hdisplay),
   lcdif->base + LCDC_V8_CTRLDESCL0_1);
 
writel(CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]),
-- 
2.35.1



[PATCH v2 4/4] drm/lcdif: switch to devm_drm_of_get_bridge

2022-07-08 Thread Marek Vasut
The function "drm_of_find_panel_or_bridge" has been deprecated in
favor of "devm_drm_of_get_bridge".

Switch to the new function and reduce boilerplate.

Reviewed-by: Liu Ying 
Reported-by: Liu Ying 
Fixes: 9db35bb349a0e ("drm: lcdif: Add support for i.MX8MP LCDIF variant")
Signed-off-by: Marek Vasut 
Cc: Alexander Stein 
Cc: Laurent Pinchart 
Cc: Liu Ying 
Cc: Lucas Stach 
Cc: Marek Vasut 
Cc: Martyn Welch 
Cc: Peng Fan 
Cc: Robby Cai 
Cc: Sam Ravnborg 
Cc: Stefan Agner 
---
V2: Add RB from Liu
---
 drivers/gpu/drm/mxsfb/lcdif_drv.c | 18 +++---
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c 
b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 1370889c6d687..746a4261f3da2 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -42,23 +42,11 @@ static int lcdif_attach_bridge(struct lcdif_drm_private 
*lcdif)
 {
struct drm_device *drm = lcdif->drm;
struct drm_bridge *bridge;
-   struct drm_panel *panel;
int ret;
 
-   ret = drm_of_find_panel_or_bridge(drm->dev->of_node, 0, 0, ,
- );
-   if (ret)
-   return ret;
-
-   if (panel) {
-   bridge = devm_drm_panel_bridge_add_typed(drm->dev, panel,
-
DRM_MODE_CONNECTOR_DPI);
-   if (IS_ERR(bridge))
-   return PTR_ERR(bridge);
-   }
-
-   if (!bridge)
-   return -ENODEV;
+   bridge = devm_drm_of_get_bridge(drm->dev, drm->dev->of_node, 0, 0);
+   if (IS_ERR(bridge))
+   return PTR_ERR(bridge);
 
ret = drm_bridge_attach(>encoder, bridge, NULL, 0);
if (ret)
-- 
2.35.1



Re: [RFC] drm/i915/huc: better define HuC status getparam possible return values.

2022-07-08 Thread Ye, Tony



On 7/8/2022 4:48 PM, Daniele Ceraolo Spurio wrote:

The current HuC status getparam return values are a bit confusing in
regards to what happens in some scenarios. In particular, most of the
error cases cause the ioctl to return an error, but a couple of them,
INIT_FAIL and LOAD_FAIL, are not explicitly handled and neither is
their expected return value documented; these 2 error cases therefore
end up into the catch-all umbrella of the "HuC not loaded" case, with
this case therefore including both some error scenarios and the load
in progress one.

The updates included in this patch change the handling so that all
error cases behave the same way, i.e. return an errno code, and so
that the HuC load in progress case is unambiguous.

The patch also includes a small change to the FW init path to make sure
we always transition to an error state if something goes wrong.

This is an RFC because this is a minor change in behavior for an ioctl.
I'm arguing that this is not an API breakage because the expected return
for the cases I've changed was not well defined, but I want to make sure
no one is in opposition to this. From comments from media driver devs
on a different patch [1], it sounds like the media driver already
expected an errno value for all errors cases and is therefore already
compatible with the proposed changes.

[1] https://lists.freedesktop.org/archives/intel-gfx/2022-July/300990.html

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Tvrtko Ursulin 
Cc: Tony Ye 
---
  drivers/gpu/drm/i915/gt/uc/intel_guc.c   |  1 +
  drivers/gpu/drm/i915/gt/uc/intel_huc.c   | 14 +++---
  drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c |  1 -
  include/uapi/drm/i915_drm.h  | 16 
  4 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 2706a8c65090..42cb244587f1 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -455,6 +455,7 @@ int intel_guc_init(struct intel_guc *guc)
  err_fw:
intel_uc_fw_fini(>fw);
  out:
+   intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_INIT_FAIL);
i915_probe_error(gt->i915, "failed with %d\n", ret);
return ret;
  }
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 3bb8838e325a..bddcd3242ad0 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -113,6 +113,7 @@ int intel_huc_init(struct intel_huc *huc)
return 0;
  
  out:

+   intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_INIT_FAIL);
drm_info(>drm, "HuC init failed with %d\n", err);
return err;
  }
@@ -200,13 +201,8 @@ static bool huc_is_authenticated(struct intel_huc *huc)
   * This function reads status register to verify if HuC
   * firmware was successfully loaded.
   *
- * Returns:
- *  * -ENODEV if HuC is not present on this platform,
- *  * -EOPNOTSUPP if HuC firmware is disabled,
- *  * -ENOPKG if HuC firmware was not installed,
- *  * -ENOEXEC if HuC firmware is invalid or mismatched,
- *  * 0 if HuC firmware is not running,
- *  * 1 if HuC firmware is authenticated and running.
+ * The return values match what is expected for the I915_PARAM_HUC_STATUS
+ * getparam.
   */
  int intel_huc_check_status(struct intel_huc *huc)
  {
@@ -219,6 +215,10 @@ int intel_huc_check_status(struct intel_huc *huc)
return -ENOPKG;
case INTEL_UC_FIRMWARE_ERROR:
return -ENOEXEC;
+   case INTEL_UC_FIRMWARE_INIT_FAIL:
+   return -ENOMEM;
+   case INTEL_UC_FIRMWARE_LOAD_FAIL:
+   return -EIO;
default:
break;
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index 27363091e1af..007401397935 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -707,7 +707,6 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
  out_unpin:
i915_gem_object_unpin_pages(uc_fw->obj);
  out:
-   intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_INIT_FAIL);
return err;
  }
  
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h

index 094f6e377793..0950ef0d598c 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -645,6 +645,22 @@ typedef struct drm_i915_irq_wait {
   */
  #define   I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP  (1ul << 5)
  
+/*

+ * Query the status of HuC load.
+ *
+ * The query can fail in the following scenarios with the listed error codes:
+ *  -ENODEV if HuC is not present on this platform,
+ *  -EOPNOTSUPP if HuC firmware usage is disabled,
+ *  -ENOPKG if HuC firmware fetch failed,
+ *  -ENOEXEC if HuC firmware is invalid or mismatched,
+ *  -ENOMEM if i915 failed to prepare the FW objects for transfer to the uC,
+ *  -EIO if the FW transfer or the FW authentication failed.
+ *

[RFC] drm/i915/huc: better define HuC status getparam possible return values.

2022-07-08 Thread Daniele Ceraolo Spurio
The current HuC status getparam return values are a bit confusing in
regards to what happens in some scenarios. In particular, most of the
error cases cause the ioctl to return an error, but a couple of them,
INIT_FAIL and LOAD_FAIL, are not explicitly handled and neither is
their expected return value documented; these 2 error cases therefore
end up into the catch-all umbrella of the "HuC not loaded" case, with
this case therefore including both some error scenarios and the load
in progress one.

The updates included in this patch change the handling so that all
error cases behave the same way, i.e. return an errno code, and so
that the HuC load in progress case is unambiguous.

The patch also includes a small change to the FW init path to make sure
we always transition to an error state if something goes wrong.

This is an RFC because this is a minor change in behavior for an ioctl.
I'm arguing that this is not an API breakage because the expected return
for the cases I've changed was not well defined, but I want to make sure
no one is in opposition to this. From comments from media driver devs
on a different patch [1], it sounds like the media driver already
expected an errno value for all errors cases and is therefore already
compatible with the proposed changes.

[1] https://lists.freedesktop.org/archives/intel-gfx/2022-July/300990.html

Signed-off-by: Daniele Ceraolo Spurio 
Cc: Tvrtko Ursulin 
Cc: Tony Ye 
---
 drivers/gpu/drm/i915/gt/uc/intel_guc.c   |  1 +
 drivers/gpu/drm/i915/gt/uc/intel_huc.c   | 14 +++---
 drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c |  1 -
 include/uapi/drm/i915_drm.h  | 16 
 4 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index 2706a8c65090..42cb244587f1 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -455,6 +455,7 @@ int intel_guc_init(struct intel_guc *guc)
 err_fw:
intel_uc_fw_fini(>fw);
 out:
+   intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_INIT_FAIL);
i915_probe_error(gt->i915, "failed with %d\n", ret);
return ret;
 }
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c 
b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 3bb8838e325a..bddcd3242ad0 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -113,6 +113,7 @@ int intel_huc_init(struct intel_huc *huc)
return 0;
 
 out:
+   intel_uc_fw_change_status(>fw, INTEL_UC_FIRMWARE_INIT_FAIL);
drm_info(>drm, "HuC init failed with %d\n", err);
return err;
 }
@@ -200,13 +201,8 @@ static bool huc_is_authenticated(struct intel_huc *huc)
  * This function reads status register to verify if HuC
  * firmware was successfully loaded.
  *
- * Returns:
- *  * -ENODEV if HuC is not present on this platform,
- *  * -EOPNOTSUPP if HuC firmware is disabled,
- *  * -ENOPKG if HuC firmware was not installed,
- *  * -ENOEXEC if HuC firmware is invalid or mismatched,
- *  * 0 if HuC firmware is not running,
- *  * 1 if HuC firmware is authenticated and running.
+ * The return values match what is expected for the I915_PARAM_HUC_STATUS
+ * getparam.
  */
 int intel_huc_check_status(struct intel_huc *huc)
 {
@@ -219,6 +215,10 @@ int intel_huc_check_status(struct intel_huc *huc)
return -ENOPKG;
case INTEL_UC_FIRMWARE_ERROR:
return -ENOEXEC;
+   case INTEL_UC_FIRMWARE_INIT_FAIL:
+   return -ENOMEM;
+   case INTEL_UC_FIRMWARE_LOAD_FAIL:
+   return -EIO;
default:
break;
}
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c 
b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
index 27363091e1af..007401397935 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -707,7 +707,6 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
 out_unpin:
i915_gem_object_unpin_pages(uc_fw->obj);
 out:
-   intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_INIT_FAIL);
return err;
 }
 
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 094f6e377793..0950ef0d598c 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -645,6 +645,22 @@ typedef struct drm_i915_irq_wait {
  */
 #define   I915_SCHEDULER_CAP_STATIC_PRIORITY_MAP   (1ul << 5)
 
+/*
+ * Query the status of HuC load.
+ *
+ * The query can fail in the following scenarios with the listed error codes:
+ *  -ENODEV if HuC is not present on this platform,
+ *  -EOPNOTSUPP if HuC firmware usage is disabled,
+ *  -ENOPKG if HuC firmware fetch failed,
+ *  -ENOEXEC if HuC firmware is invalid or mismatched,
+ *  -ENOMEM if i915 failed to prepare the FW objects for transfer to the uC,
+ *  -EIO if the FW transfer or the FW authentication failed.
+ *
+ * If the IOCTL is successful, the returned parameter will be set to one of the

[PATCH v3 09/10] vfio/ccw: Add kmap_local_page() for memcpy

2022-07-08 Thread Nicolin Chen
A PFN is not secure enough to promise that the memory is not IO. And
direct access via memcpy() that only handles CPU memory will crash on
S390 if the PFN is an IO PFN, as we have to use the memcpy_to/fromio()
that uses the special S390 IO access instructions. On the other hand,
a "struct page *" is always a CPU coherent thing that fits memcpy().

Also, casting a PFN to "void *" for memcpy() is not a proper practice,
kmap_local_page() is the correct API to call here, though S390 doesn't
use highmem, which means kmap_local_page() is a NOP.

There's a following patch changing the vfio_pin_pages() API to return
a list of "struct page *" instead of PFNs. It will block any IO memory
from ever getting into this call path, for such a security purpose. In
this patch, add kmap_local_page() to prepare for that.

Suggested-by: Jason Gunthorpe 
Reviewed-by: Jason Gunthorpe 
Acked-by: Eric Farman 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 drivers/s390/cio/vfio_ccw_cp.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 3854c3d573f5..cd4ec4f6d6ff 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -230,7 +231,6 @@ static long copy_from_iova(struct vfio_device *vdev, void 
*to, u64 iova,
   unsigned long n)
 {
struct page_array pa = {0};
-   u64 from;
int i, ret;
unsigned long l, m;
 
@@ -246,7 +246,9 @@ static long copy_from_iova(struct vfio_device *vdev, void 
*to, u64 iova,
 
l = n;
for (i = 0; i < pa.pa_nr; i++) {
-   from = pa.pa_pfn[i] << PAGE_SHIFT;
+   struct page *page = pfn_to_page(pa.pa_pfn[i]);
+   void *from = kmap_local_page(page);
+
m = PAGE_SIZE;
if (i == 0) {
from += iova & (PAGE_SIZE - 1);
@@ -254,7 +256,8 @@ static long copy_from_iova(struct vfio_device *vdev, void 
*to, u64 iova,
}
 
m = min(l, m);
-   memcpy(to + (n - l), (void *)from, m);
+   memcpy(to + (n - l), from, m);
+   kunmap_local(from);
 
l -= m;
if (l == 0)
-- 
2.17.1



[PATCH v3 08/10] vfio: Rename user_iova of vfio_dma_rw()

2022-07-08 Thread Nicolin Chen
Following the updated vfio_pin/unpin_pages(), use the simpler "iova".

Reviewed-by: Christoph Hellwig 
Reviewed-by: Jason Gunthorpe 
Reviewed-by: Kevin Tian 
Tested-by: Terrence Xu 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 drivers/vfio/vfio.c  | 6 +++---
 include/linux/vfio.h | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index ee4d45c2f210..153e5a7bce6a 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1993,13 +1993,13 @@ EXPORT_SYMBOL(vfio_unpin_pages);
  * not a real device DMA, it is not necessary to pin the user space memory.
  *
  * @device [in]: VFIO device
- * @user_iova [in] : base IOVA of a user space buffer
+ * @iova [in]  : base IOVA of a user space buffer
  * @data [in]  : pointer to kernel buffer
  * @len [in]   : kernel buffer length
  * @write  : indicate read or write
  * Return error code on failure or 0 on success.
  */
-int vfio_dma_rw(struct vfio_device *device, dma_addr_t user_iova, void *data,
+int vfio_dma_rw(struct vfio_device *device, dma_addr_t iova, void *data,
size_t len, bool write)
 {
struct vfio_container *container;
@@ -2015,7 +2015,7 @@ int vfio_dma_rw(struct vfio_device *device, dma_addr_t 
user_iova, void *data,
 
if (likely(driver && driver->ops->dma_rw))
ret = driver->ops->dma_rw(container->iommu_data,
- user_iova, data, len, write);
+ iova, data, len, write);
else
ret = -ENOTTY;
return ret;
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 2cefb63751f9..1d4febc4f711 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -160,7 +160,7 @@ bool vfio_file_has_dev(struct file *file, struct 
vfio_device *device);
 int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
   int npage, int prot, unsigned long *phys_pfn);
 void vfio_unpin_pages(struct vfio_device *device, dma_addr_t iova, int npage);
-int vfio_dma_rw(struct vfio_device *device, dma_addr_t user_iova,
+int vfio_dma_rw(struct vfio_device *device, dma_addr_t iova,
void *data, size_t len, bool write);
 
 /* each type has independent events */
-- 
2.17.1



[PATCH v3 06/10] vfio/ap: Change saved_pfn to saved_iova

2022-07-08 Thread Nicolin Chen
The vfio_ap_ops code maintains both nib address and its PFN, which
is redundant, merely because vfio_pin/unpin_pages API wanted pfn.
Since vfio_pin/unpin_pages() now accept "iova", change "saved_pfn"
to "saved_iova" and remove pfn in the vfio_ap_validate_nib().

Reviewed-by: Jason Gunthorpe 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 drivers/s390/crypto/vfio_ap_ops.c | 42 +++
 drivers/s390/crypto/vfio_ap_private.h |  4 +--
 2 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
b/drivers/s390/crypto/vfio_ap_ops.c
index 8a2018ab3cf0..e8856a7e151c 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -112,7 +112,7 @@ static void vfio_ap_wait_for_irqclear(int apqn)
  *
  * Unregisters the ISC in the GIB when the saved ISC not invalid.
  * Unpins the guest's page holding the NIB when it exists.
- * Resets the saved_pfn and saved_isc to invalid values.
+ * Resets the saved_iova and saved_isc to invalid values.
  */
 static void vfio_ap_free_aqic_resources(struct vfio_ap_queue *q)
 {
@@ -123,9 +123,9 @@ static void vfio_ap_free_aqic_resources(struct 
vfio_ap_queue *q)
kvm_s390_gisc_unregister(q->matrix_mdev->kvm, q->saved_isc);
q->saved_isc = VFIO_AP_ISC_INVALID;
}
-   if (q->saved_pfn && !WARN_ON(!q->matrix_mdev)) {
-   vfio_unpin_pages(>matrix_mdev->vdev, q->saved_pfn << 
PAGE_SHIFT, 1);
-   q->saved_pfn = 0;
+   if (q->saved_iova && !WARN_ON(!q->matrix_mdev)) {
+   vfio_unpin_pages(>matrix_mdev->vdev, q->saved_iova, 1);
+   q->saved_iova = 0;
}
 }
 
@@ -189,27 +189,19 @@ static struct ap_queue_status vfio_ap_irq_disable(struct 
vfio_ap_queue *q)
  *
  * @vcpu: the object representing the vcpu executing the PQAP(AQIC) 
instruction.
  * @nib: the location for storing the nib address.
- * @g_pfn: the location for storing the page frame number of the page 
containing
- *the nib.
  *
  * When the PQAP(AQIC) instruction is executed, general register 2 contains the
  * address of the notification indicator byte (nib) used for IRQ notification.
- * This function parses the nib from gr2 and calculates the page frame
- * number for the guest of the page containing the nib. The values are
- * stored in @nib and @g_pfn respectively.
- *
- * The g_pfn of the nib is then validated to ensure the nib address is valid.
+ * This function parses and validates the nib from gr2.
  *
  * Return: returns zero if the nib address is a valid; otherwise, returns
  *-EINVAL.
  */
-static int vfio_ap_validate_nib(struct kvm_vcpu *vcpu, unsigned long *nib,
-   unsigned long *g_pfn)
+static int vfio_ap_validate_nib(struct kvm_vcpu *vcpu, dma_addr_t *nib)
 {
*nib = vcpu->run->s.regs.gprs[2];
-   *g_pfn = *nib >> PAGE_SHIFT;
 
-   if (kvm_is_error_hva(gfn_to_hva(vcpu->kvm, *g_pfn)))
+   if (kvm_is_error_hva(gfn_to_hva(vcpu->kvm, *nib >> PAGE_SHIFT)))
return -EINVAL;
 
return 0;
@@ -239,34 +231,34 @@ static struct ap_queue_status vfio_ap_irq_enable(struct 
vfio_ap_queue *q,
 int isc,
 struct kvm_vcpu *vcpu)
 {
-   unsigned long nib;
struct ap_qirq_ctrl aqic_gisa = {};
struct ap_queue_status status = {};
struct kvm_s390_gisa *gisa;
int nisc;
struct kvm *kvm;
-   unsigned long g_pfn, h_pfn;
+   unsigned long h_pfn;
phys_addr_t h_nib;
+   dma_addr_t nib;
int ret;
 
/* Verify that the notification indicator byte address is valid */
-   if (vfio_ap_validate_nib(vcpu, , _pfn)) {
-   VFIO_AP_DBF_WARN("%s: invalid NIB address: nib=%#lx, 
g_pfn=%#lx, apqn=%#04x\n",
-__func__, nib, g_pfn, q->apqn);
+   if (vfio_ap_validate_nib(vcpu, )) {
+   VFIO_AP_DBF_WARN("%s: invalid NIB address: nib=%pad, 
apqn=%#04x\n",
+__func__, , q->apqn);
 
status.response_code = AP_RESPONSE_INVALID_ADDRESS;
return status;
}
 
-   ret = vfio_pin_pages(>matrix_mdev->vdev, g_pfn << PAGE_SHIFT, 1,
+   ret = vfio_pin_pages(>matrix_mdev->vdev, nib, 1,
 IOMMU_READ | IOMMU_WRITE, _pfn);
switch (ret) {
case 1:
break;
default:
VFIO_AP_DBF_WARN("%s: vfio_pin_pages failed: rc=%d,"
-"nib=%#lx, g_pfn=%#lx, apqn=%#04x\n",
-__func__, ret, nib, g_pfn, q->apqn);
+"nib=%pad, apqn=%#04x\n",
+__func__, ret, , q->apqn);
 
status.response_code = AP_RESPONSE_INVALID_ADDRESS;
return status;
@@ -296,12 +288,12 @@ static struct 

[PATCH v3 01/10] vfio: Make vfio_unpin_pages() return void

2022-07-08 Thread Nicolin Chen
There's only one caller that checks its return value with a WARN_ON_ONCE,
while all other callers don't check the return value at all. Above that,
an undo function should not fail. So, simplify the API to return void by
embedding similar WARN_ONs.

Also for users to pinpoint which condition fails, separate WARN_ON lines,
yet remove the "driver->ops->unpin_pages" check, since it's unreasonable
for callers to unpin on something totally random that wasn't even pinned.
And remove NULL pointer checks for they would trigger oops vs. warnings.
Note that npage is already validated in the vfio core, thus drop the same
check in the type1 code.

Suggested-by: Christoph Hellwig 
Reviewed-by: Christoph Hellwig 
Reviewed-by: Jason Gunthorpe 
Reviewed-by: Kirti Wankhede 
Tested-by: Terrence Xu 
Signed-off-by: Nicolin Chen 
---
 .../driver-api/vfio-mediated-device.rst   |  2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c  |  5 +
 drivers/vfio/vfio.c   | 21 +++
 drivers/vfio/vfio.h   |  2 +-
 drivers/vfio/vfio_iommu_type1.c   | 15 ++---
 include/linux/vfio.h  |  4 ++--
 6 files changed, 18 insertions(+), 31 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst 
b/Documentation/driver-api/vfio-mediated-device.rst
index d7a512676853..4307421dcaa0 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -263,7 +263,7 @@ driver::
int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
  int npage, int prot, unsigned long *phys_pfn);
 
-   int vfio_unpin_pages(struct vfio_device *device, unsigned long 
*user_pfn,
+   void vfio_unpin_pages(struct vfio_device *device, unsigned long 
*user_pfn,
int npage);
 
 These functions call back into the back-end IOMMU module by using the pin_pages
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index e2f6c56ab342..8c67c9aba82d 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -231,18 +231,15 @@ static void intel_gvt_cleanup_vgpu_type_groups(struct 
intel_gvt *gvt)
 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long size)
 {
-   struct drm_i915_private *i915 = vgpu->gvt->gt->i915;
int total_pages;
int npage;
-   int ret;
 
total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
 
for (npage = 0; npage < total_pages; npage++) {
unsigned long cur_gfn = gfn + npage;
 
-   ret = vfio_unpin_pages(>vfio_device, _gfn, 1);
-   drm_WARN_ON(>drm, ret != 1);
+   vfio_unpin_pages(>vfio_device, _gfn, 1);
}
 }
 
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 100a3d84380c..ad90adbfddc8 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1964,31 +1964,24 @@ EXPORT_SYMBOL(vfio_pin_pages);
  *PFNs should not be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
  * @npage [in]   : count of elements in user_pfn array.  This count should not
  * be greater than VFIO_PIN_PAGES_MAX_ENTRIES.
- * Return error or number of pages unpinned.
  */
-int vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
-int npage)
+void vfio_unpin_pages(struct vfio_device *device, unsigned long *user_pfn,
+ int npage)
 {
struct vfio_container *container;
struct vfio_iommu_driver *driver;
-   int ret;
 
-   if (!user_pfn || !npage || !vfio_assert_device_open(device))
-   return -EINVAL;
+   if (WARN_ON(npage <= 0 || npage > VFIO_PIN_PAGES_MAX_ENTRIES))
+   return;
 
-   if (npage > VFIO_PIN_PAGES_MAX_ENTRIES)
-   return -E2BIG;
+   if (WARN_ON(!vfio_assert_device_open(device)))
+   return;
 
/* group->container cannot change while a vfio device is open */
container = device->group->container;
driver = container->iommu_driver;
-   if (likely(driver && driver->ops->unpin_pages))
-   ret = driver->ops->unpin_pages(container->iommu_data, user_pfn,
-  npage);
-   else
-   ret = -ENOTTY;
 
-   return ret;
+   driver->ops->unpin_pages(container->iommu_data, user_pfn, npage);
 }
 EXPORT_SYMBOL(vfio_unpin_pages);
 
diff --git a/drivers/vfio/vfio.h b/drivers/vfio/vfio.h
index a67130221151..bef4edf58138 100644
--- a/drivers/vfio/vfio.h
+++ b/drivers/vfio/vfio.h
@@ -53,7 +53,7 @@ struct vfio_iommu_driver_ops {
 unsigned long *user_pfn,
 int npage, int prot,
 unsigned long *phys_pfn);
-   int (*unpin_pages)(void 

[PATCH v3 07/10] vfio/ccw: Change pa_pfn list to pa_iova list

2022-07-08 Thread Nicolin Chen
The vfio_ccw_cp code maintains both iova and its PFN list because the
vfio_pin/unpin_pages API wanted pfn list. Since vfio_pin/unpin_pages()
now accept "iova", change to maintain only pa_iova list and rename all
"pfn_array" strings to "page_array", so as to simplify the code.

Reviewed-by: Jason Gunthorpe 
Reviewed-by: Eric Farman 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 drivers/s390/cio/vfio_ccw_cp.c | 135 -
 1 file changed, 64 insertions(+), 71 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index a739262f988d..3854c3d573f5 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -18,11 +18,9 @@
 #include "vfio_ccw_cp.h"
 #include "vfio_ccw_private.h"
 
-struct pfn_array {
-   /* Starting guest physical I/O address. */
-   unsigned long   pa_iova;
-   /* Array that stores PFNs of the pages need to pin. */
-   unsigned long   *pa_iova_pfn;
+struct page_array {
+   /* Array that stores pages need to pin. */
+   dma_addr_t  *pa_iova;
/* Array that receives PFNs of the pages pinned. */
unsigned long   *pa_pfn;
/* Number of pages pinned from @pa_iova. */
@@ -37,53 +35,50 @@ struct ccwchain {
/* Count of the valid ccws in chain. */
int ch_len;
/* Pinned PAGEs for the original data. */
-   struct pfn_array*ch_pa;
+   struct page_array   *ch_pa;
 };
 
 /*
- * pfn_array_alloc() - alloc memory for PFNs
- * @pa: pfn_array on which to perform the operation
+ * page_array_alloc() - alloc memory for page array
+ * @pa: page_array on which to perform the operation
  * @iova: target guest physical address
  * @len: number of bytes that should be pinned from @iova
  *
- * Attempt to allocate memory for PFNs.
+ * Attempt to allocate memory for page array.
  *
- * Usage of pfn_array:
- * We expect (pa_nr == 0) and (pa_iova_pfn == NULL), any field in
+ * Usage of page_array:
+ * We expect (pa_nr == 0) and (pa_iova == NULL), any field in
  * this structure will be filled in by this function.
  *
  * Returns:
- * 0 if PFNs are allocated
- *   -EINVAL if pa->pa_nr is not initially zero, or pa->pa_iova_pfn is not NULL
+ * 0 if page array is allocated
+ *   -EINVAL if pa->pa_nr is not initially zero, or pa->pa_iova is not NULL
  *   -ENOMEM if alloc failed
  */
-static int pfn_array_alloc(struct pfn_array *pa, u64 iova, unsigned int len)
+static int page_array_alloc(struct page_array *pa, u64 iova, unsigned int len)
 {
int i;
 
-   if (pa->pa_nr || pa->pa_iova_pfn)
+   if (pa->pa_nr || pa->pa_iova)
return -EINVAL;
 
-   pa->pa_iova = iova;
-
pa->pa_nr = ((iova & ~PAGE_MASK) + len + (PAGE_SIZE - 1)) >> PAGE_SHIFT;
if (!pa->pa_nr)
return -EINVAL;
 
-   pa->pa_iova_pfn = kcalloc(pa->pa_nr,
- sizeof(*pa->pa_iova_pfn) +
- sizeof(*pa->pa_pfn),
- GFP_KERNEL);
-   if (unlikely(!pa->pa_iova_pfn)) {
+   pa->pa_iova = kcalloc(pa->pa_nr,
+ sizeof(*pa->pa_iova) + sizeof(*pa->pa_pfn),
+ GFP_KERNEL);
+   if (unlikely(!pa->pa_iova)) {
pa->pa_nr = 0;
return -ENOMEM;
}
-   pa->pa_pfn = pa->pa_iova_pfn + pa->pa_nr;
+   pa->pa_pfn = (unsigned long *)>pa_iova[pa->pa_nr];
 
-   pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
+   pa->pa_iova[0] = iova;
pa->pa_pfn[0] = -1ULL;
for (i = 1; i < pa->pa_nr; i++) {
-   pa->pa_iova_pfn[i] = pa->pa_iova_pfn[i - 1] + 1;
+   pa->pa_iova[i] = pa->pa_iova[i - 1] + PAGE_SIZE;
pa->pa_pfn[i] = -1ULL;
}
 
@@ -91,30 +86,30 @@ static int pfn_array_alloc(struct pfn_array *pa, u64 iova, 
unsigned int len)
 }
 
 /*
- * pfn_array_unpin() - Unpin user pages in memory
- * @pa: pfn_array on which to perform the operation
+ * page_array_unpin() - Unpin user pages in memory
+ * @pa: page_array on which to perform the operation
  * @vdev: the vfio device to perform the operation
  * @pa_nr: number of user pages to unpin
  *
  * Only unpin if any pages were pinned to begin with, i.e. pa_nr > 0,
  * otherwise only clear pa->pa_nr
  */
-static void pfn_array_unpin(struct pfn_array *pa,
-   struct vfio_device *vdev, int pa_nr)
+static void page_array_unpin(struct page_array *pa,
+struct vfio_device *vdev, int pa_nr)
 {
int unpinned = 0, npage = 1;
 
while (unpinned < pa_nr) {
-   unsigned long *first = >pa_iova_pfn[unpinned];
-   unsigned long *last = [npage];
+   dma_addr_t *first = >pa_iova[unpinned];
+   dma_addr_t *last = [npage];
 
if (unpinned + npage < pa_nr &&
-   

[PATCH v3 05/10] vfio: Pass in starting IOVA to vfio_pin/unpin_pages API

2022-07-08 Thread Nicolin Chen
The vfio_pin/unpin_pages() so far accepted arrays of PFNs of user IOVA.
Among all three callers, there was only one caller possibly passing in
a non-contiguous PFN list, which is now ensured to have contiguous PFN
inputs too.

Pass in the starting address with "iova" alone to simplify things, so
callers no longer need to maintain a PFN list or to pin/unpin one page
at a time. This also allows VFIO to use more efficient implementations
of pin/unpin_pages.

For now, also update vfio_iommu_type1 to fit this new parameter too,
while keeping its input intact (being user_iova) since we don't want
to spend too much effort swapping its parameters and local variables
at that level.

Reviewed-by: Christoph Hellwig 
Reviewed by: Kirti Wankhede 
Reviewed-by: Jason Gunthorpe 
Reviewed-by: Kevin Tian 
Acked-by: Eric Farman 
Tested-by: Terrence Xu 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 .../driver-api/vfio-mediated-device.rst   |  4 +--
 drivers/gpu/drm/i915/gvt/kvmgt.c  | 22 ++-
 drivers/s390/cio/vfio_ccw_cp.c|  4 +--
 drivers/s390/crypto/vfio_ap_ops.c |  9 +++
 drivers/vfio/vfio.c   | 27 +--
 drivers/vfio/vfio.h   |  4 +--
 drivers/vfio/vfio_iommu_type1.c   | 15 +--
 include/linux/vfio.h  |  5 ++--
 8 files changed, 39 insertions(+), 51 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst 
b/Documentation/driver-api/vfio-mediated-device.rst
index 4307421dcaa0..af31eaf836e8 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -260,10 +260,10 @@ Translation APIs for Mediated Devices
 The following APIs are provided for translating user pfn to host pfn in a VFIO
 driver::
 
-   int vfio_pin_pages(struct vfio_device *device, unsigned long *user_pfn,
+   int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
  int npage, int prot, unsigned long *phys_pfn);
 
-   void vfio_unpin_pages(struct vfio_device *device, unsigned long 
*user_pfn,
+   void vfio_unpin_pages(struct vfio_device *device, dma_addr_t iova,
int npage);
 
 These functions call back into the back-end IOMMU module by using the pin_pages
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 7ce7b09aa5b2..d3ac8383d759 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -231,14 +231,8 @@ static void intel_gvt_cleanup_vgpu_type_groups(struct 
intel_gvt *gvt)
 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long size)
 {
-   int total_pages = DIV_ROUND_UP(size, PAGE_SIZE);
-   int npage;
-
-   for (npage = 0; npage < total_pages; npage++) {
-   unsigned long cur_gfn = gfn + npage;
-
-   vfio_unpin_pages(>vfio_device, _gfn, 1);
-   }
+   vfio_unpin_pages(>vfio_device, gfn << PAGE_SHIFT,
+DIV_ROUND_UP(size, PAGE_SIZE));
 }
 
 /* Pin a normal or compound guest page for dma. */
@@ -255,14 +249,14 @@ static int gvt_pin_guest_page(struct intel_vgpu *vgpu, 
unsigned long gfn,
 * on stack to hold pfns.
 */
for (npage = 0; npage < total_pages; npage++) {
-   unsigned long cur_gfn = gfn + npage;
+   dma_addr_t cur_iova = (gfn + npage) << PAGE_SHIFT;
unsigned long pfn;
 
-   ret = vfio_pin_pages(>vfio_device, _gfn, 1,
+   ret = vfio_pin_pages(>vfio_device, cur_iova, 1,
 IOMMU_READ | IOMMU_WRITE, );
if (ret != 1) {
-   gvt_vgpu_err("vfio_pin_pages failed for gfn 0x%lx, ret 
%d\n",
-cur_gfn, ret);
+   gvt_vgpu_err("vfio_pin_pages failed for iova %pad, ret 
%d\n",
+_iova, ret);
goto err;
}
 
@@ -306,7 +300,7 @@ static int gvt_dma_map_page(struct intel_vgpu *vgpu, 
unsigned long gfn,
if (dma_mapping_error(dev, *dma_addr)) {
gvt_vgpu_err("DMA mapping failed for pfn 0x%lx, ret %d\n",
 page_to_pfn(page), ret);
-   gvt_unpin_guest_page(vgpu, gfn, size);
+   gvt_unpin_guest_page(vgpu, gfn << PAGE_SHIFT, size);
return -ENOMEM;
}
 
@@ -319,7 +313,7 @@ static void gvt_dma_unmap_page(struct intel_vgpu *vgpu, 
unsigned long gfn,
struct device *dev = vgpu->gvt->gt->i915->drm.dev;
 
dma_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL);
-   gvt_unpin_guest_page(vgpu, gfn, size);
+   gvt_unpin_guest_page(vgpu, gfn << PAGE_SHIFT, size);
 }
 
 static struct gvt_dma *__gvt_cache_find_dma_addr(struct intel_vgpu *vgpu,
diff --git 

[PATCH v3 04/10] vfio/ccw: Only pass in contiguous pages

2022-07-08 Thread Nicolin Chen
This driver is the only caller of vfio_pin/unpin_pages that might pass
in a non-contiguous PFN list, but in many cases it has a contiguous PFN
list to process. So letting VFIO API handle a non-contiguous PFN list
is actually counterproductive.

Add a pair of simple loops to pass in contiguous PFNs only, to have an
efficient implementation in VFIO.

Reviewed-by: Jason Gunthorpe 
Reviewed-by: Eric Farman 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 drivers/s390/cio/vfio_ccw_cp.c | 70 +++---
 1 file changed, 56 insertions(+), 14 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c
index 0c2be9421ab7..3b94863ad24e 100644
--- a/drivers/s390/cio/vfio_ccw_cp.c
+++ b/drivers/s390/cio/vfio_ccw_cp.c
@@ -90,6 +90,38 @@ static int pfn_array_alloc(struct pfn_array *pa, u64 iova, 
unsigned int len)
return 0;
 }
 
+/*
+ * pfn_array_unpin() - Unpin user pages in memory
+ * @pa: pfn_array on which to perform the operation
+ * @vdev: the vfio device to perform the operation
+ * @pa_nr: number of user pages to unpin
+ *
+ * Only unpin if any pages were pinned to begin with, i.e. pa_nr > 0,
+ * otherwise only clear pa->pa_nr
+ */
+static void pfn_array_unpin(struct pfn_array *pa,
+   struct vfio_device *vdev, int pa_nr)
+{
+   int unpinned = 0, npage = 1;
+
+   while (unpinned < pa_nr) {
+   unsigned long *first = >pa_iova_pfn[unpinned];
+   unsigned long *last = [npage];
+
+   if (unpinned + npage < pa_nr &&
+   *first + npage == *last) {
+   npage++;
+   continue;
+   }
+
+   vfio_unpin_pages(vdev, first, npage);
+   unpinned += npage;
+   npage = 1;
+   }
+
+   pa->pa_nr = 0;
+}
+
 /*
  * pfn_array_pin() - Pin user pages in memory
  * @pa: pfn_array on which to perform the operation
@@ -101,34 +133,44 @@ static int pfn_array_alloc(struct pfn_array *pa, u64 
iova, unsigned int len)
  */
 static int pfn_array_pin(struct pfn_array *pa, struct vfio_device *vdev)
 {
+   int pinned = 0, npage = 1;
int ret = 0;
 
-   ret = vfio_pin_pages(vdev, pa->pa_iova_pfn, pa->pa_nr,
-IOMMU_READ | IOMMU_WRITE, pa->pa_pfn);
+   while (pinned < pa->pa_nr) {
+   unsigned long *first = >pa_iova_pfn[pinned];
+   unsigned long *last = [npage];
 
-   if (ret < 0) {
-   goto err_out;
-   } else if (ret > 0 && ret != pa->pa_nr) {
-   vfio_unpin_pages(vdev, pa->pa_iova_pfn, ret);
-   ret = -EINVAL;
-   goto err_out;
+   if (pinned + npage < pa->pa_nr &&
+   *first + npage == *last) {
+   npage++;
+   continue;
+   }
+
+   ret = vfio_pin_pages(vdev, first, npage,
+IOMMU_READ | IOMMU_WRITE,
+>pa_pfn[pinned]);
+   if (ret < 0) {
+   goto err_out;
+   } else if (ret > 0 && ret != npage) {
+   pinned += ret;
+   ret = -EINVAL;
+   goto err_out;
+   }
+   pinned += npage;
+   npage = 1;
}
 
return ret;
 
 err_out:
-   pa->pa_nr = 0;
-
+   pfn_array_unpin(pa, vdev, pinned);
return ret;
 }
 
 /* Unpin the pages before releasing the memory. */
 static void pfn_array_unpin_free(struct pfn_array *pa, struct vfio_device 
*vdev)
 {
-   /* Only unpin if any pages were pinned to begin with */
-   if (pa->pa_nr)
-   vfio_unpin_pages(vdev, pa->pa_iova_pfn, pa->pa_nr);
-   pa->pa_nr = 0;
+   pfn_array_unpin(pa, vdev, pa->pa_nr);
kfree(pa->pa_iova_pfn);
 }
 
-- 
2.17.1



[PATCH v3 03/10] vfio/ap: Pass in physical address of ind to ap_aqic()

2022-07-08 Thread Nicolin Chen
The ap_aqic() is called by vfio_ap_irq_enable() where it passes in a
virt value that's casted from a physical address "h_nib". Inside the
ap_aqic(), it does virt_to_phys() again.

Since ap_aqic() needs a physical address, let's just pass in a pa of
ind directly. So change the "ind" to "pa_ind".

Reviewed-by: Harald Freudenberger 
Reviewed-by: Jason Gunthorpe 
Tested-by: Eric Farman 
Signed-off-by: Nicolin Chen 
---
 arch/s390/include/asm/ap.h| 6 +++---
 drivers/s390/crypto/ap_queue.c| 2 +-
 drivers/s390/crypto/vfio_ap_ops.c | 7 ---
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/arch/s390/include/asm/ap.h b/arch/s390/include/asm/ap.h
index b515cfa62bd9..f508f5025e38 100644
--- a/arch/s390/include/asm/ap.h
+++ b/arch/s390/include/asm/ap.h
@@ -227,13 +227,13 @@ struct ap_qirq_ctrl {
  * ap_aqic(): Control interruption for a specific AP.
  * @qid: The AP queue number
  * @qirqctrl: struct ap_qirq_ctrl (64 bit value)
- * @ind: The notification indicator byte
+ * @pa_ind: Physical address of the notification indicator byte
  *
  * Returns AP queue status.
  */
 static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
 struct ap_qirq_ctrl qirqctrl,
-void *ind)
+phys_addr_t pa_ind)
 {
unsigned long reg0 = qid | (3UL << 24);  /* fc 3UL is AQIC */
union {
@@ -241,7 +241,7 @@ static inline struct ap_queue_status ap_aqic(ap_qid_t qid,
struct ap_qirq_ctrl qirqctrl;
struct ap_queue_status status;
} reg1;
-   unsigned long reg2 = virt_to_phys(ind);
+   unsigned long reg2 = pa_ind;
 
reg1.qirqctrl = qirqctrl;
 
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index c48b0db824e3..a32457b4cbb8 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -34,7 +34,7 @@ static int ap_queue_enable_irq(struct ap_queue *aq, void *ind)
 
qirqctrl.ir = 1;
qirqctrl.isc = AP_ISC;
-   status = ap_aqic(aq->qid, qirqctrl, ind);
+   status = ap_aqic(aq->qid, qirqctrl, virt_to_phys(ind));
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
case AP_RESPONSE_OTHERWISE_CHANGED:
diff --git a/drivers/s390/crypto/vfio_ap_ops.c 
b/drivers/s390/crypto/vfio_ap_ops.c
index a7d2a95796d3..bb869b28cebd 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -154,7 +154,7 @@ static struct ap_queue_status vfio_ap_irq_disable(struct 
vfio_ap_queue *q)
int retries = 5;
 
do {
-   status = ap_aqic(q->apqn, aqic_gisa, NULL);
+   status = ap_aqic(q->apqn, aqic_gisa, 0);
switch (status.response_code) {
case AP_RESPONSE_OTHERWISE_CHANGED:
case AP_RESPONSE_NORMAL:
@@ -245,7 +245,8 @@ static struct ap_queue_status vfio_ap_irq_enable(struct 
vfio_ap_queue *q,
struct kvm_s390_gisa *gisa;
int nisc;
struct kvm *kvm;
-   unsigned long h_nib, g_pfn, h_pfn;
+   unsigned long g_pfn, h_pfn;
+   phys_addr_t h_nib;
int ret;
 
/* Verify that the notification indicator byte address is valid */
@@ -290,7 +291,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct 
vfio_ap_queue *q,
aqic_gisa.ir = 1;
aqic_gisa.gisa = (uint64_t)gisa >> 4;
 
-   status = ap_aqic(q->apqn, aqic_gisa, (void *)h_nib);
+   status = ap_aqic(q->apqn, aqic_gisa, h_nib);
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
/* See if we did clear older IRQ configuration */
-- 
2.17.1



[PATCH v3 02/10] drm/i915/gvt: Replace roundup with DIV_ROUND_UP

2022-07-08 Thread Nicolin Chen
It's a bit redundant for the maths here using roundup.

Suggested-by: Jason Gunthorpe 
Tested-by: Terrence Xu 
Signed-off-by: Nicolin Chen 
---
 drivers/gpu/drm/i915/gvt/kvmgt.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 8c67c9aba82d..7ce7b09aa5b2 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -231,11 +231,9 @@ static void intel_gvt_cleanup_vgpu_type_groups(struct 
intel_gvt *gvt)
 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long size)
 {
-   int total_pages;
+   int total_pages = DIV_ROUND_UP(size, PAGE_SIZE);
int npage;
 
-   total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
-
for (npage = 0; npage < total_pages; npage++) {
unsigned long cur_gfn = gfn + npage;
 
@@ -247,12 +245,11 @@ static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, 
unsigned long gfn,
 static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
unsigned long size, struct page **page)
 {
+   int total_pages = DIV_ROUND_UP(size, PAGE_SIZE);
unsigned long base_pfn = 0;
-   int total_pages;
int npage;
int ret;
 
-   total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
/*
 * We pin the pages one-by-one to avoid allocating a big arrary
 * on stack to hold pfns.
-- 
2.17.1



[PATCH v3 00/10] Update vfio_pin/unpin_pages API

2022-07-08 Thread Nicolin Chen
This is a preparatory series for IOMMUFD v2 patches. It prepares for
replacing vfio_iommu_type1 implementations of vfio_pin/unpin_pages()
with IOMMUFD version.

There's a gap between these two versions: the vfio_iommu_type1 version
inputs a non-contiguous PFN list and outputs another PFN list for the
pinned physical page list, while the IOMMUFD version only supports a
contiguous address input by accepting the starting IO virtual address
of a set of pages to pin and by outputting to a physical page list.

The nature of existing callers mostly aligns with the IOMMUFD version,
except s390's vfio_ccw_cp code where some additional change is needed
along with this series. Overall, updating to "iova" and "phys_page"
does improve the caller side to some extent.

Also fix a misuse of physical address and virtual address in the s390's
crypto code. And update the input naming at the adjacent vfio_dma_rw().

This is on github:
https://github.com/nicolinc/iommufd/commits/vfio_pin_pages

Terrence has tested this series on i915; Eric has tested on s390.

Thanks!

Changelog
v3:
 * Added a patch to replace roundup with DIV_ROUND_UP in i915 gvt
 * Dropped the "driver->ops->unpin_pages" and NULL checks in PATCH-1
 * Changed to use WARN_ON and separate into lines in PATCH-1
 * Replaced "guest" words with "user" and fix typo in PATCH-5
 * Updated commit log of PATCH-1, PATCH-6, and PATCH-10
 * Added Reviewed/Acked-by from Christoph, Jason, Kirti, Kevin and Eric
 * Added Tested-by from Terrence (i915) and Eric (s390)
v2: https://lore.kernel.org/kvm/20220706062759.24946-1-nicol...@nvidia.com/
 * Added a patch to make vfio_unpin_pages return void
 * Added two patches to remove PFN list from two s390 callers
 * Renamed "phys_page" parameter to "pages" for vfio_pin_pages
 * Updated commit log of kmap_local_page() patch
 * Added Harald's "Reviewed-by" to pa_ind patch
 * Rebased on top of Alex's extern removal path
v1: https://lore.kernel.org/kvm/20220616235212.15185-1-nicol...@nvidia.com/

Nicolin Chen (10):
  vfio: Make vfio_unpin_pages() return void
  drm/i915/gvt: Replace roundup with DIV_ROUND_UP
  vfio/ap: Pass in physical address of ind to ap_aqic()
  vfio/ccw: Only pass in contiguous pages
  vfio: Pass in starting IOVA to vfio_pin/unpin_pages API
  vfio/ap: Change saved_pfn to saved_iova
  vfio/ccw: Change pa_pfn list to pa_iova list
  vfio: Rename user_iova of vfio_dma_rw()
  vfio/ccw: Add kmap_local_page() for memcpy
  vfio: Replace phys_pfn with pages for vfio_pin_pages()

 .../driver-api/vfio-mediated-device.rst   |   6 +-
 arch/s390/include/asm/ap.h|   6 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c  |  49 ++---
 drivers/s390/cio/vfio_ccw_cp.c| 195 +++---
 drivers/s390/crypto/ap_queue.c|   2 +-
 drivers/s390/crypto/vfio_ap_ops.c |  54 +++--
 drivers/s390/crypto/vfio_ap_private.h |   4 +-
 drivers/vfio/vfio.c   |  54 ++---
 drivers/vfio/vfio.h   |   8 +-
 drivers/vfio/vfio_iommu_type1.c   |  45 ++--
 include/linux/vfio.h  |   9 +-
 11 files changed, 215 insertions(+), 217 deletions(-)

-- 
2.17.1



[PATCH] drm/i915/guc: skip scrub_ctbs selftest if reset is disabled

2022-07-08 Thread Daniele Ceraolo Spurio
The test needs GT reset to trigger the scrubbing logic, so we can only
run it when reset is enabled.

Signed-off-by: Daniele Ceraolo Spurio 
Cc: John Harrison 
Cc: Matthew Brost 
---
 drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c 
b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c
index 1df71d0796ae..5bd804f29b32 100644
--- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c
@@ -54,6 +54,9 @@ static int intel_guc_scrub_ctbs(void *arg)
struct intel_engine_cs *engine;
struct intel_context *ce;
 
+   if (!intel_has_gpu_reset(gt))
+   return 0;
+
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
engine = intel_selftest_find_any_engine(gt);
 
-- 
2.25.1



Re: [PATCH 1/9] dt-bindings: msm/dp: drop extra p1 region

2022-07-08 Thread Rob Herring
On Fri, 08 Jul 2022 00:31:56 +0300, Dmitry Baryshkov wrote:
> The p1 region was probably added by mistake, none of the DTS files
> provides one (and the driver source code also doesn't use one). Drop it
> now.
> 
> Fixes: 687825c402f1 ("dt-bindings: msm/dp: Change reg definition")
> Signed-off-by: Dmitry Baryshkov 
> ---
>  Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 -
>  1 file changed, 1 deletion(-)
> 

My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check'
on your patch (DT_CHECKER_FLAGS is new in v5.13):

yamllint warnings/errors:

dtschema/dtc warnings/errors:
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/msm/dp-controller.example.dtb:
 displayport-controller@ae9: reg: [[183042048, 512], [183042560, 512], 
[183043072, 3072], [183046144, 1024], [183047168, 1024]] is too long
From schema: 
/builds/robherring/linux-dt-review/Documentation/devicetree/bindings/display/msm/dp-controller.yaml

doc reference errors (make refcheckdocs):

See https://patchwork.ozlabs.org/patch/

This check can fail if there are any dependencies. The base for a patch
series is generally the most recent rc1.

If you already ran 'make dt_binding_check' and didn't see the above
error(s), then make sure 'yamllint' is installed and dt-schema is up to
date:

pip3 install dtschema --upgrade

Please check and re-submit.



Re: [PATCH v8 02/15] mm: move page zone helpers into new header-specific file

2022-07-08 Thread Felix Kuehling

On 2022-07-08 07:28, David Hildenbrand wrote:

On 07.07.22 21:03, Alex Sierra wrote:

[WHY]
Have a cleaner way to expose all page zone helpers in one header

What exactly is a "page zone"? Do you mean a buddy zone as in
include/linux/mmzone.h ?

Zone as in ZONE_DEVICE. Maybe we could extend mmzone.h instead of 
creating page_zone.h? That should work as long as it's OK to include 
mmzone.h in memremap.h.


Regards,
  Felix




Re: [PATCH] drm/msm/dsi: Set panel orientation when directly connected

2022-07-08 Thread Abhinav Kumar




On 7/8/2022 1:58 PM, Dmitry Baryshkov wrote:

On Fri, 8 Jul 2022 at 22:42, Abhinav Kumar  wrote:




On 7/8/2022 9:00 AM, Abhinav Kumar wrote:



On 7/8/2022 8:25 AM, Doug Anderson wrote:

Hi,

On Wed, Jul 6, 2022 at 12:14 PM Stephen Boyd  wrote:


Set the panel orientation in drm when the panel is directly connected,
i.e. we're not using an external bridge. The external bridge case is
already handled by the panel bridge code, so we only update the path we
take when the panel is directly connected/internal. This silences a
warning splat coming from __drm_mode_object_add() on Wormdingler boards.

Cc: Hsin-Yi Wang 
Cc: Douglas Anderson 
Signed-off-by: Stephen Boyd 
---

This relies on commit 5e41b01a7808 ("drm/panel: Add an API to allow drm
to set orientation from panel") which is in drm-misc

   drivers/gpu/drm/msm/dsi/dsi_manager.c | 2 ++
   1 file changed, 2 insertions(+)


I don't personally have objections to this, but (to my understanding)
"the future" is that everyone should use panel_bridge. If we made the
move to panel_bridge today then we wouldn't need to do this. In
general I think panel_bridge would end up letting us delete a bunch of
code...

See commit 4e5763f03e10 ("drm/bridge: ti-sn65dsi86: Wrap panel with
panel-bridge") for when this was done by ti-sn65dsi86.

Then again, I spent a small amount of time looking into this and it's
definitely non-trivial. Still likely worthwhile, but not worth
blocking a tiny fix like this. It also should be fairly obvious that
we should delete this when we switch to panel_bridge.


Right, from what I saw on IRC, panel_bridge is the way forward and
dmitry did push a change to do that

https://patchwork.freedesktop.org/patch/492585/

But I think we can go ahead with this change because its simple enough.

Regarding the panel_bridge migration, I am going to start reviewing that
as well.



I did some more digging up on the panel_bridge migration.

Dmitry has posted this towards december last year

https://patches.linaro.org/project/dri-devel/patch/20211207222901.988484-3-dmitry.barysh...@linaro.org/


and I had given my R-b on this already in Jan.

I am not sure why this change was dropped OR was not part of msm-next
already.

Dmitry, any reason this change was left out so long and why the R-b was
not retained and this was reposted?

  From what i can see the change looks identical.


I don't remember if it is identical or not. Basically it was postponed
to allow DSC to flow in. We used drm_panel to pass DSC pps data. And
if we use panel-bridge, we don't get a handle of the panel.
Later on I have posted the series moving DSC pps pointer from
drm_panel to mipi_dsi_device (which is logical anyway, since it's not
only the panel, who can provide the DSC pps info, some bridges can
process DSC-compressed data). But since that time it received no
feedback.


Thanks for the details.

I will try to review the DRM core bits. But I guess for them to land, we 
need some of the core maintainers to pitch in on that.








Re: [PATCH] drm/msm/dsi: Set panel orientation when directly connected

2022-07-08 Thread Dmitry Baryshkov
On Fri, 8 Jul 2022 at 22:42, Abhinav Kumar  wrote:
>
>
>
> On 7/8/2022 9:00 AM, Abhinav Kumar wrote:
> >
> >
> > On 7/8/2022 8:25 AM, Doug Anderson wrote:
> >> Hi,
> >>
> >> On Wed, Jul 6, 2022 at 12:14 PM Stephen Boyd  wrote:
> >>>
> >>> Set the panel orientation in drm when the panel is directly connected,
> >>> i.e. we're not using an external bridge. The external bridge case is
> >>> already handled by the panel bridge code, so we only update the path we
> >>> take when the panel is directly connected/internal. This silences a
> >>> warning splat coming from __drm_mode_object_add() on Wormdingler boards.
> >>>
> >>> Cc: Hsin-Yi Wang 
> >>> Cc: Douglas Anderson 
> >>> Signed-off-by: Stephen Boyd 
> >>> ---
> >>>
> >>> This relies on commit 5e41b01a7808 ("drm/panel: Add an API to allow drm
> >>> to set orientation from panel") which is in drm-misc
> >>>
> >>>   drivers/gpu/drm/msm/dsi/dsi_manager.c | 2 ++
> >>>   1 file changed, 2 insertions(+)
> >>
> >> I don't personally have objections to this, but (to my understanding)
> >> "the future" is that everyone should use panel_bridge. If we made the
> >> move to panel_bridge today then we wouldn't need to do this. In
> >> general I think panel_bridge would end up letting us delete a bunch of
> >> code...
> >>
> >> See commit 4e5763f03e10 ("drm/bridge: ti-sn65dsi86: Wrap panel with
> >> panel-bridge") for when this was done by ti-sn65dsi86.
> >>
> >> Then again, I spent a small amount of time looking into this and it's
> >> definitely non-trivial. Still likely worthwhile, but not worth
> >> blocking a tiny fix like this. It also should be fairly obvious that
> >> we should delete this when we switch to panel_bridge.
> >
> > Right, from what I saw on IRC, panel_bridge is the way forward and
> > dmitry did push a change to do that
> >
> > https://patchwork.freedesktop.org/patch/492585/
> >
> > But I think we can go ahead with this change because its simple enough.
> >
> > Regarding the panel_bridge migration, I am going to start reviewing that
> > as well.
> >
>
> I did some more digging up on the panel_bridge migration.
>
> Dmitry has posted this towards december last year
>
> https://patches.linaro.org/project/dri-devel/patch/20211207222901.988484-3-dmitry.barysh...@linaro.org/
>
>
> and I had given my R-b on this already in Jan.
>
> I am not sure why this change was dropped OR was not part of msm-next
> already.
>
> Dmitry, any reason this change was left out so long and why the R-b was
> not retained and this was reposted?
>
>  From what i can see the change looks identical.

I don't remember if it is identical or not. Basically it was postponed
to allow DSC to flow in. We used drm_panel to pass DSC pps data. And
if we use panel-bridge, we don't get a handle of the panel.
Later on I have posted the series moving DSC pps pointer from
drm_panel to mipi_dsi_device (which is logical anyway, since it's not
only the panel, who can provide the DSC pps info, some bridges can
process DSC-compressed data). But since that time it received no
feedback.


-- 
With best wishes
Dmitry


[PATCH 6/6] drm/ingenic: Use the new PM macros

2022-07-08 Thread Paul Cercueil
- Use DEFINE_SIMPLE_DEV_PM_OPS() instead of the SIMPLE_DEV_PM_OPS()
  macro. This makes it possible to remove the __maybe_unused flags on
  the callback functions.
- Since we only have callbacks for suspend/resume, we can conditionally
  compile the dev_pm_ops structure for when CONFIG_PM_SLEEP is enabled;
  so use the pm_sleep_ptr() macro instead of pm_ptr().

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 98ff038d95d6..d5dcff59b9a8 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1470,21 +1470,22 @@ static int ingenic_drm_remove(struct platform_device 
*pdev)
return 0;
 }
 
-static int __maybe_unused ingenic_drm_suspend(struct device *dev)
+static int ingenic_drm_suspend(struct device *dev)
 {
struct ingenic_drm *priv = dev_get_drvdata(dev);
 
return drm_mode_config_helper_suspend(>drm);
 }
 
-static int __maybe_unused ingenic_drm_resume(struct device *dev)
+static int ingenic_drm_resume(struct device *dev)
 {
struct ingenic_drm *priv = dev_get_drvdata(dev);
 
return drm_mode_config_helper_resume(>drm);
 }
 
-static SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops, ingenic_drm_suspend, 
ingenic_drm_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ingenic_drm_pm_ops,
+   ingenic_drm_suspend, ingenic_drm_resume);
 
 static const u32 jz4740_formats[] = {
DRM_FORMAT_XRGB1555,
@@ -1615,7 +1616,7 @@ MODULE_DEVICE_TABLE(of, ingenic_drm_of_match);
 static struct platform_driver ingenic_drm_driver = {
.driver = {
.name = "ingenic-drm",
-   .pm = pm_ptr(_drm_pm_ops),
+   .pm = pm_sleep_ptr(_drm_pm_ops),
.of_match_table = of_match_ptr(ingenic_drm_of_match),
},
.probe = ingenic_drm_probe,
-- 
2.35.1



[PATCH 5/6] drm/ingenic: Make IPU driver its own module

2022-07-08 Thread Paul Cercueil
Instead of building the IPU driver code into the ingenic-drm driver,
create a ingenic-ipu driver.

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/Kconfig   |  2 +-
 drivers/gpu/drm/ingenic/Makefile  |  2 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 33 +--
 drivers/gpu/drm/ingenic/ingenic-drm.h |  3 ---
 drivers/gpu/drm/ingenic/ingenic-ipu.c |  6 -
 5 files changed, 14 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/ingenic/Kconfig b/drivers/gpu/drm/ingenic/Kconfig
index 090830bcbde7..daa1aa81b46b 100644
--- a/drivers/gpu/drm/ingenic/Kconfig
+++ b/drivers/gpu/drm/ingenic/Kconfig
@@ -18,7 +18,7 @@ config DRM_INGENIC
 if DRM_INGENIC
 
 config DRM_INGENIC_IPU
-   bool "IPU support for Ingenic SoCs"
+   tristate "IPU support for Ingenic SoCs"
help
  Choose this option to enable support for the IPU found in Ingenic 
SoCs.
 
diff --git a/drivers/gpu/drm/ingenic/Makefile b/drivers/gpu/drm/ingenic/Makefile
index f10cc1c5a5f2..e650d4ec895b 100644
--- a/drivers/gpu/drm/ingenic/Makefile
+++ b/drivers/gpu/drm/ingenic/Makefile
@@ -1,4 +1,4 @@
 obj-$(CONFIG_DRM_INGENIC) += ingenic-drm.o
 ingenic-drm-y = ingenic-drm-drv.o
-ingenic-drm-$(CONFIG_DRM_INGENIC_IPU) += ingenic-ipu.o
+obj-$(CONFIG_DRM_INGENIC_IPU) += ingenic-ipu.o
 obj-$(CONFIG_DRM_INGENIC_DW_HDMI) += ingenic-dw-hdmi.o
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 78d0b035e2d7..98ff038d95d6 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -550,6 +550,7 @@ void ingenic_drm_plane_disable(struct device *dev, struct 
drm_plane *plane)
regmap_clear_bits(priv->map, JZ_REG_LCD_OSDC, en_bit);
}
 }
+EXPORT_SYMBOL_GPL(ingenic_drm_plane_disable);
 
 static void ingenic_drm_plane_atomic_disable(struct drm_plane *plane,
 struct drm_atomic_state *state)
@@ -633,6 +634,7 @@ void ingenic_drm_plane_config(struct device *dev,
 state->crtc_h << JZ_LCD_SIZE01_HEIGHT_LSB);
}
 }
+EXPORT_SYMBOL_GPL(ingenic_drm_plane_config);
 
 bool ingenic_drm_map_noncoherent(const struct device *dev)
 {
@@ -640,6 +642,7 @@ bool ingenic_drm_map_noncoherent(const struct device *dev)
 
return priv->soc_info->map_noncoherent;
 }
+EXPORT_SYMBOL_GPL(ingenic_drm_map_noncoherent);
 
 static void ingenic_drm_update_palette(struct ingenic_drm *priv,
   const struct drm_color_lut *lut)
@@ -1438,6 +1441,9 @@ static int ingenic_drm_probe(struct platform_device *pdev)
struct component_match *match = NULL;
struct device_node *np;
 
+   if (drm_firmware_drivers_only())
+   return -ENODEV;
+
if (!IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
return ingenic_drm_bind(dev, false);
 
@@ -1615,32 +1621,7 @@ static struct platform_driver ingenic_drm_driver = {
.probe = ingenic_drm_probe,
.remove = ingenic_drm_remove,
 };
-
-static int ingenic_drm_init(void)
-{
-   int err;
-
-   if (drm_firmware_drivers_only())
-   return -ENODEV;
-
-   if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU)) {
-   err = platform_driver_register(ingenic_ipu_driver_ptr);
-   if (err)
-   return err;
-   }
-
-   return platform_driver_register(_drm_driver);
-}
-module_init(ingenic_drm_init);
-
-static void ingenic_drm_exit(void)
-{
-   platform_driver_unregister(_drm_driver);
-
-   if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU))
-   platform_driver_unregister(ingenic_ipu_driver_ptr);
-}
-module_exit(ingenic_drm_exit);
+module_platform_driver(ingenic_drm_driver);
 
 MODULE_AUTHOR("Paul Cercueil ");
 MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n");
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.h 
b/drivers/gpu/drm/ingenic/ingenic-drm.h
index e5bd007ea93d..9b89929b81bc 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm.h
+++ b/drivers/gpu/drm/ingenic/ingenic-drm.h
@@ -220,13 +220,10 @@
 struct device;
 struct drm_plane;
 struct drm_plane_state;
-struct platform_driver;
 
 void ingenic_drm_plane_config(struct device *dev,
  struct drm_plane *plane, u32 fourcc);
 void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane);
 bool ingenic_drm_map_noncoherent(const struct device *dev);
 
-extern struct platform_driver *ingenic_ipu_driver_ptr;
-
 #endif /* DRIVERS_GPU_DRM_INGENIC_INGENIC_DRM_H */
diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c 
b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index d13f58ad4769..fb62c27819ea 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -995,5 +996,8 @@ static struct platform_driver ingenic_ipu_driver = {
.probe = ingenic_ipu_probe,
 

[PATCH 4/6] drm/ingenic: Don't request full modeset if property is not modified

2022-07-08 Thread Paul Cercueil
Avoid requesting a full modeset if the sharpness property is not
modified, because then we don't actually need it.

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-ipu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c 
b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 32a50935aa6d..d13f58ad4769 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -697,10 +697,12 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane 
*plane,
 {
struct ingenic_ipu *ipu = plane_to_ingenic_ipu(plane);
struct drm_crtc_state *crtc_state;
+   bool mode_changed;
 
if (property != ipu->sharpness_prop)
return -EINVAL;
 
+   mode_changed = val != ipu->sharpness;
ipu->sharpness = val;
 
if (state->crtc) {
@@ -708,7 +710,7 @@ ingenic_ipu_plane_atomic_set_property(struct drm_plane 
*plane,
if (WARN_ON(!crtc_state))
return -EINVAL;
 
-   crtc_state->mode_changed = true;
+   crtc_state->mode_changed |= mode_changed;
}
 
return 0;
-- 
2.35.1



[PATCH 3/6] drm/ingenic: Add support for the JZ4760(B)

2022-07-08 Thread Paul Cercueil
Add support for the JZ4760 and JZ4760B SoCs to the ingenic-drm display
driver.

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 28 +++
 1 file changed, 28 insertions(+)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index e435c19d54d5..78d0b035e2d7 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1541,6 +1541,32 @@ static const struct jz_soc_info jz4725b_soc_info = {
.num_formats_f0 = ARRAY_SIZE(jz4725b_formats_f0),
 };
 
+static const struct jz_soc_info jz4760_soc_info = {
+   .needs_dev_clk = false,
+   .has_osd = true,
+   .map_noncoherent = false,
+   .max_width = 1280,
+   .max_height = 720,
+   .max_burst = JZ_LCD_CTRL_BURST_32,
+   .formats_f1 = jz4770_formats_f1,
+   .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
+   .formats_f0 = jz4770_formats_f0,
+   .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
+};
+
+static const struct jz_soc_info jz4760b_soc_info = {
+   .needs_dev_clk = false,
+   .has_osd = true,
+   .map_noncoherent = false,
+   .max_width = 1280,
+   .max_height = 720,
+   .max_burst = JZ_LCD_CTRL_BURST_64,
+   .formats_f1 = jz4770_formats_f1,
+   .num_formats_f1 = ARRAY_SIZE(jz4770_formats_f1),
+   .formats_f0 = jz4770_formats_f0,
+   .num_formats_f0 = ARRAY_SIZE(jz4770_formats_f0),
+};
+
 static const struct jz_soc_info jz4770_soc_info = {
.needs_dev_clk = false,
.has_osd = true,
@@ -1572,6 +1598,8 @@ static const struct jz_soc_info jz4780_soc_info = {
 static const struct of_device_id ingenic_drm_of_match[] = {
{ .compatible = "ingenic,jz4740-lcd", .data = _soc_info },
{ .compatible = "ingenic,jz4725b-lcd", .data = _soc_info },
+   { .compatible = "ingenic,jz4760-lcd", .data = _soc_info },
+   { .compatible = "ingenic,jz4760b-lcd", .data = _soc_info },
{ .compatible = "ingenic,jz4770-lcd", .data = _soc_info },
{ .compatible = "ingenic,jz4780-lcd", .data = _soc_info },
{ /* sentinel */ },
-- 
2.35.1



[PATCH 2/6] drm/ingenic: Fix MODULE_LICENSE() string

2022-07-08 Thread Paul Cercueil
The previous "GPL v2" string is deprecated. For more info, see commit
bf7fbeeae6db ("module: Cure the MODULE_LICENSE "GPL" vs. "GPL v2" bogosity")

Signed-off-by: Paul Cercueil 
---
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c 
b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index eb8208bfe5ab..e435c19d54d5 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1616,4 +1616,4 @@ module_exit(ingenic_drm_exit);
 
 MODULE_AUTHOR("Paul Cercueil ");
 MODULE_DESCRIPTION("DRM driver for the Ingenic SoCs\n");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
-- 
2.35.1



[PATCH 1/6] dt-bindings/display: ingenic: Add compatible string for the JZ4760(B)

2022-07-08 Thread Paul Cercueil
Add compatible strings for the LCD controllers found in the JZ4760 and
JZ4760B SoCs from Ingenic.

Signed-off-by: Paul Cercueil 
Cc: Rob Herring 
Cc: Krzysztof Kozlowski 
Cc: devicet...@vger.kernel.org
---
 Documentation/devicetree/bindings/display/ingenic,lcd.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/Documentation/devicetree/bindings/display/ingenic,lcd.yaml 
b/Documentation/devicetree/bindings/display/ingenic,lcd.yaml
index 0049010b37ca..c0bb02fb49f4 100644
--- a/Documentation/devicetree/bindings/display/ingenic,lcd.yaml
+++ b/Documentation/devicetree/bindings/display/ingenic,lcd.yaml
@@ -17,6 +17,8 @@ properties:
 enum:
   - ingenic,jz4740-lcd
   - ingenic,jz4725b-lcd
+  - ingenic,jz4760-lcd
+  - ingenic,jz4760b-lcd
   - ingenic,jz4770-lcd
   - ingenic,jz4780-lcd
 
-- 
2.35.1



[PATCH 0/6] drm/ingenic: JZ4760(B) support and random changes

2022-07-08 Thread Paul Cercueil
Hi,

A small set of changes to the ingenic-drm driver.

The most notable thing is that ingenic-ipu is now its own platform
driver.

Cheers,
-Paul

Paul Cercueil (6):
  dt-bindings/display: ingenic: Add compatible string for the JZ4760(B)
  drm/ingenic: Fix MODULE_LICENSE() string
  drm/ingenic: Add support for the JZ4760(B)
  drm/ingenic: Don't request full modeset if property is not modified
  drm/ingenic: Make IPU driver its own module
  drm/ingenic: Use the new PM macros

 .../bindings/display/ingenic,lcd.yaml |  2 +
 drivers/gpu/drm/ingenic/Kconfig   |  2 +-
 drivers/gpu/drm/ingenic/Makefile  |  2 +-
 drivers/gpu/drm/ingenic/ingenic-drm-drv.c | 72 +++
 drivers/gpu/drm/ingenic/ingenic-drm.h |  3 -
 drivers/gpu/drm/ingenic/ingenic-ipu.c | 10 ++-
 6 files changed, 53 insertions(+), 38 deletions(-)

-- 
2.35.1



[PATCH v5 9/9] drm: selftest: convert drm_mm selftest to KUnit

2022-07-08 Thread Maíra Canal
From: Arthur Grillo 

Considering the current adoption of the KUnit framework, convert the
DRM mm selftest to the KUnit API.

Signed-off-by: Arthur Grillo 
Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 Documentation/gpu/todo.rst|   11 -
 drivers/gpu/drm/Kconfig   |   20 -
 drivers/gpu/drm/Makefile  |1 -
 drivers/gpu/drm/selftests/Makefile|2 -
 drivers/gpu/drm/selftests/drm_mm_selftests.h  |   28 -
 drivers/gpu/drm/selftests/drm_selftest.c  |  109 --
 drivers/gpu/drm/selftests/drm_selftest.h  |   41 -
 drivers/gpu/drm/tests/Makefile|2 +-
 .../test-drm_mm.c => tests/drm_mm_test.c} | 1248 +++--
 9 files changed, 509 insertions(+), 953 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/Makefile
 delete mode 100644 drivers/gpu/drm/selftests/drm_mm_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.c
 delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.h
 rename drivers/gpu/drm/{selftests/test-drm_mm.c => tests/drm_mm_test.c} (55%)

diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 513b20ccef1e..10bfb50908d1 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -617,17 +617,6 @@ Contact: Javier Martinez Canillas 
 
 Level: Intermediate
 
-Convert Kernel Selftests (kselftest) to KUnit tests when appropriate
-
-
-Many of the `Kselftest 
`_
-tests in DRM could be converted to Kunit tests instead, since that framework
-is more suitable for unit testing.
-
-Contact: Javier Martinez Canillas 
-
-Level: Starter
-
 Enable trinity for DRM
 --
 
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 06822ecf51c6..1c91e1e861a5 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -50,26 +50,6 @@ config DRM_DEBUG_MM
 
  If in doubt, say "N".
 
-config DRM_DEBUG_SELFTEST
-   tristate "kselftests for DRM"
-   depends on DRM
-   depends on DEBUG_KERNEL
-   select PRIME_NUMBERS
-   select DRM_DISPLAY_DP_HELPER
-   select DRM_DISPLAY_HELPER
-   select DRM_LIB_RANDOM
-   select DRM_KMS_HELPER
-   select DRM_BUDDY
-   select DRM_EXPORT_FOR_TESTS if m
-   default n
-   help
- This option provides kernel modules that can be used to run
- various selftests on parts of the DRM api. This option is not
- useful for distributions or general kernels, but only for kernel
- developers working on DRM and associated drivers.
-
- If in doubt, say "N".
-
 config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
depends on DRM && KUNIT
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index e7af358e6dda..25016dcab55e 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -75,7 +75,6 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
 # Drivers and the rest
 #
 
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
 obj-$(CONFIG_DRM_KUNIT_TEST) += tests/
 
 obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
deleted file mode 100644
index a4ebecb8146b..
--- a/drivers/gpu/drm/selftests/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o
diff --git a/drivers/gpu/drm/selftests/drm_mm_selftests.h 
b/drivers/gpu/drm/selftests/drm_mm_selftests.h
deleted file mode 100644
index 8c87c964176b..
--- a/drivers/gpu/drm/selftests/drm_mm_selftests.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(name, function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_mm
- */
-selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
-selftest(init, igt_init)
-selftest(debug, igt_debug)
-selftest(reserve, igt_reserve)
-selftest(insert, igt_insert)
-selftest(replace, igt_replace)
-selftest(insert_range, igt_insert_range)
-selftest(align, igt_align)
-selftest(frag, igt_frag)
-selftest(align32, igt_align32)
-selftest(align64, igt_align64)
-selftest(evict, igt_evict)
-selftest(evict_range, igt_evict_range)
-selftest(bottomup, igt_bottomup)
-selftest(lowest, igt_lowest)
-selftest(topdown, igt_topdown)
-selftest(highest, igt_highest)
-selftest(color, igt_color)
-selftest(color_evict, igt_color_evict)
-selftest(color_evict_range, igt_color_evict_range)
diff --git a/drivers/gpu/drm/selftests/drm_selftest.c 
b/drivers/gpu/drm/selftests/drm_selftest.c
deleted file mode 

[PATCH v5 8/9] drm: selftest: convert drm_buddy selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM buddy selftest to the KUnit API.

Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/selftests/Makefile|   2 +-
 .../gpu/drm/selftests/drm_buddy_selftests.h   |  15 -
 drivers/gpu/drm/selftests/test-drm_buddy.c| 994 --
 drivers/gpu/drm/tests/Makefile|   2 +-
 drivers/gpu/drm/tests/drm_buddy_test.c| 756 +
 5 files changed, 758 insertions(+), 1011 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
 create mode 100644 drivers/gpu/drm/tests/drm_buddy_test.c

diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index f7db628b60cb..a4ebecb8146b 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,2 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_buddy.o
+obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o
diff --git a/drivers/gpu/drm/selftests/drm_buddy_selftests.h 
b/drivers/gpu/drm/selftests/drm_buddy_selftests.h
deleted file mode 100644
index 455b756c4ae5..
--- a/drivers/gpu/drm/selftests/drm_buddy_selftests.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(name, function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_buddy
- */
-selftest(sanitycheck, igt_sanitycheck) /* keep first (selfcheck for igt) */
-selftest(buddy_alloc_limit, igt_buddy_alloc_limit)
-selftest(buddy_alloc_range, igt_buddy_alloc_range)
-selftest(buddy_alloc_optimistic, igt_buddy_alloc_optimistic)
-selftest(buddy_alloc_pessimistic, igt_buddy_alloc_pessimistic)
-selftest(buddy_alloc_smoke, igt_buddy_alloc_smoke)
-selftest(buddy_alloc_pathological, igt_buddy_alloc_pathological)
diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c 
b/drivers/gpu/drm/selftests/test-drm_buddy.c
deleted file mode 100644
index aca0c491040f..
--- a/drivers/gpu/drm/selftests/test-drm_buddy.c
+++ /dev/null
@@ -1,994 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright © 2019 Intel Corporation
- */
-
-#define pr_fmt(fmt) "drm_buddy: " fmt
-
-#include 
-#include 
-#include 
-
-#include 
-
-#include "../lib/drm_random.h"
-
-#define TESTS "drm_buddy_selftests.h"
-#include "drm_selftest.h"
-
-#define IGT_TIMEOUT(name__) \
-   unsigned long name__ = jiffies + MAX_SCHEDULE_TIMEOUT
-
-static unsigned int random_seed;
-
-static inline u64 get_size(int order, u64 chunk_size)
-{
-   return (1 << order) * chunk_size;
-}
-
-__printf(2, 3)
-static bool __igt_timeout(unsigned long timeout, const char *fmt, ...)
-{
-   va_list va;
-
-   if (!signal_pending(current)) {
-   cond_resched();
-   if (time_before(jiffies, timeout))
-   return false;
-   }
-
-   if (fmt) {
-   va_start(va, fmt);
-   vprintk(fmt, va);
-   va_end(va);
-   }
-
-   return true;
-}
-
-static inline const char *yesno(bool v)
-{
-   return v ? "yes" : "no";
-}
-
-static void __igt_dump_block(struct drm_buddy *mm,
-struct drm_buddy_block *block,
-bool buddy)
-{
-   pr_err("block info: header=%llx, state=%u, order=%d, offset=%llx 
size=%llx root=%s buddy=%s\n",
-  block->header,
-  drm_buddy_block_state(block),
-  drm_buddy_block_order(block),
-  drm_buddy_block_offset(block),
-  drm_buddy_block_size(mm, block),
-  yesno(!block->parent),
-  yesno(buddy));
-}
-
-static void igt_dump_block(struct drm_buddy *mm,
-  struct drm_buddy_block *block)
-{
-   struct drm_buddy_block *buddy;
-
-   __igt_dump_block(mm, block, false);
-
-   buddy = drm_get_buddy(block);
-   if (buddy)
-   __igt_dump_block(mm, buddy, true);
-}
-
-static int igt_check_block(struct drm_buddy *mm,
-  struct drm_buddy_block *block)
-{
-   struct drm_buddy_block *buddy;
-   unsigned int block_state;
-   u64 block_size;
-   u64 offset;
-   int err = 0;
-
-   block_state = drm_buddy_block_state(block);
-
-   if (block_state != DRM_BUDDY_ALLOCATED &&
-   block_state != DRM_BUDDY_FREE &&
-   block_state != DRM_BUDDY_SPLIT) {
-   pr_err("block state mismatch\n");
-   err = -EINVAL;
-   }
-
-   block_size = drm_buddy_block_size(mm, block);
-   offset = drm_buddy_block_offset(block);
-
-   if (block_size < mm->chunk_size) {
-   pr_err("block size 

[PATCH v5 6/9] drm: selftest: convert drm_dp_mst_helper selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM DP MST helper selftest to the KUnit API.

Co-developed-by: Rubens Gomes Neto 
Signed-off-by: Rubens Gomes Neto 
Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/selftests/Makefile|  3 +-
 .../gpu/drm/selftests/drm_modeset_selftests.h |  2 -
 .../drm/selftests/test-drm_modeset_common.h   |  2 -
 drivers/gpu/drm/tests/Makefile|  3 +-
 .../drm_dp_mst_helper_test.c} | 89 +++
 5 files changed, 53 insertions(+), 46 deletions(-)
 rename drivers/gpu/drm/{selftests/test-drm_dp_mst_helper.c => 
tests/drm_dp_mst_helper_test.c} (72%)

diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index 9e0ccb482841..1539f55db9a7 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o \
-   test-drm_dp_mst_helper.o
+test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \
test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h 
b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
index 22e467f6465a..40a29b8cf386 100644
--- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
@@ -7,5 +7,3 @@
  * Tests are executed in order by igt/drm_selftests_helper
  */
 selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
-selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode)
-selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h 
b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
index 790f3cf31f0d..3feb2fea1a6b 100644
--- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h
+++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
@@ -17,7 +17,5 @@
 #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
 
 int igt_check_drm_framebuffer_create(void *ignored);
-int igt_dp_mst_calc_pbn_mode(void *ignored);
-int igt_dp_mst_sideband_msg_req_decode(void *ignored);
 
 #endif
diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 4d44006a4f23..5ffacd3eacf3 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -1,4 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o 
drm_damage_helper_test.o \
-   drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o 
drm_plane_helper_test.o
+   drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o 
drm_plane_helper_test.o \
+   drm_dp_mst_helper_test.o
diff --git a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c 
b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
similarity index 72%
rename from drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
rename to drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
index 4caa9be900ac..1d2fade56227 100644
--- a/drivers/gpu/drm/selftests/test-drm_dp_mst_helper.c
+++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
@@ -1,19 +1,22 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
  * Test cases for the DRM DP MST helpers
+ *
+ * Copyright (c) 2022 Maíra Canal 
  */
 
 #define PREFIX_STR "[drm_dp_mst_helper]"
 
+#include 
+
 #include 
 
 #include 
 #include 
 
 #include "../display/drm_dp_mst_topology_internal.h"
-#include "test-drm_modeset_common.h"
 
-int igt_dp_mst_calc_pbn_mode(void *ignored)
+static void igt_dp_mst_calc_pbn_mode(struct kunit *test)
 {
int pbn, i;
const struct {
@@ -33,13 +36,11 @@ int igt_dp_mst_calc_pbn_mode(void *ignored)
pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
   test_params[i].bpp,
   test_params[i].dsc);
-   FAIL(pbn != test_params[i].expected,
-"Expected PBN %d for clock %d bpp %d, got %d\n",
+   KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected,
+   "Expected PBN %d for clock %d bpp %d, got 
%d\n",
 test_params[i].expected, test_params[i].rate,
 test_params[i].bpp, pbn);
}
-
-   return 0;
 }
 
 static bool
@@ -176,66 +177,64 @@ sideband_msg_req_encode_decode(struct 
drm_dp_sideband_msg_req_body *in)
return result;
 }
 
-int igt_dp_mst_sideband_msg_req_decode(void *unused)
+static void igt_dp_mst_sideband_msg_req_decode(struct kunit *test)
 {
struct drm_dp_sideband_msg_req_body in = { 0 };
u8 data[] = { 0xff, 0x0, 0xdd };
int i;
 
-#define DO_TEST() 

[PATCH v5 5/9] drm: selftest: convert drm_plane_helper selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM plane helper selftest to the KUnit API.

Co-developed-by: Djakson C. G. Filho 
Signed-off-by: Djakson C. G. Filho 
Co-developed-by: Anderson Fraga 
Signed-off-by: Anderson Fraga 
Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/selftests/Makefile|   4 +-
 .../gpu/drm/selftests/drm_modeset_selftests.h |   1 -
 .../drm/selftests/test-drm_modeset_common.h   |   1 -
 drivers/gpu/drm/tests/Makefile|   2 +-
 .../drm_plane_helper_test.c}  | 122 ++
 5 files changed, 71 insertions(+), 59 deletions(-)
 rename drivers/gpu/drm/{selftests/test-drm_plane_helper.c => 
tests/drm_plane_helper_test.c} (57%)

diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index b7f252d886d0..9e0ccb482841 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
-test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
-  test-drm_framebuffer.o test-drm_dp_mst_helper.o
+test-drm_modeset-y := test-drm_modeset_common.o test-drm_framebuffer.o \
+   test-drm_dp_mst_helper.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \
test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h 
b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
index 63061ef55eff..22e467f6465a 100644
--- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
@@ -6,7 +6,6 @@
  *
  * Tests are executed in order by igt/drm_selftests_helper
  */
-selftest(check_plane_state, igt_check_plane_state)
 selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
 selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode)
 selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h 
b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
index 5709d967a5c4..790f3cf31f0d 100644
--- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h
+++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
@@ -16,7 +16,6 @@
 
 #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
 
-int igt_check_plane_state(void *ignored);
 int igt_check_drm_framebuffer_create(void *ignored);
 int igt_dp_mst_calc_pbn_mode(void *ignored);
 int igt_dp_mst_sideband_msg_req_decode(void *ignored);
diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 1aa1627cb5e6..4d44006a4f23 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o 
drm_damage_helper_test.o \
-   drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o
+   drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o 
drm_plane_helper_test.o
diff --git a/drivers/gpu/drm/selftests/test-drm_plane_helper.c 
b/drivers/gpu/drm/tests/drm_plane_helper_test.c
similarity index 57%
rename from drivers/gpu/drm/selftests/test-drm_plane_helper.c
rename to drivers/gpu/drm/tests/drm_plane_helper_test.c
index 64e8938ab194..e298766cd41f 100644
--- a/drivers/gpu/drm/selftests/test-drm_plane_helper.c
+++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c
@@ -1,20 +1,20 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Test cases for the drm_plane_helper functions
+ *
+ * Copyright (c) 2022 Maíra Canal 
  */
 
-#define pr_fmt(fmt) "drm_plane_helper: " fmt
+#include 
 
 #include 
 #include 
 #include 
 #include 
 
-#include "test-drm_modeset_common.h"
-
 static void set_src(struct drm_plane_state *plane_state,
-   unsigned src_x, unsigned src_y,
-   unsigned src_w, unsigned src_h)
+   unsigned int src_x, unsigned int src_y,
+   unsigned int src_w, unsigned int src_h)
 {
plane_state->src_x = src_x;
plane_state->src_y = src_y;
@@ -23,8 +23,8 @@ static void set_src(struct drm_plane_state *plane_state,
 }
 
 static bool check_src_eq(struct drm_plane_state *plane_state,
-unsigned src_x, unsigned src_y,
-unsigned src_w, unsigned src_h)
+unsigned int src_x, unsigned int src_y,
+unsigned int src_w, unsigned int src_h)
 {
if (plane_state->src.x1 < 0) {
pr_err("src x coordinate %x should never be below 0.\n", 
plane_state->src.x1);
@@ -50,7 +50,7 @@ static bool check_src_eq(struct drm_plane_state *plane_state,
 
 static void set_crtc(struct drm_plane_state *plane_state,
 int crtc_x, int crtc_y,
-unsigned crtc_w, unsigned crtc_h)
+   

[PATCH v5 4/9] drm: selftest: convert drm_format selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM format selftest to the KUnit API.

Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/selftests/Makefile|   3 +-
 .../gpu/drm/selftests/drm_modeset_selftests.h |   3 -
 drivers/gpu/drm/selftests/test-drm_format.c   | 280 -
 .../drm/selftests/test-drm_modeset_common.h   |   3 -
 drivers/gpu/drm/tests/Makefile|   2 +-
 drivers/gpu/drm/tests/drm_format_test.c   | 287 ++
 6 files changed, 289 insertions(+), 289 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c
 create mode 100644 drivers/gpu/drm/tests/drm_format_test.c

diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index 8a794914e328..b7f252d886d0 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,7 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
 test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
-  test-drm_format.o test-drm_framebuffer.o \
- test-drm_dp_mst_helper.o
+  test-drm_framebuffer.o test-drm_dp_mst_helper.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \
test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h 
b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
index a3ca90307364..63061ef55eff 100644
--- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
@@ -7,9 +7,6 @@
  * Tests are executed in order by igt/drm_selftests_helper
  */
 selftest(check_plane_state, igt_check_plane_state)
-selftest(check_drm_format_block_width, igt_check_drm_format_block_width)
-selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
-selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch)
 selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
 selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode)
 selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
diff --git a/drivers/gpu/drm/selftests/test-drm_format.c 
b/drivers/gpu/drm/selftests/test-drm_format.c
deleted file mode 100644
index c5e212afa27a..
--- a/drivers/gpu/drm/selftests/test-drm_format.c
+++ /dev/null
@@ -1,280 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_format functions
- */
-
-#define pr_fmt(fmt) "drm_format: " fmt
-
-#include 
-#include 
-
-#include 
-
-#include "test-drm_modeset_common.h"
-
-int igt_check_drm_format_block_width(void *ignored)
-{
-   const struct drm_format_info *info = NULL;
-
-   /* Test invalid arguments */
-   FAIL_ON(drm_format_info_block_width(info, 0) != 0);
-   FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-   FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-
-   /* Test 1 plane format */
-   info = drm_format_info(DRM_FORMAT_XRGB);
-   FAIL_ON(!info);
-   FAIL_ON(drm_format_info_block_width(info, 0) != 1);
-   FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-   FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-   /* Test 2 planes format */
-   info = drm_format_info(DRM_FORMAT_NV12);
-   FAIL_ON(!info);
-   FAIL_ON(drm_format_info_block_width(info, 0) != 1);
-   FAIL_ON(drm_format_info_block_width(info, 1) != 1);
-   FAIL_ON(drm_format_info_block_width(info, 2) != 0);
-   FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-   /* Test 3 planes format */
-   info = drm_format_info(DRM_FORMAT_YUV422);
-   FAIL_ON(!info);
-   FAIL_ON(drm_format_info_block_width(info, 0) != 1);
-   FAIL_ON(drm_format_info_block_width(info, 1) != 1);
-   FAIL_ON(drm_format_info_block_width(info, 2) != 1);
-   FAIL_ON(drm_format_info_block_width(info, 3) != 0);
-   FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-   /* Test a tiled format */
-   info = drm_format_info(DRM_FORMAT_X0L0);
-   FAIL_ON(!info);
-   FAIL_ON(drm_format_info_block_width(info, 0) != 2);
-   FAIL_ON(drm_format_info_block_width(info, 1) != 0);
-   FAIL_ON(drm_format_info_block_width(info, -1) != 0);
-
-   return 0;
-}
-
-int igt_check_drm_format_block_height(void *ignored)
-{
-   const struct drm_format_info *info = NULL;
-
-   /* Test invalid arguments */
-   FAIL_ON(drm_format_info_block_height(info, 0) != 0);
-   FAIL_ON(drm_format_info_block_height(info, -1) != 0);
-   FAIL_ON(drm_format_info_block_height(info, 1) != 0);
-
-   /* Test 1 plane format */
-   info = drm_format_info(DRM_FORMAT_XRGB);
-   FAIL_ON(!info);
-   FAIL_ON(drm_format_info_block_height(info, 0) != 1);
-   FAIL_ON(drm_format_info_block_height(info, 1) != 0);
-   

Re: [RFT][PATCH v2 0/9] Update vfio_pin/unpin_pages API

2022-07-08 Thread Nicolin Chen
On Fri, Jul 08, 2022 at 04:30:32PM -0400, Eric Farman wrote:
> External email: Use caution opening links or attachments
> 
> 
> On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> > This is a preparatory series for IOMMUFD v2 patches. It prepares for
> > replacing vfio_iommu_type1 implementations of vfio_pin/unpin_pages()
> > with IOMMUFD version.
> >
> > There's a gap between these two versions: the vfio_iommu_type1
> > version
> > inputs a non-contiguous PFN list and outputs another PFN list for the
> > pinned physical page list, while the IOMMUFD version only supports a
> > contiguous address input by accepting the starting IO virtual address
> > of a set of pages to pin and by outputting to a physical page list.
> >
> > The nature of existing callers mostly aligns with the IOMMUFD
> > version,
> > except s390's vfio_ccw_cp code where some additional change is needed
> > along with this series. Overall, updating to "iova" and "phys_page"
> > does improve the caller side to some extent.
> >
> > Also fix a misuse of physical address and virtual address in the
> > s390's
> > crypto code. And update the input naming at the adjacent
> > vfio_dma_rw().
> >
> > This is on github:
> > https://github.com/nicolinc/iommufd/commits/vfio_pin_pages
> >
> > Request for testing: I only did build for s390 and i915 code, so it'd
> > be nice to have people who have environment to run sanity
> > accordingly.
> 
> Tested-by: Eric Farman# s390

Thank you for the review and test!


[PATCH v5 3/9] drm: selftest: convert drm_rect selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM rect selftest to the KUnit API.

Co-developed-by: Carlos Veras 
Signed-off-by: Carlos Veras 
Co-developed-by: Matheus Vieira 
Signed-off-by: Matheus Vieira 
Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/selftests/Makefile|   2 +-
 .../gpu/drm/selftests/drm_modeset_selftests.h |   4 -
 .../drm/selftests/test-drm_modeset_common.h   |   4 -
 drivers/gpu/drm/selftests/test-drm_rect.c | 223 --
 drivers/gpu/drm/tests/Makefile|   2 +-
 drivers/gpu/drm/tests/drm_rect_test.c | 214 +
 6 files changed, 216 insertions(+), 233 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_rect.c
 create mode 100644 drivers/gpu/drm/tests/drm_rect_test.c

diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index 8633bb9ea717..8a794914e328 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
   test-drm_format.o test-drm_framebuffer.o \
- test-drm_dp_mst_helper.o test-drm_rect.o
+ test-drm_dp_mst_helper.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \
test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h 
b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
index 4787b3b70709..a3ca90307364 100644
--- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
@@ -6,10 +6,6 @@
  *
  * Tests are executed in order by igt/drm_selftests_helper
  */
-selftest(drm_rect_clip_scaled_div_by_zero, 
igt_drm_rect_clip_scaled_div_by_zero)
-selftest(drm_rect_clip_scaled_not_clipped, 
igt_drm_rect_clip_scaled_not_clipped)
-selftest(drm_rect_clip_scaled_clipped, igt_drm_rect_clip_scaled_clipped)
-selftest(drm_rect_clip_scaled_signed_vs_unsigned, 
igt_drm_rect_clip_scaled_signed_vs_unsigned)
 selftest(check_plane_state, igt_check_plane_state)
 selftest(check_drm_format_block_width, igt_check_drm_format_block_width)
 selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
diff --git a/drivers/gpu/drm/selftests/test-drm_modeset_common.h 
b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
index c29354e59cec..42a10d7da51c 100644
--- a/drivers/gpu/drm/selftests/test-drm_modeset_common.h
+++ b/drivers/gpu/drm/selftests/test-drm_modeset_common.h
@@ -16,10 +16,6 @@
 
 #define FAIL_ON(x) FAIL((x), "%s", "FAIL_ON(" __stringify(x) ")\n")
 
-int igt_drm_rect_clip_scaled_div_by_zero(void *ignored);
-int igt_drm_rect_clip_scaled_not_clipped(void *ignored);
-int igt_drm_rect_clip_scaled_clipped(void *ignored);
-int igt_drm_rect_clip_scaled_signed_vs_unsigned(void *ignored);
 int igt_check_plane_state(void *ignored);
 int igt_check_drm_format_block_width(void *ignored);
 int igt_check_drm_format_block_height(void *ignored);
diff --git a/drivers/gpu/drm/selftests/test-drm_rect.c 
b/drivers/gpu/drm/selftests/test-drm_rect.c
deleted file mode 100644
index 3a5ff38321f4..
--- a/drivers/gpu/drm/selftests/test-drm_rect.c
+++ /dev/null
@@ -1,223 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Test cases for the drm_rect functions
- */
-
-#define pr_fmt(fmt) "drm_rect: " fmt
-
-#include 
-
-#include 
-
-#include "test-drm_modeset_common.h"
-
-int igt_drm_rect_clip_scaled_div_by_zero(void *ignored)
-{
-   struct drm_rect src, dst, clip;
-   bool visible;
-
-   /*
-* Make sure we don't divide by zero when dst
-* width/height is zero and dst and clip do not intersect.
-*/
-   drm_rect_init(, 0, 0, 0, 0);
-   drm_rect_init(, 0, 0, 0, 0);
-   drm_rect_init(, 1, 1, 1, 1);
-   visible = drm_rect_clip_scaled(, , );
-   FAIL(visible, "Destination not be visible\n");
-   FAIL(drm_rect_visible(), "Source should not be visible\n");
-
-   drm_rect_init(, 0, 0, 0, 0);
-   drm_rect_init(, 3, 3, 0, 0);
-   drm_rect_init(, 1, 1, 1, 1);
-   visible = drm_rect_clip_scaled(, , );
-   FAIL(visible, "Destination not be visible\n");
-   FAIL(drm_rect_visible(), "Source should not be visible\n");
-
-   return 0;
-}
-
-int igt_drm_rect_clip_scaled_not_clipped(void *ignored)
-{
-   struct drm_rect src, dst, clip;
-   bool visible;
-
-   /* 1:1 scaling */
-   drm_rect_init(, 0, 0, 1 << 16, 1 << 16);
-   drm_rect_init(, 0, 0, 1, 1);
-   drm_rect_init(, 0, 0, 1, 1);
-
-   visible = drm_rect_clip_scaled(, , );
-
-   FAIL(src.x1 != 0 || src.x2 != 1 << 16 ||
-src.y1 != 0 || src.y2 != 1 << 16,
-"Source badly clipped\n");
-   FAIL(dst.x1 != 0 || dst.x2 != 1 ||
-dst.y1 != 0 || 

[PATCH v5 2/9] drm: selftest: convert drm_cmdline_parser selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM cmdline parser selftest to the KUnit API.

Co-developed-by: Arthur Grillo 
Signed-off-by: Arthur Grillo 
Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/selftests/Makefile|2 +-
 .../gpu/drm/selftests/drm_cmdline_selftests.h |   68 -
 .../drm/selftests/test-drm_cmdline_parser.c   | 1141 -
 drivers/gpu/drm/tests/Makefile|3 +-
 .../gpu/drm/tests/drm_cmdline_parser_test.c   | 1078 
 5 files changed, 1081 insertions(+), 1211 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/drm_cmdline_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
 create mode 100644 drivers/gpu/drm/tests/drm_cmdline_parser_test.c

diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index 7a1a732e0a1b..8633bb9ea717 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -3,5 +3,5 @@ test-drm_modeset-y := test-drm_modeset_common.o 
test-drm_plane_helper.o \
   test-drm_format.o test-drm_framebuffer.o \
  test-drm_dp_mst_helper.o test-drm_rect.o
 
-obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o 
test-drm_cmdline_parser.o \
+obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o \
test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h 
b/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
deleted file mode 100644
index 29e367db6118..
--- a/drivers/gpu/drm/selftests/drm_cmdline_selftests.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* List each unit test as selftest(function)
- *
- * The name is used as both an enum and expanded as igt__name to create
- * a module parameter. It must be unique and legal for a C identifier.
- *
- * Tests are executed in order by igt/drm_mm
- */
-
-#define cmdline_test(test) selftest(test, test)
-
-cmdline_test(drm_cmdline_test_force_d_only)
-cmdline_test(drm_cmdline_test_force_D_only_dvi)
-cmdline_test(drm_cmdline_test_force_D_only_hdmi)
-cmdline_test(drm_cmdline_test_force_D_only_not_digital)
-cmdline_test(drm_cmdline_test_force_e_only)
-cmdline_test(drm_cmdline_test_margin_only)
-cmdline_test(drm_cmdline_test_interlace_only)
-cmdline_test(drm_cmdline_test_res)
-cmdline_test(drm_cmdline_test_res_missing_x)
-cmdline_test(drm_cmdline_test_res_missing_y)
-cmdline_test(drm_cmdline_test_res_bad_y)
-cmdline_test(drm_cmdline_test_res_missing_y_bpp)
-cmdline_test(drm_cmdline_test_res_vesa)
-cmdline_test(drm_cmdline_test_res_vesa_rblank)
-cmdline_test(drm_cmdline_test_res_rblank)
-cmdline_test(drm_cmdline_test_res_bpp)
-cmdline_test(drm_cmdline_test_res_bad_bpp)
-cmdline_test(drm_cmdline_test_res_refresh)
-cmdline_test(drm_cmdline_test_res_bad_refresh)
-cmdline_test(drm_cmdline_test_res_bpp_refresh)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_margins)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_off)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_off)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_analog)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_force_on_digital)
-cmdline_test(drm_cmdline_test_res_bpp_refresh_interlaced_margins_force_on)
-cmdline_test(drm_cmdline_test_res_margins_force_on)
-cmdline_test(drm_cmdline_test_res_vesa_margins)
-cmdline_test(drm_cmdline_test_res_invalid_mode)
-cmdline_test(drm_cmdline_test_res_bpp_wrong_place_mode)
-cmdline_test(drm_cmdline_test_name)
-cmdline_test(drm_cmdline_test_name_bpp)
-cmdline_test(drm_cmdline_test_name_refresh)
-cmdline_test(drm_cmdline_test_name_bpp_refresh)
-cmdline_test(drm_cmdline_test_name_refresh_wrong_mode)
-cmdline_test(drm_cmdline_test_name_refresh_invalid_mode)
-cmdline_test(drm_cmdline_test_name_option)
-cmdline_test(drm_cmdline_test_name_bpp_option)
-cmdline_test(drm_cmdline_test_rotate_0)
-cmdline_test(drm_cmdline_test_rotate_90)
-cmdline_test(drm_cmdline_test_rotate_180)
-cmdline_test(drm_cmdline_test_rotate_270)
-cmdline_test(drm_cmdline_test_rotate_multiple)
-cmdline_test(drm_cmdline_test_rotate_invalid_val)
-cmdline_test(drm_cmdline_test_rotate_truncated)
-cmdline_test(drm_cmdline_test_hmirror)
-cmdline_test(drm_cmdline_test_vmirror)
-cmdline_test(drm_cmdline_test_margin_options)
-cmdline_test(drm_cmdline_test_multiple_options)
-cmdline_test(drm_cmdline_test_invalid_option)
-cmdline_test(drm_cmdline_test_bpp_extra_and_option)
-cmdline_test(drm_cmdline_test_extra_and_option)
-cmdline_test(drm_cmdline_test_freestanding_options)
-cmdline_test(drm_cmdline_test_freestanding_force_e_and_options)
-cmdline_test(drm_cmdline_test_panel_orientation)
diff --git 

[PATCH v5 1/9] drm: selftest: convert drm_damage_helper selftest to KUnit

2022-07-08 Thread Maíra Canal
Considering the current adoption of the KUnit framework, convert the
DRM damage helper selftest to the KUnit API.

Co-developed-by: Arthur Grillo 
Signed-off-by: Arthur Grillo 
Tested-by: David Gow 
Acked-by: Daniel Latypov 
Reviewed-by: Javier Martinez Canillas 
Signed-off-by: Maíra Canal 
---
 drivers/gpu/drm/Kconfig   |   8 +-
 drivers/gpu/drm/selftests/Makefile|   3 +-
 .../gpu/drm/selftests/drm_modeset_selftests.h |  21 -
 .../drm/selftests/test-drm_damage_helper.c| 668 --
 .../drm/selftests/test-drm_modeset_common.h   |  21 -
 drivers/gpu/drm/tests/Makefile|   2 +-
 .../gpu/drm/tests/drm_damage_helper_test.c| 634 +
 7 files changed, 643 insertions(+), 714 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_damage_helper.c
 create mode 100644 drivers/gpu/drm/tests/drm_damage_helper_test.c

diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 6c2256e8474b..06822ecf51c6 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -72,8 +72,14 @@ config DRM_DEBUG_SELFTEST
 
 config DRM_KUNIT_TEST
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
-   depends on DRM && KUNIT=y
+   depends on DRM && KUNIT
+   select PRIME_NUMBERS
+   select DRM_DISPLAY_DP_HELPER
+   select DRM_DISPLAY_HELPER
+   select DRM_LIB_RANDOM
select DRM_KMS_HELPER
+   select DRM_BUDDY
+   select DRM_EXPORT_FOR_TESTS if m
default KUNIT_ALL_TESTS
help
  This builds unit tests for DRM. This option is not useful for
diff --git a/drivers/gpu/drm/selftests/Makefile 
b/drivers/gpu/drm/selftests/Makefile
index 5ba5f9138c95..7a1a732e0a1b 100644
--- a/drivers/gpu/drm/selftests/Makefile
+++ b/drivers/gpu/drm/selftests/Makefile
@@ -1,8 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 test-drm_modeset-y := test-drm_modeset_common.o test-drm_plane_helper.o \
   test-drm_format.o test-drm_framebuffer.o \
- test-drm_damage_helper.o test-drm_dp_mst_helper.o \
- test-drm_rect.o
+ test-drm_dp_mst_helper.o test-drm_rect.o
 
 obj-$(CONFIG_DRM_DEBUG_SELFTEST) += test-drm_mm.o test-drm_modeset.o 
test-drm_cmdline_parser.o \
test-drm_buddy.o
diff --git a/drivers/gpu/drm/selftests/drm_modeset_selftests.h 
b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
index 782e285ca383..4787b3b70709 100644
--- a/drivers/gpu/drm/selftests/drm_modeset_selftests.h
+++ b/drivers/gpu/drm/selftests/drm_modeset_selftests.h
@@ -15,26 +15,5 @@ selftest(check_drm_format_block_width, 
igt_check_drm_format_block_width)
 selftest(check_drm_format_block_height, igt_check_drm_format_block_height)
 selftest(check_drm_format_min_pitch, igt_check_drm_format_min_pitch)
 selftest(check_drm_framebuffer_create, igt_check_drm_framebuffer_create)
-selftest(damage_iter_no_damage, igt_damage_iter_no_damage)
-selftest(damage_iter_no_damage_fractional_src, 
igt_damage_iter_no_damage_fractional_src)
-selftest(damage_iter_no_damage_src_moved, igt_damage_iter_no_damage_src_moved)
-selftest(damage_iter_no_damage_fractional_src_moved, 
igt_damage_iter_no_damage_fractional_src_moved)
-selftest(damage_iter_no_damage_not_visible, 
igt_damage_iter_no_damage_not_visible)
-selftest(damage_iter_no_damage_no_crtc, igt_damage_iter_no_damage_no_crtc)
-selftest(damage_iter_no_damage_no_fb, igt_damage_iter_no_damage_no_fb)
-selftest(damage_iter_simple_damage, igt_damage_iter_simple_damage)
-selftest(damage_iter_single_damage, igt_damage_iter_single_damage)
-selftest(damage_iter_single_damage_intersect_src, 
igt_damage_iter_single_damage_intersect_src)
-selftest(damage_iter_single_damage_outside_src, 
igt_damage_iter_single_damage_outside_src)
-selftest(damage_iter_single_damage_fractional_src, 
igt_damage_iter_single_damage_fractional_src)
-selftest(damage_iter_single_damage_intersect_fractional_src, 
igt_damage_iter_single_damage_intersect_fractional_src)
-selftest(damage_iter_single_damage_outside_fractional_src, 
igt_damage_iter_single_damage_outside_fractional_src)
-selftest(damage_iter_single_damage_src_moved, 
igt_damage_iter_single_damage_src_moved)
-selftest(damage_iter_single_damage_fractional_src_moved, 
igt_damage_iter_single_damage_fractional_src_moved)
-selftest(damage_iter_damage, igt_damage_iter_damage)
-selftest(damage_iter_damage_one_intersect, 
igt_damage_iter_damage_one_intersect)
-selftest(damage_iter_damage_one_outside, igt_damage_iter_damage_one_outside)
-selftest(damage_iter_damage_src_moved, igt_damage_iter_damage_src_moved)
-selftest(damage_iter_damage_not_visible, igt_damage_iter_damage_not_visible)
 selftest(dp_mst_calc_pbn_mode, igt_dp_mst_calc_pbn_mode)
 selftest(dp_mst_sideband_msg_req_decode, igt_dp_mst_sideband_msg_req_decode)
diff --git a/drivers/gpu/drm/selftests/test-drm_damage_helper.c 
b/drivers/gpu/drm/selftests/test-drm_damage_helper.c
deleted file mode 100644

[PATCH v5 0/9] drm: selftest: Convert to KUnit

2022-07-08 Thread Maíra Canal
Hi everyone,

Here is the v5 of the conversion of selftests to KUnit. Since the v4, the only
fix was checking the checkpatch warnings and checks (Thank you Javier).

Thanks for your attention and any feedback is welcomed!

Best Regards,
- Maíra Canal

v1 -> v2: 
https://lore.kernel.org/dri-devel/20220615135824.15522-1-maira.ca...@usp.br/T/

- The suites not longer end in _tests (David Gow).
- Remove the TODO entry involving the conversion of selftests to KUnit (Javier 
Martinez Canillas).
- Change the filenames to match the documentation: use *_test.c (Javier 
Martinez Canillas).
- Add MODULE_LICENSE to all tests (kernel test robot).
- Make use of a generic symbol to group all tests - DRM_KUNIT_TEST (Javier 
Martinez Canillas).
- Add .kunitconfig on the first patch (it was on the second patch of the 
series).
- Straightforward conversion of the drm_cmdline_parser tests without functional 
changes (Shuah Khan)
- Add David's Tested-by tags.

v2 -> v3: 
https://lore.kernel.org/dri-devel/20220621200926.257002-1-maira.ca...@usp.br/

- Rebase it on top of the drm-misc-next with drm_format_helper KUnit tests.
- Change KUNIT_EXPECT_FALSE to KUNIT_EXPECT_EQ on drm_format_test (Daniel 
Latypov).
- Add Daniel's Acked-by tag.

v3 -> v4: 
https://lore.kernel.org/dri-devel/9185aadb-e459-00fe-70be-3675f6f3e...@redhat.com/T/

- Add blank line after #include   (Javier Martinez Canillas).
- Make the order of the tags chronological  (Javier Martinez Canillas).
- Add Copywrite to the tests (Javier Martinez Canillas).
- Add  Javier Martinez Canillas's Reviewed-By tag.

v4 -> v5: 
https://lore.kernel.org/dri-devel/20220702131116.457444-1-maira.ca...@usp.br/T/

- Fix checkpatch warnings and checks (Javier Martinez Canillas).

Arthur Grillo (1):
  drm: selftest: convert drm_mm selftest to KUnit

Maíra Canal (8):
  drm: selftest: convert drm_damage_helper selftest to KUnit
  drm: selftest: convert drm_cmdline_parser selftest to KUnit
  drm: selftest: convert drm_rect selftest to KUnit
  drm: selftest: convert drm_format selftest to KUnit
  drm: selftest: convert drm_plane_helper selftest to KUnit
  drm: selftest: convert drm_dp_mst_helper selftest to KUnit
  drm: selftest: convert drm_framebuffer selftest to KUnit
  drm: selftest: convert drm_buddy selftest to KUnit

 Documentation/gpu/todo.rst|   11 -
 drivers/gpu/drm/Kconfig   |   20 +-
 drivers/gpu/drm/Makefile  |1 -
 drivers/gpu/drm/selftests/Makefile|8 -
 .../gpu/drm/selftests/drm_buddy_selftests.h   |   15 -
 .../gpu/drm/selftests/drm_cmdline_selftests.h |   68 -
 drivers/gpu/drm/selftests/drm_mm_selftests.h  |   28 -
 .../gpu/drm/selftests/drm_modeset_selftests.h |   40 -
 drivers/gpu/drm/selftests/drm_selftest.c  |  109 --
 drivers/gpu/drm/selftests/drm_selftest.h  |   41 -
 drivers/gpu/drm/selftests/test-drm_buddy.c|  994 -
 .../drm/selftests/test-drm_cmdline_parser.c   | 1141 ---
 .../drm/selftests/test-drm_damage_helper.c|  668 -
 drivers/gpu/drm/selftests/test-drm_format.c   |  280 
 .../drm/selftests/test-drm_modeset_common.c   |   32 -
 .../drm/selftests/test-drm_modeset_common.h   |   52 -
 drivers/gpu/drm/selftests/test-drm_rect.c |  223 ---
 drivers/gpu/drm/tests/Makefile|4 +-
 drivers/gpu/drm/tests/drm_buddy_test.c|  756 ++
 .../gpu/drm/tests/drm_cmdline_parser_test.c   | 1078 ++
 .../gpu/drm/tests/drm_damage_helper_test.c|  634 +
 .../drm_dp_mst_helper_test.c} |   89 +-
 drivers/gpu/drm/tests/drm_format_test.c   |  287 
 .../drm_framebuffer_test.c}   |   77 +-
 .../test-drm_mm.c => tests/drm_mm_test.c} | 1248 +++--
 .../drm_plane_helper_test.c}  |  122 +-
 drivers/gpu/drm/tests/drm_rect_test.c |  214 +++
 27 files changed, 3652 insertions(+), 4588 deletions(-)
 delete mode 100644 drivers/gpu/drm/selftests/Makefile
 delete mode 100644 drivers/gpu/drm/selftests/drm_buddy_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/drm_cmdline_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/drm_mm_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/drm_modeset_selftests.h
 delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.c
 delete mode 100644 drivers/gpu/drm/selftests/drm_selftest.h
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_buddy.c
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_cmdline_parser.c
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_damage_helper.c
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_format.c
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_modeset_common.c
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_modeset_common.h
 delete mode 100644 drivers/gpu/drm/selftests/test-drm_rect.c
 create mode 100644 drivers/gpu/drm/tests/drm_buddy_test.c
 create mode 100644 

Re: [RFT][PATCH v2 0/9] Update vfio_pin/unpin_pages API

2022-07-08 Thread Eric Farman
On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> This is a preparatory series for IOMMUFD v2 patches. It prepares for
> replacing vfio_iommu_type1 implementations of vfio_pin/unpin_pages()
> with IOMMUFD version.
> 
> There's a gap between these two versions: the vfio_iommu_type1
> version
> inputs a non-contiguous PFN list and outputs another PFN list for the
> pinned physical page list, while the IOMMUFD version only supports a
> contiguous address input by accepting the starting IO virtual address
> of a set of pages to pin and by outputting to a physical page list.
> 
> The nature of existing callers mostly aligns with the IOMMUFD
> version,
> except s390's vfio_ccw_cp code where some additional change is needed
> along with this series. Overall, updating to "iova" and "phys_page"
> does improve the caller side to some extent.
> 
> Also fix a misuse of physical address and virtual address in the
> s390's
> crypto code. And update the input naming at the adjacent
> vfio_dma_rw().
> 
> This is on github:
> https://github.com/nicolinc/iommufd/commits/vfio_pin_pages
> 
> Request for testing: I only did build for s390 and i915 code, so it'd
> be nice to have people who have environment to run sanity
> accordingly.

Tested-by: Eric Farman# s390

> 
> Thanks!
> 
> Changelog
> v2:
>  * Added a patch to make vfio_unpin_pages return void
>  * Added two patches to remove PFN list from two s390 callers
>  * Renamed "phys_page" parameter to "pages" for vfio_pin_pages
>  * Updated commit log of kmap_local_page() patch
>  * Added Harald's "Reviewed-by" to pa_ind patch
>  * Rebased on top of Alex's extern removal path
> v1: 
> https://lore.kernel.org/kvm/20220616235212.15185-1-nicol...@nvidia.com/
> 
> Nicolin Chen (9):
>   vfio: Make vfio_unpin_pages() return void
>   vfio/ap: Pass in physical address of ind to ap_aqic()
>   vfio/ccw: Only pass in contiguous pages
>   vfio: Pass in starting IOVA to vfio_pin/unpin_pages API
>   vfio/ap: Remove redundant pfn
>   vfio/ccw: Change pa_pfn list to pa_iova list
>   vfio: Rename user_iova of vfio_dma_rw()
>   vfio/ccw: Add kmap_local_page() for memcpy
>   vfio: Replace phys_pfn with pages for vfio_pin_pages()
> 
>  .../driver-api/vfio-mediated-device.rst   |   6 +-
>  arch/s390/include/asm/ap.h|   6 +-
>  drivers/gpu/drm/i915/gvt/kvmgt.c  |  46 ++---
>  drivers/s390/cio/vfio_ccw_cp.c| 195 +++-
> --
>  drivers/s390/crypto/ap_queue.c|   2 +-
>  drivers/s390/crypto/vfio_ap_ops.c |  54 +++--
>  drivers/s390/crypto/vfio_ap_private.h |   4 +-
>  drivers/vfio/vfio.c   |  55 +++--
>  drivers/vfio/vfio.h   |   8 +-
>  drivers/vfio/vfio_iommu_type1.c   |  46 +++--
>  include/linux/vfio.h  |   9 +-
>  11 files changed, 218 insertions(+), 213 deletions(-)
> 



Re: [RFT][PATCH v2 9/9] vfio: Replace phys_pfn with pages for vfio_pin_pages()

2022-07-08 Thread Eric Farman
On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> Most of the callers of vfio_pin_pages() want "struct page *" and the
> low-level mm code to pin pages returns a list of "struct page *" too.
> So there's no gain in converting "struct page *" to PFN in between.
> 
> Replace the output parameter "phys_pfn" list with a "pages" list, to
> simplify callers. This also allows us to replace the vfio_iommu_type1
> implementation with a more efficient one.
> 
> For now, also update vfio_iommu_type1 to fit this new parameter too.
> 
> Signed-off-by: Nicolin Chen 
> ---
>  .../driver-api/vfio-mediated-device.rst   |  2 +-
>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 19 ++---
> --
>  drivers/s390/cio/vfio_ccw_cp.c| 19 +--
> 

Acked-by: Eric Farman 

>  drivers/s390/crypto/vfio_ap_ops.c |  6 +++---
>  drivers/vfio/vfio.c   |  8 
>  drivers/vfio/vfio.h   |  2 +-
>  drivers/vfio/vfio_iommu_type1.c   | 19 +++
> 
>  include/linux/vfio.h  |  2 +-
>  8 files changed, 36 insertions(+), 41 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index ea32a0f13ddb..ba5fefcdae1a 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -263,7 +263,7 @@ The following APIs are provided for translating
> user pfn to host pfn in a VFIO
>  driver::
>  
>   int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
> -   int npage, int prot, unsigned long
> *phys_pfn);
> +   int npage, int prot, struct page
> **pages);
>  
>   void vfio_unpin_pages(struct vfio_device *device, dma_addr_t
> iova,
>   int npage);
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index ea6041fa48ac..3a49471dcc16 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -239,7 +239,7 @@ static void gvt_unpin_guest_page(struct
> intel_vgpu *vgpu, unsigned long gfn,
>  static int gvt_pin_guest_page(struct intel_vgpu *vgpu, unsigned long
> gfn,
>   unsigned long size, struct page **page)
>  {
> - unsigned long base_pfn = 0;
> + struct page *base_page = NULL;
>   int total_pages;
>   int npage;
>   int ret;
> @@ -251,26 +251,19 @@ static int gvt_pin_guest_page(struct intel_vgpu
> *vgpu, unsigned long gfn,
>*/
>   for (npage = 0; npage < total_pages; npage++) {
>   dma_addr_t cur_iova = (gfn + npage) << PAGE_SHIFT;
> - unsigned long pfn;
> + struct page *cur_page;
>  
>   ret = vfio_pin_pages(>vfio_device, cur_iova, 1,
> -  IOMMU_READ | IOMMU_WRITE, );
> +  IOMMU_READ | IOMMU_WRITE,
> _page);
>   if (ret != 1) {
>   gvt_vgpu_err("vfio_pin_pages failed for iova
> %pad, ret %d\n",
>_iova, ret);
>   goto err;
>   }
>  
> - if (!pfn_valid(pfn)) {
> - gvt_vgpu_err("pfn 0x%lx is not mem backed\n",
> pfn);
> - npage++;
> - ret = -EFAULT;
> - goto err;
> - }
> -
>   if (npage == 0)
> - base_pfn = pfn;
> - else if (base_pfn + npage != pfn) {
> + base_page = cur_page;
> + else if (base_page + npage != cur_page) {
>   gvt_vgpu_err("The pages are not continuous\n");
>   ret = -EINVAL;
>   npage++;
> @@ -278,7 +271,7 @@ static int gvt_pin_guest_page(struct intel_vgpu
> *vgpu, unsigned long gfn,
>   }
>   }
>  
> - *page = pfn_to_page(base_pfn);
> + *page = base_page;
>   return 0;
>  err:
>   gvt_unpin_guest_page(vgpu, gfn, npage * PAGE_SIZE);
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c
> b/drivers/s390/cio/vfio_ccw_cp.c
> index cd4ec4f6d6ff..8963f452f963 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -22,8 +22,8 @@
>  struct page_array {
>   /* Array that stores pages need to pin. */
>   dma_addr_t  *pa_iova;
> - /* Array that receives PFNs of the pages pinned. */
> - unsigned long   *pa_pfn;
> + /* Array that receives the pinned pages. */
> + struct page **pa_page;
>   /* Number of pages pinned from @pa_iova. */
>   int pa_nr;
>  };
> @@ -68,19 +68,19 @@ static int page_array_alloc(struct page_array
> *pa, u64 iova, unsigned int len)
>   return -EINVAL;
>  
>   pa->pa_iova = kcalloc(pa->pa_nr,
> -

Re: [RFT][PATCH v2 8/9] vfio/ccw: Add kmap_local_page() for memcpy

2022-07-08 Thread Eric Farman
On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> A PFN is not secure enough to promise that the memory is not IO. And
> direct access via memcpy() that only handles CPU memory will crash on
> S390 if the PFN is an IO PFN, as we have to use the
> memcpy_to/fromio()
> that uses the special S390 IO access instructions. On the other hand,
> a "struct page *" is always a CPU coherent thing that fits memcpy().
> 
> Also, casting a PFN to "void *" for memcpy() is not a proper
> practice,
> kmap_local_page() is the correct API to call here, though S390
> doesn't
> use highmem, which means kmap_local_page() is a NOP.
> 
> There's a following patch changing the vfio_pin_pages() API to return
> a list of "struct page *" instead of PFNs. It will block any IO
> memory
> from ever getting into this call path, for such a security purpose.
> In
> this patch, add kmap_local_page() to prepare for that.

This all sounds like it's conflating vfio-ccw with vfio-pci, and
configuration-wise I have a hard time picturing the situation described
above. But in the interest of the change in the next patch, I suppose
it's fine.

Acked-by: Eric Farman 

> 
> Suggested-by: Jason Gunthorpe 
> Signed-off-by: Nicolin Chen 
> ---
>  drivers/s390/cio/vfio_ccw_cp.c | 9 ++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c
> b/drivers/s390/cio/vfio_ccw_cp.c
> index 3854c3d573f5..cd4ec4f6d6ff 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -11,6 +11,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -230,7 +231,6 @@ static long copy_from_iova(struct vfio_device
> *vdev, void *to, u64 iova,
>  unsigned long n)
>  {
>   struct page_array pa = {0};
> - u64 from;
>   int i, ret;
>   unsigned long l, m;
>  
> @@ -246,7 +246,9 @@ static long copy_from_iova(struct vfio_device
> *vdev, void *to, u64 iova,
>  
>   l = n;
>   for (i = 0; i < pa.pa_nr; i++) {
> - from = pa.pa_pfn[i] << PAGE_SHIFT;
> + struct page *page = pfn_to_page(pa.pa_pfn[i]);
> + void *from = kmap_local_page(page);
> +
>   m = PAGE_SIZE;
>   if (i == 0) {
>   from += iova & (PAGE_SIZE - 1);
> @@ -254,7 +256,8 @@ static long copy_from_iova(struct vfio_device
> *vdev, void *to, u64 iova,
>   }
>  
>   m = min(l, m);
> - memcpy(to + (n - l), (void *)from, m);
> + memcpy(to + (n - l), from, m);
> + kunmap_local(from);
>  
>   l -= m;
>   if (l == 0)



Re: [RFT][PATCH v2 4/9] vfio: Pass in starting IOVA to vfio_pin/unpin_pages API

2022-07-08 Thread Eric Farman
On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> The vfio_pin/unpin_pages() so far accepted arrays of PFNs of user
> IOVA.
> Among all three callers, there was only one caller possibly passing
> in
> a non-contiguous PFN list, which is now ensured to have contiguous
> PFN
> inputs too.
> 
> Pass in the starting address with "iova" alone to simplify things, so
> callers no longer need to maintain a PFN list or to pin/unpin one
> page
> at a time. This also allows VFIO to use more efficient
> implementations
> of pin/unpin_pages.
> 
> For now, also update vfio_iommu_type1 to fit this new parameter too,
> while keeping its input intact (being user_iova) since we don't want
> to spend too much effort swapping its parameters and local variables
> at that level.
> 
> Signed-off-by: Nicolin Chen 
> ---
>  .../driver-api/vfio-mediated-device.rst   |  4 +--
>  drivers/gpu/drm/i915/gvt/kvmgt.c  | 24 ++---
>  drivers/s390/cio/vfio_ccw_cp.c|  4 +--

Acked-by: Eric Farman 

>  drivers/s390/crypto/vfio_ap_ops.c |  9 +++
>  drivers/vfio/vfio.c   | 27 +--
> 
>  drivers/vfio/vfio.h   |  4 +--
>  drivers/vfio/vfio_iommu_type1.c   | 17 ++--
>  include/linux/vfio.h  |  5 ++--
>  8 files changed, 40 insertions(+), 54 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index b0fdf76b339a..ea32a0f13ddb 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -262,10 +262,10 @@ Translation APIs for Mediated Devices
>  The following APIs are provided for translating user pfn to host pfn
> in a VFIO
>  driver::
>  
> - int vfio_pin_pages(struct vfio_device *device, unsigned long
> *user_pfn,
> + int vfio_pin_pages(struct vfio_device *device, dma_addr_t iova,
> int npage, int prot, unsigned long
> *phys_pfn);
>  
> - void vfio_unpin_pages(struct vfio_device *device, unsigned long
> *user_pfn,
> + void vfio_unpin_pages(struct vfio_device *device, dma_addr_t
> iova,
>   int npage);
>  
>  These functions call back into the back-end IOMMU module by using
> the pin_pages
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 8c67c9aba82d..ea6041fa48ac 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -231,16 +231,8 @@ static void
> intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
>  static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned
> long gfn,
>   unsigned long size)
>  {
> - int total_pages;
> - int npage;
> -
> - total_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
> -
> - for (npage = 0; npage < total_pages; npage++) {
> - unsigned long cur_gfn = gfn + npage;
> -
> - vfio_unpin_pages(>vfio_device, _gfn, 1);
> - }
> + vfio_unpin_pages(>vfio_device, gfn << PAGE_SHIFT,
> +  roundup(size, PAGE_SIZE) / PAGE_SIZE);
>  }
>  
>  /* Pin a normal or compound guest page for dma. */
> @@ -258,14 +250,14 @@ static int gvt_pin_guest_page(struct intel_vgpu
> *vgpu, unsigned long gfn,
>* on stack to hold pfns.
>*/
>   for (npage = 0; npage < total_pages; npage++) {
> - unsigned long cur_gfn = gfn + npage;
> + dma_addr_t cur_iova = (gfn + npage) << PAGE_SHIFT;
>   unsigned long pfn;
>  
> - ret = vfio_pin_pages(>vfio_device, _gfn, 1,
> + ret = vfio_pin_pages(>vfio_device, cur_iova, 1,
>IOMMU_READ | IOMMU_WRITE, );
>   if (ret != 1) {
> - gvt_vgpu_err("vfio_pin_pages failed for gfn
> 0x%lx, ret %d\n",
> -  cur_gfn, ret);
> + gvt_vgpu_err("vfio_pin_pages failed for iova
> %pad, ret %d\n",
> +  _iova, ret);
>   goto err;
>   }
>  
> @@ -309,7 +301,7 @@ static int gvt_dma_map_page(struct intel_vgpu
> *vgpu, unsigned long gfn,
>   if (dma_mapping_error(dev, *dma_addr)) {
>   gvt_vgpu_err("DMA mapping failed for pfn 0x%lx, ret
> %d\n",
>page_to_pfn(page), ret);
> - gvt_unpin_guest_page(vgpu, gfn, size);
> + gvt_unpin_guest_page(vgpu, gfn << PAGE_SHIFT, size);
>   return -ENOMEM;
>   }
>  
> @@ -322,7 +314,7 @@ static void gvt_dma_unmap_page(struct intel_vgpu
> *vgpu, unsigned long gfn,
>   struct device *dev = vgpu->gvt->gt->i915->drm.dev;
>  
>   dma_unmap_page(dev, dma_addr, size, DMA_BIDIRECTIONAL);
> - gvt_unpin_guest_page(vgpu, gfn, size);
> + gvt_unpin_guest_page(vgpu, gfn << PAGE_SHIFT, size);
>  }
>  
> 

Re: [RFT][PATCH v2 6/9] vfio/ccw: Change pa_pfn list to pa_iova list

2022-07-08 Thread Eric Farman
On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> The vfio_ccw_cp code maintains both iova and its PFN list because the
> vfio_pin/unpin_pages API wanted pfn list. Since
> vfio_pin/unpin_pages()
> now accept "iova", change to maintain only pa_iova list and rename
> all
> "pfn_array" strings to "page_array", so as to simplify the code.
> 
> Signed-off-by: Nicolin Chen 

Reviewed-by: Eric Farman 

> ---
>  drivers/s390/cio/vfio_ccw_cp.c | 135 ---
> --
>  1 file changed, 64 insertions(+), 71 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c
> b/drivers/s390/cio/vfio_ccw_cp.c
> index a739262f988d..3854c3d573f5 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -18,11 +18,9 @@
>  #include "vfio_ccw_cp.h"
>  #include "vfio_ccw_private.h"
>  
> -struct pfn_array {
> - /* Starting guest physical I/O address. */
> - unsigned long   pa_iova;
> - /* Array that stores PFNs of the pages need to pin. */
> - unsigned long   *pa_iova_pfn;
> +struct page_array {
> + /* Array that stores pages need to pin. */
> + dma_addr_t  *pa_iova;
>   /* Array that receives PFNs of the pages pinned. */
>   unsigned long   *pa_pfn;
>   /* Number of pages pinned from @pa_iova. */
> @@ -37,53 +35,50 @@ struct ccwchain {
>   /* Count of the valid ccws in chain. */
>   int ch_len;
>   /* Pinned PAGEs for the original data. */
> - struct pfn_array*ch_pa;
> + struct page_array   *ch_pa;
>  };
>  
>  /*
> - * pfn_array_alloc() - alloc memory for PFNs
> - * @pa: pfn_array on which to perform the operation
> + * page_array_alloc() - alloc memory for page array
> + * @pa: page_array on which to perform the operation
>   * @iova: target guest physical address
>   * @len: number of bytes that should be pinned from @iova
>   *
> - * Attempt to allocate memory for PFNs.
> + * Attempt to allocate memory for page array.
>   *
> - * Usage of pfn_array:
> - * We expect (pa_nr == 0) and (pa_iova_pfn == NULL), any field in
> + * Usage of page_array:
> + * We expect (pa_nr == 0) and (pa_iova == NULL), any field in
>   * this structure will be filled in by this function.
>   *
>   * Returns:
> - * 0 if PFNs are allocated
> - *   -EINVAL if pa->pa_nr is not initially zero, or pa->pa_iova_pfn
> is not NULL
> + * 0 if page array is allocated
> + *   -EINVAL if pa->pa_nr is not initially zero, or pa->pa_iova is
> not NULL
>   *   -ENOMEM if alloc failed
>   */
> -static int pfn_array_alloc(struct pfn_array *pa, u64 iova, unsigned
> int len)
> +static int page_array_alloc(struct page_array *pa, u64 iova,
> unsigned int len)
>  {
>   int i;
>  
> - if (pa->pa_nr || pa->pa_iova_pfn)
> + if (pa->pa_nr || pa->pa_iova)
>   return -EINVAL;
>  
> - pa->pa_iova = iova;
> -
>   pa->pa_nr = ((iova & ~PAGE_MASK) + len + (PAGE_SIZE - 1)) >>
> PAGE_SHIFT;
>   if (!pa->pa_nr)
>   return -EINVAL;
>  
> - pa->pa_iova_pfn = kcalloc(pa->pa_nr,
> -   sizeof(*pa->pa_iova_pfn) +
> -   sizeof(*pa->pa_pfn),
> -   GFP_KERNEL);
> - if (unlikely(!pa->pa_iova_pfn)) {
> + pa->pa_iova = kcalloc(pa->pa_nr,
> +   sizeof(*pa->pa_iova) + sizeof(*pa-
> >pa_pfn),
> +   GFP_KERNEL);
> + if (unlikely(!pa->pa_iova)) {
>   pa->pa_nr = 0;
>   return -ENOMEM;
>   }
> - pa->pa_pfn = pa->pa_iova_pfn + pa->pa_nr;
> + pa->pa_pfn = (unsigned long *)>pa_iova[pa->pa_nr];
>  
> - pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
> + pa->pa_iova[0] = iova;
>   pa->pa_pfn[0] = -1ULL;
>   for (i = 1; i < pa->pa_nr; i++) {
> - pa->pa_iova_pfn[i] = pa->pa_iova_pfn[i - 1] + 1;
> + pa->pa_iova[i] = pa->pa_iova[i - 1] + PAGE_SIZE;
>   pa->pa_pfn[i] = -1ULL;
>   }
>  
> @@ -91,30 +86,30 @@ static int pfn_array_alloc(struct pfn_array *pa,
> u64 iova, unsigned int len)
>  }
>  
>  /*
> - * pfn_array_unpin() - Unpin user pages in memory
> - * @pa: pfn_array on which to perform the operation
> + * page_array_unpin() - Unpin user pages in memory
> + * @pa: page_array on which to perform the operation
>   * @vdev: the vfio device to perform the operation
>   * @pa_nr: number of user pages to unpin
>   *
>   * Only unpin if any pages were pinned to begin with, i.e. pa_nr >
> 0,
>   * otherwise only clear pa->pa_nr
>   */
> -static void pfn_array_unpin(struct pfn_array *pa,
> - struct vfio_device *vdev, int pa_nr)
> +static void page_array_unpin(struct page_array *pa,
> +  struct vfio_device *vdev, int pa_nr)
>  {
>   int unpinned = 0, npage = 1;
>  
>   while (unpinned < pa_nr) {
> - unsigned long *first = >pa_iova_pfn[unpinned];
> - unsigned 

Re: [RFT][PATCH v2 3/9] vfio/ccw: Only pass in contiguous pages

2022-07-08 Thread Eric Farman
On Wed, 2022-07-06 at 14:05 -0300, Jason Gunthorpe wrote:
> On Tue, Jul 05, 2022 at 11:27:53PM -0700, Nicolin Chen wrote:
> > This driver is the only caller of vfio_pin/unpin_pages that might
> > pass
> > in a non-contiguous PFN list, but in many cases it has a contiguous
> > PFN
> > list to process. So letting VFIO API handle a non-contiguous PFN
> > list
> > is actually counterproductive.
> > 
> > Add a pair of simple loops to pass in contiguous PFNs only, to have
> > an
> > efficient implementation in VFIO.
> > 
> > Signed-off-by: Nicolin Chen 
> > ---
> >  drivers/s390/cio/vfio_ccw_cp.c | 70 +++---
> > 
> >  1 file changed, 56 insertions(+), 14 deletions(-)
> 
> I think this is fine as-is for this series, but someone who knows and
> can test ccw should go in and fix things so that pfn_array_alloc()
> doesn't exist. Allocating memory and filling it with consecutive
> integers is kind of silly given we can just call vfio_pin_pages()
> with
> pa_nr directly.
> 
>   pa->pa_iova_pfn[0] = pa->pa_iova >> PAGE_SHIFT;
>   pa->pa_pfn[0] = -1ULL;
>   for (i = 1; i < pa->pa_nr; i++) {
>   pa->pa_iova_pfn[i] = pa->pa_iova_pfn[i - 1] + 1;
> 
> It looks like only the 'ccw_is_idal' flow can actually create
> non-continuities.

This code is certainly not my favorite, but you're right that it's the
IDAL flow that generates the non-contiguous requests and the code you
reference is simply an initialization for the !IDAL case. As I have a
todo in this code anyway, I'll register your suggestion to see if they
can be untangled.

>  Also the loop in copy_from_iova() should ideally be
> using the much faster 'rw' interface, and not a pin/unpin cycle just
> to memcpy.

I guess I missed when that was added. This looks like low hanging fruit
for some old code regardless of the above. Will get to this once
I'm back. Thank you!

Eric

> 
> If I guess right these changes would significantly speed this driver
> up.
> 
> Anyhow,
> 
> Reviewed-by: Jason Gunthorpe 
> 
> Jason



Re: [RFT][PATCH v2 3/9] vfio/ccw: Only pass in contiguous pages

2022-07-08 Thread Eric Farman
On Tue, 2022-07-05 at 23:27 -0700, Nicolin Chen wrote:
> This driver is the only caller of vfio_pin/unpin_pages that might
> pass
> in a non-contiguous PFN list, but in many cases it has a contiguous
> PFN
> list to process. So letting VFIO API handle a non-contiguous PFN list
> is actually counterproductive.
> 
> Add a pair of simple loops to pass in contiguous PFNs only, to have
> an
> efficient implementation in VFIO.
> 
> Signed-off-by: Nicolin Chen 

Reviewed-by: Eric Farman 

> ---
>  drivers/s390/cio/vfio_ccw_cp.c | 70 +++-
> --
>  1 file changed, 56 insertions(+), 14 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_cp.c
> b/drivers/s390/cio/vfio_ccw_cp.c
> index 0c2be9421ab7..3b94863ad24e 100644
> --- a/drivers/s390/cio/vfio_ccw_cp.c
> +++ b/drivers/s390/cio/vfio_ccw_cp.c
> @@ -90,6 +90,38 @@ static int pfn_array_alloc(struct pfn_array *pa,
> u64 iova, unsigned int len)
>   return 0;
>  }
>  
> +/*
> + * pfn_array_unpin() - Unpin user pages in memory
> + * @pa: pfn_array on which to perform the operation
> + * @vdev: the vfio device to perform the operation
> + * @pa_nr: number of user pages to unpin
> + *
> + * Only unpin if any pages were pinned to begin with, i.e. pa_nr >
> 0,
> + * otherwise only clear pa->pa_nr
> + */
> +static void pfn_array_unpin(struct pfn_array *pa,
> + struct vfio_device *vdev, int pa_nr)
> +{
> + int unpinned = 0, npage = 1;
> +
> + while (unpinned < pa_nr) {
> + unsigned long *first = >pa_iova_pfn[unpinned];
> + unsigned long *last = [npage];
> +
> + if (unpinned + npage < pa_nr &&
> + *first + npage == *last) {
> + npage++;
> + continue;
> + }
> +
> + vfio_unpin_pages(vdev, first, npage);
> + unpinned += npage;
> + npage = 1;
> + }
> +
> + pa->pa_nr = 0;
> +}
> +
>  /*
>   * pfn_array_pin() - Pin user pages in memory
>   * @pa: pfn_array on which to perform the operation
> @@ -101,34 +133,44 @@ static int pfn_array_alloc(struct pfn_array
> *pa, u64 iova, unsigned int len)
>   */
>  static int pfn_array_pin(struct pfn_array *pa, struct vfio_device
> *vdev)
>  {
> + int pinned = 0, npage = 1;
>   int ret = 0;
>  
> - ret = vfio_pin_pages(vdev, pa->pa_iova_pfn, pa->pa_nr,
> -  IOMMU_READ | IOMMU_WRITE, pa->pa_pfn);
> + while (pinned < pa->pa_nr) {
> + unsigned long *first = >pa_iova_pfn[pinned];
> + unsigned long *last = [npage];
>  
> - if (ret < 0) {
> - goto err_out;
> - } else if (ret > 0 && ret != pa->pa_nr) {
> - vfio_unpin_pages(vdev, pa->pa_iova_pfn, ret);
> - ret = -EINVAL;
> - goto err_out;
> + if (pinned + npage < pa->pa_nr &&
> + *first + npage == *last) {
> + npage++;
> + continue;
> + }
> +
> + ret = vfio_pin_pages(vdev, first, npage,
> +  IOMMU_READ | IOMMU_WRITE,
> +  >pa_pfn[pinned]);
> + if (ret < 0) {
> + goto err_out;
> + } else if (ret > 0 && ret != npage) {
> + pinned += ret;
> + ret = -EINVAL;
> + goto err_out;
> + }
> + pinned += npage;
> + npage = 1;
>   }
>  
>   return ret;
>  
>  err_out:
> - pa->pa_nr = 0;
> -
> + pfn_array_unpin(pa, vdev, pinned);
>   return ret;
>  }
>  
>  /* Unpin the pages before releasing the memory. */
>  static void pfn_array_unpin_free(struct pfn_array *pa, struct
> vfio_device *vdev)
>  {
> - /* Only unpin if any pages were pinned to begin with */
> - if (pa->pa_nr)
> - vfio_unpin_pages(vdev, pa->pa_iova_pfn, pa->pa_nr);
> - pa->pa_nr = 0;
> + pfn_array_unpin(pa, vdev, pa->pa_nr);
>   kfree(pa->pa_iova_pfn);
>  }
>  



Re: [RFT][PATCH v2 0/9] Update vfio_pin/unpin_pages API

2022-07-08 Thread Nicolin Chen
On Fri, Jul 08, 2022 at 07:24:30AM +, Xu, Terrence wrote:
> External email: Use caution opening links or attachments
> 
> 
> > -Original Message-
> > From: intel-gvt-dev  On Behalf 
> > Of
> > On Thu, Jul 07, 2022 at 06:08:45AM +, Tian, Kevin wrote:
> >
> > > > Request for testing: I only did build for s390 and i915 code, so
> > > > it'd be nice to have people who have environment to run sanity 
> > > > accordingly.
> > > >
> > >
> > > +Terrence who is testing it for i915 now...
> >
> > Hi Terrence, would it be possible for you to pull v3 to test on?
> > https://github.com/nicolinc/iommufd/commits/dev/vfio_pin_pages-v3
> >
> > They are basically same but there's a new DIV_ROUND_UP change, which
> > shouldn't result in any functional difference, IMHO. If
> > v3 passes, I can simply add your Tested-by when I respin it.
> 
> Hi Nicolin, I already completed KVMGT key feature testing based on
> your v3 repo, VM booted up successfully and run smoothly, but there
> is a call trace during each time VM booting up, as the attachment.

Nice! Thank you for the testing. I will add your Tested-by in v3.


Re: [PATCH 2/5] drm/modes: Extract drm_mode_parse_cmdline_named_mode()

2022-07-08 Thread Geert Uytterhoeven
Hi Hans,

On Fri, Jul 8, 2022 at 9:46 PM Hans de Goede  wrote:
> On 7/8/22 20:21, Geert Uytterhoeven wrote:
> > Extract the code to check for a named mode parameter into its own
> > function, to streamline the main parsing flow.
> >
> > Signed-off-by: Geert Uytterhoeven 

> > --- a/drivers/gpu/drm/drm_modes.c
> > +++ b/drivers/gpu/drm/drm_modes.c
> > @@ -1749,6 +1749,30 @@ static const char * const 
> > drm_named_modes_whitelist[] = {
> >   "PAL",
> >  };
> >
> > +static int drm_mode_parse_cmdline_named_mode(const char *name,
> > +  unsigned int length,
> > +  bool refresh,
> > +  struct drm_cmdline_mode *mode)
> > +{
> > + unsigned int i;
> > + int ret;
> > +
> > + for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> > + ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> > + if (!ret)
>
> As discussed in my review of 1/5 this needs to become:
>
> if (ret != length)
> > + continue;

Agreed.

> Which renders my other comment on this patch (length not being used) mute.

/me wonders if he would have seen the light earlier if gcc would have
warned about that...

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH 1/5] drm/modes: parse_cmdline: Handle empty mode name part

2022-07-08 Thread Geert Uytterhoeven
Hi Hans,

On Fri, Jul 8, 2022 at 10:06 PM Geert Uytterhoeven  wrote:
> On Fri, Jul 8, 2022 at 9:28 PM Hans de Goede  wrote:
> > On 7/8/22 20:21, Geert Uytterhoeven wrote:
> > > If no mode name part was specified, mode_end is zero, and the "ret ==
> > > mode_end" check does the wrong thing.
> > >
> > > Fix this by checking for a non-zero return value instead.
> >
> > Which is wrong to do, since now if you have e.g. a mode list
> > with:
> >
> > "dblntsc",
> > "dblntsc-ff"
> >
> > in there and the cmdline contains "dblntsc-ff" then you
> > will already stop with a (wrong!) match at "dblntsc".
>
> It indeed behaves that way, and did so before, as str_has_prefix()
> checks for a matching prefix, and thus may never get to the full
> match.  However, can we change that to an exact match, without
> introducing regressions?
> This can be avoided by reverse-sorting the modelist (or iterating
> backwards through a sorted modelist), though.
>
> > > While at it, skip all named mode handling when mode_end is zero, as it
> > > is futile.
> >
> > AFAICT, this is actually what needs to be done to fix this, while keeping
> > the ret == mode_end check.
>
> "ret == mode_end" or "ret" doesn't matter (except for the special
> case of mode_end is zero), as str_has_prefix() returns either zero or
> the length of the prefix.  Hence it never returns a non-zero value
> smaller than the length of the prefix.

Ignore that.  I finally saw what's really happening.
And I do agree with your comment.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH 1/5] drm/modes: parse_cmdline: Handle empty mode name part

2022-07-08 Thread Geert Uytterhoeven
Hi Hans.

On Fri, Jul 8, 2022 at 9:28 PM Hans de Goede  wrote:
> On 7/8/22 20:21, Geert Uytterhoeven wrote:
> > If no mode name part was specified, mode_end is zero, and the "ret ==
> > mode_end" check does the wrong thing.
> >
> > Fix this by checking for a non-zero return value instead.
>
> Which is wrong to do, since now if you have e.g. a mode list
> with:
>
> "dblntsc",
> "dblntsc-ff"
>
> in there and the cmdline contains "dblntsc-ff" then you
> will already stop with a (wrong!) match at "dblntsc".

It indeed behaves that way, and did so before, as str_has_prefix()
checks for a matching prefix, and thus may never get to the full
match.  However, can we change that to an exact match, without
introducing regressions?
This can be avoided by reverse-sorting the modelist (or iterating
backwards through a sorted modelist), though.

> > While at it, skip all named mode handling when mode_end is zero, as it
> > is futile.
>
> AFAICT, this is actually what needs to be done to fix this, while keeping
> the ret == mode_end check.

"ret == mode_end" or "ret" doesn't matter (except for the special
case of mode_end is zero), as str_has_prefix() returns either zero or
the length of the prefix.  Hence it never returns a non-zero value
smaller than the length of the prefix.

> > Fixes: 7b1cce760afe38b4 ("drm/modes: parse_cmdline: Allow specifying 
> > stand-alone options")
> > Signed-off-by: Geert Uytterhoeven 
> > ---
> >  drivers/gpu/drm/drm_modes.c | 4 ++--
> >  1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> > index 14b746f7ba975954..30a7be97707bfb16 100644
> > --- a/drivers/gpu/drm/drm_modes.c
> > +++ b/drivers/gpu/drm/drm_modes.c
> > @@ -1823,9 +1823,9 @@ bool drm_mode_parse_command_line_for_connector(const 
> > char *mode_option,
> >   }
> >
> >   /* First check for a named mode */
> > - for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> > + for (i = 0; mode_end && i < ARRAY_SIZE(drm_named_modes_whitelist); 
> > i++) {
> >   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> > - if (ret == mode_end) {
> > + if (ret) {
> >   if (refresh_ptr)
> >   return false; /* named + refresh is invalid */

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


Re: [PATCH 1/9] dt-bindings: msm/dp: drop extra p1 region

2022-07-08 Thread Abhinav Kumar




On 7/8/2022 12:51 PM, Stephen Boyd wrote:

Quoting Abhinav Kumar (2022-07-08 12:38:09)

+ kuogee

On 7/8/2022 12:27 PM, Stephen Boyd wrote:


Yes I see the same address for P1 on sc7280. Maybe it's a typo? Abhinav,
can you confirm?


P1 block does exist on sc7280 and yes its address is same as the address
mentioned in sc7180. So its not a typo.


Thanks!



Yes, we are not programming this today but I would prefer to keep this
as optional.

I did sync up with Kuogee on this change this morning, we will check a
few things internally on the P1 block's usage as to which use-cases we
need to program it for and update here.

The idea behind having this register space listed in the yaml is thats
how the software documents have the blocks listed so dropping P1 block
just because its unused seemed wrong to me. Optional seems more appropriate.



It doesn't sound optional on sc7180 or sc7280. It exists in the
hardware, so we should list the reg property. My understanding of
optional properties is for the case where something could be different
in the hardware design, like an optionally connected pin on a device.


Ack, if thats the purpose of optional, then we should keep it and yes 
lets drop this change.


Re: [PATCH 1/9] dt-bindings: msm/dp: drop extra p1 region

2022-07-08 Thread Stephen Boyd
Quoting Abhinav Kumar (2022-07-08 12:38:09)
> + kuogee
>
> On 7/8/2022 12:27 PM, Stephen Boyd wrote:
> >
> > Yes I see the same address for P1 on sc7280. Maybe it's a typo? Abhinav,
> > can you confirm?
>
> P1 block does exist on sc7280 and yes its address is same as the address
> mentioned in sc7180. So its not a typo.

Thanks!

>
> Yes, we are not programming this today but I would prefer to keep this
> as optional.
>
> I did sync up with Kuogee on this change this morning, we will check a
> few things internally on the P1 block's usage as to which use-cases we
> need to program it for and update here.
>
> The idea behind having this register space listed in the yaml is thats
> how the software documents have the blocks listed so dropping P1 block
> just because its unused seemed wrong to me. Optional seems more appropriate.
>

It doesn't sound optional on sc7180 or sc7280. It exists in the
hardware, so we should list the reg property. My understanding of
optional properties is for the case where something could be different
in the hardware design, like an optionally connected pin on a device.


Re: [PATCH 1/9] dt-bindings: msm/dp: drop extra p1 region

2022-07-08 Thread Kuogee Hsieh



On 7/8/2022 12:38 PM, Abhinav Kumar wrote:

+ kuogee

On 7/8/2022 12:27 PM, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-07-07 20:46:43)

On 08/07/2022 04:28, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-07-07 14:31:56)

The p1 region was probably added by mistake, none of the DTS files
provides one (and the driver source code also doesn't use one). 
Drop it

now.


Yes, looks like the driver doesn't use it.



Fixes: 687825c402f1 ("dt-bindings: msm/dp: Change reg definition")
Signed-off-by: Dmitry Baryshkov 
---
Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 
1 -

   1 file changed, 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml 
b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml

index 94bc6e1b6451..d6bbe58ef9e8 100644
--- 
a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ 
b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml

@@ -29,7 +29,6 @@ properties:
 - description: aux register block
 - description: link register block
 - description: p0 register block
-  - description: p1 register block


The p1 registers exist on sc7180. They start where the example starts,
at 0xae91400.


Do they exist on e.g. sc7280? In other words, should we add the region
to the DTS? For now I'm going to mark it as optional.



Yes I see the same address for P1 on sc7280. Maybe it's a typo? Abhinav,
can you confirm?


P1 block does exist on sc7280 and yes its address is same as the 
address mentioned in sc7180. So its not a typo.


Yes, we are not programming this today but I would prefer to keep this 
as optional.


I did sync up with Kuogee on this change this morning, we will check a 
few things internally on the P1 block's usage as to which use-cases we 
need to program it for and update here.


P1 block is for dp MST application.  This allow two dp streams can be 
mux into same DP phy.


We should keep it since we may support MST later.

The idea behind having this register space listed in the yaml is thats 
how the software documents have the blocks listed so dropping P1 block 
just because its unused seemed wrong to me. Optional seems more 
appropriate.


Thanks

Abhinav


Re: [PATCH 2/5] drm/modes: Extract drm_mode_parse_cmdline_named_mode()

2022-07-08 Thread Hans de Goede
Hi,

On 7/8/22 20:21, Geert Uytterhoeven wrote:
> Extract the code to check for a named mode parameter into its own
> function, to streamline the main parsing flow.
> 
> Signed-off-by: Geert Uytterhoeven 
> ---
>  drivers/gpu/drm/drm_modes.c | 41 +++--
>  1 file changed, 30 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 30a7be97707bfb16..434383469e9d984d 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1749,6 +1749,30 @@ static const char * const drm_named_modes_whitelist[] 
> = {
>   "PAL",
>  };
>  
> +static int drm_mode_parse_cmdline_named_mode(const char *name,
> +  unsigned int length,
> +  bool refresh,
> +  struct drm_cmdline_mode *mode)
> +{
> + unsigned int i;
> + int ret;
> +
> + for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> + ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> + if (!ret)

As discussed in my review of 1/5 this needs to become:

if (ret != length)
> + continue;

Which renders my other comment on this patch (length not being used) mute.

Regards,

Hans

> +
> + if (refresh)
> + return -EINVAL; /* named + refresh is invalid */
> +
> + strcpy(mode->name, drm_named_modes_whitelist[i]);
> + mode->specified = true;
> + return 0;
> + }
> +
> + return 0;
> +}
> +
>  /**
>   * drm_mode_parse_command_line_for_connector - parse command line modeline 
> for connector
>   * @mode_option: optional per connector mode option
> @@ -1785,7 +1809,7 @@ bool drm_mode_parse_command_line_for_connector(const 
> char *mode_option,
>   const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
>   const char *options_ptr = NULL;
>   char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
> - int i, len, ret;
> + int len, ret;
>  
>   memset(mode, 0, sizeof(*mode));
>   mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
> @@ -1823,16 +1847,11 @@ bool drm_mode_parse_command_line_for_connector(const 
> char *mode_option,
>   }
>  
>   /* First check for a named mode */
> - for (i = 0; mode_end && i < ARRAY_SIZE(drm_named_modes_whitelist); i++) 
> {
> - ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> - if (ret) {
> - if (refresh_ptr)
> - return false; /* named + refresh is invalid */
> -
> - strcpy(mode->name, drm_named_modes_whitelist[i]);
> - mode->specified = true;
> - break;
> - }
> + if (mode_end) {
> + ret = drm_mode_parse_cmdline_named_mode(name, mode_end,
> + refresh_ptr, mode);
> + if (ret)
> + return false;
>   }
>  
>   /* No named mode? Check for a normal mode argument, e.g. 1024x768 */



Re: [PATCH] drm/msm/dsi: Set panel orientation when directly connected

2022-07-08 Thread Abhinav Kumar




On 7/8/2022 9:00 AM, Abhinav Kumar wrote:



On 7/8/2022 8:25 AM, Doug Anderson wrote:

Hi,

On Wed, Jul 6, 2022 at 12:14 PM Stephen Boyd  wrote:


Set the panel orientation in drm when the panel is directly connected,
i.e. we're not using an external bridge. The external bridge case is
already handled by the panel bridge code, so we only update the path we
take when the panel is directly connected/internal. This silences a
warning splat coming from __drm_mode_object_add() on Wormdingler boards.

Cc: Hsin-Yi Wang 
Cc: Douglas Anderson 
Signed-off-by: Stephen Boyd 
---

This relies on commit 5e41b01a7808 ("drm/panel: Add an API to allow drm
to set orientation from panel") which is in drm-misc

  drivers/gpu/drm/msm/dsi/dsi_manager.c | 2 ++
  1 file changed, 2 insertions(+)


I don't personally have objections to this, but (to my understanding)
"the future" is that everyone should use panel_bridge. If we made the
move to panel_bridge today then we wouldn't need to do this. In
general I think panel_bridge would end up letting us delete a bunch of
code...

See commit 4e5763f03e10 ("drm/bridge: ti-sn65dsi86: Wrap panel with
panel-bridge") for when this was done by ti-sn65dsi86.

Then again, I spent a small amount of time looking into this and it's
definitely non-trivial. Still likely worthwhile, but not worth
blocking a tiny fix like this. It also should be fairly obvious that
we should delete this when we switch to panel_bridge.


Right, from what I saw on IRC, panel_bridge is the way forward and 
dmitry did push a change to do that


https://patchwork.freedesktop.org/patch/492585/

But I think we can go ahead with this change because its simple enough.

Regarding the panel_bridge migration, I am going to start reviewing that 
as well.




I did some more digging up on the panel_bridge migration.

Dmitry has posted this towards december last year

https://patches.linaro.org/project/dri-devel/patch/20211207222901.988484-3-dmitry.barysh...@linaro.org/ 



and I had given my R-b on this already in Jan.

I am not sure why this change was dropped OR was not part of msm-next 
already.


Dmitry, any reason this change was left out so long and why the R-b was 
not retained and this was reposted?


From what i can see the change looks identical.

Thanks

Abhinav


Thus:

Reviewed-by: Douglas Anderson 

I'll assume that we'll just snooze this commit until drm-misc-next
merges into a tree that msm-next is based on, which will probably be
the next -rc1. If desired and Acked I could land this in
drm-misc-next, but it's probably not worth it?


Re: [PATCH 1/9] dt-bindings: msm/dp: drop extra p1 region

2022-07-08 Thread Abhinav Kumar

+ kuogee

On 7/8/2022 12:27 PM, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-07-07 20:46:43)

On 08/07/2022 04:28, Stephen Boyd wrote:

Quoting Dmitry Baryshkov (2022-07-07 14:31:56)

The p1 region was probably added by mistake, none of the DTS files
provides one (and the driver source code also doesn't use one). Drop it
now.


Yes, looks like the driver doesn't use it.



Fixes: 687825c402f1 ("dt-bindings: msm/dp: Change reg definition")
Signed-off-by: Dmitry Baryshkov 
---
   Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 -
   1 file changed, 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml 
b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index 94bc6e1b6451..d6bbe58ef9e8 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -29,7 +29,6 @@ properties:
 - description: aux register block
 - description: link register block
 - description: p0 register block
-  - description: p1 register block


The p1 registers exist on sc7180. They start where the example starts,
at 0xae91400.


Do they exist on e.g. sc7280? In other words, should we add the region
to the DTS? For now I'm going to mark it as optional.



Yes I see the same address for P1 on sc7280. Maybe it's a typo? Abhinav,
can you confirm?


P1 block does exist on sc7280 and yes its address is same as the address 
mentioned in sc7180. So its not a typo.


Yes, we are not programming this today but I would prefer to keep this 
as optional.


I did sync up with Kuogee on this change this morning, we will check a 
few things internally on the P1 block's usage as to which use-cases we 
need to program it for and update here.


The idea behind having this register space listed in the yaml is thats 
how the software documents have the blocks listed so dropping P1 block 
just because its unused seemed wrong to me. Optional seems more appropriate.


Thanks

Abhinav


[PATCH] drm/vc4: Use the bitmap API to allocate bitmaps

2022-07-08 Thread Christophe JAILLET
Use bitmap_zalloc()/bitmap_free() instead of hand-writing them.

It is less verbose and it improves the semantic.

Signed-off-by: Christophe JAILLET 
---
 drivers/gpu/drm/vc4/vc4_validate_shaders.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_validate_shaders.c 
b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
index e315aeb5fef5..d074d2014be4 100644
--- a/drivers/gpu/drm/vc4/vc4_validate_shaders.c
+++ b/drivers/gpu/drm/vc4/vc4_validate_shaders.c
@@ -795,9 +795,8 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
 
reset_validation_state(_state);
 
-   validation_state.branch_targets =
-   kcalloc(BITS_TO_LONGS(validation_state.max_ip),
-   sizeof(unsigned long), GFP_KERNEL);
+   validation_state.branch_targets = bitmap_zalloc(validation_state.max_ip,
+   GFP_KERNEL);
if (!validation_state.branch_targets)
goto fail;
 
@@ -939,12 +938,12 @@ vc4_validate_shader(struct drm_gem_cma_object *shader_obj)
(validated_shader->uniforms_size +
 4 * validated_shader->num_texture_samples);
 
-   kfree(validation_state.branch_targets);
+   bitmap_free(validation_state.branch_targets);
 
return validated_shader;
 
 fail:
-   kfree(validation_state.branch_targets);
+   bitmap_free(validation_state.branch_targets);
if (validated_shader) {
kfree(validated_shader->uniform_addr_offsets);
kfree(validated_shader->texture_samples);
-- 
2.34.1



Re: [PATCH 0/5] drm/modes: Command line mode selection fixes and improvements

2022-07-08 Thread Hans de Goede
Hi Geert,

On 7/8/22 20:21, Geert Uytterhoeven wrote:
>   Hi all,
> 
> This patch series contains fixes and improvements for specifying video
> modes on the kernel command line.
> 
> This has been tested on ARAnyM using a work-in-progress Atari DRM driver
> (more info and related patches can be found in [1]).
> 
> Thanks for your comments!
> 
> [1] "[PATCH v3 00/10] drm: Add support for low-color frame buffer formats"
> https://lore.kernel.org/r/cover.1657294931.git.ge...@linux-m68k.org
> 
> Geert Uytterhoeven (5):
>   drm/modes: parse_cmdline: Handle empty mode name part
>   drm/modes: Extract drm_mode_parse_cmdline_named_mode()
>   drm/modes: parse_cmdline: Make mode->*specified handling more uniform
>   drm/modes: Add support for driver-specific named modes
>   drm/modes: parse_cmdline: Add support for named modes containing
> dashes

Thanks, I have some remarks on patches 1/5 and 2/5 the rest looks
good to me. 

For 1/5 and 2/5 with my remarks addressed:

Reviewed-by: Hans de Goede 

For 3/5, 4/5 and 5/5:

Reviewed-by: Hans de Goede 

Regards,

Hans

> 
>  drivers/gpu/drm/drm_modes.c | 57 ++---
>  include/drm/drm_connector.h | 10 +++
>  2 files changed, 50 insertions(+), 17 deletions(-)
> 



Re: [PATCH 1/5] drm/modes: parse_cmdline: Handle empty mode name part

2022-07-08 Thread Hans de Goede
Hi Geert,

On 7/8/22 20:21, Geert Uytterhoeven wrote:
> If no mode name part was specified, mode_end is zero, and the "ret ==
> mode_end" check does the wrong thing.
> 
> Fix this by checking for a non-zero return value instead.

Which is wrong to do, since now if you have e.g. a mode list
with:

"dblntsc",
"dblntsc-ff"

in there and the cmdline contains "dblntsc-ff" then you
will already stop with a (wrong!) match at "dblntsc".

> While at it, skip all named mode handling when mode_end is zero, as it
> is futile.

AFAICT, this is actually what needs to be done to fix this, while keeping
the ret == mode_end check.

Regards,

Hans


> 
> Fixes: 7b1cce760afe38b4 ("drm/modes: parse_cmdline: Allow specifying 
> stand-alone options")
> Signed-off-by: Geert Uytterhoeven 
> ---
>  drivers/gpu/drm/drm_modes.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index 14b746f7ba975954..30a7be97707bfb16 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1823,9 +1823,9 @@ bool drm_mode_parse_command_line_for_connector(const 
> char *mode_option,
>   }
>  
>   /* First check for a named mode */
> - for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
> + for (i = 0; mode_end && i < ARRAY_SIZE(drm_named_modes_whitelist); i++) 
> {
>   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
> - if (ret == mode_end) {
> + if (ret) {
>   if (refresh_ptr)
>   return false; /* named + refresh is invalid */
>  



Re: [PATCH 1/9] dt-bindings: msm/dp: drop extra p1 region

2022-07-08 Thread Stephen Boyd
Quoting Dmitry Baryshkov (2022-07-07 20:46:43)
> On 08/07/2022 04:28, Stephen Boyd wrote:
> > Quoting Dmitry Baryshkov (2022-07-07 14:31:56)
> >> The p1 region was probably added by mistake, none of the DTS files
> >> provides one (and the driver source code also doesn't use one). Drop it
> >> now.
> >
> > Yes, looks like the driver doesn't use it.
> >
> >>
> >> Fixes: 687825c402f1 ("dt-bindings: msm/dp: Change reg definition")
> >> Signed-off-by: Dmitry Baryshkov 
> >> ---
> >>   Documentation/devicetree/bindings/display/msm/dp-controller.yaml | 1 -
> >>   1 file changed, 1 deletion(-)
> >>
> >> diff --git 
> >> a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml 
> >> b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
> >> index 94bc6e1b6451..d6bbe58ef9e8 100644
> >> --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
> >> +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
> >> @@ -29,7 +29,6 @@ properties:
> >> - description: aux register block
> >> - description: link register block
> >> - description: p0 register block
> >> -  - description: p1 register block
> >
> > The p1 registers exist on sc7180. They start where the example starts,
> > at 0xae91400.
>
> Do they exist on e.g. sc7280? In other words, should we add the region
> to the DTS? For now I'm going to mark it as optional.
>

Yes I see the same address for P1 on sc7280. Maybe it's a typo? Abhinav,
can you confirm?


Re: [PATCH 5/9] dt-bindings: msm/dp: account for clocks specific for qcom, sc7280-edp

2022-07-08 Thread Stephen Boyd
Quoting Dmitry Baryshkov (2022-07-07 20:59:02)
> On 08/07/2022 04:32, Stephen Boyd wrote:
> > Quoting Dmitry Baryshkov (2022-07-07 14:32:00)
> >> diff --git 
> >> a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml 
> >> b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
> >> index f00eae66196f..1ef845005b14 100644
> >> --- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
> >> +++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
> >> @@ -119,6 +111,50 @@ required:
> >> - power-domains
> >> - ports
> >>
> >> +allOf:
> >> +  - if:
> >> +  properties:
> >> +compatible:
> >> +  contains:
> >> +enum:
> >> +  - qcom,sc7280-edp
> >> +then:
> >> +  properties:
> >> +clocks:
> >> +  items:
> >> +- description: XO clock
> >
> > What is this for? I would guess it's for the eDP phy, but that isn't
> > part of the eDP controller, so probably it can be removed.
>
> Good question. I was documenting what is present in the sc7280-edp
> controller DT entry. Could you please check if we can drop them? I don't
> have the hardware at hand.
>

eDP works fine without those two clks on CRD (hoglin). They can be
dropped from the dtsi file.


Re: [GIT PULL] fbdev updates & fixes for v5.19-rc6

2022-07-08 Thread pr-tracker-bot
The pull request you sent on Fri, 8 Jul 2022 09:38:00 +0200:

> http://git.kernel.org/pub/scm/linux/kernel/git/deller/linux-fbdev.git 
> tags/for-5.19/fbdev-3

has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/086ff84617185393a0bbf25830c4f36412a7d3f4

Thank you!

-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html


[PATCH libdrm] modetest: Add support for named modes containing dashes

2022-07-08 Thread Geert Uytterhoeven
It is fairly common for named video modes to contain dashes (e.g.
"tt-mid" on Atari, "dblntsc-ff" on Amiga).  Currently such mode names
are not recognized, as the dash is considered to be a separator between
mode name and vertical refrsh.

Fix this by skipping any dashes that are not followed immediately by a
digit when looking for the separator.

Signed-off-by: Geert Uytterhoeven 
---
Please refer to [1] for related Linux DRM patches and background
information.

v2:
  - New.

[1] "[PATCH v3 00/10] drm: Add support for low-color frame buffer formats"
https://lore.kernel.org/r/cover.1657294931.git.ge...@linux-m68k.org
---
 tests/modetest/modetest.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 7c6c21ef5174c41a..09f026764a07aad9 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1903,8 +1903,11 @@ static int parse_connector(struct pipe_arg *pipe, const 
char *arg)
 
arg = endp + 1;
 
-   /* Search for the vertical refresh or the format. */
+   /* Search for the vertical refresh or the format, */
+   /* The former must be followed by a number */
p = strpbrk(arg, "-@");
+   while (p && *p == '-' && !isdigit(p[1]))
+   p = strpbrk(p + 1, "-@");
if (p == NULL)
p = arg + strlen(arg);
len = min(sizeof pipe->mode_str - 1, (unsigned int)(p - arg));
-- 
2.25.1



[PATCH libdrm v2 07/10] util: Add test pattern support for big-endian XRGB1555/RGB565

2022-07-08 Thread Geert Uytterhoeven
Add support for drawing the SMPTE and tiles test patterns in buffers
using big-endian formats.

For now this is limited to XRGB1555 and RGB565, which are the most
common big-endian formats.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/util/pattern.c | 31 +--
 1 file changed, 21 insertions(+), 10 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index c0bd382fbced90fb..e693892bb3cf93c1 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -23,6 +23,7 @@
  * IN THE SOFTWARE.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -75,13 +76,17 @@ static inline uint32_t swap32(uint32_t x)
 }
 
 #if defined(__BIG_ENDIAN__) || defined(__ARM_BIG_ENDIAN) || 
defined(__mc68000__) || defined(__MIPSEB__) || defined(__s390__) || 
defined(__sparc__)
+#define cpu_to_be16(x) (x)
 #define cpu_to_le16(x) swap16(x)
 #define cpu_to_le32(x) swap32(x)
 #else
+#define cpu_to_be16(x) swap16(x)
 #define cpu_to_le16(x) (x)
 #define cpu_to_le32(x) (x)
 #endif
 
+#define cpu_to_fb16(x) (fb_be ? cpu_to_be16(x) : cpu_to_le16(x))
+
 /* This function takes 8-bit color values */
 static inline uint32_t shiftcolor8(const struct util_color_component *comp,
  uint32_t value)
@@ -382,7 +387,7 @@ static void fill_smpte_yuv_packed(const struct 
util_yuv_info *yuv, void *mem,
 
 static void fill_smpte_rgb16(const struct util_rgb_info *rgb, void *mem,
 unsigned int width, unsigned int height,
-unsigned int stride)
+unsigned int stride, bool fb_be)
 {
const uint16_t colors_top[] = {
MAKE_RGBA(rgb, 192, 192, 192, 255), /* grey */
@@ -417,26 +422,26 @@ static void fill_smpte_rgb16(const struct util_rgb_info 
*rgb, void *mem,
 
for (y = 0; y < height * 6 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint16_t *)mem)[x] = cpu_to_le16(colors_top[x * 7 / 
width]);
+   ((uint16_t *)mem)[x] = cpu_to_fb16(colors_top[x * 7 / 
width]);
mem += stride;
}
 
for (; y < height * 7 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint16_t *)mem)[x] = cpu_to_le16(colors_middle[x * 7 
/ width]);
+   ((uint16_t *)mem)[x] = cpu_to_fb16(colors_middle[x * 7 
/ width]);
mem += stride;
}
 
for (; y < height; ++y) {
for (x = 0; x < width * 5 / 7; ++x)
((uint16_t *)mem)[x] =
-   cpu_to_le16(colors_bottom[x * 4 / (width * 5 / 
7)]);
+   cpu_to_fb16(colors_bottom[x * 4 / (width * 5 / 
7)]);
for (; x < width * 6 / 7; ++x)
((uint16_t *)mem)[x] =
-   cpu_to_le16(colors_bottom[(x - width * 5 / 7) * 
3
+   cpu_to_fb16(colors_bottom[(x - width * 5 / 7) * 
3
  / (width / 7) + 4]);
for (; x < width; ++x)
-   ((uint16_t *)mem)[x] = cpu_to_le16(colors_bottom[7]);
+   ((uint16_t *)mem)[x] = cpu_to_fb16(colors_bottom[7]);
mem += stride;
}
 }
@@ -1081,9 +1086,11 @@ static void fill_smpte(const struct util_format_info 
*info, void *planes[3],
case DRM_FORMAT_BGRA:
case DRM_FORMAT_BGRX:
case DRM_FORMAT_RGB565:
+   case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_BGR565:
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_XRGB1555:
+   case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_ABGR1555:
case DRM_FORMAT_XBGR1555:
case DRM_FORMAT_RGBA5551:
@@ -1091,7 +1098,8 @@ static void fill_smpte(const struct util_format_info 
*info, void *planes[3],
case DRM_FORMAT_BGRA5551:
case DRM_FORMAT_BGRX5551:
return fill_smpte_rgb16(>rgb, planes[0],
-   width, height, stride);
+   width, height, stride,
+   info->format & DRM_FORMAT_BIG_ENDIAN);
 
case DRM_FORMAT_BGR888:
case DRM_FORMAT_RGB888:
@@ -1263,7 +1271,7 @@ static void fill_tiles_yuv_packed(const struct 
util_format_info *info,
 
 static void fill_tiles_rgb16(const struct util_format_info *info, void *mem,
 unsigned int width, unsigned int height,
-unsigned int stride)
+unsigned int stride, bool fb_be)
 {
const struct util_rgb_info *rgb = >rgb;
void *mem_base = mem;
@@ -1279,7 +1287,7 @@ static void fill_tiles_rgb16(const struct 
util_format_info *info, void *mem,
  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
  

[PATCH libdrm v2 09/10] util: Add pwetty support for big-endian RGB565

2022-07-08 Thread Geert Uytterhoeven
Add support for rendering the crosshairs in a buffer using the
big-endian RGB565 format.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/util/pattern.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 627f402be1d02e1c..1222b47ea3f14cd0 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -1178,6 +1178,7 @@ static void make_pwetty(void *data, unsigned int width, 
unsigned int height,
cairo_format = CAIRO_FORMAT_ARGB32;
break;
case DRM_FORMAT_RGB565:
+   case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_BGR565:
cairo_format = CAIRO_FORMAT_RGB16_565;
swap16 = fb_foreign_endian(format);
-- 
2.25.1



[PATCH libdrm v2 02/10] util: Fix 32 bpp patterns on big-endian

2022-07-08 Thread Geert Uytterhoeven
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set.  Hence writes of multi-byte pixel
values need to take endianness into account.

Introduce a swap32() helper to byteswap 32-bit values, and a
cpu_to_le32() helper to convert 32-bit values from CPU-endian to
little-endian, and use the latter in the various pattern fill functions
for 32-bit formats.

Signed-off-by: Geert Uytterhoeven 
Acked-by: Pekka Paalanen 
---
Works now with Linux' drm_fb_xrgb_to_rgb332_line(), which uses
le32_to_cpu() to read pixel values from memory.

v2:
  - Add Acked-by,
  - Add swap32() intermediate helper,
  - Add __ARM_BIG_ENDIAN and __s390__.
---
 tests/util/pattern.c | 32 +++-
 1 file changed, 23 insertions(+), 9 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 631114563fa011c2..26e0614bd4faa620 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -61,6 +61,20 @@ struct color_yuv {
  .u = MAKE_YUV_601_U(r, g, b), \
  .v = MAKE_YUV_601_V(r, g, b) }
 
+static inline uint32_t swap32(uint32_t x)
+{
+   return ((x & 0x00ffU) << 24) |
+  ((x & 0xff00U) <<  8) |
+  ((x & 0x00ffU) >>  8) |
+  ((x & 0xff00U) >> 24);
+}
+
+#if defined(__BIG_ENDIAN__) || defined(__ARM_BIG_ENDIAN) || 
defined(__mc68000__) || defined(__MIPSEB__) || defined(__s390__) || 
defined(__sparc__)
+#define cpu_to_le32(x) swap32(x)
+#else
+#define cpu_to_le32(x) (x)
+#endif
+
 /* This function takes 8-bit color values */
 static inline uint32_t shiftcolor8(const struct util_color_component *comp,
  uint32_t value)
@@ -520,26 +534,26 @@ static void fill_smpte_rgb32(const struct util_rgb_info 
*rgb, void *mem,
 
for (y = 0; y < height * 6 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint32_t *)mem)[x] = colors_top[x * 7 / width];
+   ((uint32_t *)mem)[x] = cpu_to_le32(colors_top[x * 7 / 
width]);
mem += stride;
}
 
for (; y < height * 7 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint32_t *)mem)[x] = colors_middle[x * 7 / width];
+   ((uint32_t *)mem)[x] = cpu_to_le32(colors_middle[x * 7 
/ width]);
mem += stride;
}
 
for (; y < height; ++y) {
for (x = 0; x < width * 5 / 7; ++x)
((uint32_t *)mem)[x] =
-   colors_bottom[x * 4 / (width * 5 / 7)];
+   cpu_to_le32(colors_bottom[x * 4 / (width * 5 / 
7)]);
for (; x < width * 6 / 7; ++x)
((uint32_t *)mem)[x] =
-   colors_bottom[(x - width * 5 / 7) * 3
- / (width / 7) + 4];
+   cpu_to_le32(colors_bottom[(x - width * 5 / 7) * 
3
+ / (width / 7) + 4]);
for (; x < width; ++x)
-   ((uint32_t *)mem)[x] = colors_bottom[7];
+   ((uint32_t *)mem)[x] = cpu_to_le32(colors_bottom[7]);
mem += stride;
}
 }
@@ -1307,7 +1321,7 @@ static void fill_tiles_rgb32(const struct 
util_format_info *info, void *mem,
  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
  alpha);
 
-   ((uint32_t *)mem)[x] = color;
+   ((uint32_t *)mem)[x] = cpu_to_le32(color);
}
mem += stride;
}
@@ -1454,7 +1468,7 @@ static void fill_gradient_rgb32(const struct 
util_rgb_info *rgb,
 
for (j = 0; j < width / 2; j++) {
uint32_t value = MAKE_RGBA10(rgb, j & 0x3ff, j & 0x3ff, 
j & 0x3ff, 0);
-   row[2*j] = row[2*j+1] = value;
+   row[2*j] = row[2*j+1] = cpu_to_le32(value);
}
mem += stride;
}
@@ -1464,7 +1478,7 @@ static void fill_gradient_rgb32(const struct 
util_rgb_info *rgb,
 
for (j = 0; j < width / 2; j++) {
uint32_t value = MAKE_RGBA10(rgb, j & 0x3fc, j & 0x3fc, 
j & 0x3fc, 0);
-   row[2*j] = row[2*j+1] = value;
+   row[2*j] = row[2*j+1] = cpu_to_le32(value);
}
mem += stride;
}
-- 
2.25.1



[PATCH libdrm v2 08/10] util: Fix pwetty on big-endian

2022-07-08 Thread Geert Uytterhoeven
Cairo always uses native byte order for rendering.

Hence if the byte order of the frame buffer differs from the byte order
of the CPU, the frame buffer contents need to be byteswapped twice: once
before rendering, to convert to native byte order, and a second time
after rendering, to restore the frame buffer format's byte order.

Note that byte swapping is not done for ARGB32 formats, as for these
formats, byte order only affects the order of the red, green, and blue
channels, which we do not care about here.

Signed-off-by: Geert Uytterhoeven 
---
This is ugly, but I see no better solution.

v2:
  - RGB30 is untested.
---
 tests/util/pattern.c | 54 +++-
 1 file changed, 48 insertions(+), 6 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index e693892bb3cf93c1..627f402be1d02e1c 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -76,13 +76,15 @@ static inline uint32_t swap32(uint32_t x)
 }
 
 #if defined(__BIG_ENDIAN__) || defined(__ARM_BIG_ENDIAN) || 
defined(__mc68000__) || defined(__MIPSEB__) || defined(__s390__) || 
defined(__sparc__)
-#define cpu_to_be16(x) (x)
-#define cpu_to_le16(x) swap16(x)
-#define cpu_to_le32(x) swap32(x)
+#define cpu_to_be16(x) (x)
+#define cpu_to_le16(x) swap16(x)
+#define cpu_to_le32(x) swap32(x)
+#define fb_foreign_endian(format)  (!((format) & DRM_FORMAT_BIG_ENDIAN))
 #else
-#define cpu_to_be16(x) swap16(x)
-#define cpu_to_le16(x) (x)
-#define cpu_to_le32(x) (x)
+#define cpu_to_be16(x) swap16(x)
+#define cpu_to_le16(x) (x)
+#define cpu_to_le32(x) (x)
+#define fb_foreign_endian(format)  ((format) & DRM_FORMAT_BIG_ENDIAN)
 #endif
 
 #define cpu_to_fb16(x) (fb_be ? cpu_to_be16(x) : cpu_to_le16(x))
@@ -1133,6 +1135,30 @@ static void fill_smpte(const struct util_format_info 
*info, void *planes[3],
 #define GREEN 1
 #define BLUE  0
 
+static void byteswap_buffer16(void *mem, unsigned int width, unsigned int 
height,
+ unsigned int stride)
+{
+   unsigned int x, y;
+
+   for (y = 0; y < height; ++y) {
+   for (x = 0; x < width; ++x)
+   ((uint16_t *)mem)[x] = swap16(((uint16_t *)mem)[x]);
+   mem += stride;
+   }
+}
+
+static void byteswap_buffer32(void *mem, unsigned int width, unsigned int 
height,
+ unsigned int stride)
+{
+   unsigned int x, y;
+
+   for (y = 0; y < height; ++y) {
+   for (x = 0; x < width; ++x)
+   ((uint32_t *)mem)[x] = swap32(((uint32_t *)mem)[x]);
+   mem += stride;
+   }
+}
+
 static void make_pwetty(void *data, unsigned int width, unsigned int height,
unsigned int stride, uint32_t format)
 {
@@ -1140,6 +1166,8 @@ static void make_pwetty(void *data, unsigned int width, 
unsigned int height,
cairo_surface_t *surface;
cairo_t *cr;
cairo_format_t cairo_format;
+   bool swap16 = false;
+   bool swap32 = false;
 
/* we can ignore the order of R,G,B channels */
switch (format) {
@@ -1152,6 +1180,7 @@ static void make_pwetty(void *data, unsigned int width, 
unsigned int height,
case DRM_FORMAT_RGB565:
case DRM_FORMAT_BGR565:
cairo_format = CAIRO_FORMAT_RGB16_565;
+   swap16 = fb_foreign_endian(format);
break;
 #if CAIRO_VERSION_MAJOR > 1 || (CAIRO_VERSION_MAJOR == 1 && 
CAIRO_VERSION_MINOR >= 12)
case DRM_FORMAT_ARGB2101010:
@@ -1159,12 +1188,19 @@ static void make_pwetty(void *data, unsigned int width, 
unsigned int height,
case DRM_FORMAT_ABGR2101010:
case DRM_FORMAT_XBGR2101010:
cairo_format = CAIRO_FORMAT_RGB30;
+   swap32 = fb_foreign_endian(format);
break;
 #endif
default:
return;
}
 
+   /* Cairo uses native byte order, so we may have to byteswap before... */
+   if (swap16)
+   byteswap_buffer16(data, width, height, stride);
+   if (swap32)
+   byteswap_buffer32(data, width, height, stride);
+
surface = cairo_image_surface_create_for_data(data,
  cairo_format,
  width, height,
@@ -1200,6 +1236,12 @@ static void make_pwetty(void *data, unsigned int width, 
unsigned int height,
}
 
cairo_destroy(cr);
+
+   /* ... and after */
+   if (swap16)
+   byteswap_buffer16(data, width, height, stride);
+   if (swap32)
+   byteswap_buffer32(data, width, height, stride);
 #endif
 }
 
-- 
2.25.1



[PATCH libdrm v2 10/10] modetest: Add SMPTE pattern support for C4 format

2022-07-08 Thread Geert Uytterhoeven
Add support for drawing the SMPTE pattern in buffers using a
color-indexed frame buffer formats with two, four, or sixteen colors.

Note that this still uses 256 as the CLUT size, as
DRM_IOCTL_MODE_SETGAMMA enforces that the size matches against the
(fixed) gamma size, while the CLUT size depends on the format.

Move clearing the color LUT entries from util_smpte_index_gamma() to its
caller, as only the caller knows how many entries there really are
(currently DRM always assumes 256 entries).

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - Split off changes to tests/modetest/modetest.c,
  - Add C1 and C2 support.

The linuxdoc comments say userspace can query the gamma size:

 * drm_mode_gamma_set_ioctl - set the gamma table
 *
 * Set the gamma table of a CRTC to the one passed in by the user. Userspace can
 * inquire the required gamma table size through drm_mode_gamma_get_ioctl.

 * drm_mode_gamma_get_ioctl - get the gamma table
 *
 * Copy the current gamma table into the storage provided. This also provides
 * the gamma table size the driver expects, which can be used to size the
 * allocated storage.

but the code doesn't seem to support that in an easy way (like setting
red/green/blue to NULL on input, retrieving gamma_size on output), only
by providing big enough buffers for red/green/blue, and looping over
gamma_size until -EINVAL is no longer returned.
---
 tests/modetest/modetest.c | 9 ++---
 tests/util/pattern.c  | 1 -
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 11a39ada80579293..1d87046f0fdfaf24 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1129,13 +1129,16 @@ static bool add_property_optional(struct device *dev, 
uint32_t obj_id,
 static void set_gamma(struct device *dev, unsigned crtc_id, unsigned fourcc)
 {
unsigned blob_id = 0;
+   const struct util_format_info *info;
/* TODO: support 1024-sized LUTs, when the use-case arises */
struct drm_color_lut gamma_lut[256];
int i, ret;
 
-   if (fourcc == DRM_FORMAT_C8) {
-   /* TODO: Add C8 support for more patterns */
-   util_smpte_index_gamma(256, gamma_lut);
+   info = util_format_info_find(fourcc);
+   if (info->ncolors) {
+   memset(gamma_lut, 0, sizeof(gamma_lut));
+   /* TODO: Add index support for more patterns */
+   util_smpte_index_gamma(info->ncolors, gamma_lut);
drmModeCreatePropertyBlob(dev->fd, gamma_lut, 
sizeof(gamma_lut), _id);
} else {
for (i = 0; i < 256; i++) {
diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index a5c4e31ad856709e..631114563fa011c2 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -990,7 +990,6 @@ void util_smpte_index_gamma(unsigned size, struct 
drm_color_lut *lut)
printf("Error: gamma too small: %u < 2\n", size);
return;
}
-   memset(lut, 0, size * sizeof(struct drm_color_lut));
 
 #define FILL_COLOR(idx, r, g, b) \
lut[idx].red = (r) * 0x101; \
-- 
2.25.1



[PATCH libdrm v2 06/10] modetest: Add support for parsing big-endian formats

2022-07-08 Thread Geert Uytterhoeven
When specifying a frame buffer format like "RG16be" (big-endian RG16),
modetest still uses the little-endian variant, as the format string is
truncated to four characters.

Fix this by increasing the format string size to 7 bytes (6 characters +
NUL terminator).

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/modetest/modetest.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index f70043d1e6815497..7c6c21ef5174c41a 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -821,7 +821,7 @@ struct pipe_arg {
unsigned int num_cons;
uint32_t crtc_id;
char mode_str[64];
-   char format_str[5];
+   char format_str[7];
float vrefresh;
unsigned int fourcc;
drmModeModeInfo *mode;
@@ -843,7 +843,7 @@ struct plane_arg {
unsigned int old_fb_id;
struct bo *bo;
struct bo *old_bo;
-   char format_str[5]; /* need to leave room for terminating \0 */
+   char format_str[7]; /* need to leave room for "be" and terminating \0 */
unsigned int fourcc;
 };
 
@@ -1917,8 +1917,8 @@ static int parse_connector(struct pipe_arg *pipe, const 
char *arg)
}
 
if (*p == '@') {
-   strncpy(pipe->format_str, p + 1, 4);
-   pipe->format_str[4] = '\0';
+   strncpy(pipe->format_str, p + 1, 6);
+   pipe->format_str[6] = '\0';
}
 
pipe->fourcc = util_format_fourcc(pipe->format_str);
@@ -1970,8 +1970,8 @@ static int parse_plane(struct plane_arg *plane, const 
char *p)
}
 
if (*end == '@') {
-   strncpy(plane->format_str, end + 1, 4);
-   plane->format_str[4] = '\0';
+   strncpy(plane->format_str, end + 1, 6);
+   plane->format_str[6] = '\0';
} else {
strcpy(plane->format_str, "XR24");
}
-- 
2.25.1



[PATCH libdrm v2 04/10] util: Add missing big-endian RGB16 frame buffer formats

2022-07-08 Thread Geert Uytterhoeven
Signed-off-by: Geert Uytterhoeven 
---
Any better suggestion than appending "be"?

v2:
  - New.
---
 tests/util/format.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/util/format.c b/tests/util/format.c
index a5464de6fc1ac70f..42a652c9a402a654 100644
--- a/tests/util/format.c
+++ b/tests/util/format.c
@@ -76,6 +76,9 @@ static const struct util_format_info format_info[] = {
{ DRM_FORMAT_BGRX5551, "BX15", MAKE_RGB_INFO(5, 1, 5, 6, 5, 11, 0, 0) },
{ DRM_FORMAT_RGB565, "RG16", MAKE_RGB_INFO(5, 11, 6, 5, 5, 0, 0, 0) },
{ DRM_FORMAT_BGR565, "BG16", MAKE_RGB_INFO(5, 0, 6, 5, 5, 11, 0, 0) },
+   /* Big-endian RGB16 */
+   { DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN, "XR15be", 
MAKE_RGB_INFO(5, 10, 5, 5, 5, 0, 0, 0) },
+   { DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN, "RG16be", MAKE_RGB_INFO(5, 
11, 6, 5, 5, 0, 0, 0) },
/* RGB24 */
{ DRM_FORMAT_BGR888, "BG24", MAKE_RGB_INFO(8, 0, 8, 8, 8, 16, 0, 0) },
{ DRM_FORMAT_RGB888, "RG24", MAKE_RGB_INFO(8, 16, 8, 8, 8, 0, 0, 0) },
-- 
2.25.1



[PATCH libdrm v2 00/10] Big-endian fixes

2022-07-08 Thread Geert Uytterhoeven
Hi all,

This patch series fixes some endianness issues in libdrm.
It has been tested on ARAnyM using a work-in-progress Atari DRM driver.

Changes compared to v1:
  - Consider arm, aarch64, microblaze, s390, and sh in endianness
checks,
  - Add Acked-by,
  - Add swap32() intermediate helper,
  - Fix 16 bpp formats on big-endian,
  - Add support for big-endian XRGB1555 and RGB565,
  - Fix printing of big-endian fourcc values,
  - Fix pwetty on big-endian.

Please refer to [2] for related Linux DRM patches and background
information.

Thanks for your comments!

[1] "[PATCH RFC libdrm 0/2] Big-endian fixes"
https://lore.kernel.org/r/cover.1646684158.git.ge...@linux-m68k.org
[2] "[PATCH v3 00/10] drm: Add support for low-color frame buffer formats"
https://lore.kernel.org/r/cover.1657294931.git.ge...@linux-m68k.org

Geert Uytterhoeven (11):
  intel: Improve checks for big-endian
  util: Fix 32 bpp patterns on big-endian
  util: Fix 16 bpp patterns on big-endian
  util: Add missing big-endian RGB16 frame buffer formats
  modetest: Fix printing of big-endian fourcc values
  modetest: Add support for parsing big-endian formats
  util: Add test pattern support for big-endian XRGB1555/RGB565
  util: Fix pwetty on big-endian
  util: Add pwetty support for big-endian RGB565
  modetest: Add support for big-endian XRGB1555/RGB565

 intel/uthash.h|   2 +-
 tests/modetest/buffers.c  |   4 ++
 tests/modetest/modetest.c |  25 ---
 tests/util/format.c   |   3 +
 tests/util/pattern.c  | 115 +++---
 5 files changed, 115 insertions(+), 29 deletions(-)

-- 
2.25.1

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH libdrm v2 02/10] util: Factor out and optimize C8 SMPTE color LUT

2022-07-08 Thread Geert Uytterhoeven
The color LUT for the SMPTE pattern in indexed mode contains 22 entries,
although only 13 are non-unique.

Reduce the size of the color LUT by dropping duplicate entries, so it
can be reused for formats supporting e.g. 16 colors.  Rename
util_smpte_c8_gamma() to util_smpte_index_gamma() accordingly.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - Factor out smpte color LUT.
---
 tests/modetest/modetest.c |   2 +-
 tests/util/pattern.c  | 107 ++
 tests/util/pattern.h  |   2 +-
 3 files changed, 76 insertions(+), 35 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 9ceb5688f7683ffc..11a39ada80579293 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -1135,7 +1135,7 @@ static void set_gamma(struct device *dev, unsigned 
crtc_id, unsigned fourcc)
 
if (fourcc == DRM_FORMAT_C8) {
/* TODO: Add C8 support for more patterns */
-   util_smpte_c8_gamma(256, gamma_lut);
+   util_smpte_index_gamma(256, gamma_lut);
drmModeCreatePropertyBlob(dev->fd, gamma_lut, 
sizeof(gamma_lut), _id);
} else {
for (i = 0; i < 256; i++) {
diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 3753ebc1eeae6c9a..5a648b468e524fbb 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -605,6 +605,69 @@ static void fill_smpte_rgb16fp(const struct util_rgb_info 
*rgb, void *mem,
}
 }
 
+enum smpte_colors {
+   SMPTE_COLOR_GREY,
+   SMPTE_COLOR_YELLOW,
+   SMPTE_COLOR_CYAN,
+   SMPTE_COLOR_GREEN,
+   SMPTE_COLOR_MAGENTA,
+   SMPTE_COLOR_RED,
+   SMPTE_COLOR_BLUE,
+   SMPTE_COLOR_BLACK,
+   SMPTE_COLOR_IN_PHASE,
+   SMPTE_COLOR_SUPER_WHITE,
+   SMPTE_COLOR_QUADRATURE,
+   SMPTE_COLOR_3PC5,
+   SMPTE_COLOR_11PC5,
+};
+
+static const struct drm_color_lut smpte_color_lut[] = {
+   [SMPTE_COLOR_GREY] ={ 192 * 0x101, 192 * 0x101, 192 * 0x101 },
+   [SMPTE_COLOR_YELLOW] =  { 192 * 0x101, 192 * 0x101, 0   * 0x101 },
+   [SMPTE_COLOR_CYAN] ={ 0   * 0x101, 192 * 0x101, 192 * 0x101 },
+   [SMPTE_COLOR_GREEN] =   { 0   * 0x101, 192 * 0x101, 0   * 0x101 },
+   [SMPTE_COLOR_MAGENTA] = { 192 * 0x101, 0   * 0x101, 192 * 0x101 },
+   [SMPTE_COLOR_RED] = { 192 * 0x101, 0   * 0x101, 0   * 0x101 },
+   [SMPTE_COLOR_BLUE] ={ 0   * 0x101, 0   * 0x101, 192 * 0x101 },
+   [SMPTE_COLOR_BLACK] =   { 19  * 0x101, 19  * 0x101, 19  * 0x101 },
+   [SMPTE_COLOR_IN_PHASE] ={ 0   * 0x101, 33  * 0x101, 76  * 0x101 },
+   [SMPTE_COLOR_SUPER_WHITE] = { 255 * 0x101, 255 * 0x101, 255 * 0x101 },
+   [SMPTE_COLOR_QUADRATURE] =  { 50  * 0x101, 0   * 0x101, 106 * 0x101 },
+   [SMPTE_COLOR_3PC5] ={ 9   * 0x101, 9   * 0x101, 9   * 0x101 },
+   [SMPTE_COLOR_11PC5] =   { 29  * 0x101, 29  * 0x101, 29  * 0x101 },
+};
+
+static unsigned int smpte_top[7] = {
+   SMPTE_COLOR_GREY,
+   SMPTE_COLOR_YELLOW,
+   SMPTE_COLOR_CYAN,
+   SMPTE_COLOR_GREEN,
+   SMPTE_COLOR_MAGENTA,
+   SMPTE_COLOR_RED,
+   SMPTE_COLOR_BLUE,
+};
+
+static unsigned int smpte_middle[7] = {
+   SMPTE_COLOR_BLUE,
+   SMPTE_COLOR_BLACK,
+   SMPTE_COLOR_MAGENTA,
+   SMPTE_COLOR_BLACK,
+   SMPTE_COLOR_CYAN,
+   SMPTE_COLOR_BLACK,
+   SMPTE_COLOR_GREY,
+};
+
+static unsigned int smpte_bottom[8] = {
+   SMPTE_COLOR_IN_PHASE,
+   SMPTE_COLOR_SUPER_WHITE,
+   SMPTE_COLOR_QUADRATURE,
+   SMPTE_COLOR_BLACK,
+   SMPTE_COLOR_3PC5,
+   SMPTE_COLOR_BLACK,
+   SMPTE_COLOR_11PC5,
+   SMPTE_COLOR_BLACK,
+};
+
 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
  unsigned int stride)
 {
@@ -613,34 +676,35 @@ static void fill_smpte_c8(void *mem, unsigned int width, 
unsigned int height,
 
for (y = 0; y < height * 6 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint8_t *)mem)[x] = x * 7 / width;
+   ((uint8_t *)mem)[x] = smpte_top[x * 7 / width];
mem += stride;
}
 
for (; y < height * 7 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint8_t *)mem)[x] = 7 + (x * 7 / width);
+   ((uint8_t *)mem)[x] = smpte_middle[x * 7 / width];
mem += stride;
}
 
for (; y < height; ++y) {
for (x = 0; x < width * 5 / 7; ++x)
((uint8_t *)mem)[x] =
-   14 + (x * 4 / (width * 5 / 7));
+   smpte_bottom[x * 4 / (width * 5 / 7)];
for (; x < width * 6 / 7; ++x)
((uint8_t *)mem)[x] =
-   14 + ((x - width * 5 / 7) * 3
- / (width / 7) + 4);
+   

[PATCH libdrm v2 01/10] intel: Improve checks for big-endian

2022-07-08 Thread Geert Uytterhoeven
  - sparc64-linux-gnu-gcc does not define __BIG_ENDIAN__ or SPARC, but
does define __sparc__, hence replace the check for SPARC by a check
for __sparc__,
  - powerpc{,64,64}-linux-gnu-gcc does not define __ppc__ or __ppc64__,
but does define __BIG_ENDIAN__.
powerpc64le-linux-gnu-gcc does not define __ppc__ or __ppc64__, but
does define __LITTLE_ENDIAN__.
Hence remove the checks for __ppc__ and __ppc64__.
  - arm-linux-gnueabi-gcc and aarch64-linux-gnu-gcc do not define
__BIG_ENDIAN__ for targets in big-endian mode, but do define
__ARM_BIG_ENDIAN, so add a check for the latter,
  - m68k-linux-gnu-gcc does not define __BIG_ENDIAN__, but does define
__mc68000__, so add a check for the latter,
  - mips{,64}-linux-gnu{,abi64}-gcc does not define __BIG_ENDIAN__, but
does define __MIPSEB__, so add a check for the latter,
  - s390x-linux-gnu-gcc does not define __BIG_ENDIAN__, but does define
__s390__, so add a check for the latter,
  - hppa{,64}-linux-gnu-gcc, microblaze-linux-gcc, and sh4-linux-gnu-gcc
in big-endian mode do define __BIG_ENDIAN__, and thus should work
out-of-the-box.

Signed-off-by: Geert Uytterhoeven 
---
Untested due to lack of hardware.

v2:
  - Add arm, aarch64, microblaze, s390, and sh.
---
 intel/uthash.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/intel/uthash.h b/intel/uthash.h
index 45d1f9fc12a1d6f9..a8465f23ff9fbcac 100644
--- a/intel/uthash.h
+++ b/intel/uthash.h
@@ -648,7 +648,7 @@ do {
 #define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 3UL) == 2UL)
 #define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 3UL) == 3UL)
 #define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
-#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || 
defined(__ppc64__))
+#if (defined(__BIG_ENDIAN__) || defined(__ARM_BIG_ENDIAN) || 
defined(__mc68000__) || defined(__MIPSEB__) || defined(__s390__) || 
defined(__sparc__))
 #define MUR_THREE_ONE(p) *WP(p))&0x00ff) << 8) | 
(((*(WP(p)+1))&0xff00) >> 24))
 #define MUR_TWO_TWO(p)   *WP(p))&0x) <<16) | 
(((*(WP(p)+1))&0x) >> 16))
 #define MUR_ONE_THREE(p) *WP(p))&0x00ff) <<24) | 
(((*(WP(p)+1))&0xff00) >>  8))
-- 
2.25.1



[PATCH libdrm v2 03/10] util: Fix 16 bpp patterns on big-endian

2022-07-08 Thread Geert Uytterhoeven
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set.  Hence writes of multi-byte pixel
values need to take endianness into account.

Introduce a swap16() helper to byteswap 16-bit values, and a
cpu_to_le16() helper to convert 16-bit values from CPU-endian to
little-endian, and use the latter in the various pattern fill functions
for 16-bit formats.

Signed-off-by: Geert Uytterhoeven 
---
Works now with both Linux' drm_fb_swab() and my own
drm_fb_rgb565_to_rgb332_line() (the latter uses le16_to_cpu() to read
pixel values from memory).

v2:
  - New.
---
 tests/util/pattern.c | 21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 26e0614bd4faa620..c0bd382fbced90fb 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -61,6 +61,11 @@ struct color_yuv {
  .u = MAKE_YUV_601_U(r, g, b), \
  .v = MAKE_YUV_601_V(r, g, b) }
 
+static inline uint16_t swap16(uint16_t x)
+{
+   return ((x & 0x00ffU) << 8) | ((x & 0xff00U) >> 8);
+}
+
 static inline uint32_t swap32(uint32_t x)
 {
return ((x & 0x00ffU) << 24) |
@@ -70,8 +75,10 @@ static inline uint32_t swap32(uint32_t x)
 }
 
 #if defined(__BIG_ENDIAN__) || defined(__ARM_BIG_ENDIAN) || 
defined(__mc68000__) || defined(__MIPSEB__) || defined(__s390__) || 
defined(__sparc__)
+#define cpu_to_le16(x) swap16(x)
 #define cpu_to_le32(x) swap32(x)
 #else
+#define cpu_to_le16(x) (x)
 #define cpu_to_le32(x) (x)
 #endif
 
@@ -410,26 +417,26 @@ static void fill_smpte_rgb16(const struct util_rgb_info 
*rgb, void *mem,
 
for (y = 0; y < height * 6 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint16_t *)mem)[x] = colors_top[x * 7 / width];
+   ((uint16_t *)mem)[x] = cpu_to_le16(colors_top[x * 7 / 
width]);
mem += stride;
}
 
for (; y < height * 7 / 9; ++y) {
for (x = 0; x < width; ++x)
-   ((uint16_t *)mem)[x] = colors_middle[x * 7 / width];
+   ((uint16_t *)mem)[x] = cpu_to_le16(colors_middle[x * 7 
/ width]);
mem += stride;
}
 
for (; y < height; ++y) {
for (x = 0; x < width * 5 / 7; ++x)
((uint16_t *)mem)[x] =
-   colors_bottom[x * 4 / (width * 5 / 7)];
+   cpu_to_le16(colors_bottom[x * 4 / (width * 5 / 
7)]);
for (; x < width * 6 / 7; ++x)
((uint16_t *)mem)[x] =
-   colors_bottom[(x - width * 5 / 7) * 3
- / (width / 7) + 4];
+   cpu_to_le16(colors_bottom[(x - width * 5 / 7) * 
3
+ / (width / 7) + 4]);
for (; x < width; ++x)
-   ((uint16_t *)mem)[x] = colors_bottom[7];
+   ((uint16_t *)mem)[x] = cpu_to_le16(colors_bottom[7]);
mem += stride;
}
 }
@@ -1272,7 +1279,7 @@ static void fill_tiles_rgb16(const struct 
util_format_info *info, void *mem,
  (rgb32 >> 8) & 0xff, rgb32 & 0xff,
  255);
 
-   ((uint16_t *)mem)[x] = color;
+   ((uint16_t *)mem)[x] = cpu_to_le16(color);
}
mem += stride;
}
-- 
2.25.1



[PATCH libdrm v2 05/10] modetest: Fix printing of big-endian fourcc values

2022-07-08 Thread Geert Uytterhoeven
Big-endian fourcc values have the MSB set, as that is the
DRM_FORMAT_BIG_ENDIAN flag.  Hence printing the last byte unmodified
leads to weird characters.

Fix this by stripping the DRM_FORMAT_BIG_ENDIAN flag, and appending "be"
for big-endian formats.

Sample impact:

 Planes:
 id crtcfb  CRTC x,yx,y gamma size  possible 
crtcs
 32 34  36  0,0 0,0 0   0x0001
-  formats: C1   C2   C4   C8   RG16 RG1� XR24
+  formats: C1   C2   C4   C8   RG16 RG16be XR24
   props:
8 type:
flags: immutable enum
enums: Overlay=0 Primary=1 Cursor=2
value: 1
30 IN_FORMATS:
flags: immutable blob
blobs:

value:
000100070018
000100382020314320203243
202034432020384336314752b6314752
34325258007f

in_formats blob decoded:
 C1  :  LINEAR
 C2  :  LINEAR
 C4  :  LINEAR
 C8  :  LINEAR
 RG16:  LINEAR
-RG1�:  LINEAR
+RG16be:  LINEAR
 XR24:  LINEAR

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/modetest/modetest.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 1d87046f0fdfaf24..f70043d1e6815497 100644
--- a/tests/modetest/modetest.c
+++ b/tests/modetest/modetest.c
@@ -198,11 +198,15 @@ static bit_name_fn(mode_flag)
 
 static void dump_fourcc(uint32_t fourcc)
 {
-   printf(" %c%c%c%c",
+   bool be = fourcc & DRM_FORMAT_BIG_ENDIAN;
+
+   fourcc &= ~DRM_FORMAT_BIG_ENDIAN;
+   printf(" %c%c%c%c%s",
fourcc,
fourcc >> 8,
fourcc >> 16,
-   fourcc >> 24);
+   fourcc >> 24,
+   be ? "be" : "");
 }
 
 static void dump_encoders(struct device *dev)
-- 
2.25.1



[PATCH libdrm v2 08/10] util: Add SMPTE pattern support for C2 format

2022-07-08 Thread Geert Uytterhoeven
Add support for drawing the SMPTE pattern in a buffer using the C2
indexed format.

As only four colors are available, resolution is halved, and the pattern
is drawn in a PenTile RG-GB matrix, using Floyd-Steinberg dithering.
The magnitude of the green subpixels is reduced, as there are twice as
many green subpixels as red or blue subpixels.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/util/pattern.c | 97 +++-
 1 file changed, 96 insertions(+), 1 deletion(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 5ec7d66495209df4..a5c4e31ad856709e 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -825,6 +825,93 @@ static void fill_smpte_c1(void *mem, unsigned int width, 
unsigned int height,
 
free(fsd);
 }
+
+static void write_pixel_2(uint8_t *mem, unsigned int x, unsigned int pixel)
+{
+   unsigned int shift = 6 - 2 * (x & 3);
+   unsigned int mask = 3U << shift;
+
+   mem[x / 4] = (mem[x / 4] & ~mask) | ((pixel << shift) & mask);
+}
+
+static void write_color_2(struct fsd *fsd, uint8_t *mem, unsigned int stride,
+ unsigned int x, unsigned int index)
+{
+   struct drm_color_lut color = smpte_color_lut[index];
+   unsigned int r, g, b;
+
+   fsd_dither(fsd, );
+
+   if (color.red >= 32768) {
+   r = 1;
+   color.red = 65535;
+   } else {
+   r = 0;
+   color.red = 0;
+   }
+   if (color.green >= 32768) {
+   g = 2;
+   color.green = 65535;
+   } else {
+   g = 0;
+   color.green = 0;
+   }
+   if (color.blue >= 32768) {
+   b = 3;
+   color.blue = 65535;
+   } else {
+   b = 0;
+   color.blue = 0;
+   }
+
+   fsd_update(fsd, );
+
+   /* Use PenTile RG-GB */
+   write_pixel_2(mem, 2 * x, r);
+   write_pixel_2(mem, 2 * x + 1, g);
+   write_pixel_2(mem + stride, 2 * x, g);
+   write_pixel_2(mem + stride, 2 * x + 1, b);
+}
+
+static void fill_smpte_c2(void *mem, unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+   struct fsd *fsd = fsd_alloc(width);
+   unsigned int x;
+   unsigned int y;
+
+   /* Half resolution for PenTile RG-GB */
+   width /= 2;
+   height /= 2;
+
+   for (y = 0; y < height * 6 / 9; ++y) {
+   for (x = 0; x < width; ++x)
+   write_color_2(fsd, mem, stride, x, smpte_top[x * 7 / 
width]);
+   mem += 2 * stride;
+   }
+
+   for (; y < height * 7 / 9; ++y) {
+   for (x = 0; x < width; ++x)
+   write_color_2(fsd, mem, stride, x, smpte_middle[x * 7 / 
width]);
+   mem += 2 * stride;
+   }
+
+   for (; y < height; ++y) {
+   for (x = 0; x < width * 5 / 7; ++x)
+   write_color_2(fsd, mem, stride, x,
+ smpte_bottom[x * 4 / (width * 5 / 7)]);
+   for (; x < width * 6 / 7; ++x)
+   write_color_2(fsd, mem, stride, x,
+ smpte_bottom[(x - width * 5 / 7) * 3 /
+  (width / 7) + 4]);
+   for (; x < width; ++x)
+   write_color_2(fsd, mem, stride, x, smpte_bottom[7]);
+   mem += 2 * stride;
+   }
+
+   free(fsd);
+}
+
 static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel)
 {
if (x & 1)
@@ -910,9 +997,15 @@ void util_smpte_index_gamma(unsigned size, struct 
drm_color_lut *lut)
lut[idx].green = (g) * 0x101; \
lut[idx].blue = (b) * 0x101
 
-   if (size < ARRAY_SIZE(smpte_color_lut)) {
+   if (size < 4) {
FILL_COLOR(0, 0,   0,   0  );   /* black */
FILL_COLOR(1, 255, 255, 255);   /* white */
+   } else if (size < ARRAY_SIZE(smpte_color_lut)) {
+   /* PenTile RG-GB */
+   FILL_COLOR(0, 0,   0,   0  );   /* black */
+   FILL_COLOR(1, 255, 0,   0  );   /* red */
+   FILL_COLOR(2, 0,   207, 0  );   /* green */
+   FILL_COLOR(3, 0,   0,   255);   /* blue */
} else {
memcpy(lut, smpte_color_lut, sizeof(smpte_color_lut));
}
@@ -929,6 +1022,8 @@ static void fill_smpte(const struct util_format_info 
*info, void *planes[3],
switch (info->format) {
case DRM_FORMAT_C1:
return fill_smpte_c1(planes[0], width, height, stride);
+   case DRM_FORMAT_C2:
+   return fill_smpte_c2(planes[0], width, height, stride);
case DRM_FORMAT_C4:
return fill_smpte_c4(planes[0], width, height, stride);
case DRM_FORMAT_C8:
-- 
2.25.1



[PATCH libdrm v2 09/10] modetest: Add support for DRM_FORMAT_C[124]

2022-07-08 Thread Geert Uytterhoeven
Add support for creating buffers using the new color-indexed frame
buffer formats with two, four, and sixteen colors.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - Split off changes to tests/modetest/buffers.c.
---
 tests/modetest/buffers.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
index 8a8d9e0143474378..af7f60b4fb4d09ad 100644
--- a/tests/modetest/buffers.c
+++ b/tests/modetest/buffers.c
@@ -135,6 +135,18 @@ bo_create(int fd, unsigned int format,
int ret;
 
switch (format) {
+   case DRM_FORMAT_C1:
+   bpp = 1;
+   break;
+
+   case DRM_FORMAT_C2:
+   bpp = 2;
+   break;
+
+   case DRM_FORMAT_C4:
+   bpp = 4;
+   break;
+
case DRM_FORMAT_C8:
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV21:
@@ -283,6 +295,9 @@ bo_create(int fd, unsigned int format,
planes[2] = virtual + offsets[2];
break;
 
+   case DRM_FORMAT_C1:
+   case DRM_FORMAT_C2:
+   case DRM_FORMAT_C4:
case DRM_FORMAT_C8:
case DRM_FORMAT_ARGB:
case DRM_FORMAT_XRGB:
-- 
2.25.1



[PATCH libdrm v2 05/10] util: Store number of colors for indexed formats

2022-07-08 Thread Geert Uytterhoeven
Store the number of available colors for color-indexed frame
buffer formats in the format_info[] array.  This avoids the need of test
code for having to use switch statements all the time to obtain the
number of colors, or to check if a mode is color-indexed or not.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/util/format.c | 8 
 tests/util/format.h | 1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/tests/util/format.c b/tests/util/format.c
index 4b984af9bce8ac6f..a5464de6fc1ac70f 100644
--- a/tests/util/format.c
+++ b/tests/util/format.c
@@ -40,10 +40,10 @@
 
 static const struct util_format_info format_info[] = {
/* Indexed */
-   { DRM_FORMAT_C1, "C1" },
-   { DRM_FORMAT_C2, "C2" },
-   { DRM_FORMAT_C4, "C4" },
-   { DRM_FORMAT_C8, "C8" },
+   { DRM_FORMAT_C1, "C1", .ncolors = 2 },
+   { DRM_FORMAT_C2, "C2", .ncolors = 4 },
+   { DRM_FORMAT_C4, "C4", .ncolors = 16 },
+   { DRM_FORMAT_C8, "C8", .ncolors = 256 },
/* YUV packed */
{ DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
{ DRM_FORMAT_VYUY, "VYUY", MAKE_YUV_INFO(YUV_YCrCb | YUV_CY, 2, 2, 2) },
diff --git a/tests/util/format.h b/tests/util/format.h
index 2ce1c021fd78d51d..b847c9f2933b3cde 100644
--- a/tests/util/format.h
+++ b/tests/util/format.h
@@ -55,6 +55,7 @@ struct util_yuv_info {
 struct util_format_info {
uint32_t format;
const char *name;
+   unsigned int ncolors;
const struct util_rgb_info rgb;
const struct util_yuv_info yuv;
 };
-- 
2.25.1



[PATCH libdrm v2 07/10] util: Add SMPTE pattern support for C1 format

2022-07-08 Thread Geert Uytterhoeven
Add support for drawing the SMPTE pattern in a buffer using the C1
indexed format.

As only two colors are available, the pattern is drawn in black and
white, using Floyd-Steinberg dithering.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  New.
---
 tests/util/pattern.c | 171 ++-
 1 file changed, 167 insertions(+), 4 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 8ed5f8dd1a6282f9..5ec7d66495209df4 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -668,6 +668,163 @@ static unsigned int smpte_bottom[8] = {
SMPTE_COLOR_BLACK,
 };
 
+/*
+ * Floyd-Steinberg dithering
+ */
+
+struct fsd {
+   unsigned int width;
+   unsigned int x;
+   unsigned int i;
+   int red;
+   int green;
+   int blue;
+   int error[];
+};
+
+static struct fsd *fsd_alloc(unsigned int width)
+{
+   unsigned int n = 3 * (width + 1);
+   struct fsd *fsd = malloc(sizeof(*fsd) + n * sizeof(fsd->error[0]));
+
+   fsd->width = width;
+   fsd->x = 0;
+   fsd->i = 0;
+   memset(fsd->error, 0, n * sizeof(fsd->error[0]));
+
+   return fsd;
+}
+
+static inline int clamp(int val, int min, int max)
+{
+   if (val < min)
+   return min;
+   if (val > max)
+   return max;
+   return val;
+}
+
+static void fsd_dither(struct fsd *fsd, struct drm_color_lut *color)
+{
+   unsigned int i = fsd->i;
+
+   fsd->red = (int)color->red + (fsd->error[3 * i] + 8) / 16;
+   fsd->green = (int)color->green + (fsd->error[3 * i + 1] + 8) / 16;
+   fsd->blue = (int)color->blue + (fsd->error[3 * i + 2] + 8) / 16;
+
+   color->red = clamp(fsd->red, 0, 65535);
+   color->green = clamp(fsd->green, 0, 65535);
+   color->blue = clamp(fsd->blue, 0, 65535);
+}
+
+static void fsd_update(struct fsd *fsd, const struct drm_color_lut *actual)
+{
+   int error_red = fsd->red - (int)actual->red;
+   int error_green = fsd->green - (int)actual->green;
+   int error_blue = fsd->blue - (int)actual->blue;
+   unsigned int width = fsd->width;
+   unsigned int i = fsd->i, j;
+   unsigned int n = width + 1;
+
+   /* Distribute errors over neighboring pixels */
+   if (fsd->x == width - 1) {
+   /* Last pixel on this scanline */
+   /* South East: initialize to zero */
+   fsd->error[3 * i] = 0;
+   fsd->error[3 * i + 1] = 0;
+   fsd->error[3 * i + 2] = 0;
+   } else {
+   /* East: accumulate error */
+   j = (i + 1) % n;
+   fsd->error[3 * j] += 7 * error_red;
+   fsd->error[3 * j + 1] += 7 * error_green;
+   fsd->error[3 * j + 2] += 7 * error_blue;
+
+   /* South East: initial error */
+   fsd->error[3 * i] = error_red;
+   fsd->error[3 * i + 1] = error_green;
+   fsd->error[3 * i + 2] = error_blue;
+   }
+   /* South West: accumulate error */
+   j = (i + width - 1) % n;
+   fsd->error[3 * j] += 3 * error_red;
+   fsd->error[3 * j + 1] += 3 * error_green;
+   fsd->error[3 * j + 2] += 3 * error_blue;
+
+   /* South: accumulate error */
+   j = (i + width) % n;
+   fsd->error[3 * j] += 5 * error_red;
+   fsd->error[3 * j + 1] += 5 * error_green;
+   fsd->error[3 * j + 2] += 5 * error_blue;
+
+   fsd->x = (fsd->x + 1) % width;
+   fsd->i = (fsd->i + 1) % n;
+}
+
+static void write_pixel_1(uint8_t *mem, unsigned int x, unsigned int pixel)
+{
+   unsigned int shift = 7 - (x & 7);
+   unsigned int mask = 1U << shift;
+
+   mem[x / 8] = (mem[x / 8] & ~mask) | ((pixel << shift) & mask);
+}
+
+static void write_color_1(struct fsd *fsd, uint8_t *mem, unsigned int x,
+ unsigned int index)
+{
+   struct drm_color_lut color = smpte_color_lut[index];
+   unsigned int pixel;
+
+   fsd_dither(fsd, );
+
+   /* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
+   if (3 * color.red + 6 * color.green + color.blue >= 10 * 32768) {
+   pixel = 1;
+   color.red = color.green = color.blue = 65535;
+   } else {
+   pixel = 0;
+   color.red = color.green = color.blue = 0;
+   }
+
+   fsd_update(fsd, );
+
+   write_pixel_1(mem, x, pixel);
+}
+
+static void fill_smpte_c1(void *mem, unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+   struct fsd *fsd = fsd_alloc(width);
+   unsigned int x;
+   unsigned int y;
+
+   for (y = 0; y < height * 6 / 9; ++y) {
+   for (x = 0; x < width; ++x)
+   write_color_1(fsd, mem, x, smpte_top[x * 7 / width]);
+   mem += stride;
+   }
+
+   for (; y < height * 7 / 9; ++y) {
+   for (x = 0; x < width; ++x)
+   write_color_1(fsd, mem, x, smpte_middle[x * 7 / width]);
+

[PATCH libdrm v2 10/10] modetest: Add support for big-endian XRGB1555/RGB565

2022-07-08 Thread Geert Uytterhoeven
Add support for creating buffers using big-endian formats.

For now this is limited to XRGB1555 and RGB565, which are the most
common big-endian formats.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/modetest/buffers.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
index af7f60b4fb4d09ad..aa4a976a7eb19dbd 100644
--- a/tests/modetest/buffers.c
+++ b/tests/modetest/buffers.c
@@ -167,6 +167,7 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_BGRX:
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_XRGB1555:
+   case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_ABGR1555:
case DRM_FORMAT_XBGR1555:
case DRM_FORMAT_RGBA5551:
@@ -174,6 +175,7 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_BGRA5551:
case DRM_FORMAT_BGRX5551:
case DRM_FORMAT_RGB565:
+   case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_BGR565:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VYUY:
@@ -309,6 +311,7 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_BGRX:
case DRM_FORMAT_ARGB1555:
case DRM_FORMAT_XRGB1555:
+   case DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_ABGR1555:
case DRM_FORMAT_XBGR1555:
case DRM_FORMAT_RGBA5551:
@@ -316,6 +319,7 @@ bo_create(int fd, unsigned int format,
case DRM_FORMAT_BGRA5551:
case DRM_FORMAT_BGRX5551:
case DRM_FORMAT_RGB565:
+   case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
case DRM_FORMAT_BGR565:
case DRM_FORMAT_BGR888:
case DRM_FORMAT_RGB888:
-- 
2.25.1



[PATCH libdrm v2 06/10] util: Add SMPTE pattern support for C4 format

2022-07-08 Thread Geert Uytterhoeven
Add support for drawing the SMPTE pattern in a buffer using the C4
indexed format.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - Use new smpte_top[],
  - Split off changes to tests/util/pattern.c.
---
 tests/util/pattern.c | 42 ++
 1 file changed, 42 insertions(+)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 5a648b468e524fbb..8ed5f8dd1a6282f9 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -668,6 +668,46 @@ static unsigned int smpte_bottom[8] = {
SMPTE_COLOR_BLACK,
 };
 
+static void write_pixel_4(uint8_t *mem, unsigned int x, unsigned int pixel)
+{
+   if (x & 1)
+   mem[x / 2] = (mem[x / 2] & 0xf0) | (pixel & 0x0f);
+   else
+   mem[x / 2] = (mem[x / 2] & 0x0f) | (pixel << 4);
+}
+
+static void fill_smpte_c4(void *mem, unsigned int width, unsigned int height,
+ unsigned int stride)
+{
+   unsigned int x;
+   unsigned int y;
+
+   for (y = 0; y < height * 6 / 9; ++y) {
+   for (x = 0; x < width; ++x)
+   write_pixel_4(mem, x, smpte_top[x * 7 / width]);
+   mem += stride;
+   }
+
+   for (; y < height * 7 / 9; ++y) {
+   for (x = 0; x < width; ++x)
+   write_pixel_4(mem, x, smpte_middle[x * 7 / width]);
+   mem += stride;
+   }
+
+   for (; y < height; ++y) {
+   for (x = 0; x < width * 5 / 7; ++x)
+   write_pixel_4(mem, x,
+ smpte_bottom[x * 4 / (width * 5 / 7)]);
+   for (; x < width * 6 / 7; ++x)
+   write_pixel_4(mem, x,
+ smpte_bottom[(x - width * 5 / 7) * 3 /
+  (width / 7) + 4]);
+   for (; x < width; ++x)
+   write_pixel_4(mem, x, smpte_bottom[7]);
+   mem += stride;
+   }
+}
+
 static void fill_smpte_c8(void *mem, unsigned int width, unsigned int height,
  unsigned int stride)
 {
@@ -726,6 +766,8 @@ static void fill_smpte(const struct util_format_info *info, 
void *planes[3],
unsigned char *u, *v;
 
switch (info->format) {
+   case DRM_FORMAT_C4:
+   return fill_smpte_c4(planes[0], width, height, stride);
case DRM_FORMAT_C8:
return fill_smpte_c8(planes[0], width, height, stride);
case DRM_FORMAT_UYVY:
-- 
2.25.1



[PATCH libdrm v2 04/10] util: Add support for DRM_FORMAT_C[124]

2022-07-08 Thread Geert Uytterhoeven
Add support for creating buffers using the new color-indexed frame
buffer formats with two, four, and sixteen colors.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - Split off changes to tests/util/format.c.
---
 tests/util/format.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/util/format.c b/tests/util/format.c
index 1ca1b82ce947b2f4..4b984af9bce8ac6f 100644
--- a/tests/util/format.c
+++ b/tests/util/format.c
@@ -40,6 +40,9 @@
 
 static const struct util_format_info format_info[] = {
/* Indexed */
+   { DRM_FORMAT_C1, "C1" },
+   { DRM_FORMAT_C2, "C2" },
+   { DRM_FORMAT_C4, "C4" },
{ DRM_FORMAT_C8, "C8" },
/* YUV packed */
{ DRM_FORMAT_UYVY, "UYVY", MAKE_YUV_INFO(YUV_YCbCr | YUV_CY, 2, 2, 2) },
-- 
2.25.1



[PATCH libdrm v2 01/10] util: Improve SMPTE color LUT accuracy

2022-07-08 Thread Geert Uytterhoeven
Fill in the LSB when converting color components from 8-bit to 16-bit.

Signed-off-by: Geert Uytterhoeven 
---
v2:
  - New.
---
 tests/util/pattern.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/tests/util/pattern.c b/tests/util/pattern.c
index 178aee8341a38920..3753ebc1eeae6c9a 100644
--- a/tests/util/pattern.c
+++ b/tests/util/pattern.c
@@ -646,9 +646,9 @@ void util_smpte_c8_gamma(unsigned size, struct 
drm_color_lut *lut)
memset(lut, 0, size * sizeof(struct drm_color_lut));
 
 #define FILL_COLOR(idx, r, g, b) \
-   lut[idx].red = (r) << 8; \
-   lut[idx].green = (g) << 8; \
-   lut[idx].blue = (b) << 8
+   lut[idx].red = (r) * 0x101; \
+   lut[idx].green = (g) * 0x101; \
+   lut[idx].blue = (b) * 0x101
 
FILL_COLOR( 0, 192, 192, 192);  /* grey */
FILL_COLOR( 1, 192, 192, 0  );  /* yellow */
-- 
2.25.1



[PATCH/RFC libdrm v2 03/10] drm_fourcc: Add DRM_FORMAT_C[124]

2022-07-08 Thread Geert Uytterhoeven
Introduce fourcc codes for color-indexed frame buffer formats with two,
four, and sixteen colors.

The fill order (the order in which multiple pixels are packed in a byte)
is the same order as used for indexed-color (2, 4, and 16 colors) images
in the PNG specification, Version 1.2.
This order is also the recommended and default order (FillOrder = 1) for
palette-color (16 colors) images in the TIFF 6.0 Specification, and is
also used for 16-color Linux frame buffer logos.

Signed-off-by: Geert Uytterhoeven 
---
Marked RFC, as this patch should be replaced by a proper sync with
Linux' include/drm/drm_fourcc.h, once accepted.

https://gitlab.freedesktop.org/mesa/drm/-/blob/main/include/drm/README
section "When and how to update these files".

v2:
  - Split off changes to include/drm/drm_fourcc.h,
  - Improve description.
---
 include/drm/drm_fourcc.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index c668ffb877f1b777..789c7a180cf559af 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -99,7 +99,10 @@ extern "C" {
 #define DRM_FORMAT_INVALID 0
 
 /* color index */
-#define DRM_FORMAT_C8  fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
+#define DRM_FORMAT_C1  fourcc_code('C', '1', ' ', ' ') /* [7:0] 
C0:C1:C2:C3:C4:C5:C6:C7 1:1:1:1:1:1:1:1 eight pixels/byte */
+#define DRM_FORMAT_C2  fourcc_code('C', '2', ' ', ' ') /* [7:0] 
C0:C1:C2:C3 2:2:2:2 four pixels/byte */
+#define DRM_FORMAT_C4  fourcc_code('C', '4', ' ', ' ') /* [7:0] C0:C1 
4:4 two pixels/byte */
+#define DRM_FORMAT_C8  fourcc_code('C', '8', ' ', ' ') /* [7:0] C 8 
one pixel/byte */
 
 /* 8 bpp Red */
 #define DRM_FORMAT_R8  fourcc_code('R', '8', ' ', ' ') /* [7:0] R */
-- 
2.25.1



[PATCH libdrm v2 00/10] Add support for low-color frame buffer formats

2022-07-08 Thread Geert Uytterhoeven
Hi all,

A long outstanding issue with the DRM subsystem has been the lack of
support for low-color displays, as used typically on older desktop
systems, and on small embedded displays.

This patch series adds support for color-indexed frame buffer formats
with 2, 4, and 16 colors.  It has been tested on ARAnyM using a
work-in-progress Atari DRM driver.

Changes compared to v1:
  - SMPTE color LUT accuracy,
  - Factor out smpte color LUT,
  - Restructure patches,
  - Improve descriptions.
  - Store number of colors for indexed formats,
  - Add SMPTE pattern support for the C1 and C2 formats.

Please refer to [2] for related Linux DRM patches and background
information.

Thanks for your comments!

[1] "[PATCH libdrm 0/3] Add support for low-color frame buffer formats"
https://lore.kernel.org/r/cover.1646683737.git.ge...@linux-m68k.org
[2] "[PATCH v3 00/10] drm: Add support for low-color frame buffer formats"
https://lore.kernel.org/r/cover.1657294931.git.ge...@linux-m68k.org

Geert Uytterhoeven (10):
  util: Improve SMPTE color LUT accuracy
  util: Factor out and optimize C8 SMPTE color LUT
  [RFC] drm_fourcc: Add DRM_FORMAT_C[124]
  util: Add support for DRM_FORMAT_C[124]
  util: Store number of colors for indexed formats
  util: Add SMPTE pattern support for C4 format
  util: Add SMPTE pattern support for C1 format
  util: Add SMPTE pattern support for C2 format
  modetest: Add support for DRM_FORMAT_C[124]
  modetest: Add SMPTE pattern support for C4 format

 include/drm/drm_fourcc.h  |   5 +-
 tests/modetest/buffers.c  |  15 ++
 tests/modetest/modetest.c |   9 +-
 tests/util/format.c   |   5 +-
 tests/util/format.h   |   1 +
 tests/util/pattern.c  | 416 ++
 tests/util/pattern.h  |   2 +-
 7 files changed, 409 insertions(+), 44 deletions(-)

-- 
2.25.1



[PATCH 3/5] drm/modes: parse_cmdline: Make mode->*specified handling more uniform

2022-07-08 Thread Geert Uytterhoeven
The various mode->*specified flags are not handled in an uniform way:
some flags are set by the corresponding drm_mode_parse_cmdline_*()
function, some flags by the caller of the function, and some flags by
both.

Make this uniform by making this the responsibility of the various
parsing helpers, i.e.
  - Move the setting of mode->specified from caller to callee,
  - Drop the duplicate setting of mode->bpp_specified and
mode->refresh_specified from callers.

Signed-off-by: Geert Uytterhoeven 
---
 drivers/gpu/drm/drm_modes.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 434383469e9d984d..9ce275fbda566b7c 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1599,6 +1599,7 @@ static int drm_mode_parse_cmdline_res_mode(const char 
*str, unsigned int length,
mode->yres = yres;
mode->cvt = cvt;
mode->rb = rb;
+   mode->specified = true;
 
return 0;
 }
@@ -1862,8 +1863,6 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
  mode);
if (ret)
return false;
-
-   mode->specified = true;
}
 
/* No mode? Check for freestanding extras and/or options */
@@ -1885,8 +1884,6 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
ret = drm_mode_parse_cmdline_bpp(bpp_ptr, _end_ptr, mode);
if (ret)
return false;
-
-   mode->bpp_specified = true;
}
 
if (refresh_ptr) {
@@ -1894,8 +1891,6 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
 _end_ptr, mode);
if (ret)
return false;
-
-   mode->refresh_specified = true;
}
 
/*
-- 
2.25.1



[PATCH 5/5] drm/modes: parse_cmdline: Add support for named modes containing dashes

2022-07-08 Thread Geert Uytterhoeven
It is fairly common for named video modes to contain dashes (e.g.
"tt-mid" on Atari, "dblntsc-ff" on Amiga).  Currently such mode names
are not recognized, as the dash is considered to be a separator between
mode name and bpp.

Fix this by skipping any dashes that are not followed immediately by a
digit when looking for the separator.

Signed-off-by: Geert Uytterhoeven 
---
 drivers/gpu/drm/drm_modes.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 7a00eb6df502e991..52e852518c6ad8e9 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1828,6 +1828,8 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
 
/* Try to locate the bpp and refresh specifiers, if any */
bpp_ptr = strchr(name, '-');
+   while (bpp_ptr && !isdigit(bpp_ptr[1]))
+   bpp_ptr = strchr(bpp_ptr + 1, '-');
if (bpp_ptr)
bpp_off = bpp_ptr - name;
 
-- 
2.25.1



[PATCH 4/5] drm/modes: Add support for driver-specific named modes

2022-07-08 Thread Geert Uytterhoeven
The mode parsing code recognizes named modes only if they are explicitly
listed in the internal whitelist, which is currently limited to "NTSC"
and "PAL".

Provide a mechanism for drivers to override this list to support custom
mode names.

Ideally, this list should just come from the driver's actual list of
modes, but connector->probed_modes is not yet populated at the time of
parsing.

Signed-off-by: Geert Uytterhoeven 
---
 drivers/gpu/drm/drm_modes.c | 15 +++
 include/drm/drm_connector.h | 10 ++
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 9ce275fbda566b7c..7a00eb6df502e991 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1748,25 +1748,31 @@ static int drm_mode_parse_cmdline_options(const char 
*str,
 static const char * const drm_named_modes_whitelist[] = {
"NTSC",
"PAL",
+   NULL
 };
 
 static int drm_mode_parse_cmdline_named_mode(const char *name,
 unsigned int length,
 bool refresh,
+const struct drm_connector 
*connector,
 struct drm_cmdline_mode *mode)
 {
+   const char * const *named_modes_whitelist;
unsigned int i;
int ret;
 
-   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
-   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+   named_modes_whitelist = connector->named_modes_whitelist ? :
+   drm_named_modes_whitelist;
+
+   for (i = 0; named_modes_whitelist[i]; i++) {
+   ret = str_has_prefix(name, named_modes_whitelist[i]);
if (!ret)
continue;
 
if (refresh)
return -EINVAL; /* named + refresh is invalid */
 
-   strcpy(mode->name, drm_named_modes_whitelist[i]);
+   strcpy(mode->name, named_modes_whitelist[i]);
mode->specified = true;
return 0;
}
@@ -1850,7 +1856,8 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
/* First check for a named mode */
if (mode_end) {
ret = drm_mode_parse_cmdline_named_mode(name, mode_end,
-   refresh_ptr, mode);
+   refresh_ptr, connector,
+   mode);
if (ret)
return false;
}
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 3ac4bf87f2571c4c..6361f8a596c01107 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -1659,6 +1659,16 @@ struct drm_connector {
 
/** @hdr_sink_metadata: HDR Metadata Information read from sink */
struct hdr_sink_metadata hdr_sink_metadata;
+
+   /**
+* @named_modes_whitelist:
+*
+* Optional NULL-terminated array of names to be considered valid mode
+* names.  This lets the command line option parser distinguish between
+* mode names and freestanding extras and/or options.
+* If not set, a set of defaults will be used.
+*/
+   const char * const *named_modes_whitelist;
 };
 
 #define obj_to_connector(x) container_of(x, struct drm_connector, base)
-- 
2.25.1



[PATCH 0/5] drm/modes: Command line mode selection fixes and improvements

2022-07-08 Thread Geert Uytterhoeven
Hi all,

This patch series contains fixes and improvements for specifying video
modes on the kernel command line.

This has been tested on ARAnyM using a work-in-progress Atari DRM driver
(more info and related patches can be found in [1]).

Thanks for your comments!

[1] "[PATCH v3 00/10] drm: Add support for low-color frame buffer formats"
https://lore.kernel.org/r/cover.1657294931.git.ge...@linux-m68k.org

Geert Uytterhoeven (5):
  drm/modes: parse_cmdline: Handle empty mode name part
  drm/modes: Extract drm_mode_parse_cmdline_named_mode()
  drm/modes: parse_cmdline: Make mode->*specified handling more uniform
  drm/modes: Add support for driver-specific named modes
  drm/modes: parse_cmdline: Add support for named modes containing
dashes

 drivers/gpu/drm/drm_modes.c | 57 ++---
 include/drm/drm_connector.h | 10 +++
 2 files changed, 50 insertions(+), 17 deletions(-)

-- 
2.25.1

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH 1/5] drm/modes: parse_cmdline: Handle empty mode name part

2022-07-08 Thread Geert Uytterhoeven
If no mode name part was specified, mode_end is zero, and the "ret ==
mode_end" check does the wrong thing.

Fix this by checking for a non-zero return value instead.
While at it, skip all named mode handling when mode_end is zero, as it
is futile.

Fixes: 7b1cce760afe38b4 ("drm/modes: parse_cmdline: Allow specifying 
stand-alone options")
Signed-off-by: Geert Uytterhoeven 
---
 drivers/gpu/drm/drm_modes.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 14b746f7ba975954..30a7be97707bfb16 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1823,9 +1823,9 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
}
 
/* First check for a named mode */
-   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+   for (i = 0; mode_end && i < ARRAY_SIZE(drm_named_modes_whitelist); i++) 
{
ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
-   if (ret == mode_end) {
+   if (ret) {
if (refresh_ptr)
return false; /* named + refresh is invalid */
 
-- 
2.25.1



[PATCH 3/3] drm/gud: Fix endianness in gud_xrgb8888_to_color() helper

2022-07-08 Thread Geert Uytterhoeven
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set.  Hence when converting from one
format to another, multi-byte pixel values loaded from memory must be
converted from little-endian to host-endian.  Conversely, multi-byte
pixel values written to memory must be converted from host-endian to
little-endian.  Currently only drm_fb_xrgb_to_rgb332_line() includes
endianness handling.

Fix gud_xrgb_to_color() on big-endian platforms by adding the
missing endianness handling.

Signed-off-by: Geert Uytterhoeven 
---
Compile-tested only.

Interestingly, drm_fb_xrgb_to_rgb332() was introduced for GUD,
and always had correct endiannes handling...
---
 drivers/gpu/drm/gud/gud_pipe.c | 14 --
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/gud/gud_pipe.c b/drivers/gpu/drm/gud/gud_pipe.c
index 4873f9799f412e04..d42592f6daab8b2a 100644
--- a/drivers/gpu/drm/gud/gud_pipe.c
+++ b/drivers/gpu/drm/gud/gud_pipe.c
@@ -105,7 +105,8 @@ static size_t gud_xrgb_to_color(u8 *dst, const struct 
drm_format_info *forma
unsigned int bits_per_pixel = 8 / block_width;
u8 r, g, b, pix, *block = dst; /* Assign to silence compiler warning */
unsigned int x, y, width;
-   u32 *pix32;
+   __le32 *sbuf32;
+   u32 pix32;
size_t len;
 
/* Start on a byte boundary */
@@ -114,8 +115,8 @@ static size_t gud_xrgb_to_color(u8 *dst, const struct 
drm_format_info *forma
len = drm_format_info_min_pitch(format, 0, width) * 
drm_rect_height(rect);
 
for (y = rect->y1; y < rect->y2; y++) {
-   pix32 = src + (y * fb->pitches[0]);
-   pix32 += rect->x1;
+   sbuf32 = src + (y * fb->pitches[0]);
+   sbuf32 += rect->x1;
 
for (x = 0; x < width; x++) {
unsigned int pixpos = x % block_width; /* within byte 
from the left */
@@ -126,9 +127,10 @@ static size_t gud_xrgb_to_color(u8 *dst, const struct 
drm_format_info *forma
*block = 0;
}
 
-   r = *pix32 >> 16;
-   g = *pix32 >> 8;
-   b = *pix32++;
+   pix32 = le32_to_cpu(*sbuf32++);
+   r = pix32 >> 16;
+   g = pix32 >> 8;
+   b = pix32;
 
switch (format->format) {
case GUD_DRM_FORMAT_XRGB:
-- 
2.25.1



[PATCH 2/5] drm/modes: Extract drm_mode_parse_cmdline_named_mode()

2022-07-08 Thread Geert Uytterhoeven
Extract the code to check for a named mode parameter into its own
function, to streamline the main parsing flow.

Signed-off-by: Geert Uytterhoeven 
---
 drivers/gpu/drm/drm_modes.c | 41 +++--
 1 file changed, 30 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 30a7be97707bfb16..434383469e9d984d 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1749,6 +1749,30 @@ static const char * const drm_named_modes_whitelist[] = {
"PAL",
 };
 
+static int drm_mode_parse_cmdline_named_mode(const char *name,
+unsigned int length,
+bool refresh,
+struct drm_cmdline_mode *mode)
+{
+   unsigned int i;
+   int ret;
+
+   for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
+   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
+   if (!ret)
+   continue;
+
+   if (refresh)
+   return -EINVAL; /* named + refresh is invalid */
+
+   strcpy(mode->name, drm_named_modes_whitelist[i]);
+   mode->specified = true;
+   return 0;
+   }
+
+   return 0;
+}
+
 /**
  * drm_mode_parse_command_line_for_connector - parse command line modeline for 
connector
  * @mode_option: optional per connector mode option
@@ -1785,7 +1809,7 @@ bool drm_mode_parse_command_line_for_connector(const char 
*mode_option,
const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
const char *options_ptr = NULL;
char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
-   int i, len, ret;
+   int len, ret;
 
memset(mode, 0, sizeof(*mode));
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
@@ -1823,16 +1847,11 @@ bool drm_mode_parse_command_line_for_connector(const 
char *mode_option,
}
 
/* First check for a named mode */
-   for (i = 0; mode_end && i < ARRAY_SIZE(drm_named_modes_whitelist); i++) 
{
-   ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
-   if (ret) {
-   if (refresh_ptr)
-   return false; /* named + refresh is invalid */
-
-   strcpy(mode->name, drm_named_modes_whitelist[i]);
-   mode->specified = true;
-   break;
-   }
+   if (mode_end) {
+   ret = drm_mode_parse_cmdline_named_mode(name, mode_end,
+   refresh_ptr, mode);
+   if (ret)
+   return false;
}
 
/* No named mode? Check for a normal mode argument, e.g. 1024x768 */
-- 
2.25.1



[PATCH 1/3] drm/fourcc: Add missing big-endian XRGB1555 and RGB565 formats

2022-07-08 Thread Geert Uytterhoeven
As of commit eae06120f1974e1a ("drm: refuse ADDFB2 ioctl for broken
bigendian drivers"), drivers must set the
quirk_addfb_prefer_host_byte_order quirk to make the drm_mode_addfb()
compat code work correctly on big-endian machines.

While that works fine for big-endian XRGB and ARGB, which are
mapped to the existing little-endian BGRX and BGRA formats, it
does not work for big-endian XRGB1555 and RGB565, as the latter are not
listed in the format database.

Fix this by adding the missing formats.  Limit this to big-endian
platforms, as there is currently no need to support these formats on
little-endian platforms.

Fixes: 6960e6da9cec3f66 ("drm: fix drm_mode_addfb() on big endian machines.")
Signed-off-by: Geert Uytterhoeven 
---
Cirrus is the only driver setting quirk_addfb_prefer_host_byte_order
and supporting RGB565 or XRGB1555, but no one tried that on big-endian?
Cirrus does not support DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN
in cirrus_fb_create, so you cannot get a graphical text console.

Do we need these definitions on little-endian platforms, too?
Would it be better to use "DRM_FORMAT_{XRGB1555,RGB565} |
DRM_FORMAT_BIG_ENDIAN" instead of "DRM_FORMAT_HOST_{XRGB1555,RGB565}" in
formats[]?

Alternative, callers could filter out the DRM_FORMAT_BIG_ENDIAN flag
when calling {,__}drm_format_info().

Advantages:
  - No need to have separate entries with DRM_FORMAT_BIG_ENDIAN set.

Disadvantages:
  - {,__}drm_format_info() returns a pointer to a const object,
whose .format field won't have the DRM_FORMAT_BIG_ENDIAN flag set,
complicating callers,
  - All callers need to be updated,
  - It is difficult to know which big-endian formats are really
supported, especially as only a few are needed.
---
 drivers/gpu/drm/drm_fourcc.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index e09331bb3bc73f21..16a854c9e07fa4b0 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -190,6 +190,10 @@ const struct drm_format_info *__drm_format_info(u32 format)
{ .format = DRM_FORMAT_BGRA5551,.depth = 15, 
.num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1, .has_alpha = true },
{ .format = DRM_FORMAT_RGB565,  .depth = 16, 
.num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_BGR565,  .depth = 16, 
.num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+#ifdef __BIG_ENDIAN
+   { .format = DRM_FORMAT_HOST_XRGB1555,   .depth = 15, 
.num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+   { .format = DRM_FORMAT_HOST_RGB565, .depth = 16, 
.num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
+#endif
{ .format = DRM_FORMAT_RGB888,  .depth = 24, 
.num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_BGR888,  .depth = 24, 
.num_planes = 1, .cpp = { 3, 0, 0 }, .hsub = 1, .vsub = 1 },
{ .format = DRM_FORMAT_XRGB,.depth = 24, 
.num_planes = 1, .cpp = { 4, 0, 0 }, .hsub = 1, .vsub = 1 },
-- 
2.25.1



[PATCH 2/3] drm/format-helper: Fix endianness in drm_fb_*_to_*() conversion helpers

2022-07-08 Thread Geert Uytterhoeven
DRM formats are defined to be little-endian, unless the
DRM_FORMAT_BIG_ENDIAN flag is set.  Hence when converting from one
format to another, multi-byte pixel values loaded from memory must be
converted from little-endian to host-endian.  Conversely, multi-byte
pixel values written to memory must be converted from host-endian to
little-endian.  Currently only drm_fb_xrgb_to_rgb332_line() includes
endianness handling.

Fix this by adding endianness handling to all conversion functions that
process multi-byte pixel values.

Note that the conversion to RGB565 is special, as there are two
versions: with and without byteswapping of the RGB565 pixel data.

Signed-off-by: Geert Uytterhoeven 
---
Tested with WIP atari_drm, which supports native big-endian RGB565.

Notes:
  - Most of these are used only by GUD or simpledrm (the latter through
drm_fb_blit_toio()).
Interestingly, drm_fb_xrgb_to_rgb332() was introduced for GUD,
and always had correct endiannes handling...
  - drm_fb_xrgb_to_gray8() is also used by st7586.c.
---
 drivers/gpu/drm/drm_format_helper.c | 80 +
 1 file changed, 46 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/drm_format_helper.c 
b/drivers/gpu/drm/drm_format_helper.c
index a3ccd8bc966fd816..c6182b5de78b0bd8 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -279,14 +279,16 @@ EXPORT_SYMBOL(drm_fb_xrgb_to_rgb332);
 static void drm_fb_xrgb_to_rgb565_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
 {
u16 *dbuf16 = dbuf;
-   const u32 *sbuf32 = sbuf;
+   const __le32 *sbuf32 = sbuf;
unsigned int x;
u16 val16;
+   u32 pix;
 
for (x = 0; x < pixels; x++) {
-   val16 = ((sbuf32[x] & 0x00F8) >> 8) |
-   ((sbuf32[x] & 0xFC00) >> 5) |
-   ((sbuf32[x] & 0x00F8) >> 3);
+   pix = le32_to_cpu(sbuf32[x]);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
dbuf16[x] = val16;
}
 }
@@ -295,14 +297,16 @@ static void drm_fb_xrgb_to_rgb565_swab_line(void 
*dbuf, const void *sbuf,
unsigned int pixels)
 {
u16 *dbuf16 = dbuf;
-   const u32 *sbuf32 = sbuf;
+   const __le32 *sbuf32 = sbuf;
unsigned int x;
u16 val16;
+   u32 pix;
 
for (x = 0; x < pixels; x++) {
-   val16 = ((sbuf32[x] & 0x00F8) >> 8) |
-   ((sbuf32[x] & 0xFC00) >> 5) |
-   ((sbuf32[x] & 0x00F8) >> 3);
+   pix = le32_to_cpu(sbuf32[x]);
+   val16 = ((pix & 0x00F8) >> 8) |
+   ((pix & 0xFC00) >> 5) |
+   ((pix & 0x00F8) >> 3);
dbuf16[x] = swab16(val16);
}
 }
@@ -360,13 +364,15 @@ EXPORT_SYMBOL(drm_fb_xrgb_to_rgb565_toio);
 static void drm_fb_xrgb_to_rgb888_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
 {
u8 *dbuf8 = dbuf;
-   const u32 *sbuf32 = sbuf;
+   const __le32 *sbuf32 = sbuf;
unsigned int x;
+   u32 pix;
 
for (x = 0; x < pixels; x++) {
-   *dbuf8++ = (sbuf32[x] & 0x00FF) >>  0;
-   *dbuf8++ = (sbuf32[x] & 0xFF00) >>  8;
-   *dbuf8++ = (sbuf32[x] & 0x00FF) >> 16;
+   pix = le32_to_cpu(sbuf32[x]);
+   *dbuf8++ = (pix & 0x00FF) >>  0;
+   *dbuf8++ = (pix & 0xFF00) >>  8;
+   *dbuf8++ = (pix & 0x00FF) >> 16;
}
 }
 
@@ -410,17 +416,19 @@ EXPORT_SYMBOL(drm_fb_xrgb_to_rgb888_toio);
 
 static void drm_fb_rgb565_to_xrgb_line(void *dbuf, const void *sbuf, 
unsigned int pixels)
 {
-   u32 *dbuf32 = dbuf;
-   const u16 *sbuf16 = sbuf;
+   __le32 *dbuf32 = dbuf;
+   const __le16 *sbuf16 = sbuf;
unsigned int x;
 
-   for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) {
-   u32 val32 = ((*sbuf16 & 0xf800) << 8) |
-   ((*sbuf16 & 0x07e0) << 5) |
-   ((*sbuf16 & 0x001f) << 3);
-   *dbuf32 = 0xff00 | val32 |
- ((val32 >> 3) & 0x00070007) |
- ((val32 >> 2) & 0x0300);
+   for (x = 0; x < pixels; x++) {
+   u16 val16 = le16_to_cpu(sbuf16[x]);
+   u32 val32 = ((val16 & 0xf800) << 8) |
+   ((val16 & 0x07e0) << 5) |
+   ((val16 & 0x001f) << 3);
+   val32 = 0xff00 | val32 |
+   ((val32 >> 3) & 0x00070007) |
+   ((val32 >> 2) & 0x0300);
+   dbuf32[x] = cpu_to_le32(val32);
}
 }
 
@@ -434,7 +442,7 @@ static void drm_fb_rgb565_to_xrgb_toio(void __iomem 
*dst, 

[PATCH v3 06/10] drm/fb-helper: Add support for DRM_FORMAT_C[124]

2022-07-08 Thread Geert Uytterhoeven
Add support for color-indexed frame buffer formats with two, four, and
sixteen colors to the DRM framebuffer helper functions:
  1. Add support for 1, 2, and 4 bits per pixel to the damage helper,
  2. For color-indexed modes, the length of the color bitfields must be
 set to the color depth, else the logo code may pick a logo with too
 many colors.  Drop the incorrect DAC width comment, which
 originates from the i915 driver.
  3. Accept C[124] modes when validating or filling in struct
 fb_var_screeninfo, and use the correct number of bits per pixel.
  4. Set the visual to FB_VISUAL_PSEUDOCOLOR for all color-indexed
 modes.

Signed-off-by: Geert Uytterhoeven 
Reviewed-by: Javier Martinez Canillas 
---
If "[PATCH] drm/fb-helper: Remove helpers to change frame buffer
config"[1] is accepted, the changes to drm_fb_helper_check_var() can
just be removed.

v3:
  - Fix FB_VISUAL_TRUECOLOR,
  - Add Reviewed-by,

v2:
  - Use drm_format_info_bpp() helper instead of deprecated .depth field
or format-dependent calculations,
  - Use new .is_color_indexed field instead of checking against a list
of formats.

[1] Link: 
https://lore.kernel.org/r/20220629105658.1373770-1-ge...@linux-m68k.org
---
 drivers/gpu/drm/drm_fb_helper.c | 101 
 1 file changed, 75 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 1705e8d345aba50a..5098efb374fe64ed 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -376,12 +376,31 @@ static void drm_fb_helper_damage_blit_real(struct 
drm_fb_helper *fb_helper,
   struct iosys_map *dst)
 {
struct drm_framebuffer *fb = fb_helper->fb;
-   unsigned int cpp = fb->format->cpp[0];
-   size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
-   void *src = fb_helper->fbdev->screen_buffer + offset;
-   size_t len = (clip->x2 - clip->x1) * cpp;
+   size_t offset = clip->y1 * fb->pitches[0];
+   size_t len = clip->x2 - clip->x1;
unsigned int y;
+   void *src;
 
+   switch (drm_format_info_bpp(fb->format, 0)) {
+   case 1:
+   offset += clip->x1 / 8;
+   len = DIV_ROUND_UP(len + clip->x1 % 8, 8);
+   break;
+   case 2:
+   offset += clip->x1 / 4;
+   len = DIV_ROUND_UP(len + clip->x1 % 4, 4);
+   break;
+   case 4:
+   offset += clip->x1 / 2;
+   len = DIV_ROUND_UP(len + clip->x1 % 2, 2);
+   break;
+   default:
+   offset += clip->x1 * fb->format->cpp[0];
+   len *= fb->format->cpp[0];
+   break;
+   }
+
+   src = fb_helper->fbdev->screen_buffer + offset;
iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
 
for (y = clip->y1; y < clip->y2; y++) {
@@ -1273,19 +1292,23 @@ static bool drm_fb_pixel_format_equal(const struct 
fb_var_screeninfo *var_1,
 }
 
 static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
-u8 depth)
+const struct drm_format_info *format)
 {
-   switch (depth) {
-   case 8:
+   u8 depth = format->depth;
+
+   if (format->is_color_indexed) {
var->red.offset = 0;
var->green.offset = 0;
var->blue.offset = 0;
-   var->red.length = 8; /* 8bit DAC */
-   var->green.length = 8;
-   var->blue.length = 8;
+   var->red.length = depth;
+   var->green.length = depth;
+   var->blue.length = depth;
var->transp.offset = 0;
var->transp.length = 0;
-   break;
+   return;
+   }
+
+   switch (depth) {
case 15:
var->red.offset = 10;
var->green.offset = 5;
@@ -1340,7 +1363,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
 {
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
+   const struct drm_format_info *format = fb->format;
struct drm_device *dev = fb_helper->dev;
+   unsigned int bpp;
 
if (in_dbg_master())
return -EINVAL;
@@ -1350,22 +1375,33 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo 
*var,
var->pixclock = 0;
}
 
-   if ((drm_format_info_block_width(fb->format, 0) > 1) ||
-   (drm_format_info_block_height(fb->format, 0) > 1))
-   return -EINVAL;
+   switch (format->format) {
+   case DRM_FORMAT_C1:
+   case DRM_FORMAT_C2:
+   case DRM_FORMAT_C4:
+   /* supported format with sub-byte pixels */
+   break;
+
+   default:
+   if ((drm_format_info_block_width(format, 0) > 1) ||
+   

[PATCH 0/3] drm: Endianness fixes

2022-07-08 Thread Geert Uytterhoeven
Hi all,

This patch series contains several endianness fixes for the DRM
subsystem.

This has been tested on ARAnyM using a work-in-progress Atari DRM
driver, which supports (a.o.) big-endian RGB565 (more info and related
patches can be found in [1]).

Thanks for your comments!

[1] "[PATCH v3 00/10] drm: Add support for low-color frame buffer formats"
https://lore.kernel.org/r/cover.1657294931.git.ge...@linux-m68k.org

Geert Uytterhoeven (3):
  drm/fourcc: Add missing big-endian XRGB1555 and RGB565 formats
  drm/format-helper: Fix endianness in drm_fb_*_to_*() conversion
helpers
  drm/gud: Fix endianness in gud_xrgb_to_color() helper

 drivers/gpu/drm/drm_format_helper.c | 80 +
 drivers/gpu/drm/drm_fourcc.c|  4 ++
 drivers/gpu/drm/gud/gud_pipe.c  | 14 ++---
 3 files changed, 58 insertions(+), 40 deletions(-)

-- 
2.25.1

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds


[PATCH v3 01/10] drm/fourcc: Add drm_format_info_bpp() helper

2022-07-08 Thread Geert Uytterhoeven
Add a helper to retrieve the actual number of bits per pixel for a
plane, taking into account the number of characters and pixels per
block for tiled formats.

Signed-off-by: Geert Uytterhoeven 
Reviewed-by: Javier Martinez Canillas 
---
v3:
  - Add Reviewed-by,

v2:
  - Move up.
---
 drivers/gpu/drm/drm_fourcc.c | 19 +++
 include/drm/drm_fourcc.h |  1 +
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index 07741b678798b0f1..cf48ea0b2cb70ba8 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -370,6 +370,25 @@ unsigned int drm_format_info_block_height(const struct 
drm_format_info *info,
 }
 EXPORT_SYMBOL(drm_format_info_block_height);
 
+/**
+ * drm_format_info_bpp - number of bits per pixel
+ * @info: pixel format info
+ * @plane: plane index
+ *
+ * Returns:
+ * The actual number of bits per pixel, depending on the plane index.
+ */
+unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane)
+{
+   if (!info || plane < 0 || plane >= info->num_planes)
+   return 0;
+
+   return info->char_per_block[plane] * 8 /
+  (drm_format_info_block_width(info, plane) *
+   drm_format_info_block_height(info, plane));
+}
+EXPORT_SYMBOL(drm_format_info_bpp);
+
 /**
  * drm_format_info_min_pitch - computes the minimum required pitch in bytes
  * @info: pixel format info
diff --git a/include/drm/drm_fourcc.h b/include/drm/drm_fourcc.h
index 22aa64d07c7905e2..3800a7ad7f0cda7a 100644
--- a/include/drm/drm_fourcc.h
+++ b/include/drm/drm_fourcc.h
@@ -313,6 +313,7 @@ unsigned int drm_format_info_block_width(const struct 
drm_format_info *info,
 int plane);
 unsigned int drm_format_info_block_height(const struct drm_format_info *info,
  int plane);
+unsigned int drm_format_info_bpp(const struct drm_format_info *info, int 
plane);
 uint64_t drm_format_info_min_pitch(const struct drm_format_info *info,
   int plane, unsigned int buffer_width);
 
-- 
2.25.1



[PATCH v3 03/10] drm/client: Use actual bpp when allocating frame buffers

2022-07-08 Thread Geert Uytterhoeven
When allocating a frame buffer, the number of bits per pixel needed is
derived from the deprecated drm_format_info.cpp[] field.  While this may
work for formats using less than 8 bits per pixel, it does lead to a
large overallocation.

Reduce memory consumption by using the actual number of bits per pixel
instead.

Signed-off-by: Geert Uytterhoeven 
Acked-by: Thomas Zimmermann 
Reviewed-by: Javier Martinez Canillas 
---
v3:
  - Add Reviewed-by,

v2:
  - Add Acked-by.
---
 drivers/gpu/drm/drm_client.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index af3b7395bf6932f7..2b230b4d69423752 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -264,7 +264,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 
width, u32 height, u
 
dumb_args.width = width;
dumb_args.height = height;
-   dumb_args.bpp = info->cpp[0] * 8;
+   dumb_args.bpp = drm_format_info_bpp(info, 0);
ret = drm_mode_create_dumb(dev, _args, client->file);
if (ret)
goto err_delete;
@@ -373,7 +373,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer 
*buffer,
int ret;
 
info = drm_format_info(format);
-   fb_req.bpp = info->cpp[0] * 8;
+   fb_req.bpp = drm_format_info_bpp(info, 0);
fb_req.depth = info->depth;
fb_req.width = width;
fb_req.height = height;
-- 
2.25.1



  1   2   3   >